git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Bug: diff --no-index with cachetextconv crashes
@ 2024-02-26  7:03 Paweł Dominiak
  2024-02-26  7:22 ` Jeff King
  0 siblings, 1 reply; 5+ messages in thread
From: Paweł Dominiak @ 2024-02-26  7:03 UTC (permalink / raw)
  To: git

Hey!

That's my first bug report for git and my first email to a mailing
list in general, I hope for understanding :)

[Steps to reproduce your issue]

Global .gitattributes:

*.txt diff=test

Global .gitconfig:

[diff "test"]
    textconv = cat
    cachetextconv = true

Called command:

git --no-pager diff --no-index foo.txt bar.txt

[Expected behavior]

diff --git a/foo.txt b/bar.txt
index f6a4b70..2b24d27 100644
--- a/foo.txt
+++ b/bar.txt
@@ -1 +1 @@
-Foo bar baz
+Foo bar qux

[Actual behavior]

BUG: refs.c:2095: attempting to get main_ref_store outside of repository

The command works as expected if cachetextconv is disabled:

git --no-pager -c diff.test.cachetextconv=false diff --no-index foo.txt bar.txt

[System Info]
git version 2.44.0.windows.1
cpu: x86_64
built from commit: ad0bbfffa543db6979717be96df630d3e5741331
sizeof-long: 4
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
uname: Windows 10.0 19045
compiler info: gnuc: 13.2
libc info: no libc information available
$SHELL (typically, interactive shell): C:\Program Files\Git\usr\bin\bash.exe

[Enabled Hooks]
not run from a git repository - no hooks to show

Pawel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: Bug: diff --no-index with cachetextconv crashes
  2024-02-26  7:03 Bug: diff --no-index with cachetextconv crashes Paweł Dominiak
@ 2024-02-26  7:22 ` Jeff King
  2024-02-26  7:56   ` Paweł Dominiak
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff King @ 2024-02-26  7:22 UTC (permalink / raw)
  To: Paweł Dominiak; +Cc: git

On Mon, Feb 26, 2024 at 08:03:04AM +0100, Paweł Dominiak wrote:

> That's my first bug report for git and my first email to a mailing
> list in general, I hope for understanding :)

Hi, welcome, and thanks for a clear bug report. :)

> [Steps to reproduce your issue]
> 
> Global .gitattributes:
> 
> *.txt diff=test
> 
> Global .gitconfig:
> 
> [diff "test"]
>     textconv = cat
>     cachetextconv = true
> 
> Called command:
> 
> git --no-pager diff --no-index foo.txt bar.txt

OK, I would say that this failing is semi-expected. :) The caching
system works using "git notes", which are stored in refs in the
repository. And since you are running "diff --no-index" outside of a
repository, there is nowhere to put them.

And so this BUG call makes sense:

> BUG: refs.c:2095: attempting to get main_ref_store outside of repository

We tried to load notes but there's no ref store at all, and the
low-level ref code caught this.

Of course any time we see a BUG something has gone wrong. What I think
_should_ happen is that we should quietly disable the caching (which,
after all, is just an optimization) and otherwise complete the command.

So we'd probably want something like this:

diff --git a/userdiff.c b/userdiff.c
index e399543823..fce3a31efa 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -3,6 +3,7 @@
 #include "userdiff.h"
 #include "attr.h"
 #include "strbuf.h"
+#include "environment.h"
 
 static struct userdiff_driver *drivers;
 static int ndrivers;
@@ -460,7 +461,8 @@ struct userdiff_driver *userdiff_get_textconv(struct repository *r,
 	if (!driver->textconv)
 		return NULL;
 
-	if (driver->textconv_want_cache && !driver->textconv_cache) {
+	if (driver->textconv_want_cache && !driver->textconv_cache &&
+	    have_git_dir()) {
 		struct notes_cache *c = xmalloc(sizeof(*c));
 		struct strbuf name = STRBUF_INIT;
 

-Peff

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: Bug: diff --no-index with cachetextconv crashes
  2024-02-26  7:22 ` Jeff King
@ 2024-02-26  7:56   ` Paweł Dominiak
  2024-02-26 10:27     ` [PATCH] userdiff: skip textconv caching when not in a repository Jeff King
  0 siblings, 1 reply; 5+ messages in thread
From: Paweł Dominiak @ 2024-02-26  7:56 UTC (permalink / raw)
  To: Jeff King; +Cc: git

> OK, I would say that this failing is semi-expected. :) The caching
> system works using "git notes", which are stored in refs in the
> repository. And since you are running "diff --no-index" outside of a
> repository, there is nowhere to put them.

