Skip to content

Commit 798d618

Browse files
dschoGit for Windows Build Agent
authored and
Git for Windows Build Agent
committed
Merge pull request #2504 from dscho/access-repo-via-junction
Handle `git add <file>` where <file> traverses an NTFS junction
2 parents 2d939fa + 4c75c86 commit 798d618

File tree

5 files changed

+51
-0
lines changed

5 files changed

+51
-0
lines changed

abspath.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
9595
goto error_out;
9696
}
9797

98+
if (platform_strbuf_realpath(resolved, path))
99+
return resolved->buf;
100+
98101
strbuf_addstr(&remaining, path);
99102
get_root_part(resolved, &remaining);
100103

compat/mingw.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,37 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
12561256
return NULL;
12571257
}
12581258

1259+
char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path)
1260+
{
1261+
wchar_t wpath[MAX_PATH];
1262+
HANDLE h;
1263+
DWORD ret;
1264+
int len;
1265+
1266+
if (xutftowcs_path(wpath, path) < 0)
1267+
return NULL;
1268+
1269+
h = CreateFileW(wpath, 0,
1270+
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
1271+
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1272+
if (h == INVALID_HANDLE_VALUE)
1273+
return NULL;
1274+
1275+
ret = GetFinalPathNameByHandleW(h, wpath, ARRAY_SIZE(wpath), 0);
1276+
CloseHandle(h);
1277+
if (!ret || ret >= ARRAY_SIZE(wpath))
1278+
return NULL;
1279+
1280+
len = wcslen(wpath) * 3;
1281+
strbuf_grow(resolved, len);
1282+
len = xwcstoutf(resolved->buf, normalize_ntpath(wpath), len);
1283+
if (len < 0)
1284+
return NULL;
1285+
resolved->len = len;
1286+
return resolved->buf;
1287+
1288+
}
1289+
12591290
char *mingw_getcwd(char *pointer, int len)
12601291
{
12611292
wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];

compat/mingw.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ extern int (*win32_is_mount_point)(struct strbuf *path);
471471
#define PATH_SEP ';'
472472
char *mingw_query_user_email(void);
473473
#define query_user_email mingw_query_user_email
474+
char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path);
475+
#define platform_strbuf_realpath mingw_strbuf_realpath
474476
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
475477
#define PRIuMAX "I64u"
476478
#define PRId64 "I64d"

git-compat-util.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,10 @@ static inline int git_create_symlink(struct index_state *index, const char *targ
408408
#define query_user_email() NULL
409409
#endif
410410

411+
#ifndef platform_strbuf_realpath
412+
#define platform_strbuf_realpath(resolved, path) NULL
413+
#endif
414+
411415
#ifdef __TANDEM
412416
#include <floss.h(floss_execl,floss_execlp,floss_execv,floss_execvp)>
413417
#include <floss.h(floss_getpwuid)>

t/t3700-add.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,4 +421,15 @@ test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' '
421421
git add "$downcased"
422422
'
423423

424+
test_expect_success MINGW 'can add files via NTFS junctions' '
425+
test_when_finished "cmd //c rmdir junction && rm -rf target" &&
426+
test_create_repo target &&
427+
cmd //c "mklink /j junction target" &&
428+
>target/via-junction &&
429+
git -C junction add "$(pwd)/junction/via-junction" &&
430+
echo via-junction >expect &&
431+
git -C target diff --cached --name-only >actual &&
432+
test_cmp expect actual
433+
'
434+
424435
test_done

0 commit comments

Comments
 (0)