Refactor doom-initialize-packages & package API

- Packages are initialized once, when package.el is first loaded, and
  must be updated manually via doom/reload-packages.
- Package->module association is now stored in the package's PLIST under
  :modules. This is an internal property and cannot be explicitly set
  through `package!'
- Add doom-package-list function
- Rename doom-get-packages to doom-find-packages
- Updated doom-find-packages' docstring
- Added the :core filter to doom-find-packages
- Simplified doom-initialize-packages
- doom/reload calls doom/reload-packages if necessary.
- Fix redundant properties in doom-packages
- Remove tracking of after!, def-package! and def-package-hook! blocks.
  Replaced with doom-package-list being able to see all packages, even
  in disabled modules.
- Add :built-in property to package! for dummy packages. This is
  important so that doom/describe-package can see built-in packages.
This commit is contained in:
Henrik Lissner 2019-03-06 00:26:33 -05:00
parent 8bfa5a30fd
commit a443d9ab07
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
8 changed files with 207 additions and 182 deletions

View file

@ -32,5 +32,7 @@ init.el and config.el. Then runs `doom-reload-hook'."
(doom-initialize)) (doom-initialize))
(with-demoted-errors "PRIVATE CONFIG ERROR: %s" (with-demoted-errors "PRIVATE CONFIG ERROR: %s"
(doom-initialize-modules 'force)) (doom-initialize-modules 'force))
(when (bound-and-true-p doom-packages)
(doom/reload-packages))
(run-hook-wrapped 'doom-reload-hook #'doom-try-run-hook) (run-hook-wrapped 'doom-reload-hook #'doom-try-run-hook)
(message "Finished!")) (message "Finished!"))

View file

