diff options
author | Junio C Hamano <gitster@pobox.com> | 2014-10-30 12:50:03 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-10-30 12:51:10 -0700 |
commit | 21912d8f23aca75ef9b6a5a3f5d937ef96ea7c68 (patch) | |
tree | 66663db9c89d5c5f872aee7c4f66827751a9a308 | |
parent | 2ce406ccb85c4546b6d19309a6101b37c7bd952e (diff) | |
download | git-jc/first-parent-merge-bases.tar.gz |
-rw-r--r-- | builtin/merge-base.c | 16 | ||||
-rw-r--r-- | commit.c | 36 | ||||
-rw-r--r-- | commit.h | 1 |
3 files changed, 35 insertions, 18 deletions
diff --git a/builtin/merge-base.c b/builtin/merge-base.c index fdebef6fa1..19f77f4943 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -6,7 +6,8 @@ #include "revision.h" #include "parse-options.h" -static int show_merge_base(struct commit **rev, int rev_nr, int show_all) +static int show_merge_base(struct commit **rev, int rev_nr, + int show_all, int first_parent_only) { struct commit_list *result; @@ -208,10 +209,13 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix) struct commit **rev; int rev_nr = 0; int show_all = 0; + int first_parent_only = 0; int cmdmode = 0; struct option options[] = { OPT_BOOL('a', "all", &show_all, N_("output all common ancestors")), + OPT_BOOL(0, "first-parent", &first_parent_only, + N_("traverse first-parent chain only")), OPT_CMDMODE(0, "octopus", &cmdmode, N_("find ancestors for a single n-way merge"), 'o'), OPT_CMDMODE(0, "independent", &cmdmode, @@ -234,8 +238,12 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix) return handle_is_ancestor(argc, argv); } - if (cmdmode == 'r' && show_all) - die("--independent cannot be used with --all"); + if (cmdmode == 'r' && (show_all | first_parent_only)) + die("--independent cannot be used with --all or --first-parent"); + if (cmdmode == 'f' && (show_all | first_parent_only)) + die("--fork-point cannot be used with --all or --first-parent"); + if (cmdmode == 'o' && first_parent_only) + die("--octopus cannot be used with --first-parent"); if (cmdmode == 'o') return handle_octopus(argc, argv, show_all); @@ -255,5 +263,5 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix) rev = xmalloc(argc * sizeof(*rev)); while (argc-- > 0) rev[rev_nr++] = get_commit_reference(*argv++); - return show_merge_base(rev, rev_nr, show_all); + return show_merge_base(rev, rev_nr, show_all, first_parent_only); } @@ -783,7 +783,7 @@ static struct commit *interesting(struct commit_list *list) } /* all input commits in one and twos[] must have been parsed! */ -static struct commit_list *paint_down_to_common(struct commit *one, int n, struct commit **twos) +static struct commit_list *paint_down_to_common(struct commit *one, int n, struct commit **twos, int first_parent_only) { struct commit_list *list = NULL; struct commit_list *result = NULL; @@ -821,7 +821,7 @@ static struct commit_list *paint_down_to_common(struct commit *one, int n, struc parents = commit->parents; while (parents) { struct commit *p = parents->item; - parents = parents->next; + parents = first_parent_only ? NULL : parents->next; if ((p->object.flags & flags) == flags) continue; if (parse_commit(p)) @@ -835,7 +835,7 @@ static struct commit_list *paint_down_to_common(struct commit *one, int n, struc return result; } -static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos) +static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos, int first_parent_only) { struct commit_list *list = NULL; struct commit_list *result = NULL; @@ -857,7 +857,7 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co return NULL; } - list = paint_down_to_common(one, n, twos); + list = paint_down_to_common(one, n, twos, first_parent_only); while (list) { struct commit_list *next = list->next; @@ -896,7 +896,7 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in) return ret; } -static int remove_redundant(struct commit **array, int cnt) +static int remove_redundant(struct commit **array, int cnt, int first_parent_only) { /* * Some commit in the array may be an ancestor of @@ -926,7 +926,7 @@ static int remove_redundant(struct commit **array, int cnt) filled_index[filled] = j; work[filled++] = array[j]; } - common = paint_down_to_common(array[i], filled, work); + common = paint_down_to_common(array[i], filled, work, first_parent_only); if (array[i]->object.flags & PARENT2) redundant[i] = 1; for (j = 0; j < filled; j++) @@ -955,14 +955,15 @@ static int remove_redundant(struct commit **array, int cnt) static struct commit_list *get_merge_bases_many_0(struct commit *one, int n, struct commit **twos, - int cleanup) + int cleanup, + int first_parent_only) { struct commit_list *list; struct commit **rslt; struct commit_list *result; int cnt, i; - result = merge_bases_many(one, n, twos); + result = merge_bases_many(one, n, twos, first_parent_only); for (i = 0; i < n; i++) { if (one == twos[i]) return result; @@ -990,7 +991,7 @@ static struct commit_list *get_merge_bases_many_0(struct commit *one, clear_commit_marks(one, all_flags); clear_commit_marks_many(n, twos, all_flags); - cnt = remove_redundant(rslt, cnt); + cnt = remove_redundant(rslt, cnt, first_parent_only); result = NULL; for (i = 0; i < cnt; i++) commit_list_insert_by_date(rslt[i], &result); @@ -1002,19 +1003,26 @@ struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos) { - return get_merge_bases_many_0(one, n, twos, 1); + return get_merge_bases_many_0(one, n, twos, 1, 0); } struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos) { - return get_merge_bases_many_0(one, n, twos, 0); + return get_merge_bases_many_0(one, n, twos, 0, 0); +} + +struct commit_list *get_first_parent_merge_bases_many_dirty(struct commit *one, + int n, + struct commit **twos) +{ + return get_merge_bases_many_0(one, n, twos, 0, 1); } struct commit_list *get_merge_bases(struct commit *one, struct commit *two) { - return get_merge_bases_many_0(one, 1, &two, 1); + return get_merge_bases_many_0(one, 1, &two, 1, 0); } /* @@ -1049,7 +1057,7 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit * if (parse_commit(reference[i])) return ret; - bases = paint_down_to_common(commit, nr_reference, reference); + bases = paint_down_to_common(commit, nr_reference, reference, 0); if (commit->object.flags & PARENT2) ret = 1; clear_commit_marks(commit, all_flags); @@ -1092,7 +1100,7 @@ struct commit_list *reduce_heads(struct commit_list *heads) p->item->object.flags &= ~STALE; } } - num_head = remove_redundant(array, num_head); + num_head = remove_redundant(array, num_head, 0); for (i = 0; i < num_head; i++) tail = &commit_list_insert(array[i], tail)->next; return result; @@ -229,6 +229,7 @@ extern struct commit_list *get_octopus_merge_bases(struct commit_list *in); /* To be used only when object flags after this call no longer matter */ extern struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos); +extern struct commit_list *get_first_parent_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos); /* largest positive number a signed 32-bit integer can contain */ #define INFINITE_DEPTH 0x7fffffff |