Repository navigation
fix: serialize snapshot Git indexes across processes and reject failed captures - #4
Draft
thelabcorner wants to merge 12 commits into
Draft
thelabcorner wants to merge 12 commits into
thelabcorner wants to merge 12 commits into
Conversation
…sed on Git errors
…ship, and fail-safe revert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why this was necessary
OpenFork logged
fatal: Unable to create .../snapshot/.../index.lock: File exists(Git exit 128), then loggedtracking hash="". The legacy snapshot stage operation logged and swallowed errors, allowing subsequent Git operations to proceed on an untrusted shadow index. The V1 service had only an in-process semaphore; the core/V2 snapshot service uses the same shadow Git directory with a separate lock. Two services or independent server processes could therefore interleave writes.Implemented
packages/core/src/snapshot-index-lock.tsdefines one filesystem-lease protocol with a single key, root and timeout contract. Both V1 and core/V2 acquire it over the entire index mutation transaction, on top of existing in-process locks. Reuses the project Flock implementation (atomic mkdir, heartbeat, owner-token verification, stale lock reclamation).git addretries bounded transient legacyindex.lockcollisions, then rejects exhaustion. Errors from Git ignore detection, file enumeration, indexed removals, staging and index rebuilding no longer allow write-tree to run. Both V1 and core Git reject malformed/empty tree object IDs. Core Git ignore checking now correctly treats exit 1 as no ignored paths but rejects real check failures; it no longer silently includes ignored files in a capture. V1 invalidates unsuccessful capture memoization and returnsundefinedrather than publishing stale/empty trees.read-tree/checkout-indexnow fail the operation. Revert prevalidates tree IDs and worktree containment; a failedls-treecannot imply absence and therefore cannot trigger file deletion.Targeted regression tests added
index.lockduringgit add→ failed capture, lock untouched, no empty/stale hash, successful subsequent recovery once unlocked.Verification / outstanding gates
tree-sitter-powershellinvokes an olderg++that does not recognize-std=gnu++20; this is an unrelated runner toolchain blocker, not a passing validation result. See job 114323169269.Recovery / rollout
index.lockis not blindly deleted: because Git does not encode lock ownership, removing a live writer's lock can corrupt the index. For the already-affected machine, stop OpenFork servers and ensure Git is not writing that shadow repository, then remove only the verified staleindex.lock.