forked from tangled.org/core
this repo has no description
at master 2.9 kB view raw
1package xrpc 2 3import ( 4 "encoding/json" 5 "net/http" 6 "net/url" 7 "path/filepath" 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 refParam := r.URL.Query().Get("ref") 25 if refParam == "" { 26 writeError(w, xrpcerr.NewXrpcError( 27 xrpcerr.WithTag("InvalidRequest"), 28 xrpcerr.WithMessage("missing ref parameter"), 29 ), http.StatusBadRequest) 30 return 31 } 32 33 path := r.URL.Query().Get("path") 34 // path can be empty (defaults to root) 35 36 ref, err := url.QueryUnescape(refParam) 37 if err != nil { 38 writeError(w, xrpcerr.NewXrpcError( 39 xrpcerr.WithTag("InvalidRequest"), 40 xrpcerr.WithMessage("invalid ref parameter"), 41 ), http.StatusBadRequest) 42 return 43 } 44 45 gr, err := git.Open(repoPath, ref) 46 if err != nil { 47 x.Logger.Error("failed to open git repository", "error", err, "path", repoPath, "ref", ref) 48 writeError(w, xrpcerr.NewXrpcError( 49 xrpcerr.WithTag("RefNotFound"), 50 xrpcerr.WithMessage("repository or ref not found"), 51 ), http.StatusNotFound) 52 return 53 } 54 55 files, err := gr.FileTree(ctx, path) 56 if err != nil { 57 x.Logger.Error("failed to get file tree", "error", err, "path", path) 58 writeError(w, xrpcerr.NewXrpcError( 59 xrpcerr.WithTag("PathNotFound"), 60 xrpcerr.WithMessage("failed to read repository tree"), 61 ), http.StatusNotFound) 62 return 63 } 64 65 // convert NiceTree -> tangled.RepoTree_TreeEntry 66 treeEntries := make([]*tangled.RepoTree_TreeEntry, len(files)) 67 for i, file := range files { 68 entry := &tangled.RepoTree_TreeEntry{ 69 Name: file.Name, 70 Mode: file.Mode, 71 Size: file.Size, 72 Is_file: file.IsFile, 73 Is_subtree: file.IsSubtree, 74 } 75 76 if file.LastCommit != nil { 77 entry.Last_commit = &tangled.RepoTree_LastCommit{ 78 Hash: file.LastCommit.Hash.String(), 79 Message: file.LastCommit.Message, 80 When: file.LastCommit.When.Format("2006-01-02T15:04:05.000Z"), 81 } 82 } 83 84 treeEntries[i] = entry 85 } 86 87 var parentPtr *string 88 if path != "" { 89 parentPtr = &path 90 } 91 92 var dotdotPtr *string 93 if path != "" { 94 dotdot := filepath.Dir(path) 95 if dotdot != "." { 96 dotdotPtr = &dotdot 97 } 98 } 99 100 response := tangled.RepoTree_Output{ 101 Ref: ref, 102 Parent: parentPtr, 103 Dotdot: dotdotPtr, 104 Files: treeEntries, 105 } 106 107 w.Header().Set("Content-Type", "application/json") 108 if err := json.NewEncoder(w).Encode(response); err != nil { 109 x.Logger.Error("failed to encode response", "error", err) 110 writeError(w, xrpcerr.NewXrpcError( 111 xrpcerr.WithTag("InternalServerError"), 112 xrpcerr.WithMessage("failed to encode response"), 113 ), http.StatusInternalServerError) 114 return 115 } 116}