merge-base.con commit [PATCH] Switch implementations of merge-base, port to parsing (b5039db)
   1#include <stdlib.h>
   2#include "cache.h"
   3#include "commit.h"
   4
   5static struct commit *process_list(struct commit_list **list_p, int this_mark,
   6                                   int other_mark)
   7{
   8        struct commit_list *parent, *temp;
   9        struct commit_list *posn = *list_p;
  10        *list_p = NULL;
  11        while (posn) {
  12                parse_commit(posn->item);
  13                if (posn->item->object.flags & this_mark) {
  14                        /*
  15                          printf("%d already seen %s %x\n",
  16                          this_mark
  17                          sha1_to_hex(posn->parent->sha1),
  18                          posn->parent->flags);
  19                        */
  20                        /* do nothing; this indicates that this side
  21                         * split and reformed, and we only need to
  22                         * mark it once.
  23                         */
  24                } else if (posn->item->object.flags & other_mark) {
  25                        return posn->item;
  26                } else {
  27                        /*
  28                          printf("%d based on %s\n",
  29                          this_mark,
  30                          sha1_to_hex(posn->parent->sha1));
  31                        */
  32                        posn->item->object.flags |= this_mark;
  33                        
  34                        parent = posn->item->parents;
  35                        while (parent) {
  36                                temp = malloc(sizeof(struct commit_list));
  37                                temp->next = *list_p;
  38                                temp->item = parent->item;
  39                                *list_p = temp;
  40                                parent = parent->next;
  41                        }
  42                }
  43                posn = posn->next;
  44        }
  45        return NULL;
  46}
  47
  48struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
  49{
  50        struct commit_list *rev1list = malloc(sizeof(struct commit_list));
  51        struct commit_list *rev2list = malloc(sizeof(struct commit_list));
  52
  53        rev1list->item = rev1;
  54        rev1list->next = NULL;
  55
  56        rev2list->item = rev2;
  57        rev2list->next = NULL;
  58
  59        while (rev1list || rev2list) {
  60                struct commit *ret;
  61                ret = process_list(&rev1list, 0x1, 0x2);
  62                if (ret) {
  63                        /* XXXX free lists */
  64                        return ret;
  65                }
  66                ret = process_list(&rev2list, 0x2, 0x1);
  67                if (ret) {
  68                        /* XXXX free lists */
  69                        return ret;
  70                }
  71        }
  72        return NULL;
  73}
  74
  75int main(int argc, char **argv)
  76{
  77        struct commit *rev1, *rev2, *ret;
  78        unsigned char rev1key[20], rev2key[20];
  79
  80        if (argc != 3 ||
  81            get_sha1_hex(argv[1], rev1key) ||
  82            get_sha1_hex(argv[2], rev2key)) {
  83                usage("merge-base <commit-id> <commit-id>");
  84        }
  85        rev1 = lookup_commit(rev1key);
  86        rev2 = lookup_commit(rev2key);
  87        ret = common_ancestor(rev1, rev2);
  88        if (ret) {
  89                printf("%s\n", sha1_to_hex(ret->object.sha1));
  90                return 0;
  91        } else {
  92                return 1;
  93        }
  94        
  95}