*/
void init_diff_ui_defaults(void)
{
- diff_detect_rename_default = 1;
+ diff_detect_rename_default = DIFF_DETECT_RENAME;
}
int git_diff_heuristic_config(const char *var, const char *value, void *cb)
struct moved_entry *next_line;
};
-static int next_byte(const char **cp, const char **endp,
- const struct diff_options *diffopt)
-{
- int retval;
-
- if (*cp > *endp)
- return -1;
-
- if (isspace(**cp)) {
- if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE_CHANGE)) {
- while (*cp < *endp && isspace(**cp))
- (*cp)++;
- /*
- * After skipping a couple of whitespaces,
- * we still have to account for one space.
- */
- return (int)' ';
- }
-
- if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE)) {
- while (*cp < *endp && isspace(**cp))
- (*cp)++;
- /* return the first non-ws character via the usual below */
- }
- }
-
- retval = (unsigned char)(**cp);
- (*cp)++;
- return retval;
-}
-
static int moved_entry_cmp(const struct diff_options *diffopt,
const struct moved_entry *a,
const struct moved_entry *b,
const void *keydata)
{
- const char *ap = a->es->line, *ae = a->es->line + a->es->len;
- const char *bp = b->es->line, *be = b->es->line + b->es->len;
-
- if (!(diffopt->xdl_opts & XDF_WHITESPACE_FLAGS))
- return a->es->len != b->es->len || memcmp(ap, bp, a->es->len);
-
- if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE_AT_EOL)) {
- while (ae > ap && isspace(*ae))
- ae--;
- while (be > bp && isspace(*be))
- be--;
- }
-
- while (1) {
- int ca, cb;
- ca = next_byte(&ap, &ae, diffopt);
- cb = next_byte(&bp, &be, diffopt);
- if (ca != cb)
- return 1;
- if (ca < 0)
- return 0;
- }
-}
-
-static unsigned get_string_hash(struct emitted_diff_symbol *es, struct diff_options *o)
-{
- if (o->xdl_opts & XDF_WHITESPACE_FLAGS) {
- static struct strbuf sb = STRBUF_INIT;
- const char *ap = es->line, *ae = es->line + es->len;
- int c;
-
- strbuf_reset(&sb);
- while (ae > ap && isspace(*ae))
- ae--;
- while ((c = next_byte(&ap, &ae, o)) > 0)
- strbuf_addch(&sb, c);
-
- return memhash(sb.buf, sb.len);
- } else {
- return memhash(es->line, es->len);
- }
+ return !xdiff_compare_lines(a->es->line, a->es->len,
+ b->es->line, b->es->len,
+ diffopt->xdl_opts);
}
static struct moved_entry *prepare_entry(struct diff_options *o,
struct moved_entry *ret = xmalloc(sizeof(*ret));
struct emitted_diff_symbol *l = &o->emitted_symbols->buf[line_no];
- ret->ent.hash = get_string_hash(l, o);
+ ret->ent.hash = xdiff_hash_string(l->line, l->len, o->xdl_opts);
ret->es = l;
ret->next_line = NULL;
ecbdata.opt = o;
ecbdata.header = header.len ? &header : NULL;
xpp.flags = o->xdl_opts;
+ xpp.anchors = o->anchors;
+ xpp.anchors_nr = o->anchors_nr;
xecfg.ctxlen = o->context;
xecfg.interhunkctxlen = o->interhunkcontext;
xecfg.flags = XDL_EMIT_FUNCNAMES;
memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
xpp.flags = o->xdl_opts;
+ xpp.anchors = o->anchors;
+ xpp.anchors_nr = o->anchors_nr;
xecfg.ctxlen = o->context;
xecfg.interhunkctxlen = o->interhunkcontext;
if (xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
int fd;
if (lstat(s->path, &st) < 0) {
- if (errno == ENOENT) {
- err_empty:
- err = -1;
- empty:
- s->data = (char *)"";
- s->size = 0;
- return err;
- }
+ err_empty:
+ err = -1;
+ empty:
+ s->data = (char *)"";
+ s->size = 0;
+ return err;
}
s->size = xsize_t(st.st_size);
if (!s->size)
options->interhunkcontext = diff_interhunk_context_default;
options->ws_error_highlight = ws_error_highlight_default;
options->flags.rename_empty = 1;
+ options->objfind = NULL;
/* pathchange left =NULL by default */
options->change = diff_change;
void diff_setup_done(struct diff_options *options)
{
- int count = 0;
+ unsigned check_mask = DIFF_FORMAT_NAME |
+ DIFF_FORMAT_NAME_STATUS |
+ DIFF_FORMAT_CHECKDIFF |
+ DIFF_FORMAT_NO_OUTPUT;
if (options->set_default)
options->set_default(options);
- if (options->output_format & DIFF_FORMAT_NAME)
- count++;
- if (options->output_format & DIFF_FORMAT_NAME_STATUS)
- count++;
- if (options->output_format & DIFF_FORMAT_CHECKDIFF)
- count++;
- if (options->output_format & DIFF_FORMAT_NO_OUTPUT)
- count++;
- if (count > 1)
+ if (HAS_MULTI_BITS(options->output_format & check_mask))
die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
+ if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
+ die(_("-G, -S and --find-object are mutually exclusive"));
+
/*
* Most of the time we can say "there are changes"
* only by checking if there are changed paths, but
* inside contents.
*/
- if (DIFF_XDL_TST(options, IGNORE_WHITESPACE) ||
- DIFF_XDL_TST(options, IGNORE_WHITESPACE_CHANGE) ||
- DIFF_XDL_TST(options, IGNORE_WHITESPACE_AT_EOL))
+ if ((options->xdl_opts & XDF_WHITESPACE_FLAGS))
options->flags.diff_from_contents = 1;
else
options->flags.diff_from_contents = 0;
/*
* Also pickaxe would not work very well if you do not say recursive
*/
- if (options->pickaxe)
+ if (options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK)
options->flags.recursive = 1;
/*
* When patches are generated, submodules diffed against the work tree
return 1;
}
+static int parse_objfind_opt(struct diff_options *opt, const char *arg)
+{
+ struct object_id oid;
+
+ if (get_oid(arg, &oid))
+ return error("unable to resolve '%s'", arg);
+
+ if (!opt->objfind)
+ opt->objfind = xcalloc(1, sizeof(*opt->objfind));
+
+ opt->pickaxe_opts |= DIFF_PICKAXE_KIND_OBJFIND;
+ opt->flags.recursive = 1;
+ opt->flags.tree_in_recursive = 1;
+ oidset_insert(opt->objfind, &oid);
+ return 1;
+}
+
int diff_opt_parse(struct diff_options *options,
const char **av, int ac, const char *prefix)
{
options->output_format |= DIFF_FORMAT_NUMSTAT;
else if (!strcmp(arg, "--shortstat"))
options->output_format |= DIFF_FORMAT_SHORTSTAT;
- else if (!strcmp(arg, "-X") || !strcmp(arg, "--dirstat"))
- return parse_dirstat_opt(options, "");
- else if (skip_prefix(arg, "-X", &arg))
- return parse_dirstat_opt(options, arg);
- else if (skip_prefix(arg, "--dirstat=", &arg))
+ else if (skip_prefix(arg, "-X", &arg) ||
+ skip_to_optional_arg(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 (skip_prefix(arg, "--dirstat-by-file=", &arg)) {
+ else if (skip_to_optional_arg(arg, "--dirstat-by-file", &arg)) {
parse_dirstat_opt(options, "files");
return parse_dirstat_opt(options, arg);
}
return stat_opt(options, av);
/* renames options */
- else if (starts_with(arg, "-B") || starts_with(arg, "--break-rewrites=") ||
- !strcmp(arg, "--break-rewrites")) {
+ else if (starts_with(arg, "-B") ||
+ skip_to_optional_arg(arg, "--break-rewrites", NULL)) {
if ((options->break_opt = diff_scoreopt_parse(arg)) == -1)
return error("invalid argument to -B: %s", arg+2);
}
- else if (starts_with(arg, "-M") || starts_with(arg, "--find-renames=") ||
- !strcmp(arg, "--find-renames")) {
+ else if (starts_with(arg, "-M") ||
+ skip_to_optional_arg(arg, "--find-renames", NULL)) {
if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
return error("invalid argument to -M: %s", arg+2);
options->detect_rename = DIFF_DETECT_RENAME;
else if (!strcmp(arg, "-D") || !strcmp(arg, "--irreversible-delete")) {
options->irreversible_delete = 1;
}
- else if (starts_with(arg, "-C") || starts_with(arg, "--find-copies=") ||
- !strcmp(arg, "--find-copies")) {
+ else if (starts_with(arg, "-C") ||
+ skip_to_optional_arg(arg, "--find-copies", NULL)) {
if (options->detect_rename == DIFF_DETECT_COPY)
options->flags.find_copies_harder = 1;
if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
options->flags.rename_empty = 1;
else if (!strcmp(arg, "--no-rename-empty"))
options->flags.rename_empty = 0;
- else if (!strcmp(arg, "--relative"))
- options->flags.relative_name = 1;
- else if (skip_prefix(arg, "--relative=", &arg)) {
+ else if (skip_to_optional_arg_default(arg, "--relative", &arg, NULL)) {
options->flags.relative_name = 1;
- options->prefix = arg;
+ if (arg)
+ options->prefix = arg;
}
/* xdiff options */
DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);
else if (!strcmp(arg, "--ignore-space-at-eol"))
DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
+ else if (!strcmp(arg, "--ignore-cr-at-eol"))
+ DIFF_XDL_SET(options, IGNORE_CR_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);
else if (!strcmp(arg, "--no-indent-heuristic"))
DIFF_XDL_CLR(options, INDENT_HEURISTIC);
- else if (!strcmp(arg, "--patience"))
+ else if (!strcmp(arg, "--patience")) {
+ int i;
options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
- else if (!strcmp(arg, "--histogram"))
+ /*
+ * Both --patience and --anchored use PATIENCE_DIFF
+ * internally, so remove any anchors previously
+ * specified.
+ */
+ for (i = 0; i < options->anchors_nr; i++)
+ free(options->anchors[i]);
+ options->anchors_nr = 0;
+ } else if (!strcmp(arg, "--histogram"))
options->xdl_opts = DIFF_WITH_ALG(options, HISTOGRAM_DIFF);
else if ((argcount = parse_long_opt("diff-algorithm", av, &optarg))) {
long value = parse_algorithm_value(optarg);
options->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
options->xdl_opts |= value;
return argcount;
+ } else if (skip_prefix(arg, "--anchored=", &arg)) {
+ options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
+ ALLOC_GROW(options->anchors, options->anchors_nr + 1,
+ options->anchors_alloc);
+ options->anchors[options->anchors_nr++] = xstrdup(arg);
}
/* flags options */
else if (!strcmp(arg, "--no-follow")) {
options->flags.follow_renames = 0;
options->flags.default_follow_renames = 0;
- } else if (!strcmp(arg, "--color"))
- options->use_color = 1;
- else if (skip_prefix(arg, "--color=", &arg)) {
+ } else if (skip_to_optional_arg_default(arg, "--color", &arg, "always")) {
int value = git_config_colorbool(NULL, arg);
if (value < 0)
return error("option `color' expects \"always\", \"auto\", or \"never\"");
if (cm < 0)
die("bad --color-moved argument: %s", arg);
options->color_moved = cm;
- } else if (!strcmp(arg, "--color-words")) {
- options->use_color = 1;
- options->word_diff = DIFF_WORDS_COLOR;
- }
- else if (skip_prefix(arg, "--color-words=", &arg)) {
+ } else if (skip_to_optional_arg_default(arg, "--color-words", &options->word_regex, NULL)) {
options->use_color = 1;
options->word_diff = DIFF_WORDS_COLOR;
- options->word_regex = arg;
}
else if (!strcmp(arg, "--word-diff")) {
if (options->word_diff == DIFF_WORDS_NONE)
options->flags.textconv_set_via_cmdline = 1;
} else if (!strcmp(arg, "--no-textconv"))
options->flags.allow_textconv = 0;
- else if (!strcmp(arg, "--ignore-submodules")) {
- options->flags.override_submodule_config = 1;
- handle_ignore_submodules_arg(options, "all");
- } else if (skip_prefix(arg, "--ignore-submodules=", &arg)) {
+ else if (skip_to_optional_arg_default(arg, "--ignore-submodules", &arg, "all")) {
options->flags.override_submodule_config = 1;
handle_ignore_submodules_arg(options, arg);
- } else if (!strcmp(arg, "--submodule"))
- options->submodule_format = DIFF_SUBMODULE_LOG;
- else if (skip_prefix(arg, "--submodule=", &arg))
+ } else if (skip_to_optional_arg_default(arg, "--submodule", &arg, "log"))
return parse_submodule_opt(options, arg);
else if (skip_prefix(arg, "--ws-error-highlight=", &arg))
return parse_ws_error_highlight_opt(options, arg);
else if ((argcount = short_opt('O', av, &optarg))) {
options->orderfile = prefix_filename(prefix, optarg);
return argcount;
- }
+ } else if (skip_prefix(arg, "--find-object=", &arg))
+ return parse_objfind_opt(options, arg);
else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
int offending = parse_diff_filter_opt(optarg, options);
if (offending)
int abblen;
const char *abbrev;
+ /* Do we want all 40 hex characters? */
if (len == GIT_SHA1_HEXSZ)
return oid_to_hex(oid);
+ /* An abbreviated value is fine, possibly followed by an ellipsis. */
abbrev = diff_abbrev_oid(oid, len);
+
+ if (!print_sha1_ellipsis())
+ return abbrev;
+
abblen = strlen(abbrev);
/*
- * In well-behaved cases, where the abbbreviated result is the
+ * In well-behaved cases, where the abbreviated 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
warning(_(rename_limit_warning));
else
return;
- if (0 < needed && needed < 32767)
+ if (0 < needed)
warning(_(rename_limit_advice), varname, needed);
}
if (options->break_opt != -1)
diffcore_merge_broken();
}
- if (options->pickaxe)
+ if (options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK)
diffcore_pickaxe(options);
if (options->orderfile)
diffcore_order(options->orderfile);