Commit 05f69012 by Edward Thomson Committed by Edward Thomson

checkout: remove blocking dir when FORCEd

parent 3520c970
...@@ -409,6 +409,14 @@ static bool submodule_is_config_only( ...@@ -409,6 +409,14 @@ static bool submodule_is_config_only(
return rval; 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( static int checkout_action_with_wd(
int *action, int *action,
checkout_data *data, checkout_data *data,
...@@ -526,6 +534,7 @@ static int checkout_action_with_wd_dir( ...@@ -526,6 +534,7 @@ static int checkout_action_with_wd_dir(
checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL)); checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL));
GITERR_CHECK_ERROR( GITERR_CHECK_ERROR(
checkout_notify(data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd)); checkout_notify(data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd));
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, NONE);
break; break;
case GIT_DELTA_ADDED:/* case 4 (and 7 for dir) */ case GIT_DELTA_ADDED:/* case 4 (and 7 for dir) */
case GIT_DELTA_MODIFIED: /* case 20 (or 37 but not really) */ case GIT_DELTA_MODIFIED: /* case 20 (or 37 but not really) */
...@@ -550,8 +559,6 @@ static int checkout_action_with_wd_dir( ...@@ -550,8 +559,6 @@ static int checkout_action_with_wd_dir(
* dir and it will succeed if no children are left. * dir and it will succeed if no children are left.
*/ */
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); *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) else if (delta->new_file.mode != GIT_FILEMODE_TREE)
/* For typechange to dir, dir is already created so no action */ /* For typechange to dir, dir is already created so no action */
...@@ -564,6 +571,20 @@ static int checkout_action_with_wd_dir( ...@@ -564,6 +571,20 @@ static int checkout_action_with_wd_dir(
return checkout_action_common(action, data, delta, wd); 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( static int checkout_action(
int *action, int *action,
checkout_data *data, checkout_data *data,
...@@ -653,7 +674,9 @@ static int checkout_action( ...@@ -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 */ /* case 6 - wd is after delta */
......
...@@ -21,7 +21,7 @@ void test_checkout_icase__initialize(void) ...@@ -21,7 +21,7 @@ void test_checkout_icase__initialize(void)
cl_git_pass(git_object_lookup(&obj, repo, &id, GIT_OBJ_ANY)); cl_git_pass(git_object_lookup(&obj, repo, &id, GIT_OBJ_ANY));
git_checkout_init_options(&checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION); 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) void test_checkout_icase__cleanup(void)
...@@ -79,8 +79,21 @@ static void assert_name_is(const char *expected) ...@@ -79,8 +79,21 @@ static void assert_name_is(const char *expected)
free(actual); 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, \ cl_git_write2file("testrepo/NEW.txt", "neue file\n", 10, \
O_WRONLY | O_CREAT | O_TRUNC, 0644); O_WRONLY | O_CREAT | O_TRUNC, 0644);
...@@ -88,8 +101,22 @@ void test_checkout_icase__overwrites_files_for_files(void) ...@@ -88,8 +101,22 @@ void test_checkout_icase__overwrites_files_for_files(void)
assert_name_is("testrepo/new.txt"); 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_must_pass(p_symlink("../tmp", "testrepo/NEW.txt"));
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts)); cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
...@@ -98,9 +125,39 @@ void test_checkout_icase__overwrites_links_for_files(void) ...@@ -98,9 +125,39 @@ void test_checkout_icase__overwrites_links_for_files(void)
assert_name_is("testrepo/new.txt"); 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));
assert_name_is("testrepo/new.txt");
cl_assert(!git_path_isdir("testrepo/new.txt"));
}
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_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)); cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
...@@ -108,8 +165,22 @@ void test_checkout_icase__overwites_folders_for_files(void) ...@@ -108,8 +165,22 @@ void test_checkout_icase__overwites_folders_for_files(void)
cl_assert(!git_path_isdir("testrepo/new.txt")); cl_assert(!git_path_isdir("testrepo/new.txt"));
} }
void test_checkout_icase__overwrites_files_for_folders(void) 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, \ cl_git_write2file("testrepo/A", "neue file\n", 10, \
O_WRONLY | O_CREAT | O_TRUNC, 0644); O_WRONLY | O_CREAT | O_TRUNC, 0644);
...@@ -118,8 +189,22 @@ void test_checkout_icase__overwrites_files_for_folders(void) ...@@ -118,8 +189,22 @@ void test_checkout_icase__overwrites_files_for_folders(void)
cl_assert(git_path_isdir("testrepo/a")); 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_must_pass(p_symlink("..", "testrepo/A"));
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts)); cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
...@@ -127,4 +212,3 @@ void test_checkout_icase__overwrites_links_for_folders(void) ...@@ -127,4 +212,3 @@ void test_checkout_icase__overwrites_links_for_folders(void)
cl_assert(!git_path_exists("b.txt")); cl_assert(!git_path_exists("b.txt"));
assert_name_is("testrepo/a"); assert_name_is("testrepo/a");
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment