Gene Goykhman <g...@indigo1.com> writes:

Hi Gene,

I've seen your name on file at the FSF. Congratulations!

> Following up on 
> https://lists.gnu.org/archive/html/tramp-devel/2023-08/msg00001.html, I have 
> prepared a patch to add remote container completion support to TRAMP.

Thanks for this! As usual, I have some comments.

> A couple of questions/things I'm uncertain of in this patch:
>
> 1. I am removing the check for executable-find for the docker and
> podman programs since they need to be run on the remote system (and
> executable-find will fail as it only checks the local machine while
> multi-hopping). I'm not sure if there is a better way to handle this.

That's a problem, indeed. I'll think about a better solution, ATM we
should do it as proposed by you.

> 2. In tramp-set-completion-function I am short-circuiting the cond
> check for a valid "file or registry key" since again, file-exists-p
> will fail when checking for the docker or podman program on a remote
> system when checking a multi-hop path. I'm open to a better ideas here
> since my change effectively no-ops the whole cond.

Same as above.

> 3. (style question) I've added my required variable tramp-last-hop-directory 
> as an autoload in tramp.el but if there's a better place for it I'd be happy 
> to move it.

No autoload is needed. tramp-container.el requires tramp.el, the
variable is known therefore.

> --- a/lisp/net/tramp-container.el
> +++ b/lisp/net/tramp-container.el
> @@ -157,6 +157,8 @@ If it is nil, the default context will be used."
>  (defconst tramp-flatpak-method "flatpak"
>    "Tramp method name to use to connect to Flatpak sandboxes.")
>
> +(defvar tramp-last-hop-directory)

Not needed.

>  This function is used by `tramp-set-completion-function', please
>  see its function help for a description of the format."
> -  (when-let ((default-directory tramp-compat-temporary-file-directory)
> +  (when-let ((default-directory (or tramp-last-hop-directory
> +                                    tramp-compat-temporary-file-directory))

Please give it a verbose comment, that poor souls reading Tramp sources
understand the trick.

> diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
> index a0092a2d706..427c0871310 100644
> --- a/lisp/net/tramp.el
> +++ b/lisp/net/tramp.el
> @@ -82,6 +82,9 @@
>  (defvar tramp-completion-method-regexp)
>  (defvar tramp-completion-file-name-regexp)
>
> +;;;###tramp-autoload
> +(defvar tramp-last-hop-directory nil)
> +

No ;;;###tramp-autoload cookie needed.  A docstring is missing, which
explains the purpose. For example, that it shouldn't be set manually,
but be let-bound.

> @@ -2133,8 +2136,8 @@ Example:
>                   ;; DNS-SD service type.
>                   ((string-match-p
>                     tramp-dns-sd-service-regexp (nth 1 (car v))))
> -                 ;; Configuration file or empty string.
> -                 (t (file-exists-p (nth 1 (car v))))))
> +                    ;; Allow arbitrary executable name (for remote systems) 
> too.
> +                    (t t)))

Perhaps you mark it with a FIXME: comment.

> +(defun container-host-directory (orig)
> +  "Strips off the `tramp-docker-program' or `tramp-podman-program' suffix 
> from ORIG."
> +  "Returned path can be used to start programs on the container host."
> +  (let ((regexp (format "\\(.*\\)|\\(\\(%s\\)\\|\\(%s\\)\\)" 
> tramp-docker-program tramp-podman-program)))
> +    (if (string-match regexp orig)
> +        (concat (match-string 1 orig) ":/")
> +      orig)))

This function has several problems:

- It hard-codes "docker" and "podman". We want to use the new
  functionality also for other methods.

- It just replaces "docker" or "podman" whereever it is in the file
  name. What if you have "/docker:host|ssh:"?

- It expects the default file name syntax, where the method is followed
  by a colon, like in "/ssh:host|docker:". We have also other Tramp
  syntaxes, like the separate syntax. The same file name to be completed
  would be there "/[ssh/host|docker/".

- It doesn't allow docker host parts of the file name. What if a user
  wants to complete "/ssh:host|docker:ab", when she knows the target
  host starts with "ab"?

- We don't need it at all :-) See below.

>  (defun tramp-completion-handle-file-name-all-completions (filename directory)
>    "Like `file-name-all-completions' for partial Tramp files."
> +  (let ((use-container-host-directory (container-host-directory directory)))
> +    (when (tramp-tramp-file-p use-container-host-directory)
> +      (let ((minibuffer-completing-file-name nil))
> +        (setq tramp-last-hop-directory (tramp-make-tramp-file-name
> +                                         (tramp-dissect-file-name 
> use-container-host-directory))))))

No. Don't do that. Instead, bind tramp-last-hop-directory to nil in that
let-clause:

>    (let ((fullname ...

Furthermore, the hop is already evall'ed in the function. We have

--8<---------------cut here---------------start------------->8---
      (setq hop (match-string 1 fullname)
            fullname (replace-match "" nil nil fullname 1)))
--8<---------------cut here---------------end--------------->8---

Replace this by

--8<---------------cut here---------------start------------->8---
      (setq hop (match-string 1 fullname)
            fullname (replace-match "" nil nil fullname 1)
            tramp-last-hop-directory
            (file-remote-p
             (tramp-make-tramp-file-name (tramp-dissect-hop-name hop)))))
--8<---------------cut here---------------end--------------->8---

With these changes, it looks good, and the completion on the other host
works. However, there are still open points:

- Completion for the host name somewhere else but local takes
  time. People might dislike it. So perhaps we add a user option, where
  a user can decide, whether she wants this feature.

- Completion of "/ssh:host|docker: TAB" works only, if there is already
  an etablished connection to "/ssh:host:". I'll contemplate how to
  simplify this.

Best regards, Michael.

Reply via email to