diff options
-rw-r--r-- | src/index.c | 12 | ||||
-rw-r--r-- | tests-clar/index/addall.c | 20 |
2 files changed, 29 insertions, 3 deletions
diff --git a/src/index.c b/src/index.c index e65dc052c..d5568528b 100644 --- a/src/index.c +++ b/src/index.c @@ -2176,6 +2176,7 @@ static int index_apply_to_all( size_t i; git_pathspec_context ps; const char *match; + git_buf path = GIT_BUF_INIT; assert(index); @@ -2205,23 +2206,27 @@ static int index_apply_to_all( } } + /* index manipulation may alter entry, so don't depend on it */ + if ((error = git_buf_sets(&path, entry->path)) < 0) + break; + switch (action) { case INDEX_ACTION_NONE: break; case INDEX_ACTION_UPDATE: - error = git_index_add_bypath(index, entry->path); + error = git_index_add_bypath(index, path.ptr); if (error == GIT_ENOTFOUND) { giterr_clear(); - error = git_index_remove_bypath(index, entry->path); + error = git_index_remove_bypath(index, path.ptr); if (!error) /* back up foreach if we removed this */ i--; } break; case INDEX_ACTION_REMOVE: - if (!(error = git_index_remove_bypath(index, entry->path))) + if (!(error = git_index_remove_bypath(index, path.ptr))) i--; /* back up foreach if we removed this */ break; default: @@ -2231,6 +2236,7 @@ static int index_apply_to_all( } } + git_buf_free(&path); git_pathspec_context_free(&ps); return error; diff --git a/tests-clar/index/addall.c b/tests-clar/index/addall.c index 33873cb7a..fca6e77fa 100644 --- a/tests-clar/index/addall.c +++ b/tests-clar/index/addall.c @@ -132,6 +132,7 @@ static void commit_index_to_head( cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_index_write_tree(&tree_id, index)); + cl_git_pass(git_index_write(index)); /* not needed, but might as well */ git_index_free(index); cl_git_pass(git_tree_lookup(&tree, repo, &tree_id)); @@ -250,5 +251,24 @@ void test_index_addall__repo_lifecycle(void) cl_git_pass(git_index_update_all(index, NULL, NULL, NULL)); check_status(g_repo, 0, 1, 0, 3, 0, 0, 0); + strs[0] = "*"; + cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); + check_status(g_repo, 3, 1, 0, 0, 0, 0, 0); + + /* must be able to remove at any position while still updating other files */ + cl_must_pass(p_unlink("addall/.gitignore")); + cl_git_rewritefile("addall/file.zzz", "reconstructed file"); + cl_git_rewritefile("addall/more.zzz", "altered file reality"); + check_status(g_repo, 3, 1, 0, 1, 1, 1, 0); + + cl_git_pass(git_index_update_all(index, NULL, NULL, NULL)); + check_status(g_repo, 2, 1, 0, 1, 0, 0, 0); + /* this behavior actually matches 'git add -u' where "file.zzz" has + * been removed from the index, so when you go to update, even though + * it exists in the HEAD, it is not re-added to the index, leaving it + * as a DELETE when comparing HEAD to index and as an ADD comparing + * index to worktree + */ + git_index_free(index); } |