A vibe coded tangled fork which supports pijul.
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}