All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
	phiggins@google.com, snoksrud@gmail.com,
	"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH] apply: fix adding new files on i-t-a entries
Date: Tue, 23 Jun 2015 19:34:15 +0700	[thread overview]
Message-ID: <1435062855-26274-1-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <CACfKtTAvH7FH2AkC5hUNFEQ620gF401SNYaULLy62iE8S55-7A@mail.gmail.com>

Since d95d728 (diff-lib.c: adjust position of i-t-a entries in diff -
2015-03-16), a normal "git diff" on i-t-a entries would produce a diff
that _adds_ those files, not just adding content to existing and empty
files like before.

This is correct. Unfortunately, applying such a patch on the same
repository that has the same i-t-a entries will fail with message
"already exists in index" because git-apply checks, sees those i-t-a
entries and aborts. git-apply does not realize those are for
bookkeeping only, they do not really exist in the index.

This patch tightens the "exists in index" check, ignoring i-t-a
entries. For fixing the above problem, only the change in
check_to_create() is needed. For other changes,

 - load_current(), reporting "not exists in index" is better than "does
   not match index"

 - check_preimage(), similar to load_current(), but it may also use
   ce_mode from i-t-a entry which is always zero

 - get_current_sha1(), or actually build_fake_ancestor(), we should not
   add i-t-a entries to the temporary index, at least not without also
   adding i-t-a flag back

Since "git add -p" and "git am" use "git apply" underneath, they are
broken too before this patch and fixed now.

Reported-by: Patrick Higgins <phiggins@google.com>
Reported-by: Bjørnar Snoksrud <snoksrud@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 I think I'm opening a can of worms with d95d728. There's nothing
 wrong with that patch per se, but with this issue popping up, I need
 to go over all {cache,index}_name_pos call sites and see what would be
 the sensible behavior when i-t-a entries are involved.
 
 So far blame, rm and checkout-entry and "checkout <paths>" are on my
 to-think-or-fix list. But this patch can get in early to fix a real
 regression instead of waiting for one big series. A lot more
 discussions will be had before that series gets in good shape.

 builtin/apply.c       |  8 ++++----
 cache.h               |  2 ++
 read-cache.c          | 12 ++++++++++++
 t/t2203-add-intent.sh | 10 ++++++++++
 4 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 146be97..4f813ac 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3344,7 +3344,7 @@ static int load_current(struct image *image, struct patch *patch)
 	if (!patch->is_new)
 		die("BUG: patch to %s is not a creation", patch->old_name);
 
-	pos = cache_name_pos(name, strlen(name));
+	pos = exists_in_cache(name, strlen(name));
 	if (pos < 0)
 		return error(_("%s: does not exist in index"), name);
 	ce = active_cache[pos];
