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

View file

@ -49,7 +49,10 @@ OPTIONS:
(add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h) (add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h)
(when jobs (when jobs
(setq native-comp-async-jobs-number (truncate 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 (unwind-protect
(print-group! (print-group!
(when (and (not noenvvar?) (when (and (not noenvvar?)

View file

@ -39,6 +39,20 @@
;; Ensure errors are sufficiently detailed from this point on. ;; Ensure errors are sufficiently detailed from this point on.
(setq debug-on-error t) (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 ;; HACK Load `cl' and site files manually to prevent polluting logs and stdout
;; with deprecation and/or file load messages. ;; with deprecation and/or file load messages.
(let ((inhibit-message (not (or (getenv "DEBUG") init-file-debug)))) (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/") (defconst doom-modules-dir (concat doom-emacs-dir "modules/")
"The root directory for Doom's modules. Must end with a slash.") "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/") (defconst doom-docs-dir (concat doom-emacs-dir "docs/")
"Where Doom's documentation files are stored. Must end with a slash.") "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; Defaults to ~/.config/doom, ~/.doom.d or the value of the DOOMDIR envvar;
whichever is found first. Must end in a slash.") 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 (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. "Where `doom-reload-core-autoloads' stores its core autoloads.
This file is responsible for informing Emacs where to find all of Doom's This file is responsible for informing Emacs where to find all of Doom's
autoloaded core functions (in core/autoload/*.el).") 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`. "The location of your envvar file, generated by `doom env`.
This file contains environment variables scraped from your shell environment, This file contains environment variables scraped from your shell environment,

View file

@ -121,18 +121,17 @@
(setq user-emacs-directory profile-dir) (setq user-emacs-directory profile-dir)
(throw 'found t))) (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 ;;; Bootstrap
;; Let er rip
(let (init-file)
;; Load the heart of Doom Emacs ;; Load the heart of Doom Emacs
(if (load (expand-file-name "core/core" user-emacs-directory) t t) (unless (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))
;; ...but if that fails, then this is likely not a Doom config. ;; ...but if that fails, then this is likely not a Doom config.
(setq early-init-file (expand-file-name "early-init" user-emacs-directory)) (setq early-init-file (expand-file-name "early-init" user-emacs-directory))
(load early-init-file t t)) (load early-init-file t t))
@ -156,9 +155,12 @@
(define-advice startup--load-user-init-file (:filter-args (args) init-doom) (define-advice startup--load-user-init-file (:filter-args (args) init-doom)
"Initialize Doom Emacs in an interactive session." "Initialize Doom Emacs in an interactive session."
(list (lambda () (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))) (expand-file-name "init.el" user-emacs-directory)))
nil ; TODO Replace with safe mode initfile (when (boundp 'doom-profiles-dir)
(caddr args)))) (lambda ()
(expand-file-name "safe-mode@static/init.el" doom-profiles-dir)))
(caddr args)))
;;; early-init.el ends here ;;; early-init.el ends here