|
8 | 8 | #include "diff.h"
|
9 | 9 | #include "revision.h"
|
10 | 10 |
|
11 |
| -/* bits #0 and #1 in revision.h */ |
| 11 | +/* bits #0-2 in revision.h */ |
12 | 12 |
|
13 |
| -#define COUNTED (1u << 2) |
14 |
| -#define SHOWN (1u << 3) |
15 |
| -#define TREECHANGE (1u << 4) |
| 13 | +#define COUNTED (1u << 3) |
| 14 | +#define SHOWN (1u << 4) |
16 | 15 | #define TMP_MARK (1u << 5) /* for isolated cases; clean after use */
|
17 | 16 |
|
18 | 17 | static const char rev_list_usage[] =
|
@@ -213,17 +212,17 @@ static struct object_list **process_tree(struct tree *tree,
|
213 | 212 | return p;
|
214 | 213 | }
|
215 | 214 |
|
216 |
| -static void show_commit_list(struct commit_list *list) |
| 215 | +static void show_commit_list(struct rev_info *revs) |
217 | 216 | {
|
| 217 | + struct commit *commit; |
218 | 218 | struct object_list *objects = NULL, **p = &objects, *pending;
|
219 |
| - while (list) { |
220 |
| - struct commit *commit = pop_most_recent_commit(&list, SEEN); |
221 | 219 |
|
| 220 | + while ((commit = get_revision(revs)) != NULL) { |
222 | 221 | p = process_tree(commit->tree, p, NULL, "");
|
223 | 222 | if (process_commit(commit) == STOP)
|
224 | 223 | break;
|
225 | 224 | }
|
226 |
| - for (pending = revs.pending_objects; pending; pending = pending->next) { |
| 225 | + for (pending = revs->pending_objects; pending; pending = pending->next) { |
227 | 226 | struct object *obj = pending->item;
|
228 | 227 | const char *name = pending->name;
|
229 | 228 | if (obj->flags & (UNINTERESTING | SEEN))
|
@@ -259,19 +258,6 @@ static void show_commit_list(struct commit_list *list)
|
259 | 258 | }
|
260 | 259 | }
|
261 | 260 |
|
262 |
| -static int everybody_uninteresting(struct commit_list *orig) |
263 |
| -{ |
264 |
| - struct commit_list *list = orig; |
265 |
| - while (list) { |
266 |
| - struct commit *commit = list->item; |
267 |
| - list = list->next; |
268 |
| - if (commit->object.flags & UNINTERESTING) |
269 |
| - continue; |
270 |
| - return 0; |
271 |
| - } |
272 |
| - return 1; |
273 |
| -} |
274 |
| - |
275 | 261 | /*
|
276 | 262 | * This is a truly stupid algorithm, but it's only
|
277 | 263 | * used for bisection, and we just don't care enough.
|
@@ -379,224 +365,12 @@ static void mark_edges_uninteresting(struct commit_list *list)
|
379 | 365 | }
|
380 | 366 | }
|
381 | 367 |
|
382 |
| -#define TREE_SAME 0 |
383 |
| -#define TREE_NEW 1 |
384 |
| -#define TREE_DIFFERENT 2 |
385 |
| -static int tree_difference = TREE_SAME; |
386 |
| - |
387 |
| -static void file_add_remove(struct diff_options *options, |
388 |
| - int addremove, unsigned mode, |
389 |
| - const unsigned char *sha1, |
390 |
| - const char *base, const char *path) |
391 |
| -{ |
392 |
| - int diff = TREE_DIFFERENT; |
393 |
| - |
394 |
| - /* |
395 |
| - * Is it an add of a new file? It means that |
396 |
| - * the old tree didn't have it at all, so we |
397 |
| - * will turn "TREE_SAME" -> "TREE_NEW", but |
398 |
| - * leave any "TREE_DIFFERENT" alone (and if |
399 |
| - * it already was "TREE_NEW", we'll keep it |
400 |
| - * "TREE_NEW" of course). |
401 |
| - */ |
402 |
| - if (addremove == '+') { |
403 |
| - diff = tree_difference; |
404 |
| - if (diff != TREE_SAME) |
405 |
| - return; |
406 |
| - diff = TREE_NEW; |
407 |
| - } |
408 |
| - tree_difference = diff; |
409 |
| -} |
410 |
| - |
411 |
| -static void file_change(struct diff_options *options, |
412 |
| - unsigned old_mode, unsigned new_mode, |
413 |
| - const unsigned char *old_sha1, |
414 |
| - const unsigned char *new_sha1, |
415 |
| - const char *base, const char *path) |
416 |
| -{ |
417 |
| - tree_difference = TREE_DIFFERENT; |
418 |
| -} |
419 |
| - |
420 |
| -static struct diff_options diff_opt = { |
421 |
| - .recursive = 1, |
422 |
| - .add_remove = file_add_remove, |
423 |
| - .change = file_change, |
424 |
| -}; |
425 |
| - |
426 |
| -static int compare_tree(struct tree *t1, struct tree *t2) |
427 |
| -{ |
428 |
| - if (!t1) |
429 |
| - return TREE_NEW; |
430 |
| - if (!t2) |
431 |
| - return TREE_DIFFERENT; |
432 |
| - tree_difference = TREE_SAME; |
433 |
| - if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "", &diff_opt) < 0) |
434 |
| - return TREE_DIFFERENT; |
435 |
| - return tree_difference; |
436 |
| -} |
437 |
| - |
438 |
| -static int same_tree_as_empty(struct tree *t1) |
439 |
| -{ |
440 |
| - int retval; |
441 |
| - void *tree; |
442 |
| - struct tree_desc empty, real; |
443 |
| - |
444 |
| - if (!t1) |
445 |
| - return 0; |
446 |
| - |
447 |
| - tree = read_object_with_reference(t1->object.sha1, "tree", &real.size, NULL); |
448 |
| - if (!tree) |
449 |
| - return 0; |
450 |
| - real.buf = tree; |
451 |
| - |
452 |
| - empty.buf = ""; |
453 |
| - empty.size = 0; |
454 |
| - |
455 |
| - tree_difference = 0; |
456 |
| - retval = diff_tree(&empty, &real, "", &diff_opt); |
457 |
| - free(tree); |
458 |
| - |
459 |
| - return retval >= 0 && !tree_difference; |
460 |
| -} |
461 |
| - |
462 |
| -static void try_to_simplify_commit(struct commit *commit) |
463 |
| -{ |
464 |
| - struct commit_list **pp, *parent; |
465 |
| - |
466 |
| - if (!commit->tree) |
467 |
| - return; |
468 |
| - |
469 |
| - if (!commit->parents) { |
470 |
| - if (!same_tree_as_empty(commit->tree)) |
471 |
| - commit->object.flags |= TREECHANGE; |
472 |
| - return; |
473 |
| - } |
474 |
| - |
475 |
| - pp = &commit->parents; |
476 |
| - while ((parent = *pp) != NULL) { |
477 |
| - struct commit *p = parent->item; |
478 |
| - |
479 |
| - if (p->object.flags & UNINTERESTING) { |
480 |
| - pp = &parent->next; |
481 |
| - continue; |
482 |
| - } |
483 |
| - |
484 |
| - parse_commit(p); |
485 |
| - switch (compare_tree(p->tree, commit->tree)) { |
486 |
| - case TREE_SAME: |
487 |
| - parent->next = NULL; |
488 |
| - commit->parents = parent; |
489 |
| - return; |
490 |
| - |
491 |
| - case TREE_NEW: |
492 |
| - if (revs.remove_empty_trees && same_tree_as_empty(p->tree)) { |
493 |
| - *pp = parent->next; |
494 |
| - continue; |
495 |
| - } |
496 |
| - /* fallthrough */ |
497 |
| - case TREE_DIFFERENT: |
498 |
| - pp = &parent->next; |
499 |
| - continue; |
500 |
| - } |
501 |
| - die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1)); |
502 |
| - } |
503 |
| - commit->object.flags |= TREECHANGE; |
504 |
| -} |
505 |
| - |
506 |
| -static void add_parents_to_list(struct commit *commit, struct commit_list **list) |
507 |
| -{ |
508 |
| - struct commit_list *parent = commit->parents; |
509 |
| - |
510 |
| - /* |
511 |
| - * If the commit is uninteresting, don't try to |
512 |
| - * prune parents - we want the maximal uninteresting |
513 |
| - * set. |
514 |
| - * |
515 |
| - * Normally we haven't parsed the parent |
516 |
| - * yet, so we won't have a parent of a parent |
517 |
| - * here. However, it may turn out that we've |
518 |
| - * reached this commit some other way (where it |
519 |
| - * wasn't uninteresting), in which case we need |
520 |
| - * to mark its parents recursively too.. |
521 |
| - */ |
522 |
| - if (commit->object.flags & UNINTERESTING) { |
523 |
| - while (parent) { |
524 |
| - struct commit *p = parent->item; |
525 |
| - parent = parent->next; |
526 |
| - parse_commit(p); |
527 |
| - p->object.flags |= UNINTERESTING; |
528 |
| - if (p->parents) |
529 |
| - mark_parents_uninteresting(p); |
530 |
| - if (p->object.flags & SEEN) |
531 |
| - continue; |
532 |
| - p->object.flags |= SEEN; |
533 |
| - insert_by_date(p, list); |
534 |
| - } |
535 |
| - return; |
536 |
| - } |
537 |
| - |
538 |
| - /* |
539 |
| - * Ok, the commit wasn't uninteresting. Try to |
540 |
| - * simplify the commit history and find the parent |
541 |
| - * that has no differences in the path set if one exists. |
542 |
| - */ |
543 |
| - if (revs.paths) |
544 |
| - try_to_simplify_commit(commit); |
545 |
| - |
546 |
| - parent = commit->parents; |
547 |
| - while (parent) { |
548 |
| - struct commit *p = parent->item; |
549 |
| - |
550 |
| - parent = parent->next; |
551 |
| - |
552 |
| - parse_commit(p); |
553 |
| - if (p->object.flags & SEEN) |
554 |
| - continue; |
555 |
| - p->object.flags |= SEEN; |
556 |
| - insert_by_date(p, list); |
557 |
| - } |
558 |
| -} |
559 |
| - |
560 |
| -static struct commit_list *limit_list(struct commit_list *list) |
561 |
| -{ |
562 |
| - struct commit_list *newlist = NULL; |
563 |
| - struct commit_list **p = &newlist; |
564 |
| - while (list) { |
565 |
| - struct commit_list *entry = list; |
566 |
| - struct commit *commit = list->item; |
567 |
| - struct object *obj = &commit->object; |
568 |
| - |
569 |
| - list = list->next; |
570 |
| - free(entry); |
571 |
| - |
572 |
| - if (revs.max_age != -1 && (commit->date < revs.max_age)) |
573 |
| - obj->flags |= UNINTERESTING; |
574 |
| - if (revs.unpacked && has_sha1_pack(obj->sha1)) |
575 |
| - obj->flags |= UNINTERESTING; |
576 |
| - add_parents_to_list(commit, &list); |
577 |
| - if (obj->flags & UNINTERESTING) { |
578 |
| - mark_parents_uninteresting(commit); |
579 |
| - if (everybody_uninteresting(list)) |
580 |
| - break; |
581 |
| - continue; |
582 |
| - } |
583 |
| - if (revs.min_age != -1 && (commit->date > revs.min_age)) |
584 |
| - continue; |
585 |
| - p = &commit_list_insert(commit, p)->next; |
586 |
| - } |
587 |
| - if (revs.tree_objects) |
588 |
| - mark_edges_uninteresting(newlist); |
589 |
| - if (bisect_list) |
590 |
| - newlist = find_bisection(newlist); |
591 |
| - return newlist; |
592 |
| -} |
593 |
| - |
594 | 368 | int main(int argc, const char **argv)
|
595 | 369 | {
|
596 | 370 | struct commit_list *list;
|
597 | 371 | int i;
|
598 | 372 |
|
599 |
| - argc = setup_revisions(argc, argv, &revs); |
| 373 | + argc = setup_revisions(argc, argv, &revs, NULL); |
600 | 374 |
|
601 | 375 | for (i = 1 ; i < argc; i++) {
|
602 | 376 | const char *arg = argv[i];
|
@@ -672,24 +446,18 @@ int main(int argc, const char **argv)
|
672 | 446 | (!(revs.tag_objects||revs.tree_objects||revs.blob_objects) && !revs.pending_objects))
|
673 | 447 | usage(rev_list_usage);
|
674 | 448 |
|
675 |
| - if (revs.paths) |
676 |
| - diff_tree_setup_paths(revs.paths); |
| 449 | + prepare_revision_walk(&revs); |
| 450 | + if (revs.tree_objects) |
| 451 | + mark_edges_uninteresting(revs.commits); |
| 452 | + |
| 453 | + if (bisect_list) |
| 454 | + revs.commits = find_bisection(revs.commits); |
677 | 455 |
|
678 | 456 | save_commit_buffer = verbose_header;
|
679 | 457 | track_object_refs = 0;
|
680 | 458 |
|
681 |
| - if (!merge_order) { |
682 |
| - sort_by_date(&list); |
683 |
| - if (list && !revs.limited && revs.max_count == 1 && |
684 |
| - !revs.tag_objects && !revs.tree_objects && !revs.blob_objects) { |
685 |
| - show_commit(list->item); |
686 |
| - return 0; |
687 |
| - } |
688 |
| - if (revs.limited) |
689 |
| - list = limit_list(list); |
690 |
| - if (revs.topo_order) |
691 |
| - sort_in_topological_order(&list, revs.lifo); |
692 |
| - show_commit_list(list); |
| 459 | + if (!merge_order) { |
| 460 | + show_commit_list(&revs); |
693 | 461 | } else {
|
694 | 462 | #ifndef NO_OPENSSL
|
695 | 463 | if (sort_list_in_merge_order(list, &process_commit)) {
|
|
0 commit comments