merge-base.con commit [PATCH] Fix git-rev-parse's parent handling (ef0bd2e)
   1#include <stdlib.h>
   2#include "cache.h"
   3#include "commit.h"
   4
   5static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
   6{
   7        struct commit_list *list = NULL;
   8        struct commit_list *result = NULL;
   9
  10        if (rev1 == rev2)
  11                return rev1;
  12
  13        parse_commit(rev1);
  14        parse_commit(rev2);
  15
  16        rev1->object.flags |= 1;
  17        rev2->object.flags |= 2;
  18        insert_by_date(rev1, &list);
  19        insert_by_date(rev2, &list);
  20
  21        while (list) {
  22                struct commit *commit = list->item;
  23                struct commit_list *tmp = list, *parents;
  24                int flags = commit->object.flags & 3;
  25
  26                list = list->next;
  27                free(tmp);
  28                switch (flags) {
  29                case 3:
  30                        insert_by_date(commit, &result);
  31                        continue;
  32                case 0:
  33                        die("git-merge-base: commit without either parent?");
  34                }
  35                parents = commit->parents;
  36                while (parents) {
  37                        struct commit *p = parents->item;
  38                        parents = parents->next;
  39                        if ((p->object.flags & flags) == flags)
  40                                continue;
  41                        parse_commit(p);
  42                        p->object.flags |= flags;
  43                        insert_by_date(p, &list);
  44                }
  45        }
  46        if (!result)
  47                return NULL;
  48        return result->item;
  49}
  50
  51int main(int argc, char **argv)
  52{
  53        struct commit *rev1, *rev2, *ret;
  54        unsigned char rev1key[20], rev2key[20];
  55
  56        if (argc != 3 ||
  57            get_sha1(argv[1], rev1key) ||
  58            get_sha1(argv[2], rev2key)) {
  59                usage("git-merge-base <commit-id> <commit-id>");
  60        }
  61        rev1 = lookup_commit_reference(rev1key);
  62        rev2 = lookup_commit_reference(rev2key);
  63        if (!rev1 || !rev2)
  64                return 1;
  65        ret = common_ancestor(rev1, rev2);
  66        if (!ret)
  67                return 1;
  68        printf("%s\n", sha1_to_hex(ret->object.sha1));
  69        return 0;
  70}