Merge branch 'jk/diff-convfilter'
* jk/diff-convfilter: enable textconv for diff in verbose status/commit wt-status: load diff ui config only textconv regular files userdiff: require explicitly allowing textconv refactor userdiff textconv code Conflicts: t/t4030-diff-textconv.sh
This commit is contained in:
@ -300,6 +300,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
|
DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
|
||||||
DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
|
DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
|
||||||
|
DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the user asked for our exit code then don't start a
|
* If the user asked for our exit code then don't start a
|
||||||
|
@ -59,6 +59,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
|
|||||||
} else
|
} else
|
||||||
die("unrecognized argument: %s", arg);
|
die("unrecognized argument: %s", arg);
|
||||||
}
|
}
|
||||||
|
DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
70
diff.c
70
diff.c
@ -93,12 +93,6 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
|
|||||||
if (!strcmp(var, "diff.external"))
|
if (!strcmp(var, "diff.external"))
|
||||||
return git_config_string(&external_diff_cmd_cfg, var, value);
|
return git_config_string(&external_diff_cmd_cfg, var, value);
|
||||||
|
|
||||||
switch (userdiff_config_porcelain(var, value)) {
|
|
||||||
case 0: break;
|
|
||||||
case -1: return -1;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return git_diff_basic_config(var, value, cb);
|
return git_diff_basic_config(var, value, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +103,12 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (userdiff_config(var, value)) {
|
||||||
|
case 0: break;
|
||||||
|
case -1: return -1;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
|
if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
|
||||||
int slot = parse_diff_color_slot(var, 11);
|
int slot = parse_diff_color_slot(var, 11);
|
||||||
if (!value)
|
if (!value)
|
||||||
@ -123,12 +123,6 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (userdiff_config_basic(var, value)) {
|
|
||||||
case 0: break;
|
|
||||||
case -1: return -1;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return git_color_default_config(var, value, cb);
|
return git_color_default_config(var, value, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,18 +288,8 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
|
|||||||
else if (diff_populate_filespec(one, 0))
|
else if (diff_populate_filespec(one, 0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
diff_filespec_load_driver(one);
|
mf->ptr = one->data;
|
||||||
if (one->driver->textconv) {
|
mf->size = one->size;
|
||||||
size_t size;
|
|
||||||
mf->ptr = run_textconv(one->driver->textconv, one, &size);
|
|
||||||
if (!mf->ptr)
|
|
||||||
return -1;
|
|
||||||
mf->size = size;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mf->ptr = one->data;
|
|
||||||
mf->size = one->size;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1324,6 +1308,16 @@ void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const
|
|||||||
options->b_prefix = b;
|
options->b_prefix = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *get_textconv(struct diff_filespec *one)
|
||||||
|
{
|
||||||
|
if (!DIFF_FILE_VALID(one))
|
||||||
|
return NULL;
|
||||||
|
if (!S_ISREG(one->mode))
|
||||||
|
return NULL;
|
||||||
|
diff_filespec_load_driver(one);
|
||||||
|
return one->driver->textconv;
|
||||||
|
}
|
||||||
|
|
||||||
static void builtin_diff(const char *name_a,
|
static void builtin_diff(const char *name_a,
|
||||||
const char *name_b,
|
const char *name_b,
|
||||||
struct diff_filespec *one,
|
struct diff_filespec *one,
|
||||||
@ -1338,6 +1332,7 @@ static void builtin_diff(const char *name_a,
|
|||||||
const char *set = diff_get_color_opt(o, DIFF_METAINFO);
|
const char *set = diff_get_color_opt(o, DIFF_METAINFO);
|
||||||
const char *reset = diff_get_color_opt(o, DIFF_RESET);
|
const char *reset = diff_get_color_opt(o, DIFF_RESET);
|
||||||
const char *a_prefix, *b_prefix;
|
const char *a_prefix, *b_prefix;
|
||||||
|
const char *textconv_one = NULL, *textconv_two = NULL;
|
||||||
|
|
||||||
diff_set_mnemonic_prefix(o, "a/", "b/");
|
diff_set_mnemonic_prefix(o, "a/", "b/");
|
||||||
if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
|
if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
|
||||||
@ -1391,8 +1386,14 @@ static void builtin_diff(const char *name_a,
|
|||||||
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
|
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
|
||||||
die("unable to read files to diff");
|
die("unable to read files to diff");
|
||||||
|
|
||||||
|
if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
|
||||||
|
textconv_one = get_textconv(one);
|
||||||
|
textconv_two = get_textconv(two);
|
||||||
|
}
|
||||||
|
|
||||||
if (!DIFF_OPT_TST(o, TEXT) &&
|
if (!DIFF_OPT_TST(o, TEXT) &&
|
||||||
(diff_filespec_is_binary(one) || diff_filespec_is_binary(two))) {
|
( (diff_filespec_is_binary(one) && !textconv_one) ||
|
||||||
|
(diff_filespec_is_binary(two) && !textconv_two) )) {
|
||||||
/* Quite common confusing case */
|
/* Quite common confusing case */
|
||||||
if (mf1.size == mf2.size &&
|
if (mf1.size == mf2.size &&
|
||||||
!memcmp(mf1.ptr, mf2.ptr, mf1.size))
|
!memcmp(mf1.ptr, mf2.ptr, mf1.size))
|
||||||
@ -1413,6 +1414,21 @@ static void builtin_diff(const char *name_a,
|
|||||||
struct emit_callback ecbdata;
|
struct emit_callback ecbdata;
|
||||||
const struct userdiff_funcname *pe;
|
const struct userdiff_funcname *pe;
|
||||||
|
|
||||||
|
if (textconv_one) {
|
||||||
|
size_t size;
|
||||||
|
mf1.ptr = run_textconv(textconv_one, one, &size);
|
||||||
|
if (!mf1.ptr)
|
||||||
|
die("unable to read files to diff");
|
||||||
|
mf1.size = size;
|
||||||
|
}
|
||||||
|
if (textconv_two) {
|
||||||
|
size_t size;
|
||||||
|
mf2.ptr = run_textconv(textconv_two, two, &size);
|
||||||
|
if (!mf2.ptr)
|
||||||
|
die("unable to read files to diff");
|
||||||
|
mf2.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
pe = diff_funcname_pattern(one);
|
pe = diff_funcname_pattern(one);
|
||||||
if (!pe)
|
if (!pe)
|
||||||
pe = diff_funcname_pattern(two);
|
pe = diff_funcname_pattern(two);
|
||||||
@ -1445,6 +1461,10 @@ static void builtin_diff(const char *name_a,
|
|||||||
&xpp, &xecfg, &ecb);
|
&xpp, &xecfg, &ecb);
|
||||||
if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS))
|
if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS))
|
||||||
free_diff_words_data(&ecbdata);
|
free_diff_words_data(&ecbdata);
|
||||||
|
if (textconv_one)
|
||||||
|
free(mf1.ptr);
|
||||||
|
if (textconv_two)
|
||||||
|
free(mf2.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_ab_and_return:
|
free_ab_and_return:
|
||||||
|
1
diff.h
1
diff.h
@ -65,6 +65,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
|
|||||||
#define DIFF_OPT_IGNORE_SUBMODULES (1 << 18)
|
#define DIFF_OPT_IGNORE_SUBMODULES (1 << 18)
|
||||||
#define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19)
|
#define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19)
|
||||||
#define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20)
|
#define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20)
|
||||||
|
#define DIFF_OPT_ALLOW_TEXTCONV (1 << 21)
|
||||||
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
|
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
|
||||||
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
|
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
|
||||||
#define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag)
|
#define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag)
|
||||||
|
@ -52,7 +52,7 @@ test_expect_success 'setup textconv filters' '
|
|||||||
git config diff.fail.textconv false
|
git config diff.fail.textconv false
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_failure 'diff produces text' '
|
test_expect_success 'diff produces text' '
|
||||||
git diff HEAD^ HEAD >diff &&
|
git diff HEAD^ HEAD >diff &&
|
||||||
find_diff <diff >actual &&
|
find_diff <diff >actual &&
|
||||||
test_cmp expect.text actual
|
test_cmp expect.text actual
|
||||||
@ -64,23 +64,31 @@ test_expect_success 'diff-tree produces binary' '
|
|||||||
test_cmp expect.binary actual
|
test_cmp expect.binary actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_failure 'log produces text' '
|
test_expect_success 'log produces text' '
|
||||||
git log -1 -p >log &&
|
git log -1 -p >log &&
|
||||||
find_diff <log >actual &&
|
find_diff <log >actual &&
|
||||||
test_cmp expect.text actual
|
test_cmp expect.text actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_failure 'format-patch produces binary' '
|
test_expect_success 'format-patch produces binary' '
|
||||||
git format-patch --no-binary --stdout HEAD^ >patch &&
|
git format-patch --no-binary --stdout HEAD^ >patch &&
|
||||||
find_diff <patch >actual &&
|
find_diff <patch >actual &&
|
||||||
test_cmp expect.binary actual
|
test_cmp expect.binary actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'status -v produces text' '
|
||||||
|
git reset --soft HEAD^ &&
|
||||||
|
git status -v >diff &&
|
||||||
|
find_diff <diff >actual &&
|
||||||
|
test_cmp expect.text actual &&
|
||||||
|
git reset --soft HEAD@{1}
|
||||||
|
'
|
||||||
|
|
||||||
cat >expect.stat <<'EOF'
|
cat >expect.stat <<'EOF'
|
||||||
file | Bin 2 -> 4 bytes
|
file | Bin 2 -> 4 bytes
|
||||||
1 files changed, 0 insertions(+), 0 deletions(-)
|
1 files changed, 0 insertions(+), 0 deletions(-)
|
||||||
EOF
|
EOF
|
||||||
test_expect_failure 'diffstat does not run textconv' '
|
test_expect_success 'diffstat does not run textconv' '
|
||||||
echo file diff=fail >.gitattributes &&
|
echo file diff=fail >.gitattributes &&
|
||||||
git diff --stat HEAD^ HEAD >actual &&
|
git diff --stat HEAD^ HEAD >actual &&
|
||||||
test_cmp expect.stat actual
|
test_cmp expect.stat actual
|
||||||
@ -104,7 +112,7 @@ index ad8b3d2..67be421
|
|||||||
\ No newline at end of file
|
\ No newline at end of file
|
||||||
EOF
|
EOF
|
||||||
# make a symlink the hard way that works on symlink-challenged file systems
|
# make a symlink the hard way that works on symlink-challenged file systems
|
||||||
test_expect_failure 'textconv does not act on symlinks' '
|
test_expect_success 'textconv does not act on symlinks' '
|
||||||
printf frotz > file &&
|
printf frotz > file &&
|
||||||
git add file &&
|
git add file &&
|
||||||
git ls-files -s | sed -e s/100644/120000/ |
|
git ls-files -s | sed -e s/100644/120000/ |
|
||||||
|
@ -89,6 +89,14 @@ test_expect_success 'verbose' '
|
|||||||
|
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'verbose respects diff config' '
|
||||||
|
|
||||||
|
git config color.diff always &&
|
||||||
|
git status -v >actual &&
|
||||||
|
grep "\[1mdiff --git" actual &&
|
||||||
|
git config --unset color.diff
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'cleanup commit messages (verbatim,-t)' '
|
test_expect_success 'cleanup commit messages (verbatim,-t)' '
|
||||||
|
|
||||||
echo >>negative &&
|
echo >>negative &&
|
||||||
|
10
userdiff.c
10
userdiff.c
@ -120,7 +120,7 @@ static int parse_tristate(int *b, const char *k, const char *v)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int userdiff_config_basic(const char *k, const char *v)
|
int userdiff_config(const char *k, const char *v)
|
||||||
{
|
{
|
||||||
struct userdiff_driver *drv;
|
struct userdiff_driver *drv;
|
||||||
|
|
||||||
@ -130,14 +130,6 @@ int userdiff_config_basic(const char *k, const char *v)
|
|||||||
return parse_funcname(&drv->funcname, k, v, REG_EXTENDED);
|
return parse_funcname(&drv->funcname, k, v, REG_EXTENDED);
|
||||||
if ((drv = parse_driver(k, v, "binary")))
|
if ((drv = parse_driver(k, v, "binary")))
|
||||||
return parse_tristate(&drv->binary, k, v);
|
return parse_tristate(&drv->binary, k, v);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int userdiff_config_porcelain(const char *k, const char *v)
|
|
||||||
{
|
|
||||||
struct userdiff_driver *drv;
|
|
||||||
|
|
||||||
if ((drv = parse_driver(k, v, "command")))
|
if ((drv = parse_driver(k, v, "command")))
|
||||||
return parse_string(&drv->external, k, v);
|
return parse_string(&drv->external, k, v);
|
||||||
if ((drv = parse_driver(k, v, "textconv")))
|
if ((drv = parse_driver(k, v, "textconv")))
|
||||||
|
@ -14,8 +14,7 @@ struct userdiff_driver {
|
|||||||
const char *textconv;
|
const char *textconv;
|
||||||
};
|
};
|
||||||
|
|
||||||
int userdiff_config_basic(const char *k, const char *v);
|
int userdiff_config(const char *k, const char *v);
|
||||||
int userdiff_config_porcelain(const char *k, const char *v);
|
|
||||||
struct userdiff_driver *userdiff_find_by_name(const char *name);
|
struct userdiff_driver *userdiff_find_by_name(const char *name);
|
||||||
struct userdiff_driver *userdiff_find_by_path(const char *path);
|
struct userdiff_driver *userdiff_find_by_path(const char *path);
|
||||||
|
|
||||||
|
11
wt-status.c
11
wt-status.c
@ -301,8 +301,17 @@ static void wt_status_print_verbose(struct wt_status *s)
|
|||||||
setup_revisions(0, NULL, &rev, s->reference);
|
setup_revisions(0, NULL, &rev, s->reference);
|
||||||
rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
|
rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
|
||||||
rev.diffopt.detect_rename = 1;
|
rev.diffopt.detect_rename = 1;
|
||||||
|
DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
|
||||||
rev.diffopt.file = s->fp;
|
rev.diffopt.file = s->fp;
|
||||||
rev.diffopt.close_file = 0;
|
rev.diffopt.close_file = 0;
|
||||||
|
/*
|
||||||
|
* If we're not going to stdout, then we definitely don't
|
||||||
|
* want color, since we are going to the commit message
|
||||||
|
* file (and even the "auto" setting won't work, since it
|
||||||
|
* will have checked isatty on stdout).
|
||||||
|
*/
|
||||||
|
if (s->fp != stdout)
|
||||||
|
DIFF_OPT_CLR(&rev.diffopt, COLOR_DIFF);
|
||||||
run_diff_index(&rev, 1);
|
run_diff_index(&rev, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,5 +431,5 @@ int git_status_config(const char *k, const char *v, void *cb)
|
|||||||
return error("Invalid untracked files mode '%s'", v);
|
return error("Invalid untracked files mode '%s'", v);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return git_color_default_config(k, v, cb);
|
return git_diff_ui_config(k, v, cb);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user