mirror of
https://git.proxmox.com/git/libgit2
synced 2026-01-04 19:28:32 +00:00
checkout: remove blocking dir when FORCEd
This commit is contained in:
parent
3520c97057
commit
05f690122e
@ -409,6 +409,14 @@ static bool submodule_is_config_only(
|
||||
return rval;
|
||||
}
|
||||
|
||||
static bool checkout_is_empty_dir(checkout_data *data, const char *path)
|
||||
{
|
||||
git_buf_truncate(&data->path, data->workdir_len);
|
||||
if (git_buf_puts(&data->path, path) < 0)
|
||||
return false;
|
||||
return git_path_is_empty_dir(data->path.ptr);
|
||||
}
|
||||
|
||||
static int checkout_action_with_wd(
|
||||
int *action,
|
||||
checkout_data *data,
|
||||
@ -526,6 +534,7 @@ static int checkout_action_with_wd_dir(
|
||||
checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL));
|
||||
GITERR_CHECK_ERROR(
|
||||
checkout_notify(data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd));
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, NONE);
|
||||
break;
|
||||
case GIT_DELTA_ADDED:/* case 4 (and 7 for dir) */
|
||||
case GIT_DELTA_MODIFIED: /* case 20 (or 37 but not really) */
|
||||
@ -550,8 +559,6 @@ static int checkout_action_with_wd_dir(
|
||||
* dir and it will succeed if no children are left.
|
||||
*/
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
if (*action != CHECKOUT_ACTION__NONE)
|
||||
*action |= CHECKOUT_ACTION__DEFER_REMOVE;
|
||||
}
|
||||
else if (delta->new_file.mode != GIT_FILEMODE_TREE)
|
||||
/* For typechange to dir, dir is already created so no action */
|
||||
@ -564,6 +571,20 @@ static int checkout_action_with_wd_dir(
|
||||
return checkout_action_common(action, data, delta, wd);
|
||||
}
|
||||
|
||||
static int checkout_action_with_wd_dir_empty(
|
||||
int *action,
|
||||
checkout_data *data,
|
||||
const git_diff_delta *delta)
|
||||
{
|
||||
int error = checkout_action_no_wd(action, data, delta);
|
||||
|
||||
/* We can always safely remove an empty directory. */
|
||||
if (error == 0 && *action != CHECKOUT_ACTION__NONE)
|
||||
*action |= CHECKOUT_ACTION__REMOVE;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int checkout_action(
|
||||
int *action,
|
||||
checkout_data *data,
|
||||
@ -653,7 +674,9 @@ static int checkout_action(
|
||||
}
|
||||
}
|
||||
|
||||
return checkout_action_with_wd_dir(action, data, delta, workdir, wd);
|
||||
return checkout_is_empty_dir(data, wd->path) ?
|
||||
checkout_action_with_wd_dir_empty(action, data, delta) :
|
||||
checkout_action_with_wd_dir(action, data, delta, workdir, wd);
|
||||
}
|
||||
|
||||
/* case 6 - wd is after delta */
|
||||
|
||||
@ -21,7 +21,7 @@ void test_checkout_icase__initialize(void)
|
||||
cl_git_pass(git_object_lookup(&obj, repo, &id, GIT_OBJ_ANY));
|
||||
|
||||
git_checkout_init_options(&checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION);
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;
|
||||
}
|
||||
|
||||
void test_checkout_icase__cleanup(void)
|
||||
@ -79,8 +79,21 @@ static void assert_name_is(const char *expected)
|
||||
free(actual);
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwrites_files_for_files(void)
|
||||
void test_checkout_icase__refuses_to_overwrite_files_for_files(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
|
||||
|
||||
cl_git_write2file("testrepo/BRANCH_FILE.txt", "neue file\n", 10, \
|
||||
O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
|
||||
cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
|
||||
assert_name_is("testrepo/BRANCH_FILE.txt");
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwrites_files_for_files_when_forced(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
|
||||
cl_git_write2file("testrepo/NEW.txt", "neue file\n", 10, \
|
||||
O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
|
||||
@ -88,8 +101,22 @@ void test_checkout_icase__overwrites_files_for_files(void)
|
||||
assert_name_is("testrepo/new.txt");
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwrites_links_for_files(void)
|
||||
void test_checkout_icase__refuses_to_overwrite_links_for_files(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
|
||||
|
||||
cl_must_pass(p_symlink("../tmp", "testrepo/BRANCH_FILE.txt"));
|
||||
|
||||
cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
|
||||
|
||||
cl_assert(!git_path_exists("tmp"));
|
||||
assert_name_is("testrepo/BRANCH_FILE.txt");
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwrites_links_for_files_when_forced(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
|
||||
cl_must_pass(p_symlink("../tmp", "testrepo/NEW.txt"));
|
||||
|
||||
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
|
||||
@ -98,8 +125,10 @@ void test_checkout_icase__overwrites_links_for_files(void)
|
||||
assert_name_is("testrepo/new.txt");
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwites_folders_for_files(void)
|
||||
void test_checkout_icase__overwrites_empty_folders_for_files(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
|
||||
|
||||
cl_must_pass(p_mkdir("testrepo/NEW.txt", 0777));
|
||||
|
||||
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
|
||||
@ -108,8 +137,50 @@ void test_checkout_icase__overwites_folders_for_files(void)
|
||||
cl_assert(!git_path_isdir("testrepo/new.txt"));
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwrites_files_for_folders(void)
|
||||
void test_checkout_icase__refuses_to_overwrite_populated_folders_for_files(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
|
||||
|
||||
cl_must_pass(p_mkdir("testrepo/BRANCH_FILE.txt", 0777));
|
||||
cl_git_write2file("testrepo/BRANCH_FILE.txt/foobar", "neue file\n", 10, \
|
||||
O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
|
||||
cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
|
||||
|
||||
assert_name_is("testrepo/BRANCH_FILE.txt");
|
||||
cl_assert(git_path_isdir("testrepo/BRANCH_FILE.txt"));
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwrites_folders_for_files_when_forced(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
|
||||
cl_must_pass(p_mkdir("testrepo/NEW.txt", 0777));
|
||||
cl_git_write2file("testrepo/NEW.txt/foobar", "neue file\n", 10, \
|
||||
O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
|
||||
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
|
||||
|
||||
assert_name_is("testrepo/new.txt");
|
||||
cl_assert(!git_path_isdir("testrepo/new.txt"));
|
||||
}
|
||||
|
||||
void test_checkout_icase__refuses_to_overwrite_files_for_folders(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
|
||||
|
||||
cl_git_write2file("testrepo/A", "neue file\n", 10, \
|
||||
O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
|
||||
cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
|
||||
assert_name_is("testrepo/A");
|
||||
cl_assert(!git_path_isdir("testrepo/A"));
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwrites_files_for_folders_when_forced(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
|
||||
cl_git_write2file("testrepo/A", "neue file\n", 10, \
|
||||
O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
|
||||
@ -118,8 +189,22 @@ void test_checkout_icase__overwrites_files_for_folders(void)
|
||||
cl_assert(git_path_isdir("testrepo/a"));
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwrites_links_for_folders(void)
|
||||
void test_checkout_icase__refuses_to_overwrite_links_for_folders(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
|
||||
|
||||
cl_must_pass(p_symlink("..", "testrepo/A"));
|
||||
|
||||
cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
|
||||
|
||||
cl_assert(!git_path_exists("b.txt"));
|
||||
assert_name_is("testrepo/A");
|
||||
}
|
||||
|
||||
void test_checkout_icase__overwrites_links_for_folders_when_forced(void)
|
||||
{
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
|
||||
cl_must_pass(p_symlink("..", "testrepo/A"));
|
||||
|
||||
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
|
||||
@ -127,4 +212,3 @@ void test_checkout_icase__overwrites_links_for_folders(void)
|
||||
cl_assert(!git_path_exists("b.txt"));
|
||||
assert_name_is("testrepo/a");
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user