diff --git a/diff.c b/diff.c index e87847fa4bdfe8..4929c054fac53a 100644 --- a/diff.c +++ b/diff.c @@ -55,6 +55,7 @@ static int diff_detect_rename_default; static int diff_indent_heuristic = 1; +static int diff_slide_down; static int diff_rename_limit_default = 1000; static int diff_suppress_blank_empty; static enum git_colorbool diff_use_color_default = GIT_COLOR_UNKNOWN; @@ -289,6 +290,8 @@ int git_diff_heuristic_config(const char *var, const char *value, { if (!strcmp(var, "diff.indentheuristic")) diff_indent_heuristic = git_config_bool(var, value); + if (!strcmp(var, "diff.slidedown")) + diff_slide_down = git_config_bool(var, value); return 0; } @@ -4861,6 +4864,8 @@ void repo_diff_setup(struct repository *r, struct diff_options *options) options->xdl_opts |= diff_algorithm; if (diff_indent_heuristic) DIFF_XDL_SET(options, INDENT_HEURISTIC); + if (diff_slide_down) + DIFF_XDL_SET(options, SLIDE_DOWN); options->orderfile = xstrdup_or_null(diff_order_file_cfg); @@ -5910,6 +5915,9 @@ struct option *add_diff_options(const struct option *opts, OPT_BIT(0, "indent-heuristic", &options->xdl_opts, N_("heuristic to shift diff hunk boundaries for easy reading"), XDF_INDENT_HEURISTIC), + OPT_BIT(0, "slide-down", &options->xdl_opts, + N_("slide ambiguous diff hunks downward (append after context)"), + XDF_SLIDE_DOWN), OPT_CALLBACK_F(0, "patience", options, NULL, N_("generate diff using the \"patience diff\" algorithm"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index dc370712e92860..125f80eadbf0a8 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -47,6 +47,7 @@ extern "C" { #define XDF_DIFF_ALG(x) ((x) & XDF_DIFF_ALGORITHM_MASK) #define XDF_INDENT_HEURISTIC (1 << 23) +#define XDF_SLIDE_DOWN (1 << 24) /* xdemitconf_t.flags */ #define XDL_EMIT_FUNCNAMES (1 << 0) diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c index 4376f943dba539..cf7a9a9588e4a0 100644 --- a/xdiff/xdiffi.c +++ b/xdiff/xdiffi.c @@ -857,6 +857,15 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) { if (g.end == earliest_end) { /* no shifting was possible */ + } else if (flags & XDF_SLIDE_DOWN) { + /* + * --slide-down: the group is already at the + * furthest-down position. Leave it there. + * This produces diffs where ambiguous hunks + * (e.g., duplicate delimiter lines) appear + * as appended after existing context rather + * than inserted before it. + */ } else if (end_matching_other != -1) { /* * Move the possibly merged group of changes back to