]> git.ipfire.org Git - thirdparty/git.git/commitdiff
diff-lib: define diff_get_merge_base()
authorDenton Liu <liu.denton@gmail.com>
Sun, 20 Sep 2020 11:22:23 +0000 (04:22 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 21 Sep 2020 04:30:26 +0000 (21:30 -0700)
In a future commit, we will be using this function to implement
--merge-base functionality in various diff commands.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff-lib.c
diff.h

index ed720853ede3e2c1e9f2b1a6ce3a1b9a00ff8c9f..468e3fe854aa605b5826b8b4a73a40ecb467d1c9 100644 (file)
@@ -13,6 +13,7 @@
 #include "submodule.h"
 #include "dir.h"
 #include "fsmonitor.h"
+#include "commit-reach.h"
 
 /*
  * diff-files
@@ -512,6 +513,50 @@ static int diff_cache(struct rev_info *revs,
        return unpack_trees(1, &t, &opts);
 }
 
+void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb)
+{
+       int i;
+       struct commit *mb_child[2] = {0};
+       struct commit_list *merge_bases;
+
+       for (i = 0; i < revs->pending.nr; i++) {
+               struct object *obj = revs->pending.objects[i].item;
+               if (obj->flags)
+                       die(_("--merge-base does not work with ranges"));
+               if (obj->type != OBJ_COMMIT)
+                       die(_("--merge-base only works with commits"));
+       }
+
+       /*
+        * This check must go after the for loop above because A...B
+        * ranges produce three pending commits, resulting in a
+        * misleading error message.
+        */
+       if (revs->pending.nr < 1 || revs->pending.nr > 2)
+               BUG("unexpected revs->pending.nr: %d", revs->pending.nr);
+
+       for (i = 0; i < revs->pending.nr; i++)
+               mb_child[i] = lookup_commit_reference(the_repository, &revs->pending.objects[i].item->oid);
+       if (revs->pending.nr == 1) {
+               struct object_id oid;
+
+               if (get_oid("HEAD", &oid))
+                       die(_("unable to get HEAD"));
+
+               mb_child[1] = lookup_commit_reference(the_repository, &oid);
+       }
+
+       merge_bases = repo_get_merge_bases(the_repository, mb_child[0], mb_child[1]);
+       if (!merge_bases)
+               die(_("no merge base found"));
+       if (merge_bases->next)
+               die(_("multiple merge bases found"));
+
+       oidcpy(mb, &merge_bases->item->object.oid);
+
+       free_commit_list(merge_bases);
+}
+
 int run_diff_index(struct rev_info *revs, unsigned int option)
 {
        struct object_array_entry *ent;
diff --git a/diff.h b/diff.h
index aea0d5b96beca8adeb365c30bf4cf410a9d39be4..fedfeab7a2615e90d3ecacb0ad194514fa9093ec 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -580,6 +580,8 @@ void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc);
  */
 const char *diff_aligned_abbrev(const struct object_id *sha1, int);
 
+void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb);
+
 /* do not report anything on removed paths */
 #define DIFF_SILENT_ON_REMOVED 01
 /* report racily-clean paths as modified */