Merge branch 'jk/cached-textconv'
* jk/cached-textconv: diff: avoid useless filespec population diff: cache textconv output textconv: refactor calls to run_textconv introduce notes-cache interface make commit_tree a library function
This commit is contained in:
119
diff.c
119
diff.c
@ -44,7 +44,8 @@ static char diff_colors[][COLOR_MAXLEN] = {
|
||||
};
|
||||
|
||||
static void diff_filespec_load_driver(struct diff_filespec *one);
|
||||
static char *run_textconv(const char *, struct diff_filespec *, size_t *);
|
||||
static size_t fill_textconv(struct userdiff_driver *driver,
|
||||
struct diff_filespec *df, char **outbuf);
|
||||
|
||||
static int parse_diff_color_slot(const char *var, int ofs)
|
||||
{
|
||||
@ -466,8 +467,8 @@ static void emit_rewrite_diff(const char *name_a,
|
||||
const char *name_b,
|
||||
struct diff_filespec *one,
|
||||
struct diff_filespec *two,
|
||||
const char *textconv_one,
|
||||
const char *textconv_two,
|
||||
struct userdiff_driver *textconv_one,
|
||||
struct userdiff_driver *textconv_two,
|
||||
struct diff_options *o)
|
||||
{
|
||||
int lc_a, lc_b;
|
||||
@ -478,7 +479,7 @@ static void emit_rewrite_diff(const char *name_a,
|
||||
const char *reset = diff_get_color(color_diff, DIFF_RESET);
|
||||
static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;
|
||||
const char *a_prefix, *b_prefix;
|
||||
const char *data_one, *data_two;
|
||||
char *data_one, *data_two;
|
||||
size_t size_one, size_two;
|
||||
struct emit_callback ecbdata;
|
||||
|
||||
@ -500,26 +501,8 @@ static void emit_rewrite_diff(const char *name_a,
|
||||
quote_two_c_style(&a_name, a_prefix, name_a, 0);
|
||||
quote_two_c_style(&b_name, b_prefix, name_b, 0);
|
||||
|
||||
diff_populate_filespec(one, 0);
|
||||
diff_populate_filespec(two, 0);
|
||||
if (textconv_one) {
|
||||
data_one = run_textconv(textconv_one, one, &size_one);
|
||||
if (!data_one)
|
||||
die("unable to read files to diff");
|
||||
}
|
||||
else {
|
||||
data_one = one->data;
|
||||
size_one = one->size;
|
||||
}
|
||||
if (textconv_two) {
|
||||
data_two = run_textconv(textconv_two, two, &size_two);
|
||||
if (!data_two)
|
||||
die("unable to read files to diff");
|
||||
}
|
||||
else {
|
||||
data_two = two->data;
|
||||
size_two = two->size;
|
||||
}
|
||||
size_one = fill_textconv(textconv_one, one, &data_one);
|
||||
size_two = fill_textconv(textconv_two, two, &data_two);
|
||||
|
||||
memset(&ecbdata, 0, sizeof(ecbdata));
|
||||
ecbdata.color_diff = color_diff;
|
||||
@ -1585,14 +1568,26 @@ void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const
|
||||
options->b_prefix = b;
|
||||
}
|
||||
|
||||
static const char *get_textconv(struct diff_filespec *one)
|
||||
static struct userdiff_driver *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;
|
||||
if (!one->driver->textconv)
|
||||
return NULL;
|
||||
|
||||
if (one->driver->textconv_want_cache && !one->driver->textconv_cache) {
|
||||
struct notes_cache *c = xmalloc(sizeof(*c));
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
|
||||
strbuf_addf(&name, "textconv/%s", one->driver->name);
|
||||
notes_cache_init(c, name.buf, one->driver->textconv);
|
||||
one->driver->textconv_cache = c;
|
||||
}
|
||||
|
||||
return one->driver;
|
||||
}
|
||||
|
||||
static void builtin_diff(const char *name_a,
|
||||
@ -1609,7 +1604,8 @@ static void builtin_diff(const char *name_a,
|
||||
const char *set = diff_get_color_opt(o, DIFF_METAINFO);
|
||||
const char *reset = diff_get_color_opt(o, DIFF_RESET);
|
||||
const char *a_prefix, *b_prefix;
|
||||
const char *textconv_one = NULL, *textconv_two = NULL;
|
||||
struct userdiff_driver *textconv_one = NULL;
|
||||
struct userdiff_driver *textconv_two = NULL;
|
||||
struct strbuf header = STRBUF_INIT;
|
||||
|
||||
if (DIFF_OPT_TST(o, SUBMODULE_LOG) &&
|
||||
@ -1683,12 +1679,11 @@ static void builtin_diff(const char *name_a,
|
||||
}
|
||||
}
|
||||
|
||||
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
|
||||
die("unable to read files to diff");
|
||||
|
||||
if (!DIFF_OPT_TST(o, TEXT) &&
|
||||
( (diff_filespec_is_binary(one) && !textconv_one) ||
|
||||
(diff_filespec_is_binary(two) && !textconv_two) )) {
|
||||
( (!textconv_one && diff_filespec_is_binary(one)) ||
|
||||
(!textconv_two && diff_filespec_is_binary(two)) )) {
|
||||
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
|
||||
die("unable to read files to diff");
|
||||
/* Quite common confusing case */
|
||||
if (mf1.size == mf2.size &&
|
||||
!memcmp(mf1.ptr, mf2.ptr, mf1.size))
|
||||
@ -1715,20 +1710,8 @@ static void builtin_diff(const char *name_a,
|
||||
strbuf_reset(&header);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
mf1.size = fill_textconv(textconv_one, one, &mf1.ptr);
|
||||
mf2.size = fill_textconv(textconv_two, two, &mf2.ptr);
|
||||
|
||||
pe = diff_funcname_pattern(one);
|
||||
if (!pe)
|
||||
@ -3912,3 +3895,47 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
|
||||
|
||||
return strbuf_detach(&buf, outsize);
|
||||
}
|
||||
|
||||
static size_t fill_textconv(struct userdiff_driver *driver,
|
||||
struct diff_filespec *df,
|
||||
char **outbuf)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
if (!driver || !driver->textconv) {
|
||||
if (!DIFF_FILE_VALID(df)) {
|
||||
*outbuf = "";
|
||||
return 0;
|
||||
}
|
||||
if (diff_populate_filespec(df, 0))
|
||||
die("unable to read files to diff");
|
||||
*outbuf = df->data;
|
||||
return df->size;
|
||||
}
|
||||
|
||||
if (driver->textconv_cache) {
|
||||
*outbuf = notes_cache_get(driver->textconv_cache, df->sha1,
|
||||
&size);
|
||||
if (*outbuf)
|
||||
return size;
|
||||
}
|
||||
|
||||
*outbuf = run_textconv(driver->textconv, df, &size);
|
||||
if (!*outbuf)
|
||||
die("unable to read files to diff");
|
||||
|
||||
if (driver->textconv_cache) {
|
||||
/* ignore errors, as we might be in a readonly repository */
|
||||
notes_cache_put(driver->textconv_cache, df->sha1, *outbuf,
|
||||
size);
|
||||
/*
|
||||
* we could save up changes and flush them all at the end,
|
||||
* but we would need an extra call after all diffing is done.
|
||||
* Since generating a cache entry is the slow path anyway,
|
||||
* this extra overhead probably isn't a big deal.
|
||||
*/
|
||||
notes_cache_write(driver->textconv_cache);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user