doomemacs/bin/doom
Henrik Lissner fbfc635300
fix(cli): GIT_CONFIG* envvars leaking child processes
When launching Doom via 'doom run', the child process inherits
bin/doom's environment. This change restricts this sub-environment to
the intended target: straight and its use of git.

Fix: #6320
2022-04-21 22:36:36 +02:00

167 lines
7.2 KiB
Bash
Executable File

#!/usr/bin/env sh
:; set -e # -*- mode: emacs-lisp; lexical-binding: t -*-
:; case "$EMACS" in *term*) EMACS=emacs ;; *) EMACS="${EMACS:-emacs}" ;; esac
:; $EMACS --version >/dev/null 2>&1 || { >&2 echo "Can't find emacs in your PATH"; exit 1; }
:; $EMACS --no-site-file --script "$0" -- "$@" || __DOOMCODE=$?
:; [ "${__DOOMCODE:-0}" -eq 128 ] && { sh "`$EMACS -Q --batch --eval '(princ temporary-file-directory)'`/doom.sh" "$0" "$@" && true; __DOOMCODE=$?; }
:; exit $__DOOMCODE
;; The garbage collector isn't as important during CLI ops. A higher threshold
;; makes it 15-30% faster, but set it too high and we risk runaway memory usage
;; in longer sessions.
(setq gc-cons-threshold 134217728) ; 128mb
;; Prioritize non-byte-compiled source files in non-interactive sessions to
;; prevent loading stale byte-code.
(setq load-prefer-newer t)
;; Ensure Doom runs out of this file's parent directory, where Doom is
;; presumably installed. Use the EMACSDIR envvar to change this.
(setq user-emacs-directory
(if (getenv-internal "EMACSDIR")
(file-name-as-directory (expand-file-name (getenv-internal "EMACSDIR")))
(expand-file-name
"../" (file-name-directory (file-truename load-file-name)))))
;;
;;; Sanity checks
(when (version< emacs-version "27.1")
(error
(concat "Detected Emacs " emacs-version " (at " (car command-line-args) ").\n\n"
"Doom only supports Emacs 27.1 and newer. A guide to install a newer version\n"
"of Emacs can be found at:\n\n "
(format "https://doomemacs.org/docs/getting_started.org#%s\n"
(cond ((eq system-type 'darwin) "on-macos")
((memq system-type '(cygwin windows-nt ms-dos)) "on-windows")
("on-linux")))
"Aborting...")))
(unless (file-readable-p (expand-file-name "core/core.el" user-emacs-directory))
(error
(concat
"Couldn't find or read '"
(abbreviate-file-name
(expand-file-name "core/core.el" user-emacs-directory))
"'.\n\n"
"Are you sure Doom Emacs is correctly installed?\n\n"
(when (file-symlink-p load-file-name)
(concat "This error can occur if you've symlinked the 'doom' script, which Doom does not\n"
"support. Consider symlinking its parent directory instead or explicitly set the\n"
"EMACSDIR environment variable, e.g.\n\n "
(if (string-match-p "/fish$" (getenv "SHELL"))
"env EMACSDIR=~/.emacs.d doom"
"EMACSDIR=~/.emacs.d doom sync"))
"\n\n")
"Aborting...")))
(when (equal (user-real-uid) 0)
;; If ~/.emacs.d is owned by root, assume the user genuinely wants root to be
;; their primary user.
(unless (= 0 (file-attribute-user-id (file-attributes user-emacs-directory)))
(error
(concat
"Do not run this script as root. It will cause file permissions errors later.\n\n"
"To carry on anyway, change the owner of your Emacs config to root:\n\n"
" chown root:root -R " (abbreviate-file-name user-emacs-directory) "\n\n"
"Aborting..."))))
;;
;;; Let 'er rip!
;; HACK Load `cl' and site files manually to prevent polluting logs and stdout
;; with deprecation and/or file load messages.
(let ((inhibit-message t))
(require 'cl)
(unless site-run-file
(let ((site-run-file "site-start")
(verbose (or (getenv "DEBUG") init-file-debug))
(tail load-path)
(lispdir (expand-file-name "../lisp" data-directory))
dir)
(while tail
(setq dir (car tail))
(let ((default-directory dir))
(load (expand-file-name "subdirs.el") t (not verbose) t))
(or (string-prefix-p lispdir dir)
(let ((default-directory dir))
(load (expand-file-name "leim-list.el") t (not verbose) t)))
(setq tail (cdr tail)))
(load site-run-file t (not verbose)))))
;; Load the heart of the beast and its CLI processing library
(load (expand-file-name "core/core.el" user-emacs-directory) nil t)
(require 'core-cli)
(kill-emacs
;; Process the arguments passed to this script. `doom-cli-execute' should
;; return one of two things: a cons cell whose CAR is t, and CDR is the
;; command's return value OR one of: a keyword, command string, or command
;; list.
(pcase (apply #'doom-cli-execute :doom (cdr (member "--" argv)))
;; If a CLI command returns an integer, treat it as an exit code.
((and (app car-safe `t) code)
(if (integerp (cdr code))
(cdr code)))
;; CLI commands can do (throw 'exit SHELL-COMMAND) to run something after
;; this session ends. e.g.
;;
;; (throw 'exit "$@") or (throw 'exit :restart)
;; This reruns the current command with the same arguments.
;; (throw 'exit "$@ -h -c")
;; This reruns the current command with two new switches.
;; (throw 'exit "emacs -nw FILE")
;; Opens Emacs on FILE
;; (throw 'exit t) or (throw 'exit nil)
;; A safe way to simply abort back to the shell with exit code 0
;; (throw 'exit 42)
;; Abort to shell with an explicit exit code (as a more abrupt
;; alternative to having the CLI command return 42).
;;
;; How this works: the command is written to a temporary shell script which
;; is executed after this session ends (see the shebang lines of this file).
;; It's done this way because Emacs' batch library lacks an implementation of
;; the exec system call.
(command
(cond
((integerp command)
command)
((booleanp command)
0)
((let ((script (expand-file-name "doom.sh" temporary-file-directory))
(coding-system-for-write 'utf-8-unix)
(coding-system-for-read 'utf-8-unix))
(with-temp-file script
(insert "#!/usr/bin/env sh\n"
"_postscript() {\n"
" rm -f " (shell-quote-argument script) "\n "
(cond ((eq command :restart) "$@")
((stringp command) command)
((listp command)
(string-join
(if (listp (car-safe command))
(cl-loop for line in (doom-enlist command)
collect (mapconcat #'shell-quote-argument (remq nil line) " "))
(list (mapconcat #'shell-quote-argument (remq nil command) " ")))
"\n ")))
"\n}\n"
(save-match-data
(cl-loop for env
in (cl-set-difference process-environment
(get 'process-environment 'initial-value)
:test #'equal)
if (string-match "^\\([a-zA-Z0-9_]+\\)=\\(.+\\)$" env)
concat (format "%s=%s \\\n"
(match-string 1 env)
(shell-quote-argument (match-string 2 env)))))
(format "PATH=\"%s%s$PATH\" \\\n" (concat doom-emacs-dir "bin/") path-separator)
"_postscript $@\n"))
(set-file-modes script #o600)
;; Error code 128 is special: it means run the post-script after this
;; session ends.
128))))))