1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 22:41:06 -08:00

Simplify Tramp's find-executable

* lisp/net/tramp-cache.el (with-tramp-saved-connection-property):
Fix typo.

* lisp/net/tramp-compat.el: Add TODO.

* lisp/net/tramp-sh.el (tramp-find-executable): Simplify, using
"type -P ...".
(tramp-set-remote-path): Better handling of superlong $PATH.
(tramp-get-remote-path): Adapt/use connection properties.

* test/lisp/net/tramp-tests.el (tramp--test-enabled)
(tramp-test03-file-name-host-rules): Don't wrap
`tramp-cleanup-connection' with `ignore-errors'.
This commit is contained in:
Michael Albinus 2025-02-19 19:38:25 +01:00
parent 9faa8d32a3
commit ec34bccfee
4 changed files with 74 additions and 91 deletions

View file

@ -482,10 +482,10 @@ used to cache connection properties of the local machine."
(hash (tramp-get-hash-table key)) (hash (tramp-get-hash-table key))
(cached (and (hash-table-p hash) (cached (and (hash-table-p hash)
(gethash ,property hash tramp-cache-undefined)))) (gethash ,property hash tramp-cache-undefined))))
(tramp-message key 7 "Saved %s %s" property cached) (tramp-message key 7 "Saved %s %s" ,property cached)
(unwind-protect (progn ,@body) (unwind-protect (progn ,@body)
;; Reset PROPERTY. Recompute hash, it could have been flushed. ;; Reset PROPERTY. Recompute hash, it could have been flushed.
(tramp-message key 7 "Restored %s %s" property cached) (tramp-message key 7 "Restored %s %s" ,property cached)
(setq hash (tramp-get-hash-table key)) (setq hash (tramp-get-hash-table key))
(if (not (eq cached tramp-cache-undefined)) (if (not (eq cached tramp-cache-undefined))
(puthash ,property cached hash) (puthash ,property cached hash)

View file

@ -245,6 +245,8 @@ value is the default binding of the variable."
;; ;;
;; * Use `with-environment-variables'. ;; * Use `with-environment-variables'.
;; ;;
;; * Use `ensure-list'.
;;
;; * Starting with Emacs 29.1, use `buffer-match-p'. ;; * Starting with Emacs 29.1, use `buffer-match-p'.
;; ;;
;; * Starting with Emacs 29.1, use `string-split'. ;; * Starting with Emacs 29.1, use `string-split'.

View file

@ -4092,44 +4092,23 @@ Returns the absolute file name of PROGNAME, if found, and nil otherwise.
This function expects to be in the right *tramp* buffer." This function expects to be in the right *tramp* buffer."
(with-current-buffer (tramp-get-connection-buffer vec) (with-current-buffer (tramp-get-connection-buffer vec)
(let (result) (unless ignore-path
;; Check whether the executable is in $PATH. "which(1)" does not (setq dirlist (cons "$PATH" dirlist)))
;; report always a correct error code; therefore we check the (when ignore-tilde
;; number of words it returns. "SunOS 5.10" (and maybe "SunOS ;; Remove all ~/foo directories from dirlist.
;; 5.11") have problems with this command, we disable the call (let (newdl d)
;; therefore. (while dirlist
(unless (or ignore-path (tramp-check-remote-uname vec tramp-sunos-unames)) (setq d (car dirlist)
(tramp-send-command vec (format "which \\%s | wc -w" progname)) dirlist (cdr dirlist))
(goto-char (point-min)) (unless (char-equal ?~ (aref d 0))
(if (looking-at-p (rx bol (* blank) "1" eol)) (setq newdl (cons d newdl))))
(setq result (concat "\\" progname)))) (setq dirlist (nreverse newdl))))
(unless result (tramp-send-command
(when ignore-tilde vec (format "%s type -P %s 2>%s"
;; Remove all ~/foo directories from dirlist. (if dirlist (concat "PATH=" (string-join dirlist ":")) "")
(let (newdl d) progname (tramp-get-remote-null-device vec)))
(while dirlist (unless (zerop (buffer-size))
(setq d (car dirlist) (string-trim (buffer-string)))))
dirlist (cdr dirlist))
(unless (char-equal ?~ (aref d 0))
(setq newdl (cons d newdl))))
(setq dirlist (nreverse newdl))))
(tramp-send-command
vec
(format (concat "while read d; "
"do if test -x $d/%s && test -f $d/%s; "
"then echo tramp_executable $d/%s; "
"break; fi; done <<'%s'\n"
"%s\n%s")
progname progname progname
tramp-end-of-heredoc
(string-join dirlist "\n")
tramp-end-of-heredoc))
(goto-char (point-max))
(when (search-backward "tramp_executable " nil t)
(skip-chars-forward "^ ")
(skip-chars-forward " ")
(setq result (buffer-substring (point) (line-end-position)))))
result)))
;; On hydra.nixos.org, the $PATH environment variable is too long to ;; On hydra.nixos.org, the $PATH environment variable is too long to
;; send it. This is likely not due to PATH_MAX, but PIPE_BUF. We ;; send it. This is likely not due to PATH_MAX, but PIPE_BUF. We
@ -4151,18 +4130,24 @@ variable PATH."
;; Use a temporary file. We cannot use `write-region' because ;; Use a temporary file. We cannot use `write-region' because
;; setting the remote path happens in the early connection ;; setting the remote path happens in the early connection
;; handshake, and not all external tools are determined yet. ;; handshake, and not all external tools are determined yet.
(setq command (concat command "\n") ;; Furthermore, we know that the COMMAND is too long, due to a
tmpfile (tramp-make-tramp-temp-file vec)) ;; very long remote-path. Set it temporarily to something
(while (not (string-empty-p command)) ;; short.
(setq chunksize (min (length command) (/ pipe-buf 2)) (with-tramp-saved-connection-property (tramp-get-process vec) "remote-path"
chunk (substring command 0 chunksize) (tramp-set-connection-property
command (substring command chunksize)) (tramp-get-process vec) "remote-path" '("/bin" "/usr/bin"))
(tramp-send-command vec (format (setq command (concat command "\n")
"printf \"%%b\" \"$*\" %s >>%s" tmpfile (tramp-make-tramp-temp-file vec))
(tramp-shell-quote-argument chunk) (while (not (string-empty-p command))
(tramp-shell-quote-argument tmpfile)))) (setq chunksize (min (length command) (/ pipe-buf 2))
(tramp-send-command vec (format ". %s" tmpfile)) chunk (substring command 0 chunksize)
(tramp-send-command vec (format "rm -f %s" tmpfile))))) command (substring command chunksize))
(tramp-send-command vec (format
"printf \"%%b\" \"$*\" %s >>%s"
(tramp-shell-quote-argument chunk)
(tramp-shell-quote-argument tmpfile))))
(tramp-send-command vec (format ". %s" tmpfile))
(tramp-send-command vec (format "rm -f %s" tmpfile))))))
;; ------------------------------------------------------------ ;; ------------------------------------------------------------
;; -- Communication with external shell -- ;; -- Communication with external shell --
@ -5569,50 +5554,48 @@ Nonexistent directories are removed from spec."
(with-current-buffer (tramp-get-connection-buffer vec) (with-current-buffer (tramp-get-connection-buffer vec)
;; Expand connection-local variables. ;; Expand connection-local variables.
(tramp-set-connection-local-variables vec) (tramp-set-connection-local-variables vec)
(with-tramp-connection-property (with-tramp-connection-property (tramp-get-process vec) "remote-path"
;; When `tramp-own-remote-path' is in `tramp-remote-path', we
;; cache the result for the session only. Otherwise, the
;; result is cached persistently.
(if (memq 'tramp-own-remote-path tramp-remote-path)
(tramp-get-process vec) vec)
"remote-path"
(let* ((remote-path (copy-tree tramp-remote-path)) (let* ((remote-path (copy-tree tramp-remote-path))
(elt1 (memq 'tramp-default-remote-path remote-path)) (elt1 (memq 'tramp-default-remote-path remote-path))
(elt2 (memq 'tramp-own-remote-path remote-path)) (elt2 (memq 'tramp-own-remote-path remote-path))
(default-remote-path (default-remote-path
(when elt1 (when elt1
(or (or
(tramp-send-command-and-read (with-tramp-connection-property
vec (tramp-get-process vec) "default-remote-path"
(format (tramp-send-command-and-read
"echo \\\"`getconf PATH 2>%s`\\\"" vec
(tramp-get-remote-null-device vec)) (format
'noerror) "echo \\\"`getconf PATH 2>%s`\\\""
;; Default if "getconf" is not available. (tramp-get-remote-null-device vec))
(progn 'noerror))
(tramp-message ;; Default if "getconf" is not available.
vec 3 (progn
"`getconf PATH' not successful, using default value \"%s\"." (tramp-message
"/bin:/usr/bin") vec 3
"/bin:/usr/bin")))) "`getconf PATH' not successful, using default value \"%s\"."
"/bin:/usr/bin")
"/bin:/usr/bin"))))
(own-remote-path (own-remote-path
;; The login shell could return more than just the $PATH ;; The login shell could return more than just the $PATH
;; string. So we use `tramp-end-of-heredoc' as marker. ;; string. So we use `tramp-end-of-heredoc' as marker.
(when elt2 (when elt2
(or (or
(tramp-send-command-and-read (with-tramp-connection-property
vec (tramp-get-process vec) "own-remote-path"
(format (tramp-send-command-and-read
"%s %s %s 'echo %s \\\"$PATH\\\"'" vec
(tramp-get-method-parameter vec 'tramp-remote-shell) (format
(string-join "%s %s %s 'echo %s \\\"$PATH\\\"'"
(tramp-get-method-parameter vec 'tramp-remote-shell-login) (tramp-get-method-parameter vec 'tramp-remote-shell)
" ") (string-join
(string-join (tramp-get-method-parameter vec 'tramp-remote-shell-login)
(tramp-get-method-parameter vec 'tramp-remote-shell-args) " ")
" ") (string-join
(tramp-shell-quote-argument tramp-end-of-heredoc)) (tramp-get-method-parameter vec 'tramp-remote-shell-args)
'noerror (rx (literal tramp-end-of-heredoc))) " ")
(tramp-shell-quote-argument tramp-end-of-heredoc))
'noerror (rx (literal tramp-end-of-heredoc))))
(progn (progn
(tramp-warning (tramp-warning
vec "Could not retrieve `tramp-own-remote-path'") vec "Could not retrieve `tramp-own-remote-path'")

View file

@ -282,8 +282,7 @@ being the result.")
(delete-directory file 'recursive) (delete-directory file 'recursive)
(delete-file file)))))) (delete-file file))))))
;; Cleanup connection. ;; Cleanup connection.
(ignore-errors (tramp-cleanup-connection tramp-test-vec nil 'keep-password))
(tramp-cleanup-connection tramp-test-vec nil 'keep-password)))
;; Return result. ;; Return result.
(cdr tramp--test-enabled-checked)) (cdr tramp--test-enabled-checked))
@ -2175,8 +2174,7 @@ being the result.")
(dolist (m '("su" "sg" "sudo" "doas" "ksu")) (dolist (m '("su" "sg" "sudo" "doas" "ksu"))
(when (assoc m tramp-methods) (when (assoc m tramp-methods)
(let (tramp-connection-properties tramp-default-proxies-alist) (let (tramp-connection-properties tramp-default-proxies-alist)
(ignore-errors (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password))
;; Single hop. The host name must match `tramp-local-host-regexp'. ;; Single hop. The host name must match `tramp-local-host-regexp'.
(should-error (should-error
(find-file (format "/%s:foo:" m)) (find-file (format "/%s:foo:" m))