X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-rev-list.c;h=c2db5a5b037babf9020353d9b11dc348915b6c1b;hb=0053e902b4f777ba454b62263d3695e5292b1559;hp=17c04b962d82701ee6fd17ad15e368e1c283af25;hpb=16a4c6ee0d9a3d07d4d0afbbc4e3467e78065eca;p=git.git diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 17c04b962..c2db5a5b0 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -7,6 +7,7 @@ #include "tree-walk.h" #include "diff.h" #include "revision.h" +#include "list-objects.h" #include "builtin.h" /* bits #0-15 in revision.h */ @@ -23,6 +24,7 @@ static const char rev_list_usage[] = " --no-merges\n" " --remove-empty\n" " --all\n" +" --stdin\n" " ordering output:\n" " --topo-order\n" " --date-order\n" @@ -39,9 +41,9 @@ static const char rev_list_usage[] = static struct rev_info revs; -static int bisect_list = 0; -static int show_timestamp = 0; -static int hdr_termination = 0; +static int bisect_list; +static int show_timestamp; +static int hdr_termination; static const char *header_prefix; static void show_commit(struct commit *commit) @@ -52,6 +54,12 @@ static void show_commit(struct commit *commit) fputs(header_prefix, stdout); if (commit->object.flags & BOUNDARY) putchar('-'); + else if (revs.left_right) { + if (commit->object.flags & SYMMETRIC_LEFT) + putchar('<'); + else + putchar('>'); + } if (revs.abbrev_commit && revs.abbrev) fputs(find_unique_abbrev(commit->object.sha1, revs.abbrev), stdout); @@ -85,108 +93,36 @@ static void show_commit(struct commit *commit) static char pretty_header[16384]; pretty_print_commit(revs.commit_format, commit, ~0, pretty_header, sizeof(pretty_header), - revs.abbrev, NULL, NULL); + revs.abbrev, NULL, NULL, revs.relative_date); printf("%s%c", pretty_header, hdr_termination); } fflush(stdout); + if (commit->parents) { + free_commit_list(commit->parents); + commit->parents = NULL; + } + free(commit->buffer); + commit->buffer = NULL; } -static struct object_list **process_blob(struct blob *blob, - struct object_list **p, - struct name_path *path, - const char *name) -{ - struct object *obj = &blob->object; - - if (!revs.blob_objects) - return p; - if (obj->flags & (UNINTERESTING | SEEN)) - return p; - obj->flags |= SEEN; - name = strdup(name); - return add_object(obj, p, path, name); -} - -static struct object_list **process_tree(struct tree *tree, - struct object_list **p, - struct name_path *path, - const char *name) +static void show_object(struct object_array_entry *p) { - struct object *obj = &tree->object; - struct tree_desc desc; - struct name_entry entry; - struct name_path me; - - if (!revs.tree_objects) - return p; - if (obj->flags & (UNINTERESTING | SEEN)) - return p; - if (parse_tree(tree) < 0) - die("bad tree object %s", sha1_to_hex(obj->sha1)); - obj->flags |= SEEN; - name = strdup(name); - p = add_object(obj, p, path, name); - me.up = path; - me.elem = name; - me.elem_len = strlen(name); - - desc.buf = tree->buffer; - desc.size = tree->size; - - while (tree_entry(&desc, &entry)) { - if (S_ISDIR(entry.mode)) - p = process_tree(lookup_tree(entry.sha1), p, &me, name); - else - p = process_blob(lookup_blob(entry.sha1), p, &me, name); + /* An object with name "foo\n0000000..." can be used to + * confuse downstream git-pack-objects very badly. + */ + const char *ep = strchr(p->name, '\n'); + if (ep) { + printf("%s %.*s\n", sha1_to_hex(p->item->sha1), + (int) (ep - p->name), + p->name); } - free(tree->buffer); - tree->buffer = NULL; - return p; + else + printf("%s %s\n", sha1_to_hex(p->item->sha1), p->name); } -static void show_commit_list(struct rev_info *revs) +static void show_edge(struct commit *commit) { - struct commit *commit; - struct object_list *objects = NULL, **p = &objects, *pending; - - while ((commit = get_revision(revs)) != NULL) { - p = process_tree(commit->tree, p, NULL, ""); - show_commit(commit); - } - for (pending = revs->pending_objects; pending; pending = pending->next) { - struct object *obj = pending->item; - const char *name = pending->name; - if (obj->flags & (UNINTERESTING | SEEN)) - continue; - if (obj->type == tag_type) { - obj->flags |= SEEN; - p = add_object(obj, p, NULL, name); - continue; - } - if (obj->type == tree_type) { - p = process_tree((struct tree *)obj, p, NULL, name); - continue; - } - if (obj->type == blob_type) { - p = process_blob((struct blob *)obj, p, NULL, name); - continue; - } - die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name); - } - while (objects) { - /* An object with name "foo\n0000000..." can be used to - * confuse downstream git-pack-objects very badly. - */ - const char *ep = strchr(objects->name, '\n'); - if (ep) { - printf("%s %.*s\n", sha1_to_hex(objects->item->sha1), - (int) (ep - objects->name), - objects->name); - } - else - printf("%s %s\n", sha1_to_hex(objects->item->sha1), objects->name); - objects = objects->next; - } + printf("-%s\n", sha1_to_hex(commit->object.sha1)); } /* @@ -267,41 +203,31 @@ static struct commit_list *find_bisection(struct commit_list *list) return best; } -static void mark_edge_parents_uninteresting(struct commit *commit) +static void read_revisions_from_stdin(struct rev_info *revs) { - struct commit_list *parents; - - for (parents = commit->parents; parents; parents = parents->next) { - struct commit *parent = parents->item; - if (!(parent->object.flags & UNINTERESTING)) - continue; - mark_tree_uninteresting(parent->tree); - if (revs.edge_hint && !(parent->object.flags & SHOWN)) { - parent->object.flags |= SHOWN; - printf("-%s\n", sha1_to_hex(parent->object.sha1)); - } - } -} + char line[1000]; -static void mark_edges_uninteresting(struct commit_list *list) -{ - for ( ; list; list = list->next) { - struct commit *commit = list->item; - - if (commit->object.flags & UNINTERESTING) { - mark_tree_uninteresting(commit->tree); - continue; - } - mark_edge_parents_uninteresting(commit); + while (fgets(line, sizeof(line), stdin) != NULL) { + int len = strlen(line); + if (line[len - 1] == '\n') + line[--len] = 0; + if (!len) + break; + if (line[0] == '-') + die("options not supported in --stdin mode"); + if (handle_revision_arg(line, revs, 0, 1)) + die("bad revision '%s'", line); } } -int cmd_rev_list(int argc, const char **argv, char **envp) +int cmd_rev_list(int argc, const char **argv, const char *prefix) { struct commit_list *list; int i; + int read_from_stdin = 0; - init_revisions(&revs); + git_config(git_default_config); + init_revisions(&revs, prefix); revs.abbrev = 0; revs.commit_format = CMIT_FMT_UNSPECIFIED; argc = setup_revisions(argc, argv, &revs, NULL); @@ -321,6 +247,12 @@ int cmd_rev_list(int argc, const char **argv, char **envp) bisect_list = 1; continue; } + if (!strcmp(arg, "--stdin")) { + if (read_from_stdin++) + die("--stdin given twice?"); + read_revisions_from_stdin(&revs); + continue; + } usage(rev_list_usage); } @@ -340,23 +272,23 @@ int cmd_rev_list(int argc, const char **argv, char **envp) if ((!list && (!(revs.tag_objects||revs.tree_objects||revs.blob_objects) && - !revs.pending_objects)) || + !revs.pending.nr)) || revs.diff) usage(rev_list_usage); - save_commit_buffer = revs.verbose_header; + save_commit_buffer = revs.verbose_header || revs.grep_filter; track_object_refs = 0; if (bisect_list) revs.limited = 1; prepare_revision_walk(&revs); if (revs.tree_objects) - mark_edges_uninteresting(revs.commits); + mark_edges_uninteresting(revs.commits, &revs, show_edge); if (bisect_list) revs.commits = find_bisection(revs.commits); - show_commit_list(&revs); + traverse_commit_list(&revs, show_commit, show_object); return 0; }