Files
ngit-grasp/src/http
DanConwayDev 4665a00ea9 fix(grasp06): inline zero-ref /prs/ cleanup under per-path lock
Replaces the periodic /prs/ cleanup sweep (reverted in the previous
commit) with inline zero-ref cleanups at the three sites that can
leave a /prs/<submitter>/<identifier>.git bare repo empty:

  1. The /prs/ receive handler at the end of a push, already in place
     prior to the revert.
  2. The PR-event policy when it discards a scoped placeholder whose
     incoming event fails the (signer, identifier, commit) check —
     deletes refs/nostr/<event-id> and, if that empties the repo,
     removes the bare directory in the same step.
  3. The standard 30-minute purgatory expiry sweep when a scoped
     placeholder times out without a matching PR event arriving —
     same shape as (2), but reached from the synchronous cleanup
     loop, so the per-path lock is taken with try_lock and the
     filesystem cleanup is skipped (leaving a harmless dangling ref)
     if a push is currently in flight to the same path.

All three sites share a single Arc<DashMap<PathBuf, Arc<Mutex<()>>>>
of per-`(submitter, identifier)` locks. The receive handler now holds
its entry for the entire pipeline — `git init --bare` →
`git-receive-pack` → per-ref validation → zero-ref cleanup — instead
of only for the init step, so a concurrent push or off-push cleanup
cannot remove the bare repo while it is still being written. The
same lock map is plumbed into PolicyContext (used by pr_event.rs)
and Purgatory (via a one-shot `set_prs_cleanup_ctx` setter wired in
main, so tests can leave it unset and get the previous behaviour for
in-memory entries).

This delivers what the reverted commit was reaching for without the
370-line periodic walker, the mtime heuristic, or the
`has_prs_scope`/`DEFAULT_EXPIRY` API surface area on Purgatory: the
last ref always implies an immediate (or, under lock contention, a
next-cycle) repo removal, and the only code path that ever deletes
a /prs/ repo dir is one that already holds the per-path lock.

Docs:

- CHANGELOG.md, docs/how-to/enable-grasp-06.md: describe the three
  inline cleanup sites; drop the "periodic 10-minute sweep" line.
- docs/explanation/architecture.md: drop the src/grasp06/cleanup.rs
  bullet; document the lock as held for the whole pipeline and
  shared with off-push cleanup paths.
- docs/explanation/grasp-06-contributor-pr-submission.md: replace
  the "Periodic /prs/ cleanup" subsection with a "Zero-ref /prs/
  cleanup" subsection enumerating the three sites and the shared
  lock map; update "On-demand bare repo creation" to reflect the
  wider lock scope.
2026-05-15 18:49:45 +00:00
..