So they don't interfere with straight in odd, unpredictable ways. If you *really* know what you're doing, set DOOMGITCONFIG to the path of a gitconfig file. This envvar may be renamed in the future, however. Close: #5640 Co-authored-by: M. Yas. Davoodeh <Davoodeh@users.noreply.github.com>
141 lines
6.8 KiB
EmacsLisp
141 lines
6.8 KiB
EmacsLisp
;;; core/cli/env.el -*- lexical-binding: t; -*-
|
|
|
|
(defcli! env
|
|
((allow ["-a" "--allow" regexp] "An additive envvar whitelist regexp")
|
|
(reject ["-r" "--reject" regexp] "An additive envvar blacklist regexp")
|
|
(allow-only ["-A" regexp] "Blacklist everything but REGEXP")
|
|
(reject-only ["-R" regexp] "Whitelist everything but REGEXP")
|
|
(clear-p ["-c" "--clear"] "Clear and delete your envvar file")
|
|
(outputfile ["-o" path]
|
|
"Generate the envvar file at PATH. Envvar files that aren't in
|
|
`doom-env-file' won't be loaded automatically at startup. You will need to load
|
|
them manually from your private config with the `doom-load-envvars-file'
|
|
function."))
|
|
"Creates or regenerates your envvars file.
|
|
|
|
The envvars file is created by scraping the current shell environment into
|
|
newline-delimited KEY=VALUE pairs. Typically by running '$SHELL -ic env' (or
|
|
'$SHELL -c set' on windows). Doom loads this file at startup (if it exists) to
|
|
ensure Emacs mirrors your shell environment (particularly to ensure PATH and
|
|
SHELL are correctly set).
|
|
|
|
This is useful in cases where you cannot guarantee that Emacs (or the daemon)
|
|
will be launched from the correct environment (e.g. on MacOS or through certain
|
|
app launchers on Linux).
|
|
|
|
This file is automatically regenerated when you run this command or 'doom sync'.
|
|
However, 'doom sync' will only regenerate this file if it exists.
|
|
|
|
Why this over exec-path-from-shell?
|
|
|
|
1. `exec-path-from-shell' spawns (at least) one process at startup to scrape
|
|
your shell environment. This can be arbitrarily slow depending on the
|
|
user's shell configuration. A single program (like pyenv or nvm) or config
|
|
framework (like oh-my-zsh) could undo all of Doom's startup optimizations
|
|
in one fell swoop.
|
|
|
|
2. `exec-path-from-shell' only scrapes some state from your shell. You have to
|
|
be proactive in order to get it to capture all the envvars relevant to your
|
|
development environment.
|
|
|
|
I'd rather it inherit your shell environment /correctly/ (and /completely/)
|
|
or not at all. It frontloads the debugging process rather than hiding it
|
|
until you least want to deal with it."
|
|
(let ((env-file (expand-file-name (or outputfile doom-env-file))))
|
|
(if (null clear-p)
|
|
(doom-cli-reload-env-file
|
|
'force env-file
|
|
(append (if reject-only (list ".")) (list allow allow-only))
|
|
(append (if allow-only (list ".")) (list reject reject-only)))
|
|
(unless (file-exists-p env-file)
|
|
(user-error! "%S does not exist to be cleared" (path env-file)))
|
|
(delete-file env-file)
|
|
(print! (success "Successfully deleted %S") (path env-file)))))
|
|
|
|
|
|
;;
|
|
;; Helpers
|
|
|
|
(defvar doom-env-blacklist
|
|
'(;; State that may be problematic if overwritten
|
|
"^HOME$" "^\\(OLD\\)?PWD$" "^SHLVL$" "^PS1$" "^R?PROMPT$" "^TERM\\(CAP\\)?$"
|
|
"^USER$" "^GIT_CONFIG"
|
|
;; X server or services' variables that shouldn't be persisted
|
|
"^DISPLAY$" "^DBUS_SESSION_BUS_ADDRESS$" "^XAUTHORITY$" "^XDG_SESSION_TYPE$"
|
|
;; Windows+WSL envvars that shouldn't be persisted
|
|
"^WSL_INTEROP$"
|
|
;; ssh and gpg variables (likely to become stale)
|
|
"^SSH_\\(AUTH_SOCK\\|AGENT_PID\\)$" "^\\(SSH\\|GPG\\)_TTY$"
|
|
"^GPG_AGENT_INFO$"
|
|
;; Internal Doom envvars
|
|
"^DEBUG$" "^INSECURE$" "^YES$" "^__")
|
|
"Environment variables to not save in `doom-env-file'.
|
|
|
|
Each string is a regexp, matched against variable names to omit from
|
|
`doom-env-file'.")
|
|
|
|
(defvar doom-env-whitelist '()
|
|
"A whitelist for envvars to save in `doom-env-file'.
|
|
|
|
This overrules `doom-env-ignored-vars'. Each string is a regexp, matched against
|
|
variable names to omit from `doom-env-file'.")
|
|
|
|
(defun doom-cli-reload-env-file (&optional force-p env-file whitelist blacklist)
|
|
"Generates `doom-env-file', if it doesn't exist (or if FORCE-P).
|
|
|
|
This scrapes the variables from your shell environment by running
|
|
`doom-env-executable' through `shell-file-name' with `doom-env-switches'. By
|
|
default, on Linux, this is '$SHELL -ic /usr/bin/env'. Variables in
|
|
`doom-env-ignored-vars' are removed."
|
|
(let ((env-file (expand-file-name (or env-file doom-env-file))))
|
|
(when (or force-p (not (file-exists-p env-file)))
|
|
(with-temp-file env-file
|
|
(setq-local coding-system-for-write 'utf-8-unix)
|
|
(print! (start "%s envvars file at %S")
|
|
(if (file-exists-p env-file)
|
|
"Regenerating"
|
|
"Generating")
|
|
(path env-file))
|
|
(print-group!
|
|
(when doom-interactive-p
|
|
(user-error "'doom env' must be run on the command line, not an interactive session"))
|
|
(goto-char (point-min))
|
|
(insert
|
|
(concat
|
|
";; -*- mode: lisp-interaction; coding: utf-8-unix; -*-\n"
|
|
";; ---------------------------------------------------------------------------\n"
|
|
";; This file was auto-generated by `doom env'. It contains a list of environment\n"
|
|
";; variables scraped from your default shell (excluding variables blacklisted\n"
|
|
";; in doom-env-ignored-vars).\n"
|
|
";;\n"
|
|
(if (file-equal-p env-file doom-env-file)
|
|
(concat ";; It is NOT safe to edit this file. Changes will be overwritten next time you\n"
|
|
";; run 'doom sync'. To create a safe-to-edit envvar file use:\n;;\n"
|
|
";; doom env -o ~/.doom.d/myenv\n;;\n"
|
|
";; And load it with (doom-load-envvars-file \"~/.doom.d/myenv\").\n")
|
|
(concat ";; This file is safe to edit by hand, but needs to be loaded manually with:\n;;\n"
|
|
";; (doom-load-envvars-file \"path/to/this/file\")\n;;\n"
|
|
";; Use 'doom env -o path/to/this/file' to regenerate it."))
|
|
"\n"))
|
|
;; We assume that this noninteractive session was spawned from the
|
|
;; user's interactive shell, therefore simply dump
|
|
;; `process-environment' to a file.
|
|
;;
|
|
;; This file should be somewhat formatted, so humans could hand-modify
|
|
;; it if they please.
|
|
(let ((blacklist (remq nil (append blacklist doom-env-blacklist)))
|
|
(whitelist (remq nil (append whitelist doom-env-whitelist))))
|
|
(insert "(")
|
|
(dolist (env (get 'process-environment 'initial-value))
|
|
(catch 'skip
|
|
(let* ((var (car (split-string env "=")))
|
|
(pred (doom-rpartial #'string-match-p var)))
|
|
(when (seq-find pred blacklist)
|
|
(if (seq-find pred whitelist)
|
|
(doom-log "Whitelisted %s" var)
|
|
(doom-log "Ignored %s" var)
|
|
(throw 'skip t)))
|
|
(insert (prin1-to-string env) "\n "))))
|
|
(insert ")"))
|
|
(print! (success "Successfully generated %S") (path env-file))
|
|
t)))))
|