]> git.ipfire.org Git - thirdparty/git.git/commitdiff
merge-ort: avoid repeating fill_tree_descriptor() on the same tree
authorElijah Newren <newren@gmail.com>
Sun, 13 Dec 2020 08:04:14 +0000 (08:04 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sun, 13 Dec 2020 22:18:20 +0000 (14:18 -0800)
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>
merge-ort.c

index 4a2c7de6e8ee1bb79b7784e310c97eeddc036a91..690c64fe264f0b2420a9a5d34033670f133e7f20 100644 (file)
@@ -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;
                }