diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2018-10-19 03:14:53 -0700 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2018-10-20 14:13:34 +0100 |
commit | b433a22a979ae78c28c8b16f8c3487e2787cb73e (patch) | |
tree | b350fd34571ae50cf22d9d4ed975d5f5fc0a28c5 /src/repository.c | |
parent | 628dae8b1c87da412db2a7714fa6b0f3a4b1eea9 (diff) | |
download | libgit2-b433a22a979ae78c28c8b16f8c3487e2787cb73e.tar.gz |
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.
Diffstat (limited to 'src/repository.c')
-rw-r--r-- | src/repository.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/src/repository.c b/src/repository.c index a2f88a283..9af067933 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1411,24 +1411,56 @@ static bool is_filesystem_case_insensitive(const char *gitdir_path) static bool are_symlinks_supported(const char *wd_path) { + git_config *config = NULL; git_buf path = GIT_BUF_INIT; int fd; struct stat st; - int symlinks_supported = -1; + bool symlinks = false; + + /* + * To emulate Git for Windows, symlinks on Windows must be explicitly + * opted-in. We examine the system configuration for a core.symlinks + * set to true. If found, we then examine the filesystem to see if + * symlinks are _actually_ supported by the current user. If that is + * _not_ set, then we do not test or enable symlink support. + */ +#ifdef GIT_WIN32 + git_buf global_buf = GIT_BUF_INIT; + git_buf xdg_buf = GIT_BUF_INIT; + git_buf system_buf = GIT_BUF_INIT; + git_buf programdata_buf = GIT_BUF_INIT; + + git_config_find_global(&global_buf); + git_config_find_xdg(&xdg_buf); + git_config_find_system(&system_buf); + git_config_find_programdata(&programdata_buf); + + if (load_config(&config, NULL, + path_unless_empty(&global_buf), + path_unless_empty(&xdg_buf), + path_unless_empty(&system_buf), + path_unless_empty(&programdata_buf)) < 0) + goto done; + + if (git_config_get_bool(&symlinks, config, "core.symlinks") < 0 || !symlinks) + goto done; +#endif if ((fd = git_futils_mktmp(&path, wd_path, 0666)) < 0 || - p_close(fd) < 0 || - p_unlink(path.ptr) < 0 || - p_symlink("testing", path.ptr) < 0 || - p_lstat(path.ptr, &st) < 0) - symlinks_supported = false; - else - symlinks_supported = (S_ISLNK(st.st_mode) != 0); + p_close(fd) < 0 || + p_unlink(path.ptr) < 0 || + p_symlink("testing", path.ptr) < 0 || + p_lstat(path.ptr, &st) < 0) + goto done; + + symlinks = (S_ISLNK(st.st_mode) != 0); (void)p_unlink(path.ptr); - git_buf_dispose(&path); - return symlinks_supported; +done: + git_buf_dispose(&path); + git_config_free(config); + return symlinks; } static int create_empty_file(const char *path, mode_t mode) |