diffcore-rename: properly honor the difference between -M and -C
We would allow rename detection to do copy detection even when asked purely for renames. That confuses users, but more importantly it can terminally confuse the recursive merge rename logic. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Linus Torvalds committed
Feb 18, 2011 at 20:10 UTC
0940e5f211452ec2520d1b04233acddf0a872c06
6 files changed
+32
-33
diffcore-rename.c
+26
-27
@@ -278,6 +278,8 @@ static int find_identical_files(struct file_similarity *src,
278
}
279
/* Give higher scores to sources that haven't been used already */
280
score = !source->rename_used;
281
+ if (source->rename_used && options->detect_rename != DIFF_DETECT_COPY)
282
+ continue;
283
score += basename_same(source, target);
284
if (score > best_score) {
285
best = p;
@@ -416,6 +418,27 @@ static void record_if_better(struct diff_score m[], struct diff_score *o)
418
m[worst] = *o;
419
}
420
421
+static int find_renames(struct diff_score *mx, int dst_cnt, int minimum_score, int copies)
422
+{
423
+ int count = 0, i;
424
+
425
+ for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
426
+ struct diff_rename_dst *dst;
427
+
428
+ if ((mx[i].dst < 0) ||
429
+ (mx[i].score < minimum_score))
430
+ break; /* there is no more usable pair. */
431
+ dst = &rename_dst[mx[i].dst];
432
+ if (dst->pair)
433
+ continue; /* already done, either exact or fuzzy. */
434
+ if (!copies && rename_src[mx[i].src].one->rename_used)
435
+ continue;
436
+ record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
437
+ count++;
438
+ }
439
+ return count;
440
+}
441
+
442
void diffcore_rename(struct diff_options *options)
443
{
444
int detect_rename = options->detect_rename;
@@ -538,33 +561,9 @@ void diffcore_rename(struct diff_options *options)
561
/* cost matrix sorted by most to least similar pair */
562
qsort(mx, dst_cnt * NUM_CANDIDATE_PER_DST, sizeof(*mx), score_compare);
563
541
- for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
542
- struct diff_rename_dst *dst;
543
-
544
- if ((mx[i].dst < 0) ||
545
- (mx[i].score < minimum_score))
546
- break; /* there is no more usable pair. */
547
- dst = &rename_dst[mx[i].dst];
548
- if (dst->pair)
549
- continue; /* already done, either exact or fuzzy. */
550
- if (rename_src[mx[i].src].one->rename_used)
551
- continue;
552
- record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
553
- rename_count++;
554
- }
555
-
556
- for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
557
- struct diff_rename_dst *dst;
558
-
559
- if ((mx[i].dst < 0) ||
560
- (mx[i].score < minimum_score))
561
- break; /* there is no more usable pair. */
562
- dst = &rename_dst[mx[i].dst];
563
- if (dst->pair)
564
- continue; /* already done, either exact or fuzzy. */
565
- record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
566
- rename_count++;
567
- }
564
+ rename_count += find_renames(mx, dst_cnt, minimum_score, 0);
565
+ if (detect_rename == DIFF_DETECT_COPY)
566
+ rename_count += find_renames(mx, dst_cnt, minimum_score, 1);
567
free(mx);
568
569
cleanup:
t/t4003-diff-rename-1.sh
+1
-1
@@ -29,7 +29,7 @@ test_expect_success \
29
# copy-and-edit one, and rename-and-edit the other. We do not say
30
# anything about rezrov.
31
32
-GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current
32
+GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current
33
cat >expected <<\EOF
34
diff --git a/COPYING b/COPYING.1
35
copy from COPYING
t/t4004-diff-rename-symlink.sh
+1
-1
@@ -35,7 +35,7 @@ test_expect_success SYMLINKS \
35
# a new creation.
36
37
test_expect_success SYMLINKS 'setup diff output' "
38
- GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current &&
38
+ GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current &&
39
cat >expected <<\EOF
40
diff --git a/bozbar b/bozbar
41
new file mode 120000
t/t4005-diff-rename-2.sh
+1
-1
@@ -29,7 +29,7 @@ test_expect_success \
29
# and COPYING.2 are based on COPYING, and do not say anything about
30
# rezrov.
31
32
-git diff-index -M $tree >current
32
+git diff-index -C $tree >current
33
34
cat >expected <<\EOF
35
:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1
t/t4008-diff-break-rewrite.sh
+2
-2
@@ -173,8 +173,8 @@ test_expect_success \
173
'compare_diff_raw expected current'
174
175
test_expect_success \
176
- 'run diff with -B -M' \
177
- 'git diff-index -B -M "$tree" >current'
176
+ 'run diff with -B -C' \
177
+ 'git diff-index -B -C "$tree" >current'
178
179
cat >expected <<\EOF
180
:100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 08bb2fb671deff4c03a4d4a0a1315dff98d5732c C095 file0 file1
t/t4009-diff-rename-4.sh
+1
-1
@@ -29,7 +29,7 @@ test_expect_success \
29
# and COPYING.2 are based on COPYING, and do not say anything about
30
# rezrov.
31
32
-git diff-index -z -M $tree >current
32
+git diff-index -z -C $tree >current
33
34
cat >expected <<\EOF
35
:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234