refactor merge_bases() as preparation to libify merge-base
authorJohannes Schindelin <Johannes.Schindelin@gmx.de>
Thu, 29 Jun 2006 13:16:46 +0000 (15:16 +0200)
committerJunio C Hamano <junkio@cox.net>
Thu, 29 Jun 2006 20:50:46 +0000 (13:50 -0700)
Signed-off-by: Junio C Hamano <junkio@cox.net>
merge-base.c

index 4856ca01c33896843c366f3fb5edadd2ea3ced37..7d87c20b7520fbf2af6071e3965f350edf77ee49 100644 (file)
@@ -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;
 }