A vibe coded tangled fork which supports pijul.
at master 112 lines 2.6 kB view raw
1package xrpc 2 3import ( 4 "net/http" 5 "strconv" 6 7 "github.com/go-git/go-git/v5/plumbing" 8 "github.com/go-git/go-git/v5/plumbing/object" 9 "tangled.org/core/knotserver/vcs" 10 "tangled.org/core/types" 11 xrpcerr "tangled.org/core/xrpc/errors" 12) 13 14func (x *Xrpc) RepoLog(w http.ResponseWriter, r *http.Request) { 15 repo := r.URL.Query().Get("repo") 16 repoPath, err := x.parseRepoParam(repo) 17 if err != nil { 18 writeError(w, err.(xrpcerr.XrpcError), http.StatusBadRequest) 19 return 20 } 21 22 ref := r.URL.Query().Get("ref") 23 24 path := r.URL.Query().Get("path") 25 cursor := r.URL.Query().Get("cursor") 26 27 limit := 50 // default 28 if limitStr := r.URL.Query().Get("limit"); limitStr != "" { 29 if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 { 30 limit = l 31 } 32 } 33 34 rv, err := vcs.Open(repoPath, ref) 35 if err != nil { 36 writeError(w, xrpcerr.RefNotFoundError, http.StatusNotFound) 37 return 38 } 39 40 // If ref was empty, resolve the actual default branch name 41 if ref == "" { 42 if defaultBranch, err := rv.DefaultBranch(); err == nil { 43 ref = defaultBranch 44 } 45 } 46 47 offset := 0 48 if cursor != "" { 49 if o, err := strconv.Atoi(cursor); err == nil && o >= 0 { 50 offset = o 51 } 52 } 53 54 entries, err := rv.History(offset, limit) 55 if err != nil { 56 x.Logger.Error("fetching history", "error", err.Error()) 57 writeError(w, xrpcerr.NewXrpcError( 58 xrpcerr.WithTag("PathNotFound"), 59 xrpcerr.WithMessage("failed to read commit log"), 60 ), http.StatusNotFound) 61 return 62 } 63 64 total, err := rv.TotalHistoryEntries() 65 if err != nil { 66 x.Logger.Error("fetching total history entries", "error", err.Error()) 67 writeError(w, xrpcerr.NewXrpcError( 68 xrpcerr.WithTag("InternalServerError"), 69 xrpcerr.WithMessage("failed to fetch total commits"), 70 ), http.StatusInternalServerError) 71 return 72 } 73 74 tcommits := make([]types.Commit, len(entries)) 75 for i, e := range entries { 76 parents := make([]plumbing.Hash, 0, len(e.Parents)) 77 for _, p := range e.Parents { 78 parents = append(parents, plumbing.NewHash(p)) 79 } 80 tcommits[i] = types.Commit{ 81 Hash: plumbing.NewHash(e.Hash), 82 Author: object.Signature{ 83 Name: e.Author.Name, 84 Email: e.Author.Email, 85 When: e.Author.When, 86 }, 87 Committer: object.Signature{ 88 Name: e.Committer.Name, 89 Email: e.Committer.Email, 90 When: e.Committer.When, 91 }, 92 Message: e.Message, 93 ParentHashes: parents, 94 } 95 } 96 97 response := types.RepoLogResponse{ 98 Commits: tcommits, 99 Ref: ref, 100 Page: (offset / limit) + 1, 101 PerPage: limit, 102 Total: total, 103 } 104 105 if path != "" { 106 response.Description = path 107 } 108 109 response.Log = true 110 111 writeJson(w, response) 112}