rebase--interactive: remote stray closing parenthesis
[gitweb.git] / diffcore-rename.c
index 91fa2bea519a39ee65dcf018b7a72885b9eeec70..79c984c9cf5489d22f359b7a2ad3464ffc271c35 100644 (file)
@@ -119,6 +119,21 @@ static int is_exact_match(struct diff_filespec *src,
        return 0;
 }
 
+static int basename_same(struct diff_filespec *src, struct diff_filespec *dst)
+{
+       int src_len = strlen(src->path), dst_len = strlen(dst->path);
+       while (src_len && dst_len) {
+               char c1 = src->path[--src_len];
+               char c2 = dst->path[--dst_len];
+               if (c1 != c2)
+                       return 0;
+               if (c1 == '/')
+                       return 1;
+       }
+       return (!src_len || src->path[src_len - 1] == '/') &&
+               (!dst_len || dst->path[dst_len - 1] == '/');
+}
+
 struct diff_score {
        int src; /* index in rename_src */
        int dst; /* index in rename_dst */
@@ -172,7 +187,8 @@ static int estimate_similarity(struct diff_filespec *src,
                return 0; /* error but caught downstream */
 
 
-       delta_limit = base_size * (MAX_SCORE-minimum_score) / MAX_SCORE;
+       delta_limit = (unsigned long)
+               (base_size * (MAX_SCORE-minimum_score) / MAX_SCORE);
        if (diffcore_count_changes(src->data, src->size,
                                   dst->data, dst->size,
                                   &src->cnt_data, &dst->cnt_data,
@@ -185,8 +201,11 @@ static int estimate_similarity(struct diff_filespec *src,
         */
        if (!dst->size)
                score = 0; /* should not happen */
-       else
-               score = src_copied * MAX_SCORE / max_size;
+       else {
+               score = (int)(src_copied * MAX_SCORE / max_size);
+               if (basename_same(src, dst))
+                       score++;
+       }
        return score;
 }
 
@@ -294,10 +313,23 @@ void diffcore_rename(struct diff_options *options)
                        if (rename_dst[i].pair)
                                continue; /* dealt with an earlier round */
                        for (j = 0; j < rename_src_nr; j++) {
+                               int k;
                                struct diff_filespec *one = rename_src[j].one;
                                if (!is_exact_match(one, two, contents_too))
                                        continue;
-                               record_rename_pair(i, j, MAX_SCORE);
+
+                               /* see if there is a basename match, too */
+                               for (k = j; k < rename_src_nr; k++) {
+                                       one = rename_src[k].one;
+                                       if (basename_same(one, two) &&
+                                               is_exact_match(one, two,
+                                                       contents_too)) {
+                                               j = k;
+                                               break;
+                                       }
+                               }
+
+                               record_rename_pair(i, j, (int)MAX_SCORE);
                                rename_count++;
                                break; /* we are done with this entry */
                        }
@@ -328,6 +360,7 @@ void diffcore_rename(struct diff_options *options)
                        m->dst = i;
                        m->score = estimate_similarity(one, two,
                                                       minimum_score);
+                       diff_free_filespec_data(one);
                }
                /* We do not need the text anymore */
                diff_free_filespec_data(two);