forked from tangled.org/core
this repo has no description
1package handler 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "os/exec" 8 "path" 9 10 "github.com/bluesky-social/indigo/atproto/syntax" 11 "github.com/go-git/go-git/v5" 12 "github.com/go-git/go-git/v5/plumbing" 13 "tangled.org/core/api/tangled" 14 "tangled.org/core/knot2/config" 15 "tangled.org/core/log" 16 xrpcerr "tangled.org/core/xrpc/errors" 17) 18 19func XrpcGitKeepCommit(cfg *config.Config) http.HandlerFunc { 20 return func(w http.ResponseWriter, r *http.Request) { 21 ctx := r.Context() 22 l := log.FromContext(ctx).With("handler", "XrpcGitKeepCommit") 23 24 // TODO: get session did 25 actorDid := syntax.DID("") 26 27 var input tangled.GitKeepCommit_Input 28 if err := json.NewDecoder(r.Body).Decode(&input); err != nil { 29 l.Error("failed to decode body", "err", err) 30 panic("unimplemented") 31 } 32 33 repoAt, err := syntax.ParseATURI(input.Repo) 34 if err != nil { 35 l.Error("failed to decode body", "err", err) 36 panic("unimplemented") 37 } 38 repoPath := repoPathFromAtUri(cfg, repoAt) 39 40 // ensure repo exist (if not, clone it) 41 repo, err := git.PlainOpen(repoPath) 42 if err != nil { 43 // TODO: clone the ref from source repo if repo doesn't exist in this knot yet 44 l.Info("repo missing in knot", "err", err) 45 panic("unimplemented") 46 } 47 48 commitId, err := repo.ResolveRevision(plumbing.Revision(input.Ref)) 49 if err != nil { 50 l.Error("failed to resolve revision", "ref", input.Ref, "err", err) 51 panic("unimplemented") 52 } 53 54 // set keep-ref for given commit 55 refspec := fmt.Sprintf("refs/knot/%s/keep/%s", actorDid, commitId) 56 updateRefCmd := exec.Command("git", "-C", repoPath, "update-ref", refspec, commitId.String()) 57 if err := updateRefCmd.Run(); err != nil { 58 writeError(w, xrpcerr.GenericError(err), http.StatusBadRequest) 59 return 60 } 61 62 output := tangled.GitKeepCommit_Output{ 63 CommitId: commitId.String(), 64 } 65 66 w.WriteHeader(http.StatusOK) 67 writeJson(w, output) 68 } 69} 70 71func repoPathFromAtUri(cfg *config.Config, repoAt syntax.ATURI) string { 72 return path.Join(cfg.RepoDir, repoAt.Authority().String(), repoAt.RecordKey().String()) 73} 74 75func writeError(w http.ResponseWriter, e xrpcerr.XrpcError, status int) { 76 w.Header().Set("Content-Type", "application/json") 77 w.WriteHeader(status) 78 json.NewEncoder(w).Encode(e) 79} 80 81func writeJson(w http.ResponseWriter, response any) { 82 w.Header().Set("Content-Type", "application/json") 83 if err := json.NewEncoder(w).Encode(response); err != nil { 84 writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError) 85 return 86 } 87}