Stop using a dynamically bound 'generated-autoload-file' variable

* doc/lispref/loading.texi (Autoload): Document change of name
(bug#39823).

* lisp/emacs-lisp/autoload.el (autoload-find-generated-file): Pass
the file name in.
(autoload-generated-file): Ditto.
(autoload-file-load-name): Ditto.
(generate-file-autoloads): Ditto.
(autoload--setup-output): Ditto.
(autoload-generate-file-autoloads): Ditto, and alter doc string to
reflect when `generated-autoload-file' is heeded.
(update-file-autoloads): Pass outfile in to functions.
(autoload-find-destination): Ditto.
(update-directory-autoloads): Make into an obsolete shim around
`make-directory-autoloads'.
(make-directory-autoloads): Renamed from
`update-directory-autoloads' with new semantics.
(batch-update-autoloads): Adjust caller.

* lisp/emacs-lisp/package.el (package-generate-autoloads): Adjust
caller.
This commit is contained in:
Lars Ingebrigtsen 2020-10-02 04:34:31 +02:00
parent fef7704feb
commit 6f36b67e41
5 changed files with 92 additions and 70 deletions

View file

@ -577,7 +577,7 @@ macro, then an error is signaled with data @code{"Autoloading failed to
define function @var{function-name}"}.
@findex update-file-autoloads
@findex update-directory-autoloads
@findex make-directory-autoloads
@cindex magic autoload comment
@cindex autoload cookie
@anchor{autoload cookie}
@ -590,7 +590,7 @@ writes a corresponding @code{autoload} call into @file{loaddefs.el}.
file generated by @code{update-file-autoloads} can be changed from the
above defaults, see below.)
Building Emacs loads @file{loaddefs.el} and thus calls @code{autoload}.
@kbd{M-x update-directory-autoloads} is even more powerful; it updates
@kbd{M-x make-directory-autoloads} is even more powerful; it updates
autoloads for all files in the current directory.
The same magic comment can copy any kind of form into

View file

@ -1469,6 +1469,13 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
* Lisp Changes in Emacs 28.1
+++
*** New command 'make-directory-autoloads'.
This does the same as the old command 'update-directory-autoloads',
but has different semantics: Instead of passing in the output file via
the dynamically bound 'generated-autoload-file' variable, the output
file is now a explicit parameter.
+++
*** New function 'string-search'.
This function takes two string parameters and returns the position of

View file

@ -254,13 +254,12 @@ expression, in which case we want to handle forms differently."
;; the doc-string in FORM.
;; Those properties are now set in lisp-mode.el.
(defun autoload-find-generated-file ()
(defun autoload-find-generated-file (file)
"Visit the autoload file for the current buffer, and return its buffer."
(let ((enable-local-variables :safe)
(enable-local-eval nil)
(find-file-hook nil)
(delay-mode-hooks t)
(file (autoload-generated-file)))
(delay-mode-hooks t))
;; We used to use `raw-text' to read this file, but this causes
;; problems when the file contains non-ASCII characters.
(with-current-buffer (find-file-noselect
@ -268,18 +267,20 @@ expression, in which case we want to handle forms differently."
(if (zerop (buffer-size)) (insert (autoload-rubric file nil t)))
(current-buffer))))
(defun autoload-generated-file ()
"Return `generated-autoload-file' as an absolute name.
If local to the current buffer, expand using the default directory;
otherwise, using `source-directory'/lisp."
(expand-file-name generated-autoload-file
(defun autoload-generated-file (outfile)
"Return OUTFILE as an absolute name.
If `generated-autoload-file' is bound locally in the current
buffer, that is used instead, and it is expanded using the
default directory; otherwise, `source-directory'/lisp is used."
(expand-file-name (if (local-variable-p 'generated-autoload-file)
generated-autoload-file
outfile)
;; File-local settings of generated-autoload-file should
;; be interpreted relative to the file's location,
;; of course.
(if (not (local-variable-p 'generated-autoload-file))
(expand-file-name "lisp" source-directory))))
(defun autoload-read-section-header ()
"Read a section header form.
Since continuation lines have been marked as comments,
@ -454,13 +455,12 @@ which lists the file name and which functions are in it, etc."
(defvar no-update-autoloads nil
"File local variable to prevent scanning this file for autoload cookies.")
(defun autoload-file-load-name (file)
(defun autoload-file-load-name (file outfile)
"Compute the name that will be used to load FILE."
;; OUTFILE should be the name of the global loaddefs.el file, which
;; is expected to be at the root directory of the files we're
;; scanning for autoloads and will be in the `load-path'.
(let* ((outfile (default-value 'generated-autoload-file))
(name (file-relative-name file (file-name-directory outfile)))
(let* ((name (file-relative-name file (file-name-directory outfile)))
(names '())
(dir (file-name-directory outfile)))
;; If `name' has directory components, only keep the
@ -490,8 +490,9 @@ If FILE is being visited in a buffer, the contents of the buffer
are used.
Return non-nil in the case where no autoloads were added at point."
(interactive "fGenerate autoloads for file: ")
(let ((generated-autoload-file buffer-file-name))
(autoload-generate-file-autoloads file (current-buffer))))
(let ((autoload-modified-buffers nil))
(autoload-generate-file-autoloads file (current-buffer) buffer-file-name)
autoload-modified-buffers))
(defvar autoload-compute-prefixes t
"If non-nil, autoload will add code to register the prefixes used in a file.
@ -608,7 +609,7 @@ Don't try to split prefixes that are already longer than that.")
`(register-definition-prefixes ,file ',(sort (delq nil strings)
'string<))))))
(defun autoload--setup-output (otherbuf outbuf absfile load-name)
(defun autoload--setup-output (otherbuf outbuf absfile load-name output-file)
(let ((outbuf
(or (if otherbuf
;; A file-local setting of
@ -616,7 +617,7 @@ Don't try to split prefixes that are already longer than that.")
;; should ignore OUTBUF.
nil
outbuf)
(autoload-find-destination absfile load-name)
(autoload-find-destination absfile load-name output-file)
;; The file has autoload cookies, but they're
;; already up-to-date. If OUTFILE is nil, the
;; entries are in the expected OUTBUF,
@ -673,23 +674,16 @@ Don't try to split prefixes that are already longer than that.")
More specifically those definitions will not be considered for the
`register-definition-prefixes' call.")
;; When called from `generate-file-autoloads' we should ignore
;; `generated-autoload-file' altogether. When called from
;; `update-file-autoloads' we don't know `outbuf'. And when called from
;; `update-directory-autoloads' it's in between: we know the default
;; `outbuf' but we should obey any file-local setting of
;; `generated-autoload-file'.
(defun autoload-generate-file-autoloads (file &optional outbuf outfile)
"Insert an autoload section for FILE in the appropriate buffer.
Autoloads are generated for defuns and defmacros in FILE
marked by `generate-autoload-cookie' (which see).
If FILE is being visited in a buffer, the contents of the buffer are used.
OUTBUF is the buffer in which the autoload statements should be inserted.
If OUTBUF is nil, it will be determined by `autoload-generated-file'.
If provided, OUTFILE is expected to be the file name of OUTBUF.
If OUTFILE is non-nil and FILE specifies a `generated-autoload-file'
different from OUTFILE, then OUTBUF is ignored.
If OUTBUF is nil, the output will go to OUTFILE, unless there's a
buffer-local setting of `generated-autoload-file' in FILE.
Return non-nil if and only if FILE adds no autoloads to OUTFILE
\(or OUTBUF if OUTFILE is nil). The actual return value is
@ -717,16 +711,19 @@ FILE's modification time."
(setq load-name
(if (stringp generated-autoload-load-name)
generated-autoload-load-name
(autoload-file-load-name absfile)))
(autoload-file-load-name absfile outfile)))
;; FIXME? Comparing file-names for equality with just equal
;; is fragile, eg if one has an automounter prefix and one
;; does not, but both refer to the same physical file.
(when (and outfile
(not outbuf)
(not
(if (memq system-type '(ms-dos windows-nt))
(equal (downcase outfile)
(downcase (autoload-generated-file)))
(equal outfile (autoload-generated-file)))))
(downcase (autoload-generated-file
outfile)))
(equal outfile (autoload-generated-file
outfile)))))
(setq otherbuf t))
(save-excursion
(save-restriction
@ -740,7 +737,8 @@ FILE's modification time."
(file-name-sans-extension
(file-name-nondirectory file))))
(setq output-start (autoload--setup-output
otherbuf outbuf absfile load-name))
otherbuf outbuf absfile
load-name outfile))
(let ((standard-output (marker-buffer output-start))
(print-quoted t))
(princ `(push (purecopy
@ -758,7 +756,8 @@ FILE's modification time."
;; If not done yet, figure out where to insert this text.
(unless output-start
(setq output-start (autoload--setup-output
otherbuf outbuf absfile load-name)))
otherbuf outbuf absfile
load-name outfile)))
(autoload--print-cookie-text output-start load-name file))
((= (following-char) ?\;)
;; Don't read the comment.
@ -789,7 +788,7 @@ FILE's modification time."
((not otherbuf)
(unless output-start
(setq output-start (autoload--setup-output
nil outbuf absfile load-name)))
nil outbuf absfile load-name outfile)))
(let ((autoload-print-form-outbuf
(marker-buffer output-start)))
(autoload-print-form form)))
@ -801,9 +800,8 @@ FILE's modification time."
;; then passing otherbuf=nil is enough, but if
;; outbuf is nil, that won't cut it, so we
;; locally bind generated-autoload-file.
(let ((generated-autoload-file
(default-value 'generated-autoload-file)))
(autoload--setup-output nil outbuf absfile load-name)))
(autoload--setup-output nil outbuf absfile load-name
outfile))
(autoload-print-form-outbuf
(marker-buffer other-output-start)))
(autoload-print-form form)
@ -925,19 +923,22 @@ Return FILE if there was no autoload cookie in it, else nil."
(interactive (list (read-file-name "Update autoloads for file: ")
current-prefix-arg
(read-file-name "Write autoload definitions to file: ")))
(let* ((generated-autoload-file (or outfile generated-autoload-file))
(autoload-modified-buffers nil)
(let* ((autoload-modified-buffers nil)
;; We need this only if the output file handles more than one input.
;; See https://debbugs.gnu.org/22213#38 and subsequent.
(autoload-timestamps t)
(no-autoloads (autoload-generate-file-autoloads file)))
(no-autoloads (autoload-generate-file-autoloads
file nil
(if (local-variable-p 'generated-autoload-file)
generated-autoload-file
outfile))))
(if autoload-modified-buffers
(if save-after (autoload-save-buffers))
(if (called-interactively-p 'interactive)
(message "Autoload section for %s is up to date." file)))
(if no-autoloads file)))
(defun autoload-find-destination (file load-name)
(defun autoload-find-destination (file load-name output-file)
"Find the destination point of the current buffer's autoloads.
FILE is the file name of the current buffer.
LOAD-NAME is the name as it appears in the output.
@ -947,12 +948,12 @@ removes any prior now out-of-date autoload entries."
(catch 'up-to-date
(let* ((buf (current-buffer))
(existing-buffer (if buffer-file-name buf))
(output-file (autoload-generated-file))
(output-file (autoload-generated-file output-file))
(output-time (if (file-exists-p output-file)
(file-attribute-modification-time
(file-attributes output-file))))
(found nil))
(with-current-buffer (autoload-find-generated-file)
(with-current-buffer (autoload-find-generated-file output-file)
;; This is to make generated-autoload-file have Unix EOLs, so
;; that it is portable to all platforms.
(or (eq 0 (coding-system-eol-type buffer-file-coding-system))
@ -1033,12 +1034,31 @@ The function does NOT recursively descend into subdirectories of the
directory or directories specified.
In an interactive call, prompt for a default output file for the
autoload definitions, and temporarily bind the variable
`generated-autoload-file' to this value. When called from Lisp,
use the existing value of `generated-autoload-file'. If any Lisp
file binds `generated-autoload-file' as a file-local variable,
write its autoloads into the specified file instead."
autoload definitions. When called from Lisp, use the existing
value of `generated-autoload-file'. If any Lisp file binds
`generated-autoload-file' as a file-local variable, write its
autoloads into the specified file instead."
(declare (obsolete make-directory-autoloads "28.1"))
(interactive "DUpdate autoloads from directory: ")
(make-directory-autoloads
dirs
(if (called-interactively-p 'interactive)
(read-file-name "Write autoload definitions to file: ")
generated-autoload-file)))
;;;###autoload
(defun make-directory-autoloads (dir output-file)
"Update autoload definitions for Lisp files in the directories DIRS.
DIR can be either a single directory or a list of
directories. (The latter usage is discouraged.)
The autoloads will be written to OUTPUT-FILE. If any Lisp file
binds `generated-autoload-file' as a file-local variable, write
its autoloads into the specified file instead.
The function does NOT recursively descend into subdirectories of the
directory or directories specified."
(interactive "DUpdate autoloads from directory: \nFWrite to file: ")
(let* ((files-re (let ((tmp nil))
(dolist (suf (get-load-suffixes))
;; We don't use module-file-suffix below because
@ -1049,10 +1069,10 @@ write its autoloads into the specified file instead."
(push suf tmp)))
(concat "\\`[^=.].*" (regexp-opt tmp t) "\\'")))
(files (apply #'nconc
(mapcar (lambda (dir)
(directory-files (expand-file-name dir)
t files-re))
dirs)))
(mapcar (lambda (d)
(directory-files (expand-file-name d)
t files-re))
(if (consp dir) dir (list dir)))))
(done ()) ;Files processed; to remove duplicates.
(changed nil) ;Non-nil if some change occurred.
(last-time)
@ -1060,16 +1080,12 @@ write its autoloads into the specified file instead."
;; files because of file-local autoload-generated-file settings.
(no-autoloads nil)
(autoload-modified-buffers nil)
(generated-autoload-file
(if (called-interactively-p 'interactive)
(read-file-name "Write autoload definitions to file: ")
generated-autoload-file))
(output-time
(if (file-exists-p generated-autoload-file)
(file-attribute-modification-time
(file-attributes generated-autoload-file)))))
(and (file-exists-p output-file)
(file-attribute-modification-time
(file-attributes output-file)))))
(with-current-buffer (autoload-find-generated-file)
(with-current-buffer (autoload-find-generated-file output-file)
(save-excursion
;; Canonicalize file names and remove the autoload file itself.
(setq files (delete (file-relative-name buffer-file-name)
@ -1126,8 +1142,7 @@ write its autoloads into the specified file instead."
(progress (make-progress-reporter
(byte-compile-info
(concat "Scraping files for "
(file-relative-name
generated-autoload-file)))
(file-relative-name output-file)))
0 (length files) nil 10))
(file-count 0)
file-time)
@ -1205,7 +1220,7 @@ should be non-nil)."
(let ((args command-line-args-left))
(batch-update-autoloads--summary args)
(setq command-line-args-left nil)
(apply #'update-directory-autoloads args)))
(make-directory-autoloads args generated-autoload-file)))
(provide 'autoload)

View file

@ -1013,7 +1013,6 @@ untar into a directory named DIR; otherwise, signal an error."
(write-region (autoload-rubric file "package" nil) nil file nil 'silent))
file)
(defvar generated-autoload-file)
(defvar autoload-timestamps)
(defvar version-control)
@ -1021,14 +1020,14 @@ untar into a directory named DIR; otherwise, signal an error."
"Generate autoloads in PKG-DIR for package named NAME."
(let* ((auto-name (format "%s-autoloads.el" name))
;;(ignore-name (concat name "-pkg.el"))
(generated-autoload-file (expand-file-name auto-name pkg-dir))
(output-file (expand-file-name auto-name pkg-dir))
;; We don't need 'em, and this makes the output reproducible.
(autoload-timestamps nil)
(backup-inhibited t)
(version-control 'never))
(package-autoload-ensure-default-file generated-autoload-file)
(update-directory-autoloads pkg-dir)
(let ((buf (find-buffer-visiting generated-autoload-file)))
(package-autoload-ensure-default-file output-file)
(make-directory-autoloads pkg-dir output-file)
(let ((buf (find-buffer-visiting output-file)))
(when buf (kill-buffer buf)))
auto-name))

View file

@ -131,7 +131,6 @@
(make-directory bzrdir)
(expand-file-name "foo.el" bzrdir)))
(default-directory (file-name-as-directory bzrdir))
(generated-autoload-file (expand-file-name "loaddefs.el" bzrdir))
(process-environment (cons (format "HOME=%s" homedir)
process-environment)))
(unwind-protect
@ -148,7 +147,9 @@
;; causes bzr status to fail. This simulates a broken bzr
;; installation.
(delete-file ".bzr/checkout/dirstate")
(should (progn (update-directory-autoloads default-directory)
(should (progn (make-directory-autoloads
default-directory
(expand-file-name "loaddefs.el" bzrdir))
t)))
(delete-directory homedir t))))