X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-rev-list.c;h=c2db5a5b037babf9020353d9b11dc348915b6c1b;hb=4b22f634a3f1752d98e1fc5eee4fa7ce0efe157c;hp=63bad0e96ade657bef21d9ca0e0de2e0ba8af61c;hpb=c0a2e1c0ba0956951b566888340e66589901b72d;p=git.git diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 63bad0e96..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,7 +93,7 @@ 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); @@ -93,110 +101,28 @@ static void show_commit(struct commit *commit) free_commit_list(commit->parents); commit->parents = NULL; } - if (commit->buffer) { - free(commit->buffer); - commit->buffer = NULL; - } -} - -static void process_blob(struct blob *blob, - struct object_array *p, - struct name_path *path, - const char *name) -{ - struct object *obj = &blob->object; - - if (!revs.blob_objects) - return; - if (obj->flags & (UNINTERESTING | SEEN)) - return; - obj->flags |= SEEN; - name = strdup(name); - add_object(obj, p, path, name); + free(commit->buffer); + commit->buffer = NULL; } -static void process_tree(struct tree *tree, - struct object_array *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; - if (obj->flags & (UNINTERESTING | SEEN)) - return; - if (parse_tree(tree) < 0) - die("bad tree object %s", sha1_to_hex(obj->sha1)); - obj->flags |= SEEN; - name = strdup(name); - 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)) - process_tree(lookup_tree(entry.sha1), p, &me, entry.path); - else - process_blob(lookup_blob(entry.sha1), p, &me, entry.path); + /* 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; + 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) { - int i; - struct commit *commit; - struct object_array objects = { 0, 0, NULL }; - - while ((commit = get_revision(revs)) != NULL) { - process_tree(commit->tree, &objects, NULL, ""); - show_commit(commit); - } - for (i = 0; i < revs->pending.nr; i++) { - struct object_array_entry *pending = revs->pending.objects + i; - struct object *obj = pending->item; - const char *name = pending->name; - if (obj->flags & (UNINTERESTING | SEEN)) - continue; - if (obj->type == TYPE_TAG) { - obj->flags |= SEEN; - add_object_array(obj, name, &objects); - continue; - } - if (obj->type == TYPE_TREE) { - process_tree((struct tree *)obj, &objects, NULL, name); - continue; - } - if (obj->type == TYPE_BLOB) { - process_blob((struct blob *)obj, &objects, NULL, name); - continue; - } - die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name); - } - for (i = 0; i < objects.nr; i++) { - struct object_array_entry *p = objects.objects + i; - - /* 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); - } - else - printf("%s %s\n", sha1_to_hex(p->item->sha1), p->name); - } + printf("-%s\n", sha1_to_hex(commit->object.sha1)); } /* @@ -277,41 +203,31 @@ static struct commit_list *find_bisection(struct commit_list *list) return best; } -static void mark_edge_parents_uninteresting(struct commit *commit) -{ - 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)); - } - } -} - -static void mark_edges_uninteresting(struct commit_list *list) +static void read_revisions_from_stdin(struct rev_info *revs) { - for ( ; list; list = list->next) { - struct commit *commit = list->item; + char line[1000]; - 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); @@ -331,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); } @@ -354,19 +276,19 @@ int cmd_rev_list(int argc, const char **argv, char **envp) 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; }