Repository navigation
Run every git process through one builder with an explicit repository policy - #29
Merged
Merged
Conversation
… policy git processes were spawned in many places, relying on whatever environment and configuration they inherited. - Recovery's scratch repository inherited GIT_DIR, so under git --git-dir=... e2ee recover its init and index-pack wrote packs into the user's repository and its connectivity check could pass for the wrong reason. - Carrier commits ran the user's hooks and signing, so a global commit.gpgSign or core.hooksPath made carrier init and push fail. - recover --repo B resolved its target from the current directory, not B. - A failed git ls-tree on a historical carrier commit counted as "no copy". - Any failed carrier fetch, even offline, ran git fsck on the whole cache, and generations replaced by rebuild were never removed. src/gitcmd.rs now builds every git command. The user's repository is resolved once to an absolute git dir and named explicitly. Repositories the program owns drop repository-selecting variables, injected config and commit identity, and add core.hooksPath=/dev/null and gpgSign=false. Commands that talk to the carrier remote keep config injected with git -c (proxies, credential helpers, insteadOf) and append those overrides after it. Carrier commits use write-tree and commit-tree --no-gpg-sign; pushes use --no-verify. Carrier listings return a typed absent/malformed/chunks result, fsck runs only when the remote was reachable, and rebuild removes the generations it replaces.
native_git_fetch_reimports_packs_after_local_objects_are_pruned failed twice on Linux CI and never locally: once with "fatal: object ... not found" on the second fetch, once because the feature commit survived gc --prune=now. Both fit Git's detached auto-maintenance after a fetch repacking concurrently with the test's own gc, but that is not confirmed. The test now disables auto-maintenance, auto-gc and commit-graph writes in its destination repository and replaces gc --prune=now with an explicit repack -a -d and prune --expire=now, so nothing outside the test changes the object store between the prune and the assertion.
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.
Step 5a of the refactoring plan, covering safety: Opus 1.8, 3.2, 3.3, 3.5; Astra Category 3 mediums on
recover --repoand on carrier commits inheriting user Git behaviour. Performance batching is step 5b and is not in this PR.Reproduced on the base branch, then fixed
GIT_DIR. Undergit --git-dir=… e2ee recover, itsinit --bareandindex-packwrote pack files into the user's repository, so the connectivity check could pass for the wrong reason.Test:
git_isolation::recovery_scratch_repository_ignores_an_inherited_git_dir. Before the fix: "recovery wrote into the repository GIT_DIR named".commit.gpgSign=trueorcore.hooksPathmade carrierinitand push fail. Carrier commits are nowwrite-treepluscommit-tree --no-gpg-signwith a fixed identity, followed byupdate-ref, and pushes use--no-verify.Test:
carrier_publication_ignores_user_hooks_and_signing, with failing hooks and a failinggpg.programset inGIT_CONFIG_GLOBAL. Before the fix,initfailed.recover --repo Bresolved its target from the current directory. It now uses B for the URL, key and state.--repois optional, with no.default.Test:
recover_resolves_its_target_through_the_named_repository, run from another repository and from outside any repository. Before the fix: "no Git remote named origin".git ls-treecounted as "no copy". A newCarrierListing { Absent, Malformed, Chunks }separates what the storage contains from Git failures, which now propagate.git_rev_parseuses--verify --quiet.Test:
storage::tests::a_failed_carrier_listing_is_an_error_not_a_missing_copy.git fsck --full, and replaced cache generations were never removed.FetchError { Remote, Local }now skips the check when the remote is unreachable, andrebuilddeletes the generations it replaces, under the lock.Tests:
an_unreachable_carrier_does_not_trigger_a_cache_check(checked withGIT_TRACE), plus a new assertion indeleted_and_corrupt_carrier_caches_are_rebuilt. Before the fix, that assertion found two generations left.The builder (
src/gitcmd.rs)GitRepository::from_environment()andGitRepository::open(path)resolve the user's repository once, to an absolute git dir.repo.git()runsgit --git-dir <abs>and drops inherited repository-selection variables, includingGIT_OBJECT_DIRECTORY,GIT_ALTERNATE_OBJECT_DIRECTORIESandGIT_COMMON_DIR.GIT_AUTHOR_*/GIT_COMMITTER_*. It adds-c core.hooksPath=/dev/null commit.gpgSign=false tag.gpgSign=false push.gpgSign=false core.fsmonitor=false.transport()handles commands that talk to the carrier remote: fetch, ls-remote and push. It keeps config injected withgit -c, such as proxies, credential helpers andinsteadOf, and appends the overrides after it, so hooks and signing stay disabled.Test:
carrier_transport_keeps_config_injected_with_dash_c_but_not_its_hooks. It fails with "Could not resolve hostname example-carrier" if transport drops injected config.EncryptedRepositoryandsrc/git.rstake&GitRepositoryinstead of&Path.git::ensure_repositoryandgit_state_directoryare deleted. About 150 test call sites were migrated.Behaviour changes
GIT_OBJECT_DIRECTORY,GIT_ALTERNATE_OBJECT_DIRECTORIESandGIT_COMMON_DIRno longer apply to the user's repository. Otherwise--repo Bcould still read A's object store.Verification
cargo fmt --check,cargo clippy --all-targets -- -D warnings,cargo test --all-targets(189 passed).~/.local/state/git-e2eeand~/.config/git-e2eedid not exist before or after the suite.Left open
rebuildremoved sees the carrier as unavailable. It fails closed at compare-and-swap.create_carrier_checkoutfailures still run fsck for any cause.resolve_tag_chainstill treats a failedcat-file -tas "missing". Step 5b rewrites tag parsing.