From 72201fead5a29023dc4359ccace3cb5db3ff1514 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 11 Jun 2018 23:21:56 +0200 Subject: [PATCH] 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!) --- core/autoload/debug.el | 6 +- core/autoload/packages.el | 114 +++++++++++++++++++++++--------------- 2 files changed, 72 insertions(+), 48 deletions(-) diff --git a/core/autoload/debug.el b/core/autoload/debug.el index 713554305..a352ffc66 100644 --- a/core/autoload/debug.el +++ b/core/autoload/debug.el @@ -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)))) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index c8856ab44..b8d5f8149 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -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))) ;;