Skip to content

Commit aff4426

Browse files
committed
mingw: try resetting the read-only bit if rename fails (git-for-windows#4527)
With this patch, Git for Windows works as intended on mounted APFS volumes (where renaming read-only files would fail). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2 parents 0cccb94 + d54a5e5 commit aff4426

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
@@ -2738,7 +2738,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
27382738
int mingw_rename(const char *pold, const char *pnew)
27392739
{
27402740
static int supports_file_rename_info_ex = 1;
2741-
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle;
2741+
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle, attrsold;
27422742
int tries = 0;
27432743
wchar_t wpold[MAX_LONG_PATH], wpnew[MAX_LONG_PATH];
27442744
int wpnew_len;
@@ -2826,11 +2826,24 @@ int mingw_rename(const char *pold, const char *pnew)
28262826
gle = GetLastError();
28272827
}
28282828

2829-
if (gle == ERROR_ACCESS_DENIED && is_inside_windows_container()) {
2830-
/* Fall back to copy to destination & remove source */
2831-
if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold))
2832-
return 0;
2833-
gle = GetLastError();
2829+
if (gle == ERROR_ACCESS_DENIED) {
2830+
if (is_inside_windows_container()) {
2831+
/* Fall back to copy to destination & remove source */
2832+
if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold))
2833+
return 0;
2834+
gle = GetLastError();
2835+
} else if ((attrsold = GetFileAttributesW(wpold)) & FILE_ATTRIBUTE_READONLY) {
2836+
/* if file is read-only, change and retry */
2837+
SetFileAttributesW(wpold, attrsold & ~FILE_ATTRIBUTE_READONLY);
2838+
if (MoveFileExW(wpold, wpnew,
2839+
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) {
2840+
SetFileAttributesW(wpnew, attrsold);
2841+
return 0;
2842+
}
2843+
gle = GetLastError();
2844+
/* revert attribute change on failure */
2845+
SetFileAttributesW(wpold, attrsold);
2846+
}
28342847
}
28352848

28362849
/* revert file attributes on failure */

0 commit comments

Comments
 (0)