files: seed a default README.txt into every member's public area

ensureUserPub only ran os.MkdirAll, so a freshly-provisioned /public
(and thus ~<name>/public on the web) came up empty — only ~chovy had a
README because it was uploaded by hand. Embed that help text as a
default and write it whenever the area has no README.txt.

ensureUserPub is hit on SFTP connect (fs.go) and when the web host
materializes ~<name>/public (AnonRoot), so this self-heals every
existing empty member the next time they connect or their page is
viewed — no manual backfill. A member's own README is never clobbered.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-07-01 02:43:27 +00:00
parent 042166b05f
commit d19c5c4c3e
4 changed files with 111 additions and 10 deletions

View file

@ -202,9 +202,11 @@ func TestWebAnonPublicSite(t *testing.T) {
}
func TestWebAnonMemberSiteEmptyNot404(t *testing.T) {
// A registered member who has not published anything yet (no public folder on
// disk) is reachable at ~name/public as an empty listing, not a 404. A missing
// file under them, and an unknown member, both still 404.
// A registered member who has not published anything yet is reachable at
// ~name/public as a browsable listing, not a 404 — materializing the area
// seeds a default README.txt, so the listing greets visitors with it rather
// than "(empty)". A missing file under them, and an unknown member, both
// still 404.
svc, st, _ := newTestService(t)
if _, err := st.EnsureUser("bob", "member", "SHA256:bobkey"); err != nil {
t.Fatal(err)
@ -216,8 +218,8 @@ func TestWebAnonMemberSiteEmptyNot404(t *testing.T) {
if rr.Code != http.StatusOK {
t.Fatalf("~bob/public (member, empty): want 200, got %d", rr.Code)
}
if !strings.Contains(rr.Body.String(), "(empty)") {
t.Fatalf("~bob/public should render an empty listing: %.200s", rr.Body.String())
if !strings.Contains(rr.Body.String(), "README.txt") {
t.Fatalf("~bob/public should render the seeded README in its listing: %.200s", rr.Body.String())
}
rr = httptest.NewRecorder()