1package web
2
3import (
4 "net/http"
5
6 "github.com/charmbracelet/log/v2"
7 "github.com/charmbracelet/soft-serve/git"
8 "github.com/charmbracelet/soft-serve/pkg/config"
9 "github.com/charmbracelet/soft-serve/pkg/proto"
10 "github.com/gorilla/mux"
11)
12
13// TreeData contains data for rendering directory tree view.
14type TreeData struct {
15 Repo proto.Repository
16 DefaultBranch string
17 Ref string
18 Path string
19 Entries git.Entries
20 ActiveTab string
21 ServerName string
22}
23
24func repoTree(w http.ResponseWriter, r *http.Request) {
25 ctx := r.Context()
26 logger := log.FromContext(ctx)
27 cfg := config.FromContext(ctx)
28 repo := proto.RepositoryFromContext(ctx)
29 if repo == nil {
30 renderNotFound(w, r)
31 return
32 }
33
34 gr, err := openRepository(repo)
35 if err != nil {
36 logger.Debug("failed to open repository", "repo", repo.Name(), "err", err)
37 renderInternalServerError(w, r)
38 return
39 }
40
41 vars := mux.Vars(r)
42 refAndPath := vars["refAndPath"]
43 ref, path := parseRefAndPath(gr, refAndPath)
44
45 if ref == "" {
46 head, err := gr.HEAD()
47 if err == nil && head != nil {
48 ref = head.Name().Short()
49 }
50 }
51
52 refObj, err := resolveAndBuildRef(gr, ref)
53 if err != nil {
54 logger.Debug("failed to resolve ref or commit", "repo", repo.Name(), "ref", ref, "err", err)
55 renderNotFound(w, r)
56 return
57 }
58
59 tree, err := gr.TreePath(refObj, path)
60 if err != nil {
61 logger.Debug("failed to get tree path", "repo", repo.Name(), "ref", ref, "path", path, "err", err)
62 renderNotFound(w, r)
63 return
64 }
65
66 entries, err := tree.Entries()
67 if err != nil {
68 logger.Debug("failed to get tree entries", "err", err)
69 renderInternalServerError(w, r)
70 return
71 }
72
73 entries.Sort()
74
75 defaultBranch := getDefaultBranch(gr)
76
77 data := TreeData{
78 Repo: repo,
79 DefaultBranch: defaultBranch,
80 Ref: ref,
81 Path: path,
82 Entries: entries,
83 ActiveTab: "tree",
84 ServerName: cfg.Name,
85 }
86
87 renderHTML(w, "tree.html", data)
88}