branch: externals/tramp commit aeb0ea73406d7d7066149cb487683e55b86e7124 Author: Michael Albinus <michael.albi...@gmx.de> Commit: Michael Albinus <michael.albi...@gmx.de>
Tramp ELPA version 2.5.2.2 released --- README | 4 +- test/tramp-tests.el | 247 +++++++++++++++++++++++++++++++++++++++++++--------- texi/tramp.texi | 20 ++++- texi/trampver.texi | 2 +- tramp-adb.el | 28 +++++- tramp-archive.el | 6 ++ tramp-cache.el | 2 +- tramp-crypt.el | 6 +- tramp-gvfs.el | 43 +++++---- tramp-rclone.el | 6 +- tramp-sh.el | 58 ++++++------ tramp-smb.el | 2 +- tramp-sshfs.el | 98 ++++++++++++++++++--- tramp-sudoedit.el | 6 +- tramp.el | 48 +++++++--- trampver.el | 6 +- 16 files changed, 448 insertions(+), 134 deletions(-) diff --git a/README b/README index e23715f468..5ed2c3efa8 100644 --- a/README +++ b/README @@ -22,11 +22,11 @@ installed with, you must recompile the package: * Remove all byte-compiled Tramp files - $ rm -f ~/.emacs.d/elpa/tramp-2.5.2.1/tramp*.elc + $ rm -f ~/.emacs.d/elpa/tramp-2.5.2.2/tramp*.elc * Start Emacs with Tramp's source files - $ emacs -L ~/.emacs.d/elpa/tramp-2.5.2.1 -l tramp + $ emacs -L ~/.emacs.d/elpa/tramp-2.5.2.2 -l tramp This should not give you the error. diff --git a/test/tramp-tests.el b/test/tramp-tests.el index 1fd99d3e72..42d4b9c43f 100644 --- a/test/tramp-tests.el +++ b/test/tramp-tests.el @@ -3476,8 +3476,10 @@ This tests also `access-file', `file-readable-p', (should (string-equal (tramp-compat-file-attribute-type attr) - (tramp-file-name-localname - (tramp-dissect-file-name tmp-name3)))) + (funcall + (if (tramp--test-sshfs-p) #'file-name-nondirectory #'identity) + (tramp-file-name-localname + (tramp-dissect-file-name tmp-name3))))) (delete-file tmp-name2)) (when test-file-ownership-preserved-p @@ -3646,8 +3648,9 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'." (should (= (file-modes tmp-name1) #o444)) (should-not (file-executable-p tmp-name1)) ;; A file is always writable for user "root". - (unless (zerop (tramp-compat-file-attribute-user-id - (file-attributes tmp-name1))) + (unless (or (zerop (tramp-compat-file-attribute-user-id + (file-attributes tmp-name1))) + (tramp--test-sshfs-p)) (should-not (file-writable-p tmp-name1))) ;; Check the NOFOLLOW arg. It exists since Emacs 28. For ;; regular files, there shouldn't be a difference. @@ -4451,6 +4454,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (let* ((tmp-name (tramp--test-make-temp-name nil quoted)) (fnnd (file-name-nondirectory tmp-name)) (default-directory tramp-test-temporary-file-directory) + (buffer (get-buffer-create "*tramp-tests*")) kill-buffer-query-functions) (unwind-protect (progn @@ -4483,31 +4487,47 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (tramp--test-shell-file-name) nil nil nil "-c" "kill -2 $$"))))) - (with-temp-buffer - (write-region "foo" nil tmp-name) - (should (file-exists-p tmp-name)) - (should (zerop (process-file "ls" nil t nil fnnd))) - ;; "ls" could produce colorized output. - (goto-char (point-min)) - (while - (re-search-forward tramp-display-escape-sequence-regexp nil t) - (replace-match "" nil nil)) - (should (string-equal (format "%s\n" fnnd) (buffer-string))) - (should-not (get-buffer-window (current-buffer) t)) + ;; Check DESTINATION. + (dolist (destination `(nil t ,buffer)) + (when (bufferp destination) + (with-current-buffer destination + (delete-region (point-min) (point-max)))) + (with-temp-buffer + (write-region "foo" nil tmp-name) + (should (file-exists-p tmp-name)) + (should (zerop (process-file "ls" nil destination nil fnnd))) + (with-current-buffer + (if (bufferp destination) destination (current-buffer)) + ;; "ls" could produce colorized output. + (goto-char (point-min)) + (while (re-search-forward + tramp-display-escape-sequence-regexp nil t) + (replace-match "" nil nil)) + (should + (string-equal (if destination (format "%s\n" fnnd) "") + (buffer-string))) + (should-not (get-buffer-window (current-buffer) t)) + (goto-char (point-max))) + + ;; Second run. The output must be appended. + (should (zerop (process-file "ls" nil destination t fnnd))) + (with-current-buffer + (if (bufferp destination) destination (current-buffer)) + ;; "ls" could produce colorized output. + (goto-char (point-min)) + (while (re-search-forward + tramp-display-escape-sequence-regexp nil t) + (replace-match "" nil nil)) + (should + (string-equal + (if destination (format "%s\n%s\n" fnnd fnnd) "") + (buffer-string)))) - ;; Second run. The output must be appended. - (goto-char (point-max)) - (should (zerop (process-file "ls" nil t t fnnd))) - ;; "ls" could produce colorized output. - (goto-char (point-min)) - (while - (re-search-forward tramp-display-escape-sequence-regexp nil t) - (replace-match "" nil nil)) - (should - (string-equal (format "%s\n%s\n" fnnd fnnd) (buffer-string))) - ;; A non-nil DISPLAY must not raise the buffer. - (should-not (get-buffer-window (current-buffer) t)) - (delete-file tmp-name)) + (unless (eq destination t) + (should (string-empty-p (buffer-string)))) + ;; A non-nil DISPLAY must not raise the buffer. + (should-not (get-buffer-window (current-buffer) t)) + (delete-file tmp-name))) ;; Check remote and local INFILE. (dolist (local '(nil t)) @@ -4517,10 +4537,37 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (should (file-exists-p tmp-name)) (should (zerop (process-file "cat" tmp-name t))) (should (string-equal "foo" (buffer-string))) - (should-not (get-buffer-window (current-buffer) t))) - (delete-file tmp-name))) + (should-not (get-buffer-window (current-buffer) t)) + (delete-file tmp-name))) + + ;; Check remote and local DESTNATION file. This isn't + ;; implemented yet ina all file name handler backends. + ;; (dolist (local '(nil t)) + ;; (setq tmp-name (tramp--test-make-temp-name local quoted)) + ;; (should + ;; (zerop (process-file "echo" nil `(:file ,tmp-name) nil "foo"))) + ;; (with-temp-buffer + ;; (insert-file-contents tmp-name) + ;; (should (string-equal "foo" (buffer-string))) + ;; (should-not (get-buffer-window (current-buffer) t)) + ;; (delete-file tmp-name))) + + ;; Check remote and local STDERR. + (dolist (local '(nil t)) + (setq tmp-name (tramp--test-make-temp-name local quoted)) + (should-not + (zerop + (process-file "cat" nil `(t ,tmp-name) nil "/does-not-exist"))) + (with-temp-buffer + (insert-file-contents tmp-name) + (should + (string-match-p + "cat:.* No such file or directory" (buffer-string))) + (should-not (get-buffer-window (current-buffer) t)) + (delete-file tmp-name)))) ;; Cleanup. + (ignore-errors (kill-buffer buffer)) (ignore-errors (delete-file tmp-name)))))) ;; Must be a command, because used as `sigusr1' handler. @@ -6089,6 +6136,79 @@ Use direct async.") (ignore-errors (delete-file tmp-name1)) (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password))))) +;; The functions were introduced in Emacs 28.1. +(ert-deftest tramp-test39-detect-external-change () + "Check that an external file modification is reported." + (skip-unless (tramp--test-enabled)) + (skip-unless (not (tramp--test-ange-ftp-p))) + ;; Since Emacs 28.1. + (skip-unless (and (fboundp 'lock-file) (fboundp 'file-locked-p))) + + (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil))) + (dolist (create-lockfiles '(nil t)) + (let ((tmp-name (tramp--test-make-temp-name nil quoted)) + (remote-file-name-inhibit-cache t) + (remote-file-name-inhibit-locks nil) + tramp-allow-unsafe-temporary-files + (inhibit-message t) + ;; tramp-rclone.el and tramp-sshfs.el cache the mounted files. + (tramp-fuse-unmount-on-cleanup t) + auto-save-default + (backup-inhibited t) + noninteractive) + (with-temp-buffer + (unwind-protect + (progn + (setq buffer-file-name tmp-name + buffer-file-truename tmp-name) + (insert "foo") + ;; Bug#53207: with `create-lockfiles' nil, saving the + ;; buffer results in a prompt. + (cl-letf (((symbol-function 'yes-or-no-p) + (lambda (_) (ert-fail "Test failed unexpectedly")))) + (save-buffer)) + (should-not (file-locked-p tmp-name)) + + ;; Macro `ert-with-message-capture' was introduced in Emacs 26.1. + (with-no-warnings (when (symbol-plist 'ert-with-message-capture) + ;; For local files, just changing the file + ;; modification on disk doesn't hurt, because file + ;; contents in buffer and on disk are equal. For + ;; remote files, file contents is not compared. We + ;; mock an older modification time in buffer, + ;; because Tramp regards modification times equal if + ;; they differ for less than 2 seconds. + (set-visited-file-modtime (time-add (current-time) -60)) + ;; Some Tramp methods cannot check the file + ;; modification time properly, for them it doesn't + ;; make sense to test. + (when (not (verify-visited-file-modtime)) + (cl-letf (((symbol-function 'read-char-choice) + (lambda (prompt &rest _) (message "%s" prompt) ?y))) + (ert-with-message-capture captured-messages + (insert "bar") + (when create-lockfiles + (should (string-match-p + (format + "^%s changed on disk; really edit the buffer\\?" + (if (tramp--test-crypt-p) + ".+" (file-name-nondirectory tmp-name))) + captured-messages)) + (should (file-locked-p tmp-name))))) + + ;; `save-buffer' removes the file lock. + (cl-letf (((symbol-function 'yes-or-no-p) #'tramp--test-always) + ((symbol-function 'read-char-choice) + (lambda (&rest _) ?y))) + (save-buffer)) + (should-not (file-locked-p tmp-name)))))) + + ;; Cleanup. + (set-buffer-modified-p nil) + (ignore-errors (delete-file tmp-name)) + (tramp-cleanup-connection + tramp-test-vec 'keep-debug 'keep-password))))))) + ;; The functions were introduced in Emacs 26.1. (ert-deftest tramp-test40-make-nearby-temp-file () "Check `make-nearby-temp-file' and `temporary-file-directory'." @@ -6160,10 +6280,14 @@ This requires restrictions of file name syntax." "Whether asynchronous processes tests are run. This is used in tests which we dont't want to tag `:tramp-asynchronous-processes' completely." - (ert-select-tests - (ert--stats-selector ert--current-run-stats) - (list (make-ert-test :name (ert-test-name (ert-running-test)) - :body nil :tags '(:tramp-asynchronous-processes))))) + (and + (ert-select-tests + (ert--stats-selector ert--current-run-stats) + (list (make-ert-test :name (ert-test-name (ert-running-test)) + :body nil :tags '(:tramp-asynchronous-processes)))) + ;; tramp-adb.el cannot apply multi-byte commands. + (not (and (tramp--test-adb-p) + (string-match-p "[[:multibyte:]]" default-directory))))) (defun tramp--test-crypt-p () "Check, whether the remote directory is crypted." @@ -6212,7 +6336,7 @@ If optional METHOD is given, it is checked first." Several special characters do not work properly there." ;; We must refill the cache. `file-truename' does it. (file-truename tramp-test-temporary-file-directory) - (tramp-check-remote-uname tramp-test-vec "^HP-UX")) + (ignore-errors (tramp-check-remote-uname tramp-test-vec "^HP-UX"))) (defun tramp--test-ksh-p () "Check, whether the remote shell is ksh. @@ -6227,7 +6351,7 @@ a $'' syntax." "Check, whether the remote host runs macOS." ;; We must refill the cache. `file-truename' does it. (file-truename tramp-test-temporary-file-directory) - (tramp-check-remote-uname tramp-test-vec "Darwin")) + (ignore-errors (tramp-check-remote-uname tramp-test-vec "Darwin"))) (defun tramp--test-mock-p () "Check, whether the mock method is used. @@ -6481,6 +6605,31 @@ This requires restrictions of file name syntax." (delete-file file3) (should-not (file-exists-p file3)))) + ;; Check, that a process runs on a remote + ;; `default-directory' with special characters. See + ;; Bug#53846. + (when (and (tramp--test-expensive-test-p) + (tramp--test-supports-processes-p) + ;; Prior Emacs 27, `shell-file-name' was + ;; hard coded as "/bin/sh" for remote + ;; processes in Emacs. That doesn't work + ;; for tramp-adb.el. tramp-sshfs.el times + ;; out for older Emacsen, reason unknown. + (or (and (not (tramp--test-adb-p)) + (not (tramp--test-sshfs-p))) + (tramp--test-emacs27-p))) + (let ((default-directory file1)) + (dolist (this-shell-command + (append + ;; Synchronously. + '(shell-command) + ;; Asynchronously. + (and (tramp--test-asynchronous-processes-p) + '(tramp--test-async-shell-command)))) + (with-temp-buffer + (funcall this-shell-command "cat -- *" (current-buffer)) + (should (string-equal elt (buffer-string))))))) + (delete-file file2) (should-not (file-exists-p file2)) (delete-directory file1) @@ -7170,28 +7319,34 @@ Since it unloads Tramp, it shall be the last test to run." (should (featurep 'tramp-archive)) ;; This unloads also tramp-archive.el and tramp-theme.el if needed. (unload-feature 'tramp 'force) - ;; No Tramp feature must be left. + + ;; No Tramp feature must be left except the test packages. (should-not (featurep 'tramp)) (should-not (featurep 'tramp-archive)) (should-not (featurep 'tramp-theme)) (should-not (all-completions "tramp" (delq 'tramp-tests (delq 'tramp-archive-tests features)))) + ;; `file-name-handler-alist' must be clean. (should-not (all-completions "tramp" (mapcar #'cdr file-name-handler-alist))) + ;; There shouldn't be left a bound symbol, except buffer-local - ;; variables, and autoload functions. We do not regard our test + ;; variables, and autoloaded functions. We do not regard our test ;; symbols, and the Tramp unload hooks. (mapatoms (lambda (x) (and (or (and (boundp x) (null (local-variable-if-set-p x))) - (and (functionp x) (null (autoloadp (symbol-function x))))) + (and (functionp x) (null (autoloadp (symbol-function x)))) + (macrop x)) (string-match-p "^tramp" (symbol-name x)) ;; `tramp-completion-mode' is autoloaded in Emacs < 28.1. (not (eq 'tramp-completion-mode x)) (not (string-match-p "^tramp\\(-archive\\)?--?test" (symbol-name x))) (not (string-match-p "unload-hook$" (symbol-name x))) + (not (get x 'tramp-autoload)) (ert-fail (format "`%s' still bound" x))))) + ;; The defstruct `tramp-file-name' and all its internal functions ;; shall be purged. (should-not (cl--find-class 'tramp-file-name)) @@ -7200,6 +7355,7 @@ Since it unloads Tramp, it shall be the last test to run." (and (functionp x) (string-match-p "tramp-file-name" (symbol-name x)) (ert-fail (format "Structure function `%s' still exists" x))))) + ;; There shouldn't be left a hook function containing a Tramp ;; function. We do not regard the Tramp unload hooks. (mapatoms @@ -7209,7 +7365,18 @@ Since it unloads Tramp, it shall be the last test to run." (not (string-match-p "unload-hook$" (symbol-name x))) (consp (symbol-value x)) (ignore-errors (all-completions "tramp" (symbol-value x))) - (ert-fail (format "Hook `%s' still contains Tramp function" x)))))) + (ert-fail (format "Hook `%s' still contains Tramp function" x))))) + + ;; There shouldn't be left an advice function from Tramp. + (mapatoms + (lambda (x) + (and (functionp x) + (advice-mapc + (lambda (fun _symbol) + (and (string-match-p "^tramp" (symbol-name fun)) + (ert-fail + (format "Function `%s' still contains Tramp advice" x)))) + x))))) (defun tramp-test-all (&optional interactive) "Run all tests for \\[tramp]. diff --git a/texi/tramp.texi b/texi/tramp.texi index 4f053978eb..3e5c72244c 100644 --- a/texi/tramp.texi +++ b/texi/tramp.texi @@ -4008,8 +4008,10 @@ methods}. Internally, file archives are mounted via the @acronym{GVFS} @option{archive} method. A file archive is a regular file of kind @file{/path/to/dir/file.EXT}. -The extension @samp{.EXT} identifies the type of the file archive. A -file inside a file archive, called archive file name, has the name +The extension @samp{.EXT} identifies the type of the file archive. To +examine the contents of an archive with Dired, open file name as if it +were a directory (i.e., open @file{/path/to/dir/file.EXT/}). A file +inside a file archive, called archive file name, has the name @file{/path/to/dir/file.EXT/dir/file}. Most of the @ref{Magic File Names, , magic file name operations, @@ -4329,6 +4331,20 @@ there. @cindex FAQ @itemize @bullet +@item +What is the official name - ``Tramp'' or ``@value{tramp}''? + +The official name is ``Tramp''. This is used in comments, docstrings, +and everywhere speaking about @value{tramp}. + +However, for historical reasons this is formatted as ``@@sc@{Tramp@}'' +in the @value{tramp} manual. +@ifinfo +@pxref{Smallcaps, , , texinfo}. +@end ifinfo +So it looks different there. + + @item Where is the latest @value{tramp}? diff --git a/texi/trampver.texi b/texi/trampver.texi index 8546c34829..583c3a1df2 100644 --- a/texi/trampver.texi +++ b/texi/trampver.texi @@ -8,7 +8,7 @@ @c In the Tramp GIT, the version numbers are auto-frobbed from @c tramp.el, and the bug report address is auto-frobbed from @c configure.ac. -@set trampver 2.5.2.1 +@set trampver 2.5.2.2 @set trampurl https://www.gnu.org/software/tramp/ @set tramp-bug-report-address tramp-devel@@gnu.org @set emacsver 25.1 diff --git a/tramp-adb.el b/tramp-adb.el index 78e5e2d20f..aa0f558a2b 100644 --- a/tramp-adb.el +++ b/tramp-adb.el @@ -818,7 +818,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (setq infile (tramp-compat-file-name-unquote (expand-file-name infile))) (if (tramp-equal-remote default-directory infile) ;; INFILE is on the same remote host. - (setq input (tramp-file-local-name infile)) + (setq input (tramp-unquote-file-local-name infile)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) tmpinput (tramp-make-tramp-file-name v input)) @@ -849,7 +849,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (setcar (cdr destination) (expand-file-name (cadr destination))) (if (tramp-equal-remote default-directory (cadr destination)) ;; stderr is on the same remote host. - (setq stderr (tramp-file-local-name (cadr destination))) + (setq stderr (tramp-unquote-file-local-name (cadr destination))) ;; stderr must be copied to remote host. The temporary ;; file must be deleted after execution. (setq stderr (tramp-make-tramp-temp-file v) @@ -986,6 +986,10 @@ implementation will be used." (name1 name) (i 0)) + (when (string-match-p "[[:multibyte:]]" command) + (tramp-error + v 'file-error "Cannot apply multi-byte command `%s'" command)) + (while (get-process name1) ;; NAME must be unique as process name. (setq i (1+ i) @@ -1264,7 +1268,7 @@ connection if a previous connection has died for some reason." (if (zerop (length device)) (tramp-error vec 'file-error "Device %s not connected" host)) (with-tramp-progress-reporter vec 3 "Opening adb shell connection" - (let* ((coding-system-for-read 'utf-8-dos) ;is this correct? + (let* ((coding-system-for-read 'utf-8-dos) ; Is this correct? (process-connection-type tramp-process-connection-type) (args (if (> (length host) 0) (list "-s" device "shell") @@ -1368,6 +1372,24 @@ connection if a previous connection has died for some reason." `(:application tramp :protocol ,tramp-adb-method) 'tramp-adb-connection-local-default-shell-profile)) +;; `shell-mode' tries to open remote files like "/adb::~/.history". +;; This fails, because the tilde cannot be expanded. Tell +;; `tramp-handle-expand-file-name' to tolerate this. +(defun tramp-adb-tolerate-tilde (orig-fun) + "Advice for `shell-mode' to tolerate tilde in remote file names." + (let ((tramp-tolerate-tilde + (or tramp-tolerate-tilde + (equal (file-remote-p default-directory 'method) + tramp-adb-method)))) + (funcall orig-fun))) + +(add-function + :around (symbol-function #'shell-mode) #'tramp-adb-tolerate-tilde) +(add-hook 'tramp-adb-unload-hook + (lambda () + (remove-function + (symbol-function #'shell-mode) #'tramp-adb-tolerate-tilde))) + (add-hook 'tramp-unload-hook (lambda () (unload-feature 'tramp-adb 'force))) diff --git a/tramp-archive.el b/tramp-archive.el index 1b5f42a991..77700dc9a0 100644 --- a/tramp-archive.el +++ b/tramp-archive.el @@ -188,6 +188,8 @@ It must be supported by libarchive(3).") "\\)" ;; \1 "\\(" "/" ".*" "\\)" "\\'"))) ;; \2 +(put #'tramp-archive-autoload-file-name-regexp 'tramp-autoload t) + ;; In older Emacsen (prior 27.1), `tramp-archive-autoload-file-name-regexp' ;; is not autoloaded. So we cannot expect it to be known in ;; tramp-loaddefs.el. But it exists, when tramp-archive.el is loaded. @@ -363,6 +365,8 @@ arguments to pass to the OPERATION." (tramp-archive-autoload t)) (apply #'tramp-autoload-file-name-handler operation args))))) +(put #'tramp-archive-autoload-file-name-handler 'tramp-autoload t) + ;;;###autoload (progn (defun tramp-register-archive-file-name-handler () "Add archive file name handler to `file-name-handler-alist'." @@ -372,6 +376,8 @@ arguments to pass to the OPERATION." #'tramp-archive-autoload-file-name-handler)) (put #'tramp-archive-autoload-file-name-handler 'safe-magic t)))) +(put #'tramp-register-archive-file-name-handler 'tramp-autoload t) + ;;;###autoload (progn (add-hook 'after-init-hook #'tramp-register-archive-file-name-handler) diff --git a/tramp-cache.el b/tramp-cache.el index bb17768f0a..347da916ed 100644 --- a/tramp-cache.el +++ b/tramp-cache.el @@ -123,7 +123,7 @@ If KEY is `tramp-cache-undefined', don't create anything, and return nil." (puthash key (make-hash-table :test #'equal) tramp-cache-data))) (when (tramp-file-name-p key) (dolist (elt tramp-connection-properties) - (when (tramp-compat-string-search + (when (string-match-p (or (nth 0 elt) "") (tramp-make-tramp-file-name key 'noloc 'nohop)) (tramp-set-connection-property key (nth 1 elt) (nth 2 elt))))) diff --git a/tramp-crypt.el b/tramp-crypt.el index f8c8bae751..5028e48932 100644 --- a/tramp-crypt.el +++ b/tramp-crypt.el @@ -192,9 +192,9 @@ If NAME doesn't belong to a crypted remote directory, retun nil." ;; `file-name-nondirectory' performed by default handler. ;; `file-name-sans-versions' performed by default handler. (file-newer-than-file-p . tramp-handle-file-newer-than-file-p) - (file-notify-add-watch . ignore) - (file-notify-rm-watch . ignore) - (file-notify-valid-p . ignore) + (file-notify-add-watch . tramp-handle-file-notify-add-watch) + (file-notify-rm-watch . tramp-handle-file-notify-rm-watch) + (file-notify-valid-p . tramp-handle-file-notify-valid-p) (file-ownership-preserved-p . tramp-crypt-handle-file-ownership-preserved-p) (file-readable-p . tramp-crypt-handle-file-readable-p) (file-regular-p . tramp-handle-file-regular-p) diff --git a/tramp-gvfs.el b/tramp-gvfs.el index 948f3b85d3..c09c016e64 100644 --- a/tramp-gvfs.el +++ b/tramp-gvfs.el @@ -1160,10 +1160,9 @@ file names." (tramp-get-connection-property v "default-location" "~") nil t localname 1))) ;; Tilde expansion is not possible. - (when (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname) - (tramp-error - v 'file-error - "Cannot expand tilde in file `%s'" name)) + (when (and (not tramp-tolerate-tilde) + (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)) + (tramp-error v 'file-error "Cannot expand tilde in file `%s'" name)) (unless (tramp-run-real-handler #'file-name-absolute-p (list localname)) (setq localname (concat "/" localname))) ;; We do not pass "/..". @@ -1181,7 +1180,9 @@ file names." ;; No tilde characters in file name, do normal ;; `expand-file-name' (this does "/./" and "/../"). (tramp-make-tramp-file-name - v (tramp-run-real-handler #'expand-file-name (list localname)))))) + v (if (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname) + localname + (tramp-run-real-handler #'expand-file-name (list localname))))))) (defun tramp-gvfs-get-directory-attributes (directory) "Return GVFS attributes association list of all files in DIRECTORY." @@ -1396,7 +1397,8 @@ If FILE-SYSTEM is non-nil, return file system attributes." "Like `file-executable-p' for Tramp files." (with-parsed-tramp-file-name filename nil (with-tramp-file-property v localname "file-executable-p" - (tramp-check-cached-permissions v ?x)))) + (or (tramp-check-cached-permissions v ?x) + (tramp-check-cached-permissions v ?s))))) (defun tramp-gvfs-handle-file-name-all-completions (filename directory) "Like `file-name-all-completions' for Tramp files." @@ -1612,22 +1614,18 @@ ID-FORMAT valid values are `string' and `integer'." (tramp-file-name-user vec) (when-let ((localname (tramp-get-connection-property - (tramp-get-process vec) "share" - (tramp-get-connection-property vec "default-location" nil)))) + (tramp-get-process vec) "share" nil))) (tramp-compat-file-attribute-user-id - (file-attributes - (tramp-make-tramp-file-name vec localname) id-format))))) + (file-attributes (tramp-make-tramp-file-name vec localname) id-format))))) (defun tramp-gvfs-handle-get-remote-gid (vec id-format) "The gid of the remote connection VEC, in ID-FORMAT. ID-FORMAT valid values are `string' and `integer'." (when-let ((localname (tramp-get-connection-property - (tramp-get-process vec) "share" - (tramp-get-connection-property vec "default-location" nil)))) + (tramp-get-process vec) "share" nil))) (tramp-compat-file-attribute-group-id - (file-attributes - (tramp-make-tramp-file-name vec localname) id-format)))) + (file-attributes (tramp-make-tramp-file-name vec localname) id-format)))) (defun tramp-gvfs-handle-set-file-uid-gid (filename &optional uid gid) "Like `tramp-set-file-uid-gid' for Tramp files." @@ -2253,13 +2251,7 @@ connection if a previous connection has died for some reason." COMMAND is a command from the gvfs-* utilities. It is replaced by the corresponding gio tool call if available. `call-process' is applied, and it returns t if the return code is zero." - (let* ((locale (tramp-get-local-locale vec)) - (process-environment - (append - `(,(format "LANG=%s" locale) - ,(format "LANGUAGE=%s" locale) - ,(format "LC_ALL=%s" locale)) - process-environment))) + (let ((locale (tramp-get-local-locale vec))) (when (tramp-gvfs-gio-tool-p vec) ;; Use gio tool. (setq args (cons (cdr (assoc command tramp-gvfs-gio-mapping)) @@ -2269,7 +2261,14 @@ is applied, and it returns t if the return code is zero." (with-current-buffer (tramp-get-connection-buffer vec) (tramp-gvfs-maybe-open-connection vec) (erase-buffer) - (or (zerop (apply #'tramp-call-process vec command nil t nil args)) + (or (zerop + (apply + #'tramp-call-process vec "env" nil t nil + (append `(,(format "LANG=%s" locale) + ,(format "LANGUAGE=%s" locale) + ,(format "LC_ALL=%s" locale) + ,command) + args))) ;; Remove information about mounted connection. (and (tramp-flush-file-properties vec "/") nil))))) diff --git a/tramp-rclone.el b/tramp-rclone.el index b68483657a..318df2de61 100644 --- a/tramp-rclone.el +++ b/tramp-rclone.el @@ -106,9 +106,9 @@ (file-name-nondirectory . tramp-handle-file-name-nondirectory) ;; `file-name-sans-versions' performed by default handler. (file-newer-than-file-p . tramp-handle-file-newer-than-file-p) - (file-notify-add-watch . ignore) - (file-notify-rm-watch . ignore) - (file-notify-valid-p . ignore) + (file-notify-add-watch . tramp-handle-file-notify-add-watch) + (file-notify-rm-watch . tramp-handle-file-notify-rm-watch) + (file-notify-valid-p . tramp-handle-file-notify-valid-p) (file-ownership-preserved-p . ignore) (file-readable-p . tramp-fuse-handle-file-readable-p) (file-regular-p . tramp-handle-file-regular-p) diff --git a/tramp-sh.el b/tramp-sh.el index 243bb0947e..33ff0dabfa 100644 --- a/tramp-sh.el +++ b/tramp-sh.el @@ -1574,6 +1574,7 @@ ID-FORMAT valid values are `string' and `integer'." ;; Examine `file-attributes' cache to see if request can be ;; satisfied without remote operation. (or (tramp-check-cached-permissions v ?x) + (tramp-check-cached-permissions v ?s) (tramp-run-test "-x" filename))))) (defun tramp-sh-handle-file-readable-p (filename) @@ -3083,7 +3084,7 @@ implementation will be used." (setq infile (tramp-compat-file-name-unquote (expand-file-name infile))) (if (tramp-equal-remote default-directory infile) ;; INFILE is on the same remote host. - (setq input (tramp-file-local-name infile)) + (setq input (tramp-unquote-file-local-name infile)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) tmpinput (tramp-make-tramp-file-name v input 'nohop)) @@ -3114,7 +3115,7 @@ implementation will be used." (setcar (cdr destination) (expand-file-name (cadr destination))) (if (tramp-equal-remote default-directory (cadr destination)) ;; stderr is on the same remote host. - (setq stderr (tramp-file-local-name (cadr destination))) + (setq stderr (tramp-unquote-file-local-name (cadr destination))) ;; stderr must be copied to remote host. The temporary ;; file must be deleted after execution. (setq stderr (tramp-make-tramp-temp-file v) @@ -4753,36 +4754,33 @@ Goes through the list `tramp-inline-compress-commands'." (t (setq tramp-ssh-controlmaster-options "") (let ((case-fold-search t)) (ignore-errors - (when (executable-find "ssh") - (with-tramp-progress-reporter - vec 4 "Computing ControlMaster options" - (with-temp-buffer - (tramp-call-process vec "ssh" nil t nil "-o" "ControlMaster") - (goto-char (point-min)) - (when (search-forward-regexp "missing.+argument" nil t) - (setq tramp-ssh-controlmaster-options - "-o ControlMaster=auto"))) - (unless (zerop (length tramp-ssh-controlmaster-options)) - (with-temp-buffer - ;; We use a non-existing IP address, in order to - ;; avoid useless connections, and DNS timeouts. - ;; Setting ConnectTimeout is needed since OpenSSH 7. - (tramp-call-process - vec "ssh" nil t nil - "-o" "ConnectTimeout=1" "-o" "ControlPath=%C" "0.0.0.1") - (goto-char (point-min)) + (with-tramp-progress-reporter + vec 4 "Computing ControlMaster options" + ;; We use a non-existing IP address, in order to avoid + ;; useless connections, and DNS timeouts. + (when (zerop + (tramp-call-process + vec "ssh" nil nil nil + "-G" "-o" "ControlMaster=auto" "0.0.0.1")) + (setq tramp-ssh-controlmaster-options + "-o ControlMaster=auto") + (if (zerop + (tramp-call-process + vec "ssh" nil nil nil + "-G" "-o" "ControlPath='tramp.%C'" "0.0.0.1")) (setq tramp-ssh-controlmaster-options (concat tramp-ssh-controlmaster-options - (if (search-forward-regexp "unknown.+key" nil t) - " -o ControlPath='tramp.%%r@%%h:%%p'" - " -o ControlPath='tramp.%%C'")))) - (with-temp-buffer - (tramp-call-process vec "ssh" nil t nil "-o" "ControlPersist") - (goto-char (point-min)) - (when (search-forward-regexp "missing.+argument" nil t) - (setq tramp-ssh-controlmaster-options - (concat tramp-ssh-controlmaster-options - " -o ControlPersist=no"))))))))) + " -o ControlPath='tramp.%%C'")) + (setq tramp-ssh-controlmaster-options + (concat tramp-ssh-controlmaster-options + " -o ControlPath='tramp.%%r@%%h:%%p'"))) + (when (zerop + (tramp-call-process + vec "ssh" nil nil nil + "-G" "-o" "ControlPersist=no" "0.0.0.1")) + (setq tramp-ssh-controlmaster-options + (concat tramp-ssh-controlmaster-options + " -o ControlPersist=no"))))))) tramp-ssh-controlmaster-options))) (defun tramp-scp-strict-file-name-checking (vec) diff --git a/tramp-smb.el b/tramp-smb.el index 530a4ef6b4..8e9af673e1 100644 --- a/tramp-smb.el +++ b/tramp-smb.el @@ -1287,7 +1287,7 @@ component is used as the target of the symlink." (setq infile (tramp-compat-file-name-unquote (expand-file-name infile))) (if (tramp-equal-remote default-directory infile) ;; INFILE is on the same remote host. - (setq input (tramp-file-local-name infile)) + (setq input (tramp-unquote-file-local-name infile)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) tmpinput (tramp-make-tramp-file-name v input)) diff --git a/tramp-sshfs.el b/tramp-sshfs.el index 45c1e97f8f..17a8be5c3e 100644 --- a/tramp-sshfs.el +++ b/tramp-sshfs.el @@ -51,11 +51,13 @@ (add-to-list 'tramp-methods `(,tramp-sshfs-method (tramp-mount-args (("-C") ("-p" "%p") + ("-o" "transform_symlinks") ("-o" "idmap=user,reconnect"))) ;; These are for remote processes. (tramp-login-program "ssh") - (tramp-login-args (("-q")("-l" "%u") ("-p" "%p") - ("-e" "none") ("%h") ("%l"))) + (tramp-login-args (("-q") ("-l" "%u") ("-p" "%p") + ("-e" "none") ("-t" "-t") + ("%h") ("%l"))) (tramp-direct-async t) (tramp-remote-shell ,tramp-default-remote-shell) (tramp-remote-shell-login ("-l")) @@ -106,9 +108,9 @@ (file-name-nondirectory . tramp-handle-file-name-nondirectory) ;; `file-name-sans-versions' performed by default handler. (file-newer-than-file-p . tramp-handle-file-newer-than-file-p) - (file-notify-add-watch . ignore) - (file-notify-rm-watch . ignore) - (file-notify-valid-p . ignore) + (file-notify-add-watch . tramp-handle-file-notify-add-watch) + (file-notify-rm-watch . tramp-handle-file-notify-rm-watch) + (file-notify-valid-p . tramp-handle-file-notify-valid-p) (file-ownership-preserved-p . ignore) (file-readable-p . tramp-handle-file-readable-p) (file-regular-p . tramp-handle-file-regular-p) @@ -117,7 +119,7 @@ (file-symlink-p . tramp-handle-file-symlink-p) (file-system-info . tramp-sshfs-handle-file-system-info) (file-truename . tramp-handle-file-truename) - (file-writable-p . tramp-handle-file-writable-p) + (file-writable-p . tramp-sshfs-handle-file-writable-p) (find-backup-file-name . tramp-handle-find-backup-file-name) ;; `get-file-buffer' performed by default handler. (insert-directory . tramp-handle-insert-directory) @@ -219,6 +221,10 @@ arguments to pass to the OPERATION." ;;`file-system-info' exists since Emacs 27.1. (tramp-compat-funcall 'file-system-info (tramp-fuse-local-file-name filename))) +(defun tramp-sshfs-handle-file-writable-p (filename) + "Like `file-writable-p' for Tramp files." + (file-writable-p (tramp-fuse-local-file-name filename))) + (defun tramp-sshfs-handle-insert-file-contents (filename &optional visit beg end replace) "Like `insert-file-contents' for Tramp files." @@ -239,12 +245,13 @@ arguments to pass to the OPERATION." (error "Implementation does not handle immediate return")) (with-parsed-tramp-file-name (expand-file-name default-directory) nil - (let ((command + (let ((coding-system-for-read 'utf-8-dos) ; Is this correct? + (command (format "cd %s && exec %s" (tramp-unquote-shell-quote-argument localname) (mapconcat #'tramp-shell-quote-argument (cons program args) " "))) - input tmpinput) + input tmpinput stderr tmpstderr outbuf) ;; Determine input. (if (null infile) @@ -252,18 +259,55 @@ arguments to pass to the OPERATION." (setq infile (tramp-compat-file-name-unquote (expand-file-name infile))) (if (tramp-equal-remote default-directory infile) ;; INFILE is on the same remote host. - (setq input (tramp-file-local-name infile)) + (setq input (tramp-unquote-file-local-name infile)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) tmpinput (tramp-make-tramp-file-name v input 'nohop)) (copy-file infile tmpinput t))) (when input (setq command (format "%s <%s" command input))) + ;; Determine output. + (cond + ;; Just a buffer. + ((bufferp destination) + (setq outbuf destination)) + ;; A buffer name. + ((stringp destination) + (setq outbuf (get-buffer-create destination))) + ;; (REAL-DESTINATION ERROR-DESTINATION) + ((consp destination) + ;; output. + (cond + ((bufferp (car destination)) + (setq outbuf (car destination))) + ((stringp (car destination)) + (setq outbuf (get-buffer-create (car destination)))) + ((car destination) + (setq outbuf (current-buffer)))) + ;; stderr. + (cond + ((stringp (cadr destination)) + (setcar (cdr destination) (expand-file-name (cadr destination))) + (if (tramp-equal-remote default-directory (cadr destination)) + ;; stderr is on the same remote host. + (setq stderr (tramp-unquote-file-local-name (cadr destination))) + ;; stderr must be copied to remote host. The temporary + ;; file must be deleted after execution. + (setq stderr (tramp-make-tramp-temp-file v) + tmpstderr (tramp-make-tramp-file-name v stderr)))) + ;; stderr to be discarded. + ((null (cadr destination)) + (setq stderr (tramp-get-remote-null-device v))))) + ;; 't + (destination + (setq outbuf (current-buffer)))) + (when stderr (setq command (format "%s 2>%s" command stderr))) + (unwind-protect (apply #'tramp-call-process v (tramp-get-method-parameter v 'tramp-login-program) - nil destination display + nil outbuf display (tramp-expand-args v 'tramp-login-args ?h (or (tramp-file-name-host v) "") @@ -271,6 +315,15 @@ arguments to pass to the OPERATION." ?p (or (tramp-file-name-port v) "") ?l command)) + ;; Synchronize stderr. + (when tmpstderr + (tramp-cleanup-connection v 'keep-debug 'keep-password) + (tramp-fuse-unmount v)) + + ;; Provide error file. + (when tmpstderr + (rename-file tmpstderr (cadr destination) t)) + ;; Cleanup. We remove all file cache values for the ;; connection, because the remote process could have changed ;; them. @@ -341,6 +394,13 @@ arguments to pass to the OPERATION." start end (tramp-fuse-local-file-name filename) append 'nomessage) (tramp-flush-file-properties v localname)) + ;; Set file modification time. + (when (or (eq visit t) (stringp visit)) + (set-visited-file-modtime + (or (tramp-compat-file-attribute-modification-time + (file-attributes filename)) + (current-time)))) + ;; Unlock file. (when file-locked ;; `unlock-file' exists since Emacs 28.1. @@ -411,6 +471,24 @@ connection if a previous connection has died for some reason." (with-tramp-connection-property vec "gid-string" (tramp-get-local-gid 'string))) +;; `shell-mode' tries to open remote files like "/sshfs:user@host:~/.history". +;; This fails, because the tilde cannot be expanded. Tell +;; `tramp-handle-expand-file-name' to tolerate this. +(defun tramp-sshfs-tolerate-tilde (orig-fun) + "Advice for `shell-mode' to tolerate tilde in remote file names." + (let ((tramp-tolerate-tilde + (or tramp-tolerate-tilde + (equal (file-remote-p default-directory 'method) + tramp-sshfs-method)))) + (funcall orig-fun))) + +(add-function + :around (symbol-function #'shell-mode) #'tramp-sshfs-tolerate-tilde) +(add-hook 'tramp-sshfs-unload-hook + (lambda () + (remove-function + (symbol-function #'shell-mode) #'tramp-sshfs-tolerate-tilde))) + (add-hook 'tramp-unload-hook (lambda () (unload-feature 'tramp-sshfs 'force))) diff --git a/tramp-sudoedit.el b/tramp-sudoedit.el index 0a18ef3e70..06100fbde0 100644 --- a/tramp-sudoedit.el +++ b/tramp-sudoedit.el @@ -99,9 +99,9 @@ See `tramp-actions-before-shell' for more info.") (file-name-nondirectory . tramp-handle-file-name-nondirectory) ;; `file-name-sans-versions' performed by default handler. (file-newer-than-file-p . tramp-handle-file-newer-than-file-p) - (file-notify-add-watch . ignore) - (file-notify-rm-watch . ignore) - (file-notify-valid-p . ignore) + (file-notify-add-watch . tramp-handle-file-notify-add-watch) + (file-notify-rm-watch . tramp-handle-file-notify-rm-watch) + (file-notify-valid-p . tramp-handle-file-notify-valid-p) (file-ownership-preserved-p . ignore) (file-readable-p . tramp-sudoedit-handle-file-readable-p) (file-regular-p . tramp-handle-file-regular-p) diff --git a/tramp.el b/tramp.el index 7a7790754a..1f64a9eb53 100644 --- a/tramp.el +++ b/tramp.el @@ -2680,6 +2680,8 @@ Falls back to normal file name handler if no Tramp file name handler exists." (load "tramp" 'noerror 'nomessage))) (apply operation args))) +(put #'tramp-autoload-file-name-handler 'tramp-autoload t) + ;; `tramp-autoload-file-name-handler' must be registered before ;; evaluation of site-start and init files, because there might exist ;; remote files already, f.e. files kept via recentf-mode. @@ -2691,6 +2693,7 @@ Falls back to normal file name handler if no Tramp file name handler exists." #'tramp-autoload-file-name-handler)) (put #'tramp-autoload-file-name-handler 'safe-magic t))) +(put #'tramp-register-autoload-file-name-handlers 'tramp-autoload t) ;;;###autoload (tramp-register-autoload-file-name-handlers) (defun tramp-use-absolute-autoload-file-names () @@ -2803,6 +2806,7 @@ Add operations defined in `HANDLER-alist' to `tramp-file-name-handler'." (string-prefix-p "tramp-" (symbol-name (cdr fnh)))) (setq file-name-handler-alist (delq fnh file-name-handler-alist)))))) +(put #'tramp-unload-file-name-handlers 'tramp-autoload t) (add-hook 'tramp-unload-hook #'tramp-unload-file-name-handlers) ;;; File name handler functions for completion mode: @@ -3382,6 +3386,10 @@ User is always nil." (if (file-directory-p dir) dir (file-name-directory dir)) nil (tramp-flush-directory-properties v localname))) +(defvar tramp-tolerate-tilde nil + "Indicator, that not expandable tilde shall be tolerated. +Let-bind it when necessary.") + (defun tramp-handle-expand-file-name (name &optional dir) "Like `expand-file-name' for Tramp files." ;; If DIR is not given, use DEFAULT-DIRECTORY or "/". @@ -3398,6 +3406,10 @@ User is always nil." (with-parsed-tramp-file-name name nil (unless (tramp-run-real-handler #'file-name-absolute-p (list localname)) (setq localname (concat "/" localname))) + ;; Tilde expansion is not possible. + (when (and (not tramp-tolerate-tilde) + (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)) + (tramp-error v 'file-error "Cannot expand tilde in file `%s'" name)) ;; Do not keep "/..". (when (string-match-p "^/\\.\\.?$" localname) (setq localname "/")) @@ -3407,7 +3419,9 @@ User is always nil." (let ((default-directory tramp-compat-temporary-file-directory)) (tramp-make-tramp-file-name v (tramp-drop-volume-letter - (tramp-run-real-handler #'expand-file-name (list localname)))))))) + (if (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname) + localname + (tramp-run-real-handler #'expand-file-name (list localname))))))))) (defun tramp-handle-file-accessible-directory-p (filename) "Like `file-accessible-directory-p' for Tramp files." @@ -3930,6 +3944,14 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.") ;; was visited. (catch 'dont-lock (unless (eq (file-locked-p file) t) ;; Locked by me. + (when (and buffer-file-truename + (not (verify-visited-file-modtime)) + (file-exists-p file)) + ;; In filelock.c, `userlock--ask-user-about-supersession-threat' + ;; is called, which also checks file contents. This is unwise + ;; for remote files. + (ask-user-about-supersession-threat file)) + (when-let ((info (tramp-get-lock-file file)) (match (string-match tramp-lock-file-info-regexp info))) (unless (ask-user-about-lock @@ -4207,7 +4229,9 @@ substitution. SPEC-LIST is a list of char/value pairs used for (command (mapconcat #'tramp-shell-quote-argument command " ")) ;; Set cwd and environment variables. (command - (append `("cd" ,localname "&&" "(" "env") env `(,command ")")))) + (append + `("cd" ,(tramp-shell-quote-argument localname) "&&" "(" "env") + env `(,command ")")))) ;; Check for `tramp-sh-file-name-handler', because something ;; is different between tramp-sh.el, and tramp-adb.el or @@ -4473,10 +4497,7 @@ BUFFER might be a list, in this case STDERR is separated." ;; We must disable cygwin-mount file name ;; handlers and alike. (tramp-run-real-handler - #'substitute-in-file-name (list localname)))))))) - ;; "/m:h:~" does not work for completion. We use "/m:h:~/". - (if (and (stringp localname) (string-equal "~" localname)) - (concat filename "/") + #'substitute-in-file-name (list localname))))))) filename)))) (defconst tramp-time-dont-know '(0 0 0 1000) @@ -5319,7 +5340,8 @@ be granted." (offset (cond ((eq ?r access) 1) ((eq ?w access) 2) - ((eq ?x access) 3)))) + ((eq ?x access) 3) + ((eq ?s access) 3)))) (dolist (suffix '("string" "integer") result) (setq result @@ -5352,7 +5374,8 @@ be granted." (and (eq access (aref (tramp-compat-file-attribute-modes file-attr) offset)) - (or (equal remote-uid + (or (equal remote-uid unknown-id) + (equal remote-uid (tramp-compat-file-attribute-user-id file-attr)) (equal unknown-id (tramp-compat-file-attribute-user-id file-attr)))) @@ -5361,7 +5384,8 @@ be granted." (eq access (aref (tramp-compat-file-attribute-modes file-attr) (+ offset 3))) - (or (equal remote-gid + (or (equal remote-gid unknown-id) + (equal remote-gid (tramp-compat-file-attribute-group-id file-attr)) (equal unknown-id (tramp-compat-file-attribute-group-id @@ -5669,7 +5693,9 @@ Invokes `password-read' if available, `read-passwd' else." (or prompt (with-current-buffer (process-buffer proc) (tramp-check-for-regexp proc tramp-password-prompt-regexp) - (format "%s for %s " (capitalize (match-string 1)) key)))) + (if (string-match-p "passphrase" (match-string 1)) + (match-string 0) + (format "%s for %s " (capitalize (match-string 1)) key))))) (auth-source-creation-prompts `((secret . ,pw-prompt))) ;; Use connection-local value. (auth-sources (with-current-buffer (process-buffer proc) auth-sources)) @@ -5881,6 +5907,8 @@ BODY is the backend specific code." ;; Maybe it's not loaded yet. (ignore-errors (unload-feature 'tramp 'force)))) +(put #'tramp-unload-tramp 'tramp-autoload t) + (provide 'tramp) (run-hooks 'tramp--startup-hook) diff --git a/trampver.el b/trampver.el index a944bfb48f..d68098bfc1 100644 --- a/trampver.el +++ b/trampver.el @@ -7,7 +7,7 @@ ;; Maintainer: Michael Albinus <michael.albi...@gmx.de> ;; Keywords: comm, processes ;; Package: tramp -;; Version: 2.5.2.1 +;; Version: 2.5.2.2 ;; Package-Requires: ((emacs "25.1")) ;; Package-Type: multi ;; URL: https://www.gnu.org/software/tramp/ @@ -40,7 +40,7 @@ ;; ./configure" to change them. ;;;###tramp-autoload -(defconst tramp-version "2.5.2.1" +(defconst tramp-version "2.5.2.2" "This version of Tramp.") ;;;###tramp-autoload @@ -76,7 +76,7 @@ ;; Check for Emacs version. (let ((x (if (not (string-lessp emacs-version "25.1")) "ok" - (format "Tramp 2.5.2.1 is not fit for %s" + (format "Tramp 2.5.2.2 is not fit for %s" (replace-regexp-in-string "\n" "" (emacs-version)))))) (unless (string-equal "ok" x) (error "%s" x)))