Commit 82b1c93d by Edward Thomson

stash: don't allow apply with staged changes

parent 1db6a0ab
......@@ -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 */
......
......@@ -733,6 +733,29 @@ 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;
}
int git_stash_apply(
git_repository *repo,
size_t index,
......@@ -775,6 +798,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))) {
......
......@@ -118,13 +118,14 @@ 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);
}
......@@ -238,6 +239,22 @@ void test_stash_apply__conflict_commit_with_reinstate_index(void)
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)
{
cl_git_pass(git_stash_pop(repo, 0, NULL));
......
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