userdiff: skip textconv caching when not in a repository

The textconv caching system uses git-notes to store its cache entries. But if you're using "diff --no-index" outside of a repository, then obviously that isn't going to work. Since caching is just an optimization, it's OK for us to skip it. However, the current behavior is much worse: we call notes_cache_init() which tries to look up the ref, and the low-level ref code hits a BUG(), killing the program. Instead, we should notice before setting up the cache that it there's no repository, and just silently skip it. Reported-by: Paweł Dominiak <dominiak.pawel@gmail.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Feb 26, 2024 at 05:27 UTC affe355fe706d79ce6959277c39a7f1b1ec35f58
2 files changed +25 -1
t/t4042-diff-textconv-caching.sh
+22
@@ -118,4 +118,26 @@ test_expect_success 'log notes cache and still use cache for -p' '
118 git log --no-walk -p refs/notes/textconv/magic HEAD
119 '
120
121 +test_expect_success 'caching is silently ignored outside repo' '
122 + mkdir -p non-repo &&
123 + echo one >non-repo/one &&
124 + echo two >non-repo/two &&
125 + echo "* diff=test" >attr &&
126 + test_expect_code 1 \
127 + nongit git -c core.attributesFile="$PWD/attr" \
128 + -c diff.test.textconv="tr a-z A-Z <" \
129 + -c diff.test.cachetextconv=true \
130 + diff --no-index one two >actual &&
131 + cat >expect <<-\EOF &&
132 + diff --git a/one b/two
133 + index 5626abf..f719efd 100644
134 + --- a/one
135 + +++ b/two
136 + @@ -1 +1 @@
137 + -ONE
138 + +TWO
139 + EOF
140 + test_cmp expect actual
141 +'
142 +
143 test_done
userdiff.c
+3 -1
@@ -3,6 +3,7 @@
3 #include "userdiff.h"
4 #include "attr.h"
5 #include "strbuf.h"
6 +#include "environment.h"
7
8 static struct userdiff_driver *drivers;
9 static int ndrivers;
@@ -460,7 +461,8 @@ struct userdiff_driver *userdiff_get_textconv(struct repository *r,
461 if (!driver->textconv)
462 return NULL;
463
463 - if (driver->textconv_want_cache && !driver->textconv_cache) {
464 + if (driver->textconv_want_cache && !driver->textconv_cache &&
465 + have_git_dir()) {
466 struct notes_cache *c = xmalloc(sizeof(*c));
467 struct strbuf name = STRBUF_INIT;
468