Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit eabcbcc

Browse files
committed
mingw: Create directory/file symlink from information available
Windows NTFS symbolic links require specifying whether the target is a file or directory at creation time. This can partially be done by interrogating the filesystem, however when creating symbolic links that are within a repository, there can be no guarantee of the order of creation. This patch enables the code to allow interrogation of the git cache to determine whether a target will be a file or a directory. Signed-off-by: Michael Geddes <[email protected]>
1 parent 75b8a67 commit eabcbcc

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

compat/mingw.c

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2268,6 +2268,8 @@ void mingw_open_html(const char *unixpath)
22682268
}
22692269
}
22702270

2271+
#define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
2272+
22712273
int link(const char *oldpath, const char *newpath)
22722274
{
22732275
typedef BOOL (WINAPI *T)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
@@ -2305,12 +2307,13 @@ int link(const char *oldpath, const char *newpath)
23052307
return 0;
23062308
}
23072309

2308-
int symlink(const char *oldpath, const char *newpath)
2310+
int mingw_symlink(const char *oldpath, const char *newpath, enum git_target_type targettype)
23092311
{
23102312
typedef BOOL WINAPI (*symlink_fn)(const wchar_t*, const wchar_t*, DWORD);
23112313
static symlink_fn create_symbolic_link = NULL;
23122314
wchar_t woldpath[MAX_PATH], wnewpath[MAX_PATH], wbuf[MAX_PATH];
23132315
struct stat st;
2316+
int flags = 0;
23142317

23152318
if (xutftowcs(woldpath, oldpath, MAX_PATH) < 0)
23162319
return -1;
@@ -2325,6 +2328,57 @@ int symlink(const char *oldpath, const char *newpath)
23252328
return -1;
23262329
}
23272330

2331+
switch (targettype) {
2332+
case GIT_TARGET_UNKNOWN:
2333+
{
2334+
/* Determine the target symbolic link type from the
2335+
Filesystem.
2336+
*/
2337+
wchar_t wcurdir[MAX_PATH] = L"";
2338+
if (!is_absolute_pathw(woldpath)) {
2339+
/* If woldpath is relative, then stat needs to be
2340+
from the directory containing the original file.
2341+
*/
2342+
2343+
wchar_t *pos, *wlast=NULL, oldc;
2344+
int ret;
2345+
2346+
for (pos = wnewpath; *pos; ++pos)
2347+
if (is_dir_sep(*pos))
2348+
wlast = pos;
2349+
2350+
if (wlast != NULL) {
2351+
do_getcwd(wcurdir, MAX_PATH);
2352+
2353+
oldc = *wlast;
2354+
*wlast = L'\0';
2355+
2356+
ret = do_wchdir(wnewpath);
2357+
if (ret)
2358+
*wcurdir = L'\0';
2359+
2360+
*wlast = oldc;
2361+
if (ret)
2362+
return -1;
2363+
}
2364+
}
2365+
2366+
if (!do_wlstat(1, woldpath, &st, wbuf, MAX_PATH)) {
2367+
if (S_ISDIR(st.st_mode) )
2368+
flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
2369+
}
2370+
2371+
if (*wcurdir)
2372+
do_wchdir(wcurdir);
2373+
}
2374+
break;
2375+
case GIT_TARGET_ISDIR:
2376+
flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
2377+
break;
2378+
case GIT_TARGET_ISFILE:
2379+
break;
2380+
}
2381+
23282382
if (!create_symbolic_link) {
23292383
create_symbolic_link = (symlink_fn) GetProcAddress(
23302384
GetModuleHandle("kernel32.dll"), "CreateSymbolicLinkW");
@@ -2336,7 +2390,7 @@ int symlink(const char *oldpath, const char *newpath)
23362390
return -1;
23372391
}
23382392

2339-
if (!create_symbolic_link(wnewpath, woldpath, 0)) {
2393+
if (!create_symbolic_link(wnewpath, woldpath, flags)) {
23402394
errno = err_win_to_posix(GetLastError());
23412395
return -1;
23422396
}

compat/mingw.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
144144
#define SSL_set_wfd mingw_SSL_set_wfd
145145
#endif
146146

147+
#undef symlink_with_type
148+
#define symlink_with_type(a,b,c) mingw_symlink((a),(b),(c))
149+
#define symlink(a,b) mingw_symlink((a),(b),GIT_TARGET_UNKNOWN)
150+
147151
/*
148152
* implementations of missing functions
149153
*/
@@ -159,7 +163,8 @@ struct passwd *getpwuid(uid_t uid);
159163
int setitimer(int type, struct itimerval *in, struct itimerval *out);
160164
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
161165
int link(const char *oldpath, const char *newpath);
162-
int symlink(const char *oldpath, const char *newpath);
166+
167+
int mingw_symlink(const char *oldpath, const char *newpath, enum git_target_type targettype);
163168
int readlink(const char *path, char *buf, size_t bufsiz);
164169

165170
/*

0 commit comments

Comments
 (0)