diff options
Diffstat (limited to 'diff.c')
-rw-r--r-- | diff.c | 235 |
1 files changed, 101 insertions, 134 deletions
@@ -16,6 +16,7 @@ #include "submodule.h" #include "ll-merge.h" #include "string-list.h" +#include "argv-array.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -51,23 +52,23 @@ static char diff_colors[][COLOR_MAXLEN] = { GIT_COLOR_NORMAL, /* FUNCINFO */ }; -static int parse_diff_color_slot(const char *var, int ofs) +static int parse_diff_color_slot(const char *var) { - if (!strcasecmp(var+ofs, "plain")) + if (!strcasecmp(var, "plain")) return DIFF_PLAIN; - if (!strcasecmp(var+ofs, "meta")) + if (!strcasecmp(var, "meta")) return DIFF_METAINFO; - if (!strcasecmp(var+ofs, "frag")) + if (!strcasecmp(var, "frag")) return DIFF_FRAGINFO; - if (!strcasecmp(var+ofs, "old")) + if (!strcasecmp(var, "old")) return DIFF_FILE_OLD; - if (!strcasecmp(var+ofs, "new")) + if (!strcasecmp(var, "new")) return DIFF_FILE_NEW; - if (!strcasecmp(var+ofs, "commit")) + if (!strcasecmp(var, "commit")) return DIFF_COMMIT; - if (!strcasecmp(var+ofs, "whitespace")) + if (!strcasecmp(var, "whitespace")) return DIFF_WHITESPACE; - if (!strcasecmp(var+ofs, "func")) + if (!strcasecmp(var, "func")) return DIFF_FUNCINFO; return -1; } @@ -230,6 +231,8 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) int git_diff_basic_config(const char *var, const char *value, void *cb) { + const char *name; + if (!strcmp(var, "diff.renamelimit")) { diff_rename_limit_default = git_config_int(var, value); return 0; @@ -238,8 +241,9 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) if (userdiff_config(var, value) < 0) return -1; - if (starts_with(var, "diff.color.") || starts_with(var, "color.diff.")) { - int slot = parse_diff_color_slot(var, 11); + if (skip_prefix(var, "diff.color.", &name) || + skip_prefix(var, "color.diff.", &name)) { + int slot = parse_diff_color_slot(name); if (slot < 0) return 0; if (!value) @@ -521,9 +525,9 @@ static void emit_hunk_header(struct emit_callback *ecbdata, ep += 2; /* skip over @@ */ /* The hunk header in fraginfo color */ - strbuf_add(&msgbuf, frag, strlen(frag)); + strbuf_addstr(&msgbuf, frag); strbuf_add(&msgbuf, line, ep - line); - strbuf_add(&msgbuf, reset, strlen(reset)); + strbuf_addstr(&msgbuf, reset); /* * trailing "\r\n" @@ -537,15 +541,15 @@ static void emit_hunk_header(struct emit_callback *ecbdata, if (*ep != ' ' && *ep != '\t') break; if (ep != cp) { - strbuf_add(&msgbuf, plain, strlen(plain)); + strbuf_addstr(&msgbuf, plain); strbuf_add(&msgbuf, cp, ep - cp); - strbuf_add(&msgbuf, reset, strlen(reset)); + strbuf_addstr(&msgbuf, reset); } if (ep < line + len) { - strbuf_add(&msgbuf, func, strlen(func)); + strbuf_addstr(&msgbuf, func); strbuf_add(&msgbuf, ep, line + len - ep); - strbuf_add(&msgbuf, reset, strlen(reset)); + strbuf_addstr(&msgbuf, reset); } strbuf_add(&msgbuf, line + len, org_len - len); @@ -1360,12 +1364,8 @@ static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat, const char *name_b) { struct diffstat_file *x; - x = xcalloc(sizeof (*x), 1); - if (diffstat->nr == diffstat->alloc) { - diffstat->alloc = alloc_nr(diffstat->alloc); - diffstat->files = xrealloc(diffstat->files, - diffstat->alloc * sizeof(x)); - } + x = xcalloc(1, sizeof(*x)); + ALLOC_GROW(diffstat->files, diffstat->nr + 1, diffstat->alloc); diffstat->files[diffstat->nr++] = x; if (name_b) { x->from_name = xstrdup(name_a); @@ -1465,20 +1465,12 @@ int print_stat_summary(FILE *fp, int files, int insertions, int deletions) * but nothing about added/removed lines? Is this a bug in Git?"). */ if (insertions || deletions == 0) { - /* - * TRANSLATORS: "+" in (+) is a line addition marker; - * do not translate it. - */ strbuf_addf(&sb, (insertions == 1) ? ", %d insertion(+)" : ", %d insertions(+)", insertions); } if (deletions || insertions == 0) { - /* - * TRANSLATORS: "-" in (-) is a line removal marker; - * do not translate it. - */ strbuf_addf(&sb, (deletions == 1) ? ", %d deletion(-)" : ", %d deletions(-)", deletions); @@ -2352,6 +2344,7 @@ static void builtin_diff(const char *name_a, } else { /* Crazy xdl interfaces.. */ const char *diffopts = getenv("GIT_DIFF_OPTS"); + const char *v; xpparam_t xpp; xdemitconf_t xecfg; struct emit_callback ecbdata; @@ -2390,10 +2383,10 @@ static void builtin_diff(const char *name_a, xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags); if (!diffopts) ; - else if (starts_with(diffopts, "--unified=")) - xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10); - else if (starts_with(diffopts, "-u")) - xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10); + else if (skip_prefix(diffopts, "--unified=", &v)) + xecfg.ctxlen = strtoul(v, NULL, 10); + else if (skip_prefix(diffopts, "-u", &v)) + xecfg.ctxlen = strtoul(v, NULL, 10); if (o->word_diff) init_diff_words_data(&ecbdata, o, one, two); xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata, @@ -2891,6 +2884,16 @@ static struct diff_tempfile *prepare_temp_file(const char *name, return temp; } +static void add_external_diff_name(struct argv_array *argv, + const char *name, + struct diff_filespec *df) +{ + struct diff_tempfile *temp = prepare_temp_file(name, df); + argv_array_push(argv, temp->name); + argv_array_push(argv, temp->hex); + argv_array_push(argv, temp->mode); +} + /* An external diff command takes: * * diff-cmd name infile1 infile1-sha1 infile1-mode \ @@ -2906,50 +2909,33 @@ static void run_external_diff(const char *pgm, int complete_rewrite, struct diff_options *o) { - const char *spawn_arg[10]; - int retval; - const char **arg = &spawn_arg[0]; + struct argv_array argv = ARGV_ARRAY_INIT; + struct argv_array env = ARGV_ARRAY_INIT; struct diff_queue_struct *q = &diff_queued_diff; - const char *env[3] = { NULL }; - char env_counter[50]; - char env_total[50]; + + argv_array_push(&argv, pgm); + argv_array_push(&argv, name); if (one && two) { - struct diff_tempfile *temp_one, *temp_two; - const char *othername = (other ? other : name); - temp_one = prepare_temp_file(name, one); - temp_two = prepare_temp_file(othername, two); - *arg++ = pgm; - *arg++ = name; - *arg++ = temp_one->name; - *arg++ = temp_one->hex; - *arg++ = temp_one->mode; - *arg++ = temp_two->name; - *arg++ = temp_two->hex; - *arg++ = temp_two->mode; - if (other) { - *arg++ = other; - *arg++ = xfrm_msg; + add_external_diff_name(&argv, name, one); + if (!other) + add_external_diff_name(&argv, name, two); + else { + add_external_diff_name(&argv, other, two); + argv_array_push(&argv, other); + argv_array_push(&argv, xfrm_msg); } - } else { - *arg++ = pgm; - *arg++ = name; } - *arg = NULL; - fflush(NULL); - env[0] = env_counter; - snprintf(env_counter, sizeof(env_counter), "GIT_DIFF_PATH_COUNTER=%d", - ++o->diff_path_counter); - env[1] = env_total; - snprintf(env_total, sizeof(env_total), "GIT_DIFF_PATH_TOTAL=%d", q->nr); + argv_array_pushf(&env, "GIT_DIFF_PATH_COUNTER=%d", ++o->diff_path_counter); + argv_array_pushf(&env, "GIT_DIFF_PATH_TOTAL=%d", q->nr); + + if (run_command_v_opt_cd_env(argv.argv, RUN_USING_SHELL, NULL, env.argv)) + die(_("external diff died, stopping at %s"), name); - retval = run_command_v_opt_cd_env(spawn_arg, RUN_USING_SHELL, NULL, env); remove_tempfile(); - if (retval) { - fprintf(stderr, "external diff died, stopping at %s.\n", name); - exit(1); - } + argv_array_clear(&argv); + argv_array_clear(&env); } static int similarity_index(struct diff_filepair *p) @@ -3217,6 +3203,7 @@ void diff_setup(struct diff_options *options) options->context = diff_context_default; DIFF_OPT_SET(options, RENAME_EMPTY); + /* pathchange left =NULL by default */ options->change = diff_change; options->add_remove = diff_addremove; options->use_color = diff_use_color_default; @@ -3337,6 +3324,9 @@ void diff_setup_done(struct diff_options *options) } options->diff_path_counter = 0; + + if (DIFF_OPT_TST(options, FOLLOW_RENAMES) && options->pathspec.nr != 1) + die(_("--follow requires exactly one pathspec")); } static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val) @@ -3366,14 +3356,11 @@ static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *va if (c != '-') return 0; arg++; - eq = strchr(arg, '='); - if (eq) - len = eq - arg; - else - len = strlen(arg); + eq = strchrnul(arg, '='); + len = eq - arg; if (!len || strncmp(arg, arg_long, len)) return 0; - if (eq) { + if (*eq) { int n; char *end; if (!isdigit(*++eq)) @@ -3408,12 +3395,10 @@ int parse_long_opt(const char *opt, const char **argv, const char **optarg) { const char *arg = argv[0]; - if (arg[0] != '-' || arg[1] != '-') + if (!skip_prefix(arg, "--", &arg)) return 0; - arg += strlen("--"); - if (!starts_with(arg, opt)) + if (!skip_prefix(arg, opt, &arg)) return 0; - arg += strlen(opt); if (*arg == '=') { /* stuck form: --option=value */ *optarg = arg + 1; return 1; @@ -3437,13 +3422,13 @@ static int stat_opt(struct diff_options *options, const char **av) int count = options->stat_count; int argcount = 1; - arg += strlen("--stat"); + if (!skip_prefix(arg, "--stat", &arg)) + die("BUG: stat option does not begin with --stat: %s", arg); end = (char *)arg; switch (*arg) { case '-': - if (starts_with(arg, "-width")) { - arg += strlen("-width"); + if (skip_prefix(arg, "-width", &arg)) { if (*arg == '=') width = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) @@ -3452,8 +3437,7 @@ static int stat_opt(struct diff_options *options, const char **av) width = strtoul(av[1], &end, 10); argcount = 2; } - } else if (starts_with(arg, "-name-width")) { - arg += strlen("-name-width"); + } else if (skip_prefix(arg, "-name-width", &arg)) { if (*arg == '=') name_width = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) @@ -3462,8 +3446,7 @@ static int stat_opt(struct diff_options *options, const char **av) name_width = strtoul(av[1], &end, 10); argcount = 2; } - } else if (starts_with(arg, "-graph-width")) { - arg += strlen("-graph-width"); + } else if (skip_prefix(arg, "-graph-width", &arg)) { if (*arg == '=') graph_width = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) @@ -3472,8 +3455,7 @@ static int stat_opt(struct diff_options *options, const char **av) graph_width = strtoul(av[1], &end, 10); argcount = 2; } - } else if (starts_with(arg, "-count")) { - arg += strlen("-count"); + } else if (skip_prefix(arg, "-count", &arg)) { if (*arg == '=') count = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) @@ -3600,14 +3582,6 @@ static int parse_diff_filter_opt(const char *optarg, struct diff_options *opt) return 0; } -/* Used only by "diff-files" and "diff --no-index" */ -void handle_deprecated_show_diff_q(struct diff_options *opt) -{ - warning("'diff -q' and 'diff-files -q' are deprecated."); - warning("Use 'diff --diff-filter=d' instead to ignore deleted filepairs."); - parse_diff_filter_opt("d", opt); -} - static void enable_patch_output(int *fmt) { *fmt &= ~DIFF_FORMAT_NO_OUTPUT; *fmt |= DIFF_FORMAT_PATCH; @@ -3634,17 +3608,17 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->output_format |= DIFF_FORMAT_SHORTSTAT; else if (!strcmp(arg, "-X") || !strcmp(arg, "--dirstat")) return parse_dirstat_opt(options, ""); - else if (starts_with(arg, "-X")) - return parse_dirstat_opt(options, arg + 2); - else if (starts_with(arg, "--dirstat=")) - return parse_dirstat_opt(options, arg + 10); + else if (skip_prefix(arg, "-X", &arg)) + return parse_dirstat_opt(options, arg); + else if (skip_prefix(arg, "--dirstat=", &arg)) + return parse_dirstat_opt(options, arg); else if (!strcmp(arg, "--cumulative")) return parse_dirstat_opt(options, "cumulative"); else if (!strcmp(arg, "--dirstat-by-file")) return parse_dirstat_opt(options, "files"); - else if (starts_with(arg, "--dirstat-by-file=")) { + else if (skip_prefix(arg, "--dirstat-by-file=", &arg)) { parse_dirstat_opt(options, "files"); - return parse_dirstat_opt(options, arg + 18); + return parse_dirstat_opt(options, arg); } else if (!strcmp(arg, "--check")) options->output_format |= DIFF_FORMAT_CHECKDIFF; @@ -3694,9 +3668,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_CLR(options, RENAME_EMPTY); else if (!strcmp(arg, "--relative")) DIFF_OPT_SET(options, RELATIVE_NAME); - else if (starts_with(arg, "--relative=")) { + else if (skip_prefix(arg, "--relative=", &arg)) { DIFF_OPT_SET(options, RELATIVE_NAME); - options->prefix = arg + 11; + options->prefix = arg; } /* xdiff options */ @@ -3747,8 +3721,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_CLR(options, FOLLOW_RENAMES); else if (!strcmp(arg, "--color")) options->use_color = 1; - else if (starts_with(arg, "--color=")) { - int value = git_config_colorbool(NULL, arg+8); + else if (skip_prefix(arg, "--color=", &arg)) { + int value = git_config_colorbool(NULL, arg); if (value < 0) return error("option `color' expects \"always\", \"auto\", or \"never\""); options->use_color = value; @@ -3759,29 +3733,28 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->use_color = 1; options->word_diff = DIFF_WORDS_COLOR; } - else if (starts_with(arg, "--color-words=")) { + else if (skip_prefix(arg, "--color-words=", &arg)) { options->use_color = 1; options->word_diff = DIFF_WORDS_COLOR; - options->word_regex = arg + 14; + options->word_regex = arg; } else if (!strcmp(arg, "--word-diff")) { if (options->word_diff == DIFF_WORDS_NONE) options->word_diff = DIFF_WORDS_PLAIN; } - else if (starts_with(arg, "--word-diff=")) { - const char *type = arg + 12; - if (!strcmp(type, "plain")) + else if (skip_prefix(arg, "--word-diff=", &arg)) { + if (!strcmp(arg, "plain")) options->word_diff = DIFF_WORDS_PLAIN; - else if (!strcmp(type, "color")) { + else if (!strcmp(arg, "color")) { options->use_color = 1; options->word_diff = DIFF_WORDS_COLOR; } - else if (!strcmp(type, "porcelain")) + else if (!strcmp(arg, "porcelain")) options->word_diff = DIFF_WORDS_PORCELAIN; - else if (!strcmp(type, "none")) + else if (!strcmp(arg, "none")) options->word_diff = DIFF_WORDS_NONE; else - die("bad --word-diff argument: %s", type); + die("bad --word-diff argument: %s", arg); } else if ((argcount = parse_long_opt("word-diff-regex", av, &optarg))) { if (options->word_diff == DIFF_WORDS_NONE) @@ -3804,13 +3777,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) else if (!strcmp(arg, "--ignore-submodules")) { DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG); handle_ignore_submodules_arg(options, "all"); - } else if (starts_with(arg, "--ignore-submodules=")) { + } else if (skip_prefix(arg, "--ignore-submodules=", &arg)) { DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG); - handle_ignore_submodules_arg(options, arg + 20); + handle_ignore_submodules_arg(options, arg); } else if (!strcmp(arg, "--submodule")) DIFF_OPT_SET(options, SUBMODULE_LOG); - else if (starts_with(arg, "--submodule=")) - return parse_submodule_opt(options, arg + 12); + else if (skip_prefix(arg, "--submodule=", &arg)) + return parse_submodule_opt(options, arg); /* misc options */ else if (!strcmp(arg, "-z")) @@ -3845,8 +3818,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) } else if (!strcmp(arg, "--abbrev")) options->abbrev = DEFAULT_ABBREV; - else if (starts_with(arg, "--abbrev=")) { - options->abbrev = strtoul(arg + 9, NULL, 10); + else if (skip_prefix(arg, "--abbrev=", &arg)) { + options->abbrev = strtoul(arg, NULL, 10); if (options->abbrev < MINIMUM_ABBREV) options->abbrev = MINIMUM_ABBREV; else if (40 < options->abbrev) @@ -3927,16 +3900,13 @@ static int diff_scoreopt_parse(const char *opt) cmd = *opt++; if (cmd == '-') { /* convert the long-form arguments into short-form versions */ - if (starts_with(opt, "break-rewrites")) { - opt += strlen("break-rewrites"); + if (skip_prefix(opt, "break-rewrites", &opt)) { if (*opt == 0 || *opt++ == '=') cmd = 'B'; - } else if (starts_with(opt, "find-copies")) { - opt += strlen("find-copies"); + } else if (skip_prefix(opt, "find-copies", &opt)) { if (*opt == 0 || *opt++ == '=') cmd = 'C'; - } else if (starts_with(opt, "find-renames")) { - opt += strlen("find-renames"); + } else if (skip_prefix(opt, "find-renames", &opt)) { if (*opt == 0 || *opt++ == '=') cmd = 'M'; } @@ -3966,11 +3936,7 @@ struct diff_queue_struct diff_queued_diff; void diff_q(struct diff_queue_struct *queue, struct diff_filepair *dp) { - if (queue->alloc <= queue->nr) { - queue->alloc = alloc_nr(queue->alloc); - queue->queue = xrealloc(queue->queue, - sizeof(dp) * queue->alloc); - } + ALLOC_GROW(queue->queue, queue->nr + 1, queue->alloc); queue->queue[queue->nr++] = dp; } @@ -4776,6 +4742,7 @@ void diffcore_fix_diff_index(struct diff_options *options) void diffcore_std(struct diff_options *options) { + /* NOTE please keep the following in sync with diff_tree_combined() */ if (options->skip_stat_unmatch) diffcore_skip_stat_unmatch(options); if (!options->found_follow) { |