From 9f4556182568fe84fb5aa11902d8b7b33dbb752c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Tue, 18 Aug 2020 18:45:37 -0400 Subject: [PATCH] bin/doom: inhibit POSIX errors during postscript Some doom commands will generate a temporary script at ~/.emacs.d/.local/.doom.sh so that it can run an arbitrary shell command after the current invocation of bin/doom ends. Very useful for, say, restarting the currently running doom command after a destructive operation, like updating Doom's source code, tangling your literate config, or for launching arbitrary programs, like a new instance of Emacs. This is necessary because elisp lacks an execv implementation. However, for some folks, .doom.sh wasn't executing at all. This meant: 1. Some `doom upgrade`s would upgrade Doom itself but never move on to the second step of the process: updating its packages. 2. Literate config users could tangle their configs on `doom sync`, but the actual syncing process would never happen (#3746). 3. `doom run` would do nothing. I hadn't realized /bin/sh runs bash in POSIX mode (at least, on systems where /bin/sh = bash, like nixOS or macOS). In POSIX mode the script will abort the if a builtin command (like export) returns a non-zero exit code. Since .doom.sh is basically a bunch of exports followed by an arbitrary command, and there are some environment variables that can trigger validation errors (like UID triggering a "read-only variable" error), we have a problem. Hopefully addresses #3746 --- core/core-cli.el | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/core/core-cli.el b/core/core-cli.el index 2e31515d1..a8cc89ab5 100644 --- a/core/core-cli.el +++ b/core/core-cli.el @@ -172,17 +172,18 @@ COMMAND, and passes ARGS to it." (defun doom-cli--execute-after (lines) (let ((post-script (concat doom-local-dir ".doom.sh")) (coding-system-for-write 'utf-8) - (coding-system-for-read 'utf-8)) + (coding-system-for-read 'utf-8) + (delimiter "--%EOF%--")) (with-temp-file post-script - (insert "#!/usr/bin/env sh\n" - (save-match-data + (insert (save-match-data (cl-loop for env in process-environment if (string-match "^\\([a-zA-Z0-9_]+\\)=\\(.+\\)$" env) - concat (format "export %s=%s;\n" + concat (format "%s=%s \\\n" (match-string 1 env) (shell-quote-argument (match-string 2 env))))) - (format "\nexport PATH=\"%s:$PATH\"\n" (concat doom-emacs-dir "bin/")) - "\n[ -x \"$0\" ] && rm -f \"$0\"\n" + (format "PATH=\"%s:$PATH\" \\\n" (concat doom-emacs-dir "bin/")) + "/usr/bin/env sh <<" delimiter "\n" + "rm -f " (shell-quote-argument post-script) "\n" (if (stringp lines) lines (string-join @@ -191,7 +192,7 @@ COMMAND, and passes ARGS to it." collect (mapconcat #'shell-quote-argument (remq nil line) " ")) (list (mapconcat #'shell-quote-argument (remq nil lines) " "))) "\n")) - "\n")) + "\n" delimiter "\n")) (set-file-modes post-script #o700))) (defun doom-cli-execute-lines-after (&rest lines)