X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=diffcore-rename.c;h=57a74b6bb83e14af5f7336f397f79fbfcdc8b5f7;hb=747fa12cef73b6ca04fffaddaad7326cf546cdea;hp=e99269872026c7f08e729acb6ffba7ef3c9c8fd8;hpb=f0c979f4dbbb7d6d9565d945c540f0a5748f1b80;p=git.git diff --git a/diffcore-rename.c b/diffcore-rename.c index e99269872..57a74b6bb 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -54,12 +54,14 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two, /* Table of rename/copy src files */ static struct diff_rename_src { struct diff_filespec *one; + unsigned short score; /* to remember the break score */ unsigned src_path_left : 1; } *rename_src; static int rename_src_nr, rename_src_alloc; static struct diff_rename_src *register_rename_src(struct diff_filespec *one, - int src_path_left) + int src_path_left, + unsigned short score) { int first, last; @@ -89,15 +91,20 @@ static struct diff_rename_src *register_rename_src(struct diff_filespec *one, memmove(rename_src + first + 1, rename_src + first, (rename_src_nr - first - 1) * sizeof(*rename_src)); rename_src[first].one = one; + rename_src[first].score = score; rename_src[first].src_path_left = src_path_left; return &(rename_src[first]); } -static int is_exact_match(struct diff_filespec *src, struct diff_filespec *dst) +static int is_exact_match(struct diff_filespec *src, + struct diff_filespec *dst, + int contents_too) { if (src->sha1_valid && dst->sha1_valid && - !memcmp(src->sha1, dst->sha1, 20)) + !hashcmp(src->sha1, dst->sha1)) return 1; + if (!contents_too) + return 0; if (diff_populate_filespec(src, 1) || diff_populate_filespec(dst, 1)) return 0; if (src->size != dst->size) @@ -198,7 +205,11 @@ static void record_rename_pair(int dst_index, int src_index, int score) fill_filespec(two, dst->sha1, dst->mode); dp = diff_queue(NULL, one, two); - dp->score = score; + dp->renamed_pair = 1; + if (!strcmp(src->path, dst->path)) + dp->score = rename_src[src_index].score; + else + dp->score = score; dp->source_stays = rename_src[src_index].src_path_left; rename_dst[dst_index].pair = dp; } @@ -236,7 +247,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, contents_too; int num_create, num_src, dst_cnt; if (!minimum_score) @@ -245,21 +256,25 @@ void diffcore_rename(struct diff_options *options) for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; - if (!DIFF_FILE_VALID(p->one)) + if (!DIFF_FILE_VALID(p->one)) { if (!DIFF_FILE_VALID(p->two)) continue; /* unmerged */ + else if (options->single_follow && + strcmp(options->single_follow, p->two->path)) + continue; /* not interested */ else locate_rename_dst(p->two, 1); + } else if (!DIFF_FILE_VALID(p->two)) { /* If the source is a broken "delete", and * they did not really want to get broken, * that means the source actually stays. */ int stays = (p->broken_pair && !p->score); - register_rename_src(p->one, stays); + register_rename_src(p->one, stays, p->score); } else if (detect_rename == DIFF_DETECT_COPY) - register_rename_src(p->one, 1); + register_rename_src(p->one, 1, p->score); } if (rename_dst_nr == 0 || rename_src_nr == 0 || (0 < rename_limit && rename_limit < rename_dst_nr)) @@ -267,16 +282,23 @@ void diffcore_rename(struct diff_options *options) /* We really want to cull the candidates list early * with cheap tests in order to avoid doing deltas. + * The first round matches up the up-to-date entries, + * and then during the second round we try to match + * cache-dirty entries as well. */ - for (i = 0; i < rename_dst_nr; i++) { - struct diff_filespec *two = rename_dst[i].two; - for (j = 0; j < rename_src_nr; j++) { - struct diff_filespec *one = rename_src[j].one; - if (!is_exact_match(one, two)) - continue; - record_rename_pair(i, j, MAX_SCORE); - rename_count++; - break; /* we are done with this entry */ + for (contents_too = 0; contents_too < 2; contents_too++) { + for (i = 0; i < rename_dst_nr; i++) { + struct diff_filespec *two = rename_dst[i].two; + if (rename_dst[i].pair) + continue; /* dealt with an earlier round */ + for (j = 0; j < rename_src_nr; j++) { + struct diff_filespec *one = rename_src[j].one; + if (!is_exact_match(one, two, contents_too)) + continue; + record_rename_pair(i, j, MAX_SCORE); + rename_count++; + break; /* we are done with this entry */ + } } }