summaryrefslogtreecommitdiff
path: root/diffcore-rename.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2011-01-06 13:50:06 -0800
committerJunio C Hamano <gitster@pobox.com>2011-03-22 14:29:07 -0700
commitf31027c99cb2ec4eb7ad8d1ebc7f0e20fef4bd1d (patch)
treeecc4d0213fcbd8c270b254cec1caff867034ac7d /diffcore-rename.c
parente88d6bc6f90059f6e87f6d51eba83ec15e4eecc9 (diff)
downloadgit-f31027c99cb2ec4eb7ad8d1ebc7f0e20fef4bd1d.tar.gz
diffcore-rename: fall back to -C when -C -C busts the rename limit
When there are too many paths in the project, the number of rename source candidates "git diff -C -C" finds will exceed the rename detection limit, and no inexact rename detection is performed. We however could fall back to "git diff -C" if the number of modified paths is sufficiently small. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'diffcore-rename.c')
-rw-r--r--diffcore-rename.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/diffcore-rename.c b/diffcore-rename.c
index a932f762d2..f62587e523 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -420,11 +420,18 @@ static void record_if_better(struct diff_score m[], struct diff_score *o)
m[worst] = *o;
}
+/*
+ * Returns:
+ * 0 if we are under the limit;
+ * 1 if we need to disable inexact rename detection;
+ * 2 if we would be under the limit if we were given -C instead of -C -C.
+ */
static int too_many_rename_candidates(int num_create,
struct diff_options *options)
{
int rename_limit = options->rename_limit;
int num_src = rename_src_nr;
+ int i;
options->needed_rename_limit = 0;
@@ -445,6 +452,20 @@ static int too_many_rename_candidates(int num_create,
options->needed_rename_limit =
num_src > num_create ? num_src : num_create;
+
+ /* Are we running under -C -C? */
+ if (!DIFF_OPT_TST(options, FIND_COPIES_HARDER))
+ return 1;
+
+ /* Would we bust the limit if we were running under -C? */
+ for (num_src = i = 0; i < rename_src_nr; i++) {
+ if (diff_unmodified_pair(rename_src[i].p))
+ continue;
+ num_src++;
+ }
+ if ((num_create <= rename_limit || num_src <= rename_limit) &&
+ (num_create * num_src <= rename_limit * rename_limit))
+ return 2;
return 1;
}
@@ -476,7 +497,7 @@ void diffcore_rename(struct diff_options *options)
struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq;
struct diff_score *mx;
- int i, j, rename_count;
+ int i, j, rename_count, skip_unmodified = 0;
int num_create, num_src, dst_cnt;
struct progress *progress = NULL;
@@ -539,8 +560,16 @@ void diffcore_rename(struct diff_options *options)
if (!num_create)
goto cleanup;
- if (too_many_rename_candidates(num_create, options))
+ switch (too_many_rename_candidates(num_create, options)) {
+ case 1:
goto cleanup;
+ case 2:
+ options->degraded_cc_to_c = 1;
+ skip_unmodified = 1;
+ break;
+ default:
+ break;
+ }
if (options->show_rename_progress) {
progress = start_progress_delay(
@@ -563,6 +592,11 @@ void diffcore_rename(struct diff_options *options)
for (j = 0; j < rename_src_nr; j++) {
struct diff_filespec *one = rename_src[j].p->one;
struct diff_score this_src;
+
+ if (skip_unmodified &&
+ diff_unmodified_pair(rename_src[j].p))
+ continue;
+
this_src.score = estimate_similarity(one, two,
minimum_score);
this_src.name_score = basename_same(one, two);