Refactor tramp-*-process-file functions

* lisp/net/tramp-adb.el (tramp-adb-handle-make-process):
* lisp/net/tramp-sh.el (tramp-sh-handle-make-process): Don't compute
process name, this is done in `tramp-skeleton-make-process'.

* lisp/net/tramp-adb.el (tramp-adb-handle-process-file):
* lisp/net/tramp-sh.el (tramp-sh-handle-process-file):
* lisp/net/tramp-sshfs.el (tramp-sshfs-handle-process-file):
Use `tramp-skeleton-process-file'.

* lisp/net/tramp.el (tramp-get-unique-process-name): New defun.
(tramp-skeleton-make-process): Use it.
(tramp-skeleton-process-file): New defmacro.
This commit is contained in:
Michael Albinus 2024-06-11 14:43:28 +02:00
parent 4b902f5031
commit 5ecff95993
4 changed files with 109 additions and 252 deletions

View file

@ -729,63 +729,11 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(defun tramp-adb-handle-process-file
(program &optional infile destination display &rest args)
"Like `process-file' for Tramp files."
;; The implementation is not complete yet.
(when (and (numberp destination) (zerop destination))
(error "Implementation does not handle immediate return"))
(with-parsed-tramp-file-name (expand-file-name default-directory) nil
(let (command input tmpinput stderr tmpstderr outbuf ret)
(tramp-skeleton-process-file program infile destination display args
;; Compute command.
(setq command (mapconcat #'tramp-shell-quote-argument
(cons program args) " "))
;; Determine input.
(if (null infile)
(setq input (tramp-get-remote-null-device v))
(setq infile (file-name-unquote (expand-file-name infile)))
(if (tramp-equal-remote default-directory infile)
;; INFILE is on the same remote host.
(setq input (tramp-unquote-file-local-name infile))
;; INFILE must be copied to remote host.
(setq input (tramp-make-tramp-temp-file v)
tmpinput (tramp-make-tramp-file-name v input))
(copy-file infile tmpinput t)))
(when input (setq command (format "%s <%s" command input)))
;; Determine output.
(cond
;; Just a buffer.
((bufferp destination)
(setq outbuf destination))
;; A buffer name.
((stringp destination)
(setq outbuf (get-buffer-create destination)))
;; (REAL-DESTINATION ERROR-DESTINATION)
((consp destination)
;; output.
(cond
((bufferp (car destination))
(setq outbuf (car destination)))
((stringp (car destination))
(setq outbuf (get-buffer-create (car destination))))
((car destination)
(setq outbuf (current-buffer))))
;; stderr.
(cond
((stringp (cadr destination))
(setcar (cdr destination) (expand-file-name (cadr destination)))
(if (tramp-equal-remote default-directory (cadr destination))
;; stderr is on the same remote host.
(setq stderr (tramp-unquote-file-local-name (cadr destination)))
;; stderr must be copied to remote host. The temporary
;; file must be deleted after execution.
(setq stderr (tramp-make-tramp-temp-file v)
tmpstderr (tramp-make-tramp-file-name v stderr))))
;; stderr to be discarded.
((null (cadr destination))
(setq stderr (tramp-get-remote-null-device v)))))
;; 't
(destination
(setq outbuf (current-buffer))))
(when stderr (setq command (format "%s 2>%s" command stderr)))
;; Send the command. It might not return in time, so we protect
@ -819,21 +767,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
;; since Emacs 28.1.
(when (and (bound-and-true-p process-file-return-signal-string)
(natnump ret) (> ret 128))
(setq ret (nth (- ret 128) (tramp-adb-get-signal-strings v))))
;; Provide error file.
(when tmpstderr (rename-file tmpstderr (cadr destination) t))
;; Cleanup. We remove all file cache values for the connection,
;; because the remote process could have changed them.
(when tmpinput (delete-file tmpinput))
(when process-file-side-effects
(tramp-flush-directory-properties v "/"))
;; Return exit status.
(if (equal ret -1)
(keyboard-quit)
ret))))
(setq ret (nth (- ret 128) (tramp-adb-get-signal-strings v))))))
;; We use BUFFER also as connection buffer during setup. Because of
;; this, its original contents must be saved, and restored once
@ -868,20 +802,12 @@ will be used."
(tramp-process-connection-type
(or (null program) tramp-process-connection-type))
(bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
(name1 name)
(i 0)
p)
(when (string-match-p (rx multibyte) command)
(tramp-error
v 'file-error "Cannot apply multibyte command `%s'" command))
(while (get-process name1)
;; NAME must be unique as process name.
(setq i (1+ i)
name1 (format "%s<%d>" name i)))
(setq name name1)
(with-tramp-saved-connection-properties
v '("process-name" "process-buffer")
;; Set the new process properties.

View file

@ -2581,10 +2581,6 @@ The method used must be an out-of-band method."
(tramp-get-connection-name v)
(tramp-get-connection-buffer v)
copy-program copy-args)))
;; This is needed for ssh or PuTTY based processes,
;; and only if the respective options are set.
;; Perhaps, the setting could be more fine-grained.
;; (process-put p 'tramp-shared-socket t)
(tramp-post-process-creation p v)
;; We must adapt `tramp-local-end-of-line' for sending
@ -3040,8 +3036,6 @@ will be used."
(tramp-process-connection-type
(or (null program) tramp-process-connection-type))
(bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
(name1 name)
(i 0)
;; We do not want to raise an error when `make-process'
;; has been started several times in `eshell' and
;; friends.
@ -3070,12 +3064,6 @@ will be used."
:sentinel #'ignore
:file-handler t))
(while (get-process name1)
;; NAME must be unique as process name.
(setq i (1+ i)
name1 (format "%s<%d>" name i)))
(setq name name1)
(with-tramp-saved-connection-properties
v '("process-name" "process-buffer")
;; Set the new process properties.
@ -3247,12 +3235,8 @@ will be used."
(defun tramp-sh-handle-process-file
(program &optional infile destination display &rest args)
"Like `process-file' for Tramp files."
;; The implementation is not complete yet.
(when (and (numberp destination) (zerop destination))
(error "Implementation does not handle immediate return"))
(with-parsed-tramp-file-name (expand-file-name default-directory) nil
(let (command env uenv input tmpinput stderr tmpstderr outbuf ret)
(tramp-skeleton-process-file program infile destination display args
(let (env uenv)
;; Compute command.
(setq command (mapconcat #'tramp-shell-quote-argument
(cons program args) " "))
@ -3273,54 +3257,7 @@ will be used."
(format
"unset %s && %s"
(mapconcat #'tramp-shell-quote-argument uenv " ") command)))
;; Determine input.
(if (null infile)
(setq input (tramp-get-remote-null-device v))
(setq infile (file-name-unquote (expand-file-name infile)))
(if (tramp-equal-remote default-directory infile)
;; INFILE is on the same remote host.
(setq input (tramp-unquote-file-local-name infile))
;; INFILE must be copied to remote host.
(setq input (tramp-make-tramp-temp-file v)
tmpinput (tramp-make-tramp-file-name v input))
(copy-file infile tmpinput t)))
(when input (setq command (format "%s <%s" command input)))
;; Determine output.
(cond
;; Just a buffer.
((bufferp destination)
(setq outbuf destination))
;; A buffer name.
((stringp destination)
(setq outbuf (get-buffer-create destination)))
;; (REAL-DESTINATION ERROR-DESTINATION)
((consp destination)
;; output.
(cond
((bufferp (car destination))
(setq outbuf (car destination)))
((stringp (car destination))
(setq outbuf (get-buffer-create (car destination))))
((car destination)
(setq outbuf (current-buffer))))
;; stderr.
(cond
((stringp (cadr destination))
(setcar (cdr destination) (expand-file-name (cadr destination)))
(if (tramp-equal-remote default-directory (cadr destination))
;; stderr is on the same remote host.
(setq stderr (tramp-unquote-file-local-name (cadr destination)))
;; stderr must be copied to remote host. The temporary
;; file must be deleted after execution.
(setq stderr (tramp-make-tramp-temp-file v)
tmpstderr (tramp-make-tramp-file-name v stderr))))
;; stderr to be discarded.
((null (cadr destination))
(setq stderr (tramp-get-remote-null-device v)))))
;; 't
(destination
(setq outbuf (current-buffer))))
(when stderr (setq command (format "%s 2>%s" command stderr)))
;; Send the command. It might not return in time, so we protect
@ -3355,21 +3292,7 @@ will be used."
;; since Emacs 28.1.
(when (and (bound-and-true-p process-file-return-signal-string)
(natnump ret) (>= ret 128))
(setq ret (nth (- ret 128) (tramp-sh-get-signal-strings v))))
;; Provide error file.
(when tmpstderr (rename-file tmpstderr (cadr destination) t))
;; Cleanup. We remove all file cache values for the connection,
;; because the remote process could have changed them.
(when tmpinput (delete-file tmpinput))
(when process-file-side-effects
(tramp-flush-directory-properties v "/"))
;; Return exit status.
(if (equal ret -1)
(keyboard-quit)
ret))))
(setq ret (nth (- ret 128) (tramp-sh-get-signal-strings v)))))))
(defun tramp-sh-handle-exec-path ()
"Like `exec-path' for Tramp files."
@ -3881,10 +3804,6 @@ Fall back to normal file name handler if no Tramp handler exists."
v 'file-notify-error
"`%s' failed to start on remote host"
(string-join sequence " "))
;; This is needed for ssh or PuTTY based processes, and only if
;; the respective options are set. Perhaps, the setting could
;; be more fine-grained.
;; (process-put p 'tramp-shared-socket t)
;; Needed for process filter.
(process-put p 'tramp-events events)
(process-put p 'tramp-watch-name localname)
@ -5257,10 +5176,6 @@ connection if a previous connection has died for some reason."
(and tramp-encoding-command-interactive
`(,tramp-encoding-command-interactive)))))))
;; This is needed for ssh or PuTTY based processes,
;; and only if the respective options are set.
;; Perhaps, the setting could be more fine-grained.
;; (process-put p 'tramp-shared-socket t)
;; Set sentinel. Initialize variables.
(set-process-sentinel p #'tramp-process-sentinel)
(tramp-post-process-creation p vec)

View file

@ -250,96 +250,34 @@ arguments to pass to the OPERATION."
(defun tramp-sshfs-handle-process-file
(program &optional infile destination display &rest args)
"Like `process-file' for Tramp files."
;; The implementation is not complete yet.
(when (and (numberp destination) (zerop destination))
(error "Implementation does not handle immediate return"))
(tramp-skeleton-process-file program infile destination display args
(let ((coding-system-for-read 'utf-8-dos)) ; Is this correct?
(with-parsed-tramp-file-name (expand-file-name default-directory) nil
(let ((coding-system-for-read 'utf-8-dos) ; Is this correct?
(command
(setq command
(format
"cd %s && exec %s"
(tramp-unquote-shell-quote-argument localname)
(mapconcat #'tramp-shell-quote-argument (cons program args) " ")))
input tmpinput stderr tmpstderr outbuf)
;; Determine input.
(if (null infile)
(setq input (tramp-get-remote-null-device v))
(setq infile (file-name-unquote (expand-file-name infile)))
(if (tramp-equal-remote default-directory infile)
;; INFILE is on the same remote host.
(setq input (tramp-unquote-file-local-name infile))
;; INFILE must be copied to remote host.
(setq input (tramp-make-tramp-temp-file v)
tmpinput (tramp-make-tramp-file-name v input))
(copy-file infile tmpinput t)))
(when input (setq command (format "%s <%s" command input)))
;; Determine output.
(cond
;; Just a buffer.
((bufferp destination)
(setq outbuf destination))
;; A buffer name.
((stringp destination)
(setq outbuf (get-buffer-create destination)))
;; (REAL-DESTINATION ERROR-DESTINATION)
((consp destination)
;; output.
(cond
((bufferp (car destination))
(setq outbuf (car destination)))
((stringp (car destination))
(setq outbuf (get-buffer-create (car destination))))
((car destination)
(setq outbuf (current-buffer))))
;; stderr.
(cond
((stringp (cadr destination))
(setcar (cdr destination) (expand-file-name (cadr destination)))
(if (tramp-equal-remote default-directory (cadr destination))
;; stderr is on the same remote host.
(setq stderr (tramp-unquote-file-local-name (cadr destination)))
;; stderr must be copied to remote host. The temporary
;; file must be deleted after execution.
(setq stderr (tramp-make-tramp-temp-file v)
tmpstderr (tramp-make-tramp-file-name v stderr))))
;; stderr to be discarded.
((null (cadr destination))
(setq stderr (tramp-get-remote-null-device v)))))
;; 't
(destination
(setq outbuf (current-buffer))))
(when stderr (setq command (format "%s 2>%s" command stderr)))
(unwind-protect
(apply
#'tramp-call-process
v (tramp-get-method-parameter v 'tramp-login-program)
nil outbuf display
(tramp-expand-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) "")
?a "-t" ?l command))
(setq ret
(apply
#'tramp-call-process
v (tramp-get-method-parameter v 'tramp-login-program)
nil outbuf display
(tramp-expand-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) "")
?a "-t" ?l command)))
;; Synchronize stderr.
(when tmpstderr
(tramp-cleanup-connection v 'keep-debug 'keep-password)
(tramp-fuse-unmount v))
;; Provide error file.
(when tmpstderr
(rename-file tmpstderr (cadr destination) t))
;; Cleanup. We remove all file cache values for the
;; connection, because the remote process could have changed
;; them.
(when tmpinput (delete-file tmpinput))
(when process-file-side-effects
(tramp-flush-directory-properties v "/"))))))
(tramp-fuse-unmount v))))))
(defun tramp-sshfs-handle-rename-file
(filename newname &optional ok-if-already-exists)

View file

@ -1963,6 +1963,16 @@ from the default one."
(or (tramp-get-connection-property vec "process-name")
(tramp-buffer-name vec)))
(defun tramp-get-unique-process-name (name)
"Return a unique process name, based on NAME."
(let ((name1 name)
(i 0))
(while (get-process name1)
;; NAME must be unique as process name.
(setq i (1+ i)
name1 (format "%s<%d>" name i)))
name1))
(defun tramp-get-process (vec-or-proc)
"Get the default connection process to be used for VEC-OR-PROC.
Return `tramp-cache-undefined' in case it doesn't exist."
@ -3568,6 +3578,7 @@ that a stederr file is supported. BODY is the backend specific code."
(signal 'file-error (list "Wrong stderr" stderr)))
(let ((default-directory tramp-compat-temporary-file-directory)
(name (tramp-get-unique-process-name name))
(buffer
(if buffer
(get-buffer-create buffer)
@ -3620,6 +3631,82 @@ on the same host. Otherwise, TARGET is quoted."
,@body)))
(defmacro tramp-skeleton-process-file
(_program &optional infile destination _display _args &rest body)
"Skeleton for `tramp-*-handle-process-file'.
BODY is the backend specific code."
(declare (indent 5) (debug t))
`(with-parsed-tramp-file-name (expand-file-name default-directory) nil
;; The implementation is not complete yet.
(when (and (numberp ,destination) (zerop ,destination))
(tramp-error
v 'file-error "Implementation does not handle immediate return"))
(let (command input tmpinput stderr tmpstderr outbuf ret)
;; Determine input.
(if (null ,infile)
(setq input (tramp-get-remote-null-device v))
(setq ,infile (file-name-unquote (expand-file-name ,infile)))
(if (tramp-equal-remote default-directory ,infile)
;; INFILE is on the same remote host.
(setq input (tramp-unquote-file-local-name ,infile))
;; ,INFILE must be copied to remote host.
(setq input (tramp-make-tramp-temp-file v)
tmpinput (tramp-make-tramp-file-name v input))
(copy-file ,infile tmpinput t)))
;; Determine output.
(cond
;; Just a buffer.
((bufferp ,destination)
(setq outbuf ,destination))
;; A buffer name.
((stringp ,destination)
(setq outbuf (get-buffer-create ,destination)))
;; (REAL-,DESTINATION ERROR-,DESTINATION)
((consp ,destination)
;; output.
(cond
((bufferp (car ,destination))
(setq outbuf (car ,destination)))
((stringp (car ,destination))
(setq outbuf (get-buffer-create (car ,destination))))
((car ,destination)
(setq outbuf (current-buffer))))
;; stderr.
(cond
((stringp (cadr ,destination))
(setcar (cdr ,destination) (expand-file-name (cadr ,destination)))
(if (tramp-equal-remote default-directory (cadr ,destination))
;; stderr is on the same remote host.
(setq stderr (tramp-unquote-file-local-name (cadr ,destination)))
;; stderr must be copied to remote host. The temporary
;; file must be deleted after execution.
(setq stderr (tramp-make-tramp-temp-file v)
tmpstderr (tramp-make-tramp-file-name v stderr))))
;; stderr to be discarded.
((null (cadr ,destination))
(setq stderr (tramp-get-remote-null-device v)))))
;; t
(,destination
(setq outbuf (current-buffer))))
,@body
;; Provide error file.
(when tmpstderr (rename-file tmpstderr (cadr ,destination) t))
;; Cleanup. We remove all file cache values for the connection,
;; because the remote process could have changed them.
(when tmpinput (delete-file tmpinput))
(when process-file-side-effects
(tramp-flush-directory-properties v "/"))
;; Return exit status.
(if (equal ret -1)
(keyboard-quit)
ret))))
(defcustom tramp-inhibit-errors-if-setting-file-attributes-fail nil
"Whether to warn only if `tramp-*-set-file-{modes,times,uid-gid}' fails."
:version "30.1"
@ -5065,10 +5152,6 @@ should be set connection-local.")
;; Query flag is overwritten in `tramp-post-process-creation',
;; so we reset it.
(set-process-query-on-exit-flag p (null noquery))
;; This is needed for ssh or PuTTY based processes, and only if
;; the respective options are set. Perhaps, the setting could
;; be more fine-grained.
;; (process-put p 'tramp-shared-socket t)
(process-put p 'remote-command orig-command)
(tramp-set-connection-property p "remote-command" orig-command)
(when (bufferp stderr)
@ -6936,18 +7019,13 @@ If VEC is `tramp-null-hop', return local null device."
;; <https://www.mail-archive.com/tramp-devel@nongnu.org/msg01041.html>.
;; (Bug#6850)
;;
;; * Refactor code from different handlers. Start with
;; *-process-file. One idea is to generalize `tramp-send-command'
;; and friends, for most of the handlers this is the major
;; difference between the different backends. Other handlers but
;; *-process-file would profit from this as well.
;;
;; * Implement file name abbreviation for a different user. That is,
;; (abbreviate-file-name "/ssh:user1@host:/home/user2") =>
;; "/ssh:user1@host:~user2".
;;
;; * Implement file name abbreviation for user and host names.
;;
;; * Implement user and host name completion for multi-hops.
;; * Implement user and host name completion for multi-hops. Some
;; methods in tramp-container.el have it already.
;;; tramp.el ends here