Merge with gitk.
[git.git] / merge-base.c
1 #include <stdlib.h>
2 #include "cache.h"
3 #include "commit.h"
4
5 static 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
51 int 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 }