Skip to content

Handle git add <file> where <file> traverses an NTFS junction #2504

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions abspath.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
goto error_out;
}

if (platform_strbuf_realpath(resolved, path))
return resolved->buf;

strbuf_addstr(&remaining, path);
get_root_part(resolved, &remaining);

Expand Down
31 changes: 31 additions & 0 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,37 @@ 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;

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);
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;
return resolved->buf;

}

char *mingw_getcwd(char *pointer, int len)
{
wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
Expand Down
2 changes: 2 additions & 0 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,8 @@ extern int (*win32_is_mount_point)(struct strbuf *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"
Expand Down
4 changes: 4 additions & 0 deletions git-compat-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,10 @@ static inline int git_create_symlink(struct index_state *index, const char *targ
#define query_user_email() NULL
#endif

#ifndef platform_strbuf_realpath
#define platform_strbuf_realpath(resolved, path) NULL
#endif

#ifdef __TANDEM
#include <floss.h(floss_execl,floss_execlp,floss_execv,floss_execvp)>
#include <floss.h(floss_getpwuid)>
Expand Down
11 changes: 11 additions & 0 deletions t/t3700-add.sh
Original file line number Diff line number Diff line change
Expand Up @@ -421,4 +421,15 @@ test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' '
git add "$downcased"
'

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" &&
>target/via-junction &&
git -C junction add "$(pwd)/junction/via-junction" &&
echo via-junction >expect &&
git -C target diff --cached --name-only >actual &&
test_cmp expect actual
'

test_done