From 763d0b670ca0a05c65a3353ebd794a4edae8ff71 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 17 Mar 2021 18:47:08 -0400 Subject: [PATCH] Change envvar file format Storing it as a sexp eliminates the need to parse it. Fixes #4802 --- core/cli/env.el | 73 ++++++++++++++++++++++++------------------------- core/core.el | 37 +++++++++---------------- 2 files changed, 49 insertions(+), 61 deletions(-) diff --git a/core/cli/env.el b/core/cli/env.el index 6f98708fd..5be59a6f1 100644 --- a/core/cli/env.el +++ b/core/cli/env.el @@ -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))))) diff --git a/core/core.el b/core/core.el index e0b75aa87..2e9c125ef 100644 --- a/core/core.el +++ b/core/core.el @@ -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.