diff options
Diffstat (limited to 'revision.c')
-rw-r--r-- | revision.c | 138 |
1 files changed, 89 insertions, 49 deletions
@@ -23,7 +23,7 @@ #include "bisect.h" #include "packfile.h" #include "worktree.h" -#include "argv-array.h" +#include "strvec.h" #include "commit-reach.h" #include "commit-graph.h" #include "prio-queue.h" @@ -634,7 +634,6 @@ static unsigned int count_bloom_filter_maybe; static unsigned int count_bloom_filter_definitely_not; static unsigned int count_bloom_filter_false_positive; static unsigned int count_bloom_filter_not_present; -static unsigned int count_bloom_filter_length_zero; static void trace2_bloom_filter_statistics_atexit(void) { @@ -642,7 +641,6 @@ static void trace2_bloom_filter_statistics_atexit(void) jw_object_begin(&jw, 0); jw_object_intmax(&jw, "filter_not_present", count_bloom_filter_not_present); - jw_object_intmax(&jw, "zero_length_filter", count_bloom_filter_length_zero); jw_object_intmax(&jw, "maybe", count_bloom_filter_maybe); jw_object_intmax(&jw, "definitely_not", count_bloom_filter_definitely_not); jw_object_intmax(&jw, "false_positive", count_bloom_filter_false_positive); @@ -671,9 +669,9 @@ static void prepare_to_use_bloom_filter(struct rev_info *revs) { struct pathspec_item *pi; char *path_alloc = NULL; - const char *path; - int last_index; - int len; + const char *path, *p; + size_t len; + int path_component_nr = 1; if (!revs->commits) return; @@ -694,20 +692,48 @@ static void prepare_to_use_bloom_filter(struct rev_info *revs) return; pi = &revs->pruning.pathspec.items[0]; - last_index = pi->len - 1; /* remove single trailing slash from path, if needed */ - if (pi->match[last_index] == '/') { - path_alloc = xstrdup(pi->match); - path_alloc[last_index] = '\0'; - path = path_alloc; + if (pi->len > 0 && pi->match[pi->len - 1] == '/') { + path_alloc = xmemdupz(pi->match, pi->len - 1); + path = path_alloc; } else - path = pi->match; + path = pi->match; len = strlen(path); + if (!len) { + revs->bloom_filter_settings = NULL; + free(path_alloc); + return; + } + + p = path; + while (*p) { + /* + * At this point, the path is normalized to use Unix-style + * path separators. This is required due to how the + * changed-path Bloom filters store the paths. + */ + if (*p == '/') + path_component_nr++; + p++; + } + + revs->bloom_keys_nr = path_component_nr; + ALLOC_ARRAY(revs->bloom_keys, revs->bloom_keys_nr); - revs->bloom_key = xmalloc(sizeof(struct bloom_key)); - fill_bloom_key(path, len, revs->bloom_key, revs->bloom_filter_settings); + fill_bloom_key(path, len, &revs->bloom_keys[0], + revs->bloom_filter_settings); + path_component_nr = 1; + + p = path + len - 1; + while (p > path) { + if (*p == '/') + fill_bloom_key(path, p - path, + &revs->bloom_keys[path_component_nr++], + revs->bloom_filter_settings); + p--; + } if (trace2_is_enabled() && !bloom_filter_atexit_registered) { atexit(trace2_bloom_filter_statistics_atexit); @@ -721,7 +747,7 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs, struct commit *commit) { struct bloom_filter *filter; - int result; + int result = 1, j; if (!revs->repo->objects->commit_graph) return -1; @@ -736,15 +762,12 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs, return -1; } - if (!filter->len) { - count_bloom_filter_length_zero++; - return -1; + for (j = 0; result && j < revs->bloom_keys_nr; j++) { + result = bloom_filter_contains(filter, + &revs->bloom_keys[j], + revs->bloom_filter_settings); } - result = bloom_filter_contains(filter, - revs->bloom_key, - revs->bloom_filter_settings); - if (result) count_bloom_filter_maybe++; else @@ -783,7 +806,7 @@ static int rev_compare_tree(struct rev_info *revs, return REV_TREE_SAME; } - if (revs->bloom_key && !nth_parent) { + if (revs->bloom_keys_nr && !nth_parent) { bloom_ret = check_maybe_different_in_bloom_filter(revs, commit); if (bloom_ret == 0) @@ -792,9 +815,7 @@ static int rev_compare_tree(struct rev_info *revs, tree_difference = REV_TREE_SAME; revs->pruning.flags.has_changes = 0; - if (diff_tree_oid(&t1->object.oid, &t2->object.oid, "", - &revs->pruning) < 0) - return REV_TREE_DIFFERENT; + diff_tree_oid(&t1->object.oid, &t2->object.oid, "", &revs->pruning); if (!nth_parent) if (bloom_ret == 1 && tree_difference == REV_TREE_SAME) @@ -805,7 +826,6 @@ static int rev_compare_tree(struct rev_info *revs, static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit) { - int retval; struct tree *t1 = get_commit_tree(commit); if (!t1) @@ -813,9 +833,9 @@ static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit) tree_difference = REV_TREE_SAME; revs->pruning.flags.has_changes = 0; - retval = diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning); + diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning); - return retval >= 0 && (tree_difference == REV_TREE_SAME); + return tree_difference == REV_TREE_SAME; } struct treesame_state { @@ -1796,7 +1816,7 @@ void repo_init_revisions(struct repository *r, revs->repo = r; revs->abbrev = DEFAULT_ABBREV; - revs->ignore_merges = 1; + revs->ignore_merges = -1; revs->simplify_history = 1; revs->pruning.repo = r; revs->pruning.flags.recursive = 1; @@ -1998,7 +2018,7 @@ static int handle_dotdot(const char *arg, return ret; } -int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsigned revarg_opt) +static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int flags, unsigned revarg_opt) { struct object_context oc; char *mark; @@ -2073,15 +2093,23 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi return 0; } +int handle_revision_arg(const char *arg, struct rev_info *revs, int flags, unsigned revarg_opt) +{ + int ret = handle_revision_arg_1(arg, revs, flags, revarg_opt); + if (!ret) + revs->rev_input_given = 1; + return ret; +} + static void read_pathspec_from_stdin(struct strbuf *sb, - struct argv_array *prune) + struct strvec *prune) { while (strbuf_getline(sb, stdin) != EOF) - argv_array_push(prune, sb->buf); + strvec_push(prune, sb->buf); } static void read_revisions_from_stdin(struct rev_info *revs, - struct argv_array *prune) + struct strvec *prune) { struct strbuf sb; int seen_dashdash = 0; @@ -2316,7 +2344,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg } else if (!strcmp(arg, "--unpacked")) { revs->unpacked = 1; } else if (starts_with(arg, "--unpacked=")) { - die("--unpacked=<packfile> no longer supported."); + die(_("--unpacked=<packfile> no longer supported")); } else if (!strcmp(arg, "-r")) { revs->diff = 1; revs->diffopt.flags.recursive = 1; @@ -2325,7 +2353,22 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->diffopt.flags.recursive = 1; revs->diffopt.flags.tree_in_recursive = 1; } else if (!strcmp(arg, "-m")) { + /* + * To "diff-index", "-m" means "match missing", and to the "log" + * family of commands, it means "show full diff for merges". Set + * both fields appropriately. + */ revs->ignore_merges = 0; + revs->match_missing = 1; + } else if ((argcount = parse_long_opt("diff-merges", argv, &optarg))) { + if (!strcmp(optarg, "off")) { + revs->ignore_merges = 1; + } else { + die(_("unknown value for --diff-merges: %s"), optarg); + } + return argcount; + } else if (!strcmp(arg, "--no-diff-merges")) { + revs->ignore_merges = 1; } else if (!strcmp(arg, "-c")) { revs->diff = 1; revs->dense_combined_merges = 0; @@ -2675,8 +2718,8 @@ static void NORETURN diagnose_missing_default(const char *def) */ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct setup_revision_opt *opt) { - int i, flags, left, seen_dashdash, got_rev_arg = 0, revarg_opt; - struct argv_array prune_data = ARGV_ARRAY_INIT; + int i, flags, left, seen_dashdash, revarg_opt; + struct strvec prune_data = STRVEC_INIT; const char *submodule = NULL; int seen_end_of_options = 0; @@ -2695,7 +2738,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s argv[i] = NULL; argc = i; if (argv[i + 1]) - argv_array_pushv(&prune_data, argv + i + 1); + strvec_pushv(&prune_data, argv + i + 1); seen_dashdash = 1; break; } @@ -2761,14 +2804,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s for (j = i; j < argc; j++) verify_filename(revs->prefix, argv[j], j == i); - argv_array_pushv(&prune_data, argv + i); + strvec_pushv(&prune_data, argv + i); break; } - else - got_rev_arg = 1; } - if (prune_data.argc) { + if (prune_data.nr) { /* * If we need to introduce the magic "a lone ':' means no * pathspec whatsoever", here is the place to do so. @@ -2784,9 +2825,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s * } */ parse_pathspec(&revs->prune_data, 0, 0, - revs->prefix, prune_data.argv); + revs->prefix, prune_data.v); } - argv_array_clear(&prune_data); + strvec_clear(&prune_data); if (revs->def == NULL) revs->def = opt ? opt->def : NULL; @@ -2794,7 +2835,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s opt->tweak(revs, opt); if (revs->show_merge) prepare_show_merge(revs); - if (revs->def && !revs->pending.nr && !revs->rev_input_given && !got_rev_arg) { + if (revs->def && !revs->pending.nr && !revs->rev_input_given) { struct object_id oid; struct object *object; struct object_context oc; @@ -2835,8 +2876,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s copy_pathspec(&revs->diffopt.pathspec, &revs->prune_data); } - if (revs->combine_merges) + if (revs->combine_merges && revs->ignore_merges < 0) revs->ignore_merges = 0; + if (revs->ignore_merges < 0) + revs->ignore_merges = 1; if (revs->combined_all_paths && !revs->combine_merges) die("--combined-all-paths makes no sense without -c or --cc"); @@ -2870,9 +2913,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s if (!revs->reflog_info && revs->grep_filter.use_reflog_filter) die("cannot use --grep-reflog without --walk-reflogs"); - if (revs->first_parent_only && revs->bisect) - die(_("--first-parent is incompatible with --bisect")); - if (revs->line_level_traverse && (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT))) die(_("-L does not yet support diff formats besides -p and -s")); |