merge-base.con commit Add "rev-list" program that uses the new time-based commit listing. (6474510)
   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 & this_mark) {
  11                /*
  12                  printf("%d already seen %s %x\n",
  13                  this_mark
  14                  sha1_to_hex(posn->parent->sha1),
  15                  posn->parent->flags);
  16                */
  17                /* do nothing; this indicates that this side
  18                 * split and reformed, and we only need to
  19                 * mark it once.
  20                 */
  21                *list_p = (*list_p)->next;
  22        } else if (item->object.flags & other_mark) {
  23                return item;
  24        } else {
  25                /*
  26                  printf("%d based on %s\n",
  27                  this_mark,
  28                  sha1_to_hex(posn->parent->sha1));
  29                */
  30                pop_most_recent_commit(list_p);
  31                item->object.flags |= this_mark;
  32        }
  33        return NULL;
  34}
  35
  36struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
  37{
  38        struct commit_list *rev1list = NULL;
  39        struct commit_list *rev2list = NULL;
  40
  41        commit_list_insert(rev1, &rev1list);
  42        commit_list_insert(rev2, &rev2list);
  43
  44        parse_commit(rev1);
  45        parse_commit(rev2);
  46
  47        while (rev1list || rev2list) {
  48                struct commit *ret;
  49                if (!rev1list) {
  50                        // process 2
  51                        ret = process_list(&rev2list, 0x2, 0x1);
  52                } else if (!rev2list) {
  53                        // process 1
  54                        ret = process_list(&rev1list, 0x1, 0x2);
  55                } else if (rev1list->item->date < rev2list->item->date) {
  56                        // process 2
  57                        ret = process_list(&rev2list, 0x2, 0x1);
  58                } else {
  59                        // process 1
  60                        ret = process_list(&rev1list, 0x1, 0x2);
  61                }
  62                if (ret) {
  63                        free_commit_list(rev1list);
  64                        free_commit_list(rev2list);
  65                        return ret;
  66                }
  67        }
  68        return NULL;
  69}
  70
  71int main(int argc, char **argv)
  72{
  73        struct commit *rev1, *rev2, *ret;
  74        unsigned char rev1key[20], rev2key[20];
  75
  76        if (argc != 3 ||
  77            get_sha1_hex(argv[1], rev1key) ||
  78            get_sha1_hex(argv[2], rev2key)) {
  79                usage("merge-base <commit-id> <commit-id>");
  80        }
  81        rev1 = lookup_commit(rev1key);
  82        rev2 = lookup_commit(rev2key);
  83        ret = common_ancestor(rev1, rev2);
  84        if (!ret)
  85                return 1;
  86        printf("%s\n", sha1_to_hex(ret->object.sha1));
  87        return 0;
  88}