Merge branch 'sb/diff-color-move-more'
"git diff --color-moved" feature has further been tweaked. * sb/diff-color-move-more: diff.c: offer config option to control ws handling in move detection diff.c: add white space mode to move detection that allows indent changes diff.c: factor advance_or_nullify out of mark_color_as_moved diff.c: decouple white space treatment from move detection algorithm diff.c: add a blocks mode for moved code detection diff.c: adjust hash function signature to match hashmap expectation diff.c: do not pass diff options as keydata to hashmap t4015: avoid git as a pipe input xdiff/xdiffi.c: remove unneeded function declarations xdiff/xdiff.h: remove unused flagsmaint
commit
a81575aa91
|
@ -1152,6 +1152,11 @@ diff.colorMoved::
|
||||||
true the default color mode will be used. When set to false,
|
true the default color mode will be used. When set to false,
|
||||||
moved lines are not colored.
|
moved lines are not colored.
|
||||||
|
|
||||||
|
diff.colorMovedWS::
|
||||||
|
When moved lines are colored using e.g. the `diff.colorMoved` setting,
|
||||||
|
this option controls the `<mode>` how spaces are treated
|
||||||
|
for details of valid modes see '--color-moved-ws' in linkgit:git-diff[1].
|
||||||
|
|
||||||
color.diff.<slot>::
|
color.diff.<slot>::
|
||||||
Use customized color for diff colorization. `<slot>` specifies
|
Use customized color for diff colorization. `<slot>` specifies
|
||||||
which part of the patch to use the specified color, and is one
|
which part of the patch to use the specified color, and is one
|
||||||
|
|
|
@ -276,10 +276,14 @@ plain::
|
||||||
that are added somewhere else in the diff. This mode picks up any
|
that are added somewhere else in the diff. This mode picks up any
|
||||||
moved line, but it is not very useful in a review to determine
|
moved line, but it is not very useful in a review to determine
|
||||||
if a block of code was moved without permutation.
|
if a block of code was moved without permutation.
|
||||||
zebra::
|
blocks::
|
||||||
Blocks of moved text of at least 20 alphanumeric characters
|
Blocks of moved text of at least 20 alphanumeric characters
|
||||||
are detected greedily. The detected blocks are
|
are detected greedily. The detected blocks are
|
||||||
painted using either the 'color.diff.{old,new}Moved' color or
|
painted using either the 'color.diff.{old,new}Moved' color.
|
||||||
|
Adjacent blocks cannot be told apart.
|
||||||
|
zebra::
|
||||||
|
Blocks of moved text are detected as in 'blocks' mode. The blocks
|
||||||
|
are painted using either the 'color.diff.{old,new}Moved' color or
|
||||||
'color.diff.{old,new}MovedAlternative'. The change between
|
'color.diff.{old,new}MovedAlternative'. The change between
|
||||||
the two colors indicates that a new block was detected.
|
the two colors indicates that a new block was detected.
|
||||||
dimmed_zebra::
|
dimmed_zebra::
|
||||||
|
@ -288,6 +292,31 @@ dimmed_zebra::
|
||||||
blocks are considered interesting, the rest is uninteresting.
|
blocks are considered interesting, the rest is uninteresting.
|
||||||
--
|
--
|
||||||
|
|
||||||
|
--color-moved-ws=<modes>::
|
||||||
|
This configures how white spaces are ignored when performing the
|
||||||
|
move detection for `--color-moved`.
|
||||||
|
ifdef::git-diff[]
|
||||||
|
It can be set by the `diff.colorMovedWS` configuration setting.
|
||||||
|
endif::git-diff[]
|
||||||
|
These modes can be given as a comma separated list:
|
||||||
|
+
|
||||||
|
--
|
||||||
|
ignore-space-at-eol::
|
||||||
|
Ignore changes in whitespace at EOL.
|
||||||
|
ignore-space-change::
|
||||||
|
Ignore changes in amount of whitespace. This ignores whitespace
|
||||||
|
at line end, and considers all other sequences of one or
|
||||||
|
more whitespace characters to be equivalent.
|
||||||
|
ignore-all-space::
|
||||||
|
Ignore whitespace when comparing lines. This ignores differences
|
||||||
|
even if one line has whitespace where the other line has none.
|
||||||
|
allow-indentation-change::
|
||||||
|
Initially ignore any white spaces in the move detection, then
|
||||||
|
group the moved code blocks only into a block if the change in
|
||||||
|
whitespace is the same per line. This is incompatible with the
|
||||||
|
other modes.
|
||||||
|
--
|
||||||
|
|
||||||
--word-diff[=<mode>]::
|
--word-diff[=<mode>]::
|
||||||
Show a word diff, using the <mode> to delimit changed words.
|
Show a word diff, using the <mode> to delimit changed words.
|
||||||
By default, words are delimited by whitespace; see
|
By default, words are delimited by whitespace; see
|
||||||
|
|
260
diff.c
260
diff.c
|
@ -37,6 +37,7 @@ static int diff_rename_limit_default = 400;
|
||||||
static int diff_suppress_blank_empty;
|
static int diff_suppress_blank_empty;
|
||||||
static int diff_use_color_default = -1;
|
static int diff_use_color_default = -1;
|
||||||
static int diff_color_moved_default;
|
static int diff_color_moved_default;
|
||||||
|
static int diff_color_moved_ws_default;
|
||||||
static int diff_context_default = 3;
|
static int diff_context_default = 3;
|
||||||
static int diff_interhunk_context_default;
|
static int diff_interhunk_context_default;
|
||||||
static const char *diff_word_regex_cfg;
|
static const char *diff_word_regex_cfg;
|
||||||
|
@ -264,6 +265,8 @@ static int parse_color_moved(const char *arg)
|
||||||
return COLOR_MOVED_NO;
|
return COLOR_MOVED_NO;
|
||||||
else if (!strcmp(arg, "plain"))
|
else if (!strcmp(arg, "plain"))
|
||||||
return COLOR_MOVED_PLAIN;
|
return COLOR_MOVED_PLAIN;
|
||||||
|
else if (!strcmp(arg, "blocks"))
|
||||||
|
return COLOR_MOVED_BLOCKS;
|
||||||
else if (!strcmp(arg, "zebra"))
|
else if (!strcmp(arg, "zebra"))
|
||||||
return COLOR_MOVED_ZEBRA;
|
return COLOR_MOVED_ZEBRA;
|
||||||
else if (!strcmp(arg, "default"))
|
else if (!strcmp(arg, "default"))
|
||||||
|
@ -271,7 +274,43 @@ static int parse_color_moved(const char *arg)
|
||||||
else if (!strcmp(arg, "dimmed_zebra"))
|
else if (!strcmp(arg, "dimmed_zebra"))
|
||||||
return COLOR_MOVED_ZEBRA_DIM;
|
return COLOR_MOVED_ZEBRA_DIM;
|
||||||
else
|
else
|
||||||
return error(_("color moved setting must be one of 'no', 'default', 'zebra', 'dimmed_zebra', 'plain'"));
|
return error(_("color moved setting must be one of 'no', 'default', 'blocks', 'zebra', 'dimmed_zebra', 'plain'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_color_moved_ws(const char *arg)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct string_list l = STRING_LIST_INIT_DUP;
|
||||||
|
struct string_list_item *i;
|
||||||
|
|
||||||
|
string_list_split(&l, arg, ',', -1);
|
||||||
|
|
||||||
|
for_each_string_list_item(i, &l) {
|
||||||
|
struct strbuf sb = STRBUF_INIT;
|
||||||
|
strbuf_addstr(&sb, i->string);
|
||||||
|
strbuf_trim(&sb);
|
||||||
|
|
||||||
|
if (!strcmp(sb.buf, "ignore-space-change"))
|
||||||
|
ret |= XDF_IGNORE_WHITESPACE_CHANGE;
|
||||||
|
else if (!strcmp(sb.buf, "ignore-space-at-eol"))
|
||||||
|
ret |= XDF_IGNORE_WHITESPACE_AT_EOL;
|
||||||
|
else if (!strcmp(sb.buf, "ignore-all-space"))
|
||||||
|
ret |= XDF_IGNORE_WHITESPACE;
|
||||||
|
else if (!strcmp(sb.buf, "allow-indentation-change"))
|
||||||
|
ret |= COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE;
|
||||||
|
else
|
||||||
|
error(_("ignoring unknown color-moved-ws mode '%s'"), sb.buf);
|
||||||
|
|
||||||
|
strbuf_release(&sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret & COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE) &&
|
||||||
|
(ret & XDF_WHITESPACE_FLAGS))
|
||||||
|
die(_("color-moved-ws: allow-indentation-change cannot be combined with other white space modes"));
|
||||||
|
|
||||||
|
string_list_clear(&l, 0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_diff_ui_config(const char *var, const char *value, void *cb)
|
int git_diff_ui_config(const char *var, const char *value, void *cb)
|
||||||
|
@ -287,6 +326,13 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
|
||||||
diff_color_moved_default = cm;
|
diff_color_moved_default = cm;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(var, "diff.colormovedws")) {
|
||||||
|
int cm = parse_color_moved_ws(value);
|
||||||
|
if (cm < 0)
|
||||||
|
return -1;
|
||||||
|
diff_color_moved_ws_default = cm;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!strcmp(var, "diff.context")) {
|
if (!strcmp(var, "diff.context")) {
|
||||||
diff_context_default = git_config_int(var, value);
|
diff_context_default = git_config_int(var, value);
|
||||||
if (diff_context_default < 0)
|
if (diff_context_default < 0)
|
||||||
|
@ -698,16 +744,116 @@ struct moved_entry {
|
||||||
struct hashmap_entry ent;
|
struct hashmap_entry ent;
|
||||||
const struct emitted_diff_symbol *es;
|
const struct emitted_diff_symbol *es;
|
||||||
struct moved_entry *next_line;
|
struct moved_entry *next_line;
|
||||||
|
struct ws_delta *wsd;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int moved_entry_cmp(const struct diff_options *diffopt,
|
/**
|
||||||
const struct moved_entry *a,
|
* The struct ws_delta holds white space differences between moved lines, i.e.
|
||||||
const struct moved_entry *b,
|
* between '+' and '-' lines that have been detected to be a move.
|
||||||
|
* The string contains the difference in leading white spaces, before the
|
||||||
|
* rest of the line is compared using the white space config for move
|
||||||
|
* coloring. The current_longer indicates if the first string in the
|
||||||
|
* comparision is longer than the second.
|
||||||
|
*/
|
||||||
|
struct ws_delta {
|
||||||
|
char *string;
|
||||||
|
unsigned int current_longer : 1;
|
||||||
|
};
|
||||||
|
#define WS_DELTA_INIT { NULL, 0 }
|
||||||
|
|
||||||
|
static int compute_ws_delta(const struct emitted_diff_symbol *a,
|
||||||
|
const struct emitted_diff_symbol *b,
|
||||||
|
struct ws_delta *out)
|
||||||
|
{
|
||||||
|
const struct emitted_diff_symbol *longer = a->len > b->len ? a : b;
|
||||||
|
const struct emitted_diff_symbol *shorter = a->len > b->len ? b : a;
|
||||||
|
int d = longer->len - shorter->len;
|
||||||
|
|
||||||
|
out->string = xmemdupz(longer->line, d);
|
||||||
|
out->current_longer = (a == longer);
|
||||||
|
|
||||||
|
return !strncmp(longer->line + d, shorter->line, shorter->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_in_block_with_wsd(const struct diff_options *o,
|
||||||
|
const struct moved_entry *cur,
|
||||||
|
const struct moved_entry *match,
|
||||||
|
struct moved_entry *pmb,
|
||||||
|
int n)
|
||||||
|
{
|
||||||
|
struct emitted_diff_symbol *l = &o->emitted_symbols->buf[n];
|
||||||
|
int al = cur->es->len, cl = l->len;
|
||||||
|
const char *a = cur->es->line,
|
||||||
|
*b = match->es->line,
|
||||||
|
*c = l->line;
|
||||||
|
|
||||||
|
int wslen;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to check if 'cur' is equal to 'match'.
|
||||||
|
* As those are from the same (+/-) side, we do not need to adjust for
|
||||||
|
* indent changes. However these were found using fuzzy matching
|
||||||
|
* so we do have to check if they are equal.
|
||||||
|
*/
|
||||||
|
if (strcmp(a, b))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!pmb->wsd)
|
||||||
|
/*
|
||||||
|
* No white space delta was carried forward? This can happen
|
||||||
|
* when we exit early in this function and do not carry
|
||||||
|
* forward ws.
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The indent changes of the block are known and carried forward in
|
||||||
|
* pmb->wsd; however we need to check if the indent changes of the
|
||||||
|
* current line are still the same as before.
|
||||||
|
*
|
||||||
|
* To do so we need to compare 'l' to 'cur', adjusting the
|
||||||
|
* one of them for the white spaces, depending which was longer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
wslen = strlen(pmb->wsd->string);
|
||||||
|
if (pmb->wsd->current_longer) {
|
||||||
|
c += wslen;
|
||||||
|
cl -= wslen;
|
||||||
|
} else {
|
||||||
|
a += wslen;
|
||||||
|
al -= wslen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(a, c))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int moved_entry_cmp(const void *hashmap_cmp_fn_data,
|
||||||
|
const void *entry,
|
||||||
|
const void *entry_or_key,
|
||||||
const void *keydata)
|
const void *keydata)
|
||||||
{
|
{
|
||||||
|
const struct diff_options *diffopt = hashmap_cmp_fn_data;
|
||||||
|
const struct moved_entry *a = entry;
|
||||||
|
const struct moved_entry *b = entry_or_key;
|
||||||
|
unsigned flags = diffopt->color_moved_ws_handling
|
||||||
|
& XDF_WHITESPACE_FLAGS;
|
||||||
|
|
||||||
|
if (diffopt->color_moved_ws_handling &
|
||||||
|
COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE)
|
||||||
|
/*
|
||||||
|
* As there is not specific white space config given,
|
||||||
|
* we'd need to check for a new block, so ignore all
|
||||||
|
* white space. The setup of the white space
|
||||||
|
* configuration for the next block is done else where
|
||||||
|
*/
|
||||||
|
flags |= XDF_IGNORE_WHITESPACE;
|
||||||
|
|
||||||
return !xdiff_compare_lines(a->es->line, a->es->len,
|
return !xdiff_compare_lines(a->es->line, a->es->len,
|
||||||
b->es->line, b->es->len,
|
b->es->line, b->es->len,
|
||||||
diffopt->xdl_opts);
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct moved_entry *prepare_entry(struct diff_options *o,
|
static struct moved_entry *prepare_entry(struct diff_options *o,
|
||||||
|
@ -715,10 +861,12 @@ static struct moved_entry *prepare_entry(struct diff_options *o,
|
||||||
{
|
{
|
||||||
struct moved_entry *ret = xmalloc(sizeof(*ret));
|
struct moved_entry *ret = xmalloc(sizeof(*ret));
|
||||||
struct emitted_diff_symbol *l = &o->emitted_symbols->buf[line_no];
|
struct emitted_diff_symbol *l = &o->emitted_symbols->buf[line_no];
|
||||||
|
unsigned flags = o->color_moved_ws_handling & XDF_WHITESPACE_FLAGS;
|
||||||
|
|
||||||
ret->ent.hash = xdiff_hash_string(l->line, l->len, o->xdl_opts);
|
ret->ent.hash = xdiff_hash_string(l->line, l->len, flags);
|
||||||
ret->es = l;
|
ret->es = l;
|
||||||
ret->next_line = NULL;
|
ret->next_line = NULL;
|
||||||
|
ret->wsd = NULL;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -755,6 +903,56 @@ static void add_lines_to_move_detection(struct diff_options *o,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pmb_advance_or_null(struct diff_options *o,
|
||||||
|
struct moved_entry *match,
|
||||||
|
struct hashmap *hm,
|
||||||
|
struct moved_entry **pmb,
|
||||||
|
int pmb_nr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < pmb_nr; i++) {
|
||||||
|
struct moved_entry *prev = pmb[i];
|
||||||
|
struct moved_entry *cur = (prev && prev->next_line) ?
|
||||||
|
prev->next_line : NULL;
|
||||||
|
if (cur && !hm->cmpfn(o, cur, match, NULL)) {
|
||||||
|
pmb[i] = cur;
|
||||||
|
} else {
|
||||||
|
pmb[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmb_advance_or_null_multi_match(struct diff_options *o,
|
||||||
|
struct moved_entry *match,
|
||||||
|
struct hashmap *hm,
|
||||||
|
struct moved_entry **pmb,
|
||||||
|
int pmb_nr, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *got_match = xcalloc(1, pmb_nr);
|
||||||
|
|
||||||
|
for (; match; match = hashmap_get_next(hm, match)) {
|
||||||
|
for (i = 0; i < pmb_nr; i++) {
|
||||||
|
struct moved_entry *prev = pmb[i];
|
||||||
|
struct moved_entry *cur = (prev && prev->next_line) ?
|
||||||
|
prev->next_line : NULL;
|
||||||
|
if (!cur)
|
||||||
|
continue;
|
||||||
|
if (!cmp_in_block_with_wsd(o, cur, match, pmb[i], n))
|
||||||
|
got_match[i] |= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pmb_nr; i++) {
|
||||||
|
if (got_match[i]) {
|
||||||
|
/* Carry the white space delta forward */
|
||||||
|
pmb[i]->next_line->wsd = pmb[i]->wsd;
|
||||||
|
pmb[i] = pmb[i]->next_line;
|
||||||
|
} else
|
||||||
|
pmb[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int shrink_potential_moved_blocks(struct moved_entry **pmb,
|
static int shrink_potential_moved_blocks(struct moved_entry **pmb,
|
||||||
int pmb_nr)
|
int pmb_nr)
|
||||||
{
|
{
|
||||||
|
@ -772,6 +970,10 @@ static int shrink_potential_moved_blocks(struct moved_entry **pmb,
|
||||||
|
|
||||||
if (lp < pmb_nr && rp > -1 && lp < rp) {
|
if (lp < pmb_nr && rp > -1 && lp < rp) {
|
||||||
pmb[lp] = pmb[rp];
|
pmb[lp] = pmb[rp];
|
||||||
|
if (pmb[rp]->wsd) {
|
||||||
|
free(pmb[rp]->wsd->string);
|
||||||
|
FREE_AND_NULL(pmb[rp]->wsd);
|
||||||
|
}
|
||||||
pmb[rp] = NULL;
|
pmb[rp] = NULL;
|
||||||
rp--;
|
rp--;
|
||||||
lp++;
|
lp++;
|
||||||
|
@ -829,19 +1031,18 @@ static void mark_color_as_moved(struct diff_options *o,
|
||||||
struct moved_entry *key;
|
struct moved_entry *key;
|
||||||
struct moved_entry *match = NULL;
|
struct moved_entry *match = NULL;
|
||||||
struct emitted_diff_symbol *l = &o->emitted_symbols->buf[n];
|
struct emitted_diff_symbol *l = &o->emitted_symbols->buf[n];
|
||||||
int i;
|
|
||||||
|
|
||||||
switch (l->s) {
|
switch (l->s) {
|
||||||
case DIFF_SYMBOL_PLUS:
|
case DIFF_SYMBOL_PLUS:
|
||||||
hm = del_lines;
|
hm = del_lines;
|
||||||
key = prepare_entry(o, n);
|
key = prepare_entry(o, n);
|
||||||
match = hashmap_get(hm, key, o);
|
match = hashmap_get(hm, key, NULL);
|
||||||
free(key);
|
free(key);
|
||||||
break;
|
break;
|
||||||
case DIFF_SYMBOL_MINUS:
|
case DIFF_SYMBOL_MINUS:
|
||||||
hm = add_lines;
|
hm = add_lines;
|
||||||
key = prepare_entry(o, n);
|
key = prepare_entry(o, n);
|
||||||
match = hashmap_get(hm, key, o);
|
match = hashmap_get(hm, key, NULL);
|
||||||
free(key);
|
free(key);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -860,17 +1061,11 @@ static void mark_color_as_moved(struct diff_options *o,
|
||||||
if (o->color_moved == COLOR_MOVED_PLAIN)
|
if (o->color_moved == COLOR_MOVED_PLAIN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check any potential block runs, advance each or nullify */
|
if (o->color_moved_ws_handling &
|
||||||
for (i = 0; i < pmb_nr; i++) {
|
COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE)
|
||||||
struct moved_entry *p = pmb[i];
|
pmb_advance_or_null_multi_match(o, match, hm, pmb, pmb_nr, n);
|
||||||
struct moved_entry *pnext = (p && p->next_line) ?
|
else
|
||||||
p->next_line : NULL;
|
pmb_advance_or_null(o, match, hm, pmb, pmb_nr);
|
||||||
if (pnext && !hm->cmpfn(o, pnext, match, NULL)) {
|
|
||||||
pmb[i] = p->next_line;
|
|
||||||
} else {
|
|
||||||
pmb[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pmb_nr = shrink_potential_moved_blocks(pmb, pmb_nr);
|
pmb_nr = shrink_potential_moved_blocks(pmb, pmb_nr);
|
||||||
|
|
||||||
|
@ -881,7 +1076,17 @@ static void mark_color_as_moved(struct diff_options *o,
|
||||||
*/
|
*/
|
||||||
for (; match; match = hashmap_get_next(hm, match)) {
|
for (; match; match = hashmap_get_next(hm, match)) {
|
||||||
ALLOC_GROW(pmb, pmb_nr + 1, pmb_alloc);
|
ALLOC_GROW(pmb, pmb_nr + 1, pmb_alloc);
|
||||||
|
if (o->color_moved_ws_handling &
|
||||||
|
COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE) {
|
||||||
|
struct ws_delta *wsd = xmalloc(sizeof(*match->wsd));
|
||||||
|
if (compute_ws_delta(l, match->es, wsd)) {
|
||||||
|
match->wsd = wsd;
|
||||||
pmb[pmb_nr++] = match;
|
pmb[pmb_nr++] = match;
|
||||||
|
} else
|
||||||
|
free(wsd);
|
||||||
|
} else {
|
||||||
|
pmb[pmb_nr++] = match;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flipped_block = (flipped_block + 1) % 2;
|
flipped_block = (flipped_block + 1) % 2;
|
||||||
|
@ -892,7 +1097,7 @@ static void mark_color_as_moved(struct diff_options *o,
|
||||||
|
|
||||||
block_length++;
|
block_length++;
|
||||||
|
|
||||||
if (flipped_block)
|
if (flipped_block && o->color_moved != COLOR_MOVED_BLOCKS)
|
||||||
l->flags |= DIFF_SYMBOL_MOVED_LINE_ALT;
|
l->flags |= DIFF_SYMBOL_MOVED_LINE_ALT;
|
||||||
}
|
}
|
||||||
adjust_last_block(o, n, block_length);
|
adjust_last_block(o, n, block_length);
|
||||||
|
@ -4125,6 +4330,7 @@ void diff_setup(struct diff_options *options)
|
||||||
}
|
}
|
||||||
|
|
||||||
options->color_moved = diff_color_moved_default;
|
options->color_moved = diff_color_moved_default;
|
||||||
|
options->color_moved_ws_handling = diff_color_moved_ws_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
void diff_setup_done(struct diff_options *options)
|
void diff_setup_done(struct diff_options *options)
|
||||||
|
@ -4704,6 +4910,8 @@ int diff_opt_parse(struct diff_options *options,
|
||||||
if (cm < 0)
|
if (cm < 0)
|
||||||
die("bad --color-moved argument: %s", arg);
|
die("bad --color-moved argument: %s", arg);
|
||||||
options->color_moved = cm;
|
options->color_moved = cm;
|
||||||
|
} else if (skip_prefix(arg, "--color-moved-ws=", &arg)) {
|
||||||
|
options->color_moved_ws_handling = parse_color_moved_ws(arg);
|
||||||
} else if (skip_to_optional_arg_default(arg, "--color-words", &options->word_regex, NULL)) {
|
} else if (skip_to_optional_arg_default(arg, "--color-words", &options->word_regex, NULL)) {
|
||||||
options->use_color = 1;
|
options->use_color = 1;
|
||||||
options->word_diff = DIFF_WORDS_COLOR;
|
options->word_diff = DIFF_WORDS_COLOR;
|
||||||
|
@ -5534,10 +5742,12 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
|
||||||
if (o->color_moved) {
|
if (o->color_moved) {
|
||||||
struct hashmap add_lines, del_lines;
|
struct hashmap add_lines, del_lines;
|
||||||
|
|
||||||
hashmap_init(&del_lines,
|
if (o->color_moved_ws_handling &
|
||||||
(hashmap_cmp_fn)moved_entry_cmp, o, 0);
|
COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE)
|
||||||
hashmap_init(&add_lines,
|
o->color_moved_ws_handling |= XDF_IGNORE_WHITESPACE;
|
||||||
(hashmap_cmp_fn)moved_entry_cmp, o, 0);
|
|
||||||
|
hashmap_init(&del_lines, moved_entry_cmp, o, 0);
|
||||||
|
hashmap_init(&add_lines, moved_entry_cmp, o, 0);
|
||||||
|
|
||||||
add_lines_to_move_detection(o, &add_lines, &del_lines);
|
add_lines_to_move_detection(o, &add_lines, &del_lines);
|
||||||
mark_color_as_moved(o, &add_lines, &del_lines);
|
mark_color_as_moved(o, &add_lines, &del_lines);
|
||||||
|
|
9
diff.h
9
diff.h
|
@ -208,11 +208,16 @@ struct diff_options {
|
||||||
enum {
|
enum {
|
||||||
COLOR_MOVED_NO = 0,
|
COLOR_MOVED_NO = 0,
|
||||||
COLOR_MOVED_PLAIN = 1,
|
COLOR_MOVED_PLAIN = 1,
|
||||||
COLOR_MOVED_ZEBRA = 2,
|
COLOR_MOVED_BLOCKS = 2,
|
||||||
COLOR_MOVED_ZEBRA_DIM = 3,
|
COLOR_MOVED_ZEBRA = 3,
|
||||||
|
COLOR_MOVED_ZEBRA_DIM = 4,
|
||||||
} color_moved;
|
} color_moved;
|
||||||
#define COLOR_MOVED_DEFAULT COLOR_MOVED_ZEBRA
|
#define COLOR_MOVED_DEFAULT COLOR_MOVED_ZEBRA
|
||||||
#define COLOR_MOVED_MIN_ALNUM_COUNT 20
|
#define COLOR_MOVED_MIN_ALNUM_COUNT 20
|
||||||
|
|
||||||
|
/* XDF_WHITESPACE_FLAGS regarding block detection are set at 2, 3, 4 */
|
||||||
|
#define COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE (1<<5)
|
||||||
|
int color_moved_ws_handling;
|
||||||
};
|
};
|
||||||
|
|
||||||
void diff_emit_submodule_del(struct diff_options *o, const char *line);
|
void diff_emit_submodule_del(struct diff_options *o, const char *line);
|
||||||
|
|
|
@ -1223,7 +1223,7 @@ test_expect_success 'plain moved code, inside file' '
|
||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'detect permutations inside moved code -- dimmed_zebra' '
|
test_expect_success 'detect blocks of moved code' '
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
cat <<-\EOF >lines.txt &&
|
cat <<-\EOF >lines.txt &&
|
||||||
long line 1
|
long line 1
|
||||||
|
@ -1271,9 +1271,52 @@ test_expect_success 'detect permutations inside moved code -- dimmed_zebra' '
|
||||||
test_config color.diff.newMovedDimmed "normal cyan" &&
|
test_config color.diff.newMovedDimmed "normal cyan" &&
|
||||||
test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
|
test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
|
||||||
test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
|
test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
|
||||||
git diff HEAD --no-renames --color-moved=dimmed_zebra --color |
|
git diff HEAD --no-renames --color-moved=blocks --color >actual.raw &&
|
||||||
grep -v "index" |
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
test_decode_color >actual &&
|
cat <<-\EOF >expected &&
|
||||||
|
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
||||||
|
<BOLD>--- a/lines.txt<RESET>
|
||||||
|
<BOLD>+++ b/lines.txt<RESET>
|
||||||
|
<CYAN>@@ -1,16 +1,16 @@<RESET>
|
||||||
|
<MAGENTA>-long line 1<RESET>
|
||||||
|
<MAGENTA>-long line 2<RESET>
|
||||||
|
<MAGENTA>-long line 3<RESET>
|
||||||
|
line 4<RESET>
|
||||||
|
line 5<RESET>
|
||||||
|
line 6<RESET>
|
||||||
|
line 7<RESET>
|
||||||
|
line 8<RESET>
|
||||||
|
line 9<RESET>
|
||||||
|
<CYAN>+<RESET><CYAN>long line 1<RESET>
|
||||||
|
<CYAN>+<RESET><CYAN>long line 2<RESET>
|
||||||
|
<CYAN>+<RESET><CYAN>long line 3<RESET>
|
||||||
|
<CYAN>+<RESET><CYAN>long line 14<RESET>
|
||||||
|
<CYAN>+<RESET><CYAN>long line 15<RESET>
|
||||||
|
<CYAN>+<RESET><CYAN>long line 16<RESET>
|
||||||
|
line 10<RESET>
|
||||||
|
line 11<RESET>
|
||||||
|
line 12<RESET>
|
||||||
|
line 13<RESET>
|
||||||
|
<MAGENTA>-long line 14<RESET>
|
||||||
|
<MAGENTA>-long line 15<RESET>
|
||||||
|
<MAGENTA>-long line 16<RESET>
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'detect permutations inside moved code -- dimmed_zebra' '
|
||||||
|
# reuse setup from test before!
|
||||||
|
test_config color.diff.oldMoved "magenta" &&
|
||||||
|
test_config color.diff.newMoved "cyan" &&
|
||||||
|
test_config color.diff.oldMovedAlternative "blue" &&
|
||||||
|
test_config color.diff.newMovedAlternative "yellow" &&
|
||||||
|
test_config color.diff.oldMovedDimmed "normal magenta" &&
|
||||||
|
test_config color.diff.newMovedDimmed "normal cyan" &&
|
||||||
|
test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
|
||||||
|
test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
|
||||||
|
git diff HEAD --no-renames --color-moved=dimmed_zebra --color >actual.raw &&
|
||||||
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
cat <<-\EOF >expected &&
|
cat <<-\EOF >expected &&
|
||||||
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
||||||
<BOLD>--- a/lines.txt<RESET>
|
<BOLD>--- a/lines.txt<RESET>
|
||||||
|
@ -1315,9 +1358,8 @@ test_expect_success 'cmd option assumes configured colored-moved' '
|
||||||
test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
|
test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
|
||||||
test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
|
test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
|
||||||
test_config diff.colorMoved zebra &&
|
test_config diff.colorMoved zebra &&
|
||||||
git diff HEAD --no-renames --color-moved --color |
|
git diff HEAD --no-renames --color-moved --color >actual.raw &&
|
||||||
grep -v "index" |
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
test_decode_color >actual &&
|
|
||||||
cat <<-\EOF >expected &&
|
cat <<-\EOF >expected &&
|
||||||
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
||||||
<BOLD>--- a/lines.txt<RESET>
|
<BOLD>--- a/lines.txt<RESET>
|
||||||
|
@ -1395,9 +1437,8 @@ test_expect_success 'move detection ignoring whitespace ' '
|
||||||
line 4
|
line 4
|
||||||
line 5
|
line 5
|
||||||
EOF
|
EOF
|
||||||
git diff HEAD --no-renames --color-moved --color |
|
git diff HEAD --no-renames --color-moved --color >actual.raw &&
|
||||||
grep -v "index" |
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
test_decode_color >actual &&
|
|
||||||
cat <<-\EOF >expected &&
|
cat <<-\EOF >expected &&
|
||||||
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
||||||
<BOLD>--- a/lines.txt<RESET>
|
<BOLD>--- a/lines.txt<RESET>
|
||||||
|
@ -1419,9 +1460,9 @@ test_expect_success 'move detection ignoring whitespace ' '
|
||||||
EOF
|
EOF
|
||||||
test_cmp expected actual &&
|
test_cmp expected actual &&
|
||||||
|
|
||||||
git diff HEAD --no-renames -w --color-moved --color |
|
git diff HEAD --no-renames --color-moved --color \
|
||||||
grep -v "index" |
|
--color-moved-ws=ignore-all-space >actual.raw &&
|
||||||
test_decode_color >actual &&
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
cat <<-\EOF >expected &&
|
cat <<-\EOF >expected &&
|
||||||
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
||||||
<BOLD>--- a/lines.txt<RESET>
|
<BOLD>--- a/lines.txt<RESET>
|
||||||
|
@ -1459,9 +1500,8 @@ test_expect_success 'move detection ignoring whitespace changes' '
|
||||||
line 5
|
line 5
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
git diff HEAD --no-renames --color-moved --color |
|
git diff HEAD --no-renames --color-moved --color >actual.raw &&
|
||||||
grep -v "index" |
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
test_decode_color >actual &&
|
|
||||||
cat <<-\EOF >expected &&
|
cat <<-\EOF >expected &&
|
||||||
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
||||||
<BOLD>--- a/lines.txt<RESET>
|
<BOLD>--- a/lines.txt<RESET>
|
||||||
|
@ -1483,9 +1523,9 @@ test_expect_success 'move detection ignoring whitespace changes' '
|
||||||
EOF
|
EOF
|
||||||
test_cmp expected actual &&
|
test_cmp expected actual &&
|
||||||
|
|
||||||
git diff HEAD --no-renames -b --color-moved --color |
|
git diff HEAD --no-renames --color-moved --color \
|
||||||
grep -v "index" |
|
--color-moved-ws=ignore-space-change >actual.raw &&
|
||||||
test_decode_color >actual &&
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
cat <<-\EOF >expected &&
|
cat <<-\EOF >expected &&
|
||||||
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
||||||
<BOLD>--- a/lines.txt<RESET>
|
<BOLD>--- a/lines.txt<RESET>
|
||||||
|
@ -1526,9 +1566,8 @@ test_expect_success 'move detection ignoring whitespace at eol' '
|
||||||
# avoid cluttering the output with complaints about our eol whitespace
|
# avoid cluttering the output with complaints about our eol whitespace
|
||||||
test_config core.whitespace -blank-at-eol &&
|
test_config core.whitespace -blank-at-eol &&
|
||||||
|
|
||||||
git diff HEAD --no-renames --color-moved --color |
|
git diff HEAD --no-renames --color-moved --color >actual.raw &&
|
||||||
grep -v "index" |
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
test_decode_color >actual &&
|
|
||||||
cat <<-\EOF >expected &&
|
cat <<-\EOF >expected &&
|
||||||
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
||||||
<BOLD>--- a/lines.txt<RESET>
|
<BOLD>--- a/lines.txt<RESET>
|
||||||
|
@ -1550,9 +1589,9 @@ test_expect_success 'move detection ignoring whitespace at eol' '
|
||||||
EOF
|
EOF
|
||||||
test_cmp expected actual &&
|
test_cmp expected actual &&
|
||||||
|
|
||||||
git diff HEAD --no-renames --ignore-space-at-eol --color-moved --color |
|
git diff HEAD --no-renames --color-moved --color \
|
||||||
grep -v "index" |
|
--color-moved-ws=ignore-space-at-eol >actual.raw &&
|
||||||
test_decode_color >actual &&
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
cat <<-\EOF >expected &&
|
cat <<-\EOF >expected &&
|
||||||
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
|
||||||
<BOLD>--- a/lines.txt<RESET>
|
<BOLD>--- a/lines.txt<RESET>
|
||||||
|
@ -1597,9 +1636,8 @@ test_expect_success '--color-moved block at end of diff output respects MIN_ALNU
|
||||||
irrelevant_line
|
irrelevant_line
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
git diff HEAD --color-moved=zebra --color --no-renames |
|
git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
|
||||||
grep -v "index" |
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
test_decode_color >actual &&
|
|
||||||
cat >expected <<-\EOF &&
|
cat >expected <<-\EOF &&
|
||||||
<BOLD>diff --git a/bar b/bar<RESET>
|
<BOLD>diff --git a/bar b/bar<RESET>
|
||||||
<BOLD>--- a/bar<RESET>
|
<BOLD>--- a/bar<RESET>
|
||||||
|
@ -1636,9 +1674,8 @@ test_expect_success '--color-moved respects MIN_ALNUM_COUNT' '
|
||||||
nineteen chars 456789
|
nineteen chars 456789
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
git diff HEAD --color-moved=zebra --color --no-renames |
|
git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
|
||||||
grep -v "index" |
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
test_decode_color >actual &&
|
|
||||||
cat >expected <<-\EOF &&
|
cat >expected <<-\EOF &&
|
||||||
<BOLD>diff --git a/bar b/bar<RESET>
|
<BOLD>diff --git a/bar b/bar<RESET>
|
||||||
<BOLD>--- a/bar<RESET>
|
<BOLD>--- a/bar<RESET>
|
||||||
|
@ -1679,7 +1716,8 @@ test_expect_success '--color-moved treats adjacent blocks as separate for MIN_AL
|
||||||
7charsA
|
7charsA
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
git diff HEAD --color-moved=zebra --color --no-renames | grep -v "index" | test_decode_color >actual &&
|
git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
|
||||||
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
cat >expected <<-\EOF &&
|
cat >expected <<-\EOF &&
|
||||||
<BOLD>diff --git a/bar b/bar<RESET>
|
<BOLD>diff --git a/bar b/bar<RESET>
|
||||||
<BOLD>--- a/bar<RESET>
|
<BOLD>--- a/bar<RESET>
|
||||||
|
@ -1722,7 +1760,146 @@ test_expect_success 'move detection with submodules' '
|
||||||
|
|
||||||
# nor did we mess with it another way
|
# nor did we mess with it another way
|
||||||
git diff --submodule=diff --color | test_decode_color >expect &&
|
git diff --submodule=diff --color | test_decode_color >expect &&
|
||||||
test_cmp expect decoded_actual
|
test_cmp expect decoded_actual &&
|
||||||
|
rm -rf bananas &&
|
||||||
|
git submodule deinit bananas
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'only move detection ignores white spaces' '
|
||||||
|
git reset --hard &&
|
||||||
|
q_to_tab <<-\EOF >text.txt &&
|
||||||
|
a long line to exceed per-line minimum
|
||||||
|
another long line to exceed per-line minimum
|
||||||
|
original file
|
||||||
|
EOF
|
||||||
|
git add text.txt &&
|
||||||
|
git commit -m "add text" &&
|
||||||
|
q_to_tab <<-\EOF >text.txt &&
|
||||||
|
Qa long line to exceed per-line minimum
|
||||||
|
Qanother long line to exceed per-line minimum
|
||||||
|
new file
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Make sure we get a different diff using -w
|
||||||
|
git diff --color --color-moved -w >actual.raw &&
|
||||||
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
|
q_to_tab <<-\EOF >expected &&
|
||||||
|
<BOLD>diff --git a/text.txt b/text.txt<RESET>
|
||||||
|
<BOLD>--- a/text.txt<RESET>
|
||||||
|
<BOLD>+++ b/text.txt<RESET>
|
||||||
|
<CYAN>@@ -1,3 +1,3 @@<RESET>
|
||||||
|
Qa long line to exceed per-line minimum<RESET>
|
||||||
|
Qanother long line to exceed per-line minimum<RESET>
|
||||||
|
<RED>-original file<RESET>
|
||||||
|
<GREEN>+<RESET><GREEN>new file<RESET>
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual &&
|
||||||
|
|
||||||
|
# And now ignoring white space only in the move detection
|
||||||
|
git diff --color --color-moved \
|
||||||
|
--color-moved-ws=ignore-all-space,ignore-space-change,ignore-space-at-eol >actual.raw &&
|
||||||
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
|
q_to_tab <<-\EOF >expected &&
|
||||||
|
<BOLD>diff --git a/text.txt b/text.txt<RESET>
|
||||||
|
<BOLD>--- a/text.txt<RESET>
|
||||||
|
<BOLD>+++ b/text.txt<RESET>
|
||||||
|
<CYAN>@@ -1,3 +1,3 @@<RESET>
|
||||||
|
<BOLD;MAGENTA>-a long line to exceed per-line minimum<RESET>
|
||||||
|
<BOLD;MAGENTA>-another long line to exceed per-line minimum<RESET>
|
||||||
|
<RED>-original file<RESET>
|
||||||
|
<BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>a long line to exceed per-line minimum<RESET>
|
||||||
|
<BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>another long line to exceed per-line minimum<RESET>
|
||||||
|
<GREEN>+<RESET><GREEN>new file<RESET>
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'compare whitespace delta across moved blocks' '
|
||||||
|
|
||||||
|
git reset --hard &&
|
||||||
|
q_to_tab <<-\EOF >text.txt &&
|
||||||
|
QIndented
|
||||||
|
QText across
|
||||||
|
Qsome lines
|
||||||
|
QBut! <- this stands out
|
||||||
|
QAdjusting with
|
||||||
|
QQdifferent starting
|
||||||
|
Qwhite spaces
|
||||||
|
QAnother outlier
|
||||||
|
QQQIndented
|
||||||
|
QQQText across
|
||||||
|
QQQfive lines
|
||||||
|
QQQthat has similar lines
|
||||||
|
QQQto previous blocks, but with different indent
|
||||||
|
QQQYetQAnotherQoutlierQ
|
||||||
|
EOF
|
||||||
|
|
||||||
|
git add text.txt &&
|
||||||
|
git commit -m "add text.txt" &&
|
||||||
|
|
||||||
|
q_to_tab <<-\EOF >text.txt &&
|
||||||
|
QQIndented
|
||||||
|
QQText across
|
||||||
|
QQsome lines
|
||||||
|
QQQBut! <- this stands out
|
||||||
|
Adjusting with
|
||||||
|
Qdifferent starting
|
||||||
|
white spaces
|
||||||
|
AnotherQoutlier
|
||||||
|
QQIndented
|
||||||
|
QQText across
|
||||||
|
QQfive lines
|
||||||
|
QQthat has similar lines
|
||||||
|
QQto previous blocks, but with different indent
|
||||||
|
QQYetQAnotherQoutlier
|
||||||
|
EOF
|
||||||
|
|
||||||
|
git diff --color --color-moved --color-moved-ws=allow-indentation-change >actual.raw &&
|
||||||
|
grep -v "index" actual.raw | test_decode_color >actual &&
|
||||||
|
|
||||||
|
q_to_tab <<-\EOF >expected &&
|
||||||
|
<BOLD>diff --git a/text.txt b/text.txt<RESET>
|
||||||
|
<BOLD>--- a/text.txt<RESET>
|
||||||
|
<BOLD>+++ b/text.txt<RESET>
|
||||||
|
<CYAN>@@ -1,14 +1,14 @@<RESET>
|
||||||
|
<BOLD;MAGENTA>-QIndented<RESET>
|
||||||
|
<BOLD;MAGENTA>-QText across<RESET>
|
||||||
|
<BOLD;MAGENTA>-Qsome lines<RESET>
|
||||||
|
<RED>-QBut! <- this stands out<RESET>
|
||||||
|
<BOLD;MAGENTA>-QAdjusting with<RESET>
|
||||||
|
<BOLD;MAGENTA>-QQdifferent starting<RESET>
|
||||||
|
<BOLD;MAGENTA>-Qwhite spaces<RESET>
|
||||||
|
<RED>-QAnother outlier<RESET>
|
||||||
|
<BOLD;MAGENTA>-QQQIndented<RESET>
|
||||||
|
<BOLD;MAGENTA>-QQQText across<RESET>
|
||||||
|
<BOLD;MAGENTA>-QQQfive lines<RESET>
|
||||||
|
<BOLD;MAGENTA>-QQQthat has similar lines<RESET>
|
||||||
|
<BOLD;MAGENTA>-QQQto previous blocks, but with different indent<RESET>
|
||||||
|
<RED>-QQQYetQAnotherQoutlierQ<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>some lines<RESET>
|
||||||
|
<GREEN>+<RESET>QQQ<GREEN>But! <- this stands out<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET><BOLD;CYAN>Adjusting with<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET>Q<BOLD;CYAN>different starting<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET><BOLD;CYAN>white spaces<RESET>
|
||||||
|
<GREEN>+<RESET><GREEN>AnotherQoutlier<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>five lines<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>that has similar lines<RESET>
|
||||||
|
<BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>to previous blocks, but with different indent<RESET>
|
||||||
|
<GREEN>+<RESET>QQ<GREEN>YetQAnotherQoutlier<RESET>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'compare whitespace delta incompatible with other space options' '
|
||||||
|
test_must_fail git diff \
|
||||||
|
--color-moved-ws=allow-indentation-change,ignore-all-space \
|
||||||
|
2>err &&
|
||||||
|
test_i18ngrep allow-indentation-change err
|
||||||
'
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -52,14 +52,6 @@ extern "C" {
|
||||||
#define XDL_EMIT_FUNCNAMES (1 << 0)
|
#define XDL_EMIT_FUNCNAMES (1 << 0)
|
||||||
#define XDL_EMIT_FUNCCONTEXT (1 << 2)
|
#define XDL_EMIT_FUNCCONTEXT (1 << 2)
|
||||||
|
|
||||||
#define XDL_MMB_READONLY (1 << 0)
|
|
||||||
|
|
||||||
#define XDL_MMF_ATOMIC (1 << 0)
|
|
||||||
|
|
||||||
#define XDL_BDOP_INS 1
|
|
||||||
#define XDL_BDOP_CPY 2
|
|
||||||
#define XDL_BDOP_INSB 3
|
|
||||||
|
|
||||||
/* merge simplification levels */
|
/* merge simplification levels */
|
||||||
#define XDL_MERGE_MINIMAL 0
|
#define XDL_MERGE_MINIMAL 0
|
||||||
#define XDL_MERGE_EAGER 1
|
#define XDL_MERGE_EAGER 1
|
||||||
|
|
|
@ -22,34 +22,17 @@
|
||||||
|
|
||||||
#include "xinclude.h"
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define XDL_MAX_COST_MIN 256
|
#define XDL_MAX_COST_MIN 256
|
||||||
#define XDL_HEUR_MIN_COST 256
|
#define XDL_HEUR_MIN_COST 256
|
||||||
#define XDL_LINE_MAX (long)((1UL << (CHAR_BIT * sizeof(long) - 1)) - 1)
|
#define XDL_LINE_MAX (long)((1UL << (CHAR_BIT * sizeof(long) - 1)) - 1)
|
||||||
#define XDL_SNAKE_CNT 20
|
#define XDL_SNAKE_CNT 20
|
||||||
#define XDL_K_HEUR 4
|
#define XDL_K_HEUR 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct s_xdpsplit {
|
typedef struct s_xdpsplit {
|
||||||
long i1, i2;
|
long i1, i2;
|
||||||
int min_lo, min_hi;
|
int min_lo, min_hi;
|
||||||
} xdpsplit_t;
|
} xdpsplit_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static long xdl_split(unsigned long const *ha1, long off1, long lim1,
|
|
||||||
unsigned long const *ha2, long off2, long lim2,
|
|
||||||
long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl,
|
|
||||||
xdalgoenv_t *xenv);
|
|
||||||
static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See "An O(ND) Difference Algorithm and its Variations", by Eugene Myers.
|
* See "An O(ND) Difference Algorithm and its Variations", by Eugene Myers.
|
||||||
* Basically considers a "box" (off1, off2, lim1, lim2) and scan from both
|
* Basically considers a "box" (off1, off2, lim1, lim2) and scan from both
|
||||||
|
|
Loading…
Reference in New Issue