summaryrefslogtreecommitdiff
path: root/diffcore-rename.c
diff options
context:
space:
mode:
Diffstat (limited to 'diffcore-rename.c')
-rw-r--r--diffcore-rename.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/diffcore-rename.c b/diffcore-rename.c
index f9ebea5640..3d377251be 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)
@@ -490,6 +497,19 @@ void diffcore_rename(struct diff_options *options)
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)
continue; /* already done, either exact or fuzzy. */
if (mx[i].score < minimum_score)