summaryrefslogtreecommitdiff
path: root/src/repository.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-10-19 03:14:53 -0700
committerEdward Thomson <ethomson@edwardthomson.com>2018-10-20 14:13:34 +0100
commitb433a22a979ae78c28c8b16f8c3487e2787cb73e (patch)
treeb350fd34571ae50cf22d9d4ed975d5f5fc0a28c5 /src/repository.c
parent628dae8b1c87da412db2a7714fa6b0f3a4b1eea9 (diff)
downloadlibgit2-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.c52
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)