webui_tree.go

  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	RepoBaseData
 16	Ref          string
 17	Path         string
 18	Entries      git.Entries
 19	IsCommitHash bool
 20}
 21
 22func repoTree(w http.ResponseWriter, r *http.Request) {
 23	ctx := r.Context()
 24	logger := log.FromContext(ctx)
 25	cfg := config.FromContext(ctx)
 26	repo := proto.RepositoryFromContext(ctx)
 27	if repo == nil {
 28		renderNotFound(w, r)
 29		return
 30	}
 31
 32	gr, err := openRepository(repo)
 33	if err != nil {
 34		logger.Debug("failed to open repository", "repo", repo.Name(), "err", err)
 35		renderInternalServerError(w, r)
 36		return
 37	}
 38
 39	vars := mux.Vars(r)
 40	refAndPath := vars["refAndPath"]
 41	ref, path := parseRefAndPath(gr, refAndPath)
 42
 43	if ref == "" {
 44		head, err := gr.HEAD()
 45		if err == nil && head != nil {
 46			ref = head.Name().Short()
 47		}
 48	}
 49
 50	refObj, isCommitHash, err := resolveAndBuildRef(gr, ref)
 51	if err != nil {
 52		logger.Debug("failed to resolve ref or commit", "repo", repo.Name(), "ref", ref, "err", err)
 53		renderNotFound(w, r)
 54		return
 55	}
 56
 57	tree, err := gr.TreePath(refObj, path)
 58	if err != nil {
 59		logger.Debug("failed to get tree path", "repo", repo.Name(), "ref", ref, "path", path, "err", err)
 60		renderNotFound(w, r)
 61		return
 62	}
 63
 64	entries, err := tree.Entries()
 65	if err != nil {
 66		logger.Debug("failed to get tree entries", "err", err)
 67		renderInternalServerError(w, r)
 68		return
 69	}
 70
 71	entries.Sort()
 72
 73	defaultBranch := getDefaultBranch(gr)
 74
 75	repoDisplayName := repo.ProjectName()
 76	if repoDisplayName == "" {
 77		repoDisplayName = repo.Name()
 78	}
 79
 80	title := repo.Name()
 81	if path != "." {
 82		title += "/" + path
 83	}
 84	title += " at "
 85	if isCommitHash && len(ref) > 7 {
 86		title += ref[:7]
 87	} else {
 88		title += ref
 89	}
 90	title += " | " + repoDisplayName
 91
 92	// Build fallback description matching title information
 93	descFallback := "Browse "
 94	if path != "." {
 95		descFallback += path + " at "
 96	}
 97	if isCommitHash && len(ref) > 7 {
 98		descFallback += ref[:7]
 99	} else {
100		descFallback += ref
101	}
102	descFallback += " in " + repoDisplayName
103
104	description := getRepoDescriptionOrFallback(repo, descFallback)
105
106	data := TreeData{
107		RepoBaseData: RepoBaseData{
108			BaseData: BaseData{
109				ServerName:  cfg.Name,
110				ActiveTab:   "tree",
111				Title:       title,
112				Description: description,
113			},
114			Repo:          repo,
115			DefaultBranch: defaultBranch,
116		},
117		Ref:          ref,
118		Path:         path,
119		Entries:      entries,
120		IsCommitHash: isCommitHash,
121	}
122
123	renderHTML(w, "tree.html", data)
124}