Merge branch 'jk/diff-tree-t-fix'
authorJunio C Hamano <gitster@pobox.com>
Tue, 26 Aug 2014 18:16:26 +0000 (11:16 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 26 Aug 2014 18:16:26 +0000 (11:16 -0700)
Fix (rarely used) "git diff-tree -t" regression in 2.0.

* jk/diff-tree-t-fix:
intersect_paths: respect mode in git's tree-sort

combine-diff.c
t/t4038-diff-combined.sh
index f9975d2c2ebc83e8ecfc953c8df907fbff7858f5..60cb4f81f9788efeff21d05d48f2183e94765385 100644 (file)
 #include "sha1-array.h"
 #include "revision.h"
 
+static int compare_paths(const struct combine_diff_path *one,
+                         const struct diff_filespec *two)
+{
+       if (!S_ISDIR(one->mode) && !S_ISDIR(two->mode))
+               return strcmp(one->path, two->path);
+
+       return base_name_compare(one->path, strlen(one->path), one->mode,
+                                two->path, strlen(two->path), two->mode);
+}
+
 static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
@@ -52,7 +62,7 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
        i = 0;
        while ((p = *tail) != NULL) {
                cmp = ((i >= q->nr)
-                      ? -1 : strcmp(p->path, q->queue[i]->two->path));
+                      ? -1 : compare_paths(p, q->queue[i]->two));
 
                if (cmp < 0) {
                        /* p->path not in q->queue[]; drop it */
index 41913c3aa30de6d55b016fa9331e0877579b2d6b..0b4f7dfdc6f6dac4775ab4b016d6be83681ddadd 100755 (executable)
@@ -401,4 +401,38 @@ test_expect_success 'combine diff missing delete bug' '
        compare_diff_patch expected actual
 '
 
+test_expect_success 'combine diff gets tree sorting right' '
+       # create a directory and a file that sort differently in trees
+       # versus byte-wise (implied "/" sorts after ".")
+       git checkout -f master &&
+       mkdir foo &&
+       echo base >foo/one &&
+       echo base >foo/two &&
+       echo base >foo.ext &&
+       git add foo foo.ext &&
+       git commit -m base &&
+
+       # one side modifies a file in the directory, along with the root
+       # file...
+       echo master >foo/one &&
+       echo master >foo.ext &&
+       git commit -a -m master &&
+
+       # the other side modifies the other file in the directory
+       git checkout -b other HEAD^ &&
+       echo other >foo/two &&
+       git commit -a -m other &&
+
+       # And now we merge. The files in the subdirectory will resolve cleanly,
+       # meaning that a combined diff will not find them interesting. But it
+       # will find the tree itself interesting, because it had to be merged.
+       git checkout master &&
+       git merge other &&
+
+       printf "MM\tfoo\n" >expect &&
+       git diff-tree -c --name-status -t HEAD >actual.tmp &&
+       sed 1d <actual.tmp >actual &&
+       test_cmp expect actual
+'
+
 test_done