Skip to content

Commit 4758887

Browse files
dsl101Git for Windows Build Agent
authored and
Git for Windows Build Agent
committed
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 <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 48718e8 commit 4758887

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

compat/mingw.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2705,7 +2705,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
27052705
#undef rename
27062706
int mingw_rename(const char *pold, const char *pnew)
27072707
{
2708-
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle;
2708+
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle, attrsold;
27092709
int tries = 0;
27102710
wchar_t wpold[MAX_LONG_PATH], wpnew[MAX_LONG_PATH];
27112711
if (xutftowcs_long_path(wpold, pold) < 0 ||
@@ -2718,11 +2718,24 @@ int mingw_rename(const char *pold, const char *pnew)
27182718
return 0;
27192719
gle = GetLastError();
27202720

2721-
if (gle == ERROR_ACCESS_DENIED && is_inside_windows_container()) {
2722-
/* Fall back to copy to destination & remove source */
2723-
if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold))
2724-
return 0;
2725-
gle = GetLastError();
2721+
if (gle == ERROR_ACCESS_DENIED) {
2722+
if (is_inside_windows_container()) {
2723+
/* Fall back to copy to destination & remove source */
2724+
if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold))
2725+
return 0;
2726+
gle = GetLastError();
2727+
} else if ((attrsold = GetFileAttributesW(wpold)) & FILE_ATTRIBUTE_READONLY) {
2728+
/* if file is read-only, change and retry */
2729+
SetFileAttributesW(wpold, attrsold & ~FILE_ATTRIBUTE_READONLY);
2730+
if (MoveFileExW(wpold, wpnew,
2731+
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) {
2732+
SetFileAttributesW(wpnew, attrsold);
2733+
return 0;
2734+
}
2735+
gle = GetLastError();
2736+
/* revert attribute change on failure */
2737+
SetFileAttributesW(wpold, attrsold);
2738+
}
27262739
}
27272740

27282741
/* revert file attributes on failure */

0 commit comments

Comments
 (0)