Stop the server rewriting the repositories it serves, and add git-collab-server migrate #81
Loading…
Reference in a new issue
No description provided.
Delete branch "worktree-agent-a32970d20c5f1d961"
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?
state::list_patchescalledmigrate_patch_layout, and the server callslist_patcheson every repo page. So rendering wrote to the repositorybeing rendered: any anonymous visitor mutated it, with no lock, able to
race a concurrent request or an in-flight
receive-pack.The crux is not "stop calling migrate" — it is that the read path had no
way to see an unmigrated patch at all.
patch_refs_underglobbed<id>/events, which a barerefs/collab/patches/<id>does not match, sowithout the migration the patch was simply invisible and the page would
have rendered an empty list instead of writing. Reads now tolerate both
layouts: the bare ref is the DAG and is walked where it lies. The two
shapes cannot coexist for one id — git will not have
<id>be both a refand a directory — so there is nothing to disambiguate.
Migration moves to the callers that own their repository. The CLI does it
once at its entry point, because writes genuinely need it:
<id>/rev/<oid>and a bare<id>are a directory/file conflict gitrefuses.
synckeeps the call it already had. The server has none.And an operator gets
git-collab-server migrate, which is what makes thesequencing work: once
e5096ffcstrips legacy support an unmigrated repowill fail to read, and this is how you convert a roster before the
upgrade rather than from the wreckage after it. It walks
repos_dirbythe server's own discovery rules, reports every repository including the
ones with nothing to do, and has a dry run.
It also fixes the diagnostic the old path never gave. Failures were
printed per patch on stderr with no repository name and nothing returned,
so a read-only mount produced noise and no verdict; now each repository is
probed for writability first — by writing, since a read-only mount leaves
the mode bits saying 0755 — and reported by name, with the run exiting
non-zero if anything was left behind.
Locking: each repository is migrated under its own
SyncLock, theadvisory lock
git-collab syncalready takes, so a concurrent sync isrefused rather than raced. That is not a guarantee against
git receive-pack, which takes no such lock; what covers a push is narrowerand comes from git itself, since every ref written here goes through git2
and takes the per-ref lockfile. A push landing mid-run can still leave the
report stale, which is what the dry run is for.
Tests: an old-layout patch served over real HTTP across every page that
renders patches, with all of
refs/collab/**byte-identical afterwards —and the same patch asserted present on the list, the overview and its
detail page, because not writing is worthless if it means not reading.
Plus migrate's own behaviour: it migrates, it is idempotent, it walks
nested repos and skips dot-prefixed paths, it names a repository it cannot
write without letting that stop the others, and its dry run changes
nothing.
Migrated from git-collab patche
46c3cdc545932cd8dc80206d8b99c53e977abb62.Original author: a73x dev@a73x.sh.
Fixes #80
Revision 1:
0086f3c774c2e9e353781b7d30b18ba44763d17a; base15bc9a3c2f8c1622b6eb5157c6176452ba7569bb