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")
(or (ignore-errors
(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)
collect (format "%s" (cons pkg it))
collect (format "%s" (cons name it))
else
collect (symbol-name pkg)))
collect (symbol-name name)))
"n/a")
;; abbreviate $HOME to hide username
(mapcar #'abbreviate-file-name exec-path))))

View file

@ -3,7 +3,6 @@
(load! "cache")
;;; Private functions
(defun doom--packages-choose (prompt)
(let ((table (cl-loop for pkg in package-alist
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
quelpa. Throws an error if NOERROR is nil and the package isn't installed."
(cl-check-type name symbol)
(cond ((assq name quelpa-cache)
'quelpa)
((assq name package-alist)
'elpa)
((package-built-in-p name)
'emacs)
((not noerror)
(error "%s package is not installed" name))))
(cond ((assq name quelpa-cache) 'quelpa)
((assq name package-alist) 'elpa)
((package-built-in-p name) 'emacs)
((not noerror) (error "%s package is not installed" name))))
;;;###autoload
(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
was installed with."
(cl-check-type name symbol)
(when (package-installed-p name)
(let ((quelpa-recipe (assq name quelpa-cache))
(doom-recipe (assq name doom-packages)))
(and quelpa-recipe doom-recipe
(not (equal (cdr quelpa-recipe)
(cdr (plist-get (cdr doom-recipe) :recipe))))))))
(doom-initialize-packages)
(and (package-installed-p name)
(when-let* ((quelpa-recipe (assq name quelpa-cache))
(doom-recipe (assq name doom-packages)))
(not (equal (cdr quelpa-recipe)
(cdr (plist-get (cdr doom-recipe) :recipe)))))))
;;;###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
a cons cell, whose car is the package symbol and whose cdr is the quelpa recipe
(if any).
BACKEND can be 'quelpa or 'elpa, and will instruct this function to return only
the packages relevant to that backend.
You can build a filtering criteria using one or more of the following
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.
If DISABLED, only return disabled packages.
If ALL, include disabled packages.
The resulting list is sorted unless :sort nil is passed to this function.
Warning: this function is expensive, as it re-evaluates your all packages.el
files."
(doom-initialize-packages (if (or installed backend) t 'internal))
(cl-loop with packages = (append (mapcar #'list doom-core-packages)
doom-packages)
(doom-initialize-packages)
(cl-loop with packages =
(cl-remove-duplicates (append (mapcar #'list doom-core-packages)
doom-packages)
:key #'car)
for (sym . plist)
in (if sort
(cl-sort packages #'string-lessp :key #'car)
(cl-sort (copy-sequence packages) #'string-lessp :key #'car)
packages)
if (and (or all
(not (plist-get plist :disabled)))
(or (not disabled)
(plist-get plist :disabled))
(or (not installed)
(package-installed-p sym))
(or (not backend)
if (and (or (not backend)
(eq (doom-package-backend sym t) backend))
(or (not private)
(plist-get plist :private)))
(or (eq ignored 'any)
(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)))
;;;###autoload
@ -238,7 +264,7 @@ depended on.
Used by `doom//packages-autoremove'."
(let ((package-selected-packages
(mapcar #'car (doom-get-packages :installed t))))
(mapcar #'car (doom-get-packages :disabled nil))))
(append (package--removable-packages)
(cl-loop for pkg in package-selected-packages
if (and (doom-package-different-backend-p pkg)
@ -246,7 +272,7 @@ Used by `doom//packages-autoremove'."
collect pkg))))
;;;###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
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
@ -257,16 +283,14 @@ i.e. they have an :ignore property.
Used by `doom//packages-install'."
(doom-initialize-packages)
(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)
(cl-loop for (name . plist)
in (doom-get-packages :ignored ignored :disabled nil)
if (and (or (plist-get plist :pin)
(not (assq name package--builtins)))
(or (not (assq name package-alist))
(doom-package-different-backend-p name)
(doom-package-different-recipe-p name)))
collect desc))
collect (cons name plist)))
;;