mirror of
https://github.com/git-for-windows/git.git
synced 2026-03-17 04:23:29 -05:00
mingw: implement a platform-specific strbuf_realpath()
There is a Win32 API function to resolve symbolic links, and we can use that instead of resolving them manually. Even better, this function also resolves NTFS junction points (which are somewhat similar to bind mounts). This fixes https://github.com/git-for-windows/git/issues/2481. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
@@ -1074,6 +1074,69 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path)
|
||||
{
|
||||
wchar_t wpath[MAX_PATH];
|
||||
HANDLE h;
|
||||
DWORD ret;
|
||||
int len;
|
||||
const char *last_component = NULL;
|
||||
|
||||
if (xutftowcs_path(wpath, path) < 0)
|
||||
return NULL;
|
||||
|
||||
h = CreateFileW(wpath, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
|
||||
/*
|
||||
* strbuf_realpath() allows the last path component to not exist. If
|
||||
* that is the case, now it's time to try without last component.
|
||||
*/
|
||||
if (h == INVALID_HANDLE_VALUE &&
|
||||
GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||
/* cut last component off of `wpath` */
|
||||
wchar_t *p = wpath + wcslen(wpath);
|
||||
|
||||
while (p != wpath)
|
||||
if (*(--p) == L'/' || *p == L'\\')
|
||||
break; /* found start of last component */
|
||||
|
||||
if (p != wpath && (last_component = find_last_dir_sep(path))) {
|
||||
last_component++; /* skip directory separator */
|
||||
*p = L'\0';
|
||||
h = CreateFileW(wpath, 0, FILE_SHARE_READ |
|
||||
FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
ret = GetFinalPathNameByHandleW(h, wpath, ARRAY_SIZE(wpath), 0);
|
||||
CloseHandle(h);
|
||||
if (!ret || ret >= ARRAY_SIZE(wpath))
|
||||
return NULL;
|
||||
|
||||
len = wcslen(wpath) * 3;
|
||||
strbuf_grow(resolved, len);
|
||||
len = xwcstoutf(resolved->buf, normalize_ntpath(wpath), len);
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
resolved->len = len;
|
||||
|
||||
if (last_component) {
|
||||
/* Use forward-slash, like `normalize_ntpath()` */
|
||||
strbuf_addch(resolved, '/');
|
||||
strbuf_addstr(resolved, last_component);
|
||||
}
|
||||
|
||||
return resolved->buf;
|
||||
|
||||
}
|
||||
|
||||
char *mingw_getcwd(char *pointer, int len)
|
||||
{
|
||||
wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
|
||||
|
||||
@@ -446,6 +446,8 @@ static inline void convert_slashes(char *path)
|
||||
#define PATH_SEP ';'
|
||||
char *mingw_query_user_email(void);
|
||||
#define query_user_email mingw_query_user_email
|
||||
char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path);
|
||||
#define platform_strbuf_realpath mingw_strbuf_realpath
|
||||
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
|
||||
#define PRIuMAX "I64u"
|
||||
#define PRId64 "I64d"
|
||||
|
||||
@@ -459,7 +459,7 @@ test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' '
|
||||
git add "$downcased"
|
||||
'
|
||||
|
||||
test_expect_failure MINGW 'can add files via NTFS junctions' '
|
||||
test_expect_success MINGW 'can add files via NTFS junctions' '
|
||||
test_when_finished "cmd //c rmdir junction && rm -rf target" &&
|
||||
test_create_repo target &&
|
||||
cmd //c "mklink /j junction target" &&
|
||||
|
||||
@@ -71,6 +71,13 @@ test_expect_success 'clone respects GIT_WORK_TREE' '
|
||||
|
||||
'
|
||||
|
||||
test_expect_success CASE_INSENSITIVE_FS 'core.worktree is not added due to path case' '
|
||||
|
||||
mkdir UPPERCASE &&
|
||||
git clone src "$(pwd)/uppercase" &&
|
||||
test "unset" = "$(git -C UPPERCASE config --default unset core.worktree)"
|
||||
'
|
||||
|
||||
test_expect_success 'clone from hooks' '
|
||||
|
||||
test_create_repo r0 &&
|
||||
|
||||
Reference in New Issue
Block a user