From 74a627f04528f7e02f69d8d7947820582ce7ca15 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 21 Oct 2013 09:07:19 -0700 Subject: [PATCH] Tweak to git_diff_delta structure for nfiles While the base git_diff_delta structure always contains two files, when we introduce conflict data, it will be helpful to have an indicator when an additional file is involved. --- include/git2/diff.h | 5 +++-- src/diff.c | 2 ++ src/diff_tform.c | 47 ++++++++++++++++++++++++++------------------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index fd79ccf04..f1572cbd5 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -292,8 +292,9 @@ typedef struct { */ typedef struct { git_delta_t status; - uint32_t similarity; /**< for RENAMED and COPIED, value 0-100 */ - uint32_t flags; + uint32_t flags; /**< git_diff_flag_t values */ + uint16_t similarity; /**< for RENAMED and COPIED, value 0-100 */ + uint16_t nfiles; /**< number of files in this delta */ git_diff_file old_file; git_diff_file new_file; } git_diff_delta; diff --git a/src/diff.c b/src/diff.c index 8dc704d58..37bc737d6 100644 --- a/src/diff.c +++ b/src/diff.c @@ -90,6 +90,7 @@ static int diff_delta__from_one( /* This fn is just for single-sided diffs */ assert(status != GIT_DELTA_MODIFIED); + delta->nfiles = 1; if (delta->status == GIT_DELTA_DELETED) { delta->old_file.mode = entry->mode; @@ -148,6 +149,7 @@ static int diff_delta__from_two( delta = diff_delta__alloc(diff, status, canonical_path); GITERR_CHECK_ALLOC(delta); + delta->nfiles = 2; git_oid_cpy(&delta->old_file.oid, &old_entry->oid); delta->old_file.size = old_entry->file_size; diff --git a/src/diff_tform.c b/src/diff_tform.c index 92771847c..9461ca2c8 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -350,6 +350,7 @@ static int apply_splits_and_deletes( goto on_error; deleted->status = GIT_DELTA_DELETED; + deleted->nfiles = 1; memset(&deleted->new_file, 0, sizeof(deleted->new_file)); deleted->new_file.path = deleted->old_file.path; deleted->new_file.flags |= GIT_DIFF_FLAG_VALID_OID; @@ -361,6 +362,7 @@ static int apply_splits_and_deletes( delta->status = GIT_DELTA_UNTRACKED; else delta->status = GIT_DELTA_ADDED; + delta->nfiles = 1; memset(&delta->old_file, 0, sizeof(delta->old_file)); delta->old_file.path = delta->new_file.path; delta->old_file.flags |= GIT_DIFF_FLAG_VALID_OID; @@ -612,7 +614,7 @@ static int calc_self_similarity( return error; if (similarity >= 0) { - delta->similarity = (uint32_t)similarity; + delta->similarity = (uint16_t)similarity; delta->flags |= GIT_DIFF_FLAG__HAS_SELF_SIMILARITY; } @@ -745,17 +747,18 @@ GIT_INLINE(bool) delta_is_new_only(git_diff_delta *delta) } GIT_INLINE(void) delta_make_rename( - git_diff_delta *to, const git_diff_delta *from, uint32_t similarity) + git_diff_delta *to, const git_diff_delta *from, uint16_t similarity) { to->status = GIT_DELTA_RENAMED; to->similarity = similarity; + to->nfiles = 2; memcpy(&to->old_file, &from->old_file, sizeof(to->old_file)); to->flags &= ~GIT_DIFF_FLAG__TO_SPLIT; } typedef struct { - uint32_t idx; - uint32_t similarity; + size_t idx; + uint16_t similarity; } diff_find_match; int git_diff_find_similar( @@ -763,7 +766,8 @@ int git_diff_find_similar( const git_diff_find_options *given_opts) { size_t s, t; - int error = 0, similarity; + int error = 0, result; + uint16_t similarity; git_diff_delta *src, *tgt; git_diff_find_options opts; size_t num_deltas, num_srcs = 0, num_tgts = 0; @@ -839,17 +843,18 @@ find_best_matches: /* calculate similarity for this pair and find best match */ if (s == t) - similarity = -1; /* don't measure self-similarity here */ + result = -1; /* don't measure self-similarity here */ else if ((error = similarity_measure( - &similarity, diff, &opts, sigcache, 2 * s, 2 * t + 1)) < 0) + &result, diff, &opts, sigcache, 2 * s, 2 * t + 1)) < 0) goto cleanup; - if (similarity < 0) + if (result < 0) continue; + similarity = (uint16_t)result; /* is this a better rename? */ - if (tgt2src[t].similarity < (uint32_t)similarity && - src2tgt[s].similarity < (uint32_t)similarity) + if (tgt2src[t].similarity < similarity && + src2tgt[s].similarity < similarity) { /* eject old mapping */ if (src2tgt[s].similarity > 0) { @@ -862,18 +867,18 @@ find_best_matches: } /* write new mapping */ - tgt2src[t].idx = (uint32_t)s; - tgt2src[t].similarity = (uint32_t)similarity; - src2tgt[s].idx = (uint32_t)t; - src2tgt[s].similarity = (uint32_t)similarity; + tgt2src[t].idx = s; + tgt2src[t].similarity = similarity; + src2tgt[s].idx = t; + src2tgt[s].similarity = similarity; } /* keep best absolute match for copies */ if (tgt2src_copy != NULL && - tgt2src_copy[t].similarity < (uint32_t)similarity) + tgt2src_copy[t].similarity < similarity) { - tgt2src_copy[t].idx = (uint32_t)s; - tgt2src_copy[t].similarity = (uint32_t)similarity; + tgt2src_copy[t].idx = s; + tgt2src_copy[t].similarity = similarity; } if (++tried_srcs >= num_srcs) @@ -943,7 +948,7 @@ find_best_matches: delta_make_rename(tgt, src, best_match->similarity); num_rewrites--; - src->status = GIT_DELTA_DELETED; + assert(src->status == GIT_DELTA_DELETED); memcpy(&src->old_file, &swap, sizeof(src->old_file)); memset(&src->new_file, 0, sizeof(src->new_file)); src->new_file.path = src->old_file.path; @@ -953,7 +958,7 @@ find_best_matches: if (src2tgt[t].similarity > 0 && src2tgt[t].idx > t) { /* what used to be at src t is now at src s */ - tgt2src[src2tgt[t].idx].idx = (uint32_t)s; + tgt2src[src2tgt[t].idx].idx = s; } } } @@ -969,6 +974,7 @@ find_best_matches: src->status = (diff->new_src == GIT_ITERATOR_TYPE_WORKDIR) ? GIT_DELTA_UNTRACKED : GIT_DELTA_ADDED; + src->nfiles = 1; memset(&src->old_file, 0, sizeof(src->old_file)); src->old_file.path = src->new_file.path; src->old_file.flags |= GIT_DIFF_FLAG_VALID_OID; @@ -1006,7 +1012,7 @@ find_best_matches: /* otherwise, if we just overwrote a source, update mapping */ else if (src2tgt[t].similarity > 0 && src2tgt[t].idx > t) { /* what used to be at src t is now at src s */ - tgt2src[src2tgt[t].idx].idx = (uint32_t)s; + tgt2src[src2tgt[t].idx].idx = s; } num_updates++; @@ -1026,6 +1032,7 @@ find_best_matches: tgt->status = GIT_DELTA_COPIED; tgt->similarity = best_match->similarity; + tgt->nfiles = 2; memcpy(&tgt->old_file, &src->old_file, sizeof(tgt->old_file)); num_updates++;