diff mbox series

Bug: diff --no-index with cachetextconv crashes

Message ID CACeVQwQ4MELjB8nZyeu9QDTtgwhhw0oOsL8BHdm_rxTj1vMy+A@mail.gmail.com (mailing list archive)
State New, archived
Headers show
Series Bug: diff --no-index with cachetextconv crashes | expand

Commit Message

Paweł Dominiak Feb. 26, 2024, 7:03 a.m. UTC
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]


[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

Comments

Jeff King Feb. 26, 2024, 7:22 a.m. UTC | #1
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
Paweł Dominiak Feb. 26, 2024, 7:56 a.m. UTC | #2
> 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
diff mbox series

Patch

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