Major refactor of package management API

Fixes issues where:

+ package!'s :disable property was ignored and def-package! wouldn't
  ignore disabled packages.
+ Certain quelpa packages were being removed/reinstalled infinitely
+ Improved flexibility of doom-get-packages (its docstring needs to be
  updated!)
This commit is contained in:
Henrik Lissner 2018-06-11 23:21:56 +02:00
parent 0be2be5c82
commit 72201fead5
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
2 changed files with 72 additions and 48 deletions

View file

@ -56,11 +56,11 @@ ready to be pasted in a bug report on github."
"n/a") "n/a")
(or (ignore-errors (or (ignore-errors
(require 'use-package) (require 'use-package)
(cl-loop for (pkg . plist) in (doom-get-packages :all t :private t :sort #'string-lessp) (cl-loop for (name . plist) in (doom-get-packages :private t)
if (use-package-plist-delete (copy-seq plist) :private) if (use-package-plist-delete (copy-seq plist) :private)
collect (format "%s" (cons pkg it)) collect (format "%s" (cons name it))
else else
collect (symbol-name pkg))) collect (symbol-name name)))
"n/a") "n/a")
;; abbreviate $HOME to hide username ;; abbreviate $HOME to hide username
(mapcar #'abbreviate-file-name exec-path)))) (mapcar #'abbreviate-file-name exec-path))))

View file

@ -3,7 +3,6 @@
(load! "cache") (load! "cache")
;;; Private functions ;;; Private functions
(defun doom--packages-choose (prompt) (defun doom--packages-choose (prompt)
(let ((table (cl-loop for pkg in package-alist (let ((table (cl-loop for pkg in package-alist
unless (package-built-in-p (cdr pkg)) unless (package-built-in-p (cdr pkg))
@ -57,14 +56,10 @@
"Get which backend the package NAME was installed with. Can either be elpa or "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." quelpa. Throws an error if NOERROR is nil and the package isn't installed."
(cl-check-type name symbol) (cl-check-type name symbol)
(cond ((assq name quelpa-cache) (cond ((assq name quelpa-cache) 'quelpa)
'quelpa) ((assq name package-alist) 'elpa)
((assq name package-alist) ((package-built-in-p name) 'emacs)
'elpa) ((not noerror) (error "%s package is not installed" name))))
((package-built-in-p name)
'emacs)
((not noerror)
(error "%s package is not installed" name))))
;;;###autoload ;;;###autoload
(defun doom-package-outdated-p (name) (defun doom-package-outdated-p (name)
@ -117,49 +112,80 @@ was installed with. Returns nil otherwise, or if package isn't installed."
"Return t if a package named NAME (a symbol) has a different recipe than it "Return t if a package named NAME (a symbol) has a different recipe than it
was installed with." was installed with."
(cl-check-type name symbol) (cl-check-type name symbol)
(when (package-installed-p name) (doom-initialize-packages)
(let ((quelpa-recipe (assq name quelpa-cache)) (and (package-installed-p name)
(when-let* ((quelpa-recipe (assq name quelpa-cache))
(doom-recipe (assq name doom-packages))) (doom-recipe (assq name doom-packages)))
(and quelpa-recipe doom-recipe
(not (equal (cdr quelpa-recipe) (not (equal (cdr quelpa-recipe)
(cdr (plist-get (cdr doom-recipe) :recipe)))))))) (cdr (plist-get (cdr doom-recipe) :recipe)))))))
;;;###autoload ;;;###autoload
(cl-defun doom-get-packages (&key installed backend private disabled all sort) (cl-defun doom-get-packages (&key (installed 'any)
(private 'any)
(disabled 'any)
(pinned 'any)
(ignored 'any)
(sort t)
changed
backend)
"Retrieves a list of primary packages (i.e. non-dependencies). Each element is "Retrieves a list of primary packages (i.e. non-dependencies). Each element is
a cons cell, whose car is the package symbol and whose cdr is the quelpa recipe a cons cell, whose car is the package symbol and whose cdr is the quelpa recipe
(if any). (if any).
BACKEND can be 'quelpa or 'elpa, and will instruct this function to return only You can build a filtering criteria using one or more of the following
the packages relevant to that backend. properties:
If INSTALLED is non-nil, only return installed packages. :backend BACKEND
Can be 'quelpa, 'elpa or 'emacs
:installed BOOL
Only return installed packages (t) or uninstalled packages (nil)
:private BOOL
Only return private packages (t) or non-private packages (nil)
:disabled BOOL
Only return packages that are disabled (t) or otherwise (nil)
:ignored BOOL
Only return packages that are ignored (t) or otherwise (nil)
:pinned BOOL|ARCHIVE
Only return packages that are pinned (t), not pinned (nil) or pinned to a
specific archive (stringp)
If PRIVATE, only return private packages. The resulting list is sorted unless :sort nil is passed to this function.
If DISABLED, only return disabled packages.
If ALL, include disabled packages.
Warning: this function is expensive, as it re-evaluates your all packages.el Warning: this function is expensive, as it re-evaluates your all packages.el
files." files."
(doom-initialize-packages (if (or installed backend) t 'internal)) (doom-initialize-packages)
(cl-loop with packages = (append (mapcar #'list doom-core-packages) (cl-loop with packages =
(cl-remove-duplicates (append (mapcar #'list doom-core-packages)
doom-packages) doom-packages)
:key #'car)
for (sym . plist) for (sym . plist)
in (if sort in (if sort
(cl-sort packages #'string-lessp :key #'car) (cl-sort (copy-sequence packages) #'string-lessp :key #'car)
packages) packages)
if (and (or all if (and (or (not backend)
(not (plist-get plist :disabled)))
(or (not disabled)
(plist-get plist :disabled))
(or (not installed)
(package-installed-p sym))
(or (not backend)
(eq (doom-package-backend sym t) backend)) (eq (doom-package-backend sym t) backend))
(or (not private) (or (eq ignored 'any)
(plist-get plist :private))) (if ignored
(plist-get plist :ignore)
(not (plist-get plist :ignore))))
(or (eq disabled 'any)
(if disabled
(plist-get plist :disable)
(not (plist-get plist :disable))))
(or (eq installed 'any)
(if installed
(package-installed-p sym)
(not (package-installed-p sym))))
(or (eq private 'any)
(if private
(plist-get plist :private)
(not (plist-get plist :private))))
(or (eq pinned 'any)
(cond ((eq pinned 't)
(plist-get plist :pin))
((null pinned)
(not (plist-get plist :pin)))
((equal (plist-get plist :pin) pinned)))))
collect (cons sym plist))) collect (cons sym plist)))
;;;###autoload ;;;###autoload
@ -238,7 +264,7 @@ depended on.
Used by `doom//packages-autoremove'." Used by `doom//packages-autoremove'."
(let ((package-selected-packages (let ((package-selected-packages
(mapcar #'car (doom-get-packages :installed t)))) (mapcar #'car (doom-get-packages :disabled nil))))
(append (package--removable-packages) (append (package--removable-packages)
(cl-loop for pkg in package-selected-packages (cl-loop for pkg in package-selected-packages
if (and (doom-package-different-backend-p pkg) if (and (doom-package-different-backend-p pkg)
@ -246,7 +272,7 @@ Used by `doom//packages-autoremove'."
collect pkg)))) collect pkg))))
;;;###autoload ;;;###autoload
(defun doom-get-missing-packages (&optional include-ignored-p) (cl-defun doom-get-missing-packages (&key (ignored 'any))
"Return a list of requested packages that aren't installed or built-in, but "Return a list of requested packages that aren't installed or built-in, but
are enabled (with a `package!' directive). Each element is a list whose CAR is are enabled (with a `package!' directive). Each element is a list whose CAR is
the package symbol, and whose CDR is a plist taken from that package's the package symbol, and whose CDR is a plist taken from that package's
@ -257,16 +283,14 @@ i.e. they have an :ignore property.
Used by `doom//packages-install'." Used by `doom//packages-install'."
(doom-initialize-packages) (doom-initialize-packages)
(cl-loop for desc in (doom-get-packages) (cl-loop for (name . plist)
for (name . plist) = desc in (doom-get-packages :ignored ignored :disabled nil)
if (and (or include-ignored-p if (and (or (plist-get plist :pin)
(not (plist-get plist :ignore)))
(or (plist-get plist :pin)
(not (assq name package--builtins))) (not (assq name package--builtins)))
(or (not (assq name package-alist)) (or (not (assq name package-alist))
(doom-package-different-backend-p name) (doom-package-different-backend-p name)
(doom-package-different-recipe-p name))) (doom-package-different-recipe-p name)))
collect desc)) collect (cons name plist)))
;; ;;