Commit 74a627f04528f7e02f69d8d7947820582ce7ca15

Russell Belfer 2013-10-21T09:07:19

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.

diff --git a/include/git2/diff.h b/include/git2/diff.h
index fd79ccf..f1572cb 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 8dc704d..37bc737 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 9277184..9461ca2 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++;