Subject: Re: bug#62099: 29.0.60; Intentional change to *Help* source code links?

From: Stephen Berman <[email-masked]>
Date: Sun, 14 May 2023 18:18:59 +0200

On Fri, 12 May 2023 08:51:22 +0300 Eli Zaretskii <[email-masked]> wrote:

>> From: Stephen Berman <[email-masked]>
>> Cc: [email-masked], Lars Ingebrigtsen <[email-masked]>
>> Date: Thu, 11 May 2023 23:14:37 +0200
>>
>> In fact, it's not necessary to have an existing directory under
>> ~/.emacs.d; I created ~/.emacs containing just the following line:
>>
>> (add-to-list 'load-path "~/.emacs.d/test")
>>
>> where there is no file (or directory) "test" under ~/.emacs.d, and with
>> this init file the *Help* links are shown starting with '/..' in
>> 43b0210f83c (and the current code base).  I note again that this only
>> happens with an out-of-tree build.  I haven't yet been able to determine
>> what part of the change in 43b0210f83c causes this issue.
>
> Well, if you could find out the offending code, it will be
> appreciated.

43b0210f83c only changed how loaddefs.el is generated, and for
out-of-tree builds, also how the names of the files under lisp are
represented in loaddefs.el.  Prior to the change, in out-of-tree builds
these file names appeared the same as those in in-tree builds, e.g.:

;;; Generated autoloads from play/5x5.el

But after 43b0210f83c, in my out-of-tree builds, they now look like
this:

;;; Generated autoloads from ../../../../../../home/steve/src/emacs/test-29/lisp/play/5x5.el

What I guess happens is that some code (but which?  I haven't found it)
truncates such file names to produce standard absolute file names, which
are then further truncated by help-fns-short-filename to produce the
links in *Help* buffers.  If this is right, then it works with -Q, but
when the init file adds a file or directory under ~/.emacs.d to
load-path, this somehow breaks the truncation, so
help-fns-short-filename fails to produce the desired link appearance.
But I have no idea how this breakage happens and why that initialization
triggers it.

I traced the problematic appearance of links in *Help* through the call
chain describe-function -> describe-function-1 ->
help-fns-function-description-header -> find-lisp-object-file-name ->
symbol-file, and symbol-file gets the file name from load-history.  In a
fresh Emacs, started with a triggering init file, load-history contains
only standard absolute file names, but when I type `C-h f' and then
evaluate load-history again, it now contains problematic files names
like "/../home/steve/src/emacs/test-29/lisp/help-fns.elc".  I set a
breakpoint in gdb on build_load_history, but when I hit it after typing
`C-h f' and started stepping through the function, the first opportunity
I had to evaluate its argument `filename' already showed the problematic
form.  Then I set a breakpoint on readevalloop, the caller of
build_load_history in lread.c, but again, the first opportunity I had to
evaluate readevalloop's argument `sourcename', which is passed to
build_load_history, already showed the problematic form.  I don't know
where else to look to try and find out how such forms get into
load-history.

If the reason for the aberrant file names in load-history can't be
found, or if avoiding them has more serious disadvantageous, I see two
alternatives: one is to do nothing, since this is apparently only a
cosmetic bug and there's an easy way to avoid triggering it, namely, by
not adding files under ~/.emacs.d to load-path, for which it suffices to
leave such files where they are and just symlink them to a location
outside of ~/.emacs.d and add that location to load-path; that's what
I've currently done in my init.  Or as a workaround fix in Emacs,
adjusting help-fns-short-filename as follows seems to do the trick, and
AFAICT has no unwanted side-effects:

diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 1966193d1a7..9204f45210c 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -954,7 +954,10 @@ help-fns--mention-shortdoc-groups
         (goto-char (point-max))))))

 (defun help-fns-short-filename (filename)
-  (let* ((abbrev (abbreviate-file-name filename))
+  (let* ((filename (if (string-match "^/\\.\\." filename)
+ 		       (substring filename 3)
+                     filename))
+         (abbrev (abbreviate-file-name filename))
          (short abbrev))
     (dolist (dir load-path)
       (let ((rel (file-relative-name filename dir)))

(This could, of course, also be used as advice in the init file, as
another alternative for individual users.)

Steve Berman