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