feat: make bin/doom profile aware

- Fixes Doom's former inability to (trivially) juggle multiple profiles
  based on the same EMACSDIR (see #6593).
- Adds '--profile NAME' switch to bin/doom (also recognized
  $DOOMPROFILE).
- Adds new doom-profile* variables. These will eventually replace
  doom-{local,etc,cache}-dir and doom-{autoloads,env}-file.

This is intentionally messy to ensure backwards compatibility for a
little while longer. This will be fixed over the next couple weeks.

Ref: #6593
This commit is contained in:
Henrik Lissner 2022-07-27 22:25:08 +02:00
parent 1ecb5c7b9b
commit 5af38fb08e
No known key found for this signature in database
GPG key ID: B60957CA074D39A3
5 changed files with 154 additions and 67 deletions

View file

@ -180,8 +180,7 @@ SEE ALSO:
(doomdir ("--doomdir" dir) "Use Doom config living in `DIR' (e.g. ~/.doom.d)")
(emacsdir ("--emacsdir" dir) "Use Doom install living in `DIR' (e.g. ~/.emacs.d)")
(pager ("--pager" cmd) "Pager command to use for large output")
;; TODO Implement after v3.0
;; (profile ("--profile" name) "Use profile named NAME")
(profile ("--profile" name) "Use profile named NAME")
&flags
(color? ("--color") "Whether or not to show ANSI color codes")
&multiple
@ -205,13 +204,12 @@ SEE ALSO:
(setq doom-print-backend (if (eq color? :yes) 'ansi)))
;; For these settings to take full effect, the script must be restarted:
(when (and (equal (doom-cli-context-step context) 0)
(or ;; profile
(or profile
debug?
emacsdir
doomdir))
;; TODO Implement after v3.0
;; (when profile
;; (setenv "DOOMPROFILE" profile))
(when profile
(setenv "DOOMPROFILE" profile))
(when debug?
(setenv "DEBUG" "1")
(print! (item "Debug mode enabled")))

View file

@ -49,7 +49,10 @@ OPTIONS:
(add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h)
(when jobs
(setq native-comp-async-jobs-number (truncate jobs)))
(print! (start "Synchronizing your config with Doom Emacs..."))
(print! (start "Synchronizing %S profile..." )
(if doom-profile
(car (split-string doom-profile "@"))
"default"))
(unwind-protect
(print-group!
(when (and (not noenvvar?)

View file

@ -39,6 +39,20 @@
;; Ensure errors are sufficiently detailed from this point on.
(setq debug-on-error t)
;;; Initialize profile
(let ((profile (getenv "DOOMPROFILE")))
(when profile
(with-temp-buffer
(let ((coding-system-for-read 'utf-8-auto))
(insert-file-contents (expand-file-name "profiles.el" user-emacs-directory)))
(condition-case e
(dolist (var (or (cdr (assq (intern profile) (read (current-buffer))))
(user-error "No %S profile found" profile)))
(if (eq var 'env)
(dolist (env var) (setenv (car env) (cdr env)))
(set (car var) (cdr var))))
(error (error "Failed to parse profiles.el: %s" (error-message-string e)))))))
;; HACK Load `cl' and site files manually to prevent polluting logs and stdout
;; with deprecation and/or file load messages.
(let ((inhibit-message (not (or (getenv "DEBUG") init-file-debug))))

View file

@ -128,30 +128,6 @@
(defconst doom-modules-dir (concat doom-emacs-dir "modules/")
"The root directory for Doom's modules. Must end with a slash.")
(defconst doom-local-dir
(if-let (localdir (getenv-internal "DOOMLOCALDIR"))
(expand-file-name (file-name-as-directory localdir))
(concat doom-emacs-dir ".local/"))
"Root directory for local storage.
Use this as a storage location for this system's installation of Doom Emacs.
These files should not be shared across systems. By default, it is used by
`doom-etc-dir' and `doom-cache-dir'. Must end with a slash.")
;; DEPRECATED
(defconst doom-etc-dir (concat doom-local-dir "etc/")
"Directory for non-volatile local storage.
Use this for files that don't change much, like server binaries, external
dependencies or long-term shared data. Must end with a slash.")
;; DEPRECATED
(defconst doom-cache-dir (concat doom-local-dir "cache/")
"Directory for volatile local storage.
Use this for files that change often, like cache files. Must end with a slash.")
(defconst doom-docs-dir (concat doom-emacs-dir "docs/")
"Where Doom's documentation files are stored. Must end with a slash.")
@ -169,15 +145,109 @@ Use this for files that change often, like cache files. Must end with a slash.")
Defaults to ~/.config/doom, ~/.doom.d or the value of the DOOMDIR envvar;
whichever is found first. Must end in a slash.")
;; DEPRECATED
(defconst doom-profile
(if-let (profile (getenv-internal "DOOMPROFILE"))
;; DEPRECATED Use `string-search' once 27 support is dropped
(if (string-match-p "@" profile)
profile
(concat profile "@latest"))
;; TODO Restore this when profile system is complete
;; "default@latest"
)
"The name of the active profile.")
;; TODO Use me
(defconst doom-profiles-file
(expand-file-name "profiles.el" user-emacs-directory)
"TODO")
(defconst doom-profiles-dir
(if-let (profilesdir (getenv-internal "DOOMPROFILESDIR"))
(expand-file-name "./" profilesdir)
(expand-file-name "profiles/" doom-emacs-dir))
"Where Doom stores its profiles.
Profiles are essentially snapshots of Doom Emacs environments. Every time you
update or sync, you create a new generation of a profile (which can be easily
rolled back or switched between with the DOOMPROFILE envvar). Must end in a
slash.")
(defconst doom-profile-dir
(expand-file-name (concat (or doom-profile "default@latest") "/")
doom-profiles-dir)
"The path to the current, active profile.
Must end in a slash.")
(defconst doom-profile-data-dir
(expand-file-name "data/" doom-profile-dir)
"Where file storage/servers for the current, active profile is kept.
Use this for long-living files that contain shared data that the user would
reasonably want to keep, and/or are required for Emacs to function correctly.
Must end in a slash.")
(defconst doom-profile-cache-dir
(expand-file-name "cache/" doom-profile-dir)
"Where file caches for the current, active profile is kept.
Use this for non-essential data files that, when deleted, won't cause breakage
or misbehavior, and can be restored. This includes server binaries or programs
downloaded/installed by packages. Must end in a slash.")
(defconst doom-profile-init-file
(expand-file-name "init.el" doom-profile-dir)
"TODO")
;;
;;; DEPRECATED file/directory vars
(defconst doom-local-dir
(if-let (localdir (getenv-internal "DOOMLOCALDIR"))
(expand-file-name (file-name-as-directory localdir))
(if doom-profile
(expand-file-name doom-profile doom-profiles-dir)
(format "%s.local%s/"
doom-emacs-dir
(if doom-profile (concat "." doom-profile) ""))))
"Root directory for local storage.
Use this as a storage location for this system's installation of Doom Emacs.
These files should not be shared across systems. By default, it is used by
`doom-etc-dir' and `doom-cache-dir'. Must end with a slash.")
(defconst doom-etc-dir
(if doom-profile
doom-profile-data-dir
(concat doom-local-dir "etc/"))
"Directory for non-volatile local storage.
Use this for files that don't change much, like server binaries, external
dependencies or long-term shared data. Must end with a slash.")
(defconst doom-cache-dir
(if doom-profile
doom-profile-cache-dir
(concat doom-local-dir "cache/"))
"Directory for volatile local storage.
Use this for files that change often, like cache files. Must end with a slash.")
(defconst doom-autoloads-file
(concat doom-local-dir "autoloads." emacs-version ".el")
(if doom-profile
doom-profile-init-file
(concat doom-local-dir "autoloads." emacs-version ".el"))
"Where `doom-reload-core-autoloads' stores its core autoloads.
This file is responsible for informing Emacs where to find all of Doom's
autoloaded core functions (in core/autoload/*.el).")
(defconst doom-env-file (concat doom-local-dir "env")
(defconst doom-env-file
(if doom-profile
(expand-file-name "env" doom-profile-dir)
(concat doom-local-dir "env"))
"The location of your envvar file, generated by `doom env`.
This file contains environment variables scraped from your shell environment,

View file

@ -121,18 +121,17 @@
(setq user-emacs-directory profile-dir)
(throw 'found t)))
(user-error "No %S profile found" profile))))))
(user-error "No %S profile found" profile)))
;; Ensure the selected profile persists through the session
(setenv "DOOMPROFILE" profile))))
;;
;;; Bootstrap
;; Let er rip
(let (init-file)
;; Load the heart of Doom Emacs
(if (load (expand-file-name "core/core" user-emacs-directory) t t)
;; ...and prepare it for an interactive session.
(setq init-file (expand-file-name "core-start" doom-core-dir))
(unless (load (expand-file-name "core/core" user-emacs-directory) t t)
;; ...but if that fails, then this is likely not a Doom config.
(setq early-init-file (expand-file-name "early-init" user-emacs-directory))
(load early-init-file t t))
@ -156,9 +155,12 @@
(define-advice startup--load-user-init-file (:filter-args (args) init-doom)
"Initialize Doom Emacs in an interactive session."
(list (lambda ()
(or init-file
(if (boundp 'doom-core-dir)
(expand-file-name "core-start" doom-core-dir)
(expand-file-name "init.el" user-emacs-directory)))
nil ; TODO Replace with safe mode initfile
(caddr args))))
(when (boundp 'doom-profiles-dir)
(lambda ()
(expand-file-name "safe-mode@static/init.el" doom-profiles-dir)))
(caddr args)))
;;; early-init.el ends here