Skip to content

Commit b433a22

Browse files
committed
win32: emulate Git for Windows in symlink support
Emulate the Git for Windows `core.symlinks` support. Since symbolic links are generally enabled for Administrator (and _may_ be enabled due to enabling Developer mode) but symbolic links are still sufficiently uncommon on Windows that Git users are expected to explicitly opt-in to symbolic links by enabling `core.symlinks=true` in a global (or xdg or system) configuration. When `core.symlinks=true` is set globally _and_ symbolic links support is detected then new repositories created will not have a `core.symlinks` set. If `core.symlinks` is _not_ set then no detection will be performed, and `core.symlinks=false` will be set in the repository configuration.
1 parent 628dae8 commit b433a22

File tree

1 file changed

+42
-10
lines changed

1 file changed

+42
-10
lines changed

src/repository.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,24 +1411,56 @@ static bool is_filesystem_case_insensitive(const char *gitdir_path)
14111411

14121412
static bool are_symlinks_supported(const char *wd_path)
14131413
{
1414+
git_config *config = NULL;
14141415
git_buf path = GIT_BUF_INIT;
14151416
int fd;
14161417
struct stat st;
1417-
int symlinks_supported = -1;
1418+
bool symlinks = false;
1419+
1420+
/*
1421+
* To emulate Git for Windows, symlinks on Windows must be explicitly
1422+
* opted-in. We examine the system configuration for a core.symlinks
1423+
* set to true. If found, we then examine the filesystem to see if
1424+
* symlinks are _actually_ supported by the current user. If that is
1425+
* _not_ set, then we do not test or enable symlink support.
1426+
*/
1427+
#ifdef GIT_WIN32
1428+
git_buf global_buf = GIT_BUF_INIT;
1429+
git_buf xdg_buf = GIT_BUF_INIT;
1430+
git_buf system_buf = GIT_BUF_INIT;
1431+
git_buf programdata_buf = GIT_BUF_INIT;
1432+
1433+
git_config_find_global(&global_buf);
1434+
git_config_find_xdg(&xdg_buf);
1435+
git_config_find_system(&system_buf);
1436+
git_config_find_programdata(&programdata_buf);
1437+
1438+
if (load_config(&config, NULL,
1439+
path_unless_empty(&global_buf),
1440+
path_unless_empty(&xdg_buf),
1441+
path_unless_empty(&system_buf),
1442+
path_unless_empty(&programdata_buf)) < 0)
1443+
goto done;
1444+
1445+
if (git_config_get_bool(&symlinks, config, "core.symlinks") < 0 || !symlinks)
1446+
goto done;
1447+
#endif
14181448

14191449
if ((fd = git_futils_mktmp(&path, wd_path, 0666)) < 0 ||
1420-
p_close(fd) < 0 ||
1421-
p_unlink(path.ptr) < 0 ||
1422-
p_symlink("testing", path.ptr) < 0 ||
1423-
p_lstat(path.ptr, &st) < 0)
1424-
symlinks_supported = false;
1425-
else
1426-
symlinks_supported = (S_ISLNK(st.st_mode) != 0);
1450+
p_close(fd) < 0 ||
1451+
p_unlink(path.ptr) < 0 ||
1452+
p_symlink("testing", path.ptr) < 0 ||
1453+
p_lstat(path.ptr, &st) < 0)
1454+
goto done;
1455+
1456+
symlinks = (S_ISLNK(st.st_mode) != 0);
14271457

14281458
(void)p_unlink(path.ptr);
1429-
git_buf_dispose(&path);
14301459

1431-
return symlinks_supported;
1460+
done:
1461+
git_buf_dispose(&path);
1462+
git_config_free(config);
1463+
return symlinks;
14321464
}
14331465

14341466
static int create_empty_file(const char *path, mode_t mode)

0 commit comments

Comments
 (0)