@ -61,7 +61,7 @@ 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 (name . plist) in (doom-get-packages :private t) (cl-loop for (name . plist) in (doom-find-packages :private t)
if (use-package-plist-delete (copy-sequence plist) :private) if (use-package-plist-delete (copy-sequence plist) :private)
collect (format "%s" (cons name it)) collect (format "%s" (cons name it))
else else

View file

@ -97,7 +97,6 @@ list of the package."
"Return t if a package named NAME (a symbol) has a new backend than what it "Return t if a package named NAME (a symbol) has a new backend than what it
was installed with. Returns nil otherwise, or if package isn't installed." was installed with. Returns nil otherwise, or if package isn't installed."
(cl-check-type name symbol) (cl-check-type name symbol)
(doom-initialize-packages)
(and (package-installed-p name) (and (package-installed-p name)
(let* ((plist (cdr (assq name doom-packages))) (let* ((plist (cdr (assq name doom-packages)))
(old-backend (doom-package-backend name 'noerror)) (old-backend (doom-package-backend name 'noerror))
@ -109,7 +108,6 @@ 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)
(doom-initialize-packages)
(and (package-installed-p name) (and (package-installed-p name)
(when-let* ((quelpa-recipe (assq name quelpa-cache)) (when-let* ((quelpa-recipe (assq name quelpa-cache))
(doom-recipe (assq name doom-packages))) (doom-recipe (assq name doom-packages)))
@ -117,15 +115,16 @@ was installed with."
(cdr (plist-get (cdr doom-recipe) :recipe))))))) (cdr (plist-get (cdr doom-recipe) :recipe)))))))
;;;###autoload ;;;###autoload
(cl-defun doom-get-packages (&key (installed 'any) (cl-defun doom-find-packages (&key (installed 'any)
(private 'any) (private 'any)
(disabled 'any) (disabled 'any)
(pinned 'any) (pinned 'any)
(ignored 'any) (ignored 'any)
(sort t) (core 'any)
changed sort
backend changed
deps) backend
deps)
"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).
@ -133,76 +132,134 @@ a cons cell, whose car is the package symbol and whose cdr is the quelpa recipe
You can build a filtering criteria using one or more of the following You can build a filtering criteria using one or more of the following
properties: properties:
:backend BACKEND :backend 'quelpa|'elpa|'emacs|'any
Can be 'quelpa, 'elpa or 'emacs Include packages installed through 'quelpa, 'elpa or 'emacs. 'any is the
:installed BOOL wildcard.
Only return installed packages (t) or uninstalled packages (nil) :installed BOOL|'any
:private BOOL t = only include installed packages
Only return private packages (t) or non-private packages (nil) nil = exclude installed packages
:disabled BOOL :private BOOL|'any
Only return packages that are disabled (t) or otherwise (nil) t = only include user-installed packages
:ignored BOOL nil = exclude user-installed packages
Only return packages that are ignored (t) or otherwise (nil) :core BOOL|'any
t = only include Doom core packages
nil = exclude Doom core packages
:disabled BOOL|'any
t = only include disabled packages
nil = exclude disabled packages
:ignored BOOL|'any
t = only include ignored packages
nil = exclude ignored packages
:pinned BOOL|ARCHIVE :pinned BOOL|ARCHIVE
Only return packages that are pinned (t), not pinned (nil) or pinned to a Only return packages that are pinned (t), not pinned (nil) or pinned to a
specific archive (stringp) specific archive (stringp)
:deps BOOL :deps BOOL
Includes the package's dependencies (t). Includes the package's dependencies (t) or not (nil).
The resulting list is sorted unless :sort nil is passed to this function. 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 Warning: this function is expensive, as it re-evaluates your all packages.el
files." files."
(doom-initialize-packages) (cl-loop with packages = doom-packages
(cl-remove-duplicates for (sym . plist)
(cl-loop with packages = (append (mapcar #'list doom-core-packages) in (if sort
doom-packages) (cl-sort (copy-sequence doom-packages) #'string-lessp :key #'car)
for (sym . plist) packages)
in (if sort if (and (or (not backend)
(cl-sort (copy-sequence packages) #'string-lessp :key #'car) (eq (doom-package-backend sym t) backend))
packages) (or (eq ignored 'any)
if (and (or (not backend) (let* ((form (plist-get plist :ignore))
(eq (doom-package-backend sym t) backend)) (value (eval form)))
(or (eq ignored 'any) (if ignored value (not value))))
(let* ((form (plist-get plist :ignore)) (or (eq disabled 'any)
(value (eval form))) (if disabled
(if ignored value (not value)))) (plist-get plist :disable)
(or (eq disabled 'any) (not (plist-get plist :disable))))
(if disabled (or (eq installed 'any)
(plist-get plist :disable) (if installed
(not (plist-get plist :disable)))) (doom-package-installed-p sym)
(or (eq installed 'any) (not (doom-package-installed-p sym))))
(if installed (or (eq private 'any)
(doom-package-installed-p sym) (let ((modules (plist-get plist :modules)))
(not (doom-package-installed-p sym)))) (if private
(or (eq private 'any) (assq :private modules)
(if private (not (assq :private modules)))))
(plist-get plist :private) (or (eq core 'any)
(not (plist-get plist :private)))) (let ((modules (plist-get plist :modules)))
(or (eq pinned 'any) (if core
(cond ((eq pinned 't) (assq :core modules)
(plist-get plist :pin)) (not (assq :core modules)))))
((null pinned) (or (eq pinned 'any)
(not (plist-get plist :pin))) (cond ((eq pinned 't)
((equal (plist-get plist :pin) pinned))))) (plist-get plist :pin))
collect (cons sym plist) ((null pinned)
and if (and deps (not (package-built-in-p sym))) (not (plist-get plist :pin)))
nconc ((equal (plist-get plist :pin) pinned)))))
(cl-loop for pkg in (doom-get-dependencies-for sym 'recursive 'noerror) collect (cons sym plist)
if (or (eq installed 'any) and if (and deps (not (package-built-in-p sym)))
(if installed nconc
(doom-package-installed-p pkg) (cl-loop for pkg in (doom-get-dependencies-for sym 'recursive 'noerror)
(not (doom-package-installed-p pkg)))) if (or (eq installed 'any)
collect (cons pkg (cdr (assq pkg doom-packages))))) (if installed
:key #'car)) (doom-package-installed-p pkg)
(not (doom-package-installed-p pkg))))
collect (cons pkg (cdr (assq pkg doom-packages))))))
;;;###autoload
(defun doom-package-list (&optional all-p)
"Retrieve a list of explicitly declared packages from enabled modules.
This excludes core packages listed in `doom-core-packages'.
If ALL-P, gather packages across all modules, including disabled ones."
(with-temp-buffer ; prevent buffer-local settings from propagating
(let ((noninteractive t)
(doom--stage 'packages)
(doom-modules (doom-modules))
doom-packages
doom-disabled-packages
package-pinned-packages)
(cl-letf ((load-fn
(lambda (file &optional noerror)
(condition-case e
(if all-p
(setq doom-packages
(append (let (doom-packages)
(load file noerror t t)
doom-packages)
doom-packages))
(load file noerror t t))
((debug error)
(signal 'doom-package-error
(list (or (doom-module-from-path file)
'(:private . packages))
e)))))))
(funcall load-fn (expand-file-name "packages.el" doom-core-dir))
(let ((private-packages (expand-file-name "packages.el" doom-private-dir)))
;; We load the private packages file twice to ensure disabled packages
;; are seen ASAP, and a second time to ensure privately overridden
;; packages are properly overwritten.
(funcall load-fn private-packages t)
(if all-p
(mapc load-fn (doom-files-in doom-modules-dir
:depth 2
:full t
:match "/packages\\.el$"))
(cl-loop for key being the hash-keys of doom-modules
for path = (doom-module-path (car key) (cdr key) "packages.el")
for doom--current-module = key
do (funcall load-fn path t)))
(funcall load-fn private-packages t))
(append (cl-loop for package in doom-core-packages
collect (list package :modules '((:core internal))))
(nreverse doom-packages))))))
;;;###autoload ;;;###autoload
(defun doom-get-package-alist () (defun doom-get-package-alist ()
"Returns a list of all desired packages, their dependencies and their desc "Returns a list of all desired packages, their dependencies and their desc
objects, in the order of their `package! blocks.'" objects, in the order of their `package! blocks.'"
(doom-initialize-packages)
(cl-remove-duplicates (cl-remove-duplicates
(cl-loop for name in (append doom-core-packages (mapcar #'car doom-packages)) (cl-loop for name in (mapcar #'car doom-packages)
if (assq name package-alist) if (assq name package-alist)
nconc (cl-loop for dep in (package--get-deps name) nconc (cl-loop for dep in (package--get-deps name)
if (assq dep package-alist) if (assq dep package-alist)
@ -245,7 +302,6 @@ containing (PACKAGE-SYMBOL OLD-VERSION-LIST NEW-VERSION-LIST).
If INCLUDE-FROZEN-P is non-nil, check frozen packages as well. If INCLUDE-FROZEN-P is non-nil, check frozen packages as well.
Used by `doom-packages-update'." Used by `doom-packages-update'."
(doom-initialize-packages t)
(doom-refresh-packages-maybe doom-debug-mode) (doom-refresh-packages-maybe doom-debug-mode)
(let-alist (let-alist
(seq-group-by (seq-group-by
@ -295,7 +351,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 :ignored nil :disabled nil)))) (mapcar #'car (doom-find-packages :ignored nil :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)
@ -303,22 +359,17 @@ Used by `doom-packages-autoremove'."
collect pkg)))) collect pkg))))
;;;###autoload ;;;###autoload
(defun doom-get-missing-packages (&optional include-ignored-p) (defun doom-get-missing-packages ()
"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
`package!' declaration. `package!' declaration.
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'." Used by `doom-packages-install'."
(doom-initialize-packages)
(cl-loop for (name . plist) (cl-loop for (name . plist)
in (doom-get-packages :ignored (if include-ignored-p 'any) in (doom-find-packages :ignored nil
:disabled nil :disabled nil
:deps t :deps t)
:sort nil)
if (and (or (plist-get plist :pin) if (and (or (plist-get plist :pin)
(not (package-built-in-p name))) (not (package-built-in-p name)))
(or (not (doom-package-installed-p name)) (or (not (doom-package-installed-p name))
@ -343,7 +394,6 @@ Used by `doom-packages-install'."
"Installs package NAME with optional quelpa RECIPE (see `quelpa-recipe' for an "Installs package NAME with optional quelpa RECIPE (see `quelpa-recipe' for an
example; the package name can be omitted)." example; the package name can be omitted)."
(cl-check-type name symbol) (cl-check-type name symbol)
(doom-initialize-packages)
(when (and (package-installed-p name) (when (and (package-installed-p name)
(not (package-built-in-p name))) (not (package-built-in-p name)))
(if (or (doom-package-different-backend-p name) (if (or (doom-package-different-backend-p name)
@ -371,7 +421,6 @@ example; the package name can be omitted)."
"Updates package NAME (a symbol) if it is out of date, using quelpa or "Updates package NAME (a symbol) if it is out of date, using quelpa or
package.el as appropriate." package.el as appropriate."
(cl-check-type name symbol) (cl-check-type name symbol)
(doom-initialize-packages)
(unless (package-installed-p name) (unless (package-installed-p name)
(error "%s isn't installed" name)) (error "%s isn't installed" name))
(when (doom-package-different-backend-p name) (when (doom-package-different-backend-p name)
@ -402,7 +451,6 @@ package.el as appropriate."
(defun doom-delete-package (name &optional force-p) (defun doom-delete-package (name &optional force-p)
"Uninstalls package NAME if it exists, and clears it from `quelpa-cache'." "Uninstalls package NAME if it exists, and clears it from `quelpa-cache'."
(cl-check-type name symbol) (cl-check-type name symbol)
(doom-initialize-packages)
(unless (package-installed-p name) (unless (package-installed-p name)
(user-error "%s isn't installed" name)) (user-error "%s isn't installed" name))
(let ((inhibit-message (not doom-debug-mode)) (let ((inhibit-message (not doom-debug-mode))
@ -420,6 +468,14 @@ package.el as appropriate."
;; ;;
;; Interactive commands ;; Interactive commands
;;;###autoload
(defun doom/reload-packages ()
"Reload `doom-packages', `package' and `quelpa'."
(interactive)
(message "Reloading packages")
(doom-initialize-packages t)
(message "Reloading packages...DONE"))
;;;###autoload ;;;###autoload
(defun doom/update-package (pkg) (defun doom/update-package (pkg)
"Prompts the user with a list of outdated packages and updates the selected "Prompts the user with a list of outdated packages and updates the selected
@ -437,7 +493,6 @@ calls."
(unless name (unless name
(user-error "'%s' is already up-to-date" selection)) (user-error "'%s' is already up-to-date" selection))
(list (assq name packages)))) (list (assq name packages))))
(doom-initialize-packages)
(cl-destructuring-bind (package old-version new-version) pkg (cl-destructuring-bind (package old-version new-version) pkg
(if-let* ((desc (doom-package-outdated-p package))) (if-let* ((desc (doom-package-outdated-p package)))
(let ((old-v-str (package-version-join old-version)) (let ((old-v-str (package-version-join old-version))
@ -457,7 +512,6 @@ calls."
;;;###autoload ;;;###autoload
(defun doom*package-delete (desc &rest _) (defun doom*package-delete (desc &rest _)
"Update `quelpa-cache' upon a successful `package-delete'." "Update `quelpa-cache' upon a successful `package-delete'."
(doom-initialize-packages)
(let ((name (package-desc-name desc))) (let ((name (package-desc-name desc)))
(unless (package-installed-p name) (unless (package-installed-p name)
(when-let* ((spec (assq name quelpa-cache))) (when-let* ((spec (assq name quelpa-cache)))

View file

@ -318,7 +318,7 @@ modified."
(prin1 `(setq load-path ',load-path (prin1 `(setq load-path ',load-path
auto-mode-alist ',auto-mode-alist auto-mode-alist ',auto-mode-alist
Info-directory-list ',Info-directory-list Info-directory-list ',Info-directory-list
doom-disabled-packages ',doom-disabled-packages doom-disabled-packages ',(mapcar #'car (doom-find-packages :disabled t))
package-activated-list ',package-activated-list) package-activated-list ',package-activated-list)
(current-buffer))) (current-buffer)))
@ -352,10 +352,10 @@ This should be run whenever your `doom!' block or update your packages."
(with-temp-file doom-package-autoload-file (with-temp-file doom-package-autoload-file
(doom--generate-header 'doom-reload-package-autoloads) (doom--generate-header 'doom-reload-package-autoloads)
(save-excursion (save-excursion
;; Cache the important and expensive-to-initialize state here. ;; Cache important and expensive-to-initialize state here.
(doom--generate-var-cache) (doom--generate-var-cache)
(print! (green "✓ Cached package state")) (print! (green "✓ Cached package state"))
;; Loop through packages and concatenate all their autoloads files. ;; Concatenate the autoloads of all installed packages.
(doom--generate-package-autoloads) (doom--generate-package-autoloads)
(print! (green "✓ Package autoloads included"))) (print! (green "✓ Package autoloads included")))
;; Remove `load-path' and `auto-mode-alist' modifications (most of them, ;; Remove `load-path' and `auto-mode-alist' modifications (most of them,

View file

@ -224,9 +224,7 @@ BODY is evaluated once TARGETS are loaded. TARGETS can either be:
#'progn #'progn
#'with-no-warnings) #'with-no-warnings)
(if (symbolp targets) (if (symbolp targets)
`(progn `(with-eval-after-load ',targets ,@body)
(doom-module-register-config ',targets ,(FILE!))
(with-eval-after-load ',targets ,@body))
(pcase (car-safe targets) (pcase (car-safe targets)
((or :or :any) ((or :or :any)
(macroexp-progn (macroexp-progn

View file

@ -188,15 +188,6 @@ non-nil, return paths of possible modules, activated or otherwise."
collect (plist-get plist :path))) collect (plist-get plist :path)))
(list doom-private-dir))) (list doom-private-dir)))
(defun doom-module-register-config (package file &optional append)
"TODO"
(let ((files (get package 'doom-files)))
(unless (member file files)
(if append
(setq files (append files (list file)))
(push file files))
(put package 'doom-files files))))
(defun doom-modules (&optional refresh-p) (defun doom-modules (&optional refresh-p)
"Minimally initialize `doom-modules' (a hash table) and return it." "Minimally initialize `doom-modules' (a hash table) and return it."
(or (unless refresh-p doom-modules) (or (unless refresh-p doom-modules)
@ -372,9 +363,7 @@ package is disabled."
;; package errors, so we preform this check at compile time: ;; package errors, so we preform this check at compile time:
(and (bound-and-true-p byte-compile-current-file) (and (bound-and-true-p byte-compile-current-file)
(not (locate-library (symbol-name name))))) (not (locate-library (symbol-name name)))))
`(progn `(use-package ,name ,@plist)))
(doom-module-register-config ',name ,(FILE!) t)
(use-package ,name ,@plist))))
(defmacro def-package-hook! (package when &rest body) (defmacro def-package-hook! (package when &rest body)
"Reconfigures a package's `def-package!' block. "Reconfigures a package's `def-package!' block.
@ -396,7 +385,6 @@ to have them return non-nil (or exploit that to overwrite Doom's config)."
(error "'%s' isn't a valid hook for def-package-hook!" when)) (error "'%s' isn't a valid hook for def-package-hook!" when))
`(progn `(progn
(setq use-package-inject-hooks t) (setq use-package-inject-hooks t)
(doom-module-register-config ',package ,(FILE!))
(add-hook! (add-hook!
',(intern (format "use-package--%s--%s-hook" ',(intern (format "use-package--%s--%s-hook"
package package

View file

@ -87,52 +87,27 @@ If FORCE-P is 'internal, only (re)populate `doom-packages'.
Use this before any of package.el, quelpa or Doom's package management's API to Use this before any of package.el, quelpa or Doom's package management's API to
ensure all the necessary package metadata is initialized and available for ensure all the necessary package metadata is initialized and available for
them." them."
(with-temp-buffer ; prevent buffer-local settings from propagating (let ((load-prefer-newer t)) ; reduce stale code issues
(let ((load-prefer-newer t)) ; reduce stale code issues ;; package.el and quelpa handle themselves if their state changes during the
;; package.el and quelpa handle themselves if their state changes during ;; current session, but if you change an packages.el file in a module,
;; the current session, but if you change an packages.el file in a module, ;; there's no non-trivial way to detect that, so to reload only
;; there's no non-trivial way to detect that, so we give you a way to ;; doom-packages pass 'internal as FORCE-P or use `doom/reload-packages'.
;; reload only doom-packages (by passing 'internal as FORCE-P). (unless (eq force-p 'internal)
(unless (eq force-p 'internal) ;; `package-alist'
;; `package-alist' (when (or force-p (not (bound-and-true-p package-alist)))
(when (or force-p (not (bound-and-true-p package-alist))) (doom-ensure-packages-initialized 'force)
(doom-ensure-packages-initialized 'force) (setq load-path (cl-delete-if-not #'file-directory-p load-path)))
(setq load-path (cl-remove-if-not #'file-directory-p load-path))) ;; `quelpa-cache'
;; `quelpa-cache' (when (or force-p (not (bound-and-true-p quelpa-cache)))
(when (or force-p (not (bound-and-true-p quelpa-cache))) ;; ensure un-byte-compiled version of quelpa is loaded
;; ensure un-byte-compiled version of quelpa is loaded (unless (featurep 'quelpa)
(unless (featurep 'quelpa) (load (locate-library "quelpa.el") nil t t))
(load (locate-library "quelpa.el") nil t t)) (setq quelpa-initialized-p nil)
(setq quelpa-initialized-p nil) (or (quelpa-setup-p)
(or (quelpa-setup-p) (error "Could not initialize quelpa"))))
(error "Could not initialize quelpa")))) ;; `doom-packages'
;; `doom-packages' (when (or force-p (not doom-packages))
(when (or force-p (not doom-packages)) (setq doom-packages (doom-package-list)))))
(cl-flet
((_load
(lambda (file &optional noerror)
(condition-case e
(load file noerror t t)
((debug error)
(signal 'doom-package-error
(list (or (doom-module-from-path file)
'(:private . packages))
e)))))))
(let ((doom-modules (doom-modules))
(doom--stage 'packages)
(noninteractive t))
(setq doom-packages nil)
(_load (expand-file-name "packages.el" doom-core-dir))
;; We load the private packages file twice to ensure disabled
;; packages are seen ASAP, and a second time to ensure privately
;; overridden packages are properly overwritten.
(let ((private-packages (expand-file-name "packages.el" doom-private-dir)))
(_load private-packages t)
(cl-loop for key being the hash-keys of doom-modules
for path = (doom-module-path (car key) (cdr key) "packages.el")
do (let ((doom--current-module key)) (_load path t)))
(_load private-packages t)
(setq doom-packages (reverse doom-packages)))))))))
;; ;;
@ -169,7 +144,7 @@ them."
;; ;;
;; Module package macros ;; Module package macros
(cl-defmacro package! (name &rest plist &key recipe pin disable _ignore _freeze) (cl-defmacro package! (name &rest plist &key built-in recipe pin disable _ignore _freeze)
"Declares a package and how to install it (if applicable). "Declares a package and how to install it (if applicable).
This macro is declarative and does not load nor install packages. It is used to This macro is declarative and does not load nor install packages. It is used to
@ -193,41 +168,49 @@ Accepts the following properties:
Do not install this package. Do not install this package.
:freeze FORM :freeze FORM
Do not update this package if FORM is non-nil. Do not update this package if FORM is non-nil.
:built-in BOOL
Same as :ignore if the package is a built-in Emacs package.
Returns t if package is successfully registered, and nil if it was disabled Returns t if package is successfully registered, and nil if it was disabled
elsewhere." elsewhere."
(declare (indent defun)) (declare (indent defun))
(doom--assert-stage-p 'packages #'package!) (doom--assert-stage-p 'packages #'package!)
(let ((plist (append plist (cdr (assq name doom-packages))))) (let ((old-plist (cdr (assq name doom-packages))))
(when recipe (when recipe
(when (cl-evenp (length recipe)) (when (cl-evenp (length recipe))
(setq plist (plist-put plist :recipe (cons name recipe)))) (setq plist (plist-put plist :recipe (cons name recipe))))
(setq pin nil (setq pin nil
plist (plist-put plist :pin nil))) plist (plist-put plist :pin nil)))
(when (file-in-directory-p (FILE!) doom-private-dir) (let ((module-list (plist-get old-plist :modules))
(setq plist (plist-put plist :private t))) (module (or doom--current-module
(let (newplist) (let ((file (FILE!)))
(while plist (cond ((file-in-directory-p file doom-private-dir)
(unless (null (cadr plist)) (list :private))
(push (cadr plist) newplist) ((file-in-directory-p file doom-core-dir)
(push (car plist) newplist)) (list :core))
(pop plist) ((doom-module-from-path file)))))))
(pop plist)) (doom-log "Registered package '%s'%s"
(setq plist newplist)) name (if recipe (format " with recipe %s" recipe) ""))
(unless (member module module-list)
(setq module-list (append module-list (list module) nil)
plist (plist-put plist :modules module-list))))
(when (and built-in (locate-library (symbol-name name) nil doom-site-load-path))
(doom-log "Ignoring built-in package '%s'" name)
(setq plist (plist-put plist :ignore t)))
(while plist
(unless (null (cadr plist))
(setq old-plist (plist-put old-plist (car plist) (cadr plist))))
(pop plist)
(pop plist))
(setq plist old-plist)
(macroexp-progn (macroexp-progn
(append (if disable `((add-to-list 'doom-disabled-packages ',name nil #'eq))) (append (when disable
(if pin `((setf (alist-get ',name package-pinned-packages) ,pin))) (doom-log "Disabling package '%s'" name)
`((let ((doom--current-module `((add-to-list 'doom-disabled-packages ',name nil 'eq)))
(or doom--current-module (when pin
(let ((file (FILE!))) (doom-log "Pinning package '%s' to '%s'" name pin)
(cond ((file-in-directory-p file doom-private-dir) `((setf (alist-get ',name package-pinned-packages) ,pin)))
(cons :private (intern (file-name-base file)))) `((setf (alist-get ',name doom-packages) ',plist)
((file-in-directory-p file doom-core-dir)
(cons :core nil))))))
(modules (get ',name 'doom-module)))
(cl-pushnew doom--current-module modules)
(put ',name 'doom-module modules))
(setf (alist-get ',name doom-packages) ',plist)
(not (memq ',name doom-disabled-packages))))))) (not (memq ',name doom-disabled-packages)))))))
(defmacro packages! (&rest packages) (defmacro packages! (&rest packages)

View file

@ -55,8 +55,8 @@
(doom-missing-dummy) (doom-missing-dummy)
(doom-noquelpa-dummy) (doom-noquelpa-dummy)
(doom-disabled-dummy :disable t) (doom-disabled-dummy :disable t)
(doom-private-dummy :private t) (doom-private-dummy :modules ((:private)))
(doom-disabled-private-dummy :private t :disable t) (doom-disabled-private-dummy :modules ((:private)) :disable t)
(doom-quelpa-dummy :recipe (doom-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist"))) (doom-quelpa-dummy :recipe (doom-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist")))
quelpa-cache quelpa-cache
'((doom-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist") '((doom-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist")
@ -95,31 +95,31 @@
(spy-on #'doom-package-installed-p :and-call-fake #'package-installed-p)) (spy-on #'doom-package-installed-p :and-call-fake #'package-installed-p))
(it "returns all packages" (it "returns all packages"
(expect (mapcar #'car (doom-get-packages)) (expect (mapcar #'car (doom-find-packages))
:to-have-same-items-as :to-have-same-items-as
(mapcar #'car doom-packages))) (mapcar #'car doom-packages)))
(it "returns only disabled packages" (it "returns only disabled packages"
(expect (mapcar #'car (doom-get-packages :disabled t)) (expect (mapcar #'car (doom-find-packages :disabled t))
:to-have-same-items-as :to-have-same-items-as
'(doom-disabled-dummy doom-disabled-private-dummy))) '(doom-disabled-dummy doom-disabled-private-dummy)))
(it "returns only non-disabled packages" (it "returns only non-disabled packages"
(expect (mapcar #'car (doom-get-packages :disabled nil)) (expect (mapcar #'car (doom-find-packages :disabled nil))
:to-have-same-items-as :to-have-same-items-as
'(doom-dummy doom-uptodate-dummy doom-quelpa-dummy doom-missing-dummy doom-noquelpa-dummy doom-private-dummy))) '(doom-dummy doom-uptodate-dummy doom-quelpa-dummy doom-missing-dummy doom-noquelpa-dummy doom-private-dummy)))
(it "returns only installed packages" (it "returns only installed packages"
(expect (mapcar #'car (doom-get-packages :disabled nil :installed t)) (expect (mapcar #'car (doom-find-packages :disabled nil :installed t))
:to-have-same-items-as :to-have-same-items-as
'(doom-dummy doom-uptodate-dummy doom-quelpa-dummy doom-noquelpa-dummy))) '(doom-dummy doom-uptodate-dummy doom-quelpa-dummy doom-noquelpa-dummy)))
(it "returns only non-installed packages" (it "returns only non-installed packages"
(expect (mapcar #'car (doom-get-packages :disabled nil :installed nil)) (expect (mapcar #'car (doom-find-packages :disabled nil :installed nil))
:to-have-same-items-as :to-have-same-items-as
'(doom-missing-dummy doom-private-dummy))) '(doom-missing-dummy doom-private-dummy)))
(it "returns only private packages" (it "returns only private packages"
(expect (mapcar #'car (doom-get-packages :private t)) (expect (mapcar #'car (doom-find-packages :private t))
:to-have-same-items-as :to-have-same-items-as
'(doom-private-dummy doom-disabled-private-dummy))) '(doom-private-dummy doom-disabled-private-dummy)))
(it "returns only disabled and private packages" (it "returns only disabled and private packages"
(expect (mapcar #'car (doom-get-packages :disabled t :private t)) (expect (mapcar #'car (doom-find-packages :disabled t :private t))
:to-have-same-items-as :to-have-same-items-as
'(doom-disabled-private-dummy)))) '(doom-disabled-private-dummy))))