;; would load Tramp. So we make a cheaper check.
;;;###autoload
(defvar tramp-archive-enabled (featurep 'dbusbind)
- "Non-nil when GVFS is available.")
+ "Non-nil when file archive support is available.")
+;; After loading tramp-gvfs.el, we know it better.
(setq tramp-archive-enabled tramp-gvfs-enabled)
;; <https://github.com/libarchive/libarchive/wiki/LibarchiveFormats>
"\\)" ;; \1
"\\(" "/" ".*" "\\)" "\\'"))) ;; \2
+;; 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.
;;;###tramp-autoload
(defconst tramp-archive-file-name-regexp
(ignore-errors (tramp-archive-autoload-file-name-regexp))
(vc-registered . ignore)
(verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime)
(write-region . tramp-archive-handle-not-implemented))
- "Alist of handler functions for GVFS archive method.
+ "Alist of handler functions for file archive method.
Operations not mentioned here will be handled by the default Emacs primitives.")
(defsubst tramp-archive-file-name-for-operation (operation &rest args)
;;;###tramp-autoload
(defun tramp-archive-file-name-handler (operation &rest args)
- "Invoke the GVFS archive related OPERATION.
+ "Invoke the file archive related OPERATION.
First arg specifies the OPERATION, second arg is a list of arguments to
pass to the OPERATION."
(let* ((filename (apply 'tramp-archive-file-name-for-operation
(put 'tramp-archive-file-name-handler 'safe-magic t))))
;;;###autoload
-(add-hook 'after-init-hook 'tramp-register-archive-file-name-handler)
-
+(progn
+ (add-hook 'after-init-hook 'tramp-register-archive-file-name-handler)
+ (add-hook
+ 'tramp-archive-unload-hook
+ (lambda ()
+ (remove-hook
+ 'after-init-hook 'tramp-register-archive-file-name-handler))))
+
+;; In older Emacsen (prior 27.1), the autoload above does not exist.
+;; So we call it again; it doesn't hurt.
(tramp-register-archive-file-name-handler)
;; Mark `operations' the handler is responsible for.
(remove-hook
'url-handler-mode-hook 'tramp-register-file-name-handlers)))))
-;; Debug.
-;(trace-function-background 'tramp-archive-file-name-handler)
-;(trace-function-background 'tramp-gvfs-file-name-handler)
-;(trace-function-background 'tramp-file-name-archive)
-;(trace-function-background 'tramp-archive-dissect-file-name)
-
\f
;; File name conversions.
used `tramp-file-name' structure for tramp-gvfs, and the file
name of a local copy, if any.")
+(defsubst tramp-archive-gvfs-host (archive)
+ "Return host name of ARCHIVE as used in GVFS for mounting"
+ (url-hexify-string (tramp-gvfs-url-file-name archive)))
+
(defun tramp-archive-dissect-file-name (name)
"Return a `tramp-file-name' structure.
The structure consists of the `tramp-archive-method' method, the
(let ((archive
(tramp-make-tramp-file-name
(tramp-archive-dissect-file-name archive) nil 'noarchive)))
- (setf (tramp-file-name-host vec)
- (url-hexify-string (tramp-gvfs-url-file-name archive))))
+ (setf (tramp-file-name-host vec) (tramp-archive-gvfs-host archive)))
(puthash archive (list vec) tramp-archive-hash))
;; http://...
(url-type (url-generic-parse-url archive))
url-tramp-protocols))
(archive (url-tramp-convert-url-to-tramp archive)))
- (setf (tramp-file-name-host vec)
- (url-hexify-string (tramp-gvfs-url-file-name archive))))
+ (setf (tramp-file-name-host vec) (tramp-archive-gvfs-host archive)))
(puthash archive (list vec) tramp-archive-hash))
;; GVFS supported schemes.
((or (tramp-gvfs-file-name-p archive)
(not (file-remote-p archive)))
- (setf (tramp-file-name-host vec)
- (url-hexify-string (tramp-gvfs-url-file-name archive)))
+ (setf (tramp-file-name-host vec) (tramp-archive-gvfs-host archive))
(puthash archive (list vec) tramp-archive-hash))
;; Anything else. Here we call `file-local-copy', which we
(inhibit-file-name-handlers
(cons 'jka-compr-handler inhibit-file-name-handlers))
(copy (file-local-copy archive)))
- (setf (tramp-file-name-host vec)
- (url-hexify-string (tramp-gvfs-url-file-name copy)))
+ (setf (tramp-file-name-host vec) (tramp-archive-gvfs-host copy))
(puthash archive (cons vec copy) tramp-archive-hash))))
;; So far, `vec' handles just the mount point. Add `localname',
;; Autoloading tramp-archive works since Emacs 27.1.
(skip-unless (tramp-archive--test-emacs27-p))
+ ;; tramp-archive is neither loaded at Emacs startup, nor when
+ ;; loading a file like "/ssh::" (which loads Tramp).
(let ((default-directory (expand-file-name temporary-file-directory))
(code
+ "(progn \
+ (message \"tramp-archive loaded: %%s %%s\" \
+ (featurep 'tramp) (featurep 'tramp-archive)) \
+ (file-attributes %S \"/\") \
+ (message \"tramp-archive loaded: %%s %%s\" \
+ (featurep 'tramp) (featurep 'tramp-archive)))"))
+ (dolist (file `("/ssh::foo" ,(concat tramp-archive-test-archive "foo")))
+ (should
+ (string-match
+ (format
+ "tramp-archive loaded: nil nil[[:ascii:]]+tramp-archive loaded: t %s"
+ (tramp-archive-file-name-p file))
+ (shell-command-to-string
(format
- "(message \"Tramp loaded: %%s\" (and (file-exists-p %S) t))"
- tramp-archive-test-archive)))
- (should
- (string-match
- "Tramp loaded: t[\n\r]+"
- (shell-command-to-string
- (format
- "%s -batch -Q -L %s --eval %s"
- (shell-quote-argument
- (expand-file-name invocation-name invocation-directory))
- (mapconcat 'shell-quote-argument load-path " -L ")
- (shell-quote-argument code)))))))
+ "%s -batch -Q -L %s --eval %s"
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat 'shell-quote-argument load-path " -L ")
+ (shell-quote-argument (format code file)))))))))
(ert-deftest tramp-archive-test42-delay-load ()
"Check that `tramp-archive' is loaded lazily, only when needed."
(let ((default-directory (expand-file-name temporary-file-directory))
(code
"(progn \
- (setq tramp-archive-enabled %s) \
- (message \"Tramp loaded: %%s\" (featurep 'tramp-archive)) \
- (find-file %S \"/\") \
- (message \"Tramp loaded: %%s\" (featurep 'tramp-archive)) \
- (file-attributes %S \"/\") \
- (message \"Tramp loaded: %%s\" (featurep 'tramp-archive)))"))
+ (setq tramp-archive-enabled %s) \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)) \
+ (file-attributes %S \"/\") \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)) \
+ (file-attributes %S \"/\") \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)))"))
;; tramp-archive doesn't load when `tramp-archive-enabled' is nil.
(dolist (tae '(t nil))
(should
(string-match
(format
- "Tramp loaded: nil[[:ascii:]]+Tramp loaded: nil[[:ascii:]]+Tramp loaded: %s"
+ "tramp-archive loaded: nil[[:ascii:]]+tramp-archive loaded: nil[[:ascii:]]+tramp-archive loaded: %s"
tae)
(shell-command-to-string
(format