]> git.eshelyaron.com Git - emacs.git/commitdiff
Add Tramp methods dockercp and podmancp
authorMichael Albinus <michael.albinus@gmx.de>
Tue, 20 Feb 2024 11:52:40 +0000 (12:52 +0100)
committerEshel Yaron <me@eshelyaron.com>
Wed, 28 Feb 2024 17:36:47 +0000 (18:36 +0100)
* doc/misc/tramp.texi (External methods):  Add dockercp and podmancp.

* etc/NEWS: Add Tramp methods "dockercp" and "podmancp".

* lisp/net/tramp.el (tramp-handle-make-process):
* lisp/net/tramp-adb.el (tramp-adb-maybe-open-connection):
* lisp/net/tramp-sh.el (tramp-do-copy-or-rename-file-out-of-band)
(tramp-maybe-open-connection):
* lisp/net/tramp-sshfs.el (tramp-sshfs-handle-process-file)
(tramp-sshfs-maybe-open-connection):
* lisp/net/tramp-sudoedit.el (tramp-sudoedit-send-command): Adapt
`tramp-expand-args' calls.

* lisp/net/tramp-container.el (tramp-dockercp-method)
(tramp-podmancp-method): New defconst.
(tramp-methods) <dockercp, podmancp>: Add new methods.
(tramp-container--completion-function): Adapt docstring.  Use it
for "dockercp" and "podmancp" completion.

* lisp/net/tramp.el (tramp-get-remote-tmpdir):
* lisp/net/tramp-gvfs.el (tramp-gvfs-maybe-open-connection):
* lisp/net/tramp-sh.el (tramp-maybe-open-connection): Use a default
value with `tramp-get-method-parameter'.

* lisp/net/tramp-sh.el (tramp-methods) <nc>: Add `tramp-copy-file-name'.
(tramp-default-copy-file-name): New defconst.
(tramp-make-copy-file-name): Rename from
`tramp-make-copy-program-file-name'.  Use method parameter
`tramp-copy-file-name'.  (Bug#69085)
(tramp-do-copy-or-rename-file-out-of-band): Adapt callees.

* lisp/net/tramp.el (tramp-methods): Adapt docstring.
(tramp-get-method-parameter, tramp-expand-args): New optional
argument DEFAULT.

* test/lisp/net/tramp-tests.el (tramp--test-container-p): Adapt.
(tramp--test-container-oob-p): New defun.
(tramp-test17-dired-with-wildcards, tramp-test35-remote-path)
(tramp-test41-special-characters): Use it.
(tramp--test-set-ert-test-documentation): Use `split-string'.

(cherry picked from commit 4e9993cada32a866a75b458092de0028db2f5f41)

doc/misc/tramp.texi
etc/NEWS
lisp/net/tramp-adb.el
lisp/net/tramp-container.el
lisp/net/tramp-gvfs.el
lisp/net/tramp-sh.el
lisp/net/tramp-sshfs.el
lisp/net/tramp-sudoedit.el
lisp/net/tramp.el
test/lisp/net/tramp-tests.el

index d8ed22e77a34167c7c5852495dcf12d4bb49000b..003abc6c1ab2ef6d2c2df214bd2662ece8061e8a 100644 (file)
@@ -1059,6 +1059,20 @@ session.
 
 These methods support the @samp{-P} argument.
 
+@item @option{dockercp}
+@item @option{podmancp}
+@cindex method @option{dockercp}
+@cindex @option{dockercp} method
+@cindex method @option{podmancp}
+@cindex @option{podmancp} method
+
+These methods are similar to @option{docker} or @option{podman}, but
+they use the command @command{docker cp} or @command{podman cp} for
+transferring large files.
+
+These copy commands do not support file globs, and they ignore a user
+name.
+
 @item @option{fcp}
 @cindex method @option{fcp}
 @cindex @option{fcp} method
index c1bbd466556ff27b0ccdf849010f4cdf158581f4..daaaf52f1f77bb329b96ee8d9a2725b214fbd17c 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -982,6 +982,10 @@ mode line.  'header' will display in the header line;
 
 ** Tramp
 
++++
+*** New connection methods "dockercp" and "podmancp".
+These are the external methods counterparts of "docker" and "podman".
+
 +++
 *** New connection methods "toolbox" and "flatpak".
 They allow accessing system containers provided by Toolbox or
@@ -1219,7 +1223,7 @@ the user option 'nnweb-type' to 'gmane'.
 *** New user option 'gnus-mode-line-logo'.
 This allows the user to either disable the display of any logo or
 specify which logo will be displayed as part of the
-buffer-identification in the mode-line of Gnus-buffers.
+buffer-identification in the mode-line of Gnus buffers.
 
 ** Rmail
 
@@ -1445,7 +1449,7 @@ This user option lets you customize the sample text that
 This command toggles the display of internal buffers in Buffer Menu mode;
 that is, buffers not visiting a file and whose names start with a space.
 Previously, such buffers were never shown.  This command is bound to 'I'
-in Buffer menu mode.
+in Buffer Menu mode.
 
 ** Customize
 
@@ -1537,7 +1541,7 @@ current project configuration, and later updates it as you edit the
 files and save the changes.
 
 +++
-** New package Compat
+** New package Compat.
 Emacs now comes with a stub implementation of the
 forwards-compatibility Compat package from GNU ELPA.  This allows
 built-in packages to use the library more effectively, and helps
@@ -1698,7 +1702,7 @@ instead of this variable.
 
 +++
 ** Pcase's functions (in 'pred' and 'app') can specify the argument position.
-For example, instead of (pred (< 5)) you can write (pred (> _ 5)).
+For example, instead of '(pred (< 5))' you can write '(pred (> _ 5))'.
 
 +++
 ** 'define-advice' now sets the new advice's 'name' property to NAME.
