Merge branch 'sg/diff-multiple-identical-renames'
authorJunio C Hamano <gitster@pobox.com>
Wed, 13 Apr 2016 21:12:32 +0000 (14:12 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 13 Apr 2016 21:12:32 +0000 (14:12 -0700)
"git diff -M" used to work better when two originally identical
files A and B got renamed to X/A and X/B by pairing A to X/A and B
to X/B, but this was broken in the 2.0 timeframe.

* sg/diff-multiple-identical-renames:
diffcore: fix iteration order of identical files during rename detection

1  2 
diffcore-rename.c
t/t4001-diff-rename.sh
diff --combined diffcore-rename.c
index 3b3c1ed535e7c8b17947d69dbe0bd5c8f115cf2d,69fcf77be02df4160dfaa04380d0a262b9d4aa02..7f03eb5a0404d4b44f292fba76433dfec74dcd44
@@@ -340,9 -340,11 +340,11 @@@ static int find_exact_renames(struct di
        int i, renames = 0;
        struct hashmap file_table;
  
-       /* Add all sources to the hash table */
+       /* Add all sources to the hash table in reverse order, because
+        * later on they will be retrieved in LIFO order.
+        */
        hashmap_init(&file_table, NULL, rename_src_nr);
-       for (i = 0; i < rename_src_nr; i++)
+       for (i = rename_src_nr-1; i >= 0; i--)
                insert_file_table(&file_table, i, rename_src[i].p->one);
  
        /* Walk the destinations and find best source match */
@@@ -537,7 -539,7 +539,7 @@@ void diffcore_rename(struct diff_option
                                rename_dst_nr * rename_src_nr, 50, 1);
        }
  
 -      mx = xcalloc(num_create * NUM_CANDIDATE_PER_DST, sizeof(*mx));
 +      mx = xcalloc(st_mult(num_create, NUM_CANDIDATE_PER_DST), sizeof(*mx));
        for (dst_cnt = i = 0; i < rename_dst_nr; i++) {
                struct diff_filespec *two = rename_dst[i].two;
                struct diff_score *m;
diff --combined t/t4001-diff-rename.sh
index c7e58b69a92fb464059f99ad298b9147946bf702,ed90c6c6f984979bfc250d277486550cb5129e30..0d1fa45d25e59ea100864a76b105b149c6dfcb85
@@@ -9,84 -9,21 +9,84 @@@ test_description='Test rename detectio
  . ./test-lib.sh
  . "$TEST_DIRECTORY"/diff-lib.sh
  
 -echo >path0 'Line 1
 -Line 2
 -Line 3
 -Line 4
 -Line 5
 -Line 6
 -Line 7
 -Line 8
 -Line 9
 -Line 10
 -line 11
 -Line 12
 -Line 13
 -Line 14
 -Line 15
 +test_expect_success 'setup' '
 +      cat >path0 <<-\EOF &&
 +      Line 1
 +      Line 2
 +      Line 3
 +      Line 4
 +      Line 5
 +      Line 6
 +      Line 7
 +      Line 8
 +      Line 9
 +      Line 10
 +      line 11
 +      Line 12
 +      Line 13
 +      Line 14
 +      Line 15
 +      EOF
 +      cat >expected <<-\EOF &&
 +      diff --git a/path0 b/path1
 +      rename from path0
 +      rename to path1
 +      --- a/path0
 +      +++ b/path1
 +      @@ -8,7 +8,7 @@ Line 7
 +       Line 8
 +       Line 9
 +       Line 10
 +      -line 11
 +      +Line 11
 +       Line 12
 +       Line 13
 +       Line 14
 +      EOF
 +      cat >no-rename <<-\EOF
 +      diff --git a/path0 b/path0
 +      deleted file mode 100644
 +      index fdbec44..0000000
 +      --- a/path0
 +      +++ /dev/null
 +      @@ -1,15 +0,0 @@
 +      -Line 1
 +      -Line 2
 +      -Line 3
 +      -Line 4
 +      -Line 5
 +      -Line 6
 +      -Line 7
 +      -Line 8
 +      -Line 9
 +      -Line 10
 +      -line 11
 +      -Line 12
 +      -Line 13
 +      -Line 14
 +      -Line 15
 +      diff --git a/path1 b/path1
 +      new file mode 100644
 +      index 0000000..752c50e
 +      --- /dev/null
 +      +++ b/path1
 +      @@ -0,0 +1,15 @@
 +      +Line 1
 +      +Line 2
 +      +Line 3
 +      +Line 4
 +      +Line 5
 +      +Line 6
 +      +Line 7
 +      +Line 8
 +      +Line 9
 +      +Line 10
 +      +Line 11
 +      +Line 12
 +      +Line 13
 +      +Line 14
 +      +Line 15
 +      EOF
  '
  
  test_expect_success \
@@@ -106,27 -43,27 +106,27 @@@ test_expect_success 
  test_expect_success \
      'git diff-index -p -M after rename and editing.' \
      'git diff-index -p -M $tree >current'
 -cat >expected <<\EOF
 -diff --git a/path0 b/path1
 -rename from path0
 -rename to path1
 ---- a/path0
 -+++ b/path1
 -@@ -8,7 +8,7 @@ Line 7
 - Line 8
 - Line 9
 - Line 10
 --line 11
 -+Line 11
 - Line 12
 - Line 13
 - Line 14
 -EOF
 +
  
  test_expect_success \
      'validate the output.' \
      'compare_diff_patch current expected'
  
 +test_expect_success 'test diff.renames=true' '
 +      git -c diff.renames=true diff --cached $tree >current &&
 +      compare_diff_patch current expected
 +'
 +
 +test_expect_success 'test diff.renames=false' '
 +      git -c diff.renames=false diff --cached $tree >current &&
 +      compare_diff_patch current no-rename
 +'
 +
 +test_expect_success 'test diff.renames unset' '
 +      git diff --cached $tree >current &&
 +      compare_diff_patch current expected
 +'
 +
  test_expect_success 'favour same basenames over different ones' '
        cp path1 another-path &&
        git add another-path &&
@@@ -140,6 -77,17 +140,17 @@@ test_expect_success 'favour same basena
        git show HEAD:path1 | sed "s/15/16/" > subdir/path1 &&
        git status | test_i18ngrep "renamed: .*path1 -> subdir/path1"'
  
+ test_expect_success 'two files with same basename and same content' '
+       git reset --hard &&
+       mkdir -p dir/A dir/B &&
+       cp path1 dir/A/file &&
+       cp path1 dir/B/file &&
+       git add dir &&
+       git commit -m 2 &&
+       git mv dir other-dir &&
+       git status | test_i18ngrep "renamed: .*dir/A/file -> other-dir/A/file"
+ '
  test_expect_success 'setup for many rename source candidates' '
        git reset --hard &&
        for i in 0 1 2 3 4 5 6 7 8 9;