@@ -3497,7 +3497,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
 	}
 
 	if (check_index && !previous) {
-		int pos = cache_name_pos(old_name, strlen(old_name));
+		int pos = exists_in_cache(old_name, strlen(old_name));
 		if (pos < 0) {
 			if (patch->is_new < 0)
 				goto is_new;
@@ -3551,7 +3551,7 @@ static int check_to_create(const char *new_name, int ok_if_exists)
 	struct stat nst;
 
 	if (check_index &&
-	    cache_name_pos(new_name, strlen(new_name)) >= 0 &&
+	    exists_in_cache(new_name, strlen(new_name)) >= 0 &&
 	    !ok_if_exists)
 		return EXISTS_IN_INDEX;
 	if (cached)
@@ -3824,7 +3824,7 @@ static int get_current_sha1(const char *path, unsigned char *sha1)
 
 	if (read_cache() < 0)
 		return -1;
-	pos = cache_name_pos(path, strlen(path));
+	pos = exists_in_cache(path, strlen(path));
 	if (pos < 0)
 		return -1;
 	hashcpy(sha1, active_cache[pos]->sha1);
diff --git a/cache.h b/cache.h
index 571c98f..6a44cb6 100644
--- a/cache.h
+++ b/cache.h
@@ -341,6 +341,7 @@ extern void free_name_hash(struct index_state *istate);
 #define discard_cache() discard_index(&the_index)
 #define unmerged_cache() unmerged_index(&the_index)
 #define cache_name_pos(name, namelen) index_name_pos(&the_index,(name),(namelen))
+#define exists_in_cache(name, namelen) exists_in_index(&the_index,(name),(namelen))
 #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option))
 #define rename_cache_entry_at(pos, new_name) rename_index_entry_at(&the_index, (pos), (new_name))
 #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))
@@ -512,6 +513,7 @@ extern int verify_path(const char *path);
 extern struct cache_entry *index_dir_exists(struct index_state *istate, const char *name, int namelen);
 extern struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int igncase);
 extern int index_name_pos(const struct index_state *, const char *name, int namelen);
+extern int exists_in_index(const struct index_state *, const char *name, int namelen);
 #define ADD_CACHE_OK_TO_ADD 1		/* Ok to add */
 #define ADD_CACHE_OK_TO_REPLACE 2	/* Ok to replace file/directory */
 #define ADD_CACHE_SKIP_DFCHECK 4	/* Ok to skip DF conflict checks */
diff --git a/read-cache.c b/read-cache.c
index 5dee4e2..d3b50cb 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -506,6 +506,18 @@ int index_name_pos(const struct index_state *istate, const char *name, int namel
 	return index_name_stage_pos(istate, name, namelen, 0);
 }
 
+/* This is the same as index_name_pos, except that i-t-a entries are invisible */
+int exists_in_index(const struct index_state *istate, const char *name, int namelen)
+{
+	int pos = index_name_stage_pos(istate, name, namelen, 0);
+
+	if (pos < 0)
+		return pos;
+	if (istate->cache[pos]->ce_flags & CE_INTENT_TO_ADD)
+		return -pos-1;
+	return pos;
+}
+
 /* Remove entry, return true if there are more entries to go.. */
 int remove_index_entry_at(struct index_state *istate, int pos)
 {
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index 7c641bf..a10a96a 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -97,5 +97,15 @@ test_expect_success 'cache-tree invalidates i-t-a paths' '
 	test_cmp expect actual
 '
 
+test_expect_success 'apply on i-t-a entries' '
+	git init apply &&
+	(
+		cd apply &&
+		echo content >file &&
+		git add -N file &&
+		git diff | git apply --cached
+	)
+'
+
 test_done
 
-- 
2.3.0.rc1.137.g477eb31

  parent reply	other threads:[~2015-06-23 12:33 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-22 14:29 apply --cached --whitespace=fix now failing on items added with "add -N" Patrick Higgins
2015-06-22 14:45 ` Duy Nguyen
2015-06-22 17:06   ` Junio C Hamano
2015-06-23 12:34 ` Nguyễn Thái Ngọc Duy [this message]
2015-06-23 16:50   ` [PATCH] apply: fix adding new files on i-t-a entries Junio C Hamano
2015-06-23 17:37     ` Junio C Hamano
2015-06-24  4:48     ` Junio C Hamano
2015-06-24 10:11     ` Duy Nguyen
2015-06-24 17:05       ` Junio C Hamano
2015-06-25 12:26         ` Duy Nguyen
2015-06-25 13:07           ` Junio C Hamano
2015-08-22  1:08             ` [PATCH 0/8] Resurrect "diff-lib.c: adjust position of i-t-a entries in diff" Nguyễn Thái Ngọc Duy
2015-08-22  1:08               ` [PATCH 1/8] blame: remove obsolete comment Nguyễn Thái Ngọc Duy
2015-08-22  1:08               ` [PATCH 2/8] Add and use convenient macro ce_intent_to_add() Nguyễn Thái Ngọc Duy
2015-08-22  1:08               ` [PATCH 3/8] apply: fix adding new files on i-t-a entries Nguyễn Thái Ngọc Duy
2015-08-25 17:01                 ` Junio C Hamano
2015-08-22  1:08               ` [PATCH 4/8] apply: make sure check_preimage() does not leave empty file on error Nguyễn Thái Ngọc Duy
2015-08-25 17:16                 ` Junio C Hamano
2015-08-22  1:08               ` [PATCH 5/8] checkout(-index): do not checkout i-t-a entries Nguyễn Thái Ngọc Duy
2015-08-25 17:36                 ` Junio C Hamano
2015-11-29 15:31                   ` Duy Nguyen
2015-11-30 19:17                     ` Junio C Hamano
2015-08-22  1:08               ` [PATCH 6/8] grep: make it clear i-t-a entries are ignored Nguyễn Thái Ngọc Duy
2015-08-22  1:11                 ` [PATCH 7/8] diff.h: extend "flags" field to 64 bits because we're out of bits Nguyễn Thái Ngọc Duy
2015-08-25 17:39                   ` Junio C Hamano
2015-08-31 10:22                     ` Duy Nguyen
2015-08-25 17:37                 ` [PATCH 6/8] grep: make it clear i-t-a entries are ignored Junio C Hamano
2015-08-25 17:37                 ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1435062855-26274-1-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=phiggins@google.com \
    --cc=snoksrud@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.