I have not mentioned this specifically, but my goal is a general diff
command, which internally uses text conversions, pager etc. as
configured for git.
It makes sense to cache the textconv results when used in a
repository, but I don't think it should fail when not in one.
I think the default behavior should be to silently skip caching in
such situations but produce a diff otherwise.

> Of course any time we see a BUG something has gone wrong. What I think
> _should_ happen is that we should quietly disable the caching (which,
> after all, is just an optimization) and otherwise complete the command.

In my script I currently disable caching explicitly for all drivers:

keys=$(git config --name-only --get-regexp '^diff\.\w+\.cachetextconv$')
config=(); for key in $keys; do config+=(-c "$key=false"); done

git "${config[@]}" diff --no-index --no-prefix "$@"

But it seems like something git should handle on its own, so that diff
would accommodate use in different circumstances with the same config.

-Pawel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] userdiff: skip textconv caching when not in a repository
  2024-02-26  7:56   ` Paweł Dominiak
@ 2024-02-26 10:27     ` Jeff King
  2024-02-26 16:35       ` Junio C Hamano
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff King @ 2024-02-26 10:27 UTC (permalink / raw)
  To: Paweł Dominiak; +Cc: git

On Mon, Feb 26, 2024 at 08:56:09AM +0100, Paweł Dominiak wrote:

> But it seems like something git should handle on its own, so that diff
> would accommodate use in different circumstances with the same config.

Yes, definitely. Here's my patch with a commit message and a test.

-- >8 --
Subject: 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>
---
 t/t4042-diff-textconv-caching.sh | 22 ++++++++++++++++++++++
 userdiff.c                       |  4 +++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/t/t4042-diff-textconv-caching.sh b/t/t4042-diff-textconv-caching.sh
index bf33aedf4b..8ebfa3c1be 100755
--- a/t/t4042-diff-textconv-caching.sh
+++ b/t/t4042-diff-textconv-caching.sh
@@ -118,4 +118,26 @@ test_expect_success 'log notes cache and still use cache for -p' '
 	git log --no-walk -p refs/notes/textconv/magic HEAD
 '
 
+test_expect_success 'caching is silently ignored outside repo' '
+	mkdir -p non-repo &&
+	echo one >non-repo/one &&
+	echo two >non-repo/two &&
+	echo "* diff=test" >attr &&
+	test_expect_code 1 \
+	nongit git -c core.attributesFile="$PWD/attr" \
+		   -c diff.test.textconv="tr a-z A-Z <" \
+		   -c diff.test.cachetextconv=true \
+		   diff --no-index one two >actual &&
+	cat >expect <<-\EOF &&
+	diff --git a/one b/two
+	index 5626abf..f719efd 100644
+	--- a/one
+	+++ b/two
+	@@ -1 +1 @@
+	-ONE
+	+TWO
+	EOF
+	test_cmp expect actual
+'
+
 test_done
diff --git a/userdiff.c b/userdiff.c
index e399543823..fce3a31efa 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -3,6 +3,7 @@
 #include "userdiff.h"
 #include "attr.h"
 #include "strbuf.h"
+#include "environment.h"
 
 static struct userdiff_driver *drivers;
 static int ndrivers;
@@ -460,7 +461,8 @@ struct userdiff_driver *userdiff_get_textconv(struct repository *r,
 	if (!driver->textconv)
 		return NULL;
 
-	if (driver->textconv_want_cache && !driver->textconv_cache) {
+	if (driver->textconv_want_cache && !driver->textconv_cache &&
+	    have_git_dir()) {
 		struct notes_cache *c = xmalloc(sizeof(*c));
 		struct strbuf name = STRBUF_INIT;
 
-- 
2.44.0.rc2.424.gbdbf4d014b


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] userdiff: skip textconv caching when not in a repository
  2024-02-26 10:27     ` [PATCH] userdiff: skip textconv caching when not in a repository Jeff King
@ 2024-02-26 16:35       ` Junio C Hamano
  0 siblings, 0 replies; 5+ messages in thread
From: Junio C Hamano @ 2024-02-26 16:35 UTC (permalink / raw)
  To: Jeff King; +Cc: Paweł Dominiak, git

Jeff King <peff@peff.net> writes:

> Subject: 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.

Makes sense.

Will queue.  Thanks.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-02-26 16:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-26  7:03 Bug: diff --no-index with cachetextconv crashes Paweł Dominiak
2024-02-26  7:22 ` Jeff King
2024-02-26  7:56   ` Paweł Dominiak
2024-02-26 10:27     ` [PATCH] userdiff: skip textconv caching when not in a repository Jeff King
2024-02-26 16:35       ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).