Fix packages with changed backend #222

Doom can't tell what backend a package was installed with, only whether it
is installed or not. This means if a package was installed with, say,
ELPA, then was changed to QUELPA, Doom wouldn't know.

Package management would fail. ELPA/QUELPA can't manage a package that
it didn't install.

This fix gives Doom that capability.
This commit is contained in:
Henrik Lissner 2017-11-05 16:04:31 +01:00
parent a6e0b3863d
commit 0c2b1b5a93
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395

View file

@ -27,21 +27,18 @@
(persistent-soft-store 'last-pkg-refresh nil "emacs"))
;;;###autoload
(defun doom-package-backend (name)
"Get which backend the package NAME was installed with. Can either be elpa,
quelpa or nil (if not installed)."
(defun doom-package-backend (name &optional noerror)
"Get which backend the package NAME was installed with. Can either be elpa or
quelpa. Throws an error if NOERROR is nil and the package isn't installed."
(cl-assert (symbolp name) t)
(doom-initialize-packages)
(cond ((let ((plist (cdr (assq name doom-packages))))
(and (not (plist-get plist :pin))
(or (quelpa-setup-p)
(error "Could not initialize quelpa"))
(or (assq name quelpa-cache)
(plist-get plist :recipe))))
(doom-initialize)
(cond ((and (or (quelpa-setup-p)
(error "Could not initialize quelpa"))
(assq name quelpa-cache))
'quelpa)
((assq name package-alist)
'elpa)
(t
((not noerror)
(error "%s package not installed" name))))
;;;###autoload
@ -79,6 +76,18 @@ list of the package."
(doom-initialize-packages)
(plist-get (cdr (assq name doom-packages)) prop))
;;;###autoload
(defun doom-package-different-backend-p (name)
"Return t if NAME (a package's symbol) has a new backend than what it was
installed with. Returns nil otherwise, or if package isn't installed."
(cl-assert (symbolp name) t)
(doom-initialize-packages)
(and (package-installed-p name)
(let* ((plist (cdr (assq name doom-packages)))
(old-backend (doom-package-backend name t))
(new-backend (if (plist-get plist :recipe) 'quelpa 'elpa)))
(not (eq old-backend new-backend)))))
;;;###autoload
(defun doom-get-packages (&optional installed-only-p)
"Retrieves a list of explicitly installed packages (i.e. non-dependencies).
@ -129,7 +138,8 @@ Used by `doom/packages-update'."
(let ((sym (car pkg)))
(when (and (or (not (doom-package-prop sym :freeze))
include-frozen-p)
(not (doom-package-prop sym :ignore)))
(not (doom-package-prop sym :ignore))
(not (doom-package-different-backend-p sym)))
(push sym
(if (eq (doom-package-backend sym) 'quelpa)
quelpa-pkgs
@ -158,7 +168,10 @@ Used by `doom/packages-autoremove'."
(doom-initialize-packages t)
(let ((package-selected-packages
(append (mapcar #'car doom-packages) doom-core-packages)))
(package--removable-packages)))
(append (package--removable-packages)
(cl-loop for pkg in package-selected-packages
if (doom-package-different-backend-p pkg)
collect pkg))))
;;;###autoload
(defun doom-get-missing-packages (&optional include-ignored-p)
@ -171,14 +184,15 @@ If INCLUDE-IGNORED-P is non-nil, includes missing packages that are ignored,
i.e. they have an :ignore property.
Used by `doom/packages-install'."
(cl-loop for pkgsym in (doom-get-packages)
unless
(let ((pkg (car pkgsym)))
(or (assq pkg package-alist)
(unless include-ignored-p (doom-package-prop pkg :ignore))
(and (not (plist-get (assq pkg doom-packages) :pin))
(assq pkg package--builtins))))
collect pkgsym))
(cl-loop for desc in (doom-get-packages)
for (name . plist) = desc
if (and (or include-ignored-p
(not (plist-get plist :ignore)))
(or (plist-get plist :pin)
(not (assq name package--builtins)))
(or (not (assq name package-alist))
(doom-package-different-backend-p name)))
collect desc))
;;;###autoload
(defun doom*package-delete (desc &rest _)
@ -238,6 +252,8 @@ Used by `doom/packages-install'."
example; the package name can be omitted)."
(doom-initialize-packages)
(when (package-installed-p name)
(when (doom-package-different-backend-p name)
(doom-delete-package name t))
(user-error "%s is already installed" name))
(let ((plist (or plist (cdr (assq name doom-packages))))
(inhibit-message (not doom-debug-mode))
@ -314,14 +330,20 @@ package.el as appropriate."
(y-or-n-p
(format "%s packages will be installed:\n\n%s\n\nProceed?"
(length packages)
(mapconcat (lambda (pkg)
(format "+ %s (%s)"
(car pkg)
(if (plist-get (cdr pkg) :recipe)
"QUELPA"
"ELPA")))
(sort (cl-copy-list packages) #'doom--sort-alpha)
"\n")))))
(mapconcat
(lambda (pkg)
(format "+ %s (%s)"
(car pkg)
(cond ((doom-package-different-backend-p (car pkg))
(if (plist-get (cdr pkg) :recipe)
"ELPA -> QUELPA"
"QUELPA -> ELPA"))
((plist-get (cdr pkg) :recipe)
"QUELPA")
(t
"ELPA"))))
(sort (cl-copy-list packages) #'doom--sort-alpha)
"\n")))))
(message! (yellow "Aborted!")))
(t
@ -396,12 +418,21 @@ package.el as appropriate."
(y-or-n-p
(format "%s packages will be deleted:\n\n%s\n\nProceed?"
(length packages)
(mapconcat (lambda (sym) (format "+ %s (%s)" sym
(pcase (doom-package-backend sym)
('quelpa "QUELPA")
('elpa "ELPA"))))
(sort (cl-copy-list packages) #'string-lessp)
"\n")))))
(mapconcat
(lambda (sym)
(format
"+ %s (%s)"
sym
(let ((backend (doom-package-backend sym)))
(if (doom-package-different-backend-p sym)
(if (eq backend 'quelpa)
"QUELPA->ELPA"
"ELPA->QUELPA")
(if (eq backend 'quelpa)
"QUELPA"
"ELPA")))))
(sort (cl-copy-list packages) #'string-lessp)
"\n")))))
(message! (yellow "Aborted!")))
(t
@ -417,6 +448,7 @@ package.el as appropriate."
(message! (bold (green "Finished!")))
(doom//reload-load-path)))))
;;;###autoload
(defalias 'doom/install-package #'package-install)