Commit 1790a024c2
Verified · cmc
Layout: unified · split
e2e/design_test.go +13
| @@ -57,6 +57,19 @@ func TestReadmeRelativeLinks(t *testing.T) { | |||
| 57 | t.Errorf("missing %q", want) | 57 | t.Errorf("missing %q", want) |
| 58 | } | 58 | } |
| 59 | } | 59 | } |
| 60 | // Directories sort ahead of files, whatever git's own tree order was: | ||
| 61 | // docs/ and img/ precede LICENSE and README.md despite sorting after | ||
| 62 | // them byte-wise. | ||
| 63 | for _, dir := range []string{"docs", "img"} { | ||
| 64 | d := strings.Index(body, `/tree/main/`+dir+`">`) | ||
| 65 | f := strings.Index(body, `/blob/main/README.md">`) | ||
| 66 | if d < 0 || f < 0 { | ||
| 67 | t.Fatalf("listing missing %s/ or README.md", dir) | ||
| 68 | } | ||
| 69 | if d > f { | ||
| 70 | t.Errorf("%s/ listed after README.md; directories should come first", dir) | ||
| 71 | } | ||
| 72 | } | ||
| 60 | // Branch dropdown lists branches. | 73 | // Branch dropdown lists branches. |
| 61 | if !strings.Contains(body, `class="refmenu"`) || !strings.Contains(body, ">All refs") { | 74 | if !strings.Contains(body, `class="refmenu"`) || !strings.Contains(body, ">All refs") { |
| 62 | t.Error("branch dropdown missing") | 75 | t.Error("branch dropdown missing") |
internal/httpd/web.go +7
| @@ -13,6 +13,7 @@ import ( | |||
| 13 | "net/http" | 13 | "net/http" |
| 14 | "path" | 14 | "path" |
| 15 | "regexp" | 15 | "regexp" |
| 16 | "sort" | ||
| 16 | "strconv" | 17 | "strconv" |
| 17 | "strings" | 18 | "strings" |
| 18 | "time" | 19 | "time" |
| @@ -433,6 +434,12 @@ func (s *Server) renderTree(w http.ResponseWriter, r *http.Request, p repoPage, | |||
| 433 | s.notFound(w, r) | 434 | s.notFound(w, r) |
| 434 | return | 435 | return |
| 435 | } | 436 | } |
| 437 | // Directories first. git's tree order interleaves them with files, but | ||
| 438 | // a listing is scanned by shape before name. Stable, so each group | ||
| 439 | // keeps the ordering git gave it. | ||
| 440 | sort.SliceStable(entries, func(i, j int) bool { | ||
| 441 | return entries[i].Type == "tree" && entries[j].Type != "tree" | ||
| 442 | }) | ||
| 436 | prefix := "" | 443 | prefix := "" |
| 437 | if dirPath != "" { | 444 | if dirPath != "" { |
| 438 | prefix = dirPath + "/" | 445 | prefix = dirPath + "/" |