merge-base.con commit git-rev-parse: split "revs" and "non-revs" (8ebb018)
   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 *item = (*list_p)->item;
   9
  10        if (item->object.flags & other_mark) {
  11                return item;
  12        } else {
  13                pop_most_recent_commit(list_p, this_mark);
  14        }
  15        return NULL;
  16}
  17
  18static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
  19{
  20        struct commit_list *rev1list = NULL;
  21        struct commit_list *rev2list = NULL;
  22
  23        commit_list_insert(rev1, &rev1list);
  24        rev1->object.flags |= 0x1;
  25        commit_list_insert(rev2, &rev2list);
  26        rev2->object.flags |= 0x2;
  27
  28        parse_commit(rev1);
  29        parse_commit(rev2);
  30
  31        while (rev1list || rev2list) {
  32                struct commit *ret;
  33                if (!rev1list) {
  34                        // process 2
  35                        ret = process_list(&rev2list, 0x2, 0x1);
  36                } else if (!rev2list) {
  37                        // process 1
  38                        ret = process_list(&rev1list, 0x1, 0x2);
  39                } else if (rev1list->item->date < rev2list->item->date) {
  40                        // process 2
  41                        ret = process_list(&rev2list, 0x2, 0x1);
  42                } else {
  43                        // process 1
  44                        ret = process_list(&rev1list, 0x1, 0x2);
  45                }
  46                if (ret) {
  47                        free_commit_list(rev1list);
  48                        free_commit_list(rev2list);
  49                        return ret;
  50                }
  51        }
  52        return NULL;
  53}
  54
  55int main(int argc, char **argv)
  56{
  57        struct commit *rev1, *rev2, *ret;
  58        unsigned char rev1key[20], rev2key[20];
  59
  60        if (argc != 3 ||
  61            get_sha1(argv[1], rev1key) ||
  62            get_sha1(argv[2], rev2key)) {
  63                usage("git-merge-base <commit-id> <commit-id>");
  64        }
  65        rev1 = lookup_commit_reference(rev1key);
  66        rev2 = lookup_commit_reference(rev2key);
  67        ret = common_ancestor(rev1, rev2);
  68        if (!ret)
  69                return 1;
  70        printf("%s\n", sha1_to_hex(ret->object.sha1));
  71        return 0;
  72}