Implement daisy-chaining for CLI sessions
elisp lacks an execv implementation (or mature subprocess library), so we exploit some splenderiffic hackery to get Emacs to execute arbitrary shell commands after a 'doom ...' command completes. This allows us to daisy chain doom commands in distinct sessions (wonderful for reloading doom after a 'doom upgrade', which we do). This minimizes errors when a 'doom upgrade' pulls in breaking changes to Doom's CLI. We also bring 'doom run' into elisp, since this new functionality enables us to.
This commit is contained in:
parent
e89b604f5f
commit
a814239ec7
3 changed files with 45 additions and 38 deletions
18
bin/doom
18
bin/doom
|
@ -1,13 +1,15 @@
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
:; ( echo "$EMACS" | grep -q "term" ) && EMACS=emacs || EMACS=${EMACS:-emacs} # -*-emacs-lisp-*-
|
:; ( echo "$EMACS" | grep -q "term" ) && EMACS=emacs || EMACS=${EMACS:-emacs} # -*-emacs-lisp-*-
|
||||||
:; command -v $EMACS >/dev/null || { >&2 echo "Can't find emacs in your PATH"; exit 1; }
|
:; command -v $EMACS >/dev/null || { >&2 echo "Can't find emacs in your PATH"; exit 1; }
|
||||||
:; VERSION=$($EMACS --version | head -n1)
|
:; _VERSION=$($EMACS --version | head -n1)
|
||||||
:; case "$VERSION" in *\ 2[0-5].[0-9]) echo "Detected Emacs $VERSION"; echo "Doom only supports Emacs 26.1 and newer"; echo; exit 2 ;; esac
|
:; case "$_VERSION" in *\ 2[0-5].[0-9]) echo "Detected Emacs $_VERSION"; echo "Doom only supports Emacs 26.1 and newer"; echo; exit 2 ;; esac
|
||||||
:; DOOMBASE="$(dirname "$0")/.."
|
:; _DOOMBASE="${EMACSDIR:-$(dirname "$0")/..}"
|
||||||
:; [ "$1" = -d ] || [ "$1" = --debug ] && { shift; export DEBUG=1; }
|
:; _DOOMPOST="$_DOOMBASE/.local/.doom.sh"
|
||||||
:; [ "$1" = run ] && { cd "$DOOMBASE"; shift; exec $EMACS -q --no-splash -l init.el -f doom-run-all-startup-hooks-h "$@"; exit 0; }
|
:; rm -f "$_DOOMPOST"
|
||||||
:; exec $EMACS --no-site-file --script "$0" -- "$@"
|
:; $EMACS --no-site-file --script "$0" -- "$@"
|
||||||
:; exit 0
|
:; CODE=$?
|
||||||
|
:; [ -x "$_DOOMPOST" ] && PATH="$_DOOMBASE/bin:$PATH" "$_DOOMPOST" "$0" "$@"
|
||||||
|
:; exit $CODE
|
||||||
|
|
||||||
(let* ((loaddir (file-name-directory (file-truename load-file-name)))
|
(let* ((loaddir (file-name-directory (file-truename load-file-name)))
|
||||||
(emacsdir (getenv "EMACSDIR"))
|
(emacsdir (getenv "EMACSDIR"))
|
||||||
|
@ -46,7 +48,7 @@ with a different private module."
|
||||||
:bare t
|
:bare t
|
||||||
(when emacsdir
|
(when emacsdir
|
||||||
(setq user-emacs-directory (file-name-as-directory emacsdir))
|
(setq user-emacs-directory (file-name-as-directory emacsdir))
|
||||||
(print! (info "EMACSDIR=%s") localdir))
|
(print! (info "EMACSDIR=%s") emacsdir))
|
||||||
(when doomdir
|
(when doomdir
|
||||||
(setenv "DOOMDIR" (file-name-as-directory doomdir))
|
(setenv "DOOMDIR" (file-name-as-directory doomdir))
|
||||||
(print! (info "DOOMDIR=%s") localdir))
|
(print! (info "DOOMDIR=%s") localdir))
|
||||||
|
|
|
@ -15,16 +15,19 @@ following shell commands:
|
||||||
bin/doom update"
|
bin/doom update"
|
||||||
:bare t
|
:bare t
|
||||||
(let ((doom-auto-discard force-p))
|
(let ((doom-auto-discard force-p))
|
||||||
(if (delq
|
(cond
|
||||||
nil (list
|
(packages-only-p
|
||||||
(unless packages-only-p
|
(doom-cli-execute "sync" "-u")
|
||||||
(doom-cli-upgrade doom-auto-accept doom-auto-discard))
|
(print! (success "Finished upgrading Doom Emacs")))
|
||||||
(doom-cli-execute "sync")
|
|
||||||
(when (doom-cli-packages-update)
|
((not (doom-cli-upgrade doom-auto-accept doom-auto-discard))
|
||||||
(doom-autoloads-reload)
|
(print! "Nothing to do. Doom is up-to-date!"))
|
||||||
t)))
|
|
||||||
(print! (success "Done! Restart Emacs for changes to take effect."))
|
(t
|
||||||
(print! "Nothing to do. Doom is up-to-date!"))))
|
;; Reload Doom's CLI & libraries, in case there were any
|
||||||
|
;; upstream changes. Major changes will still break, however
|
||||||
|
(print! (info "Reloading Doom Emacs"))
|
||||||
|
(doom-cli-execute-after "doom" "upgrade" "-p" (if force-p "-f"))))))
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
@ -113,24 +116,6 @@ following shell commands:
|
||||||
(equal (vc-git--rev-parse "HEAD") new-rev))
|
(equal (vc-git--rev-parse "HEAD") new-rev))
|
||||||
(error "Failed to check out %s" (substring new-rev 0 10)))
|
(error "Failed to check out %s" (substring new-rev 0 10)))
|
||||||
(print! (info "%s") (cdr result))
|
(print! (info "%s") (cdr result))
|
||||||
|
t))))))
|
||||||
;; Reload Doom's CLI & libraries, in case there were any
|
|
||||||
;; upstream changes. Major changes will still break, however
|
|
||||||
(condition-case-unless-debug e
|
|
||||||
(progn
|
|
||||||
(mapc (lambda (f) (load (symbol-name f)))
|
|
||||||
'(core core-lib
|
|
||||||
core-cli
|
|
||||||
core-modules
|
|
||||||
core-packages))
|
|
||||||
(doom-initialize 'force))
|
|
||||||
(error
|
|
||||||
(signal 'doom-error
|
|
||||||
(list "Could not reload new version of Doom"
|
|
||||||
"Try running 'doom upgrade' again"
|
|
||||||
e))))
|
|
||||||
|
|
||||||
(print! (success "Finished upgrading Doom Emacs")))
|
|
||||||
t)))))
|
|
||||||
(ignore-errors
|
(ignore-errors
|
||||||
(doom-call-process "git" "remote" "remove" doom-repo-remote))))))
|
(doom-call-process "git" "remote" "remove" doom-repo-remote))))))
|
||||||
|
|
|
@ -166,6 +166,24 @@ COMMAND, and passes ARGS to it."
|
||||||
(doom--cli-process cli (remq nil args)))
|
(doom--cli-process cli (remq nil args)))
|
||||||
(user-error "Couldn't find any %S command" command)))
|
(user-error "Couldn't find any %S command" command)))
|
||||||
|
|
||||||
|
(defun doom-cli-execute-after (&rest args)
|
||||||
|
"Execute shell command ARGS after this CLI session quits.
|
||||||
|
|
||||||
|
This is particularly useful when the capabilities of Emacs' batch terminal are
|
||||||
|
insufficient (like opening an instance of Emacs, or reloading Doom after a 'doom
|
||||||
|
upgrade')."
|
||||||
|
(let ((post-script (concat doom-local-dir ".doom.sh")))
|
||||||
|
(with-temp-file post-script
|
||||||
|
(insert "#!/usr/bin/env sh\n"
|
||||||
|
"rm -f " (prin1-to-string post-script) "\n"
|
||||||
|
"exec " (mapconcat #'shell-quote-argument (remq nil args) " ")
|
||||||
|
"\n"))
|
||||||
|
(let* ((current-mode (file-modes post-script))
|
||||||
|
(add-mode (logand ?\111 (default-file-modes))))
|
||||||
|
(or (/= (logand ?\111 current-mode) 0)
|
||||||
|
(zerop add-mode)
|
||||||
|
(set-file-modes post-script (logior current-mode add-mode))))))
|
||||||
|
|
||||||
(defmacro defcli! (name speclist &optional docstring &rest body)
|
(defmacro defcli! (name speclist &optional docstring &rest body)
|
||||||
"Defines a CLI command.
|
"Defines a CLI command.
|
||||||
|
|
||||||
|
@ -423,7 +441,9 @@ All arguments are passed on to Emacs.
|
||||||
|
|
||||||
WARNING: this command exists for convenience and testing. Doom will suffer
|
WARNING: this command exists for convenience and testing. Doom will suffer
|
||||||
additional overhead by being started this way. For the best performance, it is
|
additional overhead by being started this way. For the best performance, it is
|
||||||
best to run Doom out of ~/.emacs.d and ~/.doom.d."))
|
best to run Doom out of ~/.emacs.d and ~/.doom.d."
|
||||||
|
(apply #'doom-cli-execute-after invocation-name args)
|
||||||
|
nil))
|
||||||
|
|
||||||
(provide 'core-cli)
|
(provide 'core-cli)
|
||||||
;;; core-cli.el ends here
|
;;; core-cli.el ends here
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue