diff --git a/internal/web/repohome.go b/internal/web/repohome.go
index a217c93..7e1897d 100644
--- a/internal/web/repohome.go
+++ b/internal/web/repohome.go
@@ -13,7 +13,9 @@ import (
)
// readmeCandidates are tried in order at the repo root; first hit wins.
-var readmeCandidates = []string{"README.md", "README.markdown", "README.mkd", "README"}
+// Matched case-insensitively (a lowercase readme.md is just as valid as
+// README.md), so candidates stay lowercase for comparison.
+var readmeCandidates = []string{"readme.md", "readme.markdown", "readme.mkd", "readme"}
const (
readmeLimit = 1 << 20
@@ -152,8 +154,8 @@ func (s *Server) attachReadme(data *repoHomeData, repoPath string, entries []git
var readme string
for _, candidate := range readmeCandidates {
for _, entry := range entries {
- if entry.Type == "blob" && entry.Path == candidate {
- readme = candidate
+ if entry.Type == "blob" && strings.EqualFold(entry.Path, candidate) {
+ readme = entry.Path
break
}
}
diff --git a/internal/web/repohome_test.go b/internal/web/repohome_test.go
index be2ac6f..a28531f 100644
--- a/internal/web/repohome_test.go
+++ b/internal/web/repohome_test.go
@@ -97,6 +97,43 @@ func TestRepoHomePrivate(t *testing.T) {
}
}
+func TestRepoHomeLowercaseReadme(t *testing.T) {
+ httpServer, _, dataDir := newTestServer(t)
+ createRepo(t, newLoggedInClient(t, httpServer), httpServer, "lc", "public")
+ seedFiles(t, dataDir, "lc")
+
+ work := filepath.Join(t.TempDir(), "work")
+ cmd := exec.Command("git", "clone", "-q", filepath.Join(dataDir, "repos", "josie", "lc.git"), work)
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Fatalf("clone: %v: %s", err, out)
+ }
+ for _, args := range [][]string{
+ {"mv", "README.md", "readme.md"},
+ {"-c", "user.email=t@t", "-c", "user.name=t", "commit", "-qm", "lowercase readme"},
+ {"push", "-q", "origin", "main"},
+ } {
+ cmd := exec.Command("git", args...)
+ cmd.Dir = work
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Fatalf("git %v: %v: %s", args, err, out)
+ }
+ }
+
+ resp, err := (&http.Client{}).Get(httpServer.URL + "/josie/lc")
+ if err != nil {
+ t.Fatalf("GET /josie/lc: %v", err)
+ }
+ body := readAll(t, resp)
+ if resp.StatusCode != http.StatusOK {
+ t.Fatalf("status = %d, want 200: %q", resp.StatusCode, body)
+ }
+ for _, want := range []string{"readme.md", "<strong>readme</strong>"} {
+ if !strings.Contains(body, want) {
+ t.Errorf("body lacks %q", want)
+ }
+ }
+}
+
func TestRepoHomeEmptyRepoShowsInstructions(t *testing.T) {
httpServer, _, _ := newTestServer(t)
loggedIn := newLoggedInClient(t, httpServer)
web: match README case-insensitively
readme.md (and other casings) now render on the repo home, like GitHub/Gitea; the matcher compared against exact uppercase candidates and missed any other spelling. The file read keeps the actual on-disk path. LLM Contributor: qwen/qwen3.8-27b
b8622ddd60a831ec5e82333e8c47f4706d65253e
cjosie <administrator@josie-c.com> · 2026-10-05T12:15 ·
browse files at this commit
parents:
97f81af