]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix Bug#30293
authorMichael Albinus <michael.albinus@gmx.de>
Wed, 31 Jan 2018 14:02:46 +0000 (15:02 +0100)
committerMichael Albinus <michael.albinus@gmx.de>
Wed, 31 Jan 2018 14:02:46 +0000 (15:02 +0100)
* lisp/net/tramp-archive.el (tramp-archive-file-name-for-operation):
New defsubst.
(tramp-archive-file-name-archive, tramp-archive-file-name-localname):
New defuns.
(tramp-archive-file-name-handler, tramp-archive-dissect-file-name)
(tramp-archive-handle-not-implemented): Use them.  (Bug#30293)

* test/lisp/net/tramp-archive-tests.el (tramp-archive-test-directory):
New defconst.
(tramp-archive-test01-file-name-syntax): Extend test.
(tramp-archive-test05-expand-file-name-non-archive-directory):
New test.  (Bug#30293)

* test/lisp/net/tramp-archive-resources/foo.iso/foo: New file.

lisp/net/tramp-archive.el
test/lisp/net/tramp-archive-resources/foo.iso/foo [new file with mode: 0644]
test/lisp/net/tramp-archive-tests.el

index 51ee18fac7ab262ab2a4476775a98232750b547d..8d292e16023c103eb78b80f01f2cb1becb2495b1 100644 (file)
@@ -253,21 +253,33 @@ It must be supported by libarchive(3).")
   "Alist of handler functions for GVFS archive method.
 Operations not mentioned here will be handled by the default Emacs primitives.")
 
+(defsubst tramp-archive-file-name-for-operation (operation &rest args)
+  "Like `tramp-file-name-for-operation', but for archive file name syntax."
+  (cl-letf (((symbol-function 'tramp-tramp-file-p) 'tramp-archive-file-name-p))
+    (apply 'tramp-file-name-for-operation operation args)))
+
 ;;;###tramp-autoload
 (defun tramp-archive-file-name-handler (operation &rest args)
   "Invoke the GVFS archive related OPERATION.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
-  (unless tramp-gvfs-enabled
-    (tramp-compat-user-error nil "Package `tramp-archive' not supported"))
-  (let ((tramp-methods (cons `(,tramp-archive-method) tramp-methods))
-       (tramp-gvfs-methods tramp-archive-all-gvfs-methods)
-       (fn (assoc operation tramp-archive-file-name-handler-alist)))
-    (when (eq (cdr fn) 'tramp-archive-handle-not-implemented)
-      (setq args (cons operation args)))
-    (if fn
-       (save-match-data (apply (cdr fn) args))
-      (tramp-run-real-handler operation args))))
+  (let* ((filename (apply 'tramp-archive-file-name-for-operation
+                         operation args))
+        (archive (tramp-archive-file-name-archive filename)))
+    ;; The file archive could be a directory, see Bug#30293.
+    (if (file-directory-p archive)
+       (tramp-run-real-handler operation args)
+      ;; Now run the handler.
+      (unless tramp-gvfs-enabled
+       (tramp-compat-user-error nil "Package `tramp-archive' not supported"))
+      (let ((tramp-methods (cons `(,tramp-archive-method) tramp-methods))
+           (tramp-gvfs-methods tramp-archive-all-gvfs-methods)
+           (fn (assoc operation tramp-archive-file-name-handler-alist)))
+       (when (eq (cdr fn) 'tramp-archive-handle-not-implemented)
+         (setq args (cons operation args)))
+       (if fn
+           (save-match-data (apply (cdr fn) args))
+         (tramp-run-real-handler operation args))))))
 
 ;; Mark `operations' the handler is responsible for.
 (put 'tramp-archive-file-name-handler 'operations
@@ -300,6 +312,16 @@ pass to the OPERATION."
        (string-match tramp-archive-file-name-regexp name)
        t))
 
+(defun tramp-archive-file-name-archive (name)
+  "Return archive part of NAME."
+  (and (tramp-archive-file-name-p name)
+       (match-string 1 name)))
+
+(defun tramp-archive-file-name-localname (name)
+  "Return localname part of NAME."
+  (and (tramp-archive-file-name-p name)
+       (match-string 2 name)))
+
 (defvar tramp-archive-hash (make-hash-table :test 'equal)
   "Hash table for archive local copies.
 The hash key is the archive name.  The value is a cons of the
@@ -314,9 +336,8 @@ name is kept in slot `hop'"
   (save-match-data
     (unless (tramp-archive-file-name-p name)
       (tramp-compat-user-error nil "Not an archive file name: \"%s\"" name))
-    ;; The `string-match' happened in `tramp-archive-file-name-p'.
-    (let* ((localname (match-string 2 name))
-          (archive (file-truename (match-string 1 name)))
+    (let* ((localname (tramp-archive-file-name-localname name))
+          (archive (file-truename (tramp-archive-file-name-archive name)))
           (vec (make-tramp-file-name
                 :method tramp-archive-method :hop archive)))
 
@@ -535,7 +556,7 @@ offered."
   "Generic handler for operations not implemented for file archives."
   (let ((v (ignore-errors
             (tramp-archive-dissect-file-name
-             (apply 'tramp-file-name-for-operation operation args)))))
+             (apply 'tramp-archive-file-name-for-operation operation args)))))
     (tramp-message v 10 "%s" (cons operation args))
     (tramp-error
      v 'file-error
diff --git a/test/lisp/net/tramp-archive-resources/foo.iso/foo b/test/lisp/net/tramp-archive-resources/foo.iso/foo
new file mode 100644 (file)
index 0000000..257cc56
--- /dev/null
@@ -0,0 +1 @@
+foo
index ecfee0c556c08b83a8363b54a34bbde870a95f81..96c6a71097c4b510b469926c4e672be3a4b6f933 100644 (file)
   (file-name-as-directory tramp-archive-test-file-archive)
   "The test archive.")
 
+(defconst tramp-archive-test-directory
+  (file-truename
+   (expand-file-name "foo.iso" tramp-archive-test-resource-directory))
+  "A directory file name, which looks like an archive.")
+
 (setq password-cache-expiry nil
       tramp-verbose 0
       tramp-cache-read-persistent-data t ;; For auth-sources.
@@ -94,14 +99,51 @@ variables, so we check the Emacs version directly."
   "Check archive file name syntax."
   (should-not (tramp-archive-file-name-p tramp-archive-test-file-archive))
   (should (tramp-archive-file-name-p tramp-archive-test-archive))
+  (should
+   (string-equal
+    (tramp-archive-file-name-archive tramp-archive-test-archive)
+    tramp-archive-test-file-archive))
+  (should
+   (string-equal
+    (tramp-archive-file-name-localname tramp-archive-test-archive) "/"))
   (should (tramp-archive-file-name-p (concat tramp-archive-test-archive "foo")))
+  (should
+   (string-equal
+    (tramp-archive-file-name-localname
+     (concat tramp-archive-test-archive "foo"))
+    "/foo"))
   (should
    (tramp-archive-file-name-p (concat tramp-archive-test-archive "foo/bar")))
+  (should
+   (string-equal
+    (tramp-archive-file-name-localname
+     (concat tramp-archive-test-archive "foo/bar"))
+    "/foo/bar"))
   ;; A file archive inside a file archive.
   (should
    (tramp-archive-file-name-p (concat tramp-archive-test-archive "baz.tar")))
   (should
-   (tramp-archive-file-name-p (concat tramp-archive-test-archive "baz.tar/"))))
+   (string-equal
+    (tramp-archive-file-name-archive
+     (concat tramp-archive-test-archive "baz.tar"))
+    tramp-archive-test-file-archive))
+  (should
+   (string-equal
+    (tramp-archive-file-name-localname
+     (concat tramp-archive-test-archive "baz.tar"))
+    "/baz.tar"))
+  (should
+   (tramp-archive-file-name-p (concat tramp-archive-test-archive "baz.tar/")))
+  (should
+   (string-equal
+    (tramp-archive-file-name-archive
+     (concat tramp-archive-test-archive "baz.tar/"))
+    (concat tramp-archive-test-archive "baz.tar")))
+  (should
+   (string-equal
+    (tramp-archive-file-name-localname
+     (concat tramp-archive-test-archive "baz.tar/"))
+    "/")))
 
 (ert-deftest tramp-archive-test02-file-name-dissect ()
   "Check archive file name components."
@@ -205,6 +247,21 @@ variables, so we check the Emacs version directly."
   (should (string-equal (expand-file-name "/foo.tar/./file") "/foo.tar/file"))
   (should (string-equal (expand-file-name "/foo.tar/../file") "/file")))
 
+;; This test is inspired by Bug#30293.
+(ert-deftest tramp-archive-test05-expand-file-name-non-archive-directory ()
+  "Check existing directories with archive file name syntax.
+They shall still be supported"
+  (should (file-directory-p tramp-archive-test-directory))
+  ;; `tramp-archive-file-name-p' tests only for file name syntax.  It
+  ;; doesn't test, whether it is really a file archive.
+  (should
+   (tramp-archive-file-name-p
+    (file-name-as-directory tramp-archive-test-directory)))
+  (should
+   (file-directory-p (file-name-as-directory tramp-archive-test-directory)))
+  (should
+   (file-exists-p (expand-file-name "foo" tramp-archive-test-directory))))
+
 (ert-deftest tramp-archive-test06-directory-file-name ()
   "Check `directory-file-name'.
 This checks also `file-name-as-directory', `file-name-directory',