Subject: Re: bug#69085: 29.2; Tramp: Extend tramp-make-copy-program-file-name via tramp-methods

From: Michael Albinus <[email-masked]>
Date: Fri, 16 Feb 2024 15:54:53 +0100

Sean Devlin <[email-masked]> writes:

> Hi Michael,

Hi Sean,

> Suppose we want to add OOB copying to the Docker method. Docker
> has a copy command with usage like this:
>
> Usage:  docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
> docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
>
> We could try to add support to the Docker method for OOB copying by
> starting Emacs -Q and evaluating these forms:
>
> (add-to-list 'tramp-methods
>              `(,tramp-docker-method
>                (tramp-login-program ,tramp-docker-program)
>                (tramp-login-args (("exec")
>                                   ("-it")
>                                   ("-u" "%u")
>                                   ("%h")
>          ("%l")))
>       (tramp-direct-async (,tramp-default-remote-shell "-c"))
>                (tramp-remote-shell ,tramp-default-remote-shell)
>                (tramp-remote-shell-login ("-l"))
>                (tramp-remote-shell-args ("-i" "-c"))
>
>       (tramp-copy-program ,tramp-docker-program)
>       (tramp-copy-args (("cp")))
>       ))

Well, if "docker cp" doesn't need the user, why do we use the user at
all? Couldn't we get rid of it in this case? That is, don't use the
("-u" "%u") in tramp-login-args.

> I think what is needed is some way for the tramp-docker method to
> specify the format for remote paths in the OOB copy command, since
> tramp-make-copy-program-file-name will include the user if it is
> specified in the connection.
>
> One method might be to add a key to tramp-methods that lets you
> specify the format similar to tramp-login-args and tramp-copy-args:

I've tried another approach. In Tramp 2.7, I've added a new method
"dockercp" which doesn't use the user at all, and which adds
tramp-copy-program and tramp-copy-args.

Do you have a chance to install Tramp from its repository like

--8<---------------cut here---------------start------------->8---
# git clone https://git.savannah.gnu.org/git/tramp.git
--8<---------------cut here---------------end--------------->8---

Then pls modify tramp-container.el with the appended patch. After that,
you should be able to access your docker container like
/dockercp:CONTAINER:/path/to/file. And if you copy large files, "docker
cp" will be applied.

Best regards, Michael.

diff --git a/lisp/tramp-container.el b/lisp/tramp-container.el
index 1f578949..caea6b47 100644
--- a/lisp/tramp-container.el
+++ b/lisp/tramp-container.el
@@ -31,6 +31,7 @@
 ;; Open a file on a running Docker container:
 ;;
 ;;     C-x C-f /docker:USER@CONTAINER:/path/to/file
+;;     C-x C-f /dockercp:CONTAINER:/path/to/file
 ;;
 ;; or Podman:
 ;;
@@ -141,6 +142,11 @@ If it is nil, the default context will be used."
 (defconst tramp-docker-method "docker"
   "Tramp method name to use to connect to Docker containers.")

+;;;###tramp-autoload
+(defconst tramp-dockercp-method "dockercp"
+  "Tramp method name to use to connect to Docker containers.
+This is for out-of-band connections.")
+
 ;;;###tramp-autoload
 (defconst tramp-podman-method "podman"
   "Tramp method name to use to connect to Podman containers.")
@@ -183,7 +189,7 @@ BODY is the backend specific code."
 (defun tramp-container--completion-function (method)
   "List running containers available for connection.
 METHOD is the Tramp method to be used for \"ps\", either
-`tramp-docker-method' or `tramp-podman-method'.
+`tramp-docker-method', `tramp-dockercp-method' or `tramp-podman-method'.

 This function is used by `tramp-set-completion-function', please
 see its function help for a description of the format."
@@ -375,6 +381,20 @@ see its function help for a description of the format."
                 (tramp-remote-shell-login ("-l"))
                 (tramp-remote-shell-args ("-i" "-c"))))

+ (add-to-list 'tramp-methods
+              `(,tramp-dockercp-method
+                (tramp-login-program ,tramp-docker-program)
+                (tramp-login-args (("exec")
+                                   ("-it")
+                                   ("%h")
+			           ("%l")))
+		(tramp-direct-async (,tramp-default-remote-shell "-c"))
+                (tramp-remote-shell ,tramp-default-remote-shell)
+                (tramp-remote-shell-login ("-l"))
+                (tramp-remote-shell-args ("-i" "-c"))
+		(tramp-copy-program ,tramp-docker-program)
+		(tramp-copy-args (("cp")))))
+
  (add-to-list 'tramp-methods
               `(,tramp-podman-method
                 (tramp-login-program ,tramp-podman-program)
@@ -431,6 +451,10 @@ see its function help for a description of the format."
   tramp-docker-method
   `((tramp-container--completion-function ,tramp-docker-method)))

+ (tramp-set-completion-function
+  tramp-dockercp-method
+  `((tramp-container--completion-function ,tramp-dockercp-method)))
+
  (tramp-set-completion-function
   tramp-podman-method
   `((tramp-container--completion-function ,tramp-podman-method)))