Change envvar file format

Storing it as a sexp eliminates the need to parse it.

Fixes #4802
This commit is contained in:
Henrik Lissner 2021-03-17 18:47:08 -04:00
parent 46dedb3e33
commit 763d0b670c
2 changed files with 49 additions and 61 deletions

View File

@ -45,16 +45,12 @@ Why this over exec-path-from-shell?
(if (null clear-p)
(doom-cli-reload-env-file
'force env-file
(append (if reject-only (list "."))
(delq nil (list allow allow-only)))
(append (if allow-only (list "."))
(delq nil (list reject reject-only))))
(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)))
(user-error! "%S does not exist to be cleared" (path env-file)))
(delete-file env-file)
(print! (success "Successfully deleted %S")
(path env-file)))))
(print! (success "Successfully deleted %S") (path env-file)))))
;;
@ -88,8 +84,7 @@ 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 (if env-file (expand-file-name env-file) doom-env-file))
(process-environment doom--initial-process-environment))
(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)
@ -104,34 +99,38 @@ default, on Linux, this is '$SHELL -ic /usr/bin/env'. Variables in
(goto-char (point-min))
(insert
(concat
"# -*- mode: sh; 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"
";; -*- 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 remember to preserve the null bytes at\n"
"# the end of each line! 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\0\n"))
(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 we just dump
;; user's interactive shell, therefore simply dump
;; `process-environment' to a file.
(dolist (env process-environment)
(if (cl-find-if (doom-rpartial #'string-match-p (car (split-string env "=")))
(remq nil (append blacklist doom-env-blacklist)))
(if (not (cl-find-if (doom-rpartial #'string-match-p (car (split-string env "=")))
(remq nil (append whitelist doom-env-whitelist))))
(print! (debug "Ignoring %s") env)
(print! (debug "Whitelisted %s") env)
(insert env "\0\n"))
(insert env "\0\n")))
(print! (success "Successfully generated %S")
(path env-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 doom--initial-process-environment)
(let* ((var (car (split-string env "=")))
(pred (doom-rpartial #'string-match-p var)))
(if (seq-find pred blacklist)
(doom-log "Ignoring %s" var)
(when (seq-find pred whitelist)
(doom-log "Whitelisted %s" var))
(insert (prin1-to-string env) "\n "))))
(insert ")"))
(print! (success "Successfully generated %S") (path env-file))
t)))))

View File

@ -475,30 +475,19 @@ unreadable. Returns the names of envvars that were changed."
(if (null (file-exists-p file))
(unless noerror
(signal 'file-error (list "No envvar file exists" file)))
(when-let
(env
(with-temp-buffer
(save-excursion
(setq-local coding-system-for-read 'utf-8)
(insert "\0\n") ; to prevent off-by-one
(insert-file-contents file))
(save-match-data
(when (re-search-forward "\0\n *\\([^#= \n]*\\)=" nil t)
(setq
env (split-string (buffer-substring (match-beginning 1) (point-max))
"\0\n"
'omit-nulls))))))
(setq-default
process-environment
(append (nreverse env)
(default-value 'process-environment))
exec-path
(append (split-string (getenv "PATH") path-separator t)
(list exec-directory))
shell-file-name
(or (getenv "SHELL")
(default-value 'shell-file-name)))
env)))
(with-temp-buffer
(insert-file-contents file)
(when-let (env (read (current-buffer)))
(setq-default
process-environment
(append env (default-value 'process-environment))
exec-path
(append (split-string (getenv "PATH") path-separator t)
(list exec-directory))
shell-file-name
(or (getenv "SHELL")
(default-value 'shell-file-name)))
env))))
(defun doom-try-run-hook (hook)
"Run HOOK (a hook function) with better error handling.