diff --git a/src/checkout.c b/src/checkout.c index 0b385226b..04b2a66b2 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -259,6 +259,17 @@ static int checkout_action_no_wd( 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( checkout_data *data, git_iterator *workdir, @@ -307,11 +318,13 @@ static int checkout_action_wd_only( /* found in index */; else if (git_iterator_current_is_ignored(workdir)) { 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 { 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); diff --git a/src/stash.c b/src/stash.c index d20e29b80..86e0a627c 100644 --- a/src/stash.c +++ b/src/stash.c @@ -178,7 +178,8 @@ static int stash_update_index_from_diff( break; 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; break; diff --git a/tests/stash/save.c b/tests/stash/save.c index f06c1fb71..5165eeadf 100644 --- a/tests/stash/save.c +++ b/tests/stash/save.c @@ -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) { - 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, "how", GIT_STATUS_INDEX_MODIFIED); @@ -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); } + +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); +} diff --git a/tests/stash/stash_helpers.c b/tests/stash/stash_helpers.c index 8b7d685f8..29cb25c5f 100644 --- a/tests/stash/stash_helpers.c +++ b/tests/stash/stash_helpers.c @@ -44,13 +44,10 @@ void assert_status( unsigned int status; int error; - error = git_status_file(&status, repo, path); - - if (status_flags < 0) { - cl_assert_equal_i(status_flags, error); - return; + if (status_flags < 0) + cl_assert_equal_i(status_flags, git_status_file(&status, repo, path)); + else { + cl_git_pass(git_status_file(&status, repo, path)); + cl_assert_equal_i((unsigned int)status_flags, status); } - - cl_assert_equal_i(0, error); - cl_assert_equal_i((unsigned int)status_flags, status); }