summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-06-26 17:46:35 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2015-06-26 17:46:35 +0200
commit354268ca488fc89346d5874b446510f0cc89c007 (patch)
tree11a9ad8574670e2436406dce14a8e281c7ece3fc
parent3c7a46978deedd012c8a024eff89b539e044f57d (diff)
parentb7f5cb8dd767063719919780d90fc3470d340ac7 (diff)
downloadlibgit2-354268ca488fc89346d5874b446510f0cc89c007.tar.gz
Merge pull request #3259 from ethomson/stash_apply_argh
Stash apply: stage new files even when not updating the index
-rw-r--r--include/git2/errors.h1
-rw-r--r--src/iterator.c88
-rw-r--r--src/iterator.h15
-rw-r--r--src/merge.c116
-rw-r--r--src/stash.c104
-rw-r--r--tests/stash/apply.c94
6 files changed, 323 insertions, 95 deletions
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 5ff0f35b5..a81aa05d9 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -47,6 +47,7 @@ typedef enum {
GIT_EPEEL = -19, /**< The requested peel operation is not possible */
GIT_EEOF = -20, /**< Unexpected EOF */
GIT_EINVALID = -21, /**< Invalid operation or input */
+ GIT_EUNCOMMITTED = -22, /**< Uncommitted changes in index prevented operation */
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
diff --git a/src/iterator.c b/src/iterator.c
index d5f7eec34..45eba3955 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -1843,3 +1843,91 @@ int git_iterator_advance_over_with_status(
return error;
}
+int git_iterator_walk(
+ git_iterator **iterators,
+ size_t cnt,
+ git_iterator_walk_cb cb,
+ void *data)
+{
+ const git_index_entry **iterator_item; /* next in each iterator */
+ const git_index_entry **cur_items; /* current path in each iter */
+ const git_index_entry *first_match;
+ int cur_item_modified;
+ size_t i, j;
+ int error = 0;
+
+ iterator_item = git__calloc(cnt, sizeof(git_index_entry *));
+ cur_items = git__calloc(cnt, sizeof(git_index_entry *));
+
+ GITERR_CHECK_ALLOC(iterator_item);
+ GITERR_CHECK_ALLOC(cur_items);
+
+ /* Set up the iterators */
+ for (i = 0; i < cnt; i++) {
+ error = git_iterator_current(&iterator_item[i], iterators[i]);
+
+ if (error < 0 && error != GIT_ITEROVER)
+ goto done;
+ }
+
+ while (true) {
+ for (i = 0; i < cnt; i++)
+ cur_items[i] = NULL;
+
+ first_match = NULL;
+ cur_item_modified = 0;
+
+ /* Find the next path(s) to consume from each iterator */
+ for (i = 0; i < cnt; i++) {
+ if (iterator_item[i] == NULL)
+ continue;
+
+ if (first_match == NULL) {
+ first_match = iterator_item[i];
+ cur_items[i] = iterator_item[i];
+ } else {
+ int path_diff = git_index_entry_cmp(iterator_item[i], first_match);
+
+ if (path_diff < 0) {
+ /* Found an index entry that sorts before the one we're
+ * looking at. Forget that we've seen the other and
+ * look at the other iterators for this path.
+ */
+ for (j = 0; j < i; j++)
+ cur_items[j] = NULL;
+
+ first_match = iterator_item[i];
+ cur_items[i] = iterator_item[i];
+ } else if (path_diff > 0) {
+ /* No entry for the current item, this is modified */
+ cur_item_modified = 1;
+ } else if (path_diff == 0) {
+ cur_items[i] = iterator_item[i];
+ }
+ }
+ }
+
+ if (first_match == NULL)
+ break;
+
+ if ((error = cb(cur_items, data)) != 0)
+ goto done;
+
+ /* Advance each iterator that participated */
+ for (i = 0; i < cnt; i++) {
+ if (cur_items[i] == NULL)
+ continue;
+
+ error = git_iterator_advance(&iterator_item[i], iterators[i]);
+
+ if (error < 0 && error != GIT_ITEROVER)
+ goto done;
+ }
+ }
+
+done:
+ if (error == GIT_ITEROVER)
+ error = 0;
+
+ return error;
+}
diff --git a/src/iterator.h b/src/iterator.h
index 57f82416a..893e5db50 100644
--- a/src/iterator.h
+++ b/src/iterator.h
@@ -294,4 +294,19 @@ extern int git_iterator_advance_over_with_status(
*/
extern int git_iterator_index(git_index **out, git_iterator *iter);
+typedef int (*git_iterator_walk_cb)(
+ const git_index_entry **entries,
+ void *data);
+
+/**
+ * Walk the given iterators in lock-step. The given callback will be
+ * called for each unique path, with the index entry in each iterator
+ * (or NULL if the given iterator does not contain that path).
+ */
+extern int git_iterator_walk(
+ git_iterator **iterators,
+ size_t cnt,
+ git_iterator_walk_cb cb,
+ void *data);
+
#endif
diff --git a/src/merge.c b/src/merge.c
index 517d317de..9d6252ea8 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -1449,6 +1449,34 @@ static int merge_diff_list_insert_unmodified(
return error;
}
+struct merge_diff_find_data {
+ git_merge_diff_list *diff_list;
+ struct merge_diff_df_data df_data;
+};
+
+static int queue_difference(const git_index_entry **entries, void *data)
+{
+ struct merge_diff_find_data *find_data = data;
+ bool item_modified = false;
+ size_t i;
+
+ if (!entries[0] || !entries[1] || !entries[2]) {
+ item_modified = true;
+ } else {
+ for (i = 1; i < 3; i++) {
+ if (index_entry_cmp(entries[0], entries[i]) != 0) {
+ item_modified = true;
+ break;
+ }
+ }
+ }
+
+ return item_modified ?
+ merge_diff_list_insert_conflict(
+ find_data->diff_list, &find_data->df_data, entries) :
+ merge_diff_list_insert_unmodified(find_data->diff_list, entries);
+}
+
int git_merge_diff_list__find_differences(
git_merge_diff_list *diff_list,
git_iterator *ancestor_iter,
@@ -1456,93 +1484,9 @@ int git_merge_diff_list__find_differences(
git_iterator *their_iter)
{
git_iterator *iterators[3] = { ancestor_iter, our_iter, their_iter };
- const git_index_entry *items[3] = {0}, *best_cur_item, *cur_items[3];
- git_vector_cmp entry_compare = git_index_entry_cmp;
- struct merge_diff_df_data df_data = {0};
- int cur_item_modified;
- size_t i, j;
- int error = 0;
-
- assert(diff_list && (our_iter || their_iter));
-
- /* Set up the iterators */
- for (i = 0; i < 3; i++) {
- error = git_iterator_current(&items[i], iterators[i]);
-
- if (error < 0 && error != GIT_ITEROVER)
- goto done;
- }
-
- while (true) {
- for (i = 0; i < 3; i++)
- cur_items[i] = NULL;
-
- best_cur_item = NULL;
- cur_item_modified = 0;
-
- /* Find the next path(s) to consume from each iterator */
- for (i = 0; i < 3; i++) {
- if (items[i] == NULL) {
- cur_item_modified = 1;
- continue;
- }
-
- if (best_cur_item == NULL) {
- best_cur_item = items[i];
- cur_items[i] = items[i];
- } else {
- int path_diff = entry_compare(items[i], best_cur_item);
-
- if (path_diff < 0) {
- /*
- * Found an item that sorts before our current item, make
- * our current item this one.
- */
- for (j = 0; j < i; j++)
- cur_items[j] = NULL;
-
- cur_item_modified = 1;
- best_cur_item = items[i];
- cur_items[i] = items[i];
- } else if (path_diff > 0) {
- /* No entry for the current item, this is modified */
- cur_item_modified = 1;
- } else if (path_diff == 0) {
- cur_items[i] = items[i];
-
- if (!cur_item_modified)
- cur_item_modified = index_entry_cmp(best_cur_item, items[i]);
- }
- }
- }
-
- if (best_cur_item == NULL)
- break;
-
- if (cur_item_modified)
- error = merge_diff_list_insert_conflict(diff_list, &df_data, cur_items);
- else
- error = merge_diff_list_insert_unmodified(diff_list, cur_items);
- if (error < 0)
- goto done;
+ struct merge_diff_find_data find_data = { diff_list };
- /* Advance each iterator that participated */
- for (i = 0; i < 3; i++) {
- if (cur_items[i] == NULL)
- continue;
-
- error = git_iterator_advance(&items[i], iterators[i]);
-
- if (error < 0 && error != GIT_ITEROVER)
- goto done;
- }
- }
-
-done:
- if (error == GIT_ITEROVER)
- error = 0;
-
- return error;
+ return git_iterator_walk(iterators, 3, queue_difference, &find_data);
}
git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo)
diff --git a/src/stash.c b/src/stash.c
index 9010c476d..59ecd3b07 100644
--- a/src/stash.c
+++ b/src/stash.c
@@ -671,6 +671,31 @@ cleanup:
return error;
}
+static int merge_indexes(
+ git_index **out,
+ git_repository *repo,
+ git_tree *ancestor_tree,
+ git_index *ours_index,
+ git_index *theirs_index)
+{
+ git_iterator *ancestor = NULL, *ours = NULL, *theirs = NULL;
+ const git_iterator_flag_t flags = GIT_ITERATOR_DONT_IGNORE_CASE;
+ int error;
+
+ if ((error = git_iterator_for_tree(&ancestor, ancestor_tree, flags, NULL, NULL)) < 0 ||
+ (error = git_iterator_for_index(&ours, ours_index, flags, NULL, NULL)) < 0 ||
+ (error = git_iterator_for_index(&theirs, theirs_index, flags, NULL, NULL)) < 0)
+ goto done;
+
+ error = git_merge__iterators(out, repo, ancestor, ours, theirs, NULL);
+
+done:
+ git_iterator_free(ancestor);
+ git_iterator_free(ours);
+ git_iterator_free(theirs);
+ return error;
+}
+
static int merge_index_and_tree(
git_index **out,
git_repository *repo,
@@ -733,6 +758,70 @@ int git_stash_apply_init_options(git_stash_apply_options *opts, unsigned int ver
} \
} while(false);
+static int ensure_clean_index(git_repository *repo, git_index *index)
+{
+ git_tree *head_tree = NULL;
+ git_diff *index_diff = NULL;
+ int error = 0;
+
+ if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
+ (error = git_diff_tree_to_index(
+ &index_diff, repo, head_tree, index, NULL)) < 0)
+ goto done;
+
+ if (git_diff_num_deltas(index_diff) > 0) {
+ giterr_set(GITERR_STASH, "%d uncommitted changes exist in the index",
+ git_diff_num_deltas(index_diff));
+ error = GIT_EUNCOMMITTED;
+ }
+
+done:
+ git_diff_free(index_diff);
+ git_tree_free(head_tree);
+ return error;
+}
+
+static int stage_new_file(const git_index_entry **entries, void *data)
+{
+ git_index *index = data;
+
+ if(entries[0] == NULL)
+ return git_index_add(index, entries[1]);
+ else
+ return git_index_add(index, entries[0]);
+}
+
+static int stage_new_files(
+ git_index **out,
+ git_repository *repo,
+ git_tree *parent_tree,
+ git_tree *tree)
+{
+ git_iterator *iterators[2] = { NULL, NULL };
+ git_index *index = NULL;
+ int error;
+
+ if ((error = git_index_new(&index)) < 0 ||
+ (error = git_iterator_for_tree(&iterators[0], parent_tree,
+ GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
+ (error = git_iterator_for_tree(&iterators[1], tree,
+ GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0)
+ goto done;
+
+ error = git_iterator_walk(iterators, 2, stage_new_file, index);
+
+done:
+ if (error < 0)
+ git_index_free(index);
+ else
+ *out = index;
+
+ git_iterator_free(iterators[0]);
+ git_iterator_free(iterators[1]);
+
+ return error;
+}
+
int git_stash_apply(
git_repository *repo,
size_t index,
@@ -746,6 +835,7 @@ int git_stash_apply(
git_tree *index_tree = NULL;
git_tree *index_parent_tree = NULL;
git_tree *untracked_tree = NULL;
+ git_index *stash_adds = NULL;
git_index *repo_index = NULL;
git_index *unstashed_index = NULL;
git_index *modified_index = NULL;
@@ -775,6 +865,9 @@ int git_stash_apply(
NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX);
+ if ((error = ensure_clean_index(repo, repo_index)) < 0)
+ goto cleanup;
+
/* Restore index if required */
if ((opts.flags & GIT_STASH_APPLY_REINSTATE_INDEX) &&
git_oid_cmp(git_tree_id(stash_parent_tree), git_tree_id(index_tree))) {
@@ -787,6 +880,16 @@ int git_stash_apply(
error = GIT_ECONFLICT;
goto cleanup;
}
+
+ /* Otherwise, stage any new files in the stash tree. (Note: their
+ * previously unstaged contents are staged, not the previously staged.)
+ */
+ } else if ((opts.flags & GIT_STASH_APPLY_REINSTATE_INDEX) == 0) {
+ if ((error = stage_new_files(
+ &stash_adds, repo, stash_parent_tree, stash_tree)) < 0 ||
+ (error = merge_indexes(
+ &unstashed_index, repo, stash_parent_tree, repo_index, stash_adds)) < 0)
+ goto cleanup;
}
NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED);
@@ -848,6 +951,7 @@ cleanup:
git_index_free(untracked_index);
git_index_free(modified_index);
git_index_free(unstashed_index);
+ git_index_free(stash_adds);
git_index_free(repo_index);
git_tree_free(untracked_tree);
git_tree_free(index_parent_tree);
diff --git a/tests/stash/apply.c b/tests/stash/apply.c
index c22a31bef..901667df3 100644
--- a/tests/stash/apply.c
+++ b/tests/stash/apply.c
@@ -10,14 +10,14 @@ void test_stash_apply__initialize(void)
{
git_oid oid;
- cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */
-
- cl_git_pass(git_repository_init(&repo, "stash", 0));
+ repo = cl_git_sandbox_init_new("stash");
cl_git_pass(git_repository_index(&repo_index, repo));
+ cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */
cl_git_mkfile("stash/what", "hello\n");
cl_git_mkfile("stash/how", "small\n");
cl_git_mkfile("stash/who", "world\n");
+ cl_git_mkfile("stash/where", "meh\n");
cl_git_pass(git_index_add_bypath(repo_index, "what"));
cl_git_pass(git_index_add_bypath(repo_index, "how"));
@@ -28,14 +28,23 @@ void test_stash_apply__initialize(void)
cl_git_rewritefile("stash/what", "goodbye\n");
cl_git_rewritefile("stash/who", "funky world\n");
cl_git_mkfile("stash/when", "tomorrow\n");
+ cl_git_mkfile("stash/why", "would anybody use stash?\n");
+ cl_git_mkfile("stash/where", "????\n");
cl_git_pass(git_index_add_bypath(repo_index, "who"));
+ cl_git_pass(git_index_add_bypath(repo_index, "why"));
+ cl_git_pass(git_index_add_bypath(repo_index, "where"));
+ git_index_write(repo_index);
+
+ cl_git_rewritefile("stash/where", "....\n");
/* Pre-stash state */
assert_status(repo, "what", GIT_STATUS_WT_MODIFIED);
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_INDEX_MODIFIED);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_STATUS_INDEX_NEW);
+ assert_status(repo, "where", GIT_STATUS_INDEX_NEW|GIT_STATUS_WT_MODIFIED);
cl_git_pass(git_stash_save(&oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED));
@@ -44,6 +53,8 @@ void test_stash_apply__initialize(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_CURRENT);
assert_status(repo, "when", GIT_ENOTFOUND);
+ assert_status(repo, "why", GIT_ENOTFOUND);
+ assert_status(repo, "where", GIT_ENOTFOUND);
}
void test_stash_apply__cleanup(void)
@@ -54,15 +65,13 @@ void test_stash_apply__cleanup(void)
git_index_free(repo_index);
repo_index = NULL;
- git_repository_free(repo);
- repo = NULL;
-
- cl_git_pass(git_futils_rmdir_r("stash", NULL, GIT_RMDIR_REMOVE_FILES));
- cl_fixture_cleanup("sorry-it-is-a-non-bare-only-party");
+ cl_git_sandbox_cleanup();
}
void test_stash_apply__with_default(void)
{
+ git_buf where = GIT_BUF_INIT;
+
cl_git_pass(git_stash_apply(repo, 0, NULL));
cl_assert_equal_i(git_index_has_conflicts(repo_index), 0);
@@ -70,10 +79,42 @@ void test_stash_apply__with_default(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_WT_MODIFIED);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_STATUS_INDEX_NEW);
+ assert_status(repo, "where", GIT_STATUS_INDEX_NEW);
+
+ cl_git_pass(git_futils_readbuffer(&where, "stash/where"));
+ cl_assert_equal_s("....\n", where.ptr);
+
+ git_buf_free(&where);
+}
+
+void test_stash_apply__with_existing_file(void)
+{
+ cl_git_mkfile("stash/where", "oops!\n");
+ cl_git_fail(git_stash_apply(repo, 0, NULL));
+}
+
+void test_stash_apply__merges_new_file(void)
+{
+ git_index_entry *ancestor, *our, *their;
+
+ cl_git_mkfile("stash/where", "committed before stash\n");
+ cl_git_pass(git_index_add_bypath(repo_index, "where"));
+ cl_repo_commit_from_index(NULL, repo, signature, 0, "Other commit");
+
+ cl_git_pass(git_stash_apply(repo, 0, NULL));
+
+ cl_assert_equal_i(1, git_index_has_conflicts(repo_index));
+ assert_status(repo, "what", GIT_STATUS_INDEX_MODIFIED);
+ cl_git_pass(git_index_conflict_get(&ancestor, &our, &their, repo_index, "where")); /* unmerged */
+ assert_status(repo, "who", GIT_STATUS_INDEX_MODIFIED);
+ assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_STATUS_INDEX_NEW);
}
void test_stash_apply__with_reinstate_index(void)
{
+ git_buf where = GIT_BUF_INIT;
git_stash_apply_options opts = GIT_STASH_APPLY_OPTIONS_INIT;
opts.flags = GIT_STASH_APPLY_REINSTATE_INDEX;
@@ -85,6 +126,13 @@ void test_stash_apply__with_reinstate_index(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_INDEX_MODIFIED);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_STATUS_INDEX_NEW);
+ assert_status(repo, "where", GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_MODIFIED);
+
+ cl_git_pass(git_futils_readbuffer(&where, "stash/where"));
+ cl_assert_equal_s("....\n", where.ptr);
+
+ git_buf_free(&where);
}
void test_stash_apply__conflict_index_with_default(void)
@@ -96,6 +144,7 @@ void test_stash_apply__conflict_index_with_default(void)
cl_git_rewritefile("stash/who", "nothing\n");
cl_git_pass(git_index_add_bypath(repo_index, "who"));
cl_git_pass(git_index_write(repo_index));
+ cl_repo_commit_from_index(NULL, repo, signature, 0, "Other commit");
cl_git_pass(git_stash_apply(repo, 0, NULL));
@@ -104,6 +153,7 @@ void test_stash_apply__conflict_index_with_default(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
cl_git_pass(git_index_conflict_get(&ancestor, &our, &their, repo_index, "who")); /* unmerged */
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_STATUS_INDEX_NEW);
}
void test_stash_apply__conflict_index_with_reinstate_index(void)
@@ -115,14 +165,16 @@ void test_stash_apply__conflict_index_with_reinstate_index(void)
cl_git_rewritefile("stash/who", "nothing\n");
cl_git_pass(git_index_add_bypath(repo_index, "who"));
cl_git_pass(git_index_write(repo_index));
+ cl_repo_commit_from_index(NULL, repo, signature, 0, "Other commit");
cl_git_fail_with(git_stash_apply(repo, 0, &opts), GIT_ECONFLICT);
cl_assert_equal_i(git_index_has_conflicts(repo_index), 0);
assert_status(repo, "what", GIT_STATUS_CURRENT);
assert_status(repo, "how", GIT_STATUS_CURRENT);
- assert_status(repo, "who", GIT_STATUS_INDEX_MODIFIED);
+ assert_status(repo, "who", GIT_STATUS_CURRENT);
assert_status(repo, "when", GIT_ENOTFOUND);
+ assert_status(repo, "why", GIT_ENOTFOUND);
}
void test_stash_apply__conflict_untracked_with_default(void)
@@ -138,6 +190,7 @@ void test_stash_apply__conflict_untracked_with_default(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_CURRENT);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_ENOTFOUND);
}
void test_stash_apply__conflict_untracked_with_reinstate_index(void)
@@ -155,6 +208,7 @@ void test_stash_apply__conflict_untracked_with_reinstate_index(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_CURRENT);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_ENOTFOUND);
}
void test_stash_apply__conflict_workdir_with_default(void)
@@ -168,6 +222,7 @@ void test_stash_apply__conflict_workdir_with_default(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_CURRENT);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_ENOTFOUND);
}
void test_stash_apply__conflict_workdir_with_reinstate_index(void)
@@ -185,6 +240,7 @@ void test_stash_apply__conflict_workdir_with_reinstate_index(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_CURRENT);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_ENOTFOUND);
}
void test_stash_apply__conflict_commit_with_default(void)
@@ -204,6 +260,7 @@ void test_stash_apply__conflict_commit_with_default(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_INDEX_MODIFIED);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_STATUS_INDEX_NEW);
}
void test_stash_apply__conflict_commit_with_reinstate_index(void)
@@ -226,6 +283,23 @@ void test_stash_apply__conflict_commit_with_reinstate_index(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_INDEX_MODIFIED);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_STATUS_INDEX_NEW);
+}
+
+void test_stash_apply__fails_with_uncommitted_changes_in_index(void)
+{
+ cl_git_rewritefile("stash/who", "nothing\n");
+ cl_git_pass(git_index_add_bypath(repo_index, "who"));
+ cl_git_pass(git_index_write(repo_index));
+
+ cl_git_fail_with(git_stash_apply(repo, 0, NULL), GIT_EUNCOMMITTED);
+
+ cl_assert_equal_i(git_index_has_conflicts(repo_index), 0);
+ assert_status(repo, "what", GIT_STATUS_CURRENT);
+ assert_status(repo, "how", GIT_STATUS_CURRENT);
+ assert_status(repo, "who", GIT_STATUS_INDEX_MODIFIED);
+ assert_status(repo, "when", GIT_ENOTFOUND);
+ assert_status(repo, "why", GIT_ENOTFOUND);
}
void test_stash_apply__pop(void)
@@ -285,6 +359,8 @@ void test_stash_apply__executes_notify_cb(void)
assert_status(repo, "how", GIT_STATUS_CURRENT);
assert_status(repo, "who", GIT_STATUS_WT_MODIFIED);
assert_status(repo, "when", GIT_STATUS_WT_NEW);
+ assert_status(repo, "why", GIT_STATUS_INDEX_NEW);
+ assert_status(repo, "where", GIT_STATUS_INDEX_NEW);
cl_assert_equal_b(true, seen_paths.what);
cl_assert_equal_b(false, seen_paths.how);