From: Junio C Hamano Date: Thu, 17 Nov 2016 21:45:22 +0000 (-0800) Subject: Merge branch 'tk/diffcore-delta-remove-unused' X-Git-Tag: v2.11.0-rc2~1 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/6d40812e4b5d2128665351f4b427c7da7c7d86d5?ds=inline;hp=-c Merge branch 'tk/diffcore-delta-remove-unused' Code cleanup. * tk/diffcore-delta-remove-unused: diffcore-delta: remove unused parameter to diffcore_count_changes() --- 6d40812e4b5d2128665351f4b427c7da7c7d86d5 diff --combined diff.c index 8981477c43,bbb8977539..ec8728362d --- a/diff.c +++ b/diff.c @@@ -18,7 -18,6 +18,7 @@@ #include "ll-merge.h" #include "string-list.h" #include "argv-array.h" +#include "graph.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@@ -27,8 -26,6 +27,8 @@@ #endif static int diff_detect_rename_default; +static int diff_indent_heuristic; /* experimental */ +static int diff_compaction_heuristic; /* experimental */ static int diff_rename_limit_default = 400; static int diff_suppress_blank_empty; static int diff_use_color_default = -1; @@@ -43,7 -40,6 +43,7 @@@ static int diff_stat_graph_width static int diff_dirstat_permille_default = 30; static struct diff_options default_diff_options; static long diff_algorithm; +static unsigned ws_error_highlight_default = WSEH_NEW; static char diff_colors[][COLOR_MAXLEN] = { GIT_COLOR_RESET, @@@ -57,11 -53,6 +57,11 @@@ GIT_COLOR_NORMAL, /* FUNCINFO */ }; +static NORETURN void die_want_option(const char *option_name) +{ + die(_("option '%s' requires a value"), option_name); +} + static int parse_diff_color_slot(const char *var) { if (!strcasecmp(var, "context") || !strcasecmp(var, "plain")) @@@ -139,11 -130,9 +139,11 @@@ static int parse_dirstat_params(struct static int parse_submodule_params(struct diff_options *options, const char *value) { if (!strcmp(value, "log")) - DIFF_OPT_SET(options, SUBMODULE_LOG); + options->submodule_format = DIFF_SUBMODULE_LOG; else if (!strcmp(value, "short")) - DIFF_OPT_CLR(options, SUBMODULE_LOG); + options->submodule_format = DIFF_SUBMODULE_SHORT; + else if (!strcmp(value, "diff")) + options->submodule_format = DIFF_SUBMODULE_INLINE_DIFF; else return -1; return 0; @@@ -173,69 -162,12 +173,69 @@@ long parse_algorithm_value(const char * return -1; } +static int parse_one_token(const char **arg, const char *token) +{ + const char *rest; + if (skip_prefix(*arg, token, &rest) && (!*rest || *rest == ',')) { + *arg = rest; + return 1; + } + return 0; +} + +static int parse_ws_error_highlight(const char *arg) +{ + const char *orig_arg = arg; + unsigned val = 0; + + while (*arg) { + if (parse_one_token(&arg, "none")) + val = 0; + else if (parse_one_token(&arg, "default")) + val = WSEH_NEW; + else if (parse_one_token(&arg, "all")) + val = WSEH_NEW | WSEH_OLD | WSEH_CONTEXT; + else if (parse_one_token(&arg, "new")) + val |= WSEH_NEW; + else if (parse_one_token(&arg, "old")) + val |= WSEH_OLD; + else if (parse_one_token(&arg, "context")) + val |= WSEH_CONTEXT; + else { + return -1 - (int)(arg - orig_arg); + } + if (*arg) + arg++; + } + return val; +} + /* * These are to give UI layer defaults. * The core-level commands such as git-diff-files should * never be affected by the setting of diff.renames * the user happens to have in the configuration file. */ +void init_diff_ui_defaults(void) +{ + diff_detect_rename_default = 1; +} + +int git_diff_heuristic_config(const char *var, const char *value, void *cb) +{ + if (!strcmp(var, "diff.indentheuristic")) { + diff_indent_heuristic = git_config_bool(var, value); + if (diff_indent_heuristic) + diff_compaction_heuristic = 0; + } + if (!strcmp(var, "diff.compactionheuristic")) { + diff_compaction_heuristic = git_config_bool(var, value); + if (diff_compaction_heuristic) + diff_indent_heuristic = 0; + } + return 0; +} + int git_diff_ui_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { @@@ -292,17 -224,6 +292,17 @@@ return 0; } + if (git_diff_heuristic_config(var, value, cb) < 0) + return -1; + + if (!strcmp(var, "diff.wserrorhighlight")) { + int val = parse_ws_error_highlight(value); + if (val < 0) + return -1; + ws_error_highlight_default = val; + return 0; + } + if (git_color_config(var, value, cb) < 0) return -1; @@@ -423,6 -344,7 +423,6 @@@ struct emit_callback const char **label_path; struct diff_words_data *diff_words; struct diff_options *opt; - int *found_changesp; struct strbuf *header; }; @@@ -790,6 -712,7 +790,6 @@@ static void emit_rewrite_diff(const cha memset(&ecbdata, 0, sizeof(ecbdata)); ecbdata.color_diff = want_color(o->use_color); - ecbdata.found_changesp = &o->found_changes; ecbdata.ws_rule = whitespace_rule(name_b); ecbdata.opt = o; if (ecbdata.ws_rule & WS_BLANK_AT_EOF) { @@@ -1018,8 -941,7 +1018,8 @@@ static int find_word_boundaries(mmfile_ { if (word_regex && *begin < buffer->size) { regmatch_t match[1]; - if (!regexec(word_regex, buffer->ptr + *begin, 1, match, 0)) { + if (!regexec_buf(word_regex, buffer->ptr + *begin, + buffer->size - *begin, 1, match, 0)) { char *p = memchr(buffer->ptr + *begin + match[0].rm_so, '\n', match[0].rm_eo - match[0].rm_so); *end = p ? p - buffer->ptr : match[0].rm_eo + *begin; @@@ -1284,13 -1206,12 +1284,13 @@@ static void fn_out_consume(void *priv, struct diff_options *o = ecbdata->opt; const char *line_prefix = diff_line_prefix(o); + o->found_changes = 1; + if (ecbdata->header) { - fprintf(ecbdata->opt->file, "%s", ecbdata->header->buf); + fprintf(o->file, "%s", ecbdata->header->buf); strbuf_reset(ecbdata->header); ecbdata->header = NULL; } - *(ecbdata->found_changesp) = 1; if (ecbdata->label_path[0]) { const char *name_a_tab, *name_b_tab; @@@ -1298,9 -1219,9 +1298,9 @@@ name_a_tab = strchr(ecbdata->label_path[0], ' ') ? "\t" : ""; name_b_tab = strchr(ecbdata->label_path[1], ' ') ? "\t" : ""; - fprintf(ecbdata->opt->file, "%s%s--- %s%s%s\n", + fprintf(o->file, "%s%s--- %s%s%s\n", line_prefix, meta, ecbdata->label_path[0], reset, name_a_tab); - fprintf(ecbdata->opt->file, "%s%s+++ %s%s%s\n", + fprintf(o->file, "%s%s+++ %s%s%s\n", line_prefix, meta, ecbdata->label_path[1], reset, name_b_tab); ecbdata->label_path[0] = ecbdata->label_path[1] = NULL; } @@@ -1318,7 -1239,15 +1318,7 @@@ find_lno(line, ecbdata); emit_hunk_header(ecbdata, line, len); if (line[len-1] != '\n') - putc('\n', ecbdata->opt->file); - return; - } - - if (len < 1) { - emit_line(ecbdata->opt, reset, reset, line, len); - if (ecbdata->diff_words - && ecbdata->diff_words->type == DIFF_WORDS_PORCELAIN) - fputs("~\n", ecbdata->opt->file); + putc('\n', o->file); return; } @@@ -1343,8 -1272,8 +1343,8 @@@ } diff_words_flush(ecbdata); if (ecbdata->diff_words->type == DIFF_WORDS_PORCELAIN) { - emit_line(ecbdata->opt, context, reset, line, len); - fputs("~\n", ecbdata->opt->file); + emit_line(o, context, reset, line, len); + fputs("~\n", o->file); } else { /* * Skip the prefix character, if any. With @@@ -1355,7 -1284,7 +1355,7 @@@ line++; len--; } - emit_line(ecbdata->opt, context, reset, line, len); + emit_line(o, context, reset, line, len); } return; } @@@ -1377,7 -1306,8 +1377,7 @@@ default: /* incomplete line at the end */ ecbdata->lno_in_preimage++; - emit_line(ecbdata->opt, - diff_get_color(ecbdata->color_diff, DIFF_CONTEXT), + emit_line(o, diff_get_color(ecbdata->color_diff, DIFF_CONTEXT), reset, line, len); break; } @@@ -1685,7 -1615,7 +1685,7 @@@ static void show_stats(struct diffstat_ */ if (options->stat_width == -1) - width = term_columns() - options->output_prefix_length; + width = term_columns() - strlen(line_prefix); else width = options->stat_width ? options->stat_width : 80; number_width = decimal_width(max_change) > number_width ? @@@ -1993,8 -1923,8 +1993,8 @@@ static void show_dirstat(struct diff_op name = p->two->path ? p->two->path : p->one->path; - if (p->one->sha1_valid && p->two->sha1_valid) - content_changed = hashcmp(p->one->sha1, p->two->sha1); + if (p->one->oid_valid && p->two->oid_valid) + content_changed = oidcmp(&p->one->oid, &p->two->oid); else content_changed = 1; @@@ -2023,7 -1953,7 +2023,7 @@@ if (DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) { diff_populate_filespec(p->one, 0); diff_populate_filespec(p->two, 0); - diffcore_count_changes(p->one, p->two, NULL, NULL, 0, + diffcore_count_changes(p->one, p->two, NULL, NULL, &copied, &added); diff_free_filespec_data(p->one); diff_free_filespec_data(p->two); @@@ -2066,7 -1996,7 +2066,7 @@@ found_damage return; /* Show all directories with more than x% of the changes */ - qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare); + QSORT(dir.files, dir.nr, dirstat_compare); gather_dirstat(options, &dir, changed, "", 0); } @@@ -2110,7 -2040,7 +2110,7 @@@ static void show_dirstat_by_line(struc return; /* Show all directories with more than x% of the changes */ - qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare); + QSORT(dir.files, dir.nr, dirstat_compare); gather_dirstat(options, &dir, changed, "", 0); } @@@ -2359,37 -2289,16 +2359,37 @@@ static void builtin_diff(const char *na struct strbuf header = STRBUF_INIT; const char *line_prefix = diff_line_prefix(o); - if (DIFF_OPT_TST(o, SUBMODULE_LOG) && - (!one->mode || S_ISGITLINK(one->mode)) && - (!two->mode || S_ISGITLINK(two->mode))) { + diff_set_mnemonic_prefix(o, "a/", "b/"); + if (DIFF_OPT_TST(o, REVERSE_DIFF)) { + a_prefix = o->b_prefix; + b_prefix = o->a_prefix; + } else { + a_prefix = o->a_prefix; + b_prefix = o->b_prefix; + } + + if (o->submodule_format == DIFF_SUBMODULE_LOG && + (!one->mode || S_ISGITLINK(one->mode)) && + (!two->mode || S_ISGITLINK(two->mode))) { const char *del = diff_get_color_opt(o, DIFF_FILE_OLD); const char *add = diff_get_color_opt(o, DIFF_FILE_NEW); show_submodule_summary(o->file, one->path ? one->path : two->path, line_prefix, - one->sha1, two->sha1, two->dirty_submodule, + &one->oid, &two->oid, + two->dirty_submodule, meta, del, add, reset); return; + } else if (o->submodule_format == DIFF_SUBMODULE_INLINE_DIFF && + (!one->mode || S_ISGITLINK(one->mode)) && + (!two->mode || S_ISGITLINK(two->mode))) { + const char *del = diff_get_color_opt(o, DIFF_FILE_OLD); + const char *add = diff_get_color_opt(o, DIFF_FILE_NEW); + show_submodule_inline_diff(o->file, one->path ? one->path : two->path, + line_prefix, + &one->oid, &two->oid, + two->dirty_submodule, + meta, del, add, reset, o); + return; } if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) { @@@ -2397,6 -2306,15 +2397,6 @@@ textconv_two = get_textconv(two); } - diff_set_mnemonic_prefix(o, "a/", "b/"); - if (DIFF_OPT_TST(o, REVERSE_DIFF)) { - a_prefix = o->b_prefix; - b_prefix = o->a_prefix; - } else { - a_prefix = o->a_prefix; - b_prefix = o->b_prefix; - } - /* Never use a non-valid filename anywhere if at all possible */ name_a = DIFF_FILE_VALID(one) ? name_a : name_b; name_b = DIFF_FILE_VALID(two) ? name_b : name_a; @@@ -2456,7 -2374,7 +2456,7 @@@ if (!one->data && !two->data && S_ISREG(one->mode) && S_ISREG(two->mode) && !DIFF_OPT_TST(o, BINARY)) { - if (!hashcmp(one->sha1, two->sha1)) { + if (!oidcmp(&one->oid, &two->oid)) { if (must_show_header) fprintf(o->file, "%s", header.buf); goto free_ab_and_return; @@@ -2509,6 -2427,7 +2509,6 @@@ memset(&ecbdata, 0, sizeof(ecbdata)); ecbdata.label_path = lbl; ecbdata.color_diff = want_color(o->use_color); - ecbdata.found_changesp = &o->found_changes; ecbdata.ws_rule = whitespace_rule(name_b); if (ecbdata.ws_rule & WS_BLANK_AT_EOF) check_blank_at_eof(&mf1, &mf2, &ecbdata); @@@ -2576,7 -2495,7 +2576,7 @@@ static void builtin_diffstat(const cha return; } - same_contents = !hashcmp(one->sha1, two->sha1); + same_contents = !oidcmp(&one->oid, &two->oid); if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) { data->is_binary = 1; @@@ -2709,8 -2628,8 +2709,8 @@@ void fill_filespec(struct diff_filespe { if (mode) { spec->mode = canon_mode(mode); - hashcpy(spec->sha1, sha1); - spec->sha1_valid = sha1_valid; + hashcpy(spec->oid.hash, sha1); + spec->oid_valid = sha1_valid; } } @@@ -2753,13 -2672,6 +2753,13 @@@ static int reuse_worktree_file(const ch if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1)) return 0; + /* + * Similarly, if we'd have to convert the file contents anyway, that + * makes the optimization not worthwhile. + */ + if (!want_file && would_convert_to_git(name)) + return 0; + len = strlen(name); pos = cache_name_pos(name, len); if (pos < 0) @@@ -2770,7 -2682,7 +2770,7 @@@ * This is not the sha1 we are looking for, or * unreusable because it is not a regular file. */ - if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode)) + if (hashcmp(sha1, ce->oid.hash) || !S_ISREG(ce->ce_mode)) return 0; /* @@@ -2799,8 -2711,7 +2799,8 @@@ static int diff_populate_gitlink(struc if (s->dirty_submodule) dirty = "-dirty"; - strbuf_addf(&buf, "Subproject commit %s%s\n", sha1_to_hex(s->sha1), dirty); + strbuf_addf(&buf, "Subproject commit %s%s\n", + oid_to_hex(&s->oid), dirty); s->size = buf.len; if (size_only) { s->data = NULL; @@@ -2843,8 -2754,8 +2843,8 @@@ int diff_populate_filespec(struct diff_ if (S_ISGITLINK(s->mode)) return diff_populate_gitlink(s, size_only); - if (!s->sha1_valid || - reuse_worktree_file(s->path, s->sha1, 0)) { + if (!s->oid_valid || + reuse_worktree_file(s->path, s->oid.hash, 0)) { struct strbuf buf = STRBUF_INIT; struct stat st; int fd; @@@ -2901,10 -2812,9 +2901,10 @@@ else { enum object_type type; if (size_only || (flags & CHECK_BINARY)) { - type = sha1_object_info(s->sha1, &s->size); + type = sha1_object_info(s->oid.hash, &s->size); if (type < 0) - die("unable to read %s", sha1_to_hex(s->sha1)); + die("unable to read %s", + oid_to_hex(&s->oid)); if (size_only) return 0; if (s->size > big_file_threshold && s->is_binary == -1) { @@@ -2912,9 -2822,9 +2912,9 @@@ return 0; } } - s->data = read_sha1_file(s->sha1, &type, &s->size); + s->data = read_sha1_file(s->oid.hash, &type, &s->size); if (!s->data) - die("unable to read %s", sha1_to_hex(s->sha1)); + die("unable to read %s", oid_to_hex(&s->oid)); s->should_free = 1; } return 0; @@@ -2943,7 -2853,7 +2943,7 @@@ void diff_free_filespec_data(struct dif static void prep_temp_blob(const char *path, struct diff_tempfile *temp, void *blob, unsigned long size, - const unsigned char *sha1, + const struct object_id *oid, int mode) { int fd; @@@ -2968,7 -2878,7 +2968,7 @@@ die_errno("unable to write temp-file"); close_tempfile(&temp->tempfile); temp->name = get_tempfile_path(&temp->tempfile); - sha1_to_hex_r(temp->hex, sha1); + oid_to_hex_r(temp->hex, oid); xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode); strbuf_release(&buf); strbuf_release(&template); @@@ -2992,8 -2902,8 +2992,8 @@@ static struct diff_tempfile *prepare_te } if (!S_ISGITLINK(one->mode) && - (!one->sha1_valid || - reuse_worktree_file(name, one->sha1, 1))) { + (!one->oid_valid || + reuse_worktree_file(name, one->oid.hash, 1))) { struct stat st; if (lstat(name, &st) < 0) { if (errno == ENOENT) @@@ -3005,19 -2915,19 +3005,19 @@@ if (strbuf_readlink(&sb, name, st.st_size) < 0) die_errno("readlink(%s)", name); prep_temp_blob(name, temp, sb.buf, sb.len, - (one->sha1_valid ? - one->sha1 : null_sha1), - (one->sha1_valid ? + (one->oid_valid ? + &one->oid : &null_oid), + (one->oid_valid ? one->mode : S_IFLNK)); strbuf_release(&sb); } else { /* we can borrow from the file in the work tree */ temp->name = name; - if (!one->sha1_valid) + if (!one->oid_valid) sha1_to_hex_r(temp->hex, null_sha1); else - sha1_to_hex_r(temp->hex, one->sha1); + sha1_to_hex_r(temp->hex, one->oid.hash); /* Even though we may sometimes borrow the * contents from the work tree, we always want * one->mode. mode is trustworthy even when @@@ -3032,7 -2942,7 +3032,7 @@@ if (diff_populate_filespec(one, 0)) die("cannot read data blob for %s", one->path); prep_temp_blob(name, temp, one->data, one->size, - one->sha1, one->mode); + &one->oid, one->mode); } return temp; } @@@ -3096,21 -3006,6 +3096,21 @@@ static int similarity_index(struct diff return p->score * 100 / MAX_SCORE; } +static const char *diff_abbrev_oid(const struct object_id *oid, int abbrev) +{ + if (startup_info->have_repository) + return find_unique_abbrev(oid->hash, abbrev); + else { + char *hex = oid_to_hex(oid); + if (abbrev < 0) + abbrev = FALLBACK_DEFAULT_ABBREV; + if (abbrev > GIT_SHA1_HEXSZ) + die("BUG: oid abbreviation out of range: %d", abbrev); + hex[abbrev] = '\0'; + return hex; + } +} + static void fill_metainfo(struct strbuf *msg, const char *name, const char *other, @@@ -3160,7 -3055,7 +3160,7 @@@ default: *must_show_header = 0; } - if (one && two && hashcmp(one->sha1, two->sha1)) { + if (one && two && oidcmp(&one->oid, &two->oid)) { int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV; if (DIFF_OPT_TST(o, BINARY)) { @@@ -3169,9 -3064,9 +3169,9 @@@ (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two))) abbrev = 40; } - strbuf_addf(msg, "%s%sindex %s..", line_prefix, set, - find_unique_abbrev(one->sha1, abbrev)); - strbuf_addstr(msg, find_unique_abbrev(two->sha1, abbrev)); + strbuf_addf(msg, "%s%sindex %s..%s", line_prefix, set, + diff_abbrev_oid(&one->oid, abbrev), + diff_abbrev_oid(&two->oid, abbrev)); if (one->mode == two->mode) strbuf_addf(msg, " %06o", one->mode); strbuf_addf(msg, "%s\n", reset); @@@ -3226,20 -3121,20 +3226,20 @@@ static void run_diff_cmd(const char *pg static void diff_fill_sha1_info(struct diff_filespec *one) { if (DIFF_FILE_VALID(one)) { - if (!one->sha1_valid) { + if (!one->oid_valid) { struct stat st; if (one->is_stdin) { - hashcpy(one->sha1, null_sha1); + oidclr(&one->oid); return; } if (lstat(one->path, &st) < 0) die_errno("stat '%s'", one->path); - if (index_path(one->sha1, one->path, &st, 0)) + if (index_path(one->oid.hash, one->path, &st, 0)) die("cannot hash %s", one->path); } } else - hashclr(one->sha1); + oidclr(&one->oid); } static void strip_prefix(int prefix_length, const char **namep, const char **otherp) @@@ -3369,7 -3264,7 +3369,7 @@@ void diff_setup(struct diff_options *op options->rename_limit = -1; options->dirstat_permille = diff_dirstat_permille_default; options->context = diff_context_default; - options->ws_error_highlight = WSEH_NEW; + options->ws_error_highlight = ws_error_highlight_default; DIFF_OPT_SET(options, RENAME_EMPTY); /* pathchange left =NULL by default */ @@@ -3378,10 -3273,6 +3378,10 @@@ options->use_color = diff_use_color_default; options->detect_rename = diff_detect_rename_default; options->xdl_opts |= diff_algorithm; + if (diff_indent_heuristic) + DIFF_XDL_SET(options, INDENT_HEURISTIC); + else if (diff_compaction_heuristic) + DIFF_XDL_SET(options, COMPACTION_HEURISTIC); options->orderfile = diff_order_file_cfg; @@@ -3409,7 -3300,7 +3409,7 @@@ void diff_setup_done(struct diff_option if (options->output_format & DIFF_FORMAT_NO_OUTPUT) count++; if (count > 1) - die("--name-only, --name-status, --check and -s are mutually exclusive"); + die(_("--name-only, --name-status, --check and -s are mutually exclusive")); /* * Most of the time we can say "there are changes" @@@ -3483,7 -3374,7 +3483,7 @@@ */ read_cache(); } - if (options->abbrev <= 0 || 40 < options->abbrev) + if (40 < options->abbrev) options->abbrev = 40; /* full */ /* @@@ -3605,7 -3496,7 +3605,7 @@@ static int stat_opt(struct diff_option if (*arg == '=') width = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) - die("Option '--stat-width' requires a value"); + die_want_option("--stat-width"); else if (!*arg) { width = strtoul(av[1], &end, 10); argcount = 2; @@@ -3614,7 -3505,7 +3614,7 @@@ if (*arg == '=') name_width = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) - die("Option '--stat-name-width' requires a value"); + die_want_option("--stat-name-width"); else if (!*arg) { name_width = strtoul(av[1], &end, 10); argcount = 2; @@@ -3623,7 -3514,7 +3623,7 @@@ if (*arg == '=') graph_width = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) - die("Option '--stat-graph-width' requires a value"); + die_want_option("--stat-graph-width"); else if (!*arg) { graph_width = strtoul(av[1], &end, 10); argcount = 2; @@@ -3632,7 -3523,7 +3632,7 @@@ if (*arg == '=') count = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) - die("Option '--stat-count' requires a value"); + die_want_option("--stat-count"); else if (!*arg) { count = strtoul(av[1], &end, 10); argcount = 2; @@@ -3760,14 -3651,40 +3760,14 @@@ static void enable_patch_output(int *fm *fmt |= DIFF_FORMAT_PATCH; } -static int parse_one_token(const char **arg, const char *token) +static int parse_ws_error_highlight_opt(struct diff_options *opt, const char *arg) { - const char *rest; - if (skip_prefix(*arg, token, &rest) && (!*rest || *rest == ',')) { - *arg = rest; - return 1; - } - return 0; -} + int val = parse_ws_error_highlight(arg); -static int parse_ws_error_highlight(struct diff_options *opt, const char *arg) -{ - const char *orig_arg = arg; - unsigned val = 0; - while (*arg) { - if (parse_one_token(&arg, "none")) - val = 0; - else if (parse_one_token(&arg, "default")) - val = WSEH_NEW; - else if (parse_one_token(&arg, "all")) - val = WSEH_NEW | WSEH_OLD | WSEH_CONTEXT; - else if (parse_one_token(&arg, "new")) - val |= WSEH_NEW; - else if (parse_one_token(&arg, "old")) - val |= WSEH_OLD; - else if (parse_one_token(&arg, "context")) - val |= WSEH_CONTEXT; - else { - error("unknown value after ws-error-highlight=%.*s", - (int)(arg - orig_arg), orig_arg); - return 0; - } - if (*arg) - arg++; + if (val < 0) { + error("unknown value after ws-error-highlight=%.*s", + -1 - val, arg); + return 0; } opt->ws_error_highlight = val; return 1; @@@ -3876,16 -3793,6 +3876,16 @@@ int diff_opt_parse(struct diff_options DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL); else if (!strcmp(arg, "--ignore-blank-lines")) DIFF_XDL_SET(options, IGNORE_BLANK_LINES); + else if (!strcmp(arg, "--indent-heuristic")) { + DIFF_XDL_SET(options, INDENT_HEURISTIC); + DIFF_XDL_CLR(options, COMPACTION_HEURISTIC); + } else if (!strcmp(arg, "--no-indent-heuristic")) + DIFF_XDL_CLR(options, INDENT_HEURISTIC); + else if (!strcmp(arg, "--compaction-heuristic")) { + DIFF_XDL_SET(options, COMPACTION_HEURISTIC); + DIFF_XDL_CLR(options, INDENT_HEURISTIC); + } else if (!strcmp(arg, "--no-compaction-heuristic")) + DIFF_XDL_CLR(options, COMPACTION_HEURISTIC); else if (!strcmp(arg, "--patience")) options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF); else if (!strcmp(arg, "--histogram")) @@@ -3982,15 -3889,11 +3982,15 @@@ DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG); handle_ignore_submodules_arg(options, arg); } else if (!strcmp(arg, "--submodule")) - DIFF_OPT_SET(options, SUBMODULE_LOG); + options->submodule_format = DIFF_SUBMODULE_LOG; else if (skip_prefix(arg, "--submodule=", &arg)) return parse_submodule_opt(options, arg); else if (skip_prefix(arg, "--ws-error-highlight=", &arg)) - return parse_ws_error_highlight(options, arg); + return parse_ws_error_highlight_opt(options, arg); + else if (!strcmp(arg, "--ita-invisible-in-index")) + options->ita_invisible_in_index = 1; + else if (!strcmp(arg, "--ita-visible-in-index")) + options->ita_invisible_in_index = 0; /* misc options */ else if (!strcmp(arg, "-z")) @@@ -4037,12 -3940,6 +4037,12 @@@ options->a_prefix = optarg; return argcount; } + else if ((argcount = parse_long_opt("line-prefix", av, &optarg))) { + options->line_prefix = optarg; + options->line_prefix_length = strlen(options->line_prefix); + graph_setup_line_prefix(options); + return argcount; + } else if ((argcount = parse_long_opt("dst-prefix", av, &optarg))) { options->b_prefix = optarg; return argcount; @@@ -4064,8 -3961,6 +4064,8 @@@ if (!options->file) die_errno("Could not open '%s'", path); options->close_file = 1; + if (options->use_color != GIT_COLOR_ALWAYS) + options->use_color = GIT_COLOR_NEVER; return argcount; } else return 0; @@@ -4176,46 -4071,27 +4176,46 @@@ void diff_free_filepair(struct diff_fil free(p); } -/* This is different from find_unique_abbrev() in that - * it stuffs the result with dots for alignment. - */ -const char *diff_unique_abbrev(const unsigned char *sha1, int len) +const char *diff_aligned_abbrev(const struct object_id *oid, int len) { int abblen; const char *abbrev; - if (len == 40) - return sha1_to_hex(sha1); - abbrev = find_unique_abbrev(sha1, len); + if (len == GIT_SHA1_HEXSZ) + return oid_to_hex(oid); + + abbrev = diff_abbrev_oid(oid, len); abblen = strlen(abbrev); - if (abblen < 37) { - static char hex[41]; + + /* + * In well-behaved cases, where the abbbreviated result is the + * same as the requested length, append three dots after the + * abbreviation (hence the whole logic is limited to the case + * where abblen < 37); when the actual abbreviated result is a + * bit longer than the requested length, we reduce the number + * of dots so that they match the well-behaved ones. However, + * if the actual abbreviation is longer than the requested + * length by more than three, we give up on aligning, and add + * three dots anyway, to indicate that the output is not the + * full object name. Yes, this may be suboptimal, but this + * appears only in "diff --raw --abbrev" output and it is not + * worth the effort to change it now. Note that this would + * likely to work fine when the automatic sizing of default + * abbreviation length is used--we would be fed -1 in "len" in + * that case, and will end up always appending three-dots, but + * the automatic sizing is supposed to give abblen that ensures + * uniqueness across all objects (statistically speaking). + */ + if (abblen < GIT_SHA1_HEXSZ - 3) { + static char hex[GIT_SHA1_HEXSZ + 1]; if (len < abblen && abblen <= len + 2) xsnprintf(hex, sizeof(hex), "%s%.*s", abbrev, len+3-abblen, ".."); else xsnprintf(hex, sizeof(hex), "%s...", abbrev); return hex; } - return sha1_to_hex(sha1); + + return oid_to_hex(oid); } static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt) @@@ -4226,9 -4102,8 +4226,9 @@@ fprintf(opt->file, "%s", diff_line_prefix(opt)); if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) { fprintf(opt->file, ":%06o %06o %s ", p->one->mode, p->two->mode, - diff_unique_abbrev(p->one->sha1, opt->abbrev)); - fprintf(opt->file, "%s ", diff_unique_abbrev(p->two->sha1, opt->abbrev)); + diff_aligned_abbrev(&p->one->oid, opt->abbrev)); + fprintf(opt->file, "%s ", + diff_aligned_abbrev(&p->two->oid, opt->abbrev)); } if (p->score) { fprintf(opt->file, "%c%03d%c", p->status, similarity_index(p), @@@ -4277,11 -4152,11 +4277,11 @@@ int diff_unmodified_pair(struct diff_fi /* both are valid and point at the same path. that is, we are * dealing with a change. */ - if (one->sha1_valid && two->sha1_valid && - !hashcmp(one->sha1, two->sha1) && + if (one->oid_valid && two->oid_valid && + !oidcmp(&one->oid, &two->oid) && !one->dirty_submodule && !two->dirty_submodule) return 1; /* no change */ - if (!one->sha1_valid && !two->sha1_valid) + if (!one->oid_valid && !two->oid_valid) return 1; /* both look at the same file on the filesystem. */ return 0; } @@@ -4342,7 -4217,7 +4342,7 @@@ void diff_debug_filespec(struct diff_fi s->path, DIFF_FILE_VALID(s) ? "valid" : "invalid", s->mode, - s->sha1_valid ? sha1_to_hex(s->sha1) : ""); + s->oid_valid ? oid_to_hex(&s->oid) : ""); fprintf(stderr, "queue[%d] %s size %lu\n", x, one ? one : "", s->size); @@@ -4412,11 -4287,11 +4412,11 @@@ static void diff_resolve_rename_copy(vo else p->status = DIFF_STATUS_RENAMED; } - else if (hashcmp(p->one->sha1, p->two->sha1) || + else if (oidcmp(&p->one->oid, &p->two->oid) || p->one->mode != p->two->mode || p->one->dirty_submodule || p->two->dirty_submodule || - is_null_sha1(p->one->sha1)) + is_null_oid(&p->one->oid)) p->status = DIFF_STATUS_MODIFIED; else { /* This is a "no-change" entry and should not @@@ -4558,7 -4433,7 +4558,7 @@@ static void patch_id_consume(void *priv } /* returns 0 upon success, and writes result into sha1 */ -static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) +static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only) { struct diff_queue_struct *q = &diff_queued_diff; int i; @@@ -4593,6 -4468,9 +4593,6 @@@ diff_fill_sha1_info(p->one); diff_fill_sha1_info(p->two); - if (fill_mmfile(&mf1, p->one) < 0 || - fill_mmfile(&mf2, p->two) < 0) - return error("unable to read files to diff"); len1 = remove_space(p->one->path, strlen(p->one->path)); len2 = remove_space(p->two->path, strlen(p->two->path)); @@@ -4627,19 -4505,10 +4627,19 @@@ len2, p->two->path); git_SHA1_Update(&ctx, buffer, len1); + if (diff_header_only) + continue; + + if (fill_mmfile(&mf1, p->one) < 0 || + fill_mmfile(&mf2, p->two) < 0) + return error("unable to read files to diff"); + if (diff_filespec_is_binary(p->one) || diff_filespec_is_binary(p->two)) { - git_SHA1_Update(&ctx, sha1_to_hex(p->one->sha1), 40); - git_SHA1_Update(&ctx, sha1_to_hex(p->two->sha1), 40); + git_SHA1_Update(&ctx, oid_to_hex(&p->one->oid), + 40); + git_SHA1_Update(&ctx, oid_to_hex(&p->two->oid), + 40); continue; } @@@ -4656,11 -4525,11 +4656,11 @@@ return 0; } -int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1) +int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only) { struct diff_queue_struct *q = &diff_queued_diff; int i; - int result = diff_get_patch_id(options, sha1); + int result = diff_get_patch_id(options, sha1, diff_header_only); for (i = 0; i < q->nr; i++) diff_free_filepair(q->queue[i]); @@@ -4697,25 -4566,25 +4697,25 @@@ static int is_summary_empty(const struc } static const char rename_limit_warning[] = -"inexact rename detection was skipped due to too many files."; +N_("inexact rename detection was skipped due to too many files."); static const char degrade_cc_to_c_warning[] = -"only found copies from modified paths due to too many files."; +N_("only found copies from modified paths due to too many files."); static const char rename_limit_advice[] = -"you may want to set your %s variable to at least " -"%d and retry the command."; +N_("you may want to set your %s variable to at least " + "%d and retry the command."); void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc) { if (degraded_cc) - warning(degrade_cc_to_c_warning); + warning(_(degrade_cc_to_c_warning)); else if (needed) - warning(rename_limit_warning); + warning(_(rename_limit_warning)); else return; if (0 < needed && needed < 32767) - warning(rename_limit_advice, varname, needed); + warning(_(rename_limit_advice), varname, needed); } void diff_flush(struct diff_options *options) @@@ -4931,7 -4800,7 +4931,7 @@@ static int diff_filespec_check_stat_unm */ if (!DIFF_FILE_VALID(p->one) || /* (1) */ !DIFF_FILE_VALID(p->two) || - (p->one->sha1_valid && p->two->sha1_valid) || + (p->one->oid_valid && p->two->oid_valid) || (p->one->mode != p->two->mode) || diff_populate_filespec(p->one, CHECK_SIZE_ONLY) || diff_populate_filespec(p->two, CHECK_SIZE_ONLY) || @@@ -4982,7 -4851,7 +4982,7 @@@ static int diffnamecmp(const void *a_, void diffcore_fix_diff_index(struct diff_options *options) { struct diff_queue_struct *q = &diff_queued_diff; - qsort(q->queue, q->nr, sizeof(q->queue[0]), diffnamecmp); + QSORT(q->queue, q->nr, diffnamecmp); } void diffcore_std(struct diff_options *options) @@@ -5227,9 -5096,8 +5227,9 @@@ size_t fill_textconv(struct userdiff_dr if (!driver->textconv) die("BUG: fill_textconv called with non-textconv driver"); - if (driver->textconv_cache && df->sha1_valid) { - *outbuf = notes_cache_get(driver->textconv_cache, df->sha1, + if (driver->textconv_cache && df->oid_valid) { + *outbuf = notes_cache_get(driver->textconv_cache, + df->oid.hash, &size); if (*outbuf) return size; @@@ -5239,9 -5107,9 +5239,9 @@@ if (!*outbuf) die("unable to read files to diff"); - if (driver->textconv_cache && df->sha1_valid) { + if (driver->textconv_cache && df->oid_valid) { /* ignore errors, as we might be in a readonly repository */ - notes_cache_put(driver->textconv_cache, df->sha1, *outbuf, + notes_cache_put(driver->textconv_cache, df->oid.hash, *outbuf, size); /* * we could save up changes and flush them all at the end, diff --combined diffcore-break.c index 881a74f29e,904156d92e..c64359f489 --- a/diffcore-break.c +++ b/diffcore-break.c @@@ -57,8 -57,8 +57,8 @@@ static int should_break(struct diff_fil return 1; /* even their types are different */ } - if (src->sha1_valid && dst->sha1_valid && - !hashcmp(src->sha1, dst->sha1)) + if (src->oid_valid && dst->oid_valid && + !oidcmp(&src->oid, &dst->oid)) return 0; /* they are the same */ if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0)) @@@ -73,7 -73,6 +73,6 @@@ if (diffcore_count_changes(src, dst, &src->cnt_data, &dst->cnt_data, - 0, &src_copied, &literal_added)) return 0; diff --combined diffcore-delta.c index 2ebedb32d1,e2db85abd9..ebe70fb068 --- a/diffcore-delta.c +++ b/diffcore-delta.c @@@ -158,7 -158,10 +158,7 @@@ static struct spanhash_top *hash_chars( n = 0; accum1 = accum2 = 0; } - qsort(hash->data, - 1ul << hash->alloc_log2, - sizeof(hash->data[0]), - spanhash_cmp); + QSORT(hash->data, 1ul << hash->alloc_log2, spanhash_cmp); return hash; } @@@ -166,7 -169,6 +166,6 @@@ int diffcore_count_changes(struct diff_ struct diff_filespec *dst, void **src_count_p, void **dst_count_p, - unsigned long delta_limit, unsigned long *src_copied, unsigned long *literal_added) { diff --combined diffcore-rename.c index 54a2396653,8ce3b7d661..f7444c86bd --- a/diffcore-rename.c +++ b/diffcore-rename.c @@@ -60,8 -60,7 +60,8 @@@ static int add_rename_dst(struct diff_f memmove(rename_dst + first + 1, rename_dst + first, (rename_dst_nr - first - 1) * sizeof(*rename_dst)); rename_dst[first].two = alloc_filespec(two->path); - fill_filespec(rename_dst[first].two, two->sha1, two->sha1_valid, two->mode); + fill_filespec(rename_dst[first].two, two->oid.hash, two->oid_valid, + two->mode); rename_dst[first].pair = NULL; return 0; } @@@ -145,7 -144,6 +145,6 @@@ static int estimate_similarity(struct d * call into this function in that case. */ unsigned long max_size, delta_size, base_size, src_copied, literal_added; - unsigned long delta_limit; int score; /* We deal only with regular files. Symlink renames are handled @@@ -191,11 -189,8 +190,8 @@@ if (!dst->cnt_data && diff_populate_filespec(dst, 0)) return 0; - delta_limit = (unsigned long) - (base_size * (MAX_SCORE-minimum_score) / MAX_SCORE); if (diffcore_count_changes(src, dst, &src->cnt_data, &dst->cnt_data, - delta_limit, &src_copied, &literal_added)) return 0; @@@ -261,13 -256,12 +257,13 @@@ struct file_similarity static unsigned int hash_filespec(struct diff_filespec *filespec) { - if (!filespec->sha1_valid) { + if (!filespec->oid_valid) { if (diff_populate_filespec(filespec, 0)) return 0; - hash_sha1_file(filespec->data, filespec->size, "blob", filespec->sha1); + hash_sha1_file(filespec->data, filespec->size, "blob", + filespec->oid.hash); } - return sha1hash(filespec->sha1); + return sha1hash(filespec->oid.hash); } static int find_identical_files(struct hashmap *srcs, @@@ -289,7 -283,7 +285,7 @@@ struct diff_filespec *source = p->filespec; /* False hash collision? */ - if (hashcmp(source->sha1, target->sha1)) + if (oidcmp(&source->oid, &target->oid)) continue; /* Non-regular files? If so, the modes must match! */ if (!S_ISREG(source->mode) || !S_ISREG(target->mode)) { @@@ -468,7 -462,7 +464,7 @@@ void diffcore_rename(struct diff_option strcmp(options->single_follow, p->two->path)) continue; /* not interested */ else if (!DIFF_OPT_TST(options, RENAME_EMPTY) && - is_empty_blob_sha1(p->two->sha1)) + is_empty_blob_sha1(p->two->oid.hash)) continue; else if (add_rename_dst(p->two) < 0) { warning("skipping rename detection, detected" @@@ -478,7 -472,7 +474,7 @@@ } } else if (!DIFF_OPT_TST(options, RENAME_EMPTY) && - is_empty_blob_sha1(p->one->sha1)) + is_empty_blob_sha1(p->one->oid.hash)) continue; else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) { /* @@@ -541,7 -535,7 +537,7 @@@ rename_dst_nr * rename_src_nr, 50, 1); } - mx = xcalloc(st_mult(num_create, NUM_CANDIDATE_PER_DST), sizeof(*mx)); + mx = xcalloc(st_mult(NUM_CANDIDATE_PER_DST, num_create), sizeof(*mx)); for (dst_cnt = i = 0; i < rename_dst_nr; i++) { struct diff_filespec *two = rename_dst[i].two; struct diff_score *m; @@@ -580,7 -574,7 +576,7 @@@ stop_progress(&progress); /* cost matrix sorted by most to least similar pair */ - qsort(mx, dst_cnt * NUM_CANDIDATE_PER_DST, sizeof(*mx), score_compare); + QSORT(mx, dst_cnt * NUM_CANDIDATE_PER_DST, score_compare); rename_count += find_renames(mx, dst_cnt, minimum_score, 0); if (detect_rename == DIFF_DETECT_COPY) diff --combined diffcore.h index c11b8465fc,8a9c9d781a..6230241354 --- a/diffcore.h +++ b/diffcore.h @@@ -25,7 -25,7 +25,7 @@@ struct userdiff_driver; struct diff_filespec { - unsigned char sha1[20]; + struct object_id oid; char *path; void *data; void *cnt_data; @@@ -33,7 -33,7 +33,7 @@@ int count; /* Reference count */ int rename_used; /* Count of rename users */ unsigned short mode; /* file mode */ - unsigned sha1_valid : 1; /* if true, use sha1 and trust mode; + unsigned oid_valid : 1; /* if true, use oid and trust mode; * if false, use the name and read from * the filesystem. */ @@@ -142,7 -142,6 +142,6 @@@ extern int diffcore_count_changes(struc struct diff_filespec *dst, void **src_count_p, void **dst_count_p, - unsigned long delta_limit, unsigned long *src_copied, unsigned long *literal_added);