Commit 8a4e1513 by Edward Thomson

win32: make p_rename use do_with_retries

parent cc8d9a29
...@@ -749,62 +749,47 @@ int p_access(const char* path, mode_t mode) ...@@ -749,62 +749,47 @@ int p_access(const char* path, mode_t mode)
return _waccess(buf, mode & WIN32_MODE_MASK); return _waccess(buf, mode & WIN32_MODE_MASK);
} }
static int ensure_writable(wchar_t *fpath) static int ensure_writable(wchar_t *path)
{ {
DWORD attrs; DWORD attrs;
attrs = GetFileAttributesW(fpath); if ((attrs = GetFileAttributesW(path)) == INVALID_FILE_ATTRIBUTES)
if (attrs == INVALID_FILE_ATTRIBUTES) { goto on_error;
if (GetLastError() == ERROR_FILE_NOT_FOUND)
return 0;
giterr_set(GITERR_OS, "failed to get attributes");
return -1;
}
if (!(attrs & FILE_ATTRIBUTE_READONLY)) if ((attrs & FILE_ATTRIBUTE_READONLY) == 0)
return 0; return 0;
attrs &= ~FILE_ATTRIBUTE_READONLY; if (!SetFileAttributesW(path, (attrs & ~FILE_ATTRIBUTE_READONLY)))
if (!SetFileAttributesW(fpath, attrs)) { goto on_error;
giterr_set(GITERR_OS, "failed to set attributes");
return -1;
}
return 0; return 0;
on_error:
set_errno();
return -1;
}
GIT_INLINE(int) rename_once(const wchar_t *from, const wchar_t *to)
{
if (MoveFileExW(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
return 0;
if (last_error_retryable())
return GIT_RETRY;
set_errno();
return -1;
} }
int p_rename(const char *from, const char *to) int p_rename(const char *from, const char *to)
{ {
git_win32_path wfrom; git_win32_path wfrom, wto;
git_win32_path wto;
int rename_tries;
int rename_succeeded;
int error;
if (git_win32_path_from_utf8(wfrom, from) < 0 || if (git_win32_path_from_utf8(wfrom, from) < 0 ||
git_win32_path_from_utf8(wto, to) < 0) git_win32_path_from_utf8(wto, to) < 0)
return -1; return -1;
/* wait up to 50ms if file is locked by another thread or process */ do_with_retries(rename_once(wfrom, wto), ensure_writable(wto));
rename_tries = 0;
rename_succeeded = 0;
while (rename_tries < 10) {
if (ensure_writable(wto) == 0 &&
MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0) {
rename_succeeded = 1;
break;
}
error = GetLastError();
if (error == ERROR_SHARING_VIOLATION || error == ERROR_ACCESS_DENIED) {
Sleep(5);
rename_tries++;
} else
break;
}
return rename_succeeded ? 0 : -1;
} }
int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags) int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment