diff options
| author | Jim Porter | 2022-09-15 12:24:37 -0700 |
|---|---|---|
| committer | Jim Porter | 2022-10-17 18:48:52 -0700 |
| commit | cee1cbfd54375cdece23d4741ced6b0c7091f6d9 (patch) | |
| tree | 482d4bf98473742958b4ce4f1fba1c3e305aa093 /test | |
| parent | 7c41016fca5ab0638f1e2fed260e2ee41f3400c2 (diff) | |
| download | emacs-cee1cbfd54375cdece23d4741ced6b0c7091f6d9.tar.gz emacs-cee1cbfd54375cdece23d4741ced6b0c7091f6d9.zip | |
Improve handling of $PATH in Eshell for remote directories
* lisp/eshell/esh-util.el (eshell-path-env, eshell-parse-colon-path):
Make obsolete.
(eshell-path-env-list): New variable.
(eshell-connection-default-profile): New connection-local profile.
(eshell-get-path): Reimplement using 'eshell-path-env-list'; add
LITERAL-P argument.
(eshell-set-path): New function.
* lisp/eshell/esh-var.el (eshell-variable-aliases-list): Add entry for
$PATH.
(eshell-var-initialize): Add 'eshell-path-env-list' to
'eshell-subcommand-bindings'.
* lisp/eshell/esh-ext.el (eshell-search-path): Use 'file-name-concat'
instead of 'concat'.
(eshell/addpath): Use 'eshell-get-path' and 'eshell-set-path'.
* lisp/net/tramp-integration.el: Only apply Eshell hooks when
'eshell-path-env-list' is unbound.
* test/lisp/eshell/esh-var-tests.el
(esh-var-test/path-var/local-directory)
(esh-var-test/path-var/remote-directory, esh-var-test/path-var/set)
(esh-var-test/path-var/set-locally)
(esh-var-test/path-var-preserve-across-hosts): New tests.
* test/lisp/eshell/esh-ext-tests.el: New file.
* test/lisp/eshell/eshell-tests-helpers.el
(with-temp-eshell): Set 'eshell-last-dir-ring-file-name' to nil.
(eshell-tests-remote-accessible-p, eshell-last-input)
(eshell-last-output): New functions.
(eshell-match-output, eshell-match-output--explainer): Use
'eshell-last-input' and 'eshell-last-output'.
* doc/misc/eshell.texi (Variables): Document $PATH.
* etc/NEWS: Announce this change (bug#57556).
Diffstat (limited to 'test')
| -rw-r--r-- | test/lisp/eshell/esh-ext-tests.el | 76 | ||||
| -rw-r--r-- | test/lisp/eshell/esh-var-tests.el | 60 | ||||
| -rw-r--r-- | test/lisp/eshell/eshell-tests-helpers.el | 32 |
3 files changed, 161 insertions, 7 deletions
diff --git a/test/lisp/eshell/esh-ext-tests.el b/test/lisp/eshell/esh-ext-tests.el new file mode 100644 index 00000000000..54191e9409e --- /dev/null +++ b/test/lisp/eshell/esh-ext-tests.el | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | ;;; esh-ext-tests.el --- esh-ext test suite -*- lexical-binding:t -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2022 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | ;; it under the terms of the GNU General Public License as published by | ||
| 9 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 10 | ;; (at your option) any later version. | ||
| 11 | |||
| 12 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | ;; GNU General Public License for more details. | ||
| 16 | |||
| 17 | ;; You should have received a copy of the GNU General Public License | ||
| 18 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | ;;; Commentary: | ||
| 21 | |||
| 22 | ;; Tests for Eshell's external command handling. | ||
| 23 | |||
| 24 | ;;; Code: | ||
| 25 | |||
| 26 | (require 'ert) | ||
| 27 | (require 'esh-mode) | ||
| 28 | (require 'esh-ext) | ||
| 29 | (require 'eshell) | ||
| 30 | |||
| 31 | (require 'eshell-tests-helpers | ||
| 32 | (expand-file-name "eshell-tests-helpers" | ||
| 33 | (file-name-directory (or load-file-name | ||
| 34 | default-directory)))) | ||
| 35 | |||
| 36 | ;;; Tests: | ||
| 37 | |||
| 38 | (ert-deftest esh-ext-test/addpath/end () | ||
| 39 | "Test that \"addpath\" adds paths to the end of $PATH." | ||
| 40 | (with-temp-eshell | ||
| 41 | (let ((eshell-path-env-list '("/some/path" "/other/path")) | ||
| 42 | (expected-path (string-join '("/some/path" "/other/path" "/new/path" | ||
| 43 | "/new/path2") | ||
| 44 | (path-separator)))) | ||
| 45 | (eshell-match-command-output "addpath /new/path /new/path2" | ||
| 46 | (concat expected-path "\n")) | ||
| 47 | (eshell-match-command-output "echo $PATH" | ||
| 48 | (concat expected-path "\n"))))) | ||
| 49 | |||
| 50 | (ert-deftest esh-ext-test/addpath/begin () | ||
| 51 | "Test that \"addpath -b\" adds paths to the beginning of $PATH." | ||
| 52 | (with-temp-eshell | ||
| 53 | (let ((eshell-path-env-list '("/some/path" "/other/path")) | ||
| 54 | (expected-path (string-join '("/new/path" "/new/path2" "/some/path" | ||
| 55 | "/other/path") | ||
| 56 | (path-separator)))) | ||
| 57 | (eshell-match-command-output "addpath -b /new/path /new/path2" | ||
| 58 | (concat expected-path "\n")) | ||
| 59 | (eshell-match-command-output "echo $PATH" | ||
| 60 | (concat expected-path "\n"))))) | ||
| 61 | |||
| 62 | (ert-deftest esh-ext-test/addpath/set-locally () | ||
| 63 | "Test adding to the path temporarily in a subcommand." | ||
| 64 | (let* ((eshell-path-env-list '("/some/path" "/other/path")) | ||
| 65 | (original-path (string-join eshell-path-env-list (path-separator))) | ||
| 66 | (local-path (string-join (append eshell-path-env-list '("/new/path")) | ||
| 67 | (path-separator)))) | ||
| 68 | (with-temp-eshell | ||
| 69 | (eshell-match-command-output | ||
| 70 | "{ addpath /new/path; env }" | ||
| 71 | (format "PATH=%s\n" (regexp-quote local-path))) | ||
| 72 | ;; After the last command, the previous $PATH value should be restored. | ||
| 73 | (eshell-match-command-output "echo $PATH" | ||
| 74 | (concat original-path "\n"))))) | ||
| 75 | |||
| 76 | ;; esh-ext-tests.el ends here | ||
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index a7ac52ed24a..d9b2585a327 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | ;;; Code: | 24 | ;;; Code: |
| 25 | 25 | ||
| 26 | (require 'tramp) | ||
| 26 | (require 'ert) | 27 | (require 'ert) |
| 27 | (require 'esh-mode) | 28 | (require 'esh-mode) |
| 28 | (require 'esh-var) | 29 | (require 'esh-var) |
| @@ -610,6 +611,65 @@ it, since the setter is nil." | |||
| 610 | (eshell-match-command-output "echo $INSIDE_EMACS[, 1]" | 611 | (eshell-match-command-output "echo $INSIDE_EMACS[, 1]" |
| 611 | "eshell"))) | 612 | "eshell"))) |
| 612 | 613 | ||
| 614 | (ert-deftest esh-var-test/path-var/local-directory () | ||
| 615 | "Test using $PATH in a local directory." | ||
| 616 | (let ((expected-path (string-join (eshell-get-path t) (path-separator)))) | ||
| 617 | (with-temp-eshell | ||
| 618 | (eshell-match-command-output "echo $PATH" (regexp-quote expected-path))))) | ||
| 619 | |||
| 620 | (ert-deftest esh-var-test/path-var/remote-directory () | ||
| 621 | "Test using $PATH in a remote directory." | ||
| 622 | (skip-unless (eshell-tests-remote-accessible-p)) | ||
| 623 | (let* ((default-directory ert-remote-temporary-file-directory) | ||
| 624 | (expected-path (string-join (eshell-get-path t) (path-separator)))) | ||
| 625 | (with-temp-eshell | ||
| 626 | (eshell-match-command-output "echo $PATH" (regexp-quote expected-path))))) | ||
| 627 | |||
| 628 | (ert-deftest esh-var-test/path-var/set () | ||
| 629 | "Test setting $PATH." | ||
| 630 | (let* ((path-to-set-list '("/some/path" "/other/path")) | ||
| 631 | (path-to-set (string-join path-to-set-list (path-separator)))) | ||
| 632 | (with-temp-eshell | ||
| 633 | (eshell-match-command-output (concat "set PATH " path-to-set) | ||
| 634 | (concat path-to-set "\n")) | ||
| 635 | (eshell-match-command-output "echo $PATH" (concat path-to-set "\n")) | ||
| 636 | (should (equal (eshell-get-path t) path-to-set-list))))) | ||
| 637 | |||
| 638 | (ert-deftest esh-var-test/path-var/set-locally () | ||
| 639 | "Test setting $PATH temporarily for a single command." | ||
| 640 | (let* ((path-to-set-list '("/some/path" "/other/path")) | ||
| 641 | (path-to-set (string-join path-to-set-list (path-separator)))) | ||
| 642 | (with-temp-eshell | ||
| 643 | (eshell-match-command-output (concat "set PATH " path-to-set) | ||
| 644 | (concat path-to-set "\n")) | ||
| 645 | (eshell-match-command-output "PATH=/local/path env" | ||
| 646 | "PATH=/local/path\n") | ||
| 647 | ;; After the last command, the previous $PATH value should be restored. | ||
| 648 | (eshell-match-command-output "echo $PATH" (concat path-to-set "\n")) | ||
| 649 | (should (equal (eshell-get-path t) path-to-set-list))))) | ||
| 650 | |||
| 651 | (ert-deftest esh-var-test/path-var/preserve-across-hosts () | ||
| 652 | "Test that $PATH can be set independently on multiple hosts." | ||
| 653 | (let ((local-directory default-directory) | ||
| 654 | local-path remote-path) | ||
| 655 | (with-temp-eshell | ||
| 656 | ;; Set the $PATH on localhost. | ||
| 657 | (eshell-insert-command "set PATH /local/path") | ||
| 658 | (setq local-path (eshell-last-output)) | ||
| 659 | ;; `cd' to a remote host and set the $PATH there too. | ||
| 660 | (eshell-insert-command | ||
| 661 | (format "cd %s" ert-remote-temporary-file-directory)) | ||
| 662 | (eshell-insert-command "set PATH /remote/path") | ||
| 663 | (setq remote-path (eshell-last-output)) | ||
| 664 | ;; Return to localhost and check that $PATH is the value we set | ||
| 665 | ;; originally. | ||
| 666 | (eshell-insert-command (format "cd %s" local-directory)) | ||
| 667 | (eshell-match-command-output "echo $PATH" (regexp-quote local-path)) | ||
| 668 | ;; ... and do the same for the remote host. | ||
| 669 | (eshell-insert-command | ||
| 670 | (format "cd %s" ert-remote-temporary-file-directory)) | ||
| 671 | (eshell-match-command-output "echo $PATH" (regexp-quote remote-path))))) | ||
| 672 | |||
| 613 | (ert-deftest esh-var-test/last-status-var-lisp-command () | 673 | (ert-deftest esh-var-test/last-status-var-lisp-command () |
| 614 | "Test using the \"last exit status\" ($?) variable with a Lisp command" | 674 | "Test using the \"last exit status\" ($?) variable with a Lisp command" |
| 615 | (with-temp-eshell | 675 | (with-temp-eshell |
diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el index e713e162ad0..1d9674070c0 100644 --- a/test/lisp/eshell/eshell-tests-helpers.el +++ b/test/lisp/eshell/eshell-tests-helpers.el | |||
| @@ -31,11 +31,22 @@ | |||
| 31 | (require 'eshell) | 31 | (require 'eshell) |
| 32 | 32 | ||
| 33 | (defvar eshell-history-file-name nil) | 33 | (defvar eshell-history-file-name nil) |
| 34 | (defvar eshell-last-dir-ring-file-name nil) | ||
| 34 | 35 | ||
| 35 | (defvar eshell-test--max-subprocess-time 5 | 36 | (defvar eshell-test--max-subprocess-time 5 |
| 36 | "The maximum amount of time to wait for a subprocess to finish, in seconds. | 37 | "The maximum amount of time to wait for a subprocess to finish, in seconds. |
| 37 | See `eshell-wait-for-subprocess'.") | 38 | See `eshell-wait-for-subprocess'.") |
| 38 | 39 | ||
| 40 | (defun eshell-tests-remote-accessible-p () | ||
| 41 | "Return if a test involving remote files can proceed. | ||
| 42 | If using this function, be sure to load `tramp' near the | ||
| 43 | beginning of the test file." | ||
| 44 | (ignore-errors | ||
| 45 | (and | ||
| 46 | (file-remote-p ert-remote-temporary-file-directory) | ||
| 47 | (file-directory-p ert-remote-temporary-file-directory) | ||
| 48 | (file-writable-p ert-remote-temporary-file-directory)))) | ||
| 49 | |||
| 39 | (defmacro with-temp-eshell (&rest body) | 50 | (defmacro with-temp-eshell (&rest body) |
| 40 | "Evaluate BODY in a temporary Eshell buffer." | 51 | "Evaluate BODY in a temporary Eshell buffer." |
| 41 | `(save-current-buffer | 52 | `(save-current-buffer |
| @@ -44,6 +55,7 @@ See `eshell-wait-for-subprocess'.") | |||
| 44 | ;; back on $HISTFILE. | 55 | ;; back on $HISTFILE. |
| 45 | (process-environment (cons "HISTFILE" process-environment)) | 56 | (process-environment (cons "HISTFILE" process-environment)) |
| 46 | (eshell-history-file-name nil) | 57 | (eshell-history-file-name nil) |
| 58 | (eshell-last-dir-ring-file-name nil) | ||
| 47 | (eshell-buffer (eshell t))) | 59 | (eshell-buffer (eshell t))) |
| 48 | (unwind-protect | 60 | (unwind-protect |
| 49 | (with-current-buffer eshell-buffer | 61 | (with-current-buffer eshell-buffer |
| @@ -83,19 +95,25 @@ After inserting, call FUNC. If FUNC is nil, instead call | |||
| 83 | (insert-and-inherit command) | 95 | (insert-and-inherit command) |
| 84 | (funcall (or func 'eshell-send-input))) | 96 | (funcall (or func 'eshell-send-input))) |
| 85 | 97 | ||
| 98 | (defun eshell-last-input () | ||
| 99 | "Return the input of the last Eshell command." | ||
| 100 | (buffer-substring-no-properties | ||
| 101 | eshell-last-input-start eshell-last-input-end)) | ||
| 102 | |||
| 103 | (defun eshell-last-output () | ||
| 104 | "Return the output of the last Eshell command." | ||
| 105 | (buffer-substring-no-properties | ||
| 106 | (eshell-beginning-of-output) (eshell-end-of-output))) | ||
| 107 | |||
| 86 | (defun eshell-match-output (regexp) | 108 | (defun eshell-match-output (regexp) |
| 87 | "Test whether the output of the last command matches REGEXP." | 109 | "Test whether the output of the last command matches REGEXP." |
| 88 | (string-match-p | 110 | (string-match-p regexp (eshell-last-output))) |
| 89 | regexp (buffer-substring-no-properties | ||
| 90 | (eshell-beginning-of-output) (eshell-end-of-output)))) | ||
| 91 | 111 | ||
| 92 | (defun eshell-match-output--explainer (regexp) | 112 | (defun eshell-match-output--explainer (regexp) |
| 93 | "Explain the result of `eshell-match-output'." | 113 | "Explain the result of `eshell-match-output'." |
| 94 | `(mismatched-output | 114 | `(mismatched-output |
| 95 | (command ,(buffer-substring-no-properties | 115 | (command ,(eshell-last-input)) |
| 96 | eshell-last-input-start eshell-last-input-end)) | 116 | (output ,(eshell-last-output)) |
| 97 | (output ,(buffer-substring-no-properties | ||
| 98 | (eshell-beginning-of-output) (eshell-end-of-output))) | ||
| 99 | (regexp ,regexp))) | 117 | (regexp ,regexp))) |
| 100 | 118 | ||
| 101 | (put 'eshell-match-output 'ert-explainer #'eshell-match-output--explainer) | 119 | (put 'eshell-match-output 'ert-explainer #'eshell-match-output--explainer) |