@@ -15,8 +15,7 @@ static struct diff_rename_dst {
15
15
} * rename_dst ;
16
16
static int rename_dst_nr , rename_dst_alloc ;
17
17
18
- static struct diff_rename_dst * locate_rename_dst (struct diff_filespec * two ,
19
- int insert_ok )
18
+ static int find_rename_dst (struct diff_filespec * two )
20
19
{
21
20
int first , last ;
22
21
@@ -27,16 +26,33 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
27
26
struct diff_rename_dst * dst = & (rename_dst [next ]);
28
27
int cmp = strcmp (two -> path , dst -> two -> path );
29
28
if (!cmp )
30
- return dst ;
29
+ return next ;
31
30
if (cmp < 0 ) {
32
31
last = next ;
33
32
continue ;
34
33
}
35
34
first = next + 1 ;
36
35
}
37
- /* not found */
38
- if (!insert_ok )
39
- return NULL ;
36
+ return - first - 1 ;
37
+ }
38
+
39
+ static struct diff_rename_dst * locate_rename_dst (struct diff_filespec * two )
40
+ {
41
+ int ofs = find_rename_dst (two );
42
+ return ofs < 0 ? NULL : & rename_dst [ofs ];
43
+ }
44
+
45
+ /*
46
+ * Returns 0 on success, -1 if we found a duplicate.
47
+ */
48
+ static int add_rename_dst (struct diff_filespec * two )
49
+ {
50
+ int first = find_rename_dst (two );
51
+
52
+ if (first >= 0 )
53
+ return -1 ;
54
+ first = - first - 1 ;
55
+
40
56
/* insert to make it at "first" */
41
57
ALLOC_GROW (rename_dst , rename_dst_nr + 1 , rename_dst_alloc );
42
58
rename_dst_nr ++ ;
@@ -46,7 +62,7 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
46
62
rename_dst [first ].two = alloc_filespec (two -> path );
47
63
fill_filespec (rename_dst [first ].two , two -> sha1 , two -> sha1_valid , two -> mode );
48
64
rename_dst [first ].pair = NULL ;
49
- return & ( rename_dst [ first ]) ;
65
+ return 0 ;
50
66
}
51
67
52
68
/* Table of rename/copy src files */
@@ -450,8 +466,12 @@ void diffcore_rename(struct diff_options *options)
450
466
else if (!DIFF_OPT_TST (options , RENAME_EMPTY ) &&
451
467
is_empty_blob_sha1 (p -> two -> sha1 ))
452
468
continue ;
453
- else
454
- locate_rename_dst (p -> two , 1 );
469
+ else if (add_rename_dst (p -> two ) < 0 ) {
470
+ warning ("skipping rename detection, detected"
471
+ " duplicate destination '%s'" ,
472
+ p -> two -> path );
473
+ goto cleanup ;
474
+ }
455
475
}
456
476
else if (!DIFF_OPT_TST (options , RENAME_EMPTY ) &&
457
477
is_empty_blob_sha1 (p -> one -> sha1 ))
@@ -582,8 +602,7 @@ void diffcore_rename(struct diff_options *options)
582
602
* We would output this create record if it has
583
603
* not been turned into a rename/copy already.
584
604
*/
585
- struct diff_rename_dst * dst =
586
- locate_rename_dst (p -> two , 0 );
605
+ struct diff_rename_dst * dst = locate_rename_dst (p -> two );
587
606
if (dst && dst -> pair ) {
588
607
diff_q (& outq , dst -> pair );
589
608
pair_to_free = p ;
@@ -613,8 +632,7 @@ void diffcore_rename(struct diff_options *options)
613
632
*/
614
633
if (DIFF_PAIR_BROKEN (p )) {
615
634
/* broken delete */
616
- struct diff_rename_dst * dst =
617
- locate_rename_dst (p -> one , 0 );
635
+ struct diff_rename_dst * dst = locate_rename_dst (p -> one );
618
636
if (dst && dst -> pair )
619
637
/* counterpart is now rename/copy */
620
638
pair_to_free = p ;
0 commit comments