Skip to content

Commit c3323b9

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 #4482 Signed-off-by: David Lomas <dl3@pale-eds.co.uk> Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
1 parent 789e6f1 commit c3323b9

1 file changed

Lines changed: 19 additions & 6 deletions

File tree

compat/mingw.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2821,7 +2821,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
28212821
int mingw_rename(const char *pold, const char *pnew)
28222822
{
28232823
static int supports_file_rename_info_ex = 1;
2824-
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle;
2824+
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle, attrsold;
28252825
int tries = 0;
28262826
wchar_t wpold[MAX_LONG_PATH], wpnew[MAX_LONG_PATH];
28272827
int wpnew_len;
@@ -2913,11 +2913,24 @@ int mingw_rename(const char *pold, const char *pnew)
29132913
gle = GetLastError();
29142914
}
29152915

2916-
if (gle == ERROR_ACCESS_DENIED && is_inside_windows_container()) {
2917-
/* Fall back to copy to destination & remove source */
2918-
if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold, 1))
2919-
return 0;
2920-
gle = GetLastError();
2916+
if (gle == ERROR_ACCESS_DENIED) {
2917+
if (is_inside_windows_container()) {
2918+
/* Fall back to copy to destination & remove source */
2919+
if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold, 1))
2920+
return 0;
2921+
gle = GetLastError();
2922+
} else if ((attrsold = GetFileAttributesW(wpold)) & FILE_ATTRIBUTE_READONLY) {
2923+
/* if file is read-only, change and retry */
2924+
SetFileAttributesW(wpold, attrsold & ~FILE_ATTRIBUTE_READONLY);
2925+
if (MoveFileExW(wpold, wpnew,
2926+
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) {
2927+
SetFileAttributesW(wpnew, attrsold);
2928+
return 0;
2929+
}
2930+
gle = GetLastError();
2931+
/* revert attribute change on failure */
2932+
SetFileAttributesW(wpold, attrsold);
2933+
}
29212934
}
29222935

29232936
/* revert file attributes on failure */

0 commit comments

Comments
 (0)