diff options
Diffstat (limited to 'merge-base.c')
-rw-r--r-- | merge-base.c | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/merge-base.c b/merge-base.c index 4856ca01c3..7d87c20b75 100644 --- a/merge-base.c +++ b/merge-base.c @@ -124,8 +124,6 @@ static struct commit *interesting(struct commit_list *list) * to contaminate D and E. */ -static int show_all = 0; - static void mark_reachable_commits(struct commit_list *result, struct commit_list *list) { @@ -167,34 +165,33 @@ static void mark_reachable_commits(struct commit_list *result, } } -static int merge_base(struct commit *rev1, struct commit *rev2) +struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2) { struct commit_list *list = NULL; struct commit_list *result = NULL; struct commit_list *tmp = NULL; - if (rev1 == rev2) { - printf("%s\n", sha1_to_hex(rev1->object.sha1)); - return 0; - } + if (rev1 == rev2) + return commit_list_insert(rev1, &result); parse_commit(rev1); parse_commit(rev2); - rev1->object.flags |= 1; - rev2->object.flags |= 2; + rev1->object.flags |= PARENT1; + rev2->object.flags |= PARENT2; insert_by_date(rev1, &list); insert_by_date(rev2, &list); while (interesting(list)) { struct commit *commit = list->item; struct commit_list *parents; - int flags = commit->object.flags & 7; + int flags = commit->object.flags + & (PARENT1 | PARENT2 | UNINTERESTING); tmp = list; list = list->next; free(tmp); - if (flags == 3) { + if (flags == (PARENT1 | PARENT2)) { insert_by_date(commit, &result); /* Mark parents of a found merge uninteresting */ @@ -213,21 +210,52 @@ static int merge_base(struct commit *rev1, struct commit *rev2) } if (!result) - return 1; + return NULL; if (result->next && list) mark_reachable_commits(result, list); + /* cull duplicates */ + for (tmp = result, list = NULL; tmp; ) { + struct commit *commit = tmp->item; + struct commit_list *next = tmp->next; + if (commit->object.flags & UNINTERESTING) { + if (list != NULL) + list->next = next; + free(tmp); + } else { + if (list == NULL) + result = tmp; + list = tmp; + commit->object.flags |= UNINTERESTING; + } + + tmp = next; + } + + /* reset flags */ + clear_commit_marks(rev1, PARENT1 | PARENT2 | UNINTERESTING); + clear_commit_marks(rev2, PARENT1 | PARENT2 | UNINTERESTING); + + return result; +} + +static int show_all = 0; + +static int merge_base(struct commit *rev1, struct commit *rev2) +{ + struct commit_list *result = get_merge_bases(rev1, rev2); + + if (!result) + return 1; + while (result) { - struct commit *commit = result->item; - result = result->next; - if (commit->object.flags & UNINTERESTING) - continue; - printf("%s\n", sha1_to_hex(commit->object.sha1)); + printf("%s\n", sha1_to_hex(result->item->object.sha1)); if (!show_all) return 0; - commit->object.flags |= UNINTERESTING; + result = result->next; } + return 0; } |