diff options
author | Anirudh Oppiliappan <x@icyphox.sh> | 2022-12-24 14:57:44 +0530 |
---|---|---|
committer | Anirudh Oppiliappan <x@icyphox.sh> | 2022-12-24 14:57:44 +0530 |
commit | fa66c4faa8e54a81e5c84fec1b73da374f7e0909 (patch) | |
tree | d02e9c7e15d96b60e4e7c5de9d804174868889e4 /routes | |
parent | 983dabb33c2dddcdba65b8ab9d0922bd338628aa (diff) | |
download | legit-fa66c4faa8e54a81e5c84fec1b73da374f7e0909.tar.gz legit-fa66c4faa8e54a81e5c84fec1b73da374f7e0909.tar.bz2 legit-fa66c4faa8e54a81e5c84fec1b73da374f7e0909.zip |
git: pure go git clone
Diffstat (limited to 'routes')
-rw-r--r-- | routes/git.go | 108 | ||||
-rw-r--r-- | routes/handler.go | 36 |
2 files changed, 117 insertions, 27 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 + } +} diff --git a/routes/handler.go b/routes/handler.go index c0b146c..a0e7832 100644 --- a/routes/handler.go +++ b/routes/handler.go @@ -1,26 +1,16 @@ package routes import ( - "log" "net/http" - "path/filepath" "git.icyphox.sh/legit/config" "github.com/alexedwards/flow" - "github.com/sosedoff/gitkit" ) -type depsWrapper struct { - actualDeps deps - gitsvc *gitkit.Server -} - // Checks for gitprotocol-http(5) specific smells; if found, passes // the request on to the git http service, else render the web frontend. -func (dw *depsWrapper) Multiplex(w http.ResponseWriter, r *http.Request) { +func (d *deps) Multiplex(w http.ResponseWriter, r *http.Request) { path := flow.Param(r.Context(), "...") - name := flow.Param(r.Context(), "name") - name = filepath.Clean(name) if r.URL.RawQuery == "service=git-receive-pack" { w.WriteHeader(http.StatusBadRequest) @@ -28,12 +18,14 @@ func (dw *depsWrapper) Multiplex(w http.ResponseWriter, r *http.Request) { return } - if path == "info/refs" && r.URL.RawQuery == "service=git-upload-pack" && r.Method == "GET" { - dw.gitsvc.ServeHTTP(w, r) + if path == "info/refs" && + r.URL.RawQuery == "service=git-upload-pack" && + r.Method == "GET" { + d.InfoRefs(w, r) } else if path == "git-upload-pack" && r.Method == "POST" { - dw.gitsvc.ServeHTTP(w, r) + d.UploadPack(w, r) } else if r.Method == "GET" { - dw.actualDeps.RepoIndex(w, r) + d.RepoIndex(w, r) } } @@ -41,29 +33,19 @@ func Handlers(c *config.Config) *flow.Mux { mux := flow.New() d := deps{c} - gitsvc := gitkit.New(gitkit.Config{ - Dir: c.Repo.ScanPath, - AutoCreate: false, - }) - if err := gitsvc.Setup(); err != nil { - log.Fatalf("git server: %s", err) - } - - dw := depsWrapper{actualDeps: d, gitsvc: gitsvc} - mux.NotFound = http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { d.Write404(w) }) mux.HandleFunc("/", d.Index, "GET") mux.HandleFunc("/static/:file", d.ServeStatic, "GET") - mux.HandleFunc("/:name", dw.Multiplex, "GET", "POST") + mux.HandleFunc("/:name", d.Multiplex, "GET", "POST") mux.HandleFunc("/:name/tree/:ref/...", d.RepoTree, "GET") mux.HandleFunc("/:name/blob/:ref/...", d.FileContent, "GET") mux.HandleFunc("/:name/log/:ref", d.Log, "GET") mux.HandleFunc("/:name/commit/:ref", d.Diff, "GET") mux.HandleFunc("/:name/refs", d.Refs, "GET") - mux.HandleFunc("/:name/...", dw.Multiplex, "GET", "POST") + mux.HandleFunc("/:name/...", d.Multiplex, "GET", "POST") return mux } |