X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=diffcore-rename.c;h=31941bcbbf457fe02097f8c46d25f1f9fc7c4f9f;hb=f746bae84e4746a861d9ebed29fd9255e5cd929f;hp=f9ebea56406090af207f79951618742dcd7d397f;hpb=e3d6d56f1c2097f13a427e158638e5e0918e5705;p=git.git diff --git a/diffcore-rename.c b/diffcore-rename.c index f9ebea564..31941bcbb 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -244,28 +244,35 @@ static int find_identical_files(struct file_similarity *src, * Walk over all the destinations ... */ do { - struct diff_filespec *one = dst->filespec; + struct diff_filespec *target = dst->filespec; struct file_similarity *p, *best; - int i = 100; + int i = 100, best_score = -1; /* * .. to find the best source match */ best = NULL; for (p = src; p; p = p->next) { - struct diff_filespec *two = p->filespec; + int score; + struct diff_filespec *source = p->filespec; /* False hash collission? */ - if (hashcmp(one->sha1, two->sha1)) + if (hashcmp(source->sha1, target->sha1)) continue; /* Non-regular files? If so, the modes must match! */ - if (!S_ISREG(one->mode) || !S_ISREG(two->mode)) { - if (one->mode != two->mode) + if (!S_ISREG(source->mode) || !S_ISREG(target->mode)) { + if (source->mode != target->mode) continue; } - best = p; - if (basename_same(one, two)) - break; + /* Give higher scores to sources that haven't been used already */ + score = !source->rename_used; + score += basename_same(source, target); + if (score > best_score) { + best = p; + best_score = score; + if (score == 2) + break; + } /* Too many identical alternatives? Pick one */ if (!--i) @@ -461,10 +468,11 @@ void diffcore_rename(struct diff_options *options) */ if (rename_limit <= 0 || rename_limit > 32767) rename_limit = 32767; - if (num_create > rename_limit && num_src > rename_limit) - goto cleanup; - if (num_create * num_src > rename_limit * rename_limit) + if ((num_create > rename_limit && num_src > rename_limit) || + (num_create * num_src > rename_limit * rename_limit)) { + warning("too many files, skipping inexact rename detection"); goto cleanup; + } mx = xmalloc(sizeof(*mx) * num_create * num_src); for (dst_cnt = i = 0; i < rename_dst_nr; i++) { @@ -488,6 +496,19 @@ void diffcore_rename(struct diff_options *options) } /* cost matrix sorted by most to least similar pair */ qsort(mx, num_create * num_src, sizeof(*mx), score_compare); + for (i = 0; i < num_create * num_src; i++) { + struct diff_rename_dst *dst = &rename_dst[mx[i].dst]; + struct diff_filespec *src; + if (dst->pair) + continue; /* already done, either exact or fuzzy. */ + if (mx[i].score < minimum_score) + break; /* there is no more usable pair. */ + src = rename_src[mx[i].src].one; + if (src->rename_used) + continue; + record_rename_pair(mx[i].dst, mx[i].src, mx[i].score); + rename_count++; + } for (i = 0; i < num_create * num_src; i++) { struct diff_rename_dst *dst = &rename_dst[mx[i].dst]; if (dst->pair)