From 337cb3fb8da45f10fe9a0c3cf571600f55ead2ce Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 4 Jun 2005 14:38:28 -0700 Subject: git-rev-list: allow arbitrary head selections, use git-rev-tree syntax This makes git-rev-list use the same command line syntax to mark the commits as git-rev-tree does, and instead of just allowing a start and end commit, it allows an arbitrary list of "interesting" and "uninteresting" commits. For example, imagine that you had three branches (a, b and c) that you are interested in, but you don't want to see stuff that already exists in another persons three releases (x, y and z). You can do git-rev-list a b c ^x ^y ^z (order doesn't matter, btw - feel free to put the uninteresting ones first or otherwise swithc them around), and it will show all the commits that are reachable from a/b/c but not reachable from x/y/z. The old syntax "git-rev-list start end" would not be written as "git-rev-list start ^end", or "git-rev-list ^end start". There's no limit to the number of heads you can specify (unlike git-rev-tree, which can handle a maximum of 16 heads). diff --git a/rev-list.c b/rev-list.c index 56dd814..cbfc5c4 100644 --- a/rev-list.c +++ b/rev-list.c @@ -84,7 +84,7 @@ static int everybody_uninteresting(struct commit_list *list) return 1; } -struct commit_list *limit_list(struct commit_list *list, struct commit *end) +struct commit_list *limit_list(struct commit_list *list) { struct commit_list *newlist = NULL; struct commit_list **p = &newlist; @@ -92,7 +92,7 @@ struct commit_list *limit_list(struct commit_list *list, struct commit *end) struct commit *commit = pop_most_recent_commit(&list, SEEN); struct object *obj = &commit->object; - if (commit == end || (obj->flags & UNINTERESTING)) { + if (obj->flags & UNINTERESTING) { mark_parents_uninteresting(commit); if (everybody_uninteresting(list)) break; @@ -105,15 +105,14 @@ struct commit_list *limit_list(struct commit_list *list, struct commit *end) int main(int argc, char **argv) { - int nr_sha; - unsigned char sha1[2][20]; struct commit_list *list = NULL; - struct commit *commit, *end; - int i; + int i, limited = 0; - nr_sha = 0; for (i = 1 ; i < argc; i++) { + int flags; char *arg = argv[i]; + unsigned char sha1[20]; + struct commit *commit; if (!strncmp(arg, "--max-count=", 12)) { max_count = atoi(arg + 12); @@ -143,28 +142,26 @@ int main(int argc, char **argv) continue; } - if (nr_sha > 2 || get_sha1(arg, sha1[nr_sha])) + flags = 0; + if (*arg == '^') { + flags = UNINTERESTING; + arg++; + limited = 1; + } + if (get_sha1(arg, sha1)) usage(rev_list_usage); - nr_sha++; + commit = lookup_commit_reference(sha1); + if (!commit || parse_commit(commit) < 0) + die("bad commit object %s", arg); + commit->object.flags |= flags; + commit_list_insert(commit, &list); } - if (!nr_sha) + if (!list) usage(rev_list_usage); - commit = lookup_commit_reference(sha1[0]); - if (!commit || parse_commit(commit) < 0) - die("bad starting commit object"); - - end = NULL; - if (nr_sha > 1) { - end = lookup_commit_reference(sha1[1]); - if (!end || parse_commit(end) < 0) - die("bad ending commit object"); - } - - commit_list_insert(commit, &list); - if (end) - list = limit_list(list, end); + if (limited) + list = limit_list(list); show_commit_list(list); return 0; -- cgit v0.10.2-6-g49f6