mirror of
https://github.com/git/git.git
synced 2024-05-30 07:56:11 +02:00
8f29299136
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.
144 lines
3.4 KiB
C
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);
|
|
}
|