mirror of
https://github.com/git/git.git
synced 2026-01-11 13:23:12 +09:00
mingw: support renaming symlinks
Older MSVCRT's `_wrename()` function cannot rename symlinks over existing files: it returns success without doing anything. Newer MSVCR*.dll versions probably do not share this problem: according to CRT sources, they just call `MoveFileEx()` with the `MOVEFILE_COPY_ALLOWED` flag. Avoid the `_wrename()` call, and go with directly calling `MoveFileEx()`, with proper error handling of course. Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
47112d6f96
commit
c4314a6aa8
@ -2275,7 +2275,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
|
||||
int mingw_rename(const char *pold, const char *pnew)
|
||||
{
|
||||
static int supports_file_rename_info_ex = 1;
|
||||
DWORD attrs, gle;
|
||||
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle;
|
||||
int tries = 0;
|
||||
wchar_t wpold[MAX_PATH], wpnew[MAX_PATH];
|
||||
int wpnew_len;
|
||||
@ -2286,15 +2286,6 @@ int mingw_rename(const char *pold, const char *pnew)
|
||||
if (wpnew_len < 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Try native rename() first to get errno right.
|
||||
* It is based on MoveFile(), which cannot overwrite existing files.
|
||||
*/
|
||||
if (!_wrename(wpold, wpnew))
|
||||
return 0;
|
||||
if (errno != EEXIST)
|
||||
return -1;
|
||||
|
||||
repeat:
|
||||
if (supports_file_rename_info_ex) {
|
||||
/*
|
||||
@ -2370,13 +2361,22 @@ repeat:
|
||||
* to retry.
|
||||
*/
|
||||
} else {
|
||||
if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
|
||||
if (MoveFileExW(wpold, wpnew,
|
||||
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
|
||||
return 0;
|
||||
gle = GetLastError();
|
||||
}
|
||||
|
||||
/* TODO: translate more errors */
|
||||
if (gle == ERROR_ACCESS_DENIED &&
|
||||
/* revert file attributes on failure */
|
||||
if (attrs != INVALID_FILE_ATTRIBUTES)
|
||||
SetFileAttributesW(wpnew, attrs);
|
||||
|
||||
if (!is_file_in_use_error(gle)) {
|
||||
errno = err_win_to_posix(gle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (attrs == INVALID_FILE_ATTRIBUTES &&
|
||||
(attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
|
||||
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
DWORD attrsold = GetFileAttributesW(wpold);
|
||||
@ -2388,16 +2388,10 @@ repeat:
|
||||
return -1;
|
||||
}
|
||||
if ((attrs & FILE_ATTRIBUTE_READONLY) &&
|
||||
SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
|
||||
if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
|
||||
return 0;
|
||||
gle = GetLastError();
|
||||
/* revert file attributes on failure */
|
||||
SetFileAttributesW(wpnew, attrs);
|
||||
}
|
||||
SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY))
|
||||
goto repeat;
|
||||
}
|
||||
if (gle == ERROR_ACCESS_DENIED &&
|
||||
retry_ask_yes_no(&tries, "Rename from '%s' to '%s' failed. "
|
||||
if (retry_ask_yes_no(&tries, "Rename from '%s' to '%s' failed. "
|
||||
"Should I try again?", pold, pnew))
|
||||
goto repeat;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user