DORMANTno replies

[PATCH 6/6] Teach "git-merge-base --check-ancestry" about refs.

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:48
Subsystem: documentation, the rest · Maintainers: Jonathan Corbet, Linus Torvalds

"git-merge-base --all -c $commit" is used to see if $commit is
reachable from any ref.

Signed-off-by: Junio C Hamano <redacted>
---
 Documentation/git-merge-base.txt |    6 ++++-
 builtin-merge-base.c             |   45 ++++++++++++++++++++++++++++++++-----
 2 files changed, 44 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt
index 7d4d027..21b5dd3 100644
--- a/Documentation/git-merge-base.txt
+++ b/Documentation/git-merge-base.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git-merge-base' [--all] <commit> <commit>
-'git-merge-base' --check-ancestry <commit> <commit>...
+'git-merge-base' [--all] --check-ancestry <commit> <commit>...
 
 DESCRIPTION
 -----------
@@ -33,6 +33,10 @@ OPTIONS
 --all::
 	Output all common ancestors for the two commits instead of
 	just one.
++
+When used with `--check-ancestry` option, this uses all the
+commits that are at the tip of all refs to see if the given
+commit is an ancestor of any of them.
 
 --check-ancestry::
 
diff --git a/builtin-merge-base.c b/builtin-merge-base.c
index fa07352..eeb8763 100644
--- a/builtin-merge-base.c
+++ b/builtin-merge-base.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "commit.h"
+#include "refs.h"
 
 static const char merge_base_usage[] =
 "git-merge-base [--all] <commit> <commit> | --check-ancestry <commit> <commit>...";
@@ -21,13 +22,42 @@ static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_al
 	return 0;
 }
 
-static int check_ancestry(int argc, const char **argv)
+struct add_one_ref_cb {
+	struct commit ***reference;
+	int n;
+};
+
+static int add_one_ref(const char *name, const unsigned char *sha1, int flags, void *cb_data)
+{
+	struct add_one_ref_cb *cb = (struct add_one_ref_cb *) cb_data;
+	struct commit *commit = lookup_commit_reference_gently(sha1, 1);
+
+	if (!commit)
+		return 0;
+	cb->n++;
+	*cb->reference = xrealloc(*cb->reference,
+				  sizeof(struct commit *) * cb->n);
+	(*cb->reference)[cb->n-1] = commit;
+	return 0;
+}
+
+static int add_all_refs(struct commit ***reference, int n)
+{
+	struct add_one_ref_cb cb;
+
+	cb.reference = reference;
+	cb.n = n;
+	for_each_ref(add_one_ref, &cb);
+	return cb.n;
+}
+
+static int check_ancestry(int all, int argc, const char **argv)
 {
 	struct commit *one, *two, **reference;
 	unsigned char sha1[20];
 	int i;
 
-	if (argc < 2)
+	if (argc < 1 || (!all && argc < 2))
 		usage(merge_base_usage);
 	if (get_sha1(argv[0], sha1))
 		die("Not a valid object name %s", argv[0]);
@@ -44,7 +74,12 @@ static int check_ancestry(int argc, const char **argv)
 			return 1;
 		reference[i - 1] = two;
 	}
-	return !!in_merge_bases(one, reference, argc - 1);
+	i = argc - 1;
+
+	if (all)
+		i = add_all_refs(&reference, i);
+
+	return !in_merge_bases(one, reference, i);
 }
 
 int cmd_merge_base(int argc, const char **argv, const char *prefix)
@@ -68,9 +103,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
 	}
 
 	if (check) {
-		if (show_all)
-			die("--all and --check-ancestry are mutually incompatible");
-		return check_ancestry(argc - 1, argv + 1);
+		return check_ancestry(show_all, argc - 1, argv + 1);
 	}
 
 	if (argc != 3)
-- 
1.4.4.4.g564d
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help