@cindex GNU ELPA
@vindex tramp-version
-@value{tramp} is included as part of Emacs (since @w{Emacs 22.1}).
+@value{tramp} is included as part of Emacs.
@value{tramp} is also freely packaged for download on the Internet at
@uref{https://ftp.gnu.org/gnu/tramp/}. The version number of
@end lisp
@value{tramp} is also available as @uref{https://elpa.gnu.org, GNU
-ELPA} package. Besides the standalone releases, further minor versions
-of @value{tramp} will appear on GNU ELPA, until the next @value{tramp}
-release appears. These minor versions have a four-number string, like
-``2.4.5.1''.
+ELPA} package. Besides the standalone releases, further minor
+versions of @value{tramp} will appear on GNU ELPA, until the next
+@value{tramp} release appears. These minor versions have a
+four-number string, like ``2.4.5.1''. The manual of the latest
+@value{tramp} ELPA package is located at
+@uref{https://elpa.gnu.org/packages/doc/tramp.html}.
@value{tramp} development versions are available on Git servers.
Development versions contain new and incomplete features. The
@subsection Remote process connection type
@vindex process-connection-type
-@cindex tramp-process-connection-type
+@vindex tramp-process-connection-type
Asynchronous processes behave differently based on whether they use a
pseudo tty or not. This is controlled by the variable
@end group
@end lisp
-@cindex proced
+@cindex @code{proced}
@vindex proced-show-remote-processes
If you want to see a listing of remote system processes when calling
@code{proced}, set user option @code{proced-show-remote-processes} to
@c In the Tramp GIT, the version number and the bug report address
@c are auto-frobbed from configure.ac.
-@set trampver 2.6.2.29.2
+@set trampver 2.6.3-pre
@set trampurl https://www.gnu.org/software/tramp/
@set tramp-bug-report-address tramp-devel@@gnu.org
@set emacsver 26.1
(file-name-as-directory f)
f))
(with-current-buffer (tramp-get-buffer v)
- (append
- ;; On some file systems like "sdcard", "." and ".." are
- ;; not included.
- '("." "..")
- (mapcar
- (lambda (l)
- (and (not (string-match-p (rx bol (* blank) eol) l)) l))
- (split-string (buffer-string) "\n" 'omit))))))))))
+ (mapcar
+ (lambda (l)
+ (and (not (string-match-p (rx bol (* blank) eol) l)) l))
+ (split-string (buffer-string) "\n" 'omit)))))))))
(defun tramp-adb-handle-file-local-copy (filename)
"Like `file-local-copy' for Tramp files."
(declare (indent 3) (debug t))
`(progn
;; Unify localname. Remove hop from `tramp-file-name' structure.
- (setq ,key (tramp-file-name-unify ,key ,file))
+ (setf ,key (tramp-file-name-unify ,key ,file))
(let* ((hash (tramp-get-hash-table ,key))
(cached (and (hash-table-p hash) (gethash ,property hash))))
(unwind-protect (progn ,@body)
(declare (indent 3) (debug t))
`(progn
;; Unify localname. Remove hop from `tramp-file-name' structure.
- (setq ,key (tramp-file-name-unify ,key ,file))
+ (setf ,key (tramp-file-name-unify ,key ,file))
(let* ((hash (tramp-get-hash-table ,key))
(values
(and (hash-table-p hash)
"Save PROPERTY, run BODY, reset PROPERTY."
(declare (indent 2) (debug t))
`(progn
- (setq ,key (tramp-file-name-unify ,key))
+ (setf ,key (tramp-file-name-unify ,key))
(let* ((hash (tramp-get-hash-table ,key))
(cached (and (hash-table-p hash)
(gethash ,property hash tramp-cache-undefined))))
PROPERTIES is a list of file properties (strings)."
(declare (indent 2) (debug t))
`(progn
- (setq ,key (tramp-file-name-unify ,key))
+ (setf ,key (tramp-file-name-unify ,key))
(let* ((hash (tramp-get-hash-table ,key))
(values
(mapcar
;; avoid them in cases we know what we do.
(defmacro tramp-compat-funcall (function &rest arguments)
"Call FUNCTION with ARGUMENTS if it exists. Do not raise compiler warnings."
+ (declare (indent 1) (debug t))
`(when (functionp ,function)
(with-no-warnings (funcall ,function ,@arguments))))
(and tramp-crypt-enabled (stringp name)
(not (tramp-compat-file-name-quoted-p name))
(not (string-suffix-p tramp-crypt-encfs-config name))
+ ;; No lock file name.
+ (not (string-prefix-p ".#" (file-name-nondirectory name)))
(dolist (dir tramp-crypt-directories)
(and (string-prefix-p
dir (file-name-as-directory (expand-file-name name)))
;; New handlers should be added here.
;;;###tramp-autoload
(defconst tramp-crypt-file-name-handler-alist
- '(;; `abbreviate-file-name' performed by default handler.
+ '((abbreviate-file-name . identity)
(access-file . tramp-crypt-handle-access-file)
(add-name-to-file . tramp-handle-add-name-to-file)
;; `byte-compiler-base-file-name' performed by default handler.
;;;###tramp-autoload
(defun tramp-crypt-add-directory (name)
- "Mark remote directory NAME for encryption.
+ "Mark expanded remote directory NAME for encryption.
Files in that directory and all subdirectories will be encrypted
before copying to, and decrypted after copying from that
directory. File names will be also encrypted."
#'tramp-crypt-command-completion-p)
(defun tramp-crypt-remove-directory (name)
- "Unmark remote directory NAME for encryption.
+ "Unmark expanded remote directory NAME for encryption.
Existing files in that directory and its subdirectories will be
kept in their encrypted form."
;; (declare (completion tramp-crypt-command-completion-p))
(tramp-compat-funcall
'unlock-file (tramp-crypt-encrypt-file-name filename))))
+(defun tramp-crypt-cleanup-connection (vec)
+ "Cleanup crypt ressources determined by VEC."
+ (let ((tramp-cleanup-connection-hook
+ (remove
+ #'tramp-crypt-cleanup-connection tramp-cleanup-connection-hook)))
+ (dolist (dir tramp-crypt-directories)
+ (when (tramp-file-name-equal-p vec (tramp-dissect-file-name dir))
+ (tramp-cleanup-connection (tramp-crypt-dissect-file-name dir))))))
+
+;; Add cleanup hooks.
+(add-hook 'tramp-cleanup-connection-hook #'tramp-crypt-cleanup-connection)
+(add-hook 'tramp-crypt-unload-hook
+ (lambda ()
+ (remove-hook 'tramp-cleanup-connection-hook
+ #'tramp-crypt-cleanup-connection)))
+
(with-eval-after-load 'bookmark
(add-hook 'bookmark-inhibit-context-functions
#'tramp-crypt-file-name-p)
(tramp-fuse-remove-hidden-files
(all-completions
filename
- (append
- (file-name-all-completions
- filename (tramp-fuse-local-file-name directory))
- ;; Some storage systems do not return "." and "..".
- (let (result)
- (dolist (item '(".." ".") result)
- (when (string-prefix-p filename item)
- (catch 'match
- (dolist (elt completion-regexp-list)
- (unless (string-match-p elt item) (throw 'match nil)))
- (setq result (cons (concat item "/") result)))))))))))
+ (file-name-all-completions
+ filename (tramp-fuse-local-file-name directory))))))
;; This function isn't used.
(defun tramp-fuse-handle-insert-directory
filename
(with-parsed-tramp-file-name (expand-file-name directory) nil
(with-tramp-file-property v localname "file-name-all-completions"
- (let ((result '("./" "../")))
+ (let (result)
;; Get a list of directories and files.
(dolist (item
(tramp-gvfs-get-directory-attributes directory)
(tramp-run-real-handler
#'expand-file-name (list localname))))))))))
-;;; Remote commands:
+;;; Remote processes:
+
+(defcustom tramp-pipe-stty-settings "-icanon min 1 time 0"
+ "How to prevent blocking read in pipeline processes.
+This is used in `make-process' with `connection-type' `pipe'."
+ :group 'tramp
+ :version "29.3"
+ :type '(choice (const :tag "Use size limit" "-icanon min 1 time 0")
+ (const :tag "Use timeout" "-icanon min 0 time 1")
+ string))
;; We use BUFFER also as connection buffer during setup. Because of
;; this, its original contents must be saved, and restored once
;; otherwise strings larger than 4096
;; bytes, sent by the process, could
;; block, see termios(3) and Bug#61341.
+ ;; In order to prevent blocking read
+ ;; from pipe processes, "stty -icanon"
+ ;; is used. By default, it expects at
+ ;; least one character to read. When a
+ ;; process does not read from stdin,
+ ;; like magit, it should set a timeout
+ ;; instead. See`tramp-pipe-stty-settings'.
+ ;; (Bug#62093)
;; FIXME: Shall we rather use "stty raw"?
- (if (tramp-check-remote-uname v "Darwin")
- (tramp-send-command
- v "stty -icanon min 1 time 0")
- (tramp-send-command
- v "stty -icrnl -icanon min 1 time 0")))
+ (tramp-send-command
+ v (format
+ "stty %s %s"
+ (if (tramp-check-remote-uname v "Darwin")
+ "" "-icrnl")
+ tramp-pipe-stty-settings)))
;; `tramp-maybe-open-connection' and
;; `tramp-send-command-and-read' could
;; have trashed the connection buffer.
(tramp-compat-rx
bos
(| (literal tramp-system-name)
- (| "localhost" "localhost4" "localhost6" "127.0.0.1" "::1"))
+ (| "localhost" "127.0.0.1" "::1"
+ ;; Fedora.
+ "localhost4" "localhost6"
+ ;; Ubuntu.
+ "ip6-localhost" "ip6-loopback"))
eos)
"Host names which are regarded as local host.
If the local host runs a chrooted environment, set this to nil."
- :version "29.1"
+ :version "29.3"
:type '(choice (const :tag "Chrooted environment" nil)
(regexp :tag "Host regexp")))
(tramp-run-real-handler #'file-exists-p (list filename))))
(defmacro tramp-skeleton-file-name-all-completions
- (_filename _directory &rest body)
+ (filename directory &rest body)
"Skeleton for `tramp-*-handle-filename-all-completions'.
BODY is the backend specific code."
(declare (indent 2) (debug t))
`(tramp-compat-ignore-error file-missing
(delete-dups (delq nil
(let* ((case-fold-search read-file-name-completion-ignore-case)
- (regexp (mapconcat #'identity completion-regexp-list "\\|"))
- (result ,@body))
+ (result (progn ,@body)))
+ ;; Some storage systems do not return "." and "..".
+ (when (tramp-tramp-file-p ,directory)
+ (dolist (elt '(".." "."))
+ (when (string-prefix-p ,filename elt)
+ (setq result (cons (concat elt "/") result)))))
(if (consp completion-regexp-list)
;; Discriminate over `completion-regexp-list'.
(mapcar
- (lambda (x) (and (stringp x) (string-match-p regexp x) x))
+ (lambda (x)
+ (when (stringp x)
+ (catch 'match
+ (dolist (elt completion-regexp-list x)
+ (unless (string-match-p elt x) (throw 'match nil))))))
result)
result))))))
(with-parsed-tramp-file-name (expand-file-name ,directory) nil
(tramp-barf-if-file-missing v ,directory
(when (file-directory-p ,directory)
- (setq ,directory
+ (setf ,directory
(file-name-as-directory (expand-file-name ,directory)))
(let ((temp
(with-tramp-file-property v localname "directory-files" ,@body))
`remote-pid', or PROCESS is a number and REMOTE is a remote file name,
PROCESS is interpreted as process on the respective remote host, which
will be the process to signal.
+If PROCESS is a string, it is interpreted as process object with
+the respective process name, or as a number.
SIGCODE may be an integer, or a symbol whose name is a signal name."
+ (when (stringp process)
+ (setq process (or (get-process process)
+ (and (string-match-p (rx bol (+ digit) eol) process)
+ (string-to-number process))
+ (signal 'wrong-type-argument (list #'processp process)))))
(let (pid vec)
(cond
((processp process)
;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
;; Package: tramp
-;; Version: 2.6.2.29.2
+;; Version: 2.6.3-pre
;; Package-Requires: ((emacs "26.1"))
;; Package-Type: multi
;; URL: https://www.gnu.org/software/tramp/
;; ./configure" to change them.
;;;###tramp-autoload
-(defconst tramp-version "2.6.2.29.2"
+(defconst tramp-version "2.6.3-pre"
"This version of Tramp.")
;;;###tramp-autoload
;; Check for Emacs version.
(let ((x (if (not (string-version-lessp emacs-version "26.1"))
"ok"
- (format "Tramp 2.6.2.29.2 is not fit for %s"
+ (format "Tramp 2.6.3-pre is not fit for %s"
(replace-regexp-in-string "\n" "" (emacs-version))))))
(unless (string-equal "ok" x) (error "%s" x)))
(should (eq (file-attribute-type attr) t)))
;; Cleanup.
- (ignore-errors (delete-directory tmp-name1))
+ (ignore-errors (delete-directory tmp-name1 'recursive))
(ignore-errors (delete-file tmp-name1))
(ignore-errors (delete-file tmp-name2))))))
(delete-exited-processes t)
kill-buffer-query-functions command proc)
- (dolist (sigcode '(2 INT))
- (unwind-protect
- (with-temp-buffer
- (setq command "trap 'echo boom; exit 1' 2; sleep 100"
- proc (start-file-process-shell-command
- (format "test1%s" sigcode) (current-buffer) command))
- (should (processp proc))
- (should (process-live-p proc))
- (should (equal (process-status proc) 'run))
- (should (numberp (process-get proc 'remote-pid)))
- (should (equal (process-get proc 'remote-command)
- (with-connection-local-variables
- `(,shell-file-name ,shell-command-switch ,command))))
- (should (zerop (signal-process proc sigcode)))
- ;; Let the process accept the signal.
- (with-timeout (10 (tramp--test-timeout-handler))
- (while (accept-process-output proc 0 nil t)))
- (should-not (process-live-p proc)))
+ ;; If PROCESS is a string, it must be a process name or a process
+ ;; number. Check error handling.
+ (should-error
+ (signal-process (md5 (current-time-string)) 0)
+ :type 'wrong-type-argument)
+
+ ;; The PROCESS argument of `signal-process' can be a string. Test
+ ;; this as well.
+ (dolist
+ (func '(identity
+ (lambda (x) (format "%s" (if (processp x) (process-name x) x)))))
+ (dolist (sigcode '(2 INT))
+ (unwind-protect
+ (with-temp-buffer
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ (format "test1-%s" sigcode) (current-buffer) command))
+ (should (processp proc))
+ (should (process-live-p proc))
+ (should (equal (process-status proc) 'run))
+ (should (numberp (process-get proc 'remote-pid)))
+ (should
+ (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
+ (should (zerop (signal-process (funcall func proc) sigcode)))
+ ;; Let the process accept the signal.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ (should-not (process-live-p proc)))
- ;; Cleanup.
- (ignore-errors (kill-process proc))
- (ignore-errors (delete-process proc)))
+ ;; Cleanup.
+ (ignore-errors (kill-process proc))
+ (ignore-errors (delete-process proc)))
- (unwind-protect
- (with-temp-buffer
- (setq command "trap 'echo boom; exit 1' 2; sleep 100"
- proc (start-file-process-shell-command
- (format "test2%s" sigcode) (current-buffer) command))
- (should (processp proc))
- (should (process-live-p proc))
- (should (equal (process-status proc) 'run))
- (should (numberp (process-get proc 'remote-pid)))
- (should (equal (process-get proc 'remote-command)
- (with-connection-local-variables
- `(,shell-file-name ,shell-command-switch ,command))))
- ;; `signal-process' has argument REMOTE since Emacs 29.
- (with-no-warnings
+ (unwind-protect
+ (with-temp-buffer
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ (format "test2-%s" sigcode) (current-buffer) command))
+ (should (processp proc))
+ (should (process-live-p proc))
+ (should (equal (process-status proc) 'run))
+ (should (numberp (process-get proc 'remote-pid)))
(should
- (zerop
- (signal-process
- (process-get proc 'remote-pid) sigcode default-directory))))
- ;; Let the process accept the signal.
- (with-timeout (10 (tramp--test-timeout-handler))
- (while (accept-process-output proc 0 nil t)))
- (should-not (process-live-p proc)))
+ (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
+ ;; `signal-process' has argument REMOTE since Emacs 29.
+ (with-no-warnings
+ (should
+ (zerop
+ (signal-process
+ (funcall func (process-get proc 'remote-pid))
+ sigcode default-directory))))
+ ;; Let the process accept the signal.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ (should-not (process-live-p proc)))
- ;; Cleanup.
- (ignore-errors (kill-process proc))
- (ignore-errors (delete-process proc))))))
+ ;; Cleanup.
+ (ignore-errors (kill-process proc))
+ (ignore-errors (delete-process proc)))))))
(ert-deftest tramp-test31-list-system-processes ()
"Check `list-system-processes'."