this repo has no description
1package xrpc
2
3import (
4 "encoding/json"
5 "net/http"
6 "path/filepath"
7 "time"
8
9 "tangled.sh/tangled.sh/core/api/tangled"
10 "tangled.sh/tangled.sh/core/knotserver/git"
11 xrpcerr "tangled.sh/tangled.sh/core/xrpc/errors"
12)
13
14func (x *Xrpc) RepoTree(w http.ResponseWriter, r *http.Request) {
15 ctx := r.Context()
16
17 repo := r.URL.Query().Get("repo")
18 repoPath, err := x.parseRepoParam(repo)
19 if err != nil {
20 writeError(w, err.(xrpcerr.XrpcError), http.StatusBadRequest)
21 return
22 }
23
24 ref := r.URL.Query().Get("ref")
25 // ref can be empty (git.Open handles this)
26
27 path := r.URL.Query().Get("path")
28 // path can be empty (defaults to root)
29
30 gr, err := git.Open(repoPath, ref)
31 if err != nil {
32 x.Logger.Error("failed to open git repository", "error", err, "path", repoPath, "ref", ref)
33 writeError(w, xrpcerr.NewXrpcError(
34 xrpcerr.WithTag("RefNotFound"),
35 xrpcerr.WithMessage("repository or ref not found"),
36 ), http.StatusNotFound)
37 return
38 }
39
40 files, err := gr.FileTree(ctx, path)
41 if err != nil {
42 x.Logger.Error("failed to get file tree", "error", err, "path", path)
43 writeError(w, xrpcerr.NewXrpcError(
44 xrpcerr.WithTag("PathNotFound"),
45 xrpcerr.WithMessage("failed to read repository tree"),
46 ), http.StatusNotFound)
47 return
48 }
49
50 // convert NiceTree -> tangled.RepoTree_TreeEntry
51 treeEntries := make([]*tangled.RepoTree_TreeEntry, len(files))
52 for i, file := range files {
53 entry := &tangled.RepoTree_TreeEntry{
54 Name: file.Name,
55 Mode: file.Mode,
56 Size: file.Size,
57 Is_file: file.IsFile,
58 Is_subtree: file.IsSubtree,
59 }
60
61 if file.LastCommit != nil {
62 entry.Last_commit = &tangled.RepoTree_LastCommit{
63 Hash: file.LastCommit.Hash.String(),
64 Message: file.LastCommit.Message,
65 When: file.LastCommit.When.Format(time.RFC3339),
66 }
67 }
68
69 treeEntries[i] = entry
70 }
71
72 var parentPtr *string
73 if path != "" {
74 parentPtr = &path
75 }
76
77 var dotdotPtr *string
78 if path != "" {
79 dotdot := filepath.Dir(path)
80 if dotdot != "." {
81 dotdotPtr = &dotdot
82 }
83 }
84
85 response := tangled.RepoTree_Output{
86 Ref: ref,
87 Parent: parentPtr,
88 Dotdot: dotdotPtr,
89 Files: treeEntries,
90 }
91
92 w.Header().Set("Content-Type", "application/json")
93 if err := json.NewEncoder(w).Encode(response); err != nil {
94 x.Logger.Error("failed to encode response", "error", err)
95 writeError(w, xrpcerr.NewXrpcError(
96 xrpcerr.WithTag("InternalServerError"),
97 xrpcerr.WithMessage("failed to encode response"),
98 ), http.StatusInternalServerError)
99 return
100 }
101}