💥 Replace package.el/quelpa with straight #374
There are a few kinks to iron out, but for the most part it's done. Doom Emacs, powered by straight. Goodbye gnutls and elpa/quelpa issues. This update doesn't come with rollback or lockfile support yet, but I will eventually include one with Doom, and packages will be (by default, anyway) updated in sync with Doom. Relevant threads: #1577 #1566 #1473
This commit is contained in:
parent
492f2dea1e
commit
b90dede1ab
35 changed files with 1542 additions and 1771 deletions
|
@ -1,15 +1,18 @@
|
|||
;;; core/autoload/cli.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Externs
|
||||
(defvar evil-collection-mode-list)
|
||||
|
||||
(require 'core-cli)
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-cli-run (command &rest _args)
|
||||
(defun doom--cli-run (command &rest _args)
|
||||
(when (featurep 'general)
|
||||
(general-auto-unbind-keys))
|
||||
(let* ((evil-collection-mode-list nil)
|
||||
(default-directory doom-emacs-dir)
|
||||
(buf (get-buffer-create " *bin/doom*"))
|
||||
(doom-message-backend 'ansi)
|
||||
(doom-format-backend 'ansi)
|
||||
(ignore-window-parameters t)
|
||||
(noninteractive t)
|
||||
(standard-output
|
||||
|
@ -39,21 +42,21 @@
|
|||
"TODO"
|
||||
(interactive "P")
|
||||
(let ((doom-auto-accept yes))
|
||||
(doom-cli-run "autoloads")))
|
||||
(doom--cli-run "autoloads")))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom//update (&optional yes)
|
||||
"TODO"
|
||||
(interactive "P")
|
||||
(let ((doom-auto-accept yes))
|
||||
(doom-cli-run "update")))
|
||||
(doom--cli-run "update")))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom//upgrade (&optional yes)
|
||||
"TODO"
|
||||
(interactive "P")
|
||||
(let ((doom-auto-accept yes))
|
||||
(doom-cli-run "upgrade"))
|
||||
(doom--cli-run "upgrade"))
|
||||
(when (y-or-n-p "You must restart Emacs for the upgrade to take effect. Restart?")
|
||||
(doom/restart-and-restore)))
|
||||
|
||||
|
@ -62,18 +65,18 @@
|
|||
"TODO"
|
||||
(interactive "P")
|
||||
(let ((doom-auto-accept yes))
|
||||
(doom-cli-run "install")))
|
||||
(doom--cli-run "install")))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom//autoremove (&optional yes)
|
||||
"TODO"
|
||||
(interactive "P")
|
||||
(let ((doom-auto-accept yes))
|
||||
(doom-cli-run "autoremove")))
|
||||
(doom--cli-run "autoremove")))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom//refresh (&optional yes)
|
||||
"TODO"
|
||||
(interactive "P")
|
||||
(let ((doom-auto-accept yes))
|
||||
(doom-cli-run "refresh")))
|
||||
(doom--cli-run "refresh")))
|
||||
|
|
|
@ -16,65 +16,54 @@ ready to be pasted in a bug report on github."
|
|||
(require 'vc-git)
|
||||
(let ((default-directory doom-emacs-dir)
|
||||
(doom-modules (doom-modules)))
|
||||
(format
|
||||
(concat "- OS: %s (%s)\n"
|
||||
"- Shell: %s\n"
|
||||
"- Emacs: %s (%s)\n"
|
||||
"- Doom: %s (%s)\n"
|
||||
"- Graphic display: %s (daemon: %s)\n"
|
||||
"- System features: %s\n"
|
||||
"- Details:\n"
|
||||
" ```elisp\n"
|
||||
" env bootstrapper: %s\n"
|
||||
" elc count: %s\n"
|
||||
" uname -a: %s\n"
|
||||
" modules: %s\n"
|
||||
" packages: %s\n"
|
||||
" exec-path: %s\n"
|
||||
" ```")
|
||||
system-type system-configuration
|
||||
shell-file-name
|
||||
emacs-version (format-time-string "%b %d, %Y" emacs-build-time)
|
||||
doom-version
|
||||
(or (string-trim (shell-command-to-string "git log -1 --format=\"%D %h %ci\""))
|
||||
"n/a")
|
||||
(display-graphic-p) (daemonp)
|
||||
(bound-and-true-p system-configuration-features)
|
||||
(cond ((file-exists-p doom-env-file) 'envvar-file)
|
||||
((featurep 'exec-path-from-shell) 'exec-path-from-shell))
|
||||
;; details
|
||||
(length (doom-files-in `(,@doom-modules-dirs
|
||||
,doom-core-dir
|
||||
,doom-private-dir)
|
||||
:type 'files :match "\\.elc$" :sort nil))
|
||||
(if IS-WINDOWS
|
||||
"n/a"
|
||||
(with-temp-buffer
|
||||
(unless (zerop (call-process "uname" nil t nil "-msrv"))
|
||||
(insert (format "%s" system-type)))
|
||||
(string-trim (buffer-string))))
|
||||
(or (cl-loop with cat = nil
|
||||
for key being the hash-keys of doom-modules
|
||||
if (or (not cat) (not (eq cat (car key))))
|
||||
do (setq cat (car key))
|
||||
and collect cat
|
||||
and collect (cdr key)
|
||||
else collect
|
||||
(let ((flags (doom-module-get cat (cdr key) :flags)))
|
||||
(if flags
|
||||
`(,(cdr key) ,@flags)
|
||||
(cdr key))))
|
||||
"n/a")
|
||||
(or (ignore-errors
|
||||
(require 'use-package)
|
||||
(cl-loop for (name . plist) in (doom-find-packages :private t)
|
||||
if (use-package-plist-delete (copy-sequence plist) :modules)
|
||||
collect (format "%s" (cons name it))
|
||||
else
|
||||
collect (symbol-name name)))
|
||||
"n/a")
|
||||
;; abbreviate $HOME to hide username
|
||||
(mapcar #'abbreviate-file-name exec-path))))
|
||||
(cl-letf
|
||||
(((symbol-function 'sh)
|
||||
(lambda (format)
|
||||
(string-trim
|
||||
(shell-command-to-string format)))))
|
||||
`((emacs
|
||||
(version . ,emacs-version)
|
||||
(features ,@system-configuration-features)
|
||||
(build . ,(format-time-string "%b %d, %Y" emacs-build-time))
|
||||
(buildopts ,system-configuration-options))
|
||||
(doom
|
||||
(version . ,doom-version)
|
||||
(build . ,(sh "git log -1 --format=\"%D %h %ci\"")))
|
||||
(system
|
||||
(type . ,system-type)
|
||||
(config . ,system-configuration)
|
||||
(shell . ,shell-file-name)
|
||||
(uname . ,(if IS-WINDOWS
|
||||
"n/a"
|
||||
(sh "uname -msrv")))
|
||||
(path . ,(mapcar #'abbreviate-file-name exec-path)))
|
||||
(config
|
||||
(envfile . ,(cond ((file-exists-p doom-env-file) 'envvar-file)
|
||||
((featurep 'exec-path-from-shell) 'exec-path-from-shell)))
|
||||
(elc-files . ,(length (doom-files-in `(,@doom-modules-dirs
|
||||
,doom-core-dir
|
||||
,doom-private-dir)
|
||||
:type 'files :match "\\.elc$" :sort nil)))
|
||||
(modules ,@(or (cl-loop with cat = nil
|
||||
for key being the hash-keys of doom-modules
|
||||
if (or (not cat) (not (eq cat (car key))))
|
||||
do (setq cat (car key))
|
||||
and collect cat
|
||||
and collect (cdr key)
|
||||
else collect
|
||||
(let ((flags (doom-module-get cat (cdr key) :flags)))
|
||||
(if flags
|
||||
`(,(cdr key) ,@flags)
|
||||
(cdr key))))
|
||||
'("n/a")))
|
||||
(packages ,@(or (ignore-errors
|
||||
(require 'use-package)
|
||||
(cl-loop for (name . plist) in (doom-find-packages :private t)
|
||||
if (use-package-plist-delete (copy-sequence plist) :modules)
|
||||
collect (format "%s" (cons name it))
|
||||
else
|
||||
collect (symbol-name name)))
|
||||
'("n/a"))))))))
|
||||
|
||||
|
||||
;;
|
||||
|
@ -86,24 +75,55 @@ ready to be pasted in a bug report on github."
|
|||
branch and commit."
|
||||
(interactive)
|
||||
(require 'vc-git)
|
||||
(print! "Doom v%s (Emacs v%s)\nBranch: %s\nCommit: %s"
|
||||
(print! "Doom v%s (Emacs v%s)\nBranch: %s\nCommit: %s\nBuild date: %s"
|
||||
doom-version
|
||||
emacs-version
|
||||
(or (vc-git--symbolic-ref doom-core-dir)
|
||||
"n/a")
|
||||
(or (vc-git-working-revision doom-core-dir)
|
||||
"n/a")
|
||||
(or (string-trim (shell-command-to-string "git log -1 --format=%ci"))
|
||||
"n/a")))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/info ()
|
||||
(defun doom/info (&optional raw)
|
||||
"Collects some debug information about your Emacs session, formats it into
|
||||
markdown and copies it to your clipboard, ready to be pasted into bug reports!"
|
||||
(interactive)
|
||||
(message "Generating Doom info...")
|
||||
(if noninteractive
|
||||
(print! (doom-info))
|
||||
(kill-new (doom-info))
|
||||
(message "Done! Copied to clipboard.")))
|
||||
(interactive "P")
|
||||
(let ((buffer (get-buffer-create "*doom-info*"))
|
||||
(info (doom-info)))
|
||||
(with-current-buffer buffer
|
||||
(unless (or noninteractive
|
||||
(eq major-mode 'markdown-mode)
|
||||
(not (fboundp 'markdown-mode)))
|
||||
(markdown-mode))
|
||||
(erase-buffer)
|
||||
(if raw
|
||||
(progn
|
||||
(save-excursion
|
||||
(pp info (current-buffer)))
|
||||
(when (re-search-forward "(modules " nil t)
|
||||
(goto-char (match-beginning 0))
|
||||
(cl-destructuring-bind (beg . end)
|
||||
(bounds-of-thing-at-point 'sexp)
|
||||
(let ((sexp (prin1-to-string (sexp-at-point))))
|
||||
(delete-region beg end)
|
||||
(insert sexp)))))
|
||||
(insert "<details>\n\n```\n")
|
||||
(dolist (group info)
|
||||
(insert! "%-8s%-10s %s\n"
|
||||
((car group)
|
||||
(caadr group)
|
||||
(cdadr group)))
|
||||
(dolist (spec (cddr group))
|
||||
(insert! (indent 8 "%-10s %s\n")
|
||||
((car spec) (cdr spec)))))
|
||||
(insert "```\n</details>"))
|
||||
(if noninteractive
|
||||
(print! (buffer-string))
|
||||
(switch-to-buffer buffer)
|
||||
(kill-new (buffer-string))
|
||||
(print! (green "Copied markdown to clipboard"))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/am-i-secure ()
|
||||
|
@ -144,11 +164,11 @@ markdown and copies it to your clipboard, ready to be pasted into bug reports!"
|
|||
(macroexp-progn
|
||||
(append `((setq noninteractive nil
|
||||
doom-debug-mode t
|
||||
load-path ',load-path
|
||||
package--init-file-ensured t
|
||||
package-user-dir ,package-user-dir
|
||||
package-archives ',package-archives
|
||||
user-emacs-directory ,doom-emacs-dir
|
||||
doom--modules-cache nil)
|
||||
user-emacs-directory ,doom-emacs-dir)
|
||||
(with-eval-after-load 'undo-tree
|
||||
;; undo-tree throws errors because `buffer-undo-tree' isn't
|
||||
;; corrrectly initialized
|
||||
|
|
|
@ -365,10 +365,14 @@ current file is in, or d) the module associated with the current major mode (see
|
|||
(recenter)
|
||||
(message "Couldn't find the config block"))))))))
|
||||
|
||||
(defvar doom--help-packages-list nil)
|
||||
(defun doom--help-packages-list (&optional refresh)
|
||||
(or (unless refresh
|
||||
(doom-cache-get 'help-packages))
|
||||
(doom-cache-set 'help-packages (doom-package-list 'all))))
|
||||
doom--help-packages-list)
|
||||
(setq doom--help-packages-list
|
||||
(append (cl-loop for package in doom-core-packages
|
||||
collect (list package :modules '((:core internal))))
|
||||
(doom-package-list 'all)))))
|
||||
|
||||
(defun doom--help-package-configs (package)
|
||||
;; TODO Add git checks, in case ~/.emacs.d isn't a git repo
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
;;; core/autoload/hydras.el -*- lexical-binding: t; -*-
|
||||
;;; core/autoload/hydras.el -*- lexical-binding: t; no-byte-compile: t; -*-
|
||||
|
||||
;;;###autoload (autoload 'doom-text-zoom-hydra/body "core/autoload/hydras" nil t)
|
||||
(defhydra doom-text-zoom-hydra (:hint t :color red)
|
||||
|
|
|
@ -1,128 +1,67 @@
|
|||
;;; core/autoload/packages.el -*- lexical-binding: t; -*-
|
||||
|
||||
(require 'core-packages)
|
||||
(load! "cache") ; in case autoloads haven't been generated yet
|
||||
|
||||
|
||||
(defun doom--packages-choose (prompt)
|
||||
(let ((table (cl-loop for pkg in package-alist
|
||||
unless (doom-package-built-in-p (cdr pkg))
|
||||
collect (cons (package-desc-full-name (cdr pkg))
|
||||
(cdr pkg)))))
|
||||
(cdr (assoc (completing-read prompt
|
||||
(mapcar #'car table)
|
||||
nil t)
|
||||
table))))
|
||||
|
||||
(defun doom--refresh-pkg-cache ()
|
||||
"Clear the cache for `doom-refresh-packages-maybe'."
|
||||
(setq doom--refreshed-p nil)
|
||||
(doom-cache-set 'last-pkg-refresh nil))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-refresh-packages-maybe (&optional force-p)
|
||||
"Refresh ELPA packages, if it hasn't been refreshed recently."
|
||||
(when force-p
|
||||
(doom--refresh-pkg-cache))
|
||||
(unless (or (doom-cache-get 'last-pkg-refresh)
|
||||
doom--refreshed-p)
|
||||
(condition-case e
|
||||
(progn
|
||||
(message "Refreshing package archives")
|
||||
(package-refresh-contents)
|
||||
(doom-cache-set 'last-pkg-refresh t 1200))
|
||||
((debug error)
|
||||
(doom--refresh-pkg-cache)
|
||||
(signal 'doom-error e)))))
|
||||
|
||||
|
||||
;;
|
||||
;;; Package metadata
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-plist (package)
|
||||
(defun doom-package-get (package &optional prop nil-value)
|
||||
"Returns PACKAGE's `package!' recipe from `doom-packages'."
|
||||
(cdr (assq package doom-packages)))
|
||||
(let ((plist (cdr (assq package doom-packages))))
|
||||
(if prop
|
||||
(if (plist-member plist prop)
|
||||
(plist-get plist prop)
|
||||
nil-value)
|
||||
plist)))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-desc (package)
|
||||
"Returns PACKAGE's desc struct from `package-alist'."
|
||||
(cadr (assq (or (car (doom-package-prop package :recipe))
|
||||
package)
|
||||
package-alist)))
|
||||
(defun doom-package-recipe (package &optional prop nil-value)
|
||||
"Returns the `straight' recipe PACKAGE was registered with."
|
||||
(let ((plist (gethash (symbol-name package) straight--recipe-cache)))
|
||||
(if prop
|
||||
(if (plist-member plist prop)
|
||||
(plist-get plist prop)
|
||||
nil-value)
|
||||
plist)))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-true-name (package)
|
||||
"Return PACKAGE's true name.
|
||||
|
||||
It is possible for quelpa packages to be given a psuedonym (the first argument
|
||||
of `package!'). Its real name is the car of package's :recipe. e.g.
|
||||
|
||||
(package! X :recipe (Y :fetcher github :repo \"abc/def\"))
|
||||
|
||||
X's real name is Y."
|
||||
(let ((sym (car (doom-package-prop package :recipe))))
|
||||
(or (and (symbolp sym)
|
||||
(not (keywordp sym))
|
||||
sym)
|
||||
package)))
|
||||
(defun doom-package-build-recipe (package &optional prop nil-value)
|
||||
"Returns the `straight' recipe PACKAGE was installed with."
|
||||
(let ((plist (nth 2 (gethash (symbol-name package) straight--build-cache))))
|
||||
(if prop
|
||||
(if (plist-member plist prop)
|
||||
(plist-get plist prop)
|
||||
nil-value)
|
||||
plist)))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-psuedo-name (package)
|
||||
(defun doom-package-build-time (package)
|
||||
"TODO"
|
||||
(or (cl-loop for (package . plist) in doom-packages
|
||||
for recipe-name = (car (plist-get plist :recipe))
|
||||
if (eq recipe-name package)
|
||||
return recipe-name)
|
||||
package))
|
||||
(car (gethash (symbol-name package) straight--build-cache)))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-backend (package &optional noerror)
|
||||
"Return backend that PACKAGE was installed with.
|
||||
(defun doom-package-dependencies (package &optional recursive noerror)
|
||||
"Return a list of dependencies for a package."
|
||||
(let ((deps (nth 1 (gethash (symbol-name package) straight--build-cache))))
|
||||
(if recursive
|
||||
(nconc deps (mapcan (lambda (dep) (doom-package-dependencies dep t t))
|
||||
deps))
|
||||
deps)))
|
||||
|
||||
Can either be elpa, quelpa or emacs (built-in). Throws an error if NOERROR is
|
||||
nil and the package isn't installed.
|
||||
|
||||
See `doom-package-recipe-backend' to get the backend PACKAGE is registered with
|
||||
\(as opposed to what it is was installed with)."
|
||||
(cl-check-type package symbol)
|
||||
(let ((package-truename (doom-package-true-name package)))
|
||||
(cond ((assq package-truename quelpa-cache) 'quelpa)
|
||||
((assq package-truename package-alist) 'elpa)
|
||||
((doom-package-built-in-p package) 'emacs)
|
||||
((not noerror) (error "%s package is not installed" package)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-recipe-backend (package &optional noerror)
|
||||
"Return backend that PACKAGE is registered with.
|
||||
|
||||
See `doom-package-backend' to get backend for currently installed package."
|
||||
(cl-check-type package symbol)
|
||||
(cond ((not (doom-package-registered-p package))
|
||||
(unless noerror
|
||||
(error "%s package is not registered" package)))
|
||||
((let ((builtin (eval (doom-package-prop package :built-in) t)))
|
||||
(or (and (eq builtin 'prefer)
|
||||
(locate-library (symbol-name package) nil doom-site-load-path))
|
||||
(eq builtin 't)))
|
||||
'emacs)
|
||||
((doom-package-prop package :recipe)
|
||||
'quelpa)
|
||||
('elpa)))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-prop (package prop &optional nil-value)
|
||||
"Return PROPerty in PACKAGE's plist.
|
||||
|
||||
Otherwise returns NIL-VALUE if package isn't registered or PROP doesn't
|
||||
exist/isn't specified."
|
||||
(cl-check-type package symbol)
|
||||
(cl-check-type prop keyword)
|
||||
(if-let (plist (doom-package-plist package))
|
||||
(if (plist-member plist prop)
|
||||
(plist-get plist prop)
|
||||
nil-value)
|
||||
nil-value))
|
||||
(defun doom-package-depending-on (package &optional noerror)
|
||||
"Return a list of packages that depend on the package named NAME."
|
||||
(cl-check-type name symbol)
|
||||
;; can't get dependencies for built-in packages
|
||||
(unless (or (doom-package-build-recipe name)
|
||||
noerror)
|
||||
(error "Couldn't find %s, is it installed?" name))
|
||||
(cl-loop for pkg in (hash-table-keys straight--build-cache)
|
||||
for deps = (doom-package-dependencies pkg)
|
||||
if (memq package deps)
|
||||
collect pkg
|
||||
and append (doom-package-depending-on pkg t)))
|
||||
|
||||
|
||||
;;
|
||||
|
@ -131,99 +70,52 @@ exist/isn't specified."
|
|||
;;;###autoload
|
||||
(defun doom-package-built-in-p (package)
|
||||
"Return non-nil if PACKAGE (a symbol) is built-in."
|
||||
(unless (doom-package-installed-p package)
|
||||
(or (package-built-in-p (doom-package-true-name package))
|
||||
(locate-library (symbol-name package) nil doom-site-load-path))))
|
||||
(eq (doom-package-build-recipe package :type)
|
||||
'built-in))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-installed-p (package)
|
||||
"Return non-nil if PACKAGE (a symbol) is installed."
|
||||
(when-let (desc (doom-package-desc package))
|
||||
(and (package-installed-p desc)
|
||||
(file-directory-p (package-desc-dir desc)))))
|
||||
(file-directory-p (straight--build-dir (symbol-name package))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-registered-p (package)
|
||||
"Return non-nil if PACKAGE (a symbol) has been registered with `package!'.
|
||||
|
||||
Excludes packages that have a non-nil :built-in property."
|
||||
(let ((package (or (cl-loop for (pkg . plist) in doom-packages
|
||||
for newname = (car (plist-get plist :recipe))
|
||||
if (and (symbolp newname)
|
||||
(eq newname package))
|
||||
return pkg)
|
||||
package)))
|
||||
(when-let (plist (doom-package-plist package))
|
||||
(not (eval (plist-get plist :ignore))))))
|
||||
(when-let (plist (doom-package-get package))
|
||||
(not (eval (plist-get plist :ignore) t))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-private-p (package)
|
||||
"Return non-nil if PACKAGE was installed by the user's private config."
|
||||
(doom-package-prop package :private))
|
||||
(doom-package-get package :private))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-protected-p (package)
|
||||
"Return non-nil if PACKAGE is protected.
|
||||
|
||||
A protected package cannot be deleted and will be auto-installed if missing."
|
||||
(memq (doom-package-true-name package) doom-core-packages))
|
||||
(memq package doom-core-packages))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-core-p (package)
|
||||
"Return non-nil if PACKAGE is a core Doom package."
|
||||
(or (doom-package-protected-p package)
|
||||
(assq :core (doom-package-prop package :modules))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-different-backend-p (package)
|
||||
"Return t if a PACKAGE (a symbol) has a new backend than what it was installed
|
||||
with. Returns nil otherwise, or if package isn't installed."
|
||||
(cl-check-type package symbol)
|
||||
(and (doom-package-installed-p package)
|
||||
(not (doom-get-depending-on package)) ; not a dependency
|
||||
(not (eq (doom-package-backend package 'noerror)
|
||||
(doom-package-recipe-backend package 'noerror)))))
|
||||
(assq :core (doom-package-get package :modules))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-package-different-recipe-p (name)
|
||||
"Return t if a package named NAME (a symbol) has a different recipe than it
|
||||
was installed with."
|
||||
(cl-check-type name symbol)
|
||||
(when (doom-package-installed-p name)
|
||||
(let ((package-truename (doom-package-true-name name)))
|
||||
(when-let* ((quelpa-recipe (assq package-truename quelpa-cache))
|
||||
(doom-recipe (assq package-truename doom-packages)))
|
||||
(not (equal (cdr quelpa-recipe)
|
||||
(cdr (plist-get (cdr doom-recipe) :recipe))))))))
|
||||
|
||||
(defvar quelpa-upgrade-p)
|
||||
;;;###autoload
|
||||
(defun doom-package-outdated-p (name)
|
||||
"Determine whether NAME (a symbol) is outdated or not.
|
||||
|
||||
If outdated, returns a list, whose car is NAME, and cdr the current version list
|
||||
and latest version list of the package."
|
||||
(cl-check-type name symbol)
|
||||
(when-let (desc (doom-package-desc name))
|
||||
(let* ((old-version (package-desc-version desc))
|
||||
(new-version
|
||||
(pcase (doom-package-backend name)
|
||||
(`quelpa
|
||||
(let ((recipe (doom-package-prop name :recipe))
|
||||
(dir (expand-file-name (symbol-name name) quelpa-build-dir))
|
||||
(inhibit-message (not doom-debug-mode))
|
||||
(quelpa-upgrade-p t))
|
||||
(if-let (ver (quelpa-checkout recipe dir))
|
||||
(version-to-list ver)
|
||||
old-version)))
|
||||
(`elpa
|
||||
(let ((desc (cadr (assq name package-archive-contents))))
|
||||
(when (package-desc-p desc)
|
||||
(package-desc-version desc)))))))
|
||||
(unless (and (listp old-version) (listp new-version))
|
||||
(error "Couldn't get version for %s" name))
|
||||
(when (version-list-< old-version new-version)
|
||||
(list name old-version new-version)))))
|
||||
;; TODO
|
||||
;; (when (doom-package-installed-p name)
|
||||
;; (when-let* ((doom-recipe (assq name doom-packages))
|
||||
;; (install-recipe (doom-package-recipe)))
|
||||
;; (not (equal (cdr quelpa-recipe)
|
||||
;; (cdr (plist-get (cdr doom-recipe) :recipe))))))
|
||||
)
|
||||
|
||||
|
||||
;;
|
||||
|
@ -307,32 +199,37 @@ files."
|
|||
collect (cons sym plist)
|
||||
and if (and deps (not (doom-package-built-in-p sym)))
|
||||
nconc
|
||||
(cl-loop for pkg in (doom-get-dependencies-for sym 'recursive 'noerror)
|
||||
(cl-loop for pkg in (doom-package-dependencies sym 'recursive 'noerror)
|
||||
if (or (eq installed 'any)
|
||||
(if installed
|
||||
(doom-package-installed-p pkg)
|
||||
(not (doom-package-installed-p pkg))))
|
||||
collect (cons pkg (cdr (assq pkg doom-packages)))))))
|
||||
|
||||
(defun doom--read-module-packages-file (file &optional raw noerror)
|
||||
(defun doom--read-module-packages-file (file &optional eval noerror)
|
||||
(with-temp-buffer ; prevent buffer-local settings from propagating
|
||||
(condition-case e
|
||||
(if (not raw)
|
||||
(if (not eval)
|
||||
(load file noerror t t)
|
||||
(when (file-readable-p file)
|
||||
(insert-file-contents file)
|
||||
(delay-mode-hooks (emacs-lisp-mode))
|
||||
(while (re-search-forward "(package! " nil t)
|
||||
(save-excursion
|
||||
(goto-char (match-beginning 0))
|
||||
(cl-destructuring-bind (name . plist) (cdr (sexp-at-point))
|
||||
(push (cons name
|
||||
(plist-put plist :modules
|
||||
(cond ((file-in-directory-p file doom-private-dir)
|
||||
'((:private)))
|
||||
((file-in-directory-p file doom-core-dir)
|
||||
'((:core)))
|
||||
((doom-module-from-path file)))))
|
||||
doom-packages))))))
|
||||
(unless (string-match-p
|
||||
"^.*;" (buffer-substring-no-properties
|
||||
(line-beginning-position)
|
||||
(point)))
|
||||
(cl-destructuring-bind (name . plist) (cdr (sexp-at-point))
|
||||
(push (cons name
|
||||
(plist-put plist :modules
|
||||
(cond ((file-in-directory-p file doom-private-dir)
|
||||
'((:private)))
|
||||
((file-in-directory-p file doom-core-dir)
|
||||
'((:core)))
|
||||
((doom-module-from-path file)))))
|
||||
doom-packages)))))))
|
||||
((debug error)
|
||||
(signal 'doom-package-error
|
||||
(list (or (doom-module-from-path file)
|
||||
|
@ -350,15 +247,16 @@ ones."
|
|||
(let ((noninteractive t)
|
||||
(doom-modules (doom-modules))
|
||||
doom-packages
|
||||
doom-disabled-packages
|
||||
package-pinned-packages)
|
||||
(doom--read-module-packages-file (expand-file-name "packages.el" doom-core-dir) all-p)
|
||||
doom-disabled-packages)
|
||||
(doom--read-module-packages-file
|
||||
(expand-file-name "packages.el" doom-core-dir)
|
||||
all-p t)
|
||||
(let ((private-packages (expand-file-name "packages.el" doom-private-dir)))
|
||||
(unless all-p
|
||||
;; 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.
|
||||
(doom--read-module-packages-file private-packages nil t))
|
||||
(doom--read-module-packages-file private-packages t t))
|
||||
(if all-p
|
||||
(mapc #'doom--read-module-packages-file
|
||||
(doom-files-in doom-modules-dir
|
||||
|
@ -371,192 +269,11 @@ ones."
|
|||
for doom--current-module = key
|
||||
do (doom--read-module-packages-file path nil t)))
|
||||
(doom--read-module-packages-file private-packages all-p t))
|
||||
(append (cl-loop for package in doom-core-packages
|
||||
collect (list package :modules '((:core internal))))
|
||||
(nreverse doom-packages))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-get-package-alist ()
|
||||
"Returns a list of all desired packages, their dependencies and their desc
|
||||
objects, in the order of their `package! blocks.'"
|
||||
(cl-remove-duplicates
|
||||
(cl-loop for name in (mapcar #'car doom-packages)
|
||||
if (assq name package-alist)
|
||||
nconc (cl-loop for dep in (package--get-deps name)
|
||||
if (assq dep package-alist)
|
||||
collect (cons dep (cadr it)))
|
||||
and collect (cons name (cadr it)))
|
||||
:key #'car
|
||||
:from-end t))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-get-depending-on (name &optional noerror)
|
||||
"Return a list of packages that depend on the package named NAME."
|
||||
(cl-check-type name symbol)
|
||||
(setq name (or (car (doom-package-prop name :recipe)) name))
|
||||
(unless (doom-package-built-in-p name)
|
||||
(if-let (desc (cadr (assq name package-alist)))
|
||||
(mapcar #'package-desc-name (package--used-elsewhere-p desc nil t))
|
||||
(unless noerror
|
||||
(error "Couldn't find %s, is it installed?" name)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-get-dependencies-for (name &optional recursive noerror)
|
||||
"Return a list of dependencies for a package."
|
||||
(cl-check-type name symbol)
|
||||
;; can't get dependencies for built-in packages
|
||||
(unless (doom-package-built-in-p name)
|
||||
(if-let (desc (doom-package-desc name))
|
||||
(let* ((deps (mapcar #'car (package-desc-reqs desc)))
|
||||
(deps (cl-remove-if #'doom-package-built-in-p deps)))
|
||||
(if recursive
|
||||
(nconc deps (mapcan (lambda (dep) (doom-get-dependencies-for dep t t))
|
||||
deps))
|
||||
deps))
|
||||
(unless noerror
|
||||
(error "Couldn't find %s, is it installed?" name)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-get-outdated-packages (&optional include-frozen-p)
|
||||
"Return a list of packages that are out of date. Each element is a list,
|
||||
containing (PACKAGE-SYMBOL OLD-VERSION-LIST NEW-VERSION-LIST).
|
||||
|
||||
If INCLUDE-FROZEN-P is non-nil, check frozen packages as well.
|
||||
|
||||
Used by `doom-packages-update'."
|
||||
(doom-refresh-packages-maybe doom-debug-mode)
|
||||
(cl-loop for package in (mapcar #'car package-alist)
|
||||
when (and (or (not (eval (doom-package-prop package :freeze)))
|
||||
include-frozen-p)
|
||||
(not (eval (doom-package-prop package :ignore)))
|
||||
(not (doom-package-different-backend-p package))
|
||||
(doom-package-outdated-p package))
|
||||
collect it))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-get-orphaned-packages ()
|
||||
"Return a list of symbols representing packages that are no longer needed or
|
||||
depended on.
|
||||
|
||||
Used by `doom-packages-autoremove'."
|
||||
(let ((package-selected-packages
|
||||
(mapcar #'car (doom-find-packages :ignored nil :disabled nil))))
|
||||
(append (cl-remove-if #'doom-package-registered-p (package--removable-packages))
|
||||
(cl-loop for pkg in package-selected-packages
|
||||
if (and (doom-package-different-backend-p pkg)
|
||||
(not (doom-package-built-in-p pkg)))
|
||||
collect pkg))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-get-missing-packages ()
|
||||
"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
|
||||
`package!' declaration.
|
||||
|
||||
Used by `doom-packages-install'."
|
||||
(cl-loop for (name . plist)
|
||||
in (doom-find-packages :ignored nil
|
||||
:disabled nil
|
||||
:deps t)
|
||||
if (and (equal (plist-get plist :pin)
|
||||
(ignore-errors
|
||||
(package-desc-archive
|
||||
(cadr (assq name package-alist)))))
|
||||
(or (not (doom-package-installed-p name))
|
||||
(doom-package-different-backend-p name)
|
||||
(doom-package-different-recipe-p name)))
|
||||
collect (cons name plist)))
|
||||
(nreverse doom-packages)))
|
||||
|
||||
|
||||
;;
|
||||
;; Main functions
|
||||
|
||||
(defun doom--delete-package-files (name-or-desc)
|
||||
(let ((pkg-build-dir
|
||||
(if (package-desc-p name-or-desc)
|
||||
(package-desc-dir name-or-desc)
|
||||
(expand-file-name (symbol-name name-or-desc) quelpa-build-dir))))
|
||||
(when (file-directory-p pkg-build-dir)
|
||||
(delete-directory pkg-build-dir t))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-install-package (name &optional plist)
|
||||
"Installs package NAME with optional quelpa RECIPE (see `quelpa-recipe' for an
|
||||
example; the package name can be omitted)."
|
||||
(cl-check-type name symbol)
|
||||
(when (and (doom-package-installed-p name)
|
||||
(not (doom-package-built-in-p name)))
|
||||
(if (or (doom-package-different-backend-p name)
|
||||
(doom-package-different-recipe-p name))
|
||||
(doom-delete-package name t)
|
||||
(user-error "%s is already installed" name)))
|
||||
(let* ((inhibit-message (not doom-debug-mode))
|
||||
(plist (or plist (doom-package-plist name))))
|
||||
(if-let (recipe (plist-get plist :recipe))
|
||||
(condition-case e
|
||||
(let (quelpa-upgrade-p)
|
||||
(quelpa recipe))
|
||||
((debug error)
|
||||
(doom--delete-package-files name)
|
||||
(signal (car e) (cdr e))))
|
||||
(package-install name))
|
||||
(if (not (doom-package-installed-p name))
|
||||
(doom--delete-package-files name)
|
||||
(add-to-list 'package-selected-packages name nil 'eq)
|
||||
(setf (alist-get name doom-packages) plist)
|
||||
name)))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-update-package (name &optional force-p)
|
||||
"Updates package NAME (a symbol) if it is out of date, using quelpa or
|
||||
package.el as appropriate."
|
||||
(cl-check-type name symbol)
|
||||
(unless (doom-package-installed-p name)
|
||||
(error "%s isn't installed" name))
|
||||
(when (doom-package-different-backend-p name)
|
||||
(user-error "%s's backend has changed and must be uninstalled first" name))
|
||||
(when (or force-p (doom-package-outdated-p name))
|
||||
(let ((inhibit-message (not doom-debug-mode))
|
||||
(desc (doom-package-desc name)))
|
||||
(pcase (doom-package-backend name)
|
||||
(`quelpa
|
||||
(let ((name (doom-package-true-name name)))
|
||||
(condition-case e
|
||||
(let ((quelpa-upgrade-p t))
|
||||
(quelpa (assq name quelpa-cache)))
|
||||
((debug error)
|
||||
(doom--delete-package-files name)
|
||||
(signal (car e) (cdr e))))))
|
||||
(`elpa
|
||||
(let* ((archive (cadr (assq name package-archive-contents)))
|
||||
(packages
|
||||
(if (package-desc-p archive)
|
||||
(package-compute-transaction (list archive) (package-desc-reqs archive))
|
||||
(package-compute-transaction () (list (list archive))))))
|
||||
(package-download-transaction packages))))
|
||||
(unless (doom-package-outdated-p name)
|
||||
(doom--delete-package-files desc)
|
||||
t))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-delete-package (name &optional force-p)
|
||||
"Uninstalls package NAME if it exists, and clears it from `quelpa-cache'."
|
||||
(cl-check-type name symbol)
|
||||
(unless (doom-package-installed-p name)
|
||||
(user-error "%s isn't installed" name))
|
||||
(let ((inhibit-message (not doom-debug-mode))
|
||||
(name (doom-package-true-name name)))
|
||||
(when-let (spec (assq name quelpa-cache))
|
||||
(delq! spec quelpa-cache)
|
||||
(quelpa-save-cache))
|
||||
(package-delete (doom-package-desc name) force-p)
|
||||
(doom--delete-package-files name)
|
||||
(not (doom-package-installed-p name))))
|
||||
|
||||
|
||||
;;
|
||||
;; Interactive commands
|
||||
;;; Main functions
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/reload-packages ()
|
||||
|
@ -565,61 +282,3 @@ package.el as appropriate."
|
|||
(message "Reloading packages")
|
||||
(doom-initialize-packages t)
|
||||
(message "Reloading packages...DONE"))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/update-package (pkg)
|
||||
"Prompts the user with a list of outdated packages and updates the selected
|
||||
package. Use this interactively. Use `doom-update-package' for direct
|
||||
calls."
|
||||
(declare (interactive-only t))
|
||||
(interactive
|
||||
(let* ((packages (doom-get-outdated-packages))
|
||||
(selection (if packages
|
||||
(completing-read "Update package: "
|
||||
(mapcar #'car packages)
|
||||
nil t)
|
||||
(user-error "All packages are up to date")))
|
||||
(name (car (assoc (intern selection) package-alist))))
|
||||
(unless name
|
||||
(user-error "'%s' is already up-to-date" selection))
|
||||
(list (assq name packages))))
|
||||
(cl-destructuring-bind (package old-version new-version) pkg
|
||||
(if-let (desc (doom-package-outdated-p package))
|
||||
(let ((old-v-str (package-version-join old-version))
|
||||
(new-v-str (package-version-join new-version)))
|
||||
(if (y-or-n-p (format "%s will be updated from %s to %s. Update?"
|
||||
package old-v-str new-v-str))
|
||||
(message "%s %s (%s => %s)"
|
||||
(if (doom-update-package package t) "Updated" "Failed to update")
|
||||
package old-v-str new-v-str)
|
||||
(message "Aborted")))
|
||||
(message "%s is up-to-date" package))))
|
||||
|
||||
|
||||
;;
|
||||
;; Advice
|
||||
|
||||
;;;###autoload
|
||||
(defun doom*package-delete (desc &rest _)
|
||||
"Update `quelpa-cache' upon a successful `package-delete'."
|
||||
(let ((name (package-desc-name desc)))
|
||||
(unless (doom-package-installed-p name)
|
||||
(when-let (spec (assq name quelpa-cache))
|
||||
(setq quelpa-cache (delq spec quelpa-cache))
|
||||
(quelpa-save-cache)
|
||||
(doom--delete-package-files name)))))
|
||||
|
||||
|
||||
;;
|
||||
;; Make package.el cooperate with Doom
|
||||
|
||||
;; Updates QUELPA after deleting a package
|
||||
;;;###autoload
|
||||
(advice-add #'package-delete :after #'doom*package-delete)
|
||||
|
||||
;; Replace with Doom variants
|
||||
;;;###autoload
|
||||
(advice-add #'package-autoremove :override #'doom//autoremove)
|
||||
|
||||
;;;###autoload
|
||||
(advice-add #'package-install-selected-packages :override #'doom//install)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue