@end lisp
+@subsection Using different proxies for the same destination
+
+@strong{Note}: This feature is experimental, don't use it in
+production systems!
+
+Sometimes, it is needed to specify different proxies for the same
+destination host name. This can happen for the same destination when
+the local host is located in different networks over the time. This
+can also happen when the remote destination is specified by the remote
+same file name, although different hosts are meant depending on the
+used proxy. A typical example are docker containers, which run on
+different hosts under the same docker name.
+
+When the user option @code{tramp-show-ad-hoc-proxies} is
+non-@code{nil}, such ad-hoc multi-hop file names can be used in
+parallel. In the following, on both remote hosts @samp{host1} and
+@samp{host2} there is a docker container @samp{name}, respectively:
+
+@example
+@trampfn{ssh@value{postfixhop}user1@@host1|docker,name,}
+@trampfn{ssh@value{postfixhop}user2@@host2|docker,name,}
+@end example
+
+
@node Home directories
@section Expanding @file{~} to home directory
(defun tramp-cleanup-connection
(vec &optional keep-debug keep-password keep-processes)
"Flush all connection related objects.
-This includes password cache, file cache, connection cache,
-buffers, processes. KEEP-DEBUG non-nil preserves the debug
-buffer. KEEP-PASSWORD non-nil preserves the password cache.
-KEEP-PROCESSES non-nil preserves the asynchronous processes.
-When called interactively, a Tramp connection has to be selected."
+This includes password cache, file cache, connection cache, buffers,
+processes. KEEP-DEBUG non-nil preserves the debug and trace buffer.
+KEEP-PASSWORD non-nil preserves the password cache. KEEP-PROCESSES
+non-nil preserves the asynchronous processes. When called
+interactively, a Tramp connection has to be selected."
(declare (completion tramp-active-command-completion-p))
(interactive
;; When interactive, select the Tramp remote identification.
;; Assure that the hops are in `tramp-default-proxies-alist'.
;; In tramp-archive.el, the slot `hop' is used for the archive
;; file name.
- (unless (string-equal method tramp-archive-method)
+ (unless (or minibuffer-completing-file-name
+ (string-equal method tramp-archive-method))
(tramp-add-hops (car args)))))
(t (setq method (nth 0 args)
;; the empty string. Suppress adding a hop to
;; `tramp-default-proxies-alist' due to non-expanded default values.
(let ((v (tramp-dissect-file-name file t))
- tramp-default-proxies-alist)
+ (tramp-default-proxies-alist tramp-cache-undefined))
;; Run the command on the localname portion only unless we are in
;; completion mode.
(tramp-make-tramp-file-name
;; the remote file name parts. Suppress adding a hop to
;; `tramp-default-proxies-alist' due to non-expanded default values.
(let ((v (tramp-dissect-file-name file t))
- tramp-default-proxies-alist)
+ (tramp-default-proxies-alist tramp-cache-undefined))
;; Run the command on the localname portion only. If this returns
;; nil, mark also the localname part of `v' as nil.
(tramp-make-tramp-file-name
(defun tramp-add-hops (vec)
"Add ad-hoc proxy definitions to `tramp-default-proxies-alist'."
- (when-let ((hops (tramp-file-name-hop vec))
- (item vec))
+ ;; `tramp-default-proxies-alist' is bound to `tramp-cache-undefined'
+ ;; in `tramp-handle-file-name-as-directory' and
+ ;; `tramp-handle-file-name-directory' suppressing to add a hop.
+ (when-let* (((not (eq tramp-default-proxies-alist tramp-cache-undefined)))
+ (hops (tramp-file-name-hop vec))
+ (item vec))
(let (signal-hook-function changed)
(dolist
(proxy (reverse (split-string hops tramp-postfix-hop-regexp 'omit)))
(let* ((host-port (tramp-file-name-host-port item))
+ (host-port (and (stringp host-port)
+ (rx bol (literal host-port) eol)))
(user-domain (tramp-file-name-user-domain item))
+ (user-domain (and (stringp user-domain)
+ (rx bol (literal user-domain) eol)))
(proxy (concat
tramp-prefix-format proxy tramp-postfix-host-format))
(entry
- (list (and (stringp host-port)
- (rx bol (literal host-port) eol))
- (and (stringp user-domain)
- (rx bol (literal user-domain) eol))
- (propertize proxy 'tramp-ad-hoc t))))
+ (list host-port user-domain (propertize proxy 'tramp-ad-hoc t))))
+ ;; Remove superfluous entries.
+ (when tramp-show-ad-hoc-proxies
+ (dolist (entry1 tramp-default-proxies-alist)
+ (when (and (equal host-port (car entry1))
+ (equal user-domain (cadr entry1))
+ (not (equal proxy (caddr entry1))))
+ (tramp-message
+ vec 5 "Remove %S from `tramp-default-proxies-alist'" entry1)
+ (tramp-cleanup-connection
+ vec 'keep-debug 'keep-password 'keep-processes)
+ (setq tramp-default-proxies-alist
+ (delete entry1 tramp-default-proxies-alist)))))
;; Add the hop.
(unless (member entry tramp-default-proxies-alist)
(tramp-message vec 5 "Add %S to `tramp-default-proxies-alist'" entry)