Skip to content

Commit 7170c75

Browse files
dsl101Git for Windows Build Agent
authored andcommitted
mingw: work around rename() failing on a read-only file
At least on _some_ APFS network shares, Git fails to rename the object files because they are marked as read-only, because that has the effect of setting the uchg flag on APFS, which then means the file can't be renamed or deleted. To work around that, when a rename failed, and the read-only flag is set, try to turn it off and on again. This fixes git-for-windows#4482 Signed-off-by: David Lomas <dl3@pale-eds.co.uk> Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
1 parent 5237e11 commit 7170c75

1 file changed

Lines changed: 19 additions & 6 deletions

File tree

lib/compat/mingw.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2526,7 +2526,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
25262526
int mingw_rename(const char *pold, const char *pnew)
25272527
{
25282528
static int supports_file_rename_info_ex = 1;
2529-
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle;
2529+
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle, attrsold;
25302530
int tries = 0;
25312531
wchar_t wpold[MAX_PATH], wpnew[MAX_PATH];
25322532
int wpnew_len;
@@ -2618,11 +2618,24 @@ int mingw_rename(const char *pold, const char *pnew)
26182618
gle = GetLastError();
26192619
}
26202620

2621-
if (gle == ERROR_ACCESS_DENIED && is_inside_windows_container()) {
2622-
/* Fall back to copy to destination & remove source */
2623-
if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold, 1))
2624-
return 0;
2625-
gle = GetLastError();
2621+
if (gle == ERROR_ACCESS_DENIED) {
2622+
if (is_inside_windows_container()) {
2623+
/* Fall back to copy to destination & remove source */
2624+
if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold, 1))
2625+
return 0;
2626+
gle = GetLastError();
2627+
} else if ((attrsold = GetFileAttributesW(wpold)) & FILE_ATTRIBUTE_READONLY) {
2628+
/* if file is read-only, change and retry */
2629+
SetFileAttributesW(wpold, attrsold & ~FILE_ATTRIBUTE_READONLY);
2630+
if (MoveFileExW(wpold, wpnew,
2631+
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) {
2632+
SetFileAttributesW(wpnew, attrsold);
2633+
return 0;
2634+
}
2635+
gle = GetLastError();
2636+
/* revert attribute change on failure */
2637+
SetFileAttributesW(wpold, attrsold);
2638+
}
26262639
}
26272640

26282641
/* revert file attributes on failure */

0 commit comments

Comments
 (0)