1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-15 10:30:25 -08:00

Add Tramp methods dockercp and podmancp

* 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'.
This commit is contained in:
Michael Albinus 2024-02-20 12:52:40 +01:00
parent a1cbc4d810
commit 4e9993cada
10 changed files with 182 additions and 74 deletions

View 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

View file

@ -31,15 +31,20 @@
;; 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)))

View 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

View 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")
@ -2399,10 +2403,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.
@ -2441,7 +2445,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
@ -2450,11 +2454,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)
@ -5290,7 +5294,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))
@ -5348,7 +5353,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
@ -5365,8 +5370,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)
@ -5559,8 +5563,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))
@ -5571,13 +5575,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."

View 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)))

View file

@ -771,7 +771,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))))

View 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)
@ -3943,6 +3954,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
@ -4752,15 +4766,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
@ -4939,7 +4953,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 ""))))
@ -6326,9 +6340,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))