Skip to content

Commit ded77bb

Browse files
committed
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.
1 parent e54343a commit ded77bb

File tree

7 files changed

+31
-35
lines changed

7 files changed

+31
-35
lines changed

src/path.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,3 +1924,25 @@ extern int git_path_is_gitfile(const char *path, size_t pathlen, git_path_gitfil
19241924
return -1;
19251925
}
19261926
}
1927+
1928+
bool git_path_supports_symlinks(const char *dir)
1929+
{
1930+
git_buf path = GIT_BUF_INIT;
1931+
bool supported = false;
1932+
struct stat st;
1933+
int fd;
1934+
1935+
if ((fd = git_futils_mktmp(&path, dir, 0666)) < 0 ||
1936+
p_close(fd) < 0 ||
1937+
p_unlink(path.ptr) < 0 ||
1938+
p_symlink("testing", path.ptr) < 0 ||
1939+
p_lstat(path.ptr, &st) < 0)
1940+
goto done;
1941+
1942+
supported = (S_ISLNK(st.st_mode) != 0);
1943+
done:
1944+
if (path.size)
1945+
(void)p_unlink(path.ptr);
1946+
git_buf_dispose(&path);
1947+
return supported;
1948+
}

src/path.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,4 +647,6 @@ extern bool git_path_isvalid(
647647
*/
648648
int git_path_normalize_slashes(git_buf *out, const char *path);
649649

650+
bool git_path_supports_symlinks(const char *dir);
651+
650652
#endif

src/repository.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,9 +1419,6 @@ static bool are_symlinks_supported(const char *wd_path)
14191419
git_buf xdg_buf = GIT_BUF_INIT;
14201420
git_buf system_buf = GIT_BUF_INIT;
14211421
git_buf programdata_buf = GIT_BUF_INIT;
1422-
git_buf path = GIT_BUF_INIT;
1423-
int fd;
1424-
struct stat st;
14251422
int symlinks = 0;
14261423

14271424
/*
@@ -1448,23 +1445,14 @@ static bool are_symlinks_supported(const char *wd_path)
14481445
goto done;
14491446
#endif
14501447

1451-
if ((fd = git_futils_mktmp(&path, wd_path, 0666)) < 0 ||
1452-
p_close(fd) < 0 ||
1453-
p_unlink(path.ptr) < 0 ||
1454-
p_symlink("testing", path.ptr) < 0 ||
1455-
p_lstat(path.ptr, &st) < 0)
1448+
if (!(symlinks = git_path_supports_symlinks(wd_path)))
14561449
goto done;
14571450

1458-
symlinks = (S_ISLNK(st.st_mode) != 0);
1459-
1460-
(void)p_unlink(path.ptr);
1461-
14621451
done:
14631452
git_buf_dispose(&global_buf);
14641453
git_buf_dispose(&xdg_buf);
14651454
git_buf_dispose(&system_buf);
14661455
git_buf_dispose(&programdata_buf);
1467-
git_buf_dispose(&path);
14681456
git_config_free(config);
14691457
return symlinks != 0;
14701458
}

tests/checkout/index.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ void test_checkout_index__honor_coresymlinks_default_true(void)
181181

182182
cl_must_pass(p_mkdir("symlink", 0777));
183183

184-
if (!filesystem_supports_symlinks("symlink/test"))
184+
if (!git_path_supports_symlinks("symlink/test"))
185185
cl_skip();
186186

187187
#ifdef GIT_WIN32
@@ -214,7 +214,7 @@ void test_checkout_index__honor_coresymlinks_default_false(void)
214214
* supports symlinks. Bail entirely on POSIX platforms that
215215
* do support symlinks.
216216
*/
217-
if (filesystem_supports_symlinks("symlink/test"))
217+
if (git_path_supports_symlinks("symlink/test"))
218218
cl_skip();
219219
#endif
220220

@@ -226,7 +226,7 @@ void test_checkout_index__coresymlinks_set_to_true_fails_when_unsupported(void)
226226
{
227227
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
228228

229-
if (filesystem_supports_symlinks("testrepo/test")) {
229+
if (git_path_supports_symlinks("testrepo/test")) {
230230
cl_skip();
231231
}
232232

@@ -242,7 +242,7 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
242242
char link_data[GIT_PATH_MAX];
243243
size_t link_size = GIT_PATH_MAX;
244244

245-
if (!filesystem_supports_symlinks("testrepo/test")) {
245+
if (!git_path_supports_symlinks("testrepo/test")) {
246246
cl_skip();
247247
}
248248

tests/repo/init.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ void test_repo_init__symlinks_win32_enabled_by_global_config(void)
253253
git_config *config, *repo_config;
254254
int val;
255255

256-
if (!filesystem_supports_symlinks("link"))
256+
if (!git_path_supports_symlinks("link"))
257257
cl_skip();
258258

259259
create_tmp_global_config("tmp_global_config", "core.symlinks", "true");
@@ -296,7 +296,7 @@ void test_repo_init__symlinks_posix_detected(void)
296296
cl_skip();
297297
#else
298298
assert_config_entry_on_init(
299-
"core.symlinks", filesystem_supports_symlinks("link") ? GIT_ENOTFOUND : false);
299+
"core.symlinks", git_path_supports_symlinks("link") ? GIT_ENOTFOUND : false);
300300
#endif
301301
}
302302

tests/repo/repo_helpers.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,6 @@ void delete_head(git_repository* repo)
2121
git_buf_dispose(&head_path);
2222
}
2323

24-
int filesystem_supports_symlinks(const char *path)
25-
{
26-
struct stat st;
27-
bool support = 0;
28-
29-
if (p_symlink("target", path) == 0) {
30-
if (p_lstat(path, &st) == 0 && S_ISLNK(st.st_mode))
31-
support = 1;
32-
33-
p_unlink(path);
34-
}
35-
36-
return support;
37-
}
38-
3924
void create_tmp_global_config(const char *dirname, const char *key, const char *val)
4025
{
4126
git_buf path = GIT_BUF_INIT;

tests/repo/repo_helpers.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@
44

55
extern void make_head_unborn(git_repository* repo, const char *target);
66
extern void delete_head(git_repository* repo);
7-
extern int filesystem_supports_symlinks(const char *path);
87
extern void create_tmp_global_config(const char *path, const char *key, const char *val);

0 commit comments

Comments
 (0)