mirror of
https://github.com/git-for-windows/git.git
synced 2026-03-22 04:16:27 -05:00
mingw_strbuf_realpath(): handle case of non existent last path component
git often requests `strbuf_realpath(path + "/.git")`, where "./git" does not yet exist on disk. This causes the following to happen: 1. `mingw_strbuf_realpath()` fails 2. Non-mingw `strbuf_realpath()` does the work 3. Result of `strbuf_realpath()` is slightly different, for example it will not normalize the case of disk/folder names 4. `needs_work_tree_config()` becomes confused by these differences 5. clone adds `core.worktree` setting This in turn causes various problems, for example: 1. Repository folder can no longer be renamed/moved without breaking it 2. Using the repository on WSL (Windows Subsystem for Linux) doesn't work, because it has windows-style path saved This fixes https://github.com/git-for-windows/git/issues/2569 Co-Authored-By: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Alexandr Miloslavskiy <alexandr.miloslavskiy@syntevo.com>
This commit is contained in:
committed by
Derrick Stolee
parent
7921a796bb
commit
fb7a1012e7
@@ -1293,6 +1293,7 @@ char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path)
|
||||
HANDLE h;
|
||||
DWORD ret;
|
||||
int len;
|
||||
const char *last_component = NULL;
|
||||
|
||||
if (xutftowcs_path(wpath, path) < 0)
|
||||
return NULL;
|
||||
@@ -1300,6 +1301,30 @@ char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path)
|
||||
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;
|
||||
|
||||
@@ -1314,6 +1339,13 @@ char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path)
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
@@ -68,6 +68,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