diff options
Diffstat (limited to 'routes/git.go')
-rw-r--r-- | routes/git.go | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/routes/git.go b/routes/git.go new file mode 100644 index 0000000..1a5e035 --- /dev/null +++ b/routes/git.go @@ -0,0 +1,108 @@ +package routes + +import ( + "errors" + "log" + "net/http" + "path/filepath" + + "github.com/alexedwards/flow" + "github.com/go-git/go-billy/v5/osfs" + "github.com/go-git/go-git/v5/plumbing/format/pktline" + "github.com/go-git/go-git/v5/plumbing/protocol/packp" + "github.com/go-git/go-git/v5/plumbing/transport" + "github.com/go-git/go-git/v5/plumbing/transport/server" +) + +func (d *deps) InfoRefs(w http.ResponseWriter, r *http.Request) { + name := flow.Param(r.Context(), "name") + name = filepath.Clean(name) + + repo := filepath.Join(d.c.Repo.ScanPath, name) + + w.Header().Set("content-type", "application/x-git-upload-pack-advertisement") + + ep, err := transport.NewEndpoint("/") + if err != nil { + http.Error(w, err.Error(), 500) + log.Printf("git: %s", err) + return + } + + billyfs := osfs.New(repo) + loader := server.NewFilesystemLoader(billyfs) + srv := server.NewServer(loader) + session, err := srv.NewUploadPackSession(ep, nil) + if err != nil { + http.Error(w, err.Error(), 500) + log.Printf("git: %s", err) + return + } + + ar, err := session.AdvertisedReferencesContext(r.Context()) + if errors.Is(err, transport.ErrRepositoryNotFound) { + http.Error(w, err.Error(), 404) + return + } else if err != nil { + http.Error(w, err.Error(), 500) + return + } + + ar.Prefix = [][]byte{ + []byte("# service=git-upload-pack"), + pktline.Flush, + } + + if err = ar.Encode(w); err != nil { + http.Error(w, err.Error(), 500) + log.Printf("git: %s", err) + return + } +} + +func (d *deps) UploadPack(w http.ResponseWriter, r *http.Request) { + name := flow.Param(r.Context(), "name") + name = filepath.Clean(name) + + repo := filepath.Join(d.c.Repo.ScanPath, name) + + w.Header().Set("content-type", "application/x-git-upload-pack-result") + + upr := packp.NewUploadPackRequest() + err := upr.Decode(r.Body) + if err != nil { + http.Error(w, err.Error(), 400) + log.Printf("git: %s", err) + return + } + + ep, err := transport.NewEndpoint("/") + if err != nil { + http.Error(w, err.Error(), 500) + log.Printf("git: %s", err) + return + } + + billyfs := osfs.New(repo) + loader := server.NewFilesystemLoader(billyfs) + svr := server.NewServer(loader) + session, err := svr.NewUploadPackSession(ep, nil) + if err != nil { + http.Error(w, err.Error(), 500) + log.Printf("git: %s", err) + return + } + + res, err := session.UploadPack(r.Context(), upr) + if err != nil { + http.Error(w, err.Error(), 500) + log.Printf("git: %s", err) + return + } + + if err = res.Encode(w); err != nil { + http.Error(w, err.Error(), 500) + log.Printf("git: %s", err) + return + } +} |