2023-10-04 Mysterious empty Copyright files appearing

I finally broke the curse, I hope! A long time ago, I started complaining on fedi about the issue. Last week I was at it again.

I have a strange Emacs problem. At least I think it's Emacs. Some package in my entire setup insists on creating empty "Copyright" files every now and then. I suspect it's related to me editing a file that some code believes to be copyright relevant. I don't think it's related to version control because it recently happened in a directory full of Markdown files and Perl files. It also doesn't happen all the time. Maybe once a day? Or once every time I start Emacs? Does that ring a bell?

It was aggravating!

Whatever the software package is that litters my directories with empty Copyright files is driving me up the walls. I am so angry because I can't figure out what it is, and I can't just "bisect" my config because these files don't always show up. I just checked: `find . -name 'Copyright' | wc -l` returns 46 hits, right now. I searched all the lisp files I could find for "Copyright" but that's not it, or it's obfuscated. I guess I'll restart Emacs a few times and edit some source files and see whether that manages to trigger it.

After that post, I finally decided to spend some serious brain power on the problem instead of just complaining. And I managed to consistently trigger it: M-x grep makes the Copyright file appear!

I started looking at all the hooks but grep-mode-hook is empty, compilation-mode-hook is empty, delay-mode-hooks is empty, change-major-mode-after-body-hook is empty, … OK, time to give up on this.

Running `watch ls` in the directory and edebug on grep and it seems that the first call to grep-compute-defaults creates the cursed file! 🤯 Indeed, stepping through the code I find that it's this statement, which is supposed to check whether the grep command works:

(grep-probe
 grep-command
 `(nil t nil "^Copyright"
       ,(file-local-name hello-file))
 #'process-file-shell-command)

The mind boggles. My grep-command is set to `"grep --color -niH -e "`. Perhaps I should just upgrade Emacs and see whether the problem disappears.

That wasted more time and didn't solve the problem, of course.

I ended up reporting the following bug, slightly edited.

bug

I think the problem is that I use fish version 3.0.2 (current is 3.6.1) and I have grep-command set.

So, using fish, start Emacs -Q.

(getenv "SHELL") ;; "/usr/bin/fish"
(setq grep-command "grep --color -niH -e ")

Call M-x grep. You don’t have to actually use grep. Invoking grep calls grep-compute-defaults which – if grep-command is set – calls grep-probe which calls process-file-shell-command. The resulting command:

/usr/bin/fish -c "grep --color -niH -e ^Copyright \
/usr/local/share/emacs/30.0.50/etc/HELLO"

If I run this in the shell, it hangs. I terminate with C-d and notice that the empty file “Copyright” was created. If I quote the regular expression, no problem:

/usr/bin/fish -c "grep --color -niH -e '^Copyright' \
/usr/local/share/emacs/30.0.50/etc/HELLO"

(This correctly produces a line of output.)

This seems to be a feature of fish. The following command generates an empty file called “XXX”.

echo ^XXX

In the fish documentation I see the following regarding the caret, in a section about feature flags:

feature flags

`stderr-nocaret` was introduced in fish 3.0 (and made the default in
3.3). It makes `^` an ordinary character instead of denoting an stderr
redirection, to make dealing with quoting and such easier. Use `2>`
instead. This can no longer be turned off since fish 3.5. The flag can
still be tested for compatibility, but a `no-stderr-nocaret` value will
simply be ignored.

So this is the problem and it’s already improved in newer versions of fish.

In my case, however:

alex@melanobombus ~> status features
stderr-nocaret	off	3.0	^ no longer redirects stderr
qmark-noglob	off	3.0	? no longer globs

I have since changed the stderr-nocaret to “on” for my system (and as seen above, it is going to be mandatory going forward). This seems to do the job. No change to Emacs was required.

set -U fish_features stderr-nocaret

Future fish invocations should all have the feature set.

I’m not quite sure what to suggest, here. All I can say is that I was very angry about these empty Copyright files appearing every now and then all over my directories. I looked at hooks, I grepped the sources for "Copyright" (which didn’t match "^Copyright"), I looked at packages, I just couldn’t find it, and I also couldn’t reliably reproduce it, since it effectively only created an empty Copyright file the first time I called grep in an Emacs session.

Given the difficulty in finding the source of the problem, perhaps some sort of warning message or workaround is appropriate?

And now you know, too.

find . -name Copyright -size 0 -exec trash '{}' ';'

Be gone!

​#Emacs

The Emacs manual says:
‘SHELL’The name of an interpreter used to parse and execute programs run
from inside Emacs. This is used to initialize the variable
‘shell-file-name’.
So Emacs expects this variable to point to a shell that Emacs can use
to run programs, not your interactive shell. If you want a different
shell to be used in interactive shell sessions, such as "M-x shell",
then you should use the variable explicit-shell-file-name to point to
that other shell (in your case, fish).

I understand that this is what Emacs expects. It seems to me that other parts of a user’s system might go against this expectation, however. The man page for login(1) says this, for example:

Your user and group ID will be set according to their values in
the /etc/passwd file. The value for $HOME, $SHELL, $PATH,
$LOGNAME, and $MAIL are set according to the appropriate fields
in the password entry. Ulimit, umask and nice values may also be
set according to entries in the GECOS field.

That is to say, if a users runs chsh(1) and decides to use fish, then SHELL is set to fish, it is inherited to all processes, and Emacs breaks.

The Emacs manual also says the following in (elisp) Security Considerations, which is consistent with what Eli said above (and unfortunate for users like me):

Emacs has customization and other variables with similar
considerations. For example, if the variable ‘shell-file-name’
specifies a shell with nonstandard behavior, an Emacs-based
application may misbehave.

Too bad that there is not even a warning.

I guess Emacs will remain unchanged.