internal/httpd/filenav.go
72 lines · 1975 bytes
1package httpd
2
3import (
4 "path"
5 "sort"
6
7 "gitbay.org/gitbay/internal/gitutil"
8)
9
10// fileNav is the column beside a file: its directory's entries, the file
11// marked, and a link up. It is the tree page's listing rendered as a
12// list, so reading a repository does not mean going back for each file.
13type fileNav struct {
14 Title string // the directory, or the repository name at the root
15 Parent string // URL of the parent tree; "" at the root
16 Entries []fileNavEntry
17}
18
19type fileNavEntry struct {
20 Name string // directories carry a trailing slash
21 URL string
22 Dir bool
23 Current bool
24}
25
26// sortDirsFirst orders a listing by shape before name, stably, so each
27// group keeps the order git gave it. The tree page and the navigator
28// share it.
29func sortDirsFirst(entries []gitutil.TreeEntry) {
30 sort.SliceStable(entries, func(i, j int) bool {
31 return entries[i].Type == "tree" && entries[j].Type != "tree"
32 })
33}
34
35// navDir is the directory ListTree wants for filePath: "" at the root.
36func navDir(filePath string) string {
37 if d := path.Dir(filePath); d != "." {
38 return d
39 }
40 return ""
41}
42
43// fileNavFor builds the navigator for filePath from its directory's
44// entries. repoPath is owner/name.
45func fileNavFor(repoPath, ref, filePath string, entries []gitutil.TreeEntry) fileNav {
46 dir := path.Dir(filePath)
47 if dir == "." {
48 dir = ""
49 }
50 base := "/" + repoPath
51 nav := fileNav{Title: dir}
52 if dir == "" {
53 nav.Title = path.Base(repoPath)
54 } else if up := path.Dir(dir); up == "." {
55 nav.Parent = base + "/tree/" + ref
56 } else {
57 nav.Parent = base + "/tree/" + ref + "/" + up
58 }
59 sortDirsFirst(entries)
60 for _, e := range entries {
61 full := path.Join(dir, e.Name)
62 ent := fileNavEntry{Name: e.Name, Dir: e.Type == "tree", Current: full == filePath}
63 if ent.Dir {
64 ent.Name += "/"
65 ent.URL = base + "/tree/" + ref + "/" + full
66 } else {
67 ent.URL = base + "/blob/" + ref + "/" + full
68 }
69 nav.Entries = append(nav.Entries, ent)
70 }
71 return nav
72}