From d67e7d071d332d746382dfa602ea474b0ca2e865 Mon Sep 17 00:00:00 2001 From: tjh Date: Wed, 21 May 2025 23:45:37 +0100 Subject: [PATCH] knotserver: git: add support for git protocol v2 v1-style requests are unaffected and v0 (dumb-protocol) requests remain unsupported. --- knotserver/git.go | 12 +++++----- knotserver/git/service/service.go | 37 +++++++++++++++++++------------ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/knotserver/git.go b/knotserver/git.go index 1a5d430d..82c1c522 100644 --- a/knotserver/git.go +++ b/knotserver/git.go @@ -31,8 +31,9 @@ func (d *Handle) InfoRefs(w http.ResponseWriter, r *http.Request) { } cmd := service.ServiceCommand{ - Dir: repoPath, - Stdout: w, + GitProtocol: r.Header.Get("Git-Protocol"), + Dir: repoPath, + Stdout: w, } serviceName := r.URL.Query().Get("service") @@ -81,9 +82,10 @@ func (d *Handle) UploadPack(w http.ResponseWriter, r *http.Request) { d.l.Info("git: executing git-upload-pack", "handler", "UploadPack", "repo", repo) cmd := service.ServiceCommand{ - Dir: repo, - Stdout: w, - Stdin: bodyReader, + GitProtocol: r.Header.Get("Git-Protocol"), + Dir: repo, + Stdout: w, + Stdin: bodyReader, } w.WriteHeader(http.StatusOK) diff --git a/knotserver/git/service/service.go b/knotserver/git/service/service.go index 04051c8b..e6fadda1 100644 --- a/knotserver/git/service/service.go +++ b/knotserver/git/service/service.go @@ -15,19 +15,20 @@ import ( // Mostly from charmbracelet/soft-serve and sosedoff/gitkit. type ServiceCommand struct { - Dir string - Stdin io.Reader - Stdout http.ResponseWriter + GitProtocol string + Dir string + Stdin io.Reader + Stdout http.ResponseWriter } func (c *ServiceCommand) InfoRefs() error { cmd := exec.Command("git", []string{ "upload-pack", "--stateless-rpc", - "--advertise-refs", + "--http-backend-info-refs", ".", }...) - + cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_PROTOCOL=%s", c.GitProtocol)) cmd.Dir = c.Dir cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} stdoutPipe, _ := cmd.StdoutPipe() @@ -38,14 +39,16 @@ func (c *ServiceCommand) InfoRefs() error { return err } - if err := packLine(c.Stdout, "# service=git-upload-pack\n"); err != nil { - log.Printf("git: failed to write pack line: %s", err) - return err - } + if !strings.Contains(c.GitProtocol, "version=2") { + if err := packLine(c.Stdout, "# service=git-upload-pack\n"); err != nil { + log.Printf("git: failed to write pack line: %s", err) + return err + } - if err := packFlush(c.Stdout); err != nil { - log.Printf("git: failed to flush pack: %s", err) - return err + if err := packFlush(c.Stdout); err != nil { + log.Printf("git: failed to flush pack: %s", err) + return err + } } buf := bytes.Buffer{} @@ -71,10 +74,16 @@ func (c *ServiceCommand) InfoRefs() error { func (c *ServiceCommand) UploadPack() error { var stderr bytes.Buffer - cmd := exec.Command("git", "-c", "uploadpack.allowFilter=true", - "upload-pack", "--stateless-rpc", ".") + cmd := exec.Command("git", []string{ + "-c", "uploadpack.allowFilter=true", + "upload-pack", + "--stateless-rpc", + ".", + }...) + cmd.Dir = c.Dir cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_PROTOCOL=%s", c.GitProtocol)) stdoutPipe, err := cmd.StdoutPipe() if err != nil { -- 2.51.2