index 2e4ad1cc4126d7d5105b191c42b95cc085925cec..96625fc568059515b8900cdb01dea871b641fb34 100644 (file)
@@ -1230,7 +1230,7 @@ connection if a previous connection has died for some reason."
            (let* ((coding-system-for-read 'utf-8-dos) ; Is this correct?
                   (process-connection-type tramp-process-connection-type)
                   (args (tramp-expand-args
-                         vec 'tramp-login-args ?d (or device "")))
+                         vec 'tramp-login-args nil ?d (or device "")))
                   (p (let ((default-directory
                             tramp-compat-temporary-file-directory))
                        (apply
index 1f578949e4d8358dc8edbaa43a530b91217a8821..30639cbeb85b431f12ad70ffc89a7cac35b4749b 100644 (file)
 ;; Open a file on a running Docker container:
 ;;
 ;;     C-x C-f /docker:USER@CONTAINER:/path/to/file
+;;     C-x C-f /dockercp:USER@CONTAINER:/path/to/file
 ;;
 ;; or Podman:
 ;;
 ;;     C-x C-f /podman:USER@CONTAINER:/path/to/file
+;;     C-x C-f /podmancp:USER@CONTAINER:/path/to/file
 ;;
 ;; Where:
 ;;     USER          is the user on the container to connect as (optional).
 ;;     CONTAINER     is the container to connect to.
 ;;
+;; "docker" and "podman" are inline methods, "dockercp" and "podmancp"
+;; are out-of-band methods.
+;;
 ;;
 ;;
 ;; Open file in a Kubernetes container:
@@ -141,10 +146,20 @@ 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.")
 
+;;;###tramp-autoload
+(defconst tramp-podmancp-method "podmancp"
+  "Tramp method name to use to connect to Podman containers.
+This is for out-of-band connections.")
+
 ;;;###tramp-autoload
 (defconst tramp-kubernetes-method "kubernetes"
   "Tramp method name to use to connect to Kubernetes containers.")
@@ -183,7 +198,8 @@ 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', `tramp-podman-method',
+or `tramp-podmancp-method'.
 
 This function is used by `tramp-set-completion-function', please
 see its function help for a description of the format."
@@ -375,6 +391,23 @@ 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")
+                                   ("-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")))
+               (tramp-copy-file-name (("%h" ":") ("%f")))
+                (tramp-copy-recursive t)))
+
  (add-to-list 'tramp-methods
               `(,tramp-podman-method
                 (tramp-login-program ,tramp-podman-program)
@@ -388,6 +421,23 @@ 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-podmancp-method
+                (tramp-login-program ,tramp-podman-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-podman-program)
+               (tramp-copy-args (("cp")))
+               (tramp-copy-file-name (("%h" ":") ("%f")))
+                (tramp-copy-recursive t)))
+
  (add-to-list 'tramp-methods
               `(,tramp-kubernetes-method
                 (tramp-login-program ,tramp-kubernetes-program)
@@ -431,10 +481,18 @@ 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)))
 
+ (tramp-set-completion-function
+  tramp-podmancp-method
+  `((tramp-container--completion-function ,tramp-podmancp-method)))
+
  (tramp-set-completion-function
   tramp-kubernetes-method
   `((tramp-kubernetes--completion-function ,tramp-kubernetes-method)))
index 4e949e7e60b53398ce12889507b81ba820f5c47c..93071ed73509b43b4ca6cb0832cc8fa03c3af071 100644 (file)
@@ -2294,8 +2294,8 @@ connection if a previous connection has died for some reason."
          ;; indicated by the "mounted" signal, i.e. the
          ;; "fuse-mountpoint" file property.
          (with-timeout
-             ((or (tramp-get-method-parameter vec 'tramp-connection-timeout)
-                  tramp-connection-timeout)
+             ((tramp-get-method-parameter
+               vec 'tramp-connection-timeout tramp-connection-timeout)
               (if (tramp-string-empty-or-nil-p (tramp-file-name-user vec))
                   (tramp-error
                    vec 'file-error
index b21e65a0650ad37c0e55dbcd41907e78feb65f5a..046b83b0a499ba7be819205852e744dc18009b5b 100644 (file)
@@ -282,6 +282,7 @@ The string is used in `tramp-methods'.")
                 (tramp-copy-program         "nc")
                 ;; We use "-v" for better error tracking.
                 (tramp-copy-args            (("-w" "1") ("-v") ("%h") ("%r")))
+                (tramp-copy-file-name       (("%f")))
                 (tramp-remote-copy-program  "nc")
                 ;; We use "-p" as required for newer busyboxes.  For older
                 ;; busybox/nc versions, the value must be (("-l") ("%r")).  This
@@ -428,6 +429,9 @@ The string is used in `tramp-methods'.")
                     eos)
                nil ,(user-login-name))))
 
+(defconst tramp-default-copy-file-name '(("%u" "@") ("%h" ":") ("%f"))
+  "Default `tramp-copy-file-name' entry for out-of-band methods.")
+
 ;;;###tramp-autoload
 (defconst tramp-completion-function-alist-rsh
   '((tramp-parse-rhosts "/etc/hosts.equiv")
@@ -2408,10 +2412,10 @@ The method used must be an out-of-band method."
                        #'file-name-as-directory
                      #'identity)
                    (if v1
-                       (tramp-make-copy-program-file-name v1)
+                       (tramp-make-copy-file-name v1)
                      (file-name-unquote filename)))
            target (if v2
-                      (tramp-make-copy-program-file-name v2)
+                      (tramp-make-copy-file-name v2)
                     (file-name-unquote newname)))
 
       ;; Check for listener port.
@@ -2450,7 +2454,7 @@ The method used must be an out-of-band method."
            ;; " " has either been a replacement of "%k" (when
            ;; KEEP-DATE argument is non-nil), or a replacement for
            ;; the whole keep-date sublist.
-           (delete " " (apply #'tramp-expand-args v 'tramp-copy-args spec))
+           (delete " " (apply #'tramp-expand-args v 'tramp-copy-args nil spec))
            ;; `tramp-ssh-controlmaster-options' is a string instead
            ;; of a list.  Unflatten it.
            copy-args
@@ -2459,11 +2463,11 @@ The method used must be an out-of-band method."
              (lambda (x) (if (tramp-compat-string-search " " x)
                               (split-string x) x))
              copy-args))
-           copy-env (apply #'tramp-expand-args v 'tramp-copy-env spec)
+           copy-env (apply #'tramp-expand-args v 'tramp-copy-env nil spec)
            remote-copy-program
            (tramp-get-method-parameter v 'tramp-remote-copy-program)
            remote-copy-args
-           (apply #'tramp-expand-args v 'tramp-remote-copy-args spec))
+           (apply #'tramp-expand-args v 'tramp-remote-copy-args nil spec))
 
       ;; Check for local copy program.
       (unless (executable-find copy-program)
@@ -5299,7 +5303,8 @@ connection if a previous connection has died for some reason."
                             (tramp-get-method-parameter hop 'tramp-async-args)))
                           (connection-timeout
                            (tramp-get-method-parameter
-                            hop 'tramp-connection-timeout))
+                            hop 'tramp-connection-timeout
+                            tramp-connection-timeout))
                           (command
                            (tramp-get-method-parameter
                             hop 'tramp-login-program))
@@ -5357,7 +5362,7 @@ connection if a previous connection has died for some reason."
                         ;; Add arguments for asynchronous processes.
                         (when process-name async-args)
                         (tramp-expand-args
-                         hop 'tramp-login-args
+                         hop 'tramp-login-args nil
                          ?h (or l-host "") ?u (or l-user "") ?p (or l-port "")
                          ?c (format-spec options (format-spec-make ?t tmpfile))
                          ?n (concat
@@ -5374,8 +5379,7 @@ connection if a previous connection has died for some reason."
                       p vec
                       (min
                        pos (with-current-buffer (process-buffer p) (point-max)))
-                      tramp-actions-before-shell
-                      (or connection-timeout tramp-connection-timeout))
+                      tramp-actions-before-shell connection-timeout)
                      (tramp-message
                       vec 3 "Found remote shell prompt on `%s'" l-host)
 
@@ -5568,8 +5572,8 @@ raises an error."
    string
    ""))
 
-(defun tramp-make-copy-program-file-name (vec)
-  "Create a file name suitable for `scp', `pscp', or `nc' and workalikes."
+(defun tramp-make-copy-file-name (vec)
+  "Create a file name suitable for out-of-band methods."
   (let ((method (tramp-file-name-method vec))
        (user (tramp-file-name-user vec))
        (host (tramp-file-name-host vec))
@@ -5580,13 +5584,13 @@ raises an error."
     ;; This does not work for MS Windows scp, if there are characters
     ;; to be quoted.  OpenSSH 8 supports disabling of strict file name
     ;; checking in scp, we use it when available.
-    (unless (string-match-p (rx "ftp" eos) method)
+    (unless (string-match-p (rx (| "dockercp" "podmancp" "ftp") eos) method)
       (setq localname (tramp-unquote-shell-quote-argument localname)))
-    (cond
-     ((tramp-get-method-parameter vec 'tramp-remote-copy-program)
-      localname)
-     ((tramp-string-empty-or-nil-p user) (format "%s:%s" host localname))
-     (t (format "%s@%s:%s" user host localname)))))
+    (string-join
+     (apply #'tramp-expand-args vec
+           'tramp-copy-file-name tramp-default-copy-file-name
+           (list ?h (or host "") ?u (or user "") ?f localname))
+     "")))
 
 (defun tramp-method-out-of-band-p (vec size)
   "Return t if this is an out-of-band method, nil otherwise."
index 8dad599c7e7dcdc3b1f6241a31a918a24a955ab4..d0d56b8967e2f4131485c326ce085c1fad4dd7fc 100644 (file)
@@ -322,7 +322,7 @@ arguments to pass to the OPERATION."
           v (tramp-get-method-parameter v 'tramp-login-program)
           nil outbuf display
           (tramp-expand-args
-           v 'tramp-login-args
+           v 'tramp-login-args nil
            ?h (or (tramp-file-name-host v) "")
            ?u (or (tramp-file-name-user v) "")
            ?p (or (tramp-file-name-port v) "")
@@ -424,7 +424,7 @@ connection if a previous connection has died for some reason."
                (tramp-fuse-mount-spec vec)
                (tramp-fuse-mount-point vec)
                (tramp-expand-args
-                vec 'tramp-mount-args
+                vec 'tramp-mount-args nil
                 ?p (or (tramp-file-name-port vec) ""))))))
       (tramp-error
        vec 'file-error "Error mounting %s" (tramp-fuse-mount-spec vec)))
index 953e2ac0413b71244d79546123382cfa00027221..279c46bfd8c05c599364b59c014f98c9ff604fd7 100644 (file)
@@ -773,7 +773,7 @@ in case of error, t otherwise."
                     (tramp-get-connection-name vec) (current-buffer)
                     (append
                      (tramp-expand-args
-                      vec 'tramp-sudo-login
+                      vec 'tramp-sudo-login nil
                       ?h (or (tramp-file-name-host vec) "")
                       ?u (or (tramp-file-name-user vec) ""))
                      (flatten-tree args))))
index 08444e020b80a1422fb524ad3dfeafd9889eae09..3627519690225ff5860899b3914707e88ade0ab7 100644 (file)
@@ -301,6 +301,15 @@ pair of the form (KEY VALUE).  The following KEYs are defined:
     This specifies the list of parameters to pass to the above mentioned
     program, the hints for `tramp-login-args' also apply here.
 
+  * `tramp-copy-file-name'
+    The remote source or destination file name for out-of-band methods.
+    You can use \"%u\" and \"%h\" like in `tramp-login-args'.
+    Additionally, \"%f\" denotes the local file name part.  This list
+    will be expanded to a string without spaces between the elements of
+    the list.
+
+    The default value is `tramp-default-copy-file-name'.
+
   * `tramp-copy-env'
      A list of environment variables and their values, which will
      be set when calling `tramp-copy-program'.
@@ -1545,21 +1554,23 @@ LOCALNAME and HOP do not count."
        (equal (tramp-file-name-unify vec1)
              (tramp-file-name-unify vec2))))
 
-(defun tramp-get-method-parameter (vec param)
+(defun tramp-get-method-parameter (vec param &optional default)
   "Return the method parameter PARAM.
 If VEC is a vector, check first in connection properties.
 Afterwards, check in `tramp-methods'.  If the `tramp-methods'
-entry does not exist, return nil."
+entry does not exist, return DEFAULT."
   (let ((hash-entry
         (replace-regexp-in-string (rx bos "tramp-") "" (symbol-name param))))
     (if (tramp-connection-property-p vec hash-entry)
        ;; We use the cached property.
        (tramp-get-connection-property vec hash-entry)
       ;; Use the static value from `tramp-methods'.
-      (when-let ((methods-entry
+      (if-let ((methods-entry
                  (assoc
                   param (assoc (tramp-file-name-method vec) tramp-methods))))
-       (cadr methods-entry)))))
+         (cadr methods-entry)
+       ;; Return the default value.
+       default))))
 
 ;; The localname can be quoted with "/:".  Extract this.
 (defun tramp-file-name-unquote-localname (vec)
@@ -3944,6 +3955,9 @@ Let-bind it when necessary.")
      (tramp-get-method-parameter v 'tramp-case-insensitive)
 
      ;; There isn't.  So we must check, in case there's a connection already.
+     ;; Note: We cannot use it as DEFAULT value of
+     ;; `tramp-get-method-parameter', because it would be evalled
+     ;; during the call.
      (and (let ((non-essential t)) (tramp-connectable-p v))
           (with-tramp-connection-property v "case-insensitive"
            (ignore-errors
@@ -4753,15 +4767,15 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
 (defvar tramp-extra-expand-args nil
   "Method specific arguments.")
 
-(defun tramp-expand-args (vec parameter &rest spec-list)
+(defun tramp-expand-args (vec parameter default &rest spec-list)
   "Expand login arguments as given by PARAMETER in `tramp-methods'.
 PARAMETER is a symbol like `tramp-login-args', denoting a list of
 list of strings from `tramp-methods', containing %-sequences for
-substitution.
+substitution.  DEFAULT is used when PARAMETER is not specified.
 SPEC-LIST is a list of char/value pairs used for
 `format-spec-make'.  It is appended by `tramp-extra-expand-args',
 a connection-local variable."
-  (let ((args (tramp-get-method-parameter vec parameter))
+  (let ((args (tramp-get-method-parameter vec parameter default))
        (extra-spec-list
         (mapcar
          #'eval
@@ -4940,7 +4954,7 @@ a connection-local variable."
             (mapcar
              (lambda (x) (split-string x " "))
              (tramp-expand-args
-              v 'tramp-login-args
+              v 'tramp-login-args nil
               ?h (or host "") ?u (or user "") ?p (or port "")
               ?c (format-spec (or options "") (format-spec-make ?t tmpfile))
               ?d (or device "") ?a (or pta "") ?l ""))))
@@ -6327,9 +6341,8 @@ This handles also chrooted environments, which are not regarded as local."
 (defun tramp-get-remote-tmpdir (vec)
   "Return directory for temporary files on the remote host identified by VEC."
   (with-tramp-connection-property (tramp-get-process vec) "remote-tmpdir"
-    (let ((dir
-          (tramp-make-tramp-file-name
-           vec (or (tramp-get-method-parameter vec 'tramp-tmpdir) "/tmp"))))
+    (let ((dir (tramp-make-tramp-file-name
+               vec (tramp-get-method-parameter vec 'tramp-tmpdir "/tmp"))))
       (or (and (file-directory-p dir) (file-writable-p dir)
               (tramp-file-local-name dir))
          (tramp-error vec 'file-error "Directory %s not accessible" dir))
index 623e0860a01806abd371fef631fadc326697f66e..cdd2a1efdb29c164380c0bfb313fc2176da8f743 100644 (file)
@@ -3493,6 +3493,8 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
   (skip-unless (not (tramp--test-rsync-p)))
   ;; Wildcards are not supported in tramp-crypt.el.
   (skip-unless (not (tramp--test-crypt-p)))
+  ;; Wildcards are not supported with "docker cp ..." or "podman cp ...".
+  (skip-unless (not (tramp--test-container-oob-p)))
 
   (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
     (let* ((tmp-name1
@@ -3819,7 +3821,7 @@ This tests also `access-file', `file-readable-p',
   "Set the documentation string for a derived test.
 The test is derived from TEST and COMMAND."
   (let ((test-doc
-        (string-split (ert-test-documentation (get test 'ert--test)) "\n")))
+        (split-string (ert-test-documentation (get test 'ert--test)) "\n")))
     ;; The first line must be extended.
     (setcar
      test-doc (format "%s  Use the \"%s\" command." (car test-doc) command))
@@ -6379,33 +6381,35 @@ INPUT, if non-nil, is a string sent to the process."
           (setq tramp-remote-path orig-tramp-remote-path)
 
           ;; We make a super long `tramp-remote-path'.
-          (make-directory tmp-name)
-          (should (file-directory-p tmp-name))
-          (while (tramp-compat-length< (string-join orig-exec-path ":") 5000)
-            (let ((dir (make-temp-file (file-name-as-directory tmp-name) 'dir)))
-              (should (file-directory-p dir))
-              (setq tramp-remote-path
-                    (append
-                    tramp-remote-path `(,(file-remote-p dir 'localname)))
-                    orig-exec-path
-                    (append
-                    (butlast orig-exec-path)
-                    `(,(file-remote-p dir 'localname))
-                    (last orig-exec-path)))))
-          (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
-          (should (equal (exec-path) orig-exec-path))
-          ;; Ignore trailing newline.
-         (setq path (substring (shell-command-to-string "echo $PATH") nil -1))
-         ;; The shell doesn't handle such long strings.
-         (unless (tramp-compat-length>
-                  path
-                  (tramp-get-connection-property
-                   tramp-test-vec "pipe-buf" 4096))
-           ;; The last element of `exec-path' is `exec-directory'.
-            (should
-            (string-equal path (string-join (butlast orig-exec-path) ":"))))
-         ;; The shell "sh" shall always exist.
-         (should (executable-find "sh" 'remote)))
+         (unless (tramp--test-container-oob-p)
+            (make-directory tmp-name)
+            (should (file-directory-p tmp-name))
+            (while (tramp-compat-length< (string-join orig-exec-path ":") 5000)
+              (let ((dir (make-temp-file
+                         (file-name-as-directory tmp-name) 'dir)))
+               (should (file-directory-p dir))
+               (setq tramp-remote-path
+                      (append
+                      tramp-remote-path `(,(file-remote-p dir 'localname)))
+                      orig-exec-path
+                      (append
+                      (butlast orig-exec-path)
+                      `(,(file-remote-p dir 'localname))
+                      (last orig-exec-path)))))
+            (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+            (should (equal (exec-path) orig-exec-path))
+           ;; Ignore trailing newline.
+           (setq path (substring (shell-command-to-string "echo $PATH") nil -1))
+           ;; The shell doesn't handle such long strings.
+           (unless (tramp-compat-length>
+                    path
+                    (tramp-get-connection-property
+                     tramp-test-vec "pipe-buf" 4096))
+             ;; The last element of `exec-path' is `exec-directory'.
+              (should
+              (string-equal path (string-join (butlast orig-exec-path) ":"))))
+           ;; The shell "sh" shall always exist.
+           (should (executable-find "sh" 'remote))))
 
       ;; Cleanup.
       (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
@@ -7056,17 +7060,24 @@ This is used in tests which we don't want to tag
    (not (and (tramp--test-adb-p)
             (string-match-p (rx multibyte) default-directory)))))
 
-(defun tramp--test-crypt-p ()
-  "Check, whether the remote directory is encrypted."
-  (tramp-crypt-file-name-p ert-remote-temporary-file-directory))
-
 (defun tramp--test-container-p ()
   "Check, whether a container method is used.
 This does not support some special file names."
   (string-match-p
-   (rx bol (| "docker" "podman") eol)
+   (rx bol (| "docker" "podman"))
    (file-remote-p ert-remote-temporary-file-directory 'method)))
 
+(defun tramp--test-container-oob-p ()
+  "Check, whether the dockercp or podmancp method is used.
+They does not support wildcard copy."
+  (string-match-p
+   (rx bol (| "dockercp" "podmancp") eol)
+   (file-remote-p ert-remote-temporary-file-directory 'method)))
+
+(defun tramp--test-crypt-p ()
+  "Check, whether the remote directory is encrypted."
+  (tramp-crypt-file-name-p ert-remote-temporary-file-directory))
+
 (defun tramp--test-expensive-test-p ()
   "Whether expensive tests are run.
 This is used in tests which we don't want to tag `:expensive'
@@ -7483,7 +7494,8 @@ This requires restrictions of file name syntax."
                      (tramp--test-gvfs-p)
                      (tramp--test-windows-nt-or-smb-p))
            "?foo?bar?baz?")
-         (unless (or (tramp--test-ftp-p)
+         (unless (or (tramp--test-container-oob-p)
+                     (tramp--test-ftp-p)
                      (tramp--test-gvfs-p)
                      (tramp--test-windows-nt-or-smb-p))
            "*foo+bar*baz+")
@@ -7503,7 +7515,10 @@ This requires restrictions of file name syntax."
          (unless (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
            "<foo>bar<baz>")
          "(foo)bar(baz)"
-         (unless (or (tramp--test-ftp-p) (tramp--test-gvfs-p)) "[foo]bar[baz]")
+         (unless (or (tramp--test-container-oob-p)
+                     (tramp--test-ftp-p)
+                     (tramp--test-gvfs-p))
+           "[foo]bar[baz]")
          "{foo}bar{baz}")))
     ;; Simplify test in order to speed up.
     (apply #'tramp--test-check-files