1package xrpc
2
3import (
4 "net/http"
5 "strconv"
6
7 "tangled.org/core/knotserver/git"
8 "tangled.org/core/types"
9 xrpcerr "tangled.org/core/xrpc/errors"
10)
11
12func (x *Xrpc) RepoLog(w http.ResponseWriter, r *http.Request) {
13 repo := r.URL.Query().Get("repo")
14 repoPath, err := x.parseRepoParam(repo)
15 if err != nil {
16 writeError(w, err.(xrpcerr.XrpcError), http.StatusBadRequest)
17 return
18 }
19
20 ref := r.URL.Query().Get("ref")
21
22 path := r.URL.Query().Get("path")
23 cursor := r.URL.Query().Get("cursor")
24
25 limit := 50 // default
26 if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
27 if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
28 limit = l
29 }
30 }
31
32 gr, err := git.Open(repoPath, ref)
33 if err != nil {
34 writeError(w, xrpcerr.RefNotFoundError, http.StatusNotFound)
35 return
36 }
37
38 offset := 0
39 if cursor != "" {
40 if o, err := strconv.Atoi(cursor); err == nil && o >= 0 {
41 offset = o
42 }
43 }
44
45 commits, err := gr.Commits(offset, limit)
46 if err != nil {
47 x.Logger.Error("fetching commits", "error", err.Error())
48 writeError(w, xrpcerr.NewXrpcError(
49 xrpcerr.WithTag("PathNotFound"),
50 xrpcerr.WithMessage("failed to read commit log"),
51 ), http.StatusNotFound)
52 return
53 }
54
55 total, err := gr.TotalCommits()
56 if err != nil {
57 x.Logger.Error("fetching total commits", "error", err.Error())
58 writeError(w, xrpcerr.NewXrpcError(
59 xrpcerr.WithTag("InternalServerError"),
60 xrpcerr.WithMessage("failed to fetch total commits"),
61 ), http.StatusNotFound)
62 return
63 }
64
65 // Create response using existing types.RepoLogResponse
66 response := types.RepoLogResponse{
67 Commits: commits,
68 Ref: ref,
69 Page: (offset / limit) + 1,
70 PerPage: limit,
71 Total: total,
72 }
73
74 if path != "" {
75 response.Description = path
76 }
77
78 response.Log = true
79
80 writeJson(w, response)
81}