Monorepo for Tangled tangled.org

knotserver: git: track a hidden ref

anirudh.fi 1287e6b7 19ee94f4

verified
Changed files
+67 -1
appview
state
knotserver
+14
appview/state/signer.go
··· 243 243 return s.client.Do(req) 244 244 } 245 245 246 + func (s *SignedClient) NewHiddenRef(ownerDid, targetRepo, forkBranch, remoteBranch string) (*http.Response, error) { 247 + const ( 248 + Method = "POST" 249 + ) 250 + endpoint := fmt.Sprintf("/%s/%s/hidden-ref/%s/%s", ownerDid, targetRepo, forkBranch, remoteBranch) 251 + 252 + req, err := s.newRequest(Method, endpoint, nil) 253 + if err != nil { 254 + return nil, err 255 + } 256 + 257 + return s.client.Do(req) 258 + } 259 + 246 260 type UnsignedClient struct { 247 261 Url *url.URL 248 262 client *http.Client
+28 -1
knotserver/git/fork.go
··· 2 2 3 3 import ( 4 4 "fmt" 5 + "os/exec" 5 6 6 7 "github.com/go-git/go-git/v5" 8 + "github.com/go-git/go-git/v5/config" 7 9 ) 8 10 9 11 func Fork(repoPath, source string) error { 10 12 _, err := git.PlainClone(repoPath, true, &git.CloneOptions{ 11 13 URL: source, 12 - Depth: 1, 13 14 SingleBranch: false, 14 15 }) 15 16 16 17 if err != nil { 17 18 return fmt.Errorf("failed to bare clone repository: %w", err) 19 + } 20 + 21 + err = exec.Command("git", "-C", repoPath, "config", "receive.hideRefs", "refs/hidden").Run() 22 + if err != nil { 23 + return fmt.Errorf("failed to configure hidden refs: %w", err) 24 + } 25 + 26 + return nil 27 + } 28 + 29 + // TrackHiddenRemoteRef tracks a hidden remote in the repository. For example, 30 + // if the feature branch on the fork (forkRef) is feature-1, and the remoteRef, 31 + // i.e. the branch we want to merge into, is main, this will result in a refspec: 32 + // 33 + // +refs/heads/main:refs/hidden/feature-1/main 34 + func (g *GitRepo) TrackHiddenRemoteRef(forkRef, remoteRef string) error { 35 + fetchOpts := &git.FetchOptions{ 36 + RefSpecs: []config.RefSpec{ 37 + config.RefSpec(fmt.Sprintf("+refs/heads/%s:refs/hidden/%s/%s", forkRef, forkRef, remoteRef)), 38 + }, 39 + RemoteName: "origin", 40 + } 41 + 42 + err := g.r.Fetch(fetchOpts) 43 + if err != nil { 44 + return fmt.Errorf("failed to fetch hidden remote: %s: %w", forkRef, err) 18 45 } 19 46 return nil 20 47 }
+2
knotserver/handler.go
··· 85 85 r.Post("/git-upload-pack", h.UploadPack) 86 86 r.Get("/compare/{rev1}/{rev2}", h.Compare) // git diff-tree compare of two objects 87 87 88 + r.With(h.VerifySignature).Post("/hidden-ref/{forkRef}/{remoteRef}", h.NewHiddenRef) 89 + 88 90 r.Route("/merge", func(r chi.Router) { 89 91 r.With(h.VerifySignature) 90 92 r.Post("/", h.Merge)
+23
knotserver/routes.go
··· 786 786 return 787 787 } 788 788 789 + func (h *Handle) NewHiddenRef(w http.ResponseWriter, r *http.Request) { 790 + l := h.l.With("handler", "NewHiddenRef") 791 + 792 + forkRef := chi.URLParam(r, "forkRef") 793 + remoteRef := chi.URLParam(r, "remoteRef") 794 + path, _ := securejoin.SecureJoin(h.c.Repo.ScanPath, didPath(r)) 795 + gr, err := git.PlainOpen(path) 796 + if err != nil { 797 + notFound(w) 798 + return 799 + } 800 + 801 + err = gr.TrackHiddenRemoteRef(forkRef, remoteRef) 802 + if err != nil { 803 + l.Error("error tracking hidden remote ref", "msg", err.Error()) 804 + writeError(w, "error tracking hidden remote ref", http.StatusBadRequest) 805 + return 806 + } 807 + 808 + w.WriteHeader(http.StatusNoContent) 809 + return 810 + } 811 + 789 812 func (h *Handle) AddMember(w http.ResponseWriter, r *http.Request) { 790 813 l := h.l.With("handler", "AddMember") 791 814