+41
knotserver/git/post_receive.go
+41
knotserver/git/post_receive.go
···
1
+
package git
2
+
3
+
import (
4
+
"bufio"
5
+
"io"
6
+
"strings"
7
+
)
8
+
9
+
type PostReceiveLine struct {
10
+
OldSha string // old sha of reference being updated
11
+
NewSha string // new sha of reference being updated
12
+
Ref string // the reference being updated
13
+
}
14
+
15
+
func ParsePostReceive(buf io.Reader) ([]PostReceiveLine, error) {
16
+
scanner := bufio.NewScanner(buf)
17
+
var lines []PostReceiveLine
18
+
for scanner.Scan() {
19
+
line := scanner.Text()
20
+
parts := strings.SplitN(line, " ", 3)
21
+
if len(parts) != 3 {
22
+
continue
23
+
}
24
+
25
+
oldSha := parts[0]
26
+
newSha := parts[1]
27
+
ref := parts[2]
28
+
29
+
lines = append(lines, PostReceiveLine{
30
+
OldSha: oldSha,
31
+
NewSha: newSha,
32
+
Ref: ref,
33
+
})
34
+
}
35
+
36
+
if err := scanner.Err(); err != nil {
37
+
return nil, err
38
+
}
39
+
40
+
return lines, nil
41
+
}
+20
-34
knotserver/internal.go
+20
-34
knotserver/internal.go
···
1
1
package knotserver
2
2
3
3
import (
4
-
"bufio"
5
4
"context"
6
5
"log/slog"
7
6
"net/http"
8
7
"path/filepath"
9
-
"strings"
10
8
11
9
"github.com/go-chi/chi/v5"
12
10
"github.com/go-chi/chi/v5/middleware"
13
11
"tangled.sh/tangled.sh/core/knotserver/config"
14
12
"tangled.sh/tangled.sh/core/knotserver/db"
13
+
"tangled.sh/tangled.sh/core/knotserver/git"
15
14
"tangled.sh/tangled.sh/core/knotserver/notifier"
16
15
"tangled.sh/tangled.sh/core/rbac"
17
16
)
···
70
69
}
71
70
gitUserDid := r.Header.Get("X-Git-User-Did")
72
71
73
-
var ops []db.Op
74
-
scanner := bufio.NewScanner(r.Body)
75
-
for scanner.Scan() {
76
-
line := scanner.Text()
77
-
parts := strings.SplitN(line, " ", 3)
78
-
if len(parts) != 3 {
79
-
l.Error("invalid payload", "parts", parts)
80
-
continue
81
-
}
82
-
83
-
tid := TID()
84
-
oldSha := parts[0]
85
-
newSha := parts[1]
86
-
ref := parts[2]
87
-
op := db.Op{
88
-
Tid: tid,
89
-
Did: gitUserDid,
90
-
Repo: gitRelativeDir,
91
-
OldSha: oldSha,
92
-
NewSha: newSha,
93
-
Ref: ref,
94
-
}
95
-
ops = append(ops, op)
72
+
lines, err := git.ParsePostReceive(r.Body)
73
+
if err != nil {
74
+
l.Error("failed to parse post-receive payload", "err", err)
75
+
// non-fatal
96
76
}
97
77
98
-
if err := scanner.Err(); err != nil {
99
-
l.Error("failed to read payload", "err", err)
100
-
return
101
-
}
102
-
103
-
for _, op := range ops {
104
-
err := h.db.InsertOp(op, h.n)
78
+
for _, line := range lines {
79
+
err := h.updateOpLog(line, gitUserDid, gitRelativeDir)
105
80
if err != nil {
106
-
l.Error("failed to insert op", "err", err, "op", op)
107
-
continue
81
+
l.Error("failed to insert op", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir)
108
82
}
109
83
}
110
84
111
85
return
86
+
}
87
+
88
+
func (h *InternalHandle) updateOpLog(line git.PostReceiveLine, did, repo string) error {
89
+
op := db.Op{
90
+
Tid: TID(),
91
+
Did: did,
92
+
Repo: repo,
93
+
OldSha: line.OldSha,
94
+
NewSha: line.NewSha,
95
+
Ref: line.Ref,
96
+
}
97
+
return h.db.InsertOp(op, h.n)
112
98
}
113
99
114
100
func Internal(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer, l *slog.Logger, n *notifier.Notifier) http.Handler {