Browse Source

diff-no-index: align D/F handling with that of normal Git

When a commit changes a path P that used to be a file to a directory
and creates a new path P/X in it, "git show" would say that file P
was removed and file P/X was created for such a commit.

However, if we compare two directories, D1 and D2, where D1 has a
file D1/P in it and D2 has a directory D2/P under which there is a
file D2/P/X, and ask "git diff --no-index D1 D2" to show their
differences, we simply get a refusal "file/directory conflict".

Surely, that may be what GNU diff does, but we can do better and it
is easy to do so.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Junio C Hamano 10 years ago
parent
commit
0615173998
  1. 23
      diff-no-index.c
  2. 12
      t/t4053-diff-no-index.sh

23
diff-no-index.c

@ -97,8 +97,27 @@ static int queue_diff(struct diff_options *o, @@ -97,8 +97,27 @@ static int queue_diff(struct diff_options *o,
if (get_mode(name1, &mode1) || get_mode(name2, &mode2))
return -1;

if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2))
return error("file/directory conflict: %s, %s", name1, name2);
if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2)) {
struct diff_filespec *d1, *d2;

if (S_ISDIR(mode1)) {
/* 2 is file that is created */
d1 = noindex_filespec(NULL, 0);
d2 = noindex_filespec(name2, mode2);
name2 = NULL;
mode2 = 0;
} else {
/* 1 is file that is deleted */
d1 = noindex_filespec(name1, mode1);
d2 = noindex_filespec(NULL, 0);
name1 = NULL;
mode1 = 0;
}
/* emit that file */
diff_queue(&diff_queued_diff, d1, d2);

/* and then let the entire directory be created or deleted */
}

if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
struct strbuf buffer1 = STRBUF_INIT;

12
t/t4053-diff-no-index.sh

@ -77,4 +77,16 @@ test_expect_success 'diff D F and diff F D' ' @@ -77,4 +77,16 @@ test_expect_success 'diff D F and diff F D' '
)
'

test_expect_success 'turning a file into a directory' '
(
cd non/git &&
mkdir d e e/sub &&
echo 1 >d/sub &&
echo 2 >e/sub/file &&
printf "D\td/sub\nA\te/sub/file\n" >expect &&
test_must_fail git diff --no-index --name-status d e >actual &&
test_cmp expect actual
)
'

test_done

Loading…
Cancel
Save