diff --git a/knotserver/git/post_receive.go b/knotserver/git/post_receive.go new file mode 100644 index 0000000..525afb0 --- /dev/null +++ b/knotserver/git/post_receive.go @@ -0,0 +1,41 @@ +package git + +import ( + "bufio" + "io" + "strings" +) + +type PostReceiveLine struct { + OldSha string // old sha of reference being updated + NewSha string // new sha of reference being updated + Ref string // the reference being updated +} + +func ParsePostReceive(buf io.Reader) ([]PostReceiveLine, error) { + scanner := bufio.NewScanner(buf) + var lines []PostReceiveLine + for scanner.Scan() { + line := scanner.Text() + parts := strings.SplitN(line, " ", 3) + if len(parts) != 3 { + continue + } + + oldSha := parts[0] + newSha := parts[1] + ref := parts[2] + + lines = append(lines, PostReceiveLine{ + OldSha: oldSha, + NewSha: newSha, + Ref: ref, + }) + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return lines, nil +} diff --git a/knotserver/internal.go b/knotserver/internal.go index bccffed..610fb8a 100644 --- a/knotserver/internal.go +++ b/knotserver/internal.go @@ -1,17 +1,16 @@ package knotserver import ( - "bufio" "context" "log/slog" "net/http" "path/filepath" - "strings" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "tangled.sh/tangled.sh/core/knotserver/config" "tangled.sh/tangled.sh/core/knotserver/db" + "tangled.sh/tangled.sh/core/knotserver/git" "tangled.sh/tangled.sh/core/knotserver/notifier" "tangled.sh/tangled.sh/core/rbac" ) @@ -70,47 +69,34 @@ func (h *InternalHandle) PostReceiveHook(w http.ResponseWriter, r *http.Request) } gitUserDid := r.Header.Get("X-Git-User-Did") - var ops []db.Op - scanner := bufio.NewScanner(r.Body) - for scanner.Scan() { - line := scanner.Text() - parts := strings.SplitN(line, " ", 3) - if len(parts) != 3 { - l.Error("invalid payload", "parts", parts) - continue - } - - tid := TID() - oldSha := parts[0] - newSha := parts[1] - ref := parts[2] - op := db.Op{ - Tid: tid, - Did: gitUserDid, - Repo: gitRelativeDir, - OldSha: oldSha, - NewSha: newSha, - Ref: ref, - } - ops = append(ops, op) - } - - if err := scanner.Err(); err != nil { - l.Error("failed to read payload", "err", err) - return + lines, err := git.ParsePostReceive(r.Body) + if err != nil { + l.Error("failed to parse post-receive payload", "err", err) + // non-fatal } - for _, op := range ops { - err := h.db.InsertOp(op, h.n) + for _, line := range lines { + err := h.updateOpLog(line, gitUserDid, gitRelativeDir) if err != nil { - l.Error("failed to insert op", "err", err, "op", op) - continue + l.Error("failed to insert op", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) } } return } +func (h *InternalHandle) updateOpLog(line git.PostReceiveLine, did, repo string) error { + op := db.Op{ + Tid: TID(), + Did: did, + Repo: repo, + OldSha: line.OldSha, + NewSha: line.NewSha, + Ref: line.Ref, + } + return h.db.InsertOp(op, h.n) +} + func Internal(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer, l *slog.Logger, n *notifier.Notifier) http.Handler { r := chi.NewRouter()