1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-30 07:56:11 +02:00
git/builtin/merge-base.c
Junio C Hamano 8f29299136 merge-base --octopus: reduce the result from get_octopus_merge_bases()
Scripts that use "merge-base --octopus" could do the reducing
themselves, but most of them are expected to want to get the reduced
results without having to do any work themselves.

Tests are taken from a message by Василий Макаров
<einmalfel@gmail.com>

Signed-off-by: Junio C Hamano <gitster@pobox.com>

---

 We might want to vet the existing callers of the underlying
 get_octopus_merge_bases() and find out if _all_ of them are doing
 anything extra (like deduping) because the machinery can return
 duplicate results. And if that is the case, then we may want to
 move the dedupling down the callchain instead of having it here.
2013-12-30 11:58:54 -08:00

144 lines
3.4 KiB
C

#include "builtin.h"
#include "cache.h"
#include "commit.h"
#include "parse-options.h"
static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
{
struct commit_list *result;
result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1, 0);
if (!result)
return 1;
while (result) {
printf("%s\n", sha1_to_hex(result->item->object.sha1));
if (!show_all)
return 0;
result = result->next;
}
return 0;
}
static const char * const merge_base_usage[] = {
N_("git merge-base [-a|--all] <commit> <commit>..."),
N_("git merge-base [-a|--all] --octopus <commit>..."),
N_("git merge-base --independent <commit>..."),
N_("git merge-base --is-ancestor <commit> <commit>"),
NULL
};
static struct commit *get_commit_reference(const char *arg)
{
unsigned char revkey[20];
struct commit *r;
if (get_sha1(arg, revkey))
die("Not a valid object name %s", arg);
r = lookup_commit_reference(revkey);
if (!r)
die("Not a valid commit name %s", arg);
return r;
}
static int handle_independent(int count, const char **args)
{
struct commit_list *revs = NULL;
struct commit_list *result;
int i;
for (i = count - 1; i >= 0; i--)
commit_list_insert(get_commit_reference(args[i]), &revs);
result = reduce_heads(revs);
if (!result)
return 1;
while (result) {
printf("%s\n", sha1_to_hex(result->item->object.sha1));
result = result->next;
}
return 0;
}
static int handle_octopus(int count, const char **args, int show_all)
{
struct commit_list *revs = NULL;
struct commit_list *result;
int i;
for (i = count - 1; i >= 0; i--)
commit_list_insert(get_commit_reference(args[i]), &revs);
result = reduce_heads(get_octopus_merge_bases(revs));
if (!result)
return 1;
while (result) {
printf("%s\n", sha1_to_hex(result->item->object.sha1));
if (!show_all)
return 0;
result = result->next;
}
return 0;
}
static int handle_is_ancestor(int argc, const char **argv)
{
struct commit *one, *two;
if (argc != 2)
die("--is-ancestor takes exactly two commits");
one = get_commit_reference(argv[0]);
two = get_commit_reference(argv[1]);
if (in_merge_bases(one, two))
return 0;
else
return 1;
}
int cmd_merge_base(int argc, const char **argv, const char *prefix)
{
struct commit **rev;
int rev_nr = 0;
int show_all = 0;
int octopus = 0;
int reduce = 0;
int is_ancestor = 0;
struct option options[] = {
OPT_BOOLEAN('a', "all", &show_all, N_("output all common ancestors")),
OPT_BOOLEAN(0, "octopus", &octopus, N_("find ancestors for a single n-way merge")),
OPT_BOOLEAN(0, "independent", &reduce, N_("list revs not reachable from others")),
OPT_BOOLEAN(0, "is-ancestor", &is_ancestor,
N_("is the first one ancestor of the other?")),
OPT_END()
};
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
if (!octopus && !reduce && argc < 2)
usage_with_options(merge_base_usage, options);
if (is_ancestor && (show_all || octopus || reduce))
die("--is-ancestor cannot be used with other options");
if (is_ancestor)
return handle_is_ancestor(argc, argv);
if (reduce && (show_all || octopus))
die("--independent cannot be used with other options");
if (octopus)
return handle_octopus(argc, argv, show_all);
else if (reduce)
return handle_independent(argc, argv);
rev = xmalloc(argc * sizeof(*rev));
while (argc-- > 0)
rev[rev_nr++] = get_commit_reference(*argv++);
return show_merge_base(rev, rev_nr, show_all);
}