From: Jim Porter Date: Sun, 5 May 2024 20:09:08 +0000 (-0700) Subject: Fix Eshell handling of remote files like "/ssh:remote:~/file.txt" X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=bea32a79f6409cb878e3d7e7efc1e783bc181fcb;p=emacs.git Fix Eshell handling of remote files like "/ssh:remote:~/file.txt" * lisp/eshell/em-glob.el (eshell-glob-convert): Use 'concat' instead of 'file-name-concat' to avoid extraneous slashes. (eshell-extended-glob): Bail out if we didn't find a glob after all. * test/lisp/eshell/em-glob-tests.el (tramp): Require. (em-glob-test/convert/remote-start-directory): Use the mock remote connection. (em-glob-test/remote-user-directory): New test. (cherry picked from commit 1529ad0315f8d4a96ca07969c1c91c1c50bb6075) --- diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el index 7fc6958a00f..89a40151d00 100644 --- a/lisp/eshell/em-glob.el +++ b/lisp/eshell/em-glob.el @@ -317,7 +317,7 @@ The result is a list of three elements: result) ;; We haven't seen a glob yet, so instead append to the start ;; directory. - (setq start-dir (file-name-concat start-dir (car globs)))) + (setq start-dir (concat start-dir (car globs)))) (setq last-saw-recursion nil)) (setq globs (cdr globs))) (list start-dir @@ -341,16 +341,24 @@ Mainly they are not supported because file matching is done with Emacs regular expressions, and these cannot support the above constructs." (let ((globs (eshell-glob-convert glob)) eshell-glob-matches message-shown) - (unwind-protect - (apply #'eshell-glob-entries globs) - (if message-shown - (message nil))) - (or (and eshell-glob-matches (sort eshell-glob-matches #'string<)) - (if eshell-error-if-no-glob - (error "No matches found: %s" glob) - (if eshell-glob-splice-results - (list glob) - glob))))) + (if (null (cadr globs)) + ;; If, after examining GLOB, there are no actual globs, just + ;; bail out. This can happen for remote file names using "~", + ;; like "/ssh:remote:~/file.txt". During parsing, we can't + ;; always be sure if the "~" is a home directory reference or + ;; part of a glob (e.g. if the argument was assembled from + ;; variables). + glob + (unwind-protect + (apply #'eshell-glob-entries globs) + (if message-shown + (message nil))) + (or (and eshell-glob-matches (sort eshell-glob-matches #'string<)) + (if eshell-error-if-no-glob + (error "No matches found: %s" glob) + (if eshell-glob-splice-results + (list glob) + glob)))))) ;; FIXME does this really need to abuse eshell-glob-matches, message-shown? (defun eshell-glob-entries (path globs only-dirs) diff --git a/test/lisp/eshell/em-glob-tests.el b/test/lisp/eshell/em-glob-tests.el index fc460a59eed..40cdfd1a676 100644 --- a/test/lisp/eshell/em-glob-tests.el +++ b/test/lisp/eshell/em-glob-tests.el @@ -23,6 +23,7 @@ ;;; Code: +(require 'tramp) (require 'ert) (require 'em-glob) @@ -138,9 +139,12 @@ value of `eshell-glob-splice-results'." (ert-deftest em-glob-test/convert/remote-start-directory () "Test converting a glob starting in a remote directory." - (should (equal (eshell-glob-convert "/ssh:nowhere.invalid:some/where/*.el") - '("/ssh:nowhere.invalid:/some/where/" - (("\\`.*\\.el\\'" . "\\`\\.")) nil)))) + (skip-unless (eshell-tests-remote-accessible-p)) + (let* ((default-directory ert-remote-temporary-file-directory) + (remote (file-remote-p default-directory))) + (should (equal (eshell-glob-convert (format "%s/some/where/*.el" remote)) + `(,(format "%s/some/where/" remote) + (("\\`.*\\.el\\'" . "\\`\\.")) nil))))) ;; Glob matching @@ -288,4 +292,13 @@ value of `eshell-glob-splice-results'." (let ((eshell-error-if-no-glob t)) (should-error (eshell-extended-glob "*.txt"))))) +(ert-deftest em-glob-test/remote-user-directory () + "Test that remote directories using \"~\" pass through unchanged." + (skip-unless (eshell-tests-remote-accessible-p)) + (let* ((default-directory ert-remote-temporary-file-directory) + (remote (file-remote-p default-directory)) + (eshell-error-if-no-glob t)) + (should (equal (eshell-extended-glob (format "%s~/file.txt" remote)) + (format "%s~/file.txt" remote))))) + ;; em-glob-tests.el ends here