summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-06-29 09:58:34 +0200
committerPatrick Steinhardt <ps@pks.im>2019-07-20 19:11:20 +0200
commitded77bb1f18c6cb7a0371b3f66c92387413a161d (patch)
tree44b95bb7a1998304a57b86f9892e92e2da0a2cb6
parente54343a4024e75dfaa940e652c2c9799d33634b2 (diff)
downloadlibgit2-ded77bb1f18c6cb7a0371b3f66c92387413a161d.tar.gz
path: extract function to check whether a path supports symlinks
When initializing a repository, we need to check whether its working directory supports symlinks to correctly set the initial value of the "core.symlinks" config variable. The code to check the filesystem is reusable in other parts of our codebase, like for example in our tests to determine whether certain tests can be expected to succeed or not. Extract the code into a new function `git_path_supports_symlinks` to avoid duplicate implementations. Remove a duplicate implementation in the repo test helper code.
-rw-r--r--src/path.c22
-rw-r--r--src/path.h2
-rw-r--r--src/repository.c14
-rw-r--r--tests/checkout/index.c8
-rw-r--r--tests/repo/init.c4
-rw-r--r--tests/repo/repo_helpers.c15
-rw-r--r--tests/repo/repo_helpers.h1
7 files changed, 31 insertions, 35 deletions
diff --git a/src/path.c b/src/path.c
index df6b6233b..41232c2f6 100644
--- a/src/path.c
+++ b/src/path.c
@@ -1924,3 +1924,25 @@ extern int git_path_is_gitfile(const char *path, size_t pathlen, git_path_gitfil
return -1;
}
}
+
+bool git_path_supports_symlinks(const char *dir)
+{
+ git_buf path = GIT_BUF_INIT;
+ bool supported = false;
+ struct stat st;
+ int fd;
+
+ if ((fd = git_futils_mktmp(&path, dir, 0666)) < 0 ||
+ p_close(fd) < 0 ||
+ p_unlink(path.ptr) < 0 ||
+ p_symlink("testing", path.ptr) < 0 ||
+ p_lstat(path.ptr, &st) < 0)
+ goto done;
+
+ supported = (S_ISLNK(st.st_mode) != 0);
+done:
+ if (path.size)
+ (void)p_unlink(path.ptr);
+ git_buf_dispose(&path);
+ return supported;
+}
diff --git a/src/path.h b/src/path.h
index e29a7f6b3..624ca03aa 100644
--- a/src/path.h
+++ b/src/path.h
@@ -647,4 +647,6 @@ extern bool git_path_isvalid(
*/
int git_path_normalize_slashes(git_buf *out, const char *path);
+bool git_path_supports_symlinks(const char *dir);
+
#endif
diff --git a/src/repository.c b/src/repository.c
index 6a49899ad..f9c4ef42a 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1419,9 +1419,6 @@ static bool are_symlinks_supported(const char *wd_path)
git_buf xdg_buf = GIT_BUF_INIT;
git_buf system_buf = GIT_BUF_INIT;
git_buf programdata_buf = GIT_BUF_INIT;
- git_buf path = GIT_BUF_INIT;
- int fd;
- struct stat st;
int symlinks = 0;
/*
@@ -1448,23 +1445,14 @@ static bool are_symlinks_supported(const char *wd_path)
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)
+ if (!(symlinks = git_path_supports_symlinks(wd_path)))
goto done;
- symlinks = (S_ISLNK(st.st_mode) != 0);
-
- (void)p_unlink(path.ptr);
-
done:
git_buf_dispose(&global_buf);
git_buf_dispose(&xdg_buf);
git_buf_dispose(&system_buf);
git_buf_dispose(&programdata_buf);
- git_buf_dispose(&path);
git_config_free(config);
return symlinks != 0;
}
diff --git a/tests/checkout/index.c b/tests/checkout/index.c
index dcacdd5d3..a76c471e8 100644
--- a/tests/checkout/index.c
+++ b/tests/checkout/index.c
@@ -181,7 +181,7 @@ void test_checkout_index__honor_coresymlinks_default_true(void)
cl_must_pass(p_mkdir("symlink", 0777));
- if (!filesystem_supports_symlinks("symlink/test"))
+ if (!git_path_supports_symlinks("symlink/test"))
cl_skip();
#ifdef GIT_WIN32
@@ -214,7 +214,7 @@ void test_checkout_index__honor_coresymlinks_default_false(void)
* supports symlinks. Bail entirely on POSIX platforms that
* do support symlinks.
*/
- if (filesystem_supports_symlinks("symlink/test"))
+ if (git_path_supports_symlinks("symlink/test"))
cl_skip();
#endif
@@ -226,7 +226,7 @@ void test_checkout_index__coresymlinks_set_to_true_fails_when_unsupported(void)
{
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
- if (filesystem_supports_symlinks("testrepo/test")) {
+ if (git_path_supports_symlinks("testrepo/test")) {
cl_skip();
}
@@ -242,7 +242,7 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
char link_data[GIT_PATH_MAX];
size_t link_size = GIT_PATH_MAX;
- if (!filesystem_supports_symlinks("testrepo/test")) {
+ if (!git_path_supports_symlinks("testrepo/test")) {
cl_skip();
}
diff --git a/tests/repo/init.c b/tests/repo/init.c
index 9eee830e2..5a95229e6 100644
--- a/tests/repo/init.c
+++ b/tests/repo/init.c
@@ -253,7 +253,7 @@ void test_repo_init__symlinks_win32_enabled_by_global_config(void)
git_config *config, *repo_config;
int val;
- if (!filesystem_supports_symlinks("link"))
+ if (!git_path_supports_symlinks("link"))
cl_skip();
create_tmp_global_config("tmp_global_config", "core.symlinks", "true");
@@ -296,7 +296,7 @@ void test_repo_init__symlinks_posix_detected(void)
cl_skip();
#else
assert_config_entry_on_init(
- "core.symlinks", filesystem_supports_symlinks("link") ? GIT_ENOTFOUND : false);
+ "core.symlinks", git_path_supports_symlinks("link") ? GIT_ENOTFOUND : false);
#endif
}
diff --git a/tests/repo/repo_helpers.c b/tests/repo/repo_helpers.c
index 4256314f1..b22f3f6ba 100644
--- a/tests/repo/repo_helpers.c
+++ b/tests/repo/repo_helpers.c
@@ -21,21 +21,6 @@ void delete_head(git_repository* repo)
git_buf_dispose(&head_path);
}
-int filesystem_supports_symlinks(const char *path)
-{
- struct stat st;
- bool support = 0;
-
- if (p_symlink("target", path) == 0) {
- if (p_lstat(path, &st) == 0 && S_ISLNK(st.st_mode))
- support = 1;
-
- p_unlink(path);
- }
-
- return support;
-}
-
void create_tmp_global_config(const char *dirname, const char *key, const char *val)
{
git_buf path = GIT_BUF_INIT;
diff --git a/tests/repo/repo_helpers.h b/tests/repo/repo_helpers.h
index 2c9aeabee..a93bf36ae 100644
--- a/tests/repo/repo_helpers.h
+++ b/tests/repo/repo_helpers.h
@@ -4,5 +4,4 @@
extern void make_head_unborn(git_repository* repo, const char *target);
extern void delete_head(git_repository* repo);
-extern int filesystem_supports_symlinks(const char *path);
extern void create_tmp_global_config(const char *path, const char *key, const char *val);