X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=rev-list.c;h=441c43785540bfc4bdfc66c4e70e0a4168bb30ad;hb=dff86e282fa38bf60d53b82cfa54f5f449563338;hp=2e80930b2cec2e20be00b5d7751af6a6626efdc2;hpb=d54000ca3ecc2cc1bd0e75c526672e8a3203368b;p=git.git diff --git a/rev-list.c b/rev-list.c index 2e80930b..441c4378 100644 --- a/rev-list.c +++ b/rev-list.c @@ -4,16 +4,12 @@ #include "commit.h" #include "tree.h" #include "blob.h" -#include "epoch.h" #include "diff.h" #include "revision.h" -/* bits #0 and #1 in revision.h */ +/* bits #0-4 in revision.h */ -#define COUNTED (1u << 2) -#define SHOWN (1u << 3) -#define TREECHANGE (1u << 4) -#define TMP_MARK (1u << 5) /* for isolated cases; clean after use */ +#define COUNTED (1u<<5) static const char rev_list_usage[] = "git-rev-list [OPTION] ... [ -- paths... ]\n" @@ -26,7 +22,6 @@ static const char rev_list_usage[] = " --remove-empty\n" " --all\n" " ordering output:\n" -" --merge-order [ --show-breaks ]\n" " --topo-order\n" " --date-order\n" " formatting output:\n" @@ -45,26 +40,18 @@ static int bisect_list = 0; static int verbose_header = 0; static int abbrev = DEFAULT_ABBREV; static int show_parents = 0; +static int show_timestamp = 0; static int hdr_termination = 0; static const char *commit_prefix = ""; static enum cmit_fmt commit_format = CMIT_FMT_RAW; -static int merge_order = 0; -static int show_breaks = 0; -static int stop_traversal = 0; -static int no_merges = 0; static void show_commit(struct commit *commit) { - commit->object.flags |= SHOWN; - if (show_breaks) { - commit_prefix = "| "; - if (commit->object.flags & DISCONTINUITY) { - commit_prefix = "^ "; - } else if (commit->object.flags & BOUNDARY) { - commit_prefix = "= "; - } - } - printf("%s%s", commit_prefix, sha1_to_hex(commit->object.sha1)); + if (show_timestamp) + printf("%lu ", commit->date); + if (commit_prefix[0]) + fputs(commit_prefix, stdout); + fputs(sha1_to_hex(commit->object.sha1), stdout); if (show_parents) { struct commit_list *parents = commit->parents; while (parents) { @@ -97,73 +84,6 @@ static void show_commit(struct commit *commit) fflush(stdout); } -static int rewrite_one(struct commit **pp) -{ - for (;;) { - struct commit *p = *pp; - if (p->object.flags & (TREECHANGE | UNINTERESTING)) - return 0; - if (!p->parents) - return -1; - *pp = p->parents->item; - } -} - -static void rewrite_parents(struct commit *commit) -{ - struct commit_list **pp = &commit->parents; - while (*pp) { - struct commit_list *parent = *pp; - if (rewrite_one(&parent->item) < 0) { - *pp = parent->next; - continue; - } - pp = &parent->next; - } -} - -static int filter_commit(struct commit * commit) -{ - if (stop_traversal && (commit->object.flags & BOUNDARY)) - return STOP; - if (commit->object.flags & (UNINTERESTING|SHOWN)) - return CONTINUE; - if (revs.min_age != -1 && (commit->date > revs.min_age)) - return CONTINUE; - if (revs.max_age != -1 && (commit->date < revs.max_age)) { - stop_traversal=1; - return CONTINUE; - } - if (no_merges && (commit->parents && commit->parents->next)) - return CONTINUE; - if (revs.paths && revs.dense) { - if (!(commit->object.flags & TREECHANGE)) - return CONTINUE; - rewrite_parents(commit); - } - return DO; -} - -static int process_commit(struct commit * commit) -{ - int action=filter_commit(commit); - - if (action == STOP) { - return STOP; - } - - if (action == CONTINUE) { - return CONTINUE; - } - - if (revs.max_count != -1 && !revs.max_count--) - return STOP; - - show_commit(commit); - - return CONTINUE; -} - static struct object_list **process_blob(struct blob *blob, struct object_list **p, struct name_path *path, @@ -213,17 +133,16 @@ static struct object_list **process_tree(struct tree *tree, return p; } -static void show_commit_list(struct commit_list *list) +static void show_commit_list(struct rev_info *revs) { + struct commit *commit; struct object_list *objects = NULL, **p = &objects, *pending; - while (list) { - struct commit *commit = pop_most_recent_commit(&list, SEEN); + while ((commit = get_revision(revs)) != NULL) { p = process_tree(commit->tree, p, NULL, ""); - if (process_commit(commit) == STOP) - break; + show_commit(commit); } - for (pending = revs.pending_objects; pending; pending = pending->next) { + for (pending = revs->pending_objects; pending; pending = pending->next) { struct object *obj = pending->item; const char *name = pending->name; if (obj->flags & (UNINTERESTING | SEEN)) @@ -259,19 +178,6 @@ static void show_commit_list(struct commit_list *list) } } -static int everybody_uninteresting(struct commit_list *orig) -{ - struct commit_list *list = orig; - while (list) { - struct commit *commit = list->item; - list = list->next; - if (commit->object.flags & UNINTERESTING) - continue; - return 0; - } - return 1; -} - /* * This is a truly stupid algorithm, but it's only * used for bisection, and we just don't care enough. @@ -289,7 +195,7 @@ static int count_distance(struct commit_list *entry) if (commit->object.flags & (UNINTERESTING | COUNTED)) break; - if (!revs.paths || (commit->object.flags & TREECHANGE)) + if (!revs.prune_fn || (commit->object.flags & TREECHANGE)) nr++; commit->object.flags |= COUNTED; p = commit->parents; @@ -323,7 +229,7 @@ static struct commit_list *find_bisection(struct commit_list *list) nr = 0; p = list; while (p) { - if (!revs.paths || (p->item->object.flags & TREECHANGE)) + if (!revs.prune_fn || (p->item->object.flags & TREECHANGE)) nr++; p = p->next; } @@ -333,7 +239,7 @@ static struct commit_list *find_bisection(struct commit_list *list) for (p = list; p; p = p->next) { int distance; - if (revs.paths && !(p->item->object.flags & TREECHANGE)) + if (revs.prune_fn && !(p->item->object.flags & TREECHANGE)) continue; distance = count_distance(p); @@ -379,224 +285,12 @@ static void mark_edges_uninteresting(struct commit_list *list) } } -#define TREE_SAME 0 -#define TREE_NEW 1 -#define TREE_DIFFERENT 2 -static int tree_difference = TREE_SAME; - -static void file_add_remove(struct diff_options *options, - int addremove, unsigned mode, - const unsigned char *sha1, - const char *base, const char *path) -{ - int diff = TREE_DIFFERENT; - - /* - * Is it an add of a new file? It means that - * the old tree didn't have it at all, so we - * will turn "TREE_SAME" -> "TREE_NEW", but - * leave any "TREE_DIFFERENT" alone (and if - * it already was "TREE_NEW", we'll keep it - * "TREE_NEW" of course). - */ - if (addremove == '+') { - diff = tree_difference; - if (diff != TREE_SAME) - return; - diff = TREE_NEW; - } - tree_difference = diff; -} - -static void file_change(struct diff_options *options, - unsigned old_mode, unsigned new_mode, - const unsigned char *old_sha1, - const unsigned char *new_sha1, - const char *base, const char *path) -{ - tree_difference = TREE_DIFFERENT; -} - -static struct diff_options diff_opt = { - .recursive = 1, - .add_remove = file_add_remove, - .change = file_change, -}; - -static int compare_tree(struct tree *t1, struct tree *t2) -{ - if (!t1) - return TREE_NEW; - if (!t2) - return TREE_DIFFERENT; - tree_difference = TREE_SAME; - if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "", &diff_opt) < 0) - return TREE_DIFFERENT; - return tree_difference; -} - -static int same_tree_as_empty(struct tree *t1) -{ - int retval; - void *tree; - struct tree_desc empty, real; - - if (!t1) - return 0; - - tree = read_object_with_reference(t1->object.sha1, "tree", &real.size, NULL); - if (!tree) - return 0; - real.buf = tree; - - empty.buf = ""; - empty.size = 0; - - tree_difference = 0; - retval = diff_tree(&empty, &real, "", &diff_opt); - free(tree); - - return retval >= 0 && !tree_difference; -} - -static void try_to_simplify_commit(struct commit *commit) -{ - struct commit_list **pp, *parent; - - if (!commit->tree) - return; - - if (!commit->parents) { - if (!same_tree_as_empty(commit->tree)) - commit->object.flags |= TREECHANGE; - return; - } - - pp = &commit->parents; - while ((parent = *pp) != NULL) { - struct commit *p = parent->item; - - if (p->object.flags & UNINTERESTING) { - pp = &parent->next; - continue; - } - - parse_commit(p); - switch (compare_tree(p->tree, commit->tree)) { - case TREE_SAME: - parent->next = NULL; - commit->parents = parent; - return; - - case TREE_NEW: - if (revs.remove_empty_trees && same_tree_as_empty(p->tree)) { - *pp = parent->next; - continue; - } - /* fallthrough */ - case TREE_DIFFERENT: - pp = &parent->next; - continue; - } - die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1)); - } - commit->object.flags |= TREECHANGE; -} - -static void add_parents_to_list(struct commit *commit, struct commit_list **list) -{ - struct commit_list *parent = commit->parents; - - /* - * If the commit is uninteresting, don't try to - * prune parents - we want the maximal uninteresting - * set. - * - * Normally we haven't parsed the parent - * yet, so we won't have a parent of a parent - * here. However, it may turn out that we've - * reached this commit some other way (where it - * wasn't uninteresting), in which case we need - * to mark its parents recursively too.. - */ - if (commit->object.flags & UNINTERESTING) { - while (parent) { - struct commit *p = parent->item; - parent = parent->next; - parse_commit(p); - p->object.flags |= UNINTERESTING; - if (p->parents) - mark_parents_uninteresting(p); - if (p->object.flags & SEEN) - continue; - p->object.flags |= SEEN; - insert_by_date(p, list); - } - return; - } - - /* - * Ok, the commit wasn't uninteresting. Try to - * simplify the commit history and find the parent - * that has no differences in the path set if one exists. - */ - if (revs.paths) - try_to_simplify_commit(commit); - - parent = commit->parents; - while (parent) { - struct commit *p = parent->item; - - parent = parent->next; - - parse_commit(p); - if (p->object.flags & SEEN) - continue; - p->object.flags |= SEEN; - insert_by_date(p, list); - } -} - -static struct commit_list *limit_list(struct commit_list *list) -{ - struct commit_list *newlist = NULL; - struct commit_list **p = &newlist; - while (list) { - struct commit_list *entry = list; - struct commit *commit = list->item; - struct object *obj = &commit->object; - - list = list->next; - free(entry); - - if (revs.max_age != -1 && (commit->date < revs.max_age)) - obj->flags |= UNINTERESTING; - if (revs.unpacked && has_sha1_pack(obj->sha1)) - obj->flags |= UNINTERESTING; - add_parents_to_list(commit, &list); - if (obj->flags & UNINTERESTING) { - mark_parents_uninteresting(commit); - if (everybody_uninteresting(list)) - break; - continue; - } - if (revs.min_age != -1 && (commit->date > revs.min_age)) - continue; - p = &commit_list_insert(commit, p)->next; - } - if (revs.tree_objects) - mark_edges_uninteresting(newlist); - if (bisect_list) - newlist = find_bisection(newlist); - return newlist; -} - int main(int argc, const char **argv) { struct commit_list *list; int i; - argc = setup_revisions(argc, argv, &revs); + argc = setup_revisions(argc, argv, &revs, NULL); for (i = 1 ; i < argc; i++) { const char *arg = argv[i]; @@ -642,24 +336,16 @@ int main(int argc, const char **argv) commit_prefix = "commit "; continue; } - if (!strncmp(arg, "--no-merges", 11)) { - no_merges = 1; - continue; - } if (!strcmp(arg, "--parents")) { show_parents = 1; continue; } - if (!strcmp(arg, "--bisect")) { - bisect_list = 1; + if (!strcmp(arg, "--timestamp")) { + show_timestamp = 1; continue; } - if (!strcmp(arg, "--merge-order")) { - merge_order = 1; - continue; - } - if (!strcmp(arg, "--show-breaks")) { - show_breaks = 1; + if (!strcmp(arg, "--bisect")) { + bisect_list = 1; continue; } usage(rev_list_usage); @@ -672,33 +358,17 @@ int main(int argc, const char **argv) (!(revs.tag_objects||revs.tree_objects||revs.blob_objects) && !revs.pending_objects)) usage(rev_list_usage); - if (revs.paths) - diff_tree_setup_paths(revs.paths); + prepare_revision_walk(&revs); + if (revs.tree_objects) + mark_edges_uninteresting(revs.commits); + + if (bisect_list) + revs.commits = find_bisection(revs.commits); save_commit_buffer = verbose_header; track_object_refs = 0; - if (!merge_order) { - sort_by_date(&list); - if (list && !revs.limited && revs.max_count == 1 && - !revs.tag_objects && !revs.tree_objects && !revs.blob_objects) { - show_commit(list->item); - return 0; - } - if (revs.limited) - list = limit_list(list); - if (revs.topo_order) - sort_in_topological_order(&list, revs.lifo); - show_commit_list(list); - } else { -#ifndef NO_OPENSSL - if (sort_list_in_merge_order(list, &process_commit)) { - die("merge order sort failed\n"); - } -#else - die("merge order sort unsupported, OpenSSL not linked"); -#endif - } + show_commit_list(&revs); return 0; }