DORMANTno replies

[PATCH 3/6] git-merge-base: --check-ancestry option

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

A new option drives underlying in_merge_bases() function to
determine if a commit is reachable from any of the other commits
supplied on the command line.

Signed-off-by: Junio C Hamano <redacted>
---
 Documentation/git-merge-base.txt |   13 +++++++++++-
 merge-base.c                     |   39 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt
index 6099be2..7d4d027 100644
--- a/Documentation/git-merge-base.txt
+++ b/Documentation/git-merge-base.txt
@@ -8,7 +8,9 @@ git-merge-base - Finds as good a common ancestor as possible for a merge
 
 SYNOPSIS
 --------
+[verse]
 'git-merge-base' [--all] <commit> <commit>
+'git-merge-base' --check-ancestry <commit> <commit>...
 
 DESCRIPTION
 -----------
@@ -21,7 +23,10 @@ the parent relationship.
 Given a selection of equally good common ancestors it should not be
 relied on to decide in any particular way.
 
-The "git-merge-base" algorithm is still in flux - use the source...
+With `--check-ancestry` option, the command can be used to check
+if the first commit is an ancestor of any of the remaining
+commits.
+
 
 OPTIONS
 -------
@@ -29,6 +34,12 @@ OPTIONS
 	Output all common ancestors for the two commits instead of
 	just one.
 
+--check-ancestry::
+
+	Check if the first commit is an ancestor of any of the
+	remaining commits.  If so, exit with status 0, otherwise
+	non-zero.
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>
diff --git a/merge-base.c b/merge-base.c
index 385f4ba..bc478eb 100644
--- a/merge-base.c
+++ b/merge-base.c
@@ -2,6 +2,8 @@
 #include "commit.h"
 
 static int show_all;
+static const char merge_base_usage[] =
+"git-merge-base [--all] <commit> <commit> | --check-ancestry <commit> <commit>...";
 
 static int merge_base(struct commit *rev1, struct commit *rev2)
 {
@@ -20,13 +22,37 @@ static int merge_base(struct commit *rev1, struct commit *rev2)
 	return 0;
 }
 
-static const char merge_base_usage[] =
-"git-merge-base [--all] <commit-id> <commit-id>";
+static int check_ancestry(int argc, char **argv)
+{
+	struct commit *one, *two, **reference;
+	unsigned char sha1[20];
+	int i;
+
+	if (argc < 2)
+		usage(merge_base_usage);
+	if (get_sha1(argv[0], sha1))
+		die("Not a valid object name %s", argv[0]);
+	one = lookup_commit_reference(sha1);
+	if (!one)
+		return 1;
+
+	reference = xcalloc(argc - 1, sizeof(struct commit *));
+	for (i = 1; i < argc; i++) {
+		if (get_sha1(argv[i], sha1))
+			die("Not a valid object name %s", argv[i]);
+		two = lookup_commit_reference(sha1);
+		if (!two)
+			return 1;
+		reference[i - 1] = two;
+	}
+	return !!in_merge_bases(one, reference, argc - 1);
+}
 
 int main(int argc, char **argv)
 {
 	struct commit *rev1, *rev2;
 	unsigned char rev1key[20], rev2key[20];
+	int check = 0;
 
 	setup_git_directory();
 	git_config(git_default_config);
@@ -35,10 +61,19 @@ int main(int argc, char **argv)
 		char *arg = argv[1];
 		if (!strcmp(arg, "-a") || !strcmp(arg, "--all"))
 			show_all = 1;
+		else if (!strcmp(arg, "-c") || !strcmp(arg, "--check-ancestry"))
+			check = 1;
 		else
 			usage(merge_base_usage);
 		argc--; argv++;
 	}
+
+	if (check) {
+		if (show_all)
+			die("--all and --check-ancestry are mutually incompatible");
+		return check_ancestry(argc - 1, argv + 1);
+	}
+
 	if (argc != 3)
 		usage(merge_base_usage);
 	if (get_sha1(argv[1], rev1key))
-- 
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