* doc/misc/tramp.texi (Frequently Asked Questions): Mention Emacs 28.
* doc/misc/trampver.texi:
* lisp/net/trampver.el: Change version to "2.4.4-pre".
* lisp/net/tramp-adb.el (tramp-adb-handle-copy-file)
(tramp-adb-handle-rename-file, tramp-adb-handle-process-file):
Use `tramp-file-local-name'.
(tramp-adb-handle-exec-path): Expand `default-directory'.
* lisp/net/tramp-cmds.el (tramp-rename-files):
Use `tramp-file-local-name'.
* lisp/net/tramp-sh.el (tramp-sh-handle-make-symbolic-link)
(tramp-do-copy-or-rename-file-directly)
(tramp-sh-handle-process-file, tramp-set-remote-path)
(tramp-find-inline-encoding, tramp-get-remote-touch):
Use `tramp-file-local-name'.
(tramp-sh-handle-make-process): Support `stderr' as file name.
Delete temporary stderr file.
(tramp-sh-handle-exec-path): Expand `default-directory'.
* lisp/net/tramp-smb.el (tramp-smb-handle-make-symbolic-link)
(tramp-smb-handle-process-file): Use `tramp-file-local-name'.
* lisp/net/tramp-sudoedit.el (tramp-sudoedit-do-copy-or-rename-file)
(tramp-sudoedit-handle-set-file-uid-gid):
Use `tramp-unquote-file-local-name'.
(tramp-sudoedit-handle-make-symbolic-link):
Use `tramp-file-local-name'.
(tramp-sudoedit-handle-file-system-info): Fix a scoping error.
* lisp/net/tramp.el: Bump version to 2.4.4-pre.
(tramp-ignored-file-name-regexp, tramp-time-dont-know)
(tramp-time-doesnt-exist): Fix typo.
(tramp-file-local-name): Extend for non-remote file names.
(tramp-unquote-file-local-name): New defun.
(tramp-completion-make-tramp-file-name): Simplify.
(tramp-set-connection-local-variables-for-buffer)
(tramp-equal-remote, tramp-handle-make-auto-save-file-name):
Use `tramp-tramp-file-p'.
(tramp-handle-file-name-case-insensitive-p)
(tramp-handle-file-truename, tramp-get-remote-tmpdir)
(tramp-make-tramp-temp-file): Use `tramp-file-local-name'.
(tramp-handle-shell-command, tramp-handle-start-file-process):
Implement asynchronous `error-buffer'.
@item
Which systems does it work on?
-The package works successfully on Emacs 24, Emacs 25, Emacs 26, and
-Emacs 27.
+The package works successfully on Emacs 24, Emacs 25, Emacs 26, Emacs
+27, and Emacs 28.
While Unix and Unix-like systems are the primary remote targets,
@value{tramp} has equal success connecting to other platforms, such as
@c In the Tramp GIT, the version numbers are auto-frobbed from
@c tramp.el, and the bug report address is auto-frobbed from
@c configure.ac.
-@set trampver 2.4.3.27.1
+@set trampver 2.4.4-pre
@set tramp-bug-report-address tramp-devel@@gnu.org
@set emacsver 24.4
(with-tramp-progress-reporter
v 0 (format "Copying %s to %s" filename newname)
(if (and t1 t2 (tramp-equal-remote filename newname))
- (let ((l1 (tramp-compat-file-local-name filename))
- (l2 (tramp-compat-file-local-name newname)))
+ (let ((l1 (tramp-file-local-name filename))
+ (l2 (tramp-file-local-name newname)))
;; We must also flush the cache of the directory,
;; because `file-attributes' reads the values from
;; there.
(if (and t1 t2
(tramp-equal-remote filename newname)
(not (file-directory-p filename)))
- (let ((l1 (tramp-compat-file-local-name filename))
- (l2 (tramp-compat-file-local-name newname)))
+ (let ((l1 (tramp-file-local-name filename))
+ (l2 (tramp-file-local-name newname)))
;; We must also flush the cache of the directory, because
;; `file-attributes' reads the values from there.
(tramp-flush-file-properties v l1)
(setq infile (expand-file-name infile))
(if (tramp-equal-remote default-directory infile)
;; INFILE is on the same remote host.
- (setq input (with-parsed-tramp-file-name infile nil localname))
+ (setq input (tramp-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))
(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 (with-parsed-tramp-file-name
- (cadr destination) nil localname))
+ (setq stderr (tramp-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)
(read (current-buffer)))
":" 'omit)))
;; The equivalent to `exec-directory'.
- `(,(tramp-compat-file-local-name default-directory))))
+ `(,(tramp-file-local-name (expand-file-name default-directory)))))
(defun tramp-adb-get-device (vec)
"Return full host name from VEC to be used in shell execution.
;; Append local file name if none is specified.
(when (string-equal (file-remote-p target) target)
- (setq target (concat target (file-remote-p source 'localname))))
+ (setq target (concat target (tramp-file-local-name source))))
;; Make them directory names.
(setq source (directory-file-name source)
target (directory-file-name target))
(require 'shell)
(require 'subr-x)
+;; `temporary-file-directory' as function is introduced with Emacs 26.1.
(declare-function tramp-handle-temporary-file-directory "tramp")
;; For not existing functions, obsolete functions, or functions with a
,(tramp-rclone-mount-point vec)
;; This could be nil.
,(tramp-get-method-parameter vec 'tramp-mount-args))))
- (while (not (file-exists-p (tramp-make-tramp-file-name vec 'localname)))
+ (while (not (file-exists-p (tramp-make-tramp-file-name vec 'noloc)))
(tramp-cleanup-connection vec 'keep-debug 'keep-password))
;; Mark it as connected.
(let ((non-essential t))
(when (and (tramp-tramp-file-p target)
(tramp-file-name-equal-p v (tramp-dissect-file-name target)))
- (setq target
- (tramp-file-name-localname
- (tramp-dissect-file-name (expand-file-name target))))))
+ (setq target (tramp-file-local-name (expand-file-name target)))))
;; If TARGET is still remote, quote it.
(if (tramp-tramp-file-p target)
v 'file-error
"Unknown operation `%s', must be `copy' or `rename'"
op))))
- (localname1 (tramp-compat-file-local-name filename))
- (localname2 (tramp-compat-file-local-name newname))
+ (localname1 (tramp-file-local-name filename))
+ (localname2 (tramp-file-local-name newname))
(prefix (file-remote-p (if t1 filename newname)))
cmd-result)
(when (and (eq op 'copy) (file-directory-p filename))
;; this, its original contents must be saved, and restored once
;; connection has been setup.
(defun tramp-sh-handle-make-process (&rest args)
- "Like `make-process' for Tramp files."
+ "Like `make-process' for Tramp files.
+STDERR can also be a file name."
(when args
(with-parsed-tramp-file-name (expand-file-name default-directory) nil
(let ((name (plist-get args :name))
(signal 'wrong-type-argument (list #'functionp sentinel)))
(unless (or (null stderr) (bufferp stderr) (stringp stderr))
(signal 'wrong-type-argument (list #'stringp stderr)))
+ (when (and (stringp stderr) (tramp-tramp-file-p stderr)
+ (not (tramp-equal-remote default-directory stderr)))
+ (signal 'file-error (list "Wrong stderr" stderr)))
(let* ((buffer
(if buffer
(get-buffer-create buffer)
;; BUFFER can be nil. We use a temporary buffer.
(generate-new-buffer tramp-temp-buffer-name)))
- (stderr (and stderr (get-buffer-create stderr)))
- (tmpstderr (and stderr (tramp-make-tramp-temp-file v)))
+ ;; STDERR can also be a file name.
+ (tmpstderr
+ (and stderr
+ (if (and (stringp stderr) (tramp-tramp-file-p stderr))
+ (tramp-unquote-file-local-name stderr)
+ (tramp-make-tramp-temp-file v))))
(program (car command))
(args (cdr command))
;; When PROGRAM matches "*sh", and the first arg is
(ignore-errors
(set-process-query-on-exit-flag p (null noquery))
(set-marker (process-mark p) (point)))
+ ;; Copy tmpstderr file.
+ (when (and (stringp stderr)
+ (not (tramp-tramp-file-p stderr)))
+ (add-function
+ :after (process-sentinel p)
+ (lambda (_proc _msg)
+ (rename-file
+ (tramp-make-tramp-file-name v tmpstderr) stderr))))
;; Provide error buffer. This shows only
;; initial error messages; messages arriving
;; later on shall be inserted by `auto-revert'.
- ;; The temporary file will still be existing.
- ;; TODO: Write a sentinel, which deletes the
- ;; temporary file.
- (when tmpstderr
+ ;; The temporary file will exist until the
+ ;; process is deleted.
+ (when (bufferp stderr)
;; We must flush them here already; otherwise
;; `insert-file-contents' will fail.
(tramp-flush-connection-property v "process-name")
(with-current-buffer stderr
(insert-file-contents
(tramp-make-tramp-file-name v tmpstderr) 'visit)
- (auto-revert-mode)))
+ (auto-revert-mode))
+ ;; Delete tmpstderr file.
+ (add-function
+ :after (process-sentinel p)
+ (lambda (_proc _msg)
+ (delete-file
+ (tramp-make-tramp-file-name v tmpstderr)))))
;; Return process.
p)))
(setq infile (expand-file-name infile))
(if (tramp-equal-remote default-directory infile)
;; INFILE is on the same remote host.
- (setq input (with-parsed-tramp-file-name infile nil localname))
+ (setq input (tramp-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 'nohop))
(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 (with-parsed-tramp-file-name
- (cadr destination) nil localname))
+ (setq stderr (tramp-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)
(append
(tramp-get-remote-path (tramp-dissect-file-name default-directory))
;; The equivalent to `exec-directory'.
- `(,(tramp-compat-file-local-name default-directory))))
+ `(,(tramp-file-local-name (expand-file-name default-directory)))))
(defun tramp-sh-handle-file-local-copy (filename)
"Like `file-local-copy' for Tramp files."
(setq tmpfile
(tramp-make-tramp-file-name vec (tramp-make-tramp-temp-file vec)))
(write-region command nil tmpfile)
- (tramp-send-command
- vec (format ". %s" (tramp-compat-file-local-name tmpfile)))
+ (tramp-send-command vec (format ". %s" (tramp-file-local-name tmpfile)))
(delete-file tmpfile))))
;; ------------------------------------------------------------
(format-spec
value
(format-spec-make
- ?t (tramp-compat-file-local-name tmpfile)))))
+ ?t (tramp-file-local-name tmpfile)))))
(tramp-maybe-send-script vec value name)
(setq rem-dec name)))
(tramp-message
vec 5 "Cannot timeout session, trying it again in %s seconds." 5)
(run-at-time 5 nil 'tramp-timeout-session vec))
(tramp-message
- vec 3 "Timeout session %s" (tramp-make-tramp-file-name vec 'localname))
+ vec 3 "Timeout session %s" (tramp-make-tramp-file-name vec 'noloc))
(tramp-cleanup-connection vec 'keep-debug)))
(defun tramp-maybe-open-connection (vec)
"%s -t %s %s"
result
(format-time-string "%Y%m%d%H%M.%S")
- (tramp-compat-file-local-name tmpfile))))
+ (tramp-file-local-name tmpfile))))
(delete-file tmpfile))
result)))
(let ((non-essential t))
(when (and (tramp-tramp-file-p target)
(tramp-file-name-equal-p v (tramp-dissect-file-name target)))
- (setq target
- (tramp-file-name-localname
- (tramp-dissect-file-name (expand-file-name target))))))
+ (setq target (tramp-file-local-name (expand-file-name target)))))
;; If TARGET is still remote, quote it.
(if (tramp-tramp-file-p target)
(setq infile (expand-file-name infile))
(if (tramp-equal-remote default-directory infile)
;; INFILE is on the same remote host.
- (setq input (with-parsed-tramp-file-name infile nil localname))
+ (setq input (tramp-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))
v 0 (format "%s %s to %s" msg-operation filename newname)
(unless (tramp-sudoedit-send-command
v sudoedit-operation
- (tramp-compat-file-name-unquote
- (tramp-compat-file-local-name filename))
- (tramp-compat-file-name-unquote
- (tramp-compat-file-local-name newname)))
+ (tramp-unquote-file-local-name filename)
+ (tramp-unquote-file-local-name newname))
(tramp-error
v 'file-error
"Error %s `%s' `%s'" msg-operation filename newname))))
(let ((non-essential t))
(when (and (tramp-tramp-file-p target)
(tramp-file-name-equal-p v (tramp-dissect-file-name target)))
- (setq target
- (tramp-file-name-localname
- (tramp-dissect-file-name (expand-file-name target))))))
+ (setq target (tramp-file-local-name (expand-file-name target)))))
;; If TARGET is still remote, quote it.
(if (tramp-tramp-file-p target)
(format "%d:%d"
(or uid (tramp-sudoedit-get-remote-uid v 'integer))
(or gid (tramp-sudoedit-get-remote-gid v 'integer)))
- (tramp-compat-file-name-unquote
- (tramp-compat-file-local-name filename)))))
+ (tramp-unquote-file-local-name filename))))
(defun tramp-sudoedit-handle-write-region
(start end filename &optional append visit lockname mustbenew)
;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
;; Package: tramp
-;; Version: 2.4.3
+;; Version: 2.4.4-pre
;; Package-Requires: ((emacs "24.4"))
;; Package-Type: multi
;; URL: https://savannah.gnu.org/projects/tramp
This function removes from NAME the specification of the remote
host and the method of accessing the host, leaving only the part
that identifies NAME locally on the remote system. NAME must be
-a string that matches `tramp-file-name-regexp'. The returned
-file name can be used directly as argument of `process-file',
-`start-file-process', or `shell-command'."
+a string that matches `tramp-file-name-regexp'. If NAME does not
+match `tramp-file-name-regexp', just NAME is returned. The
+returned file name can be used directly as argument of
+`process-file', `start-file-process', or `shell-command'."
(save-match-data
- (and (tramp-tramp-file-p name)
- (string-match (nth 0 tramp-file-name-structure) name)
- (match-string (nth 4 tramp-file-name-structure) name))))
+ (or (and (tramp-tramp-file-p name)
+ (string-match (nth 0 tramp-file-name-structure) name)
+ (match-string (nth 4 tramp-file-name-structure) name))
+ name)))
+
+;; The localname can be quoted with "/:". Extract this.
+(defun tramp-unquote-file-local-name (name)
+ "Return unquoted localname of NAME."
+ (tramp-compat-file-name-unquote (tramp-file-local-name name)))
(defun tramp-find-method (method user host)
"Return the right method string to use depending on USER and HOST.
tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
host)
tramp-postfix-host-format))
- (when localname localname)))
+ localname))
(defun tramp-get-buffer (vec &optional dont-create)
"Get the connection buffer to be used for VEC.
"Set connection-local variables in the current buffer.
If connection-local variables are not supported by this Emacs
version, the function does nothing."
- (when (file-remote-p default-directory)
+ (when (tramp-tramp-file-p default-directory)
;; `hack-connection-local-variables-apply' exists since Emacs 26.1.
(tramp-compat-funcall
'hack-connection-local-variables-apply
;; lower case letters. This avoids us to create a
;; temporary file.
(while (and (string-match-p
- "[a-z]" (tramp-compat-file-local-name candidate))
+ "[a-z]" (tramp-file-local-name candidate))
(not (file-exists-p candidate)))
(setq candidate
(directory-file-name
;; to Emacs 26+ like `file-name-case-insensitive-p',
;; so there is no compatibility problem calling it.
(unless
- (string-match-p
- "[a-z]" (tramp-compat-file-local-name candidate))
+ (string-match-p "[a-z]" (tramp-file-local-name candidate))
(setq tmpfile
(let ((default-directory
(file-name-directory filename)))
(file-exists-p
(concat
(file-remote-p candidate)
- (upcase (tramp-compat-file-local-name candidate))))
+ (upcase (tramp-file-local-name candidate))))
;; Cleanup.
(when tmpfile (delete-file tmpfile)))))))))))
(tramp-error
v1 'file-error
"Maximum number (%d) of symlinks exceeded" numchase-limit)))
- (tramp-compat-file-local-name (directory-file-name result)))))))))
+ (tramp-file-local-name (directory-file-name result)))))))))
(defun tramp-handle-file-writable-p (filename)
"Like `file-writable-p' for Tramp files."
(rename-uniquely))
(setq output-buffer (get-buffer-create bname)))))
- (setq buffer (if (and (not asynchronous) error-buffer)
+ (setq buffer (if error-buffer
(with-parsed-tramp-file-name default-directory nil
(list output-buffer
(tramp-make-tramp-file-name
;; Run the process.
(setq p (start-file-process-shell-command
(buffer-name output-buffer) buffer command))
- ;; Display output.
- (with-current-buffer output-buffer
- (display-buffer output-buffer '(nil (allow-no-window . t)))
- (setq mode-line-process '(":%s"))
- (shell-mode)
- (set-process-sentinel p #'shell-command-sentinel)
- (set-process-filter p #'comint-output-filter))))
+ (if (process-live-p p)
+ ;; Display output.
+ (with-current-buffer output-buffer
+ (display-buffer output-buffer '(nil (allow-no-window . t)))
+ (setq mode-line-process '(":%s"))
+ (shell-mode)
+ (set-process-filter p #'comint-output-filter)
+ (set-process-sentinel
+ p (if (listp buffer)
+ (lambda (_proc _string)
+ (with-current-buffer error-buffer
+ (insert-file-contents (cadr buffer)))
+ (delete-file (cadr buffer)))
+ #'shell-command-sentinel)))
+ ;; Show stderr.
+ (with-current-buffer error-buffer
+ (insert-file-contents (cadr buffer)))
+ (delete-file (cadr buffer)))))
(prog1
;; Run the process.
(display-message-or-buffer output-buffer)))))))
(defun tramp-handle-start-file-process (name buffer program &rest args)
- "Like `start-file-process' for Tramp files."
+ "Like `start-file-process' for Tramp files.
+BUFFER might be a list, in this case STDERR is separated."
;; `make-process' knows the `:file-handler' argument since Emacs 27.1 only.
(tramp-file-name-handler
'make-process
:name name
- :buffer buffer
+ :buffer (if (listp buffer) (car buffer) buffer)
:command (and program (cons program args))
+ ;; `shell-command' adds an errfile to `buffer'.
+ :stderr (when (listp buffer) (cadr buffer))
:noquery nil
:file-handler t))
(tramp-equal-remote \"/sudo::/etc\" \"/su::/etc\")
If both files are local, the function returns t."
- (or (and (null (file-remote-p file1)) (null (file-remote-p file2)))
+ (or (and (null (tramp-tramp-file-p file1)) (null (tramp-tramp-file-p file2)))
(and (tramp-tramp-file-p file1) (tramp-tramp-file-p file2)
(string-equal (file-remote-p file1) (file-remote-p file2)))))
(tramp-make-tramp-file-name
vec (or (tramp-get-method-parameter vec 'tramp-tmpdir) "/tmp"))))
(or (and (file-directory-p dir) (file-writable-p dir)
- (tramp-compat-file-local-name dir))
+ (tramp-file-local-name dir))
(tramp-error vec 'file-error "Directory %s not accessible" dir))
dir)))
(set-file-modes result #o0700)))
;; Return the local part.
- (with-parsed-tramp-file-name result nil localname)))
+ (tramp-file-local-name result)))
(defun tramp-delete-temp-file-function ()
"Remove temporary files related to current buffer."
(let ((system-type
(if (and (stringp tramp-auto-save-directory)
- (file-remote-p tramp-auto-save-directory))
+ (tramp-tramp-file-p tramp-auto-save-directory))
'not-windows
system-type))
(auto-save-file-name-transforms
(defvar inhibit-message)
;;;###tramp-autoload
-(defconst tramp-version "2.4.3.27.1"
+(defconst tramp-version "2.4.4-pre"
"This version of Tramp.")
;;;###tramp-autoload
;; Check for Emacs version.
(let ((x (if (not (string-lessp emacs-version "24.4"))
"ok"
- (format "Tramp 2.4.3.27.1 is not fit for %s"
+ (format "Tramp 2.4.4-pre is not fit for %s"
(replace-regexp-in-string "\n" "" (emacs-version))))))
(unless (string-equal "ok" x) (error "%s" x)))