routes/git.go (view raw)
1package routes
2
3import (
4 "errors"
5 "log"
6 "net/http"
7 "path/filepath"
8
9 "github.com/alexedwards/flow"
10 "github.com/go-git/go-billy/v5/osfs"
11 "github.com/go-git/go-git/v5/plumbing/format/pktline"
12 "github.com/go-git/go-git/v5/plumbing/protocol/packp"
13 "github.com/go-git/go-git/v5/plumbing/transport"
14 "github.com/go-git/go-git/v5/plumbing/transport/server"
15)
16
17func (d *deps) InfoRefs(w http.ResponseWriter, r *http.Request) {
18 name := flow.Param(r.Context(), "name")
19 name = filepath.Clean(name)
20
21 repo := filepath.Join(d.c.Repo.ScanPath, name)
22
23 w.Header().Set("content-type", "application/x-git-upload-pack-advertisement")
24
25 ep, err := transport.NewEndpoint("/")
26 if err != nil {
27 http.Error(w, err.Error(), 500)
28 log.Printf("git: %s", err)
29 return
30 }
31
32 billyfs := osfs.New(repo)
33 loader := server.NewFilesystemLoader(billyfs)
34 srv := server.NewServer(loader)
35 session, err := srv.NewUploadPackSession(ep, nil)
36 if err != nil {
37 http.Error(w, err.Error(), 500)
38 log.Printf("git: %s", err)
39 return
40 }
41
42 ar, err := session.AdvertisedReferencesContext(r.Context())
43 if errors.Is(err, transport.ErrRepositoryNotFound) {
44 http.Error(w, err.Error(), 404)
45 return
46 } else if err != nil {
47 http.Error(w, err.Error(), 500)
48 return
49 }
50
51 ar.Prefix = [][]byte{
52 []byte("# service=git-upload-pack"),
53 pktline.Flush,
54 }
55
56 if err = ar.Encode(w); err != nil {
57 http.Error(w, err.Error(), 500)
58 log.Printf("git: %s", err)
59 return
60 }
61}
62
63func (d *deps) UploadPack(w http.ResponseWriter, r *http.Request) {
64 name := flow.Param(r.Context(), "name")
65 name = filepath.Clean(name)
66
67 repo := filepath.Join(d.c.Repo.ScanPath, name)
68
69 w.Header().Set("content-type", "application/x-git-upload-pack-result")
70
71 upr := packp.NewUploadPackRequest()
72 err := upr.Decode(r.Body)
73 if err != nil {
74 http.Error(w, err.Error(), 400)
75 log.Printf("git: %s", err)
76 return
77 }
78
79 ep, err := transport.NewEndpoint("/")
80 if err != nil {
81 http.Error(w, err.Error(), 500)
82 log.Printf("git: %s", err)
83 return
84 }
85
86 billyfs := osfs.New(repo)
87 loader := server.NewFilesystemLoader(billyfs)
88 svr := server.NewServer(loader)
89 session, err := svr.NewUploadPackSession(ep, nil)
90 if err != nil {
91 http.Error(w, err.Error(), 500)
92 log.Printf("git: %s", err)
93 return
94 }
95
96 res, err := session.UploadPack(r.Context(), upr)
97 if err != nil {
98 http.Error(w, err.Error(), 500)
99 log.Printf("git: %s", err)
100 return
101 }
102
103 if err = res.Encode(w); err != nil {
104 http.Error(w, err.Error(), 500)
105 log.Printf("git: %s", err)
106 return
107 }
108}