mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-03 02:09:41 +00:00
fileops: allow linking files when copying directory structures
When passed the LINK_FILES flag, the recursive copy will hardlink files instead of copying them.
This commit is contained in:
parent
c1dbfcbb4a
commit
94f742bac6
@ -740,9 +740,11 @@ static int _cp_r_callback(void *ref, git_buf *from)
|
||||
return error;
|
||||
|
||||
/* make symlink or regular file */
|
||||
if (S_ISLNK(from_st.st_mode))
|
||||
if (info->flags & GIT_CPDIR_LINK_FILES) {
|
||||
error = p_link(from->ptr, info->to.ptr);
|
||||
} else if (S_ISLNK(from_st.st_mode)) {
|
||||
error = cp_link(from->ptr, info->to.ptr, (size_t)from_st.st_size);
|
||||
else {
|
||||
} else {
|
||||
mode_t usemode = from_st.st_mode;
|
||||
|
||||
if ((info->flags & GIT_CPDIR_SIMPLE_TO_MODE) != 0)
|
||||
|
@ -173,6 +173,7 @@ extern int git_futils_cp(
|
||||
* - GIT_CPDIR_SIMPLE_TO_MODE: default tries to replicate the mode of the
|
||||
* source file to the target; with this flag, always use 0666 (or 0777 if
|
||||
* source has exec bits set) for target.
|
||||
* - GIT_CPDIR_LINK_FILES will try to use hardlinks for the files
|
||||
*/
|
||||
typedef enum {
|
||||
GIT_CPDIR_CREATE_EMPTY_DIRS = (1u << 0),
|
||||
@ -181,6 +182,7 @@ typedef enum {
|
||||
GIT_CPDIR_OVERWRITE = (1u << 3),
|
||||
GIT_CPDIR_CHMOD_DIRS = (1u << 4),
|
||||
GIT_CPDIR_SIMPLE_TO_MODE = (1u << 5),
|
||||
GIT_CPDIR_LINK_FILES = (1u << 6),
|
||||
} git_futils_cpdir_flags;
|
||||
|
||||
/**
|
||||
|
@ -45,6 +45,16 @@ void test_core_copy__file_in_dir(void)
|
||||
cl_assert(!git_path_isdir("an_dir"));
|
||||
}
|
||||
|
||||
void assert_hard_link(const char *path)
|
||||
{
|
||||
/* we assert this by checking that there's more than one link to the file */
|
||||
struct stat st;
|
||||
|
||||
cl_assert(git_path_isfile(path));
|
||||
cl_git_pass(p_stat(path, &st));
|
||||
cl_assert(st.st_nlink > 1);
|
||||
}
|
||||
|
||||
void test_core_copy__tree(void)
|
||||
{
|
||||
struct stat st;
|
||||
@ -122,5 +132,21 @@ void test_core_copy__tree(void)
|
||||
cl_git_pass(git_futils_rmdir_r("t2", NULL, GIT_RMDIR_REMOVE_FILES));
|
||||
cl_assert(!git_path_isdir("t2"));
|
||||
|
||||
#ifndef GIT_WIN32
|
||||
cl_git_pass(git_futils_cp_r("src", "t3", GIT_CPDIR_CREATE_EMPTY_DIRS | GIT_CPDIR_LINK_FILES, 0));
|
||||
cl_assert(git_path_isdir("t3"));
|
||||
|
||||
cl_assert(git_path_isdir("t3"));
|
||||
cl_assert(git_path_isdir("t3/b"));
|
||||
cl_assert(git_path_isdir("t3/c"));
|
||||
cl_assert(git_path_isdir("t3/c/d"));
|
||||
cl_assert(git_path_isdir("t3/c/e"));
|
||||
|
||||
assert_hard_link("t3/f1");
|
||||
assert_hard_link("t3/b/f2");
|
||||
assert_hard_link("t3/c/f3");
|
||||
assert_hard_link("t3/c/d/f4");
|
||||
#endif
|
||||
|
||||
cl_git_pass(git_futils_rmdir_r("src", NULL, GIT_RMDIR_REMOVE_FILES));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user