mirror of
https://git.proxmox.com/git/libgit2
synced 2026-01-04 01:40:18 +00:00
Merge pull request #3498 from ethomson/windows_symlinks
Diff: Honor `core.symlinks=false` and fake symlinks
This commit is contained in:
commit
1c34b717e0
@ -259,10 +259,35 @@ static int diff_file_content_load_blob(
|
||||
return error;
|
||||
}
|
||||
|
||||
static int diff_file_content_load_workdir_symlink_fake(
|
||||
git_diff_file_content *fc, git_buf *path)
|
||||
{
|
||||
git_buf target = GIT_BUF_INIT;
|
||||
int error;
|
||||
|
||||
if ((error = git_futils_readbuffer(&target, path->ptr)) < 0)
|
||||
return error;
|
||||
|
||||
fc->map.len = git_buf_len(&target);
|
||||
fc->map.data = git_buf_detach(&target);
|
||||
fc->flags |= GIT_DIFF_FLAG__FREE_DATA;
|
||||
|
||||
git_buf_free(&target);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int diff_file_content_load_workdir_symlink(
|
||||
git_diff_file_content *fc, git_buf *path)
|
||||
{
|
||||
ssize_t alloc_len, read_len;
|
||||
int symlink_supported, error;
|
||||
|
||||
if ((error = git_repository__cvar(
|
||||
&symlink_supported, fc->repo, GIT_CVAR_SYMLINKS)) < 0)
|
||||
return -1;
|
||||
|
||||
if (!symlink_supported)
|
||||
return diff_file_content_load_workdir_symlink_fake(fc, path);
|
||||
|
||||
/* link path on disk could be UTF-16, so prepare a buffer that is
|
||||
* big enough to handle some UTF-8 data expansion
|
||||
|
||||
@ -2097,3 +2097,64 @@ void test_diff_workdir__to_index_pathlist(void)
|
||||
git_vector_free(&pathlist);
|
||||
}
|
||||
|
||||
void test_diff_workdir__symlink_changed_on_non_symlink_platform(void)
|
||||
{
|
||||
git_tree *tree;
|
||||
git_diff *diff;
|
||||
diff_expects exp = {0};
|
||||
const git_diff_delta *delta;
|
||||
const char *commit = "7fccd7";
|
||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||
git_vector pathlist = GIT_VECTOR_INIT;
|
||||
int symlinks;
|
||||
|
||||
g_repo = cl_git_sandbox_init("unsymlinked.git");
|
||||
|
||||
cl_git_pass(git_repository__cvar(&symlinks, g_repo, GIT_CVAR_SYMLINKS));
|
||||
|
||||
if (symlinks)
|
||||
cl_skip();
|
||||
|
||||
cl_git_pass(git_vector_insert(&pathlist, "include/Nu/Nu.h"));
|
||||
|
||||
opts.pathspec.strings = (char **)pathlist.contents;
|
||||
opts.pathspec.count = pathlist.length;
|
||||
|
||||
cl_must_pass(p_mkdir("symlink", 0777));
|
||||
cl_git_pass(git_repository_set_workdir(g_repo, "symlink", false));
|
||||
|
||||
cl_assert((tree = resolve_commit_oid_to_tree(g_repo, commit)) != NULL);
|
||||
|
||||
/* first, do the diff with the original contents */
|
||||
|
||||
cl_git_pass(git_futils_mkpath2file("symlink/include/Nu/Nu.h", 0755));
|
||||
cl_git_mkfile("symlink/include/Nu/Nu.h", "../../objc/Nu.h");
|
||||
|
||||
cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
|
||||
cl_assert_equal_i(0, git_diff_num_deltas(diff));
|
||||
git_diff_free(diff);
|
||||
|
||||
/* now update the contents and expect a difference, but that the file
|
||||
* mode has persisted as a symbolic link.
|
||||
*/
|
||||
|
||||
cl_git_rewritefile("symlink/include/Nu/Nu.h", "awesome content\n");
|
||||
|
||||
cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
|
||||
|
||||
cl_git_pass(git_diff_foreach(
|
||||
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
|
||||
cl_assert_equal_i(1, exp.files);
|
||||
|
||||
cl_assert_equal_i(1, git_diff_num_deltas(diff));
|
||||
delta = git_diff_get_delta(diff, 0);
|
||||
cl_assert_equal_i(GIT_FILEMODE_LINK, delta->old_file.mode);
|
||||
cl_assert_equal_i(GIT_FILEMODE_LINK, delta->new_file.mode);
|
||||
|
||||
git_diff_free(diff);
|
||||
|
||||
cl_git_pass(git_futils_rmdir_r("symlink", NULL, GIT_RMDIR_REMOVE_FILES));
|
||||
|
||||
git_tree_free(tree);
|
||||
git_vector_free(&pathlist);
|
||||
}
|
||||
|
||||
@ -328,3 +328,32 @@ void test_index_bypath__add_honors_conflict_case(void)
|
||||
cl_assert((entry = git_index_get_bypath(g_idx, "README.txt", 0)) != NULL);
|
||||
cl_assert_equal_i(GIT_FILEMODE_BLOB_EXECUTABLE, entry->mode);
|
||||
}
|
||||
|
||||
void test_index_bypath__add_honors_symlink(void)
|
||||
{
|
||||
const git_index_entry *entry;
|
||||
git_index_entry new_entry;
|
||||
int symlinks;
|
||||
|
||||
cl_git_pass(git_repository__cvar(&symlinks, g_repo, GIT_CVAR_SYMLINKS));
|
||||
|
||||
if (symlinks)
|
||||
cl_skip();
|
||||
|
||||
cl_assert((entry = git_index_get_bypath(g_idx, "README.txt", 0)) != NULL);
|
||||
|
||||
memcpy(&new_entry, entry, sizeof(git_index_entry));
|
||||
new_entry.path = "README.txt";
|
||||
new_entry.mode = GIT_FILEMODE_LINK;
|
||||
|
||||
cl_git_pass(git_index_add(g_idx, &new_entry));
|
||||
cl_git_pass(git_index_write(g_idx));
|
||||
|
||||
cl_git_rewritefile("submod2/README.txt", "Modified but still a (fake) symlink");
|
||||
|
||||
cl_git_pass(git_index_add_bypath(g_idx, "README.txt"));
|
||||
cl_git_pass(git_index_write(g_idx));
|
||||
|
||||
cl_assert((entry = git_index_get_bypath(g_idx, "README.txt", 0)) != NULL);
|
||||
cl_assert_equal_i(GIT_FILEMODE_LINK, entry->mode);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user