Commit 24d17de2 by Russell Belfer

Make stash and checkout ignore contained repos

To emulate git, stash should not remove untracked git repositories
inside the parent repo, and checkout's REMOVE_UNTRACKED should
also skip over these items.

`git stash` actually prints a warning message for these items.
That should be possible with a checkout notify callback if you
wanted to, although it would require a bit of extra logic as things
are at the moment.
parent a32d684f
...@@ -259,6 +259,17 @@ static int checkout_action_no_wd( ...@@ -259,6 +259,17 @@ static int checkout_action_no_wd(
return checkout_action_common(action, data, delta, NULL); return checkout_action_common(action, data, delta, NULL);
} }
static bool wd_item_is_removable(git_iterator *iter, const git_index_entry *wd)
{
git_buf *full = NULL;
if (wd->mode != GIT_FILEMODE_TREE)
return true;
if (git_iterator_current_workdir_path(&full, iter) < 0)
return true;
return !full || !git_path_contains(full, DOT_GIT);
}
static int checkout_action_wd_only( static int checkout_action_wd_only(
checkout_data *data, checkout_data *data,
git_iterator *workdir, git_iterator *workdir,
...@@ -307,11 +318,13 @@ static int checkout_action_wd_only( ...@@ -307,11 +318,13 @@ static int checkout_action_wd_only(
/* found in index */; /* found in index */;
else if (git_iterator_current_is_ignored(workdir)) { else if (git_iterator_current_is_ignored(workdir)) {
notify = GIT_CHECKOUT_NOTIFY_IGNORED; notify = GIT_CHECKOUT_NOTIFY_IGNORED;
remove = ((data->strategy & GIT_CHECKOUT_REMOVE_IGNORED) != 0); remove = ((data->strategy & GIT_CHECKOUT_REMOVE_IGNORED) != 0) &&
wd_item_is_removable(workdir, wd);
} }
else { else {
notify = GIT_CHECKOUT_NOTIFY_UNTRACKED; notify = GIT_CHECKOUT_NOTIFY_UNTRACKED;
remove = ((data->strategy & GIT_CHECKOUT_REMOVE_UNTRACKED) != 0); remove = ((data->strategy & GIT_CHECKOUT_REMOVE_UNTRACKED) != 0) &&
wd_item_is_removable(workdir, wd);
} }
error = checkout_notify(data, notify, NULL, wd); error = checkout_notify(data, notify, NULL, wd);
......
...@@ -178,7 +178,8 @@ static int stash_update_index_from_diff( ...@@ -178,7 +178,8 @@ static int stash_update_index_from_diff(
break; break;
case GIT_DELTA_UNTRACKED: case GIT_DELTA_UNTRACKED:
if (data->include_untracked) if (data->include_untracked &&
delta->new_file.mode != GIT_FILEMODE_TREE)
add_path = delta->new_file.path; add_path = delta->new_file.path;
break; break;
......
...@@ -342,7 +342,7 @@ void test_stash_save__can_stage_normal_then_stage_untracked(void) ...@@ -342,7 +342,7 @@ void test_stash_save__can_stage_normal_then_stage_untracked(void)
void test_stash_save__including_untracked_without_any_untracked_file_creates_an_empty_tree(void) void test_stash_save__including_untracked_without_any_untracked_file_creates_an_empty_tree(void)
{ {
cl_git_pass(p_unlink("stash/when")); cl_must_pass(p_unlink("stash/when"));
assert_status(repo, "what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); assert_status(repo, "what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED);
assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED);
...@@ -354,3 +354,18 @@ void test_stash_save__including_untracked_without_any_untracked_file_creates_an_ ...@@ -354,3 +354,18 @@ void test_stash_save__including_untracked_without_any_untracked_file_creates_an_
assert_object_oid("stash^3^{tree}", EMPTY_TREE, GIT_OBJ_TREE); assert_object_oid("stash^3^{tree}", EMPTY_TREE, GIT_OBJ_TREE);
} }
void test_stash_save__skip_submodules(void)
{
git_repository *untracked_repo;
cl_git_pass(git_repository_init(&untracked_repo, "stash/untracked_repo", false));
cl_git_mkfile("stash/untracked_repo/content", "stuff");
git_repository_free(untracked_repo);
assert_status(repo, "untracked_repo/", GIT_STATUS_WT_NEW);
cl_git_pass(git_stash_save(
&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED));
assert_status(repo, "untracked_repo/", GIT_STATUS_WT_NEW);
}
...@@ -44,13 +44,10 @@ void assert_status( ...@@ -44,13 +44,10 @@ void assert_status(
unsigned int status; unsigned int status;
int error; int error;
error = git_status_file(&status, repo, path); if (status_flags < 0)
cl_assert_equal_i(status_flags, git_status_file(&status, repo, path));
if (status_flags < 0) { else {
cl_assert_equal_i(status_flags, error); cl_git_pass(git_status_file(&status, repo, path));
return;
}
cl_assert_equal_i(0, error);
cl_assert_equal_i((unsigned int)status_flags, status); cl_assert_equal_i((unsigned int)status_flags, status);
}
} }
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