diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 32200227de..1fa6ce4758 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -656,6 +656,8 @@ PKG-DESC is a `package-desc' object." (defvar Info-directory-list) (declare-function info-initialize "info" ()) +(defvar package--fastpath-pkgs t) + (defun package--load-files-for-activation (pkg-desc reload) "Load files for activating a package given by PKG-DESC. Load the autoloads file, and ensure `load-path' is setup. If @@ -696,16 +698,19 @@ correspond to previously loaded files (those returned by (unless (package-activate (car req)) (error "Unable to activate package `%s'.\nRequired package `%s-%s' is unavailable" name (car req) (package-version-join (cadr req)))))) - (package--load-files-for-activation pkg-desc reload) - ;; Add info node. - (when (file-exists-p (expand-file-name "dir" pkg-dir)) - ;; FIXME: not the friendliest, but simple. - (require 'info) - (info-initialize) - (push pkg-dir Info-directory-list)) - (push name package-activated-list) - ;; Don't return nil. - t)) + (if (listp package--fastpath-pkgs) + ;; We're only collecting the set of packages to activate! + (push pkg-desc package--fastpath-pkgs) + (package--load-files-for-activation pkg-desc reload) + ;; Add info node. + (when (file-exists-p (expand-file-name "dir" pkg-dir)) + ;; FIXME: not the friendliest, but simple. + (require 'info) + (info-initialize) + (push pkg-dir Info-directory-list)) + (push name package-activated-list) + ;; Don't return nil. + t))) (declare-function find-library-name "find-func" (library)) @@ -3437,6 +3442,51 @@ The list is displayed in a buffer named `*Packages*'." (interactive) (list-packages t)) +;;;; Fast-path for activation! + +(defcustom package-fastpath-file (locate-user-emacs-file "package-fastpath.el") + "Location of the file used to speed up activation of packages at startup." + :type 'file) + +(defun package-fastpath-refresh () + "(Re)Generate the `package-fastpath-file'." + (interactive) + (package-initialize 'no-activate) + (let ((package--fastpath-pkgs ()) + ;; Pretend we haven't activated anything yet! + (package-activated-list ())) + (dolist (elt package-alist) + (condition-case err + (package-activate (car elt)) + ;; Don't let failure of activation of a package arbitrarily stop + ;; activation of further packages. + (error (message "%s" (error-message-string err))))) + (with-temp-file package-fastpath-file + (insert ";;; FastPath file to speed up package activation at startup -*- lexical-binding:t -*-\n") + (insert ";; ¡¡ This file is autogenerated, DO NOT EDIT !!\n\n") + (dolist (pkg package--fastpath-pkgs) + (let* ((file (locate-library (package--autoloads-file-name pkg))) + (pfile (prin1-to-string file))) + (insert "(let ((load-file-name " pfile "))\n") + (insert-file-contents file) + (while (search-forward "#$" nil 'move) + (replace-match pfile t t)) + (unless (bolp) (insert "\n")) + (insert ")\n"))) + (pp `(setq package-activated-list + (append ',(mapcar #'package-desc-name package--fastpath-pkgs) + package-activated-list)) + (current-buffer)) + (insert " +;; Local Variables: +;; version-control: never +;; no-byte-compile: nil +;; no-update-autoloads: t +;; End: +")))) + + + (provide 'package) ;;; package.el ends here