From: Junio C Hamano Date: Sun, 9 May 2010 05:33:08 +0000 (-0700) Subject: Merge branch 'jk/cached-textconv' X-Git-Tag: v1.7.2-rc0~159 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/dd75d07899653258587b854ce0e3f7f1b90610cf?hp=-c 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 --- dd75d07899653258587b854ce0e3f7f1b90610cf diff --combined Makefile index eb1d1623c2,24e92abe91..4f7224a59a --- a/Makefile +++ b/Makefile @@@ -34,7 -34,7 +34,7 @@@ all: # Define NO_D_INO_IN_DIRENT if you don't have d_ino in your struct dirent. # # Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks -# d_type in struct dirent (latest Cygwin -- will be fixed soonish). +# d_type in struct dirent (Cygwin 1.5, fixed in Cygwin 1.7). # # Define NO_C99_FORMAT if your formatted IO functions (printf/scanf et.al.) # do not support the 'size specifiers' introduced by C99, namely ll, hh, @@@ -109,7 -109,7 +109,7 @@@ # Define NO_PTHREADS if you do not have or do not want to use Pthreads. # # Define NO_PREAD if you have a problem with pread() system call (e.g. -# cygwin.dll before v1.5.22). +# cygwin1.dll before v1.5.22). # # Define NO_FAST_WORKING_DIRECTORY if accessing objects in pack files is # generally faster on your platform than accessing the working directory. @@@ -203,9 -203,6 +203,9 @@@ # Define JSMIN to point to JavaScript minifier that functions as # a filter to have gitweb.js minified. # +# Define CSSMIN to point to a CSS minifier in order to generate a minified +# version of gitweb.css +# # Define DEFAULT_PAGER to a sensible pager command (defaults to "less") if # you want to use something different. The value will be interpreted by the # shell at runtime when it is used. @@@ -282,6 -279,9 +282,6 @@@ lib = li # DESTDIR= pathsep = : -# JavaScript minifier invocation that can function as filter -JSMIN = - export prefix bindir sharedir sysconfdir CC = gcc @@@ -486,6 -486,7 +486,7 @@@ LIB_H += log-tree. LIB_H += mailmap.h LIB_H += merge-recursive.h LIB_H += notes.h + LIB_H += notes-cache.h LIB_H += object.h LIB_H += pack.h LIB_H += pack-refs.h @@@ -575,6 -576,7 +576,7 @@@ LIB_OBJS += merge-file. LIB_OBJS += merge-recursive.o LIB_OBJS += name-hash.o LIB_OBJS += notes.o + LIB_OBJS += notes-cache.o LIB_OBJS += object.o LIB_OBJS += pack-check.o LIB_OBJS += pack-refs.o @@@ -831,24 -833,22 +833,24 @@@ ifeq ($(uname_S),SunOS BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H endif ifeq ($(uname_O),Cygwin) - NO_D_TYPE_IN_DIRENT = YesPlease - NO_D_INO_IN_DIRENT = YesPlease - NO_STRCASESTR = YesPlease - NO_MEMMEM = YesPlease - NO_MKSTEMPS = YesPlease - NO_SYMLINK_HEAD = YesPlease + ifeq ($(shell expr "$(uname_R)" : '1\.[1-6]\.'),4) + NO_D_TYPE_IN_DIRENT = YesPlease + NO_D_INO_IN_DIRENT = YesPlease + NO_STRCASESTR = YesPlease + NO_MEMMEM = YesPlease + NO_MKSTEMPS = YesPlease + NO_SYMLINK_HEAD = YesPlease + NO_IPV6 = YesPlease + OLD_ICONV = UnfortunatelyYes + endif NEEDS_LIBICONV = YesPlease NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes NO_TRUSTABLE_FILEMODE = UnfortunatelyYes - OLD_ICONV = UnfortunatelyYes NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease # There are conflicting reports about this. # On some boxes NO_MMAP is needed, and not so elsewhere. # Try commenting this out if you suspect MMAP is more efficient NO_MMAP = YesPlease - NO_IPV6 = YesPlease X = .exe COMPAT_OBJS += compat/cygwin.o UNRELIABLE_FSTAT = UnfortunatelyYes @@@ -866,7 -866,6 +868,7 @@@ ifeq ($(uname_S),FreeBSD NO_UINTMAX_T = YesPlease NO_STRTOUMAX = YesPlease endif + PYTHON_PATH = /usr/local/bin/python endif ifeq ($(uname_S),OpenBSD) NO_STRCASESTR = YesPlease @@@ -922,6 -921,7 +924,6 @@@ ifeq ($(uname_S),IRIX SNPRINTF_RETURNS_BOGUS = YesPlease SHELL_PATH = /usr/gnu/bin/bash NEEDS_LIBGEN = YesPlease - NEEDS_LIBICONV = YesPlease endif ifeq ($(uname_S),IRIX64) NO_SETENV=YesPlease @@@ -940,6 -940,7 +942,6 @@@ SNPRINTF_RETURNS_BOGUS = YesPlease SHELL_PATH=/usr/gnu/bin/bash NEEDS_LIBGEN = YesPlease - NEEDS_LIBICONV = YesPlease endif ifeq ($(uname_S),HP-UX) NO_IPV6=YesPlease @@@ -1479,7 -1480,7 +1481,7 @@@ endi ifndef NO_PYTHON $(QUIET_SUBDIR0)git_remote_helpers $(QUIET_SUBDIR1) PYTHON_PATH='$(PYTHON_PATH_SQ)' prefix='$(prefix_SQ)' all endif - $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) + $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)' please_set_SHELL_PATH_to_a_more_modern_shell: @$$(:) @@@ -1561,29 -1562,18 +1563,29 @@@ gitweb $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) all ifdef JSMIN -OTHER_PROGRAMS += gitweb/gitweb.cgi gitweb/gitweb.min.js -gitweb/gitweb.cgi: gitweb/gitweb.perl gitweb/gitweb.min.js +GITWEB_PROGRAMS += gitweb/gitweb.min.js +GITWEB_JS = gitweb/gitweb.min.js else -OTHER_PROGRAMS += gitweb/gitweb.cgi -gitweb/gitweb.cgi: gitweb/gitweb.perl +GITWEB_JS = gitweb/gitweb.js endif +ifdef CSSMIN +GITWEB_PROGRAMS += gitweb/gitweb.min.css +GITWEB_CSS = gitweb/gitweb.min.css +else +GITWEB_CSS = gitweb/gitweb.css +endif +OTHER_PROGRAMS += gitweb/gitweb.cgi $(GITWEB_PROGRAMS) +gitweb/gitweb.cgi: gitweb/gitweb.perl $(GITWEB_PROGRAMS) $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@) ifdef JSMIN gitweb/gitweb.min.js: gitweb/gitweb.js $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@) endif # JSMIN +ifdef CSSMIN +gitweb/gitweb.min.css: gitweb/gitweb.css + $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@) +endif # CSSMIN git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css gitweb/gitweb.js @@@ -1593,13 -1583,11 +1595,13 @@@ -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ -e '/@@GITWEB_CGI@@/r gitweb/gitweb.cgi' \ -e '/@@GITWEB_CGI@@/d' \ - -e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \ + -e '/@@GITWEB_CSS@@/r $(GITWEB_CSS)' \ -e '/@@GITWEB_CSS@@/d' \ - -e '/@@GITWEB_JS@@/r gitweb/gitweb.js' \ + -e '/@@GITWEB_JS@@/r $(GITWEB_JS)' \ -e '/@@GITWEB_JS@@/d' \ -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \ + -e 's|@@GITWEB_CSS_NAME@@|$(GITWEB_CSS)|' \ + -e 's|@@GITWEB_JS_NAME@@|$(GITWEB_JS)|' \ $@.sh > $@+ && \ chmod +x $@+ && \ mv $@+ $@ @@@ -1625,8 -1613,9 +1627,8 @@@ $(patsubst %.py,%,$(SCRIPT_PYTHON)): % -e '}' \ -e 's|^import sys.*|&; \\\ import os; \\\ - sys.path[0] = os.environ.has_key("GITPYTHONLIB") and \\\ - os.environ["GITPYTHONLIB"] or \\\ - "@@INSTLIBDIR@@"|' \ + sys.path.insert(0, os.getenv("GITPYTHONLIB",\ + "@@INSTLIBDIR@@"));|' \ -e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \ $@.py >$@+ && \ chmod +x $@+ && \ @@@ -2098,7 -2087,7 +2100,7 @@@ clean $(RM) $(htmldocs).tar.gz $(manpages).tar.gz $(MAKE) -C Documentation/ clean ifndef NO_PERL - $(RM) gitweb/gitweb.cgi + $(MAKE) -C gitweb clean $(MAKE) -C perl clean endif ifndef NO_PYTHON diff --combined commit.h index 26ec8c0d1c,2b7fd89dfd..6ef88dcf45 --- a/commit.h +++ b/commit.h @@@ -74,16 -74,11 +74,16 @@@ struct pretty_print_contex struct reflog_walk_info *reflog_info; }; +struct userformat_want { + unsigned notes:1; +}; + extern int has_non_ascii(const char *text); struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */ extern char *reencode_commit_message(const struct commit *commit, const char **encoding_p); extern void get_commit_format(const char *arg, struct rev_info *); +extern void userformat_find_requirements(const char *fmt, struct userformat_want *w); extern void format_commit_message(const struct commit *commit, const char *format, struct strbuf *sb, const struct pretty_print_context *context); @@@ -163,4 -158,8 +163,8 @@@ static inline int single_parent(struct struct commit_list *reduce_heads(struct commit_list *heads); + extern int commit_tree(const char *msg, unsigned char *tree, + struct commit_list *parents, unsigned char *ret, + const char *author); + #endif /* COMMIT_H */ diff --combined diff.c index e40c1271da,4cb6d9a9e8..e49f14a924 --- a/diff.c +++ b/diff.c @@@ -14,7 -14,6 +14,7 @@@ #include "userdiff.h" #include "sigchain.h" #include "submodule.h" +#include "ll-merge.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@@ -44,7 -43,8 +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 -466,8 +467,8 @@@ static void emit_rewrite_diff(const cha 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 -478,7 +479,7 @@@ 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 -500,8 +501,8 @@@ 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; @@@ -552,9 -534,9 +535,9 @@@ if (lc_b) emit_rewrite_lines(&ecbdata, '+', data_two, size_two); if (textconv_one) - free(data_one); + free((char *)data_one); if (textconv_two) - free(data_two); + free((char *)data_two); } struct diff_words_buffer { @@@ -700,6 -682,7 +683,6 @@@ static void diff_words_show(struct diff { xpparam_t xpp; xdemitconf_t xecfg; - xdemitcb_t ecb; mmfile_t minus, plus; /* special case: only removal */ @@@ -721,7 -704,7 +704,7 @@@ /* as only the hunk header will be parsed, we need a 0-context */ xecfg.ctxlen = 0; xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words, - &xpp, &xecfg, &ecb); + &xpp, &xecfg); free(minus.ptr); free(plus.ptr); if (diff_words->current_plus != diff_words->plus.text.ptr + @@@ -952,7 -935,7 +935,7 @@@ struct diffstat_t unsigned is_unmerged:1; unsigned is_binary:1; unsigned is_renamed:1; - unsigned int added, deleted; + uintmax_t added, deleted; } **files; }; @@@ -1044,7 -1027,7 +1027,7 @@@ static void fill_print_name(struct diff static void show_stats(struct diffstat_t *data, struct diff_options *options) { int i, len, add, del, adds = 0, dels = 0; - int max_change = 0, max_len = 0; + uintmax_t max_change = 0, max_len = 0; int total_files = data->nr; int width, name_width; const char *reset, *set, *add_c, *del_c; @@@ -1073,7 -1056,7 +1056,7 @@@ for (i = 0; i < data->nr; i++) { struct diffstat_file *file = data->files[i]; - int change = file->added + file->deleted; + uintmax_t change = file->added + file->deleted; fill_print_name(file); len = strlen(file->print_name); if (max_len < len) @@@ -1101,8 -1084,8 +1084,8 @@@ for (i = 0; i < data->nr; i++) { const char *prefix = ""; char *name = data->files[i]->print_name; - int added = data->files[i]->added; - int deleted = data->files[i]->deleted; + uintmax_t added = data->files[i]->added; + uintmax_t deleted = data->files[i]->deleted; int name_len; /* @@@ -1123,11 -1106,9 +1106,11 @@@ if (data->files[i]->is_binary) { show_name(options->file, prefix, name, len); fprintf(options->file, " Bin "); - fprintf(options->file, "%s%d%s", del_c, deleted, reset); + fprintf(options->file, "%s%"PRIuMAX"%s", + del_c, deleted, reset); fprintf(options->file, " -> "); - fprintf(options->file, "%s%d%s", add_c, added, reset); + fprintf(options->file, "%s%"PRIuMAX"%s", + add_c, added, reset); fprintf(options->file, " bytes"); fprintf(options->file, "\n"); continue; @@@ -1156,7 -1137,7 +1139,7 @@@ del = scale_linear(del, width, max_change); } show_name(options->file, prefix, name, len); - fprintf(options->file, "%5d%s", added + deleted, + fprintf(options->file, "%5"PRIuMAX"%s", added + deleted, added + deleted ? " " : ""); show_graph(options->file, '+', add, add_c, reset); show_graph(options->file, '-', del, del_c, reset); @@@ -1206,8 -1187,7 +1189,8 @@@ static void show_numstat(struct diffsta fprintf(options->file, "-\t-\t"); else fprintf(options->file, - "%d\t%d\t", file->added, file->deleted); + "%"PRIuMAX"\t%"PRIuMAX"\t", + file->added, file->deleted); if (options->line_termination) { fill_print_name(file); if (!file->is_renamed) @@@ -1377,32 -1357,37 +1360,32 @@@ static void free_diffstat_info(struct d struct checkdiff_t { const char *filename; int lineno; + int conflict_marker_size; struct diff_options *o; unsigned ws_rule; unsigned status; }; -static int is_conflict_marker(const char *line, unsigned long len) +static int is_conflict_marker(const char *line, int marker_size, unsigned long len) { char firstchar; int cnt; - if (len < 8) + if (len < marker_size + 1) return 0; firstchar = line[0]; switch (firstchar) { - case '=': case '>': case '<': + case '=': case '>': case '<': case '|': break; default: return 0; } - for (cnt = 1; cnt < 7; cnt++) + for (cnt = 1; cnt < marker_size; cnt++) if (line[cnt] != firstchar) return 0; - /* line[0] thru line[6] are same as firstchar */ - if (firstchar == '=') { - /* divider between ours and theirs? */ - if (len != 8 || line[7] != '\n') - return 0; - } else if (len < 8 || !isspace(line[7])) { - /* not divider before ours nor after theirs */ + /* line[1] thru line[marker_size-1] are same as firstchar */ + if (len < marker_size + 1 || !isspace(line[marker_size])) return 0; - } return 1; } @@@ -1410,7 -1395,6 +1393,7 @@@ static void checkdiff_consume(void *pri { struct checkdiff_t *data = priv; int color_diff = DIFF_OPT_TST(data->o, COLOR_DIFF); + int marker_size = data->conflict_marker_size; const char *ws = diff_get_color(color_diff, DIFF_WHITESPACE); const char *reset = diff_get_color(color_diff, DIFF_RESET); const char *set = diff_get_color(color_diff, DIFF_FILE_NEW); @@@ -1419,7 -1403,7 +1402,7 @@@ if (line[0] == '+') { unsigned bad; data->lineno++; - if (is_conflict_marker(line + 1, len - 1)) { + if (is_conflict_marker(line + 1, marker_size, len - 1)) { data->status |= 1; fprintf(data->o->file, "%s:%d: leftover conflict marker\n", @@@ -1585,14 -1569,26 +1568,26 @@@ void diff_set_mnemonic_prefix(struct di 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 -1605,8 +1604,8 @@@ 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 -1680,11 +1679,11 @@@ } } - 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)) @@@ -1707,6 -1703,7 +1702,6 @@@ const char *diffopts = getenv("GIT_DIFF_OPTS"); xpparam_t xpp; xdemitconf_t xecfg; - xdemitcb_t ecb; struct emit_callback ecbdata; const struct userdiff_funcname *pe; @@@ -1715,20 -1712,8 +1710,8 @@@ 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) @@@ -1778,7 -1763,7 +1761,7 @@@ } } xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata, - &xpp, &xecfg, &ecb); + &xpp, &xecfg); if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) free_diff_words_data(&ecbdata); if (textconv_one) @@@ -1831,12 -1816,13 +1814,12 @@@ static void builtin_diffstat(const cha /* Crazy xdl interfaces.. */ xpparam_t xpp; xdemitconf_t xecfg; - xdemitcb_t ecb; memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat, - &xpp, &xecfg, &ecb); + &xpp, &xecfg); } free_and_return: @@@ -1861,7 -1847,6 +1844,7 @@@ static void builtin_checkdiff(const cha data.lineno = 0; data.o = o; data.ws_rule = whitespace_rule(attr_path); + data.conflict_marker_size = ll_merge_marker_size(attr_path); if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); @@@ -1878,13 -1863,14 +1861,13 @@@ /* Crazy xdl interfaces.. */ xpparam_t xpp; xdemitconf_t xecfg; - xdemitcb_t ecb; memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 1; /* at least one context line */ xpp.flags = XDF_NEED_MINIMAL; xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data, - &xpp, &xecfg, &ecb); + &xpp, &xecfg); if (data.ws_rule & WS_BLANK_AT_EOF) { struct emit_callback ecbdata; @@@ -3379,6 -3365,7 +3362,6 @@@ static int diff_get_patch_id(struct dif for (i = 0; i < q->nr; i++) { xpparam_t xpp; xdemitconf_t xecfg; - xdemitcb_t ecb; mmfile_t mf1, mf2; struct diff_filepair *p = q->queue[i]; int len1, len2; @@@ -3440,7 -3427,7 +3423,7 @@@ xecfg.ctxlen = 3; xecfg.flags = XDL_EMIT_FUNCNAMES; xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data, - &xpp, &xecfg, &ecb); + &xpp, &xecfg); } git_SHA1_Final(sha1, &ctx); @@@ -3912,3 -3899,47 +3895,47 @@@ static char *run_textconv(const char *p 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; + }