When deleted, the repo still shows in explore,... #200
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub#200
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
https://hub.packden.us/crueber/walhub
Check it out and see why that is still there with a loading label. It needs to be completely removed when deletions happen, such that I can import it again if I want.
Fixed by PR #202 (branch fix/issue-200, not merged). Root cause is THREE stacked layers: (1) backend: raw prefix listing resurrected deletes — filesystem CAS .lock sidecars persist by design and keep the name behind ListPrefixes (reproduced live; your crueber/walhub ghost matches this exactly); listings are now manifest-gated. (2) browser HTTP cache: SWR resurrected deletes up to 60s — SDK listings now bypass it. (3) app cache: delete/import invalidate listing keys; repo shell 404s render not-found. Verified end to end on a scratch server (UI delete → explore empty immediately, re-create → 201 + row back, both themes). Note: your :8080 stack's existing ghosts (crueber/walhub, e2e/demo2-fork, o/r-fork) will vanish on upgrade with no migration needed.
REVIEW PR #202 (fix/issue-200, commit
4e76fe7) — verified in scratch worktree /tmp/walhub-200 (reused, already at4e76fe7; no new worktree created). Main worktree untouched (still clean on main apart from pre-existing untracked .opencode/). No browser drive per instructions — tests + reasoning only.ROOT CAUSE — CONFIRMED. internal/store/filesystem.go:698-771 List skips .lock sidecars, but ListPrefixes (773-800) is a pure ReadDir subdirectory listing with no sidecar filtering. After wal.Registry.Delete (internal/wal/registry.go:271-318) sweeps every listed object, the per-key .lock flock files persist by design (filesystem_test.go:197-202 pins this), so the repo dir survives and ListPrefixes keeps returning the ghost. Memory/S3 never ghost (no sidecars), which is why this only bit filesystem users. Manifest-gating (cmd/walhub/serve.go:530-558 liveRepos) fixes it on the read path on every backend, mirroring the existing wal.refreshList precedent (registry.go:381-396, same limit-8 + fail-closed drop). Test only simulates litter with note.json (can't Put .lock via API — rejected at filesystem.go:87), acceptable stand-in since the gate only cares about manifest absence.
COST / LAW 4+6 — ACCEPTABLE, with one note. Limit 8 is a concurrency cap, not a result cap: total Heads = repos under owner, served 8-at-a-time, full sorted list returned, no truncation, so pagination semantics unchanged (endpoints were and are unpaginated full arrays; client caps MAX_OWNERS=50/MAX_REPOS_PER_OWNER=10 in web/src/lib/owners.js). Explore render pays ~2x Heads (Owners() gates per owner, then each owners.repos() re-gates) — but explore is a cold human-driven path, not a Law-6 hot path (push/refs/checkpoint untouched), and wal already pays the same scan every 30s in listingRefresher. No sequential store round trip added to any hot path; no budget assertion touched.
NO-STORE — SAFE, correctly scoped. owners/ownerRepos use writeCached with empty etag (internal/api/discovery.go:128,141) → server never emits ETag/304 here, so fetch cache:no-store (web/sdk/src/core.js:245-256) cannot break conditional flows; _dispatch 304 path untouched. Server still answers SWR; change is client-side only. Data-layer 5s TTL claim checks out (useData default DEFAULT_TTL=5000, web/src/lib/data.js:154; Owners.jsx:28,72 pass no TTL). No other callers affected.
INVALIDATION — COMPLETE for the issue path. Settings.jsx:582-586 drops owners + repos:{owner} + repo/social/activity:{full} then navigates / — explore refetches fresh. Import.jsx:66-68 drops owners + repos:{owner} on landed import (incl. 200 no-op). Minor non-blocking note: back-navigating to the deleted repo URL may briefly serve stale resolve:/tags:/latest:/policy: entries (TTL-bounded, self-heals); out of scope. Repo.jsx:470,486-503: 404 summary → null → 'repository not found' shell; loading… only while undefined — no infinite spinner; non-404 errors keep the pre-existing tray contract.
RE-IMPORT / 409 — SOUND. Exists is manifest-gated (serve.go:560-566); Delete linearizes on manifest removal first (registry.go:288), so re-create/re-import sees a clean name. Covered by TestRepoRegistryDeleteVanishesAndRecreates (serve_registry_test.go:93).
UPGRADE WITHOUT MIGRATION — TRUE. Read-path gate; old .lock litter stays on disk but is invisible to List AND ListPrefixes-gated results. Residue: ~1 tiny flock file per deleted object, no cleaner (nothing ever removes .lock sidecars) — negligible, flagging only so it's a conscious accept.
GATES — gofmt clean, go vet clean, no go.mod/go.sum/package.json changes (stdlib sort only). go test -race ./cmd/walhub/ PASS incl. 3 new TestRepoRegistry* tests. cmd/walhub cover 15.8% is pre-existing (CLI package, outside the internal/... ≥95% gate); no internal/ package touched. JS: all 48 web/test/unit/*.test.js files pass, 0 failures (run per-file; single-process glob run stalls in this env — pre-existing harness slowness, not this PR; new sdk-nostore-304.test.js 6/6 incl. the #200 pin). Docs: 07_api.md + 12_web_ui.md decision entries present and accurate.
No fixes pushed — nothing blocking found; only the two non-blocking notes above.
MERGE RECOMMENDATION: ready to merge.
Fixed by PR #202 (review: lock-sidecar mechanism confirmed, cost/pagination/invalidation verified; all green), merged. Closing.