emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/tramp aeb0ea7340: Tramp ELPA version 2.5.2.2 released


From: ELPA Syncer
Subject: [elpa] externals/tramp aeb0ea7340: Tramp ELPA version 2.5.2.2 released
Date: Sun, 27 Feb 2022 03:57:53 -0500 (EST)

branch: externals/tramp
commit aeb0ea73406d7d7066149cb487683e55b86e7124
Author: Michael Albinus <michael.albinus@gmx.de>
Commit: Michael Albinus <michael.albinus@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.albinus@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)))
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]