@@ -55,22 +55,23 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
5555
5656/* Table of rename/copy src files */
5757static struct diff_rename_src {
58- struct diff_filespec * one ;
58+ struct diff_filepair * p ;
5959 unsigned short score ; /* to remember the break score */
6060} * rename_src ;
6161static int rename_src_nr , rename_src_alloc ;
6262
63- static struct diff_rename_src * register_rename_src (struct diff_filespec * one ,
64- unsigned short score )
63+ static struct diff_rename_src * register_rename_src (struct diff_filepair * p )
6564{
6665 int first , last ;
66+ struct diff_filespec * one = p -> one ;
67+ unsigned short score = p -> score ;
6768
6869 first = 0 ;
6970 last = rename_src_nr ;
7071 while (last > first ) {
7172 int next = (last + first ) >> 1 ;
7273 struct diff_rename_src * src = & (rename_src [next ]);
73- int cmp = strcmp (one -> path , src -> one -> path );
74+ int cmp = strcmp (one -> path , src -> p -> one -> path );
7475 if (!cmp )
7576 return src ;
7677 if (cmp < 0 ) {
@@ -90,7 +91,7 @@ static struct diff_rename_src *register_rename_src(struct diff_filespec *one,
9091 if (first < rename_src_nr )
9192 memmove (rename_src + first + 1 , rename_src + first ,
9293 (rename_src_nr - first - 1 ) * sizeof (* rename_src ));
93- rename_src [first ].one = one ;
94+ rename_src [first ].p = p ;
9495 rename_src [first ].score = score ;
9596 return & (rename_src [first ]);
9697}
@@ -205,7 +206,7 @@ static void record_rename_pair(int dst_index, int src_index, int score)
205206 if (rename_dst [dst_index ].pair )
206207 die ("internal error: dst already matched." );
207208
208- src = rename_src [src_index ].one ;
209+ src = rename_src [src_index ].p -> one ;
209210 src -> rename_used ++ ;
210211 src -> count ++ ;
211212
@@ -389,7 +390,7 @@ static int find_exact_renames(struct diff_options *options)
389390
390391 init_hash (& file_table );
391392 for (i = 0 ; i < rename_src_nr ; i ++ )
392- insert_file_table (& file_table , -1 , i , rename_src [i ].one );
393+ insert_file_table (& file_table , -1 , i , rename_src [i ].p -> one );
393394
394395 for (i = 0 ; i < rename_dst_nr ; i ++ )
395396 insert_file_table (& file_table , 1 , i , rename_dst [i ].two );
@@ -419,6 +420,55 @@ static void record_if_better(struct diff_score m[], struct diff_score *o)
419420 m [worst ] = * o ;
420421}
421422
423+ /*
424+ * Returns:
425+ * 0 if we are under the limit;
426+ * 1 if we need to disable inexact rename detection;
427+ * 2 if we would be under the limit if we were given -C instead of -C -C.
428+ */
429+ static int too_many_rename_candidates (int num_create ,
430+ struct diff_options * options )
431+ {
432+ int rename_limit = options -> rename_limit ;
433+ int num_src = rename_src_nr ;
434+ int i ;
435+
436+ options -> needed_rename_limit = 0 ;
437+
438+ /*
439+ * This basically does a test for the rename matrix not
440+ * growing larger than a "rename_limit" square matrix, ie:
441+ *
442+ * num_create * num_src > rename_limit * rename_limit
443+ *
444+ * but handles the potential overflow case specially (and we
445+ * assume at least 32-bit integers)
446+ */
447+ if (rename_limit <= 0 || rename_limit > 32767 )
448+ rename_limit = 32767 ;
449+ if ((num_create <= rename_limit || num_src <= rename_limit ) &&
450+ (num_create * num_src <= rename_limit * rename_limit ))
451+ return 0 ;
452+
453+ options -> needed_rename_limit =
454+ num_src > num_create ? num_src : num_create ;
455+
456+ /* Are we running under -C -C? */
457+ if (!DIFF_OPT_TST (options , FIND_COPIES_HARDER ))
458+ return 1 ;
459+
460+ /* Would we bust the limit if we were running under -C? */
461+ for (num_src = i = 0 ; i < rename_src_nr ; i ++ ) {
462+ if (diff_unmodified_pair (rename_src [i ].p ))
463+ continue ;
464+ num_src ++ ;
465+ }
466+ if ((num_create <= rename_limit || num_src <= rename_limit ) &&
467+ (num_create * num_src <= rename_limit * rename_limit ))
468+ return 2 ;
469+ return 1 ;
470+ }
471+
422472static int find_renames (struct diff_score * mx , int dst_cnt , int minimum_score , int copies )
423473{
424474 int count = 0 , i ;
@@ -432,7 +482,7 @@ static int find_renames(struct diff_score *mx, int dst_cnt, int minimum_score, i
432482 dst = & rename_dst [mx [i ].dst ];
433483 if (dst -> pair )
434484 continue ; /* already done, either exact or fuzzy. */
435- if (!copies && rename_src [mx [i ].src ].one -> rename_used )
485+ if (!copies && rename_src [mx [i ].src ].p -> one -> rename_used )
436486 continue ;
437487 record_rename_pair (mx [i ].dst , mx [i ].src , mx [i ].score );
438488 count ++ ;
@@ -444,11 +494,10 @@ void diffcore_rename(struct diff_options *options)
444494{
445495 int detect_rename = options -> detect_rename ;
446496 int minimum_score = options -> rename_score ;
447- int rename_limit = options -> rename_limit ;
448497 struct diff_queue_struct * q = & diff_queued_diff ;
449498 struct diff_queue_struct outq ;
450499 struct diff_score * mx ;
451- int i , j , rename_count ;
500+ int i , j , rename_count , skip_unmodified = 0 ;
452501 int num_create , num_src , dst_cnt ;
453502 struct progress * progress = NULL ;
454503
@@ -476,15 +525,15 @@ void diffcore_rename(struct diff_options *options)
476525 */
477526 if (p -> broken_pair && !p -> score )
478527 p -> one -> rename_used ++ ;
479- register_rename_src (p -> one , p -> score );
528+ register_rename_src (p );
480529 }
481530 else if (detect_rename == DIFF_DETECT_COPY ) {
482531 /*
483532 * Increment the "rename_used" score by
484533 * one, to indicate ourselves as a user.
485534 */
486535 p -> one -> rename_used ++ ;
487- register_rename_src (p -> one , p -> score );
536+ register_rename_src (p );
488537 }
489538 }
490539 if (rename_dst_nr == 0 || rename_src_nr == 0 )
@@ -511,23 +560,15 @@ void diffcore_rename(struct diff_options *options)
511560 if (!num_create )
512561 goto cleanup ;
513562
514- /*
515- * This basically does a test for the rename matrix not
516- * growing larger than a "rename_limit" square matrix, ie:
517- *
518- * num_create * num_src > rename_limit * rename_limit
519- *
520- * but handles the potential overflow case specially (and we
521- * assume at least 32-bit integers)
522- */
523- options -> needed_rename_limit = 0 ;
524- if (rename_limit <= 0 || rename_limit > 32767 )
525- rename_limit = 32767 ;
526- if ((num_create > rename_limit && num_src > rename_limit ) ||
527- (num_create * num_src > rename_limit * rename_limit )) {
528- options -> needed_rename_limit =
529- num_src > num_create ? num_src : num_create ;
563+ switch (too_many_rename_candidates (num_create , options )) {
564+ case 1 :
530565 goto cleanup ;
566+ case 2 :
567+ options -> degraded_cc_to_c = 1 ;
568+ skip_unmodified = 1 ;
569+ break ;
570+ default :
571+ break ;
531572 }
532573
533574 if (options -> show_rename_progress ) {
@@ -549,8 +590,13 @@ void diffcore_rename(struct diff_options *options)
549590 m [j ].dst = -1 ;
550591
551592 for (j = 0 ; j < rename_src_nr ; j ++ ) {
552- struct diff_filespec * one = rename_src [j ].one ;
593+ struct diff_filespec * one = rename_src [j ].p -> one ;
553594 struct diff_score this_src ;
595+
596+ if (skip_unmodified &&
597+ diff_unmodified_pair (rename_src [j ].p ))
598+ continue ;
599+
554600 this_src .score = estimate_similarity (one , two ,
555601 minimum_score );
556602 this_src .name_score = basename_same (one , two );
0 commit comments