From: Michael Albinus Date: Sat, 9 Nov 2024 09:29:42 +0000 (+0100) Subject: Tramp: Support different proxies for the same destination X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=58de0d3728c49a63e776b980ce2219be85b54b04;p=emacs.git Tramp: Support different proxies for the same destination * doc/misc/tramp.texi (Ad-hoc multi-hops): New subsection "Using different proxies for the same destination". * etc/NEWS: Tramp supports different proxies for the same destination host name in parallel. Fix typos. * lisp/net/tramp-cmds.el (tramp-cleanup-connection): Fix docstring. * lisp/net/tramp.el (tramp-make-tramp-file-name): Don't call `tramp-add-hops' during file name completion. (tramp-handle-file-name-as-directory) (tramp-handle-file-name-directory): Use `tramp-cache-undefined' for an empty `tramp-default-proxies-alist'. (tramp-add-hops): Extend. Remove existing entries with same target and different proxy, if needed. (Bug#74219) (cherry picked from commit 6cde51f1bbcfd55fe8d189b045247b9d80dee4ea) --- diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 164cb60fe69..3526cafad75 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -3914,6 +3914,30 @@ shall be taken, add a proper rule to the user option @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 diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index dc3df09ec3b..d37bb612255 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -116,11 +116,11 @@ Each function is called with the current vector as argument.") (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. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 55eae7d1850..a7e70de960d 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1889,7 +1889,8 @@ expected to be a string, which will be used." ;; 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) @@ -4172,7 +4173,7 @@ Let-bind it when necessary.") ;; 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 @@ -4266,7 +4267,7 @@ Let-bind it when necessary.") ;; 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 @@ -4907,21 +4908,37 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.") (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)