rev-list.con commit Merge branch 'jc/tag' (70e1cca)
   1#include "cache.h"
   2#include "refs.h"
   3#include "tag.h"
   4#include "commit.h"
   5#include "tree.h"
   6#include "blob.h"
   7#include "epoch.h"
   8#include "diff.h"
   9
  10#define SEEN            (1u << 0)
  11#define INTERESTING     (1u << 1)
  12#define COUNTED         (1u << 2)
  13#define SHOWN           (1u << 3)
  14#define TREECHANGE      (1u << 4)
  15#define TMP_MARK        (1u << 5) /* for isolated cases; clean after use */
  16
  17static const char rev_list_usage[] =
  18"git-rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
  19"  limiting output:\n"
  20"    --max-count=nr\n"
  21"    --max-age=epoch\n"
  22"    --min-age=epoch\n"
  23"    --sparse\n"
  24"    --no-merges\n"
  25"    --remove-empty\n"
  26"    --all\n"
  27"  ordering output:\n"
  28"    --merge-order [ --show-breaks ]\n"
  29"    --topo-order\n"
  30"    --date-order\n"
  31"  formatting output:\n"
  32"    --parents\n"
  33"    --objects | --objects-edge\n"
  34"    --unpacked\n"
  35"    --header | --pretty\n"
  36"    --abbrev=nr | --no-abbrev\n"
  37"  special purpose:\n"
  38"    --bisect"
  39;
  40
  41static int dense = 1;
  42static int unpacked = 0;
  43static int bisect_list = 0;
  44static int tag_objects = 0;
  45static int tree_objects = 0;
  46static int blob_objects = 0;
  47static int edge_hint = 0;
  48static int verbose_header = 0;
  49static int abbrev = DEFAULT_ABBREV;
  50static int show_parents = 0;
  51static int hdr_termination = 0;
  52static const char *commit_prefix = "";
  53static unsigned long max_age = -1;
  54static unsigned long min_age = -1;
  55static int max_count = -1;
  56static enum cmit_fmt commit_format = CMIT_FMT_RAW;
  57static int merge_order = 0;
  58static int show_breaks = 0;
  59static int stop_traversal = 0;
  60static int topo_order = 0;
  61static int lifo = 1;
  62static int no_merges = 0;
  63static const char **paths = NULL;
  64static int remove_empty_trees = 0;
  65
  66struct name_path {
  67        struct name_path *up;
  68        int elem_len;
  69        const char *elem;
  70};
  71
  72static char *path_name(struct name_path *path, const char *name)
  73{
  74        struct name_path *p;
  75        char *n, *m;
  76        int nlen = strlen(name);
  77        int len = nlen + 1;
  78
  79        for (p = path; p; p = p->up) {
  80                if (p->elem_len)
  81                        len += p->elem_len + 1;
  82        }
  83        n = xmalloc(len);
  84        m = n + len - (nlen + 1);
  85        strcpy(m, name);
  86        for (p = path; p; p = p->up) {
  87                if (p->elem_len) {
  88                        m -= p->elem_len + 1;
  89                        memcpy(m, p->elem, p->elem_len);
  90                        m[p->elem_len] = '/';
  91                }
  92        }
  93        return n;
  94}
  95
  96static void show_commit(struct commit *commit)
  97{
  98        commit->object.flags |= SHOWN;
  99        if (show_breaks) {
 100                commit_prefix = "| ";
 101                if (commit->object.flags & DISCONTINUITY) {
 102                        commit_prefix = "^ ";     
 103                } else if (commit->object.flags & BOUNDARY) {
 104                        commit_prefix = "= ";
 105                } 
 106        }                       
 107        printf("%s%s", commit_prefix, sha1_to_hex(commit->object.sha1));
 108        if (show_parents) {
 109                struct commit_list *parents = commit->parents;
 110                while (parents) {
 111                        struct object *o = &(parents->item->object);
 112                        parents = parents->next;
 113                        if (o->flags & TMP_MARK)
 114                                continue;
 115                        printf(" %s", sha1_to_hex(o->sha1));
 116                        o->flags |= TMP_MARK;
 117                }
 118                /* TMP_MARK is a general purpose flag that can
 119                 * be used locally, but the user should clean
 120                 * things up after it is done with them.
 121                 */
 122                for (parents = commit->parents;
 123                     parents;
 124                     parents = parents->next)
 125                        parents->item->object.flags &= ~TMP_MARK;
 126        }
 127        if (commit_format == CMIT_FMT_ONELINE)
 128                putchar(' ');
 129        else
 130                putchar('\n');
 131
 132        if (verbose_header) {
 133                static char pretty_header[16384];
 134                pretty_print_commit(commit_format, commit, ~0, pretty_header, sizeof(pretty_header), abbrev);
 135                printf("%s%c", pretty_header, hdr_termination);
 136        }
 137        fflush(stdout);
 138}
 139
 140static int rewrite_one(struct commit **pp)
 141{
 142        for (;;) {
 143                struct commit *p = *pp;
 144                if (p->object.flags & (TREECHANGE | UNINTERESTING))
 145                        return 0;
 146                if (!p->parents)
 147                        return -1;
 148                *pp = p->parents->item;
 149        }
 150}
 151
 152static void rewrite_parents(struct commit *commit)
 153{
 154        struct commit_list **pp = &commit->parents;
 155        while (*pp) {
 156                struct commit_list *parent = *pp;
 157                if (rewrite_one(&parent->item) < 0) {
 158                        *pp = parent->next;
 159                        continue;
 160                }
 161                pp = &parent->next;
 162        }
 163}
 164
 165static int filter_commit(struct commit * commit)
 166{
 167        if (stop_traversal && (commit->object.flags & BOUNDARY))
 168                return STOP;
 169        if (commit->object.flags & (UNINTERESTING|SHOWN))
 170                return CONTINUE;
 171        if (min_age != -1 && (commit->date > min_age))
 172                return CONTINUE;
 173        if (max_age != -1 && (commit->date < max_age)) {
 174                stop_traversal=1;
 175                return CONTINUE;
 176        }
 177        if (no_merges && (commit->parents && commit->parents->next))
 178                return CONTINUE;
 179        if (paths && dense) {
 180                if (!(commit->object.flags & TREECHANGE))
 181                        return CONTINUE;
 182                rewrite_parents(commit);
 183        }
 184        return DO;
 185}
 186
 187static int process_commit(struct commit * commit)
 188{
 189        int action=filter_commit(commit);
 190
 191        if (action == STOP) {
 192                return STOP;
 193        }
 194
 195        if (action == CONTINUE) {
 196                return CONTINUE;
 197        }
 198
 199        if (max_count != -1 && !max_count--)
 200                return STOP;
 201
 202        show_commit(commit);
 203
 204        return CONTINUE;
 205}
 206
 207static struct object_list **add_object(struct object *obj,
 208                                       struct object_list **p,
 209                                       struct name_path *path,
 210                                       const char *name)
 211{
 212        struct object_list *entry = xmalloc(sizeof(*entry));
 213        entry->item = obj;
 214        entry->next = *p;
 215        entry->name = path_name(path, name);
 216        *p = entry;
 217        return &entry->next;
 218}
 219
 220static struct object_list **process_blob(struct blob *blob,
 221                                         struct object_list **p,
 222                                         struct name_path *path,
 223                                         const char *name)
 224{
 225        struct object *obj = &blob->object;
 226
 227        if (!blob_objects)
 228                return p;
 229        if (obj->flags & (UNINTERESTING | SEEN))
 230                return p;
 231        obj->flags |= SEEN;
 232        return add_object(obj, p, path, name);
 233}
 234
 235static struct object_list **process_tree(struct tree *tree,
 236                                         struct object_list **p,
 237                                         struct name_path *path,
 238                                         const char *name)
 239{
 240        struct object *obj = &tree->object;
 241        struct tree_entry_list *entry;
 242        struct name_path me;
 243
 244        if (!tree_objects)
 245                return p;
 246        if (obj->flags & (UNINTERESTING | SEEN))
 247                return p;
 248        if (parse_tree(tree) < 0)
 249                die("bad tree object %s", sha1_to_hex(obj->sha1));
 250        obj->flags |= SEEN;
 251        p = add_object(obj, p, path, name);
 252        me.up = path;
 253        me.elem = name;
 254        me.elem_len = strlen(name);
 255        entry = tree->entries;
 256        tree->entries = NULL;
 257        while (entry) {
 258                struct tree_entry_list *next = entry->next;
 259                if (entry->directory)
 260                        p = process_tree(entry->item.tree, p, &me, entry->name);
 261                else
 262                        p = process_blob(entry->item.blob, p, &me, entry->name);
 263                free(entry);
 264                entry = next;
 265        }
 266        return p;
 267}
 268
 269static struct object_list *pending_objects = NULL;
 270
 271static void show_commit_list(struct commit_list *list)
 272{
 273        struct object_list *objects = NULL, **p = &objects, *pending;
 274        while (list) {
 275                struct commit *commit = pop_most_recent_commit(&list, SEEN);
 276
 277                p = process_tree(commit->tree, p, NULL, "");
 278                if (process_commit(commit) == STOP)
 279                        break;
 280        }
 281        for (pending = pending_objects; pending; pending = pending->next) {
 282                struct object *obj = pending->item;
 283                const char *name = pending->name;
 284                if (obj->flags & (UNINTERESTING | SEEN))
 285                        continue;
 286                if (obj->type == tag_type) {
 287                        obj->flags |= SEEN;
 288                        p = add_object(obj, p, NULL, name);
 289                        continue;
 290                }
 291                if (obj->type == tree_type) {
 292                        p = process_tree((struct tree *)obj, p, NULL, name);
 293                        continue;
 294                }
 295                if (obj->type == blob_type) {
 296                        p = process_blob((struct blob *)obj, p, NULL, name);
 297                        continue;
 298                }
 299                die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
 300        }
 301        while (objects) {
 302                /* An object with name "foo\n0000000..." can be used to
 303                 * confuse downstream git-pack-objects very badly.
 304                 */
 305                const char *ep = strchr(objects->name, '\n');
 306                if (ep) {
 307                        printf("%s %.*s\n", sha1_to_hex(objects->item->sha1),
 308                               (int) (ep - objects->name),
 309                               objects->name);
 310                }
 311                else
 312                        printf("%s %s\n", sha1_to_hex(objects->item->sha1), objects->name);
 313                objects = objects->next;
 314        }
 315}
 316
 317static void mark_blob_uninteresting(struct blob *blob)
 318{
 319        if (!blob_objects)
 320                return;
 321        if (blob->object.flags & UNINTERESTING)
 322                return;
 323        blob->object.flags |= UNINTERESTING;
 324}
 325
 326static void mark_tree_uninteresting(struct tree *tree)
 327{
 328        struct object *obj = &tree->object;
 329        struct tree_entry_list *entry;
 330
 331        if (!tree_objects)
 332                return;
 333        if (obj->flags & UNINTERESTING)
 334                return;
 335        obj->flags |= UNINTERESTING;
 336        if (!has_sha1_file(obj->sha1))
 337                return;
 338        if (parse_tree(tree) < 0)
 339                die("bad tree %s", sha1_to_hex(obj->sha1));
 340        entry = tree->entries;
 341        tree->entries = NULL;
 342        while (entry) {
 343                struct tree_entry_list *next = entry->next;
 344                if (entry->directory)
 345                        mark_tree_uninteresting(entry->item.tree);
 346                else
 347                        mark_blob_uninteresting(entry->item.blob);
 348                free(entry);
 349                entry = next;
 350        }
 351}
 352
 353static void mark_parents_uninteresting(struct commit *commit)
 354{
 355        struct commit_list *parents = commit->parents;
 356
 357        while (parents) {
 358                struct commit *commit = parents->item;
 359                commit->object.flags |= UNINTERESTING;
 360
 361                /*
 362                 * Normally we haven't parsed the parent
 363                 * yet, so we won't have a parent of a parent
 364                 * here. However, it may turn out that we've
 365                 * reached this commit some other way (where it
 366                 * wasn't uninteresting), in which case we need
 367                 * to mark its parents recursively too..
 368                 */
 369                if (commit->parents)
 370                        mark_parents_uninteresting(commit);
 371
 372                /*
 373                 * A missing commit is ok iff its parent is marked 
 374                 * uninteresting.
 375                 *
 376                 * We just mark such a thing parsed, so that when
 377                 * it is popped next time around, we won't be trying
 378                 * to parse it and get an error.
 379                 */
 380                if (!has_sha1_file(commit->object.sha1))
 381                        commit->object.parsed = 1;
 382                parents = parents->next;
 383        }
 384}
 385
 386static int everybody_uninteresting(struct commit_list *orig)
 387{
 388        struct commit_list *list = orig;
 389        while (list) {
 390                struct commit *commit = list->item;
 391                list = list->next;
 392                if (commit->object.flags & UNINTERESTING)
 393                        continue;
 394                return 0;
 395        }
 396        return 1;
 397}
 398
 399/*
 400 * This is a truly stupid algorithm, but it's only
 401 * used for bisection, and we just don't care enough.
 402 *
 403 * We care just barely enough to avoid recursing for
 404 * non-merge entries.
 405 */
 406static int count_distance(struct commit_list *entry)
 407{
 408        int nr = 0;
 409
 410        while (entry) {
 411                struct commit *commit = entry->item;
 412                struct commit_list *p;
 413
 414                if (commit->object.flags & (UNINTERESTING | COUNTED))
 415                        break;
 416                if (!paths || (commit->object.flags & TREECHANGE))
 417                        nr++;
 418                commit->object.flags |= COUNTED;
 419                p = commit->parents;
 420                entry = p;
 421                if (p) {
 422                        p = p->next;
 423                        while (p) {
 424                                nr += count_distance(p);
 425                                p = p->next;
 426                        }
 427                }
 428        }
 429
 430        return nr;
 431}
 432
 433static void clear_distance(struct commit_list *list)
 434{
 435        while (list) {
 436                struct commit *commit = list->item;
 437                commit->object.flags &= ~COUNTED;
 438                list = list->next;
 439        }
 440}
 441
 442static struct commit_list *find_bisection(struct commit_list *list)
 443{
 444        int nr, closest;
 445        struct commit_list *p, *best;
 446
 447        nr = 0;
 448        p = list;
 449        while (p) {
 450                if (!paths || (p->item->object.flags & TREECHANGE))
 451                        nr++;
 452                p = p->next;
 453        }
 454        closest = 0;
 455        best = list;
 456
 457        for (p = list; p; p = p->next) {
 458                int distance;
 459
 460                if (paths && !(p->item->object.flags & TREECHANGE))
 461                        continue;
 462
 463                distance = count_distance(p);
 464                clear_distance(list);
 465                if (nr - distance < distance)
 466                        distance = nr - distance;
 467                if (distance > closest) {
 468                        best = p;
 469                        closest = distance;
 470                }
 471        }
 472        if (best)
 473                best->next = NULL;
 474        return best;
 475}
 476
 477static void mark_edge_parents_uninteresting(struct commit *commit)
 478{
 479        struct commit_list *parents;
 480
 481        for (parents = commit->parents; parents; parents = parents->next) {
 482                struct commit *parent = parents->item;
 483                if (!(parent->object.flags & UNINTERESTING))
 484                        continue;
 485                mark_tree_uninteresting(parent->tree);
 486                if (edge_hint && !(parent->object.flags & SHOWN)) {
 487                        parent->object.flags |= SHOWN;
 488                        printf("-%s\n", sha1_to_hex(parent->object.sha1));
 489                }
 490        }
 491}
 492
 493static void mark_edges_uninteresting(struct commit_list *list)
 494{
 495        for ( ; list; list = list->next) {
 496                struct commit *commit = list->item;
 497
 498                if (commit->object.flags & UNINTERESTING) {
 499                        mark_tree_uninteresting(commit->tree);
 500                        continue;
 501                }
 502                mark_edge_parents_uninteresting(commit);
 503        }
 504}
 505
 506#define TREE_SAME       0
 507#define TREE_NEW        1
 508#define TREE_DIFFERENT  2
 509static int tree_difference = TREE_SAME;
 510
 511static void file_add_remove(struct diff_options *options,
 512                    int addremove, unsigned mode,
 513                    const unsigned char *sha1,
 514                    const char *base, const char *path)
 515{
 516        int diff = TREE_DIFFERENT;
 517
 518        /*
 519         * Is it an add of a new file? It means that
 520         * the old tree didn't have it at all, so we
 521         * will turn "TREE_SAME" -> "TREE_NEW", but
 522         * leave any "TREE_DIFFERENT" alone (and if
 523         * it already was "TREE_NEW", we'll keep it
 524         * "TREE_NEW" of course).
 525         */
 526        if (addremove == '+') {
 527                diff = tree_difference;
 528                if (diff != TREE_SAME)
 529                        return;
 530                diff = TREE_NEW;
 531        }
 532        tree_difference = diff;
 533}
 534
 535static void file_change(struct diff_options *options,
 536                 unsigned old_mode, unsigned new_mode,
 537                 const unsigned char *old_sha1,
 538                 const unsigned char *new_sha1,
 539                 const char *base, const char *path)
 540{
 541        tree_difference = TREE_DIFFERENT;
 542}
 543
 544static struct diff_options diff_opt = {
 545        .recursive = 1,
 546        .add_remove = file_add_remove,
 547        .change = file_change,
 548};
 549
 550static int compare_tree(struct tree *t1, struct tree *t2)
 551{
 552        if (!t1)
 553                return TREE_NEW;
 554        if (!t2)
 555                return TREE_DIFFERENT;
 556        tree_difference = TREE_SAME;
 557        if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "", &diff_opt) < 0)
 558                return TREE_DIFFERENT;
 559        return tree_difference;
 560}
 561
 562static int same_tree_as_empty(struct tree *t1)
 563{
 564        int retval;
 565        void *tree;
 566        struct tree_desc empty, real;
 567
 568        if (!t1)
 569                return 0;
 570
 571        tree = read_object_with_reference(t1->object.sha1, "tree", &real.size, NULL);
 572        if (!tree)
 573                return 0;
 574        real.buf = tree;
 575
 576        empty.buf = "";
 577        empty.size = 0;
 578
 579        tree_difference = 0;
 580        retval = diff_tree(&empty, &real, "", &diff_opt);
 581        free(tree);
 582
 583        return retval >= 0 && !tree_difference;
 584}
 585
 586static void try_to_simplify_commit(struct commit *commit)
 587{
 588        struct commit_list **pp, *parent;
 589
 590        if (!commit->tree)
 591                return;
 592
 593        if (!commit->parents) {
 594                if (!same_tree_as_empty(commit->tree))
 595                        commit->object.flags |= TREECHANGE;
 596                return;
 597        }
 598
 599        pp = &commit->parents;
 600        while ((parent = *pp) != NULL) {
 601                struct commit *p = parent->item;
 602
 603                if (p->object.flags & UNINTERESTING) {
 604                        pp = &parent->next;
 605                        continue;
 606                }
 607
 608                parse_commit(p);
 609                switch (compare_tree(p->tree, commit->tree)) {
 610                case TREE_SAME:
 611                        parent->next = NULL;
 612                        commit->parents = parent;
 613                        return;
 614
 615                case TREE_NEW:
 616                        if (remove_empty_trees && same_tree_as_empty(p->tree)) {
 617                                *pp = parent->next;
 618                                continue;
 619                        }
 620                /* fallthrough */
 621                case TREE_DIFFERENT:
 622                        pp = &parent->next;
 623                        continue;
 624                }
 625                die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
 626        }
 627        commit->object.flags |= TREECHANGE;
 628}
 629
 630static void add_parents_to_list(struct commit *commit, struct commit_list **list)
 631{
 632        struct commit_list *parent = commit->parents;
 633
 634        /*
 635         * If the commit is uninteresting, don't try to
 636         * prune parents - we want the maximal uninteresting
 637         * set.
 638         *
 639         * Normally we haven't parsed the parent
 640         * yet, so we won't have a parent of a parent
 641         * here. However, it may turn out that we've
 642         * reached this commit some other way (where it
 643         * wasn't uninteresting), in which case we need
 644         * to mark its parents recursively too..
 645         */
 646        if (commit->object.flags & UNINTERESTING) {
 647                while (parent) {
 648                        struct commit *p = parent->item;
 649                        parent = parent->next;
 650                        parse_commit(p);
 651                        p->object.flags |= UNINTERESTING;
 652                        if (p->parents)
 653                                mark_parents_uninteresting(p);
 654                        if (p->object.flags & SEEN)
 655                                continue;
 656                        p->object.flags |= SEEN;
 657                        insert_by_date(p, list);
 658                }
 659                return;
 660        }
 661
 662        /*
 663         * Ok, the commit wasn't uninteresting. Try to
 664         * simplify the commit history and find the parent
 665         * that has no differences in the path set if one exists.
 666         */
 667        if (paths)
 668                try_to_simplify_commit(commit);
 669
 670        parent = commit->parents;
 671        while (parent) {
 672                struct commit *p = parent->item;
 673
 674                parent = parent->next;
 675
 676                parse_commit(p);
 677                if (p->object.flags & SEEN)
 678                        continue;
 679                p->object.flags |= SEEN;
 680                insert_by_date(p, list);
 681        }
 682}
 683
 684static struct commit_list *limit_list(struct commit_list *list)
 685{
 686        struct commit_list *newlist = NULL;
 687        struct commit_list **p = &newlist;
 688        while (list) {
 689                struct commit_list *entry = list;
 690                struct commit *commit = list->item;
 691                struct object *obj = &commit->object;
 692
 693                list = list->next;
 694                free(entry);
 695
 696                if (max_age != -1 && (commit->date < max_age))
 697                        obj->flags |= UNINTERESTING;
 698                if (unpacked && has_sha1_pack(obj->sha1))
 699                        obj->flags |= UNINTERESTING;
 700                add_parents_to_list(commit, &list);
 701                if (obj->flags & UNINTERESTING) {
 702                        mark_parents_uninteresting(commit);
 703                        if (everybody_uninteresting(list))
 704                                break;
 705                        continue;
 706                }
 707                if (min_age != -1 && (commit->date > min_age))
 708                        continue;
 709                p = &commit_list_insert(commit, p)->next;
 710        }
 711        if (tree_objects)
 712                mark_edges_uninteresting(newlist);
 713        if (bisect_list)
 714                newlist = find_bisection(newlist);
 715        return newlist;
 716}
 717
 718static void add_pending_object(struct object *obj, const char *name)
 719{
 720        add_object(obj, &pending_objects, NULL, name);
 721}
 722
 723static struct commit *get_commit_reference(const char *name, const unsigned char *sha1, unsigned int flags)
 724{
 725        struct object *object;
 726
 727        object = parse_object(sha1);
 728        if (!object)
 729                die("bad object %s", name);
 730
 731        /*
 732         * Tag object? Look what it points to..
 733         */
 734        while (object->type == tag_type) {
 735                struct tag *tag = (struct tag *) object;
 736                object->flags |= flags;
 737                if (tag_objects && !(object->flags & UNINTERESTING))
 738                        add_pending_object(object, tag->tag);
 739                object = parse_object(tag->tagged->sha1);
 740                if (!object)
 741                        die("bad object %s", sha1_to_hex(tag->tagged->sha1));
 742        }
 743
 744        /*
 745         * Commit object? Just return it, we'll do all the complex
 746         * reachability crud.
 747         */
 748        if (object->type == commit_type) {
 749                struct commit *commit = (struct commit *)object;
 750                object->flags |= flags;
 751                if (parse_commit(commit) < 0)
 752                        die("unable to parse commit %s", name);
 753                if (flags & UNINTERESTING)
 754                        mark_parents_uninteresting(commit);
 755                return commit;
 756        }
 757
 758        /*
 759         * Tree object? Either mark it uniniteresting, or add it
 760         * to the list of objects to look at later..
 761         */
 762        if (object->type == tree_type) {
 763                struct tree *tree = (struct tree *)object;
 764                if (!tree_objects)
 765                        return NULL;
 766                if (flags & UNINTERESTING) {
 767                        mark_tree_uninteresting(tree);
 768                        return NULL;
 769                }
 770                add_pending_object(object, "");
 771                return NULL;
 772        }
 773
 774        /*
 775         * Blob object? You know the drill by now..
 776         */
 777        if (object->type == blob_type) {
 778                struct blob *blob = (struct blob *)object;
 779                if (!blob_objects)
 780                        return NULL;
 781                if (flags & UNINTERESTING) {
 782                        mark_blob_uninteresting(blob);
 783                        return NULL;
 784                }
 785                add_pending_object(object, "");
 786                return NULL;
 787        }
 788        die("%s is unknown object", name);
 789}
 790
 791static void handle_one_commit(struct commit *com, struct commit_list **lst)
 792{
 793        if (!com || com->object.flags & SEEN)
 794                return;
 795        com->object.flags |= SEEN;
 796        commit_list_insert(com, lst);
 797}
 798
 799/* for_each_ref() callback does not allow user data -- Yuck. */
 800static struct commit_list **global_lst;
 801
 802static int include_one_commit(const char *path, const unsigned char *sha1)
 803{
 804        struct commit *com = get_commit_reference(path, sha1, 0);
 805        handle_one_commit(com, global_lst);
 806        return 0;
 807}
 808
 809static void handle_all(struct commit_list **lst)
 810{
 811        global_lst = lst;
 812        for_each_ref(include_one_commit);
 813        global_lst = NULL;
 814}
 815
 816int main(int argc, const char **argv)
 817{
 818        const char *prefix = setup_git_directory();
 819        struct commit_list *list = NULL;
 820        int i, limited = 0;
 821
 822        for (i = 1 ; i < argc; i++) {
 823                int flags;
 824                const char *arg = argv[i];
 825                char *dotdot;
 826                struct commit *commit;
 827                unsigned char sha1[20];
 828
 829                /* accept -<digit>, like traditilnal "head" */
 830                if ((*arg == '-') && isdigit(arg[1])) {
 831                        max_count = atoi(arg + 1);
 832                        continue;
 833                }
 834                if (!strcmp(arg, "-n")) {
 835                        if (++i >= argc)
 836                                die("-n requires an argument");
 837                        max_count = atoi(argv[i]);
 838                        continue;
 839                }
 840                if (!strncmp(arg,"-n",2)) {
 841                        max_count = atoi(arg + 2);
 842                        continue;
 843                }
 844                if (!strncmp(arg, "--max-count=", 12)) {
 845                        max_count = atoi(arg + 12);
 846                        continue;
 847                }
 848                if (!strncmp(arg, "--max-age=", 10)) {
 849                        max_age = atoi(arg + 10);
 850                        limited = 1;
 851                        continue;
 852                }
 853                if (!strncmp(arg, "--min-age=", 10)) {
 854                        min_age = atoi(arg + 10);
 855                        limited = 1;
 856                        continue;
 857                }
 858                if (!strcmp(arg, "--header")) {
 859                        verbose_header = 1;
 860                        continue;
 861                }
 862                if (!strcmp(arg, "--no-abbrev")) {
 863                        abbrev = 0;
 864                        continue;
 865                }
 866                if (!strncmp(arg, "--abbrev=", 9)) {
 867                        abbrev = strtoul(arg + 9, NULL, 10);
 868                        if (abbrev && abbrev < MINIMUM_ABBREV)
 869                                abbrev = MINIMUM_ABBREV;
 870                        else if (40 < abbrev)
 871                                abbrev = 40;
 872                        continue;
 873                }
 874                if (!strncmp(arg, "--pretty", 8)) {
 875                        commit_format = get_commit_format(arg+8);
 876                        verbose_header = 1;
 877                        hdr_termination = '\n';
 878                        if (commit_format == CMIT_FMT_ONELINE)
 879                                commit_prefix = "";
 880                        else
 881                                commit_prefix = "commit ";
 882                        continue;
 883                }
 884                if (!strncmp(arg, "--no-merges", 11)) {
 885                        no_merges = 1;
 886                        continue;
 887                }
 888                if (!strcmp(arg, "--parents")) {
 889                        show_parents = 1;
 890                        continue;
 891                }
 892                if (!strcmp(arg, "--bisect")) {
 893                        bisect_list = 1;
 894                        continue;
 895                }
 896                if (!strcmp(arg, "--all")) {
 897                        handle_all(&list);
 898                        continue;
 899                }
 900                if (!strcmp(arg, "--objects")) {
 901                        tag_objects = 1;
 902                        tree_objects = 1;
 903                        blob_objects = 1;
 904                        continue;
 905                }
 906                if (!strcmp(arg, "--objects-edge")) {
 907                        tag_objects = 1;
 908                        tree_objects = 1;
 909                        blob_objects = 1;
 910                        edge_hint = 1;
 911                        continue;
 912                }
 913                if (!strcmp(arg, "--unpacked")) {
 914                        unpacked = 1;
 915                        limited = 1;
 916                        continue;
 917                }
 918                if (!strcmp(arg, "--merge-order")) {
 919                        merge_order = 1;
 920                        continue;
 921                }
 922                if (!strcmp(arg, "--show-breaks")) {
 923                        show_breaks = 1;
 924                        continue;
 925                }
 926                if (!strcmp(arg, "--topo-order")) {
 927                        topo_order = 1;
 928                        lifo = 1;
 929                        limited = 1;
 930                        continue;
 931                }
 932                if (!strcmp(arg, "--date-order")) {
 933                        topo_order = 1;
 934                        lifo = 0;
 935                        limited = 1;
 936                        continue;
 937                }
 938                if (!strcmp(arg, "--dense")) {
 939                        dense = 1;
 940                        continue;
 941                }
 942                if (!strcmp(arg, "--sparse")) {
 943                        dense = 0;
 944                        continue;
 945                }
 946                if (!strcmp(arg, "--remove-empty")) {
 947                        remove_empty_trees = 1;
 948                        continue;
 949                }
 950                if (!strcmp(arg, "--")) {
 951                        i++;
 952                        break;
 953                }
 954
 955                if (show_breaks && !merge_order)
 956                        usage(rev_list_usage);
 957
 958                flags = 0;
 959                dotdot = strstr(arg, "..");
 960                if (dotdot) {
 961                        unsigned char from_sha1[20];
 962                        char *next = dotdot + 2;
 963                        *dotdot = 0;
 964                        if (!*next)
 965                                next = "HEAD";
 966                        if (!get_sha1(arg, from_sha1) && !get_sha1(next, sha1)) {
 967                                struct commit *exclude;
 968                                struct commit *include;
 969                                
 970                                exclude = get_commit_reference(arg, from_sha1, UNINTERESTING);
 971                                include = get_commit_reference(next, sha1, 0);
 972                                if (!exclude || !include)
 973                                        die("Invalid revision range %s..%s", arg, next);
 974                                limited = 1;
 975                                handle_one_commit(exclude, &list);
 976                                handle_one_commit(include, &list);
 977                                continue;
 978                        }
 979                        *dotdot = '.';
 980                }
 981                if (*arg == '^') {
 982                        flags = UNINTERESTING;
 983                        arg++;
 984                        limited = 1;
 985                }
 986                if (get_sha1(arg, sha1) < 0) {
 987                        struct stat st;
 988                        if (lstat(arg, &st) < 0)
 989                                die("'%s': %s", arg, strerror(errno));
 990                        break;
 991                }
 992                commit = get_commit_reference(arg, sha1, flags);
 993                handle_one_commit(commit, &list);
 994        }
 995
 996        if (!list &&
 997            (!(tag_objects||tree_objects||blob_objects) && !pending_objects))
 998                usage(rev_list_usage);
 999
1000        paths = get_pathspec(prefix, argv + i);
1001        if (paths) {
1002                limited = 1;
1003                diff_tree_setup_paths(paths);
1004        }
1005
1006        save_commit_buffer = verbose_header;
1007        track_object_refs = 0;
1008
1009        if (!merge_order) {             
1010                sort_by_date(&list);
1011                if (list && !limited && max_count == 1 &&
1012                    !tag_objects && !tree_objects && !blob_objects) {
1013                        show_commit(list->item);
1014                        return 0;
1015                }
1016                if (limited)
1017                        list = limit_list(list);
1018                if (topo_order)
1019                        sort_in_topological_order(&list, lifo);
1020                show_commit_list(list);
1021        } else {
1022#ifndef NO_OPENSSL
1023                if (sort_list_in_merge_order(list, &process_commit)) {
1024                        die("merge order sort failed\n");
1025                }
1026#else
1027                die("merge order sort unsupported, OpenSSL not linked");
1028#endif
1029        }
1030
1031        return 0;
1032}