mirror of
https://github.com/git/git
synced 2024-08-27 19:49:21 +00:00
Fix the rename detection limit checking
This adds more proper rename detection limits. Instead of just checking the limit against the number of potential rename destinations, we verify that the rename matrix (which is what really matters) doesn't grow ridiculously large, and we also make sure that we don't overflow when doing the matrix size calculation. This also changes the default limits from unlimited, to a rename matrix that is limited to 100 entries on a side. You can raise it with the config entry, or by using the "-l<n>" command line flag, but at least the default is now a sane number that avoids spending lots of time (and memory) in situations that likely don't merit it. The choice of default value is of course very debatable. Limiting the rename matrix to a 100x100 size will mean that even if you have just one obvious rename, but you also create (or delete) 10,000 files, the rename matrix will be so big that we disable the heuristics. Sounds reasonable to me, but let's see if people hit this (and, perhaps more importantly, actually *care*) in real life. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
b78281f721
commit
0024a54923
2
diff.c
2
diff.c
|
@ -17,7 +17,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int diff_detect_rename_default;
|
static int diff_detect_rename_default;
|
||||||
static int diff_rename_limit_default = -1;
|
static int diff_rename_limit_default = 100;
|
||||||
static int diff_use_color_default;
|
static int diff_use_color_default;
|
||||||
int diff_auto_refresh_index = 1;
|
int diff_auto_refresh_index = 1;
|
||||||
|
|
||||||
|
|
|
@ -298,10 +298,25 @@ void diffcore_rename(struct diff_options *options)
|
||||||
else if (detect_rename == DIFF_DETECT_COPY)
|
else if (detect_rename == DIFF_DETECT_COPY)
|
||||||
register_rename_src(p->one, 1, p->score);
|
register_rename_src(p->one, 1, p->score);
|
||||||
}
|
}
|
||||||
if (rename_dst_nr == 0 || rename_src_nr == 0 ||
|
if (rename_dst_nr == 0 || rename_src_nr == 0)
|
||||||
(0 < rename_limit && rename_limit < rename_dst_nr))
|
|
||||||
goto cleanup; /* nothing to do */
|
goto cleanup; /* nothing to do */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This basically does a test for the rename matrix not
|
||||||
|
* growing larger than a "rename_limit" square matrix, ie:
|
||||||
|
*
|
||||||
|
* rename_dst_nr * rename_src_nr > rename_limit * rename_limit
|
||||||
|
*
|
||||||
|
* but handles the potential overflow case specially (and we
|
||||||
|
* assume at least 32-bit integers)
|
||||||
|
*/
|
||||||
|
if (rename_limit <= 0 || rename_limit > 32767)
|
||||||
|
rename_limit = 32767;
|
||||||
|
if (rename_dst_nr > rename_limit && rename_src_nr > rename_limit)
|
||||||
|
goto cleanup;
|
||||||
|
if (rename_dst_nr * rename_src_nr > rename_limit * rename_limit)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
/* We really want to cull the candidates list early
|
/* We really want to cull the candidates list early
|
||||||
* with cheap tests in order to avoid doing deltas.
|
* with cheap tests in order to avoid doing deltas.
|
||||||
* The first round matches up the up-to-date entries,
|
* The first round matches up the up-to-date entries,
|
||||||
|
|
|
@ -227,6 +227,7 @@ static void wt_status_print_updated(struct wt_status *s)
|
||||||
rev.diffopt.format_callback = wt_status_print_updated_cb;
|
rev.diffopt.format_callback = wt_status_print_updated_cb;
|
||||||
rev.diffopt.format_callback_data = s;
|
rev.diffopt.format_callback_data = s;
|
||||||
rev.diffopt.detect_rename = 1;
|
rev.diffopt.detect_rename = 1;
|
||||||
|
rev.diffopt.rename_limit = 100;
|
||||||
wt_read_cache(s);
|
wt_read_cache(s);
|
||||||
run_diff_index(&rev, 1);
|
run_diff_index(&rev, 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue