diff-lib.c: adjust position of i-t-a entries in diff

Entries added by "git add -N" are reminder for the user so that they don't forget to add them before committing. These entries appear in the index even though they are not real. Their presence in the index leads to a confusing "git status" like this: On branch master Changes to be committed: new file: foo Changes not staged for commit: modified: foo If you do a "git commit", "foo" will not be included even though "status" reports it as "to be committed". This patch changes the output to become On branch master Changes not staged for commit: new file: foo no changes added to commit The two hunks in diff-lib.c adjust "diff-index" and "diff-files" so that i-t-a entries appear as new files in diff-files and nothing in diff-index. Due to this change, diff-files may start to report "new files" for the first time. "add -u" needs to be told about this or it will die in denial, screaming "new files can't exist! Reality is wrong." Luckily, it's the only one among run_diff_files() callers that needs fixing. Now in the new world order, a hierarchy in the index that contain i-t-a paths is written out as a tree object as if these i-t-a entries do not exist, and comparing the index with such a tree object that would result from writing out the hierarchy will result in no difference. Update a test in t2203 that expected the i-t-a entries to appear as "added to the index" in the comparison to instead expect no output. An earlier change eec3e7e4 (cache-tree: invalidate i-t-a paths after generating trees, 2012-12-16) becomes an unnecessary pessimization in the new world order---a cache-tree in the index that corresponds to a hierarchy with i-t-a paths can now be marked as valid and record the object name of the tree that results from writing a tree object out of that hierarchy, as it will compare equal to that tree. Reverting the commit is left for the future, though, as it is purely a performance issue and no longer affects correctness. Helped-by: Michael J Gruber <git@drmicha.warpmail.net> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Mar 16, 2015 at 20:56 UTC d95d728aba06a34394d15466045cbdabdada58a2
4 files changed +38 -8
builtin/add.c
+1
@@ -63,6 +63,7 @@ static void update_callback(struct diff_queue_struct *q,
63 switch (fix_unmerged_status(p, data)) {
64 default:
65 die(_("unexpected diff status %c"), p->status);
66 + case DIFF_STATUS_ADDED:
67 case DIFF_STATUS_MODIFIED:
68 case DIFF_STATUS_TYPE_CHANGED:
69 if (add_file_to_index(&the_index, path, data->flags)) {
diff-lib.c
+12
@@ -212,6 +212,11 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
212 ce->sha1, !is_null_sha1(ce->sha1),
213 ce->name, 0);
214 continue;
215 + } else if (ce->ce_flags & CE_INTENT_TO_ADD) {
216 + diff_addremove(&revs->diffopt, '+', ce->ce_mode,
217 + EMPTY_BLOB_SHA1_BIN, 0,
218 + ce->name, 0);
219 + continue;
220 }
221
222 changed = match_stat_with_submodule(&revs->diffopt, ce, &st,
@@ -376,6 +381,13 @@ static void do_oneway_diff(struct unpack_trees_options *o,
381 struct rev_info *revs = o->unpack_data;
382 int match_missing, cached;
383
384 + /* i-t-a entries do not actually exist in the index */
385 + if (idx && (idx->ce_flags & CE_INTENT_TO_ADD)) {
386 + idx = NULL;
387 + if (!tree)
388 + return; /* nothing to diff.. */
389 + }
390 +
391 /* if the entry is not checked out, don't examine work tree */
392 cached = o->index_only ||
393 (idx && ((idx->ce_flags & CE_VALID) || ce_skip_worktree(idx)));
t/t2203-add-intent.sh
+19 -4
@@ -5,10 +5,24 @@ test_description='Intent to add'
5 . ./test-lib.sh
6
7 test_expect_success 'intent to add' '
8 + test_commit 1 &&
9 + git rm 1.t &&
10 + echo hello >1.t &&
11 echo hello >file &&
12 echo hello >elif &&
13 git add -N file &&
11 - git add elif
14 + git add elif &&
15 + git add -N 1.t
16 +'
17 +
18 +test_expect_success 'git status' '
19 + git status --porcelain | grep -v actual >actual &&
20 + cat >expect <<-\EOF &&
21 + DA 1.t
22 + A elif
23 + A file
24 + EOF
25 + test_cmp expect actual
26 '
27
28 test_expect_success 'check result of "add -N"' '
@@ -43,7 +57,8 @@ test_expect_success 'i-t-a entry is simply ignored' '
57 git add -N nitfol &&
58 git commit -m second &&
59 test $(git ls-tree HEAD -- nitfol | wc -l) = 0 &&
46 - test $(git diff --name-only HEAD -- nitfol | wc -l) = 1
60 + test $(git diff --name-only HEAD -- nitfol | wc -l) = 0 &&
61 + test $(git diff --name-only -- nitfol | wc -l) = 1
62 '
63
64 test_expect_success 'can commit with an unrelated i-t-a entry in index' '
@@ -72,13 +87,13 @@ test_expect_success 'cache-tree invalidates i-t-a paths' '
87 : >dir/bar &&
88 git add -N dir/bar &&
89 git diff --cached --name-only >actual &&
75 - echo dir/bar >expect &&
90 + >expect &&
91 test_cmp expect actual &&
92
93 git write-tree >/dev/null &&
94
95 git diff --cached --name-only >actual &&
81 - echo dir/bar >expect &&
96 + >expect &&
97 test_cmp expect actual
98 '
99
t/t4011-diff-symlink.sh
+6 -4
@@ -139,11 +139,13 @@ test_expect_success SYMLINKS 'setup symlinks with attributes' '
139 test_expect_success SYMLINKS 'symlinks do not respect userdiff config by path' '
140 cat >expect <<-\EOF &&
141 diff --git a/file.bin b/file.bin
142 - index e69de29..d95f3ad 100644
143 - Binary files a/file.bin and b/file.bin differ
142 + new file mode 100644
143 + index 0000000..d95f3ad
144 + Binary files /dev/null and b/file.bin differ
145 diff --git a/link.bin b/link.bin
145 - index e69de29..dce41ec 120000
146 - --- a/link.bin
146 + new file mode 120000
147 + index 0000000..dce41ec
148 + --- /dev/null
149 +++ b/link.bin
150 @@ -0,0 +1 @@
151 +file.bin