]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/autoload.el
Prevent bootstrap autoload backup files
[gnu-emacs] / lisp / emacs-lisp / autoload.el
index 9d1abdddb2bba4a6167eea940fd79b4ac812153c..592d69d2eb9c2432771ea9c72eb132fedc95e1ce 100644 (file)
@@ -1,6 +1,6 @@
 ;; autoload.el --- maintain autoloads in loaddefs.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1991-1997, 2001-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1991-1997, 2001-2016 Free Software Foundation, Inc.
 
 ;; Author: Roland McGrath <roland@gnu.org>
 ;; Keywords: maint
@@ -234,9 +234,22 @@ If a buffer is visiting the desired autoload file, return it."
        (enable-local-eval nil))
     ;; We used to use `raw-text' to read this file, but this causes
     ;; problems when the file contains non-ASCII characters.
-    (let ((delay-mode-hooks t))
-      (find-file-noselect
-       (autoload-ensure-default-file (autoload-generated-file))))))
+    (let* ((delay-mode-hooks t)
+           (file (autoload-generated-file))
+           (file-missing (not (file-exists-p file))))
+      (when file-missing
+        (autoload-ensure-default-file file))
+      (with-current-buffer
+          (find-file-noselect
+           (autoload-ensure-file-writeable
+            file))
+        ;; block backups when the file has just been created, since
+        ;; the backups will just be the auto-generated headers.
+        ;; bug#23203
+        (when file-missing
+          (setq buffer-backed-up t)
+          (save-buffer))
+        (current-buffer)))))
 
 (defun autoload-generated-file ()
   (expand-file-name generated-autoload-file
@@ -357,21 +370,22 @@ not be relied upon."
 ;;;###autoload
 (put 'autoload-ensure-writable 'risky-local-variable t)
 
+(defun autoload-ensure-file-writeable (file)
+  ;; Probably pointless, but replaces the old AUTOGEN_VCS in lisp/Makefile,
+  ;; which was designed to handle CVSREAD=1 and equivalent.
+  (and autoload-ensure-writable
+       (let ((modes (file-modes file)))
+         (if (zerop (logand modes #o0200))
+             ;; Ignore any errors here, and let subsequent attempts
+             ;; to write the file raise any real error.
+             (ignore-errors (set-file-modes file (logior modes #o0200))))))
+  file)
+
 (defun autoload-ensure-default-file (file)
   "Make sure that the autoload file FILE exists, creating it if needed.
 If the file already exists and `autoload-ensure-writable' is non-nil,
 make it writable."
-  (if (file-exists-p file)
-      ;; Probably pointless, but replaces the old AUTOGEN_VCS in lisp/Makefile,
-      ;; which was designed to handle CVSREAD=1 and equivalent.
-      (and autoload-ensure-writable
-          (let ((modes (file-modes file)))
-            (if (zerop (logand modes #o0200))
-                ;; Ignore any errors here, and let subsequent attempts
-                ;; to write the file raise any real error.
-                (ignore-errors (set-file-modes file (logior modes #o0200))))))
-    (write-region (autoload-rubric file) nil file))
-  file)
+  (write-region (autoload-rubric file) nil file))
 
 (defun autoload-insert-section-header (outbuf autoloads load-name file time)
   "Insert the section-header line,
@@ -524,117 +538,130 @@ different from OUTFILE, then OUTBUF is ignored.
 Return non-nil if and only if FILE adds no autoloads to OUTFILE
 \(or OUTBUF if OUTFILE is nil).  The actual return value is
 FILE's modification time."
-  (let (load-name
-       (print-length nil)
-       (print-level nil)
-       (print-readably t)           ; This does something in Lucid Emacs.
-       (float-output-format nil)
-       (visited (get-file-buffer file))
-       (otherbuf nil)
-       (absfile (expand-file-name file))
-       ;; nil until we found a cookie.
-       output-start)
-    (when
-       (catch 'done
-         (with-current-buffer (or visited
-                                  ;; It is faster to avoid visiting the file.
-                                  (autoload-find-file file))
-           ;; Obey the no-update-autoloads file local variable.
-           (unless no-update-autoloads
-             (or noninteractive (message "Generating autoloads for %s..." file))
-             (setq load-name
-                   (if (stringp generated-autoload-load-name)
-                       generated-autoload-load-name
-                     (autoload-file-load-name absfile)))
-             ;; 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
-                         (if (memq system-type '(ms-dos windows-nt))
-                             (equal (downcase outfile)
-                                    (downcase (autoload-generated-file)))
-                           (equal outfile (autoload-generated-file)))))
-               (setq otherbuf t))
-             (save-excursion
-               (save-restriction
-                 (widen)
-                 (when autoload-builtin-package-versions
-                   (let ((version (lm-header "version"))
-                         package)
-                     (and version
-                          (setq version (ignore-errors (version-to-list version)))
-                          (setq package (or (lm-header "package")
-                                            (file-name-sans-extension
-                                             (file-name-nondirectory file))))
-                          (setq output-start (autoload--setup-output
-                                              otherbuf outbuf absfile load-name))
-                          (let ((standard-output (marker-buffer output-start))
-                                (print-quoted t))
-                            (princ `(push (purecopy
-                                           ',(cons (intern package) version))
-                                          package--builtin-versions))
-                            (princ "\n")))))
-
-                 (goto-char (point-min))
-                 (while (not (eobp))
-                   (skip-chars-forward " \t\n\f")
-                   (cond
-                    ((looking-at (regexp-quote generate-autoload-cookie))
-                     ;; 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)))
-                     (autoload--print-cookie-text output-start load-name file))
-                    ((looking-at ";")
-                     ;; Don't read the comment.
-                     (forward-line 1))
-                    (t
-                     (forward-sexp 1)
-                     (forward-line 1))))))
-
-             (when output-start
-               (let ((secondary-autoloads-file-buf
-                      (if otherbuf (current-buffer))))
-                 (with-current-buffer (marker-buffer output-start)
-                   (save-excursion
-                     ;; Insert the section-header line which lists the file name
-                     ;; and which functions are in it, etc.
-                     (goto-char output-start)
-                     (let ((relfile (file-relative-name absfile)))
-                       (autoload-insert-section-header
-                        (marker-buffer output-start)
-                        () load-name relfile
-                        (if secondary-autoloads-file-buf
-                            ;; MD5 checksums are much better because they do not
-                            ;; change unless the file changes (so they'll be
-                            ;; equal on two different systems and will change
-                            ;; less often than time-stamps, thus leading to fewer
-                            ;; unneeded changes causing spurious conflicts), but
-                            ;; using time-stamps is a very useful optimization,
-                            ;; so we use time-stamps for the main autoloads file
-                            ;; (loaddefs.el) where we have special ways to
-                            ;; circumvent the "random change problem", and MD5
-                            ;; checksum in secondary autoload files where we do
-                            ;; not need the time-stamp optimization because it is
-                            ;; already provided by the primary autoloads file.
-                            (md5 secondary-autoloads-file-buf
-                                 ;; We'd really want to just use
-                                 ;; `emacs-internal' instead.
-                                 nil nil 'emacs-mule-unix)
-                          (nth 5 (file-attributes relfile))))
-                       (insert ";;; Generated autoloads from " relfile "\n")))
-                   (insert generate-autoload-section-trailer))))
-             (or noninteractive
-                 (message "Generating autoloads for %s...done" file)))
-           (or visited
-               ;; We created this buffer, so we should kill it.
-               (kill-buffer (current-buffer))))
-         (or (not output-start)
-             ;; If the entries were added to some other buffer, then the file
-             ;; doesn't add entries to OUTFILE.
-             otherbuf))
-      (nth 5 (file-attributes absfile)))))
+  ;; Include the file name in any error messages
+  (condition-case err
+      (let (load-name
+            (print-length nil)
+            (print-level nil)
+            (print-readably t)           ; This does something in Lucid Emacs.
+            (float-output-format nil)
+            (visited (get-file-buffer file))
+            (otherbuf nil)
+            (absfile (expand-file-name file))
+            ;; nil until we found a cookie.
+            output-start)
+        (when
+            (catch 'done
+              (with-current-buffer (or visited
+                                       ;; It is faster to avoid visiting the file.
+                                       (autoload-find-file file))
+                ;; Obey the no-update-autoloads file local variable.
+                (unless no-update-autoloads
+                  (or noninteractive (message "Generating autoloads for %s..." file))
+                  (setq load-name
+                        (if (stringp generated-autoload-load-name)
+                            generated-autoload-load-name
+                          (autoload-file-load-name absfile)))
+                  ;; 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
+                              (if (memq system-type '(ms-dos windows-nt))
+                                  (equal (downcase outfile)
+                                         (downcase (autoload-generated-file)))
+                                (equal outfile (autoload-generated-file)))))
+                    (setq otherbuf t))
+                  (save-excursion
+                    (save-restriction
+                      (widen)
+                      (when autoload-builtin-package-versions
+                        (let ((version (lm-header "version"))
+                              package)
+                          (and version
+                               (setq version (ignore-errors (version-to-list version)))
+                               (setq package (or (lm-header "package")
+                                                 (file-name-sans-extension
+                                                  (file-name-nondirectory file))))
+                               (setq output-start (autoload--setup-output
+                                                   otherbuf outbuf absfile load-name))
+                               (let ((standard-output (marker-buffer output-start))
+                                     (print-quoted t))
+                                 (princ `(push (purecopy
+                                                ',(cons (intern package) version))
+                                               package--builtin-versions))
+                                 (princ "\n")))))
+
+                      (goto-char (point-min))
+                      (while (not (eobp))
+                        (skip-chars-forward " \t\n\f")
+                        (cond
+                         ((looking-at (regexp-quote generate-autoload-cookie))
+                          ;; 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)))
+                          (autoload--print-cookie-text output-start load-name file))
+                         ((looking-at ";")
+                          ;; Don't read the comment.
+                          (forward-line 1))
+                         (t
+                          (forward-sexp 1)
+                          (forward-line 1))))))
+
+                  (when output-start
+                    (let ((secondary-autoloads-file-buf
+                           (if otherbuf (current-buffer))))
+                      (with-current-buffer (marker-buffer output-start)
+                        (save-excursion
+                          ;; Insert the section-header line which lists the file name
+                          ;; and which functions are in it, etc.
+                          (goto-char output-start)
+                          (let ((relfile (file-relative-name absfile)))
+                            (autoload-insert-section-header
+                             (marker-buffer output-start)
+                             () load-name relfile
+                             (if secondary-autoloads-file-buf
+                                 ;; MD5 checksums are much better because they do not
+                                 ;; change unless the file changes (so they'll be
+                                 ;; equal on two different systems and will change
+                                 ;; less often than time-stamps, thus leading to fewer
+                                 ;; unneeded changes causing spurious conflicts), but
+                                 ;; using time-stamps is a very useful optimization,
+                                 ;; so we use time-stamps for the main autoloads file
+                                 ;; (loaddefs.el) where we have special ways to
+                                 ;; circumvent the "random change problem", and MD5
+                                 ;; checksum in secondary autoload files where we do
+                                 ;; not need the time-stamp optimization because it is
+                                 ;; already provided by the primary autoloads file.
+                                 (md5 secondary-autoloads-file-buf
+                                      ;; We'd really want to just use
+                                      ;; `emacs-internal' instead.
+                                      nil nil 'emacs-mule-unix)
+                               (nth 5 (file-attributes relfile))))
+                            (insert ";;; Generated autoloads from " relfile "\n")))
+                        (insert generate-autoload-section-trailer))))
+                  (or noninteractive
+                      (message "Generating autoloads for %s...done" file)))
+                (or visited
+                    ;; We created this buffer, so we should kill it.
+                    (kill-buffer (current-buffer))))
+              (or (not output-start)
+                  ;; If the entries were added to some other buffer, then the file
+                  ;; doesn't add entries to OUTFILE.
+                  otherbuf))
+          (nth 5 (file-attributes absfile))))
+    (error
+     ;; Probably unbalanced parens in forward-sexp. In that case, the
+     ;; condition is scan-error, and the signal data includes point
+     ;; where the error was found; we'd like to convert that to
+     ;; line:col, but line-number-at-pos gets the wrong line in batch
+     ;; mode for some reason.
+     ;;
+     ;; At least this gets the file name in the error message; the
+     ;; developer can use goto-char to get to the error position.
+     (error "%s:0:0: error: %s: %s" file (car err) (cdr err)))
+    ))
 \f
 (defun autoload-save-buffers ()
   (while autoload-modified-buffers
@@ -669,8 +696,9 @@ Return FILE if there was no autoload cookie in it, else nil."
 (defun autoload-find-destination (file load-name)
   "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.
 Returns a buffer whose point is placed at the requested location.
-Returns nil if the file's autoloads are uptodate, otherwise
+Returns nil if the file's autoloads are up-to-date, otherwise
 removes any prior now out-of-date autoload entries."
   (catch 'up-to-date
     (let* ((buf (current-buffer))
@@ -703,7 +731,7 @@ removes any prior now out-of-date autoload entries."
                                ;; last-time is the time-stamp (specifying
                                ;; the last time we looked at the file) and
                                ;; the file hasn't been changed since.
-                               (and (listp last-time) (= (length last-time) 2)
+                               (and (listp last-time)
                                     (not (time-less-p last-time file-time)))
                                ;; last-time is an MD5 checksum instead.
                                (and (stringp last-time)