Allow use of package.el #444
This makes package.el commands safe to use in Doom, and prevents errors caused by unitialized state, by running package-initialize before you use a package.el command.
This commit is contained in:
parent
10b7d2d178
commit
cdbd677423
2 changed files with 77 additions and 103 deletions
|
@ -6,11 +6,51 @@
|
|||
(require 'package)
|
||||
(require 'async)
|
||||
|
||||
;;; Private functions
|
||||
(defsubst doom--sort-alpha (it other)
|
||||
(string-lessp (symbol-name (car it))
|
||||
(symbol-name (car other))))
|
||||
|
||||
(defun doom--packages-choose (prompt)
|
||||
(let ((table (cl-loop for pkg in package-alist
|
||||
unless (package-built-in-p (cdr pkg))
|
||||
collect (cons (package-desc-full-name (cdr pkg))
|
||||
(cdr pkg)))))
|
||||
(cdr (assoc (completing-read prompt
|
||||
(mapcar #'car table)
|
||||
nil t)
|
||||
table))))
|
||||
|
||||
(defmacro doom--condition-case! (&rest body)
|
||||
`(condition-case-unless-debug ex
|
||||
(condition-case ex2
|
||||
(progn ,@body)
|
||||
('file-error
|
||||
(message! (bold (red " FILE ERROR: %s" (error-message-string ex2))))
|
||||
(message! " Trying again...")
|
||||
(quiet! (doom-refresh-packages-maybe t))
|
||||
,@body))
|
||||
('user-error
|
||||
(message! (bold (red " ERROR: %s" ex))))
|
||||
('error
|
||||
(doom--refresh-pkg-cache)
|
||||
(message! (bold (red " FATAL ERROR: %s" ex))))))
|
||||
|
||||
(defun doom--refresh-pkg-cache ()
|
||||
"Clear the cache for `doom-refresh-packages-maybe'."
|
||||
(setq doom--refreshed-p nil)
|
||||
(doom-cache-set 'last-pkg-refresh nil))
|
||||
|
||||
|
||||
;;
|
||||
;; Library
|
||||
;;
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-refresh-packages (&optional force-p)
|
||||
"Refresh ELPA packages."
|
||||
(defun doom-refresh-packages-maybe (&optional force-p)
|
||||
"Refresh ELPA packages, if it hasn't been refreshed recently."
|
||||
(when force-p
|
||||
(doom-refresh-clear-cache))
|
||||
(doom--refresh-pkg-cache))
|
||||
(unless (or (doom-cache-get 'last-pkg-refresh)
|
||||
doom--refreshed-p)
|
||||
(condition-case-unless-debug ex
|
||||
|
@ -19,16 +59,10 @@
|
|||
(package-refresh-contents)
|
||||
(doom-cache-set 'last-pkg-refresh t 900))
|
||||
('error
|
||||
(doom-refresh-clear-cache)
|
||||
(doom--refresh-pkg-cache)
|
||||
(message "Failed to refresh packages: (%s) %s"
|
||||
(car ex) (error-message-string ex))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-refresh-clear-cache ()
|
||||
"Clear the cache for `doom-refresh-packages'."
|
||||
(setq doom--refreshed-p nil)
|
||||
(doom-cache-set 'last-pkg-refresh nil))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-backend (name &optional noerror)
|
||||
"Get which backend the package NAME was installed with. Can either be elpa or
|
||||
|
@ -215,48 +249,6 @@ Used by `doom//packages-install'."
|
|||
(doom-package-different-recipe-p name)))
|
||||
collect desc))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom*package-delete (desc &rest _)
|
||||
"Update `quelpa-cache' upon a successful `package-delete'."
|
||||
(let ((name (package-desc-name desc)))
|
||||
(when (and (not (package-installed-p name))
|
||||
(assq name quelpa-cache))
|
||||
(map-delete quelpa-cache name)
|
||||
(quelpa-save-cache)
|
||||
(let ((path (expand-file-name (symbol-name name) quelpa-build-dir)))
|
||||
(when (file-exists-p path)
|
||||
(delete-directory path t))))))
|
||||
|
||||
;;; Private functions
|
||||
(defsubst doom--sort-alpha (it other)
|
||||
(string-lessp (symbol-name (car it))
|
||||
(symbol-name (car other))))
|
||||
|
||||
(defun doom--packages-choose (prompt)
|
||||
(let ((table (cl-loop for pkg in package-alist
|
||||
unless (package-built-in-p (cdr pkg))
|
||||
collect (cons (package-desc-full-name (cdr pkg))
|
||||
(cdr pkg)))))
|
||||
(cdr (assoc (completing-read prompt
|
||||
(mapcar #'car table)
|
||||
nil t)
|
||||
table))))
|
||||
|
||||
(defmacro doom--condition-case! (&rest body)
|
||||
`(condition-case-unless-debug ex
|
||||
(condition-case ex2
|
||||
(progn ,@body)
|
||||
('file-error
|
||||
(message! (bold (red " FILE ERROR: %s" (error-message-string ex2))))
|
||||
(message! " Trying again...")
|
||||
(quiet! (doom-refresh-packages t))
|
||||
,@body))
|
||||
('user-error
|
||||
(message! (bold (red " ERROR: %s" ex))))
|
||||
('error
|
||||
(doom-refresh-clear-cache)
|
||||
(message! (bold (red " FATAL ERROR: %s" ex))))))
|
||||
|
||||
|
||||
;;
|
||||
;; Main functions
|
||||
|
@ -369,7 +361,7 @@ package.el as appropriate."
|
|||
(message! (yellow "Aborted!")))
|
||||
|
||||
(t
|
||||
(doom-refresh-packages doom-debug-mode)
|
||||
(doom-refresh-packages-maybe doom-debug-mode)
|
||||
(dolist (pkg packages)
|
||||
(message! "Installing %s" (car pkg))
|
||||
(doom--condition-case!
|
||||
|
@ -394,7 +386,7 @@ package.el as appropriate."
|
|||
"Interactive command for updating packages."
|
||||
(interactive)
|
||||
(message! "Looking for outdated packages...")
|
||||
(doom-refresh-packages doom-debug-mode)
|
||||
(doom-refresh-packages-maybe doom-debug-mode)
|
||||
(let ((packages (sort (doom-get-outdated-packages) #'doom--sort-alpha)))
|
||||
(cond ((not packages)
|
||||
(message! (green "Everything is up-to-date")))
|
||||
|
@ -475,38 +467,6 @@ package.el as appropriate."
|
|||
;; Interactive commands
|
||||
;;
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'doom/install-package #'package-install)
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/reinstall-package (desc)
|
||||
"Reinstalls package package with optional quelpa RECIPE (see `quelpa-recipe' for
|
||||
an example; the package package can be omitted)."
|
||||
(declare (interactive-only t))
|
||||
(interactive
|
||||
(list (doom--packages-choose "Reinstall package: ")))
|
||||
(let ((package (package-desc-name desc)))
|
||||
(doom-delete-package package t)
|
||||
(doom-install-package package (cdr (assq package doom-packages)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/delete-package (desc)
|
||||
"Prompts the user with a list of packages and deletes the selected package.
|
||||
Use this interactively. Use `doom-delete-package' for direct calls."
|
||||
(declare (interactive-only t))
|
||||
(interactive
|
||||
(list (doom--packages-choose "Delete package: ")))
|
||||
(let ((package (package-desc-name desc)))
|
||||
(if (package-installed-p package)
|
||||
(if (y-or-n-p (format "%s will be deleted. Confirm?" package))
|
||||
(message "%s %s"
|
||||
(if (doom-delete-package package t)
|
||||
"Deleted"
|
||||
"Failed to delete")
|
||||
package)
|
||||
(message "Aborted"))
|
||||
(message "%s isn't installed" package))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/update-package (pkg)
|
||||
"Prompts the user with a list of outdated packages and updates the selected
|
||||
|
@ -521,6 +481,7 @@ calls."
|
|||
nil t)
|
||||
(user-error "All packages are up to date"))))
|
||||
(list (cdr (assq (car (assoc package package-alist)) packages)))))
|
||||
(doom-initialize-packages)
|
||||
(cl-destructuring-bind (package old-version new-version) pkg
|
||||
(if-let* ((desc (doom-package-outdated-p package)))
|
||||
(let ((old-v-str (package-version-join old-version))
|
||||
|
@ -533,10 +494,25 @@ calls."
|
|||
(message "Aborted")))
|
||||
(message "%s is up-to-date" package))))
|
||||
|
||||
|
||||
;;
|
||||
;; Advice
|
||||
;;
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/refresh-packages (&optional force-p)
|
||||
"Synchronize package metadata with the sources in `package-archives'. If
|
||||
FORCE-P (the universal argument) is set, ignore the cache."
|
||||
(declare (interactive-only t))
|
||||
(interactive "P")
|
||||
(doom-refresh-packages force-p))
|
||||
(defun doom*package-delete (desc &rest _)
|
||||
"Update `quelpa-cache' upon a successful `package-delete'."
|
||||
(let ((name (package-desc-name desc)))
|
||||
(when (and (not (package-installed-p name))
|
||||
(assq name quelpa-cache))
|
||||
(map-delete quelpa-cache name)
|
||||
(quelpa-save-cache)
|
||||
(let ((path (expand-file-name (symbol-name name) quelpa-build-dir)))
|
||||
(when (file-exists-p path)
|
||||
(delete-directory path t))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom*initialize-packages (&rest _)
|
||||
"TODO"
|
||||
(unless doom-init-p
|
||||
(doom-initialize-packages)))
|
||||
|
|
|
@ -35,15 +35,7 @@
|
|||
;; just Emacs. Arguably, my config is still over-complicated, but shhh, it's
|
||||
;; fine. Everything is fine.
|
||||
;;
|
||||
;; You should be able to use package.el commands without any conflicts, but to
|
||||
;; be absolutely certain use the doom alternatives:
|
||||
;;
|
||||
;; + `package-install': `doom/install-package'
|
||||
;; + `package-reinstall': `doom/reinstall-package'
|
||||
;; + `package-delete': `doom/delete-package'
|
||||
;; + `package-update': `doom/update-package'
|
||||
;; + `package-autoremove': `doom//packages-autoremove'
|
||||
;; + `package-refresh-contents': `doom/refresh-packages'
|
||||
;; You should be able to use package.el commands without any conflicts.
|
||||
;;
|
||||
;; See core/autoload/packages.el for more functions.
|
||||
|
||||
|
@ -852,14 +844,20 @@ compiled packages.'"
|
|||
|
||||
|
||||
;;
|
||||
;; Package.el modifications
|
||||
;; Make package.el cooperate with Doom
|
||||
;;
|
||||
|
||||
(advice-add #'package-install :before #'doom*initialize-packages)
|
||||
(advice-add #'package-reinstall :before #'doom*initialize-packages)
|
||||
(advice-add #'package-delete :before #'doom*initialize-packages)
|
||||
(advice-add #'package-refresh-contents :before #'doom*initialize-packages)
|
||||
|
||||
;; Updates QUELPA after deleting a package
|
||||
(advice-add #'package-delete :after #'doom*package-delete)
|
||||
|
||||
;; It isn't safe to use `package-autoremove', so get rid of it
|
||||
;; Replace with Doom variants
|
||||
(advice-add #'package-autoremove :override #'doom//packages-autoremove)
|
||||
(advice-add #'package-install-selected-packages :override #'doom//packages-install)
|
||||
|
||||
(provide 'core-packages)
|
||||
;;; core-packages.el ends here
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue