diff --git a/commit.h b/commit.h index 918c9ab5e4..de142afe73 100644 --- a/commit.h +++ b/commit.h @@ -45,6 +45,8 @@ enum cmit_fmt { CMIT_FMT_FULL, CMIT_FMT_FULLER, CMIT_FMT_ONELINE, + + CMIT_FMT_UNSPECIFIED, }; extern enum cmit_fmt get_commit_format(const char *arg); diff --git a/diff-tree.c b/diff-tree.c index 7015b06c7f..e578798537 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -3,7 +3,7 @@ #include "commit.h" #include "log-tree.h" -static struct log_tree_opt log_tree_opt; +static struct rev_info log_tree_opt; static int diff_tree_commit_sha1(const unsigned char *sha1) { @@ -62,47 +62,20 @@ int main(int argc, const char **argv) { int nr_sha1; char line[1000]; - unsigned char sha1[2][20]; - const char *prefix = setup_git_directory(); - static struct log_tree_opt *opt = &log_tree_opt; + struct object *tree1, *tree2; + static struct rev_info *opt = &log_tree_opt; + struct object_list *list; int read_stdin = 0; git_config(git_diff_config); nr_sha1 = 0; - init_log_tree_opt(opt); + init_revisions(opt); + opt->abbrev = 0; + argc = setup_revisions(argc, argv, opt, NULL); - for (;;) { - int opt_cnt; - const char *arg; + while (--argc > 0) { + const char *arg = *++argv; - argv++; - argc--; - arg = *argv; - if (!arg) - break; - - if (*arg != '-') { - if (nr_sha1 < 2 && !get_sha1(arg, sha1[nr_sha1])) { - nr_sha1++; - continue; - } - break; - } - - opt_cnt = log_tree_opt_parse(opt, argv, argc); - if (opt_cnt < 0) - usage(diff_tree_usage); - else if (opt_cnt) { - argv += opt_cnt - 1; - argc -= opt_cnt - 1; - continue; - } - - if (!strcmp(arg, "--")) { - argv++; - argc--; - break; - } if (!strcmp(arg, "--stdin")) { read_stdin = 1; continue; @@ -110,18 +83,36 @@ int main(int argc, const char **argv) usage(diff_tree_usage); } - if (opt->combine_merges) - opt->ignore_merges = 0; - - /* We can only do dense combined merges with diff output */ - if (opt->dense_combined_merges) - opt->diffopt.output_format = DIFF_FORMAT_PATCH; - - if (opt->diffopt.output_format == DIFF_FORMAT_PATCH) - opt->diffopt.recursive = 1; - - diff_tree_setup_paths(get_pathspec(prefix, argv), &opt->diffopt); - diff_setup_done(&opt->diffopt); + /* + * NOTE! "setup_revisions()" will have inserted the revisions + * it parsed in reverse order. So if you do + * + * git-diff-tree a b + * + * the commit list will be "b" -> "a" -> NULL, so we reverse + * the order of the objects if the first one is not marked + * UNINTERESTING. + */ + nr_sha1 = 0; + list = opt->pending_objects; + if (list) { + nr_sha1++; + tree1 = list->item; + list = list->next; + if (list) { + nr_sha1++; + tree2 = tree1; + tree1 = list->item; + if (list->next) + usage(diff_tree_usage); + /* Switch them around if the second one was uninteresting.. */ + if (tree2->flags & UNINTERESTING) { + struct object *tmp = tree2; + tree2 = tree1; + tree1 = tmp; + } + } + } switch (nr_sha1) { case 0: @@ -129,10 +120,12 @@ int main(int argc, const char **argv) usage(diff_tree_usage); break; case 1: - diff_tree_commit_sha1(sha1[0]); + diff_tree_commit_sha1(tree1->sha1); break; case 2: - diff_tree_sha1(sha1[0], sha1[1], "", &opt->diffopt); + diff_tree_sha1(tree1->sha1, + tree2->sha1, + "", &opt->diffopt); log_tree_diff_flush(opt); break; } diff --git a/git.c b/git.c index 2e0ae5e58e..239b26adfd 100644 --- a/git.c +++ b/git.c @@ -279,31 +279,28 @@ static int cmd_help(int argc, const char **argv, char **envp) #define LOGSIZE (65536) static int cmd_log_wc(int argc, const char **argv, char **envp, - struct whatchanged_opt *wcopt) + struct rev_info *rev) { struct commit *commit; char *buf = xmalloc(LOGSIZE); const char *commit_prefix = "commit "; int shown = 0; - struct rev_info *rev = &wcopt->revopt; - struct log_tree_opt *opt = &wcopt->logopt; - opt->commit_format = CMIT_FMT_DEFAULT; - wcopt->abbrev = DEFAULT_ABBREV; - argc = parse_whatchanged_opt(argc, argv, wcopt); - - if (opt->commit_format == CMIT_FMT_ONELINE) + if (argc > 1) + die("unrecognized argument: %s", argv[1]); + if (rev->commit_format == CMIT_FMT_ONELINE) commit_prefix = ""; prepare_revision_walk(rev); setup_pager(); while ((commit = get_revision(rev)) != NULL) { - if (shown && wcopt->do_diff && - opt->commit_format != CMIT_FMT_ONELINE) + if (shown && rev->diff && + rev->commit_format != CMIT_FMT_ONELINE) putchar('\n'); fputs(commit_prefix, stdout); - if (wcopt->abbrev_commit && wcopt->abbrev) - fputs(find_unique_abbrev(commit->object.sha1, wcopt->abbrev), + if (rev->abbrev_commit && rev->abbrev) + fputs(find_unique_abbrev(commit->object.sha1, + rev->abbrev), stdout); else fputs(sha1_to_hex(commit->object.sha1), stdout); @@ -326,16 +323,16 @@ static int cmd_log_wc(int argc, const char **argv, char **envp, parents = parents->next) parents->item->object.flags &= ~TMP_MARK; } - if (opt->commit_format == CMIT_FMT_ONELINE) + if (rev->commit_format == CMIT_FMT_ONELINE) putchar(' '); else putchar('\n'); - pretty_print_commit(opt->commit_format, commit, ~0, buf, - LOGSIZE, wcopt->abbrev); + pretty_print_commit(rev->commit_format, commit, ~0, buf, + LOGSIZE, rev->abbrev); printf("%s\n", buf); - if (wcopt->do_diff) { - printf("---\n"); - log_tree_commit(opt, commit); + if (rev->diff) { + printf("--\n"); + log_tree_commit(rev, commit); } shown = 1; free(commit->buffer); @@ -345,38 +342,47 @@ static int cmd_log_wc(int argc, const char **argv, char **envp, return 0; } -static int cmd_log(int ac, const char **av, char **ep) +static int cmd_wc(int argc, const char **argv, char **envp) { - struct whatchanged_opt wcopt; + struct rev_info rev; - memset(&wcopt, 0, sizeof(wcopt)); - init_log_tree_opt(&wcopt.logopt); - return cmd_log_wc(ac, av, ep, &wcopt); + init_revisions(&rev); + rev.abbrev = DEFAULT_ABBREV; + rev.no_commit_id = 1; + rev.commit_format = CMIT_FMT_DEFAULT; + rev.diff = 1; + rev.diffopt.recursive = 1; + argc = setup_revisions(argc, argv, &rev, "HEAD"); + return cmd_log_wc(argc, argv, envp, &rev); } -static int cmd_whatchanged(int ac, const char **av, char **ep) +static int cmd_show(int argc, const char **argv, char **envp) { - struct whatchanged_opt wcopt; + struct rev_info rev; - memset(&wcopt, 0, sizeof(wcopt)); - wcopt.do_diff = 1; - init_log_tree_opt(&wcopt.logopt); - wcopt.logopt.diffopt.recursive = 1; - return cmd_log_wc(ac, av, ep, &wcopt); + init_revisions(&rev); + rev.diff = 1; + rev.ignore_merges = 0; + rev.combine_merges = 1; + rev.dense_combined_merges = 1; + rev.abbrev = DEFAULT_ABBREV; + rev.commit_format = CMIT_FMT_DEFAULT; + rev.diffopt.recursive = 1; + rev.no_walk = 1; + argc = setup_revisions(argc, argv, &rev, "HEAD"); + return cmd_log_wc(argc, argv, envp, &rev); } -static int cmd_show(int ac, const char **av, char **ep) +static int cmd_log(int argc, const char **argv, char **envp) { - struct whatchanged_opt wcopt; + struct rev_info rev; - memset(&wcopt, 0, sizeof(wcopt)); - wcopt.do_diff = 1; - init_log_tree_opt(&wcopt.logopt); - wcopt.logopt.ignore_merges = 0; - wcopt.logopt.combine_merges = 1; - wcopt.logopt.dense_combined_merges = 1; - wcopt.logopt.diffopt.recursive = 1; - return cmd_log_wc(ac, av, ep, &wcopt); + init_revisions(&rev); + rev.abbrev = DEFAULT_ABBREV; + rev.no_commit_id = 1; + rev.commit_format = CMIT_FMT_DEFAULT; + argc = setup_revisions(argc, argv, &rev, "HEAD"); + return cmd_log_wc(argc, argv, envp, &rev); } static void handle_internal_command(int argc, const char **argv, char **envp) @@ -389,8 +395,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp) { "version", cmd_version }, { "help", cmd_help }, { "log", cmd_log }, + { "whatchanged", cmd_wc }, { "show", cmd_show }, - { "whatchanged", cmd_whatchanged }, }; int i; diff --git a/http-push.c b/http-push.c index 19a0f772e7..4a9dcf2bf6 100644 --- a/http-push.c +++ b/http-push.c @@ -2498,6 +2498,7 @@ int main(int argc, char **argv) commit_argv[3] = old_sha1_hex; commit_argc++; } + init_revisions(&revs); setup_revisions(commit_argc, commit_argv, &revs, NULL); free(new_sha1_hex); if (old_sha1_hex) { diff --git a/log-tree.c b/log-tree.c index 17e976a637..04a68e0f57 100644 --- a/log-tree.c +++ b/log-tree.c @@ -3,57 +3,7 @@ #include "commit.h" #include "log-tree.h" -void init_log_tree_opt(struct log_tree_opt *opt) -{ - memset(opt, 0, sizeof *opt); - opt->ignore_merges = 1; - opt->header_prefix = ""; - opt->commit_format = CMIT_FMT_RAW; - diff_setup(&opt->diffopt); -} - -int log_tree_opt_parse(struct log_tree_opt *opt, const char **av, int ac) -{ - const char *arg; - int cnt = diff_opt_parse(&opt->diffopt, av, ac); - if (0 < cnt) - return cnt; - arg = *av; - if (!strcmp(arg, "-r")) - opt->diffopt.recursive = 1; - else if (!strcmp(arg, "-t")) { - opt->diffopt.recursive = 1; - opt->diffopt.tree_in_recursive = 1; - } - else if (!strcmp(arg, "-m")) - opt->ignore_merges = 0; - else if (!strcmp(arg, "-c")) - opt->combine_merges = 1; - else if (!strcmp(arg, "--cc")) { - opt->dense_combined_merges = 1; - opt->combine_merges = 1; - } - else if (!strcmp(arg, "-v")) { - opt->verbose_header = 1; - opt->header_prefix = "diff-tree "; - } - else if (!strncmp(arg, "--pretty", 8)) { - opt->verbose_header = 1; - opt->header_prefix = "diff-tree "; - opt->commit_format = get_commit_format(arg+8); - } - else if (!strcmp(arg, "--root")) - opt->show_root_diff = 1; - else if (!strcmp(arg, "--no-commit-id")) - opt->no_commit_id = 1; - else if (!strcmp(arg, "--always")) - opt->always_show_header = 1; - else - return 0; - return 1; -} - -int log_tree_diff_flush(struct log_tree_opt *opt) +int log_tree_diff_flush(struct rev_info *opt) { diffcore_std(&opt->diffopt); if (diff_queue_is_empty()) { @@ -73,7 +23,7 @@ int log_tree_diff_flush(struct log_tree_opt *opt) return 1; } -static int diff_root_tree(struct log_tree_opt *opt, +static int diff_root_tree(struct rev_info *opt, const unsigned char *new, const char *base) { int retval; @@ -93,7 +43,7 @@ static int diff_root_tree(struct log_tree_opt *opt, return retval; } -static const char *generate_header(struct log_tree_opt *opt, +static const char *generate_header(struct rev_info *opt, const unsigned char *commit_sha1, const unsigned char *parent_sha1, const struct commit *commit) @@ -129,7 +79,7 @@ static const char *generate_header(struct log_tree_opt *opt, return this_header; } -static int do_diff_combined(struct log_tree_opt *opt, struct commit *commit) +static int do_diff_combined(struct rev_info *opt, struct commit *commit) { unsigned const char *sha1 = commit->object.sha1; @@ -142,7 +92,7 @@ static int do_diff_combined(struct log_tree_opt *opt, struct commit *commit) return 0; } -int log_tree_commit(struct log_tree_opt *opt, struct commit *commit) +int log_tree_commit(struct rev_info *opt, struct commit *commit) { struct commit_list *parents; unsigned const char *sha1 = commit->object.sha1; @@ -173,70 +123,3 @@ int log_tree_commit(struct log_tree_opt *opt, struct commit *commit) } return 0; } - -int parse_whatchanged_opt(int ac, const char **av, struct whatchanged_opt *wcopt) -{ - struct rev_info *rev = &wcopt->revopt; - struct log_tree_opt *opt = &wcopt->logopt; - const char **unrecognized = av+1; - int left = 1; - - ac = setup_revisions(ac, av, rev, "HEAD"); - if (!strcmp(av[0], "show")) - rev->no_walk = 1; - while (1 < ac) { - const char *arg = av[1]; - if (!strncmp(arg, "--pretty", 8)) { - opt->commit_format = get_commit_format(arg + 8); - } - else if (!strcmp(arg, "--no-abbrev")) { - wcopt->abbrev = 0; - } - else if (!strcmp(arg, "--abbrev")) { - wcopt->abbrev = DEFAULT_ABBREV; - } - else if (!strcmp(arg, "--abbrev-commit")) { - wcopt->abbrev_commit = 1; - } - else if (!strncmp(arg, "--abbrev=", 9)) { - wcopt->abbrev = strtoul(arg + 9, NULL, 10); - if (wcopt->abbrev && wcopt->abbrev < MINIMUM_ABBREV) - wcopt->abbrev = MINIMUM_ABBREV; - else if (40 < wcopt->abbrev) - wcopt->abbrev = 40; - } - else if (!strcmp(arg, "--full-diff")) { - wcopt->do_diff = 1; - wcopt->full_diff = 1; - } - else { - int cnt = log_tree_opt_parse(opt, av+1, ac-1); - if (0 < cnt) { - wcopt->do_diff = 1; - av += cnt; - ac -= cnt; - continue; - } - *unrecognized++ = arg; - left++; - } - ac--; av++; - } - - if (wcopt->do_diff) { - opt->diffopt.abbrev = wcopt->abbrev; - opt->verbose_header = 0; - opt->always_show_header = 0; - opt->no_commit_id = 1; - if (opt->combine_merges) - opt->ignore_merges = 0; - if (opt->dense_combined_merges) - opt->diffopt.output_format = DIFF_FORMAT_PATCH; - if (opt->diffopt.output_format == DIFF_FORMAT_PATCH) - opt->diffopt.recursive = 1; - if (!wcopt->full_diff && rev->prune_data) - diff_tree_setup_paths(rev->prune_data, &opt->diffopt); - diff_setup_done(&opt->diffopt); - } - return left; -} diff --git a/log-tree.h b/log-tree.h index 8d8f6f1458..91a909be73 100644 --- a/log-tree.h +++ b/log-tree.h @@ -3,34 +3,9 @@ #include "revision.h" -struct log_tree_opt { - struct diff_options diffopt; - int show_root_diff; - int no_commit_id; - int verbose_header; - int ignore_merges; - int combine_merges; - int dense_combined_merges; - int always_show_header; - const char *header_prefix; - const char *header; - enum cmit_fmt commit_format; -}; - -void init_log_tree_opt(struct log_tree_opt *); -int log_tree_diff_flush(struct log_tree_opt *); -int log_tree_commit(struct log_tree_opt *, struct commit *); -int log_tree_opt_parse(struct log_tree_opt *, const char **, int); - -struct whatchanged_opt { - struct rev_info revopt; - struct log_tree_opt logopt; - int abbrev; - int abbrev_commit; - int do_diff; - int full_diff; -}; - -int parse_whatchanged_opt(int, const char **, struct whatchanged_opt *); +void init_log_tree_opt(struct rev_info *); +int log_tree_diff_flush(struct rev_info *); +int log_tree_commit(struct rev_info *, struct commit *); +int log_tree_opt_parse(struct rev_info *, const char **, int); #endif diff --git a/rev-list.c b/rev-list.c index cb67b399fc..33741ebbc4 100644 --- a/rev-list.c +++ b/rev-list.c @@ -39,24 +39,20 @@ static const char rev_list_usage[] = struct rev_info revs; static int bisect_list = 0; -static int verbose_header = 0; -static int abbrev = DEFAULT_ABBREV; -static int abbrev_commit = 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 void show_commit(struct commit *commit) { if (show_timestamp) printf("%lu ", commit->date); - if (commit_prefix[0]) - fputs(commit_prefix, stdout); + if (*revs.header_prefix) + fputs(revs.header_prefix, stdout); if (commit->object.flags & BOUNDARY) putchar('-'); - if (abbrev_commit && abbrev) - fputs(find_unique_abbrev(commit->object.sha1, abbrev), stdout); + if (revs.abbrev_commit && revs.abbrev) + fputs(find_unique_abbrev(commit->object.sha1, revs.abbrev), + stdout); else fputs(sha1_to_hex(commit->object.sha1), stdout); if (revs.parents) { @@ -78,14 +74,16 @@ static void show_commit(struct commit *commit) parents = parents->next) parents->item->object.flags &= ~TMP_MARK; } - if (commit_format == CMIT_FMT_ONELINE) + if (revs.commit_format == CMIT_FMT_ONELINE) putchar(' '); else putchar('\n'); - if (verbose_header) { + if (revs.verbose_header) { static char pretty_header[16384]; - pretty_print_commit(commit_format, commit, ~0, pretty_header, sizeof(pretty_header), abbrev); + pretty_print_commit(revs.commit_format, commit, ~0, + pretty_header, sizeof(pretty_header), + revs.abbrev); printf("%s%c", pretty_header, hdr_termination); } fflush(stdout); @@ -297,58 +295,16 @@ int main(int argc, const char **argv) struct commit_list *list; int i; + init_revisions(&revs); + revs.abbrev = 0; + revs.commit_format = CMIT_FMT_UNSPECIFIED; argc = setup_revisions(argc, argv, &revs, NULL); for (i = 1 ; i < argc; i++) { const char *arg = argv[i]; - /* accept -, like traditilnal "head" */ - if ((*arg == '-') && isdigit(arg[1])) { - revs.max_count = atoi(arg + 1); - continue; - } - if (!strcmp(arg, "-n")) { - if (++i >= argc) - die("-n requires an argument"); - revs.max_count = atoi(argv[i]); - continue; - } - if (!strncmp(arg,"-n",2)) { - revs.max_count = atoi(arg + 2); - continue; - } if (!strcmp(arg, "--header")) { - verbose_header = 1; - continue; - } - if (!strcmp(arg, "--no-abbrev")) { - abbrev = 0; - continue; - } - if (!strcmp(arg, "--abbrev")) { - abbrev = DEFAULT_ABBREV; - continue; - } - if (!strcmp(arg, "--abbrev-commit")) { - abbrev_commit = 1; - continue; - } - if (!strncmp(arg, "--abbrev=", 9)) { - abbrev = strtoul(arg + 9, NULL, 10); - if (abbrev && abbrev < MINIMUM_ABBREV) - abbrev = MINIMUM_ABBREV; - else if (40 < abbrev) - abbrev = 40; - continue; - } - if (!strncmp(arg, "--pretty", 8)) { - commit_format = get_commit_format(arg+8); - verbose_header = 1; - hdr_termination = '\n'; - if (commit_format == CMIT_FMT_ONELINE) - commit_prefix = ""; - else - commit_prefix = "commit "; + revs.verbose_header = 1; continue; } if (!strcmp(arg, "--timestamp")) { @@ -362,14 +318,24 @@ int main(int argc, const char **argv) usage(rev_list_usage); } + if (revs.commit_format != CMIT_FMT_UNSPECIFIED) { + /* The command line has a --pretty */ + hdr_termination = '\n'; + if (revs.commit_format == CMIT_FMT_ONELINE) + revs.header_prefix = ""; + else + revs.header_prefix = "commit "; + } list = revs.commits; - if (!list && - (!(revs.tag_objects||revs.tree_objects||revs.blob_objects) && !revs.pending_objects)) + if ((!list && + (!(revs.tag_objects||revs.tree_objects||revs.blob_objects) && + !revs.pending_objects)) || + revs.diff) usage(rev_list_usage); - save_commit_buffer = verbose_header; + save_commit_buffer = revs.verbose_header; track_object_refs = 0; if (bisect_list) revs.limited = 1; diff --git a/revision.c b/revision.c index 0c3c392fde..f8fb028855 100644 --- a/revision.c +++ b/revision.c @@ -116,21 +116,27 @@ static void add_pending_object(struct rev_info *revs, struct object *obj, const add_object(obj, &revs->pending_objects, NULL, name); } -static struct commit *get_commit_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags) +static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags) { struct object *object; object = parse_object(sha1); if (!object) die("bad object %s", name); + object->flags |= flags; + return object; +} + +static struct commit *handle_commit(struct rev_info *revs, struct object *object, const char *name) +{ + unsigned long flags = object->flags; /* * Tag object? Look what it points to.. */ while (object->type == tag_type) { struct tag *tag = (struct tag *) object; - object->flags |= flags; - if (revs->tag_objects && !(object->flags & UNINTERESTING)) + if (revs->tag_objects && !(flags & UNINTERESTING)) add_pending_object(revs, object, tag->tag); object = parse_object(tag->tagged->sha1); if (!object) @@ -143,7 +149,6 @@ static struct commit *get_commit_reference(struct rev_info *revs, const char *na */ if (object->type == commit_type) { struct commit *commit = (struct commit *)object; - object->flags |= flags; if (parse_commit(commit) < 0) die("unable to parse commit %s", name); if (flags & UNINTERESTING) { @@ -241,7 +246,7 @@ int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2) return REV_TREE_DIFFERENT; tree_difference = REV_TREE_SAME; if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "", - &revs->diffopt) < 0) + &revs->pruning) < 0) return REV_TREE_DIFFERENT; return tree_difference; } @@ -264,7 +269,7 @@ int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1) empty.size = 0; tree_difference = 0; - retval = diff_tree(&empty, &real, "", &revs->diffopt); + retval = diff_tree(&empty, &real, "", &revs->pruning); free(tree); return retval >= 0 && !tree_difference; @@ -454,21 +459,13 @@ static void limit_list(struct rev_info *revs) revs->commits = newlist; } -static void add_one_commit(struct commit *commit, struct rev_info *revs) -{ - if (!commit || (commit->object.flags & SEEN)) - return; - commit->object.flags |= SEEN; - commit_list_insert(commit, &revs->commits); -} - static int all_flags; static struct rev_info *all_revs; static int handle_one_ref(const char *path, const unsigned char *sha1) { - struct commit *commit = get_commit_reference(all_revs, path, sha1, all_flags); - add_one_commit(commit, all_revs); + struct object *object = get_reference(all_revs, path, sha1, all_flags); + add_pending_object(all_revs, object, ""); return 0; } @@ -482,9 +479,12 @@ static void handle_all(struct rev_info *revs, unsigned flags) void init_revisions(struct rev_info *revs) { memset(revs, 0, sizeof(*revs)); - revs->diffopt.recursive = 1; - revs->diffopt.add_remove = file_add_remove; - revs->diffopt.change = file_change; + + revs->abbrev = DEFAULT_ABBREV; + revs->ignore_merges = 1; + revs->pruning.recursive = 1; + revs->pruning.add_remove = file_add_remove; + revs->pruning.change = file_change; revs->lifo = 1; revs->dense = 1; revs->prefix = setup_git_directory(); @@ -497,6 +497,11 @@ void init_revisions(struct rev_info *revs) revs->topo_setter = topo_sort_default_setter; revs->topo_getter = topo_sort_default_getter; + + revs->header_prefix = ""; + revs->commit_format = CMIT_FMT_DEFAULT; + + diff_setup(&revs->diffopt); } /* @@ -512,8 +517,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch const char **unrecognized = argv + 1; int left = 1; - init_revisions(revs); - /* First, search for "--" */ seen_dashdash = 0; for (i = 1; i < argc; i++) { @@ -529,13 +532,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch flags = 0; for (i = 1; i < argc; i++) { - struct commit *commit; + struct object *object; const char *arg = argv[i]; unsigned char sha1[20]; char *dotdot; int local_flags; if (*arg == '-') { + int opts; if (!strncmp(arg, "--max-count=", 12)) { revs->max_count = atoi(arg + 12); continue; @@ -643,6 +647,78 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->unpacked = 1; continue; } + if (!strcmp(arg, "-r")) { + revs->diff = 1; + revs->diffopt.recursive = 1; + continue; + } + if (!strcmp(arg, "-t")) { + revs->diff = 1; + revs->diffopt.recursive = 1; + revs->diffopt.tree_in_recursive = 1; + continue; + } + if (!strcmp(arg, "-m")) { + revs->ignore_merges = 0; + continue; + } + if (!strcmp(arg, "-c")) { + revs->diff = 1; + revs->combine_merges = 1; + continue; + } + if (!strcmp(arg, "--cc")) { + revs->diff = 1; + revs->dense_combined_merges = 1; + revs->combine_merges = 1; + continue; + } + if (!strcmp(arg, "-v")) { + revs->verbose_header = 1; + revs->header_prefix = "diff-tree "; + continue; + } + if (!strncmp(arg, "--pretty", 8)) { + revs->verbose_header = 1; + revs->header_prefix = "diff-tree "; + revs->commit_format = get_commit_format(arg+8); + continue; + } + if (!strcmp(arg, "--root")) { + revs->show_root_diff = 1; + continue; + } + if (!strcmp(arg, "--no-commit-id")) { + revs->no_commit_id = 1; + continue; + } + if (!strcmp(arg, "--always")) { + revs->always_show_header = 1; + continue; + } + if (!strcmp(arg, "--no-abbrev")) { + revs->abbrev = 0; + continue; + } + if (!strcmp(arg, "--abbrev")) { + revs->abbrev = DEFAULT_ABBREV; + continue; + } + if (!strcmp(arg, "--abbrev-commit")) { + revs->abbrev_commit = 1; + continue; + } + if (!strcmp(arg, "--full-diff")) { + revs->diff = 1; + revs->full_diff = 1; + continue; + } + opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i); + if (opts > 0) { + revs->diff = 1; + i += opts - 1; + continue; + } *unrecognized++ = arg; left++; continue; @@ -659,15 +735,15 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch this = "HEAD"; if (!get_sha1(this, from_sha1) && !get_sha1(next, sha1)) { - struct commit *exclude; - struct commit *include; + struct object *exclude; + struct object *include; - exclude = get_commit_reference(revs, this, from_sha1, flags ^ UNINTERESTING); - include = get_commit_reference(revs, next, sha1, flags); + exclude = get_reference(revs, this, from_sha1, flags ^ UNINTERESTING); + include = get_reference(revs, next, sha1, flags); if (!exclude || !include) die("Invalid revision range %s..%s", arg, next); - add_one_commit(exclude, revs); - add_one_commit(include, revs); + add_pending_object(revs, exclude, this); + add_pending_object(revs, include, next); continue; } *dotdot = '.'; @@ -692,34 +768,59 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->prune_data = get_pathspec(revs->prefix, argv + i); break; } - commit = get_commit_reference(revs, arg, sha1, flags ^ local_flags); - add_one_commit(commit, revs); + object = get_reference(revs, arg, sha1, flags ^ local_flags); + add_pending_object(revs, object, arg); } - if (def && !revs->commits) { + if (def && !revs->pending_objects) { unsigned char sha1[20]; - struct commit *commit; + struct object *object; if (get_sha1(def, sha1) < 0) die("bad default revision '%s'", def); - commit = get_commit_reference(revs, def, sha1, 0); - add_one_commit(commit, revs); + object = get_reference(revs, def, sha1, 0); + add_pending_object(revs, object, def); } if (revs->topo_order || revs->unpacked) revs->limited = 1; if (revs->prune_data) { - diff_tree_setup_paths(revs->prune_data, &revs->diffopt); + diff_tree_setup_paths(revs->prune_data, &revs->pruning); revs->prune_fn = try_to_simplify_commit; + if (!revs->full_diff) + diff_tree_setup_paths(revs->prune_data, &revs->diffopt); } + if (revs->combine_merges) { + revs->ignore_merges = 0; + if (revs->dense_combined_merges) + revs->diffopt.output_format = DIFF_FORMAT_PATCH; + } + if (revs->diffopt.output_format == DIFF_FORMAT_PATCH) + revs->diffopt.recursive = 1; + revs->diffopt.abbrev = revs->abbrev; + diff_setup_done(&revs->diffopt); return left; } void prepare_revision_walk(struct rev_info *revs) { + struct object_list *list; + + list = revs->pending_objects; + revs->pending_objects = NULL; + while (list) { + struct commit *commit = handle_commit(revs, list->item, list->name); + if (commit) { + if (!(commit->object.flags & SEEN)) { + commit->object.flags |= SEEN; + insert_by_date(commit, &revs->commits); + } + } + list = list->next; + } + if (revs->no_walk) return; - sort_by_date(&revs->commits); if (revs->limited) limit_list(revs); if (revs->topo_order) diff --git a/revision.h b/revision.h index ff2a13ea87..7b854866b2 100644 --- a/revision.h +++ b/revision.h @@ -39,13 +39,32 @@ struct rev_info { boundary:1, parents:1; + /* Diff flags */ + unsigned int diff:1, + full_diff:1, + show_root_diff:1, + no_commit_id:1, + verbose_header:1, + ignore_merges:1, + combine_merges:1, + dense_combined_merges:1, + always_show_header:1; + + /* Format info */ + unsigned int abbrev_commit:1; + unsigned int abbrev; + enum cmit_fmt commit_format; + const char *header_prefix; + const char *header; + /* special limits */ int max_count; unsigned long max_age; unsigned long min_age; - /* paths limiting */ + /* diff info for patches and for paths limiting */ struct diff_options diffopt; + struct diff_options pruning; topo_sort_set_fn_t topo_setter; topo_sort_get_fn_t topo_getter;