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

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

[elpa] externals/tramp 41bdf56: Tramp ELPA version 2.5.1 released


From: ELPA Syncer
Subject: [elpa] externals/tramp 41bdf56: Tramp ELPA version 2.5.1 released
Date: Tue, 29 Jun 2021 11:57:16 -0400 (EDT)

branch: externals/tramp
commit 41bdf56b37f1b869f8f40eb811b222c562302e7f
Author: Michael Albinus <michael.albinus@gmx.de>
Commit: Michael Albinus <michael.albinus@gmx.de>

    Tramp ELPA version 2.5.1 released
---
 test/tramp-tests.el |  90 ++++++++++++++++++++++++++++++++++-----
 texi/tramp.texi     |  17 +++++---
 tramp-adb.el        |   3 +-
 tramp-archive.el    |   2 +
 tramp-cache.el      |   7 ++--
 tramp-sh.el         |  15 ++-----
 tramp.el            | 118 ++++++++++++++++++++++++++++++++++++----------------
 trampver.el         |   6 +--
 8 files changed, 186 insertions(+), 72 deletions(-)

diff --git a/test/tramp-tests.el b/test/tramp-tests.el
index 66bfe73..68caadb 100644
--- a/test/tramp-tests.el
+++ b/test/tramp-tests.el
@@ -229,6 +229,16 @@ is greater than 10.
        "%s %f sec"
        ,message (float-time (time-subtract (current-time) start))))))
 
+;; `always' is introduced with Emacs 28.1.
+(defalias 'tramp--test-always
+  (if (fboundp 'always)
+      #'always
+    (lambda (&rest _arguments)
+      "Do nothing and return t.
+This function accepts any number of ARGUMENTS, but ignores them.
+Also see `ignore'."
+      t)))
+
 (ert-deftest tramp-test00-availability ()
   "Test availability of Tramp functions."
   :expected-result (if (tramp--test-enabled) :passed :failed)
@@ -2454,9 +2464,9 @@ This checks also `file-name-as-directory', 
`file-name-directory',
                        tramp--test-messages))))))))
 
            ;; Do not overwrite if excluded.
-           (cl-letf (((symbol-function #'y-or-n-p) (lambda (_prompt) t))
+           (cl-letf (((symbol-function #'y-or-n-p) #'tramp--test-always)
                      ;; Ange-FTP.
-                     ((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
+                     ((symbol-function 'yes-or-no-p) #'tramp--test-always))
              (write-region "foo" nil tmp-name nil nil nil 'mustbenew))
            ;; `mustbenew' is passed to Tramp since Emacs 26.1.
            (when (tramp--test-emacs26-p)
@@ -3671,7 +3681,7 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
                (should-error
                 (make-symbolic-link tmp-name1 tmp-name2 0)
                 :type 'file-already-exists)))
-           (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_prompt) t)))
+           (cl-letf (((symbol-function #'yes-or-no-p) #'tramp--test-always))
              (make-symbolic-link tmp-name1 tmp-name2 0)
              (should
               (string-equal
@@ -3747,7 +3757,7 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
               (should-error
                (add-name-to-file tmp-name1 tmp-name2 0)
                :type 'file-already-exists))
-            (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_prompt) t)))
+            (cl-letf (((symbol-function #'yes-or-no-p) #'tramp--test-always))
               (add-name-to-file tmp-name1 tmp-name2 0)
               (should (file-regular-p tmp-name2)))
             (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists)
@@ -4545,7 +4555,7 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
 If UNSTABLE is non-nil, the test is tagged as `:unstable'."
   (declare (indent 1))
   ;; `make-process' supports file name handlers since Emacs 27.
-  (when (let ((file-name-handler-alist '(("" . (lambda (&rest _) t)))))
+  (when (let ((file-name-handler-alist '(("" . #'tramp--test-always))))
          (ignore-errors (make-process :file-handler t)))
     `(ert-deftest ,(intern (concat (symbol-name test) "-direct-async")) ()
        ,docstring
@@ -4561,7 +4571,7 @@ If UNSTABLE is non-nil, the test is tagged as 
`:unstable'."
         ;; `file-truename' does it by side-effect.  Suppress
         ;; `tramp--test-enabled', in order to keep the connection.
         ;; Suppress "Process ... finished" messages.
-        (cl-letf (((symbol-function #'tramp--test-enabled) (lambda nil t))
+        (cl-letf (((symbol-function #'tramp--test-enabled) 
#'tramp--test-always)
                   ((symbol-function #'internal-default-process-sentinel)
                    #'ignore))
           (file-truename tramp-test-temporary-file-directory)
@@ -5554,11 +5564,38 @@ Use direct async.")
                         ("]" . "_r"))
                       (tramp-compat-file-name-unquote tmp-name1)))
                     tmp-name2)))
-                 (should (file-directory-p tmp-name2))))))
+                 (should (file-directory-p tmp-name2)))))
+
+           ;; Create temporary file.  This shall check for sensible
+           ;; files, owned by root.
+           (let ((tramp-auto-save-directory temporary-file-directory)
+                 tramp-allow-unsafe-temporary-files)
+             (write-region "foo" nil tmp-name1)
+             (when (zerop (or (tramp-compat-file-attribute-user-id
+                               (file-attributes tmp-name1))
+                              tramp-unknown-id-integer))
+               (with-temp-buffer
+                 (setq buffer-file-name tmp-name1)
+                 (tramp-cleanup-connection
+                  tramp-test-vec 'keep-debug 'keep-password)
+                 (let ((tramp-allow-unsafe-temporary-files t))
+                   (should (stringp (make-auto-save-file-name))))
+                 (tramp-cleanup-connection
+                  tramp-test-vec 'keep-debug 'keep-password)
+                 (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
+                   (should-error
+                    (make-auto-save-file-name)
+                    :type 'file-error))
+                 (tramp-cleanup-connection
+                  tramp-test-vec 'keep-debug 'keep-password)
+                 (cl-letf (((symbol-function #'yes-or-no-p)
+                            #'tramp--test-always))
+                   (should (stringp (make-auto-save-file-name))))))))
 
        ;; Cleanup.
        (ignore-errors (delete-file tmp-name1))
-       (ignore-errors (delete-directory tmp-name2 'recursive))))))
+       (ignore-errors (delete-directory tmp-name2 'recursive))
+       (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)))))
 
 (ert-deftest tramp-test38-find-backup-file-name ()
   "Check `find-backup-file-name'."
@@ -5672,7 +5709,37 @@ Use direct async.")
              (should (file-directory-p tmp-name2))))
 
        ;; Cleanup.
-       (ignore-errors (delete-directory tmp-name2 'recursive))))))
+       (ignore-errors (delete-directory tmp-name2 'recursive)))
+
+      (unwind-protect
+         ;; Create temporary file.  This shall check for sensible
+         ;; files, owned by root.
+         (let ((backup-directory-alist `(("." . ,temporary-file-directory)))
+               tramp-allow-unsafe-temporary-files
+               tramp-backup-directory-alist)
+           (write-region "foo" nil tmp-name1)
+           (when (zerop (or (tramp-compat-file-attribute-user-id
+                             (file-attributes tmp-name1))
+                            tramp-unknown-id-integer))
+             (tramp-cleanup-connection
+              tramp-test-vec 'keep-debug 'keep-password)
+             (let ((tramp-allow-unsafe-temporary-files t))
+               (should (stringp (car (find-backup-file-name tmp-name1)))))
+             (tramp-cleanup-connection
+              tramp-test-vec 'keep-debug 'keep-password)
+             (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
+               (should-error
+                (find-backup-file-name tmp-name1)
+                :type 'file-error))
+             (tramp-cleanup-connection
+              tramp-test-vec 'keep-debug 'keep-password)
+             (cl-letf (((symbol-function #'yes-or-no-p)
+                        #'tramp--test-always))
+               (should (stringp (car (find-backup-file-name tmp-name1)))))))
+
+       ;; Cleanup.
+       (ignore-errors (delete-file tmp-name1))
+       (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)))))
 
 ;; The functions were introduced in Emacs 26.1.
 (ert-deftest tramp-test39-make-nearby-temp-file ()
@@ -6213,8 +6280,9 @@ Use the `ls' command."
                      x ""))
              (not (string-empty-p x))
             ;; ?\n and ?/ shouldn't be part of any file name.  ?\t,
-            ;; ?. and ?? do not work for "smb" method.
-            (replace-regexp-in-string "[\t\n/.?]" "" x)))
+            ;; ?. and ?? do not work for "smb" method.  " " does not
+            ;; work at begin or end of the string for MS Windows.
+            (replace-regexp-in-string "[ \t\n/.?]" "" x)))
          language-info-alist)))))))
 
 (ert-deftest tramp-test41-utf8 ()
diff --git a/texi/tramp.texi b/texi/tramp.texi
index 63b6eb8..9c20b3d 100644
--- a/texi/tramp.texi
+++ b/texi/tramp.texi
@@ -1261,7 +1261,7 @@ uses @file{@trampfn{mtp,,}} as the default name.
 As the name indicates, the method @option{nextcloud} allows you to
 access OwnCloud or NextCloud hosted files and directories.  Like the
 @option{gdrive} method, your credentials must be populated in your
-@command{Online Accounts} application outside Emacs. The method
+@command{Online Accounts} application outside Emacs.  The method
 supports port numbers.
 
 @item @option{sftp}
@@ -2842,6 +2842,13 @@ auto-saved files to the same directory as the original 
file.
 Alternatively, set the user option @code{tramp-auto-save-directory}
 to direct all auto saves to that location.
 
+@vindex tramp-allow-unsafe-temporary-files
+Per default, @value{tramp} asks for confirmation if a
+@samp{root}-owned backup or auto-save remote file has to be written to
+your local temporary directory.  If you want to suppress this
+confirmation question, set user option
+@code{tramp-allow-unsafe-temporary-files} to @code{t}.
+
 
 @node Keeping files encrypted
 @section Protect remote files by encryption
@@ -3309,12 +3316,12 @@ For ad-hoc definitions to be saved automatically in
 
 Ad-hoc proxies can take patterns @code{%h} or @code{%u} like in
 @code{tramp-default-proxies-alist}.  The following file name expands
-to user @code{root} on host @code{remotehost}, starting with an
-@option{ssh} session on host @code{remotehost}:
+to user @samp{root} on host @samp{remotehost}, starting with an
+@option{ssh} session on host @samp{remotehost}:
 
@samp{@value{prefix}ssh@value{postfixhop}%h|su@value{postfixhop}remotehost@value{postfix}}.
 
 On the other hand, if a trailing hop does not specify a host name,
-the host name of the previous hop is reused. Therefore, the following
+the host name of the previous hop is reused.  Therefore, the following
 file name is equivalent to the previous example:
 
@samp{@value{prefix}ssh@value{postfixhop}remotehost|su@value{postfixhop}@value{postfix}}.
 
@@ -5294,7 +5301,7 @@ attributes cache in its process sentinel with this code:
 @end lisp
 
 Since @value{tramp} traverses subdirectories starting with the
-root-directory, it is most likely sufficient to make the
+root directory, it is most likely sufficient to make the
 @code{default-directory} of the process buffer as the root directory.
 
 
diff --git a/tramp-adb.el b/tramp-adb.el
index aacf83e..7fb0ff5 100644
--- a/tramp-adb.el
+++ b/tramp-adb.el
@@ -549,8 +549,7 @@ But handle the case, if the \"test\" command is not 
available."
       (when (and append (file-exists-p filename))
        (copy-file filename tmpfile 'ok)
        (set-file-modes tmpfile (logior (or (file-modes tmpfile) 0) #o0600)))
-      (tramp-run-real-handler
-       #'write-region (list start end tmpfile append 'no-message lockname))
+      (write-region start end tmpfile append 'no-message lockname)
       (with-tramp-progress-reporter
         v 3 (format-message
              "Moving tmp file `%s' to `%s'" tmpfile filename)
diff --git a/tramp-archive.el b/tramp-archive.el
index d2ee729..d723fd5 100644
--- a/tramp-archive.el
+++ b/tramp-archive.el
@@ -328,6 +328,8 @@ arguments to pass to the OPERATION."
         ;; `filename' could be a quoted file name.  Or the file
         ;; archive could be a directory, see Bug#30293.
         (if (or (null archive)
+                (not (tramp-archive-run-real-handler
+                      #'file-exists-p (list archive)))
                (tramp-archive-run-real-handler
                  #'file-directory-p (list archive)))
             (tramp-archive-run-real-handler operation args)
diff --git a/tramp-cache.el b/tramp-cache.el
index 4d5edc5..2d11c89 100644
--- a/tramp-cache.el
+++ b/tramp-cache.el
@@ -70,7 +70,8 @@
 ;;   process key retrieved by `tramp-get-process' (the main connection
 ;;   process).  Other processes could reuse these properties, avoiding
 ;;   recomputation when a new asynchronous process is created by
-;;   `make-process'.  Examples are "remote-path" or "device" (tramp-adb.el).
+;;   `make-process'.  Examples are "remote-path",
+;;   "unsafe-temporary-file" or "device" (tramp-adb.el).
 
 ;;; Code:
 
@@ -472,11 +473,11 @@ used to cache connection properties of the local machine."
        ;; don't save either, because all other properties might
        ;; depend on the login name, and we want to give the
        ;; possibility to use another login name later on.  Key
-       ;; "started" exists for the "ftp" method only, which must be
+       ;; "started" exists for the "ftp" method only, which must not
        ;; be kept persistent.
        (maphash
         (lambda (key value)
-          (if (and (tramp-file-name-p key) value
+          (if (and (tramp-file-name-p key) (hash-table-p value)
                    (not (string-equal
                          (tramp-file-name-method key) tramp-archive-method))
                    (not (tramp-file-name-localname key))
diff --git a/tramp-sh.el b/tramp-sh.el
index 29ed944..ebd0fbf 100644
--- a/tramp-sh.el
+++ b/tramp-sh.el
@@ -3225,7 +3225,6 @@ implementation will be used."
       (run-hooks 'tramp-handle-file-local-copy-hook)
       tmpfile)))
 
-;; CCC grok LOCKNAME
 (defun tramp-sh-handle-write-region
   (start end filename &optional append visit lockname mustbenew)
   "Like `write-region' for Tramp files."
@@ -3254,9 +3253,7 @@ implementation will be used."
                  (or (file-directory-p localname)
                      (file-writable-p localname)))))
          ;; Short track: if we are on the local host, we can run directly.
-         (tramp-run-real-handler
-          #'write-region
-          (list start end localname append 'no-message lockname))
+         (write-region start end localname append 'no-message lockname)
 
        (let* ((modes (tramp-default-file-modes
                       filename (and (eq mustbenew 'excl) 'nofollow)))
@@ -3289,13 +3286,10 @@ implementation will be used."
          ;; file.  We call `set-visited-file-modtime' ourselves later
          ;; on.  We must ensure that `file-coding-system-alist'
          ;; matches `tmpfile'.
-         (let (file-name-handler-alist
-               (file-coding-system-alist
+         (let ((file-coding-system-alist
                 (tramp-find-file-name-coding-system-alist filename tmpfile)))
            (condition-case err
-               (tramp-run-real-handler
-                #'write-region
-                (list start end tmpfile append 'no-message lockname))
+               (write-region start end tmpfile append 'no-message lockname)
              ((error quit)
               (setq tramp-temp-buffer-file-name nil)
               (delete-file tmpfile)
@@ -5296,8 +5290,7 @@ Nonexistent directories are removed from spec."
        ;; cache the result for the session only.  Otherwise, the
        ;; result is cached persistently.
        (if (memq 'tramp-own-remote-path tramp-remote-path)
-           (tramp-get-process vec)
-         vec)
+           (tramp-get-process vec) vec)
        "remote-path"
       (let* ((remote-path (copy-tree tramp-remote-path))
             (elt1 (memq 'tramp-default-remote-path remote-path))
diff --git a/tramp.el b/tramp.el
index 0b80175..10f4a2b 100644
--- a/tramp.el
+++ b/tramp.el
@@ -2052,7 +2052,7 @@ function is meant for debugging purposes."
 
 (put #'tramp-backtrace 'tramp-suppress-trace t)
 
-(defsubst tramp-error (vec-or-proc signal fmt-string &rest arguments)
+(defun tramp-error (vec-or-proc signal fmt-string &rest arguments)
   "Emit an error.
 VEC-OR-PROC identifies the connection to use, SIGNAL is the
 signal identifier to be raised, remaining arguments passed to
@@ -2644,7 +2644,14 @@ If Emacs is compiled --with-threads, the body is 
protected by a mutex."
 
       ;; When `tramp-mode' is not enabled, or the file name is quoted,
       ;; we don't do anything.
-      (tramp-run-real-handler operation args))))
+      ;; When operation is `expand-file-name', and the first argument
+      ;; is a local absolute file name, we end also here.  Handle the
+      ;; MS Windows case.
+      (funcall
+       (if (and (eq operation 'expand-file-name)
+               (not (string-match-p "\\`[[:alpha:]]:/" (car args))))
+          #'tramp-drop-volume-letter #'identity)
+       (tramp-run-real-handler operation args)))))
 
 (defun tramp-completion-file-name-handler (operation &rest args)
   "Invoke Tramp file name completion handler for OPERATION and ARGS.
@@ -3661,6 +3668,11 @@ User is always nil."
        (and (file-directory-p (file-name-directory filename))
             (file-writable-p (file-name-directory filename)))))))
 
+(defcustom tramp-allow-unsafe-temporary-files nil
+  "Whether root-owned auto-save or backup files can be written to \"/tmp\"."
+  :version "28.1"
+  :type 'boolean)
+
 (defun tramp-handle-find-backup-file-name (filename)
   "Like `find-backup-file-name' for Tramp files."
   (with-parsed-tramp-file-name filename nil
@@ -3676,8 +3688,25 @@ User is always nil."
                       (tramp-make-tramp-file-name v (cdr x))
                     (cdr x))))
                tramp-backup-directory-alist)
-            backup-directory-alist)))
-      (tramp-run-real-handler #'find-backup-file-name (list filename)))))
+            backup-directory-alist))
+         result)
+      (prog1 ;; Run plain `find-backup-file-name'.
+         (setq result
+               (tramp-run-real-handler
+                #'find-backup-file-name (list filename)))
+        ;; Protect against security hole.
+       (when (and (not tramp-allow-unsafe-temporary-files)
+                  (file-in-directory-p (car result) temporary-file-directory)
+                  (zerop (or (tramp-compat-file-attribute-user-id
+                              (file-attributes filename 'integer))
+                             tramp-unknown-id-integer))
+                  (not (with-tramp-connection-property
+                           (tramp-get-process v) "unsafe-temporary-file"
+                         (yes-or-no-p
+                          (concat
+                           "Backup file on local temporary directory, "
+                           "do you want to continue? ")))))
+         (tramp-error v 'file-error "Unsafe backup file name"))))))
 
 (defun tramp-handle-insert-directory
   (filename switches &optional wildcard full-directory-p)
@@ -4398,8 +4427,7 @@ of."
       ;; We say `no-message' here because we don't want the visited file
       ;; modtime data to be clobbered from the temp file.  We call
       ;; `set-visited-file-modtime' ourselves later on.
-      (tramp-run-real-handler
-       #'write-region (list start end tmpfile append 'no-message lockname))
+      (write-region start end tmpfile append 'no-message lockname)
       (condition-case nil
          (rename-file tmpfile filename 'ok-if-already-exists)
        (error
@@ -5259,37 +5287,53 @@ Return the local name of the temporary file."
   "Like `make-auto-save-file-name' for Tramp files.
 Returns a file name in `tramp-auto-save-directory' for autosaving
 this file, if that variable is non-nil."
-  (when (stringp tramp-auto-save-directory)
-    (setq tramp-auto-save-directory
-         (expand-file-name tramp-auto-save-directory)))
-  ;; Create directory.
-  (unless (or (null tramp-auto-save-directory)
-             (file-exists-p tramp-auto-save-directory))
-    (make-directory tramp-auto-save-directory t))
-
-  (let ((system-type
-        (if (and (stringp tramp-auto-save-directory)
-                 (tramp-tramp-file-p tramp-auto-save-directory))
-            'not-windows
-          system-type))
-       (auto-save-file-name-transforms
-        (if (null tramp-auto-save-directory)
-            auto-save-file-name-transforms))
-       (buffer-file-name
-        (if (null tramp-auto-save-directory)
-            buffer-file-name
-          (expand-file-name
-           (tramp-subst-strs-in-string
-            '(("_" . "|")
-              ("/" . "_a")
-              (":" . "_b")
-              ("|" . "__")
-              ("[" . "_l")
-              ("]" . "_r"))
-            (tramp-compat-file-name-unquote (buffer-file-name)))
-           tramp-auto-save-directory))))
-    ;; Run plain `make-auto-save-file-name'.
-    (tramp-run-real-handler #'make-auto-save-file-name nil)))
+  (with-parsed-tramp-file-name buffer-file-name nil
+    (when (stringp tramp-auto-save-directory)
+      (setq tramp-auto-save-directory
+           (expand-file-name tramp-auto-save-directory)))
+    ;; Create directory.
+    (unless (or (null tramp-auto-save-directory)
+               (file-exists-p tramp-auto-save-directory))
+      (make-directory tramp-auto-save-directory t))
+
+    (let ((system-type
+          (if (and (stringp tramp-auto-save-directory)
+                   (tramp-tramp-file-p tramp-auto-save-directory))
+              'not-windows
+            system-type))
+         (auto-save-file-name-transforms
+          (if (null tramp-auto-save-directory)
+              auto-save-file-name-transforms))
+         (filename buffer-file-name)
+         (buffer-file-name
+          (if (null tramp-auto-save-directory)
+              buffer-file-name
+            (expand-file-name
+             (tramp-subst-strs-in-string
+              '(("_" . "|")
+                ("/" . "_a")
+                (":" . "_b")
+                ("|" . "__")
+                ("[" . "_l")
+                ("]" . "_r"))
+              (tramp-compat-file-name-unquote (buffer-file-name)))
+             tramp-auto-save-directory)))
+         result)
+      (prog1 ;; Run plain `make-auto-save-file-name'.
+         (setq result (tramp-run-real-handler #'make-auto-save-file-name nil))
+       ;; Protect against security hole.
+       (when (and (not tramp-allow-unsafe-temporary-files)
+                  (file-in-directory-p result temporary-file-directory)
+                  (zerop (or (tramp-compat-file-attribute-user-id
+                              (file-attributes filename 'integer))
+                             tramp-unknown-id-integer))
+                  (not (with-tramp-connection-property
+                           (tramp-get-process v) "unsafe-temporary-file"
+                         (yes-or-no-p
+                          (concat
+                           "Autosave file on local temporary directory, "
+                           "do you want to continue? ")))))
+         (tramp-error v 'file-error "Unsafe autosave file name"))))))
 
 (defun tramp-subst-strs-in-string (alist string)
   "Replace all occurrences of the string FROM with TO in STRING.
diff --git a/trampver.el b/trampver.el
index 6c041b2..e6cf4c6 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.0.5
+;; Version: 2.5.1
 ;; 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.0.5"
+(defconst tramp-version "2.5.1"
   "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.0.5 is not fit for %s"
+    (format "Tramp 2.5.1 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]