summaryrefslogtreecommitdiff
path: root/merge-ort.c
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2020-12-13 08:04:14 (GMT)
committerJunio C Hamano <gitster@pobox.com>2020-12-13 22:18:20 (GMT)
commit885f0063e9962068d381ca5256ca49070bb2480c (patch)
tree35056ec899a130d8d8bc796ffa432f185273ba53 /merge-ort.c
parentd2bc1994f363ac2049da0cdd0b8a7bed61eeaab0 (diff)
downloadgit-885f0063e9962068d381ca5256ca49070bb2480c.zip
git-885f0063e9962068d381ca5256ca49070bb2480c.tar.gz
git-885f0063e9962068d381ca5256ca49070bb2480c.tar.bz2
merge-ort: avoid repeating fill_tree_descriptor() on the same tree
Three-way merges, by their nature, are going to often have two or more trees match at a given subdirectory. We can avoid calling fill_tree_descriptor() on the same tree by checking when these trees match. Noting when various oids match will also be useful in other calculations and optimizations as well. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'merge-ort.c')
-rw-r--r--merge-ort.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/merge-ort.c b/merge-ort.c
index 4a2c7de..690c64f 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -223,6 +223,15 @@ static int collect_merge_info_callback(int n,
unsigned mbase_null = !(mask & 1);
unsigned side1_null = !(mask & 2);
unsigned side2_null = !(mask & 4);
+ unsigned side1_matches_mbase = (!side1_null && !mbase_null &&
+ names[0].mode == names[1].mode &&
+ oideq(&names[0].oid, &names[1].oid));
+ unsigned side2_matches_mbase = (!side2_null && !mbase_null &&
+ names[0].mode == names[2].mode &&
+ oideq(&names[0].oid, &names[2].oid));
+ unsigned sides_match = (!side1_null && !side2_null &&
+ names[1].mode == names[2].mode &&
+ oideq(&names[1].oid, &names[2].oid));
/* n = 3 is a fundamental assumption. */
if (n != 3)
@@ -275,10 +284,19 @@ static int collect_merge_info_callback(int n,
newinfo.pathlen = st_add3(newinfo.pathlen, p->pathlen, 1);
for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) {
- const struct object_id *oid = NULL;
- if (dirmask & 1)
- oid = &names[i].oid;
- buf[i] = fill_tree_descriptor(opt->repo, t + i, oid);
+ if (i == 1 && side1_matches_mbase)
+ t[1] = t[0];
+ else if (i == 2 && side2_matches_mbase)
+ t[2] = t[0];
+ else if (i == 2 && sides_match)
+ t[2] = t[1];
+ else {
+ const struct object_id *oid = NULL;
+ if (dirmask & 1)
+ oid = &names[i].oid;
+ buf[i] = fill_tree_descriptor(opt->repo,
+ t + i, oid);
+ }
dirmask >>= 1;
}