Repository navigation
mingw: preserve read-only rename fallback after open failure - #6503
Open
JadeSkaggs wants to merge 1 commit into
Open
JadeSkaggs wants to merge 1 commit into
JadeSkaggs wants to merge 1 commit into
Conversation
Writing loose objects on a macOS-hosted SMB share backed by APFS can fail with "Permission denied". Git makes the temporary object read-only before renaming it. On this share, CreateFileW() with DELETE access fails with ERROR_ACCESS_DENIED for that read-only source. The POSIX rename path introduced in 391bcea returns immediately when opening the source fails, bypassing the existing read-only workaround from git-for-windows#4527. Save the error and route it through the common rename error handling instead. This allows the existing fallback to clear the source's read-only attribute, retry with MoveFileExW(), and restore the attributes on success or failure. The POSIX rename path remains unchanged when opening the source succeeds. An unmodified MSVC x64 Release build of 5cf10d7 failed at git add on the Mac SMB/APFS share, while the same build with this patch passed add, commits, checkouts, relative and absolute worktree add/remove, and fsck on both local storage and the share. Forced replacement of a read-only destination passed; a locked-destination failure preserved both files, the source's read-only attribute, and the index. These tests used windows.appendAtomically=false for the separate SMB reflog append issue. The local t7001-mv, t2400-worktree-add, and t2403-worktree-move suites passed with their platform prerequisite skips. The selected "ref transaction: many concurrent writers" test from t0610-reftable-basics also passed. No new in-tree test is added for the share-specific source-open failure. The complete test suite was not run. Co-authored-by: OpenAI Codex (GPT-6) Signed-off-by: Jade Skaggs <jade@revealtech.ai>
dscho
reviewed
Oct 22, 2026
| errno = err_win_to_posix(GetLastError()); | ||
| return -1; | ||
| gle = GetLastError(); | ||
| goto handle_rename_error; |
Member
There was a problem hiding this comment.
The err_win_to_posix() function is pretty exhaustive in the range of values it handles. However, the code behind handle_rename_error is not.
How certain can we be that this innocuous change doesn't introduce a regression via previously-handled-but-now-no-longer error value? I don't see an adequate discussion of this in the commit message, either.
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.
Why this PR
Windows-native Git can fail to write objects on a macOS-hosted SMB share backed by APFS. In the reproduced setup, even
git addin a fresh repository fails with:This prevents normal Windows development against the shared repository. The failure bypasses an existing APFS workaround introduced by #4527, rather than requiring a new SMB implementation.
Cause and change
Git makes a temporary loose object read-only before renaming it into place. On the affected share,
CreateFileW(source, DELETE, ...)returnsERROR_ACCESS_DENIEDfor that read-only source.The POSIX rename path introduced in 391bceae435 returns immediately when opening the source fails. That skips the common error handling, including the existing workaround that clears the source's read-only attribute, retries with
MoveFileExW(), and restores the attributes on success or failure.This five-line change saves the error and routes it through that existing handling. The POSIX rename path is unchanged when opening the source succeeds.
Validation
Built the clean source at
5cf10d74486d1e59b9ae6cedaedb4e26314e1557, then rebuilt with only this patch using the same compiler, dependencies, and build configuration.git addwith the loose-object permission errorThe scripted end-to-end checks ran 25 Git commands and 78 passing assertions per location against the patched executable, with zero timeouts. One rename deliberately exits nonzero to test failure preservation. Coverage includes:
git fsck --full --no-danglingand final clean status.Existing upstream tests also passed on local storage:
t7001-mvt2400-worktree-addt2403-worktree-movet0610-reftable-basics: “ref transaction: many concurrent writers”The concurrent-writers check exercises the workload for which the newer POSIX rename behavior matters.
Scope and limitations
windows.appendAtomically=falsefor the separate reflog append issue; this patch does not address that issue.