diff --git a/src/path.c b/src/path.c index cb11acee3..72cb289e0 100644 --- a/src/path.c +++ b/src/path.c @@ -526,6 +526,17 @@ bool git_path_isfile(const char *path) return S_ISREG(st.st_mode) != 0; } +bool git_path_islink(const char *path) +{ + struct stat st; + + assert(path); + if (p_lstat(path, &st) < 0) + return false; + + return S_ISLNK(st.st_mode) != 0; +} + #ifdef GIT_WIN32 bool git_path_is_empty_dir(const char *path) diff --git a/src/path.h b/src/path.h index 971603ea7..c76e90343 100644 --- a/src/path.h +++ b/src/path.h @@ -168,6 +168,12 @@ extern bool git_path_isdir(const char *path); */ extern bool git_path_isfile(const char *path); +/** + * Check if the given path points to a symbolic link. + * @return true or false + */ +extern bool git_path_islink(const char *path); + /** * Check if the given path is a directory, and is empty. */ diff --git a/tests/core/mkdir.c b/tests/core/mkdir.c index 11fecb118..8d487e594 100644 --- a/tests/core/mkdir.c +++ b/tests/core/mkdir.c @@ -222,6 +222,40 @@ void test_core_mkdir__chmods(void) check_mode(0777, st.st_mode); } +void test_core_mkdir__keeps_parent_symlinks(void) +{ +#ifndef GIT_WIN32 + git_buf path = GIT_BUF_INIT; + + cl_set_cleanup(cleanup_basic_dirs, NULL); + + /* make a directory */ + cl_assert(!git_path_isdir("d0")); + cl_git_pass(git_futils_mkdir("d0", 0755, 0)); + cl_assert(git_path_isdir("d0")); + + cl_must_pass(symlink("d0", "d1")); + cl_assert(git_path_islink("d1")); + + cl_git_pass(git_futils_mkdir("d1/foo/bar", 0755, GIT_MKDIR_PATH|GIT_MKDIR_REMOVE_SYMLINKS)); + cl_assert(git_path_islink("d1")); + cl_assert(git_path_isdir("d1/foo/bar")); + cl_assert(git_path_isdir("d0/foo/bar")); + + cl_must_pass(symlink("d0", "d2")); + cl_assert(git_path_islink("d2")); + + git_buf_joinpath(&path, clar_sandbox_path(), "d2/other/dir"); + + cl_git_pass(git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_PATH|GIT_MKDIR_REMOVE_SYMLINKS)); + cl_assert(git_path_islink("d2")); + cl_assert(git_path_isdir("d2/other/dir")); + cl_assert(git_path_isdir("d0/other/dir")); + + git_buf_free(&path); +#endif +} + void test_core_mkdir__mkdir_path_inside_unwriteable_parent(void) { struct stat st;