Repository navigation
fix(git): pin autocrlf=false on the uncached fallback clone and checkout - #3409
Open
Abhishek Acharya (abhishekacharya200) wants to merge 2 commits into
Open
Abhishek Acharya (abhishekacharya200) wants to merge 2 commits into
Abhishek Acharya (abhishekacharya200) wants to merge 2 commits into
Conversation
The fallback working-tree clone freezes the host's effective git config into GIT_CONFIG_KEY_n, so a host with core.autocrlf=true wrote CRLF bytes while the follow-up `git checkout <locked sha>` ran without that snapshot and saw every text file as modified, failing the install after the producer gained a commit. Pin core.autocrlf=false on both commands, as the GitCache and bare-cache paths already do (microsoft#2982), so the materialized bytes are the committed bytes and the two commands agree. Closes microsoft#3368
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The fixture commits retain CRLF bytes on Windows when the host’s core.autocrlf is false or unset, causing the LF assertions and Windows compatibility gate to fail.
1 open issue
What changed in this PR
Fixes #3368 by making the uncached Git fallback clone and checkout use consistent line-ending settings, preventing locked-commit installs from failing on hosts with core.autocrlf=true.
Changes:
- Adds a shared
core.autocrlf=falseargument helper to both working-tree operations. - Adds argument checks and a real-Git regression test for checking out an older commit.
- Documents the fallback fix in the changelog.
| File | Description |
|---|---|
tests/unit/cache/test_git_env.py |
Adds pin assertions and a CRLF-host regression scenario. |
src/apm_cli/utils/git_env.py |
Pins autocrlf off for working-tree clone and checkout. |
CHANGELOG.md |
Adds an Unreleased entry describing the install fix. |
Review effort: Balanced
|
|
||
| def _commit(message: str) -> None: | ||
| subprocess.run( | ||
| [git, "-C", str(src), "-c", "user.name=t", "-c", "user.email=t@t", "add", "f.txt"], |
Contributor
Author
There was a problem hiding this comment.
Fixed in 8c332e5, slightly differently from the suggestion. The fixture now writes LF bytes with write_bytes, so the commits hold LF whatever the host's autocrlf setting is, without pinning anything on git add. I could not run this on Windows, so the Windows gate is the real check.
write_text produces CRLF on Windows, and with core.autocrlf off those bytes would reach the fixture commits and fail the LF assertions.
This branch has not been deployed
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.

Fixes #3368.
Problem
The uncached fallback materializes a full working-tree clone and then checks out the locked SHA. The clone inherits the host's effective git config frozen into
GIT_CONFIG_KEY_nbygit_clone_env, so on a host withcore.autocrlf=trueit writes CRLF bytes for LF-committed files. The checkout runs under the downloader's isolated env (GIT_CONFIG_NOSYSTEM=1, emptyGIT_CONFIG_GLOBAL), which has no such snapshot, compares that CRLF worktree against the LF index, and refuses:apm installthen fails withFailed to checkout commit <sha>— but only once the locked SHA falls behind the branch head, which is why it looks intermittent.#2982pinnedcore.autocrlf=falseon the GitCache and bare-cache paths; the uncached fallback never got the pin.Fix
Added
git_autocrlf_pin_args()and applied it to bothclone_git_worktreeandcheckout_git_worktree, so the working tree the fallback writes and the checkout that follows agree on line-ending handling and the materialized bytes are the committed LF bytes regardless of host config.-coutranks the frozenGIT_CONFIG_KEY_nsnapshots, which is the same precedence argument#2971relies on. Both call sites ofcheckout_git_worktreeare the fallback commit path, so the blast radius is that path.Tests
TestUncachedFallbackLineEndings:test_clone_and_checkout_pin_autocrlf_false— asserts the pin is present, adjacent to-c, and precedesclone/checkout.test_locked_sha_checks_out_from_a_crlf_host— builds a two-commit repo, sets a host gitconfig withcore.autocrlf=truefor the clone snapshot, clones, then checks out the older SHA with the isolated env.Red/green on this Windows host: without the change the clone writes
a\r\nb\r\nc\r\nand the checkout raises the exact error above; with it the clone writesa\nb\nc\nand the checkout lands on the locked SHA.Verification
tests/unit/cache/test_git_env.py: 103 passed, 2 failed — the twotest_real_lookup_rejects_symlink_into_projectcases, which fail identically onmainhere (no Windows symlink privilege).tests/unit/cache tests/unit/deps/test_clone_connect_retry.py tests/integration/test_git_hook_env_isolation.py: 10 failures, byte-for-byte the same set asmainin this environment (symlink privilege and Windows case-sensitivity), with the two new tests passing.ruff checkandruff format --checkclean on both touched files.