From 7cfde3fa0f175d6c184d7876576c236b367d97bb Mon Sep 17 00:00:00 2001 From: "Raymond E. Pasco" Date: Thu, 6 Aug 2020 02:01:17 -0400 Subject: apply: allow "new file" patches on i-t-a entries diff-files recently changed to treat changes to paths marked "intent to add" in the index as new file diffs rather than diffs from the empty blob. However, apply refuses to apply new file diffs on top of existing index entries, except in the case of renames. This causes "git add -p", which uses apply, to fail when attempting to stage hunks from a file when intent to add has been recorded. This changes the logic in check_to_create() which checks if an entry already exists in an index in two ways: first, we only search for an index entry at all if ok_if_exists is false; second, we check for the CE_INTENT_TO_ADD flag on any index entries we find and allow the apply to proceed if it is set. Helped-by: Junio C Hamano Signed-off-by: Raymond E. Pasco Signed-off-by: Junio C Hamano --- apply.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'apply.c') diff --git a/apply.c b/apply.c index 8bff604dbe..4cba4ce71a 100644 --- a/apply.c +++ b/apply.c @@ -3747,10 +3747,13 @@ static int check_to_create(struct apply_state *state, { struct stat nst; - if (state->check_index && - index_name_pos(state->repo->index, new_name, strlen(new_name)) >= 0 && - !ok_if_exists) - return EXISTS_IN_INDEX; + if (state->check_index && !ok_if_exists) { + int pos = index_name_pos(state->repo->index, new_name, strlen(new_name)); + if (pos >= 0 && + !(state->repo->index->cache[pos]->ce_flags & CE_INTENT_TO_ADD)) + return EXISTS_IN_INDEX; + } + if (state->cached) return 0; -- cgit v1.2.3 From e3cc41b4f939a64c74b6d4a2d59f6efe006c4e4b Mon Sep 17 00:00:00 2001 From: "Raymond E. Pasco" Date: Sat, 8 Aug 2020 03:49:58 -0400 Subject: apply: make i-t-a entries never match worktree By definition, an intent-to-add index entry can never match the worktree, because worktrees have no concept of intent-to-add entries. Therefore, "apply --index" should always fail on intent-to-add paths. Because check_preimage() calls verify_index_match(), it already fails for patches other than creation patches, which check_preimage() ignores. This patch adds a check to check_preimage()'s rough equivalent for creation patches, check_to_create(). Helped-by: Junio C Hamano Signed-off-by: Raymond E. Pasco Signed-off-by: Junio C Hamano --- apply.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'apply.c') diff --git a/apply.c b/apply.c index 4cba4ce71a..c5ecb64102 100644 --- a/apply.c +++ b/apply.c @@ -3740,6 +3740,7 @@ static int check_preimage(struct apply_state *state, #define EXISTS_IN_INDEX 1 #define EXISTS_IN_WORKTREE 2 +#define EXISTS_IN_INDEX_AS_ITA 3 static int check_to_create(struct apply_state *state, const char *new_name, @@ -3747,11 +3748,21 @@ static int check_to_create(struct apply_state *state, { struct stat nst; - if (state->check_index && !ok_if_exists) { - int pos = index_name_pos(state->repo->index, new_name, strlen(new_name)); - if (pos >= 0 && - !(state->repo->index->cache[pos]->ce_flags & CE_INTENT_TO_ADD)) - return EXISTS_IN_INDEX; + if (state->check_index && (!ok_if_exists || !state->cached)) { + int pos; + + pos = index_name_pos(state->repo->index, new_name, strlen(new_name)); + if (pos >= 0) { + struct cache_entry *ce = state->repo->index->cache[pos]; + + /* allow ITA, as they do not yet exist in the index */ + if (!ok_if_exists && !(ce->ce_flags & CE_INTENT_TO_ADD)) + return EXISTS_IN_INDEX; + + /* ITA entries can never match working tree files */ + if (!state->cached && (ce->ce_flags & CE_INTENT_TO_ADD)) + return EXISTS_IN_INDEX_AS_ITA; + } } if (state->cached) @@ -3938,6 +3949,9 @@ static int check_patch(struct apply_state *state, struct patch *patch) case EXISTS_IN_INDEX: return error(_("%s: already exists in index"), new_name); break; + case EXISTS_IN_INDEX_AS_ITA: + return error(_("%s: does not match index"), new_name); + break; case EXISTS_IN_WORKTREE: return error(_("%s: already exists in working directory"), new_name); -- cgit v1.2.3