Sync with Tramp 2.7.3-pre
* doc/misc/tramp.texi: Use @dots{} where appropriate. (External methods): Precise remark on rsync speed. (Customizing Methods): Add incus-tramp. (Password handling): Mention expiration of cached passwords when a session timeout happens. (Predefined connection information): Mention also "androidsu" as special case of "tmpdir". (Ad-hoc multi-hops, Frequently Asked Questions): Improve description how ad-hoc multi-hop file names can be made persistent. (Bug#65039, Bug#76457) (Remote processes): Signals are not delivered to remote direct async processes. Say, that there are restrictions for transfer of binary data to remote direct async processes. (Bug Reports): Explain bisecting. (Frequently Asked Questions): Improve index. Speak about fingerprint readers. Recommend `small-temporary-file-directory' for ssh sockets. (External packages): Rename subsection "Timers, process filters, process sentinels, redisplay". (Extension packages): New node. (Top, Files directories and localnames): Add it to @menu. * doc/misc/trampver.texi: * lisp/net/trampver.el (tramp-version): Adapt Tramp versions. (tramp-repository-branch, tramp-repository-version): Remove ;;;###tramp-autoload cookie. * lisp/net/tramp-adb.el: * lisp/net/tramp-androidsu.el: * lisp/net/tramp-cache.el: * lisp/net/tramp-cmds.el: * lisp/net/tramp-compat.el: * lisp/net/tramp-container.el: * lisp/net/tramp-crypt.el: * lisp/net/tramp-ftp.el: * lisp/net/tramp-fuse.el: * lisp/net/tramp-gvfs.el: * lisp/net/tramp-integration.el: * lisp/net/tramp-message.el: * lisp/net/tramp-rclone.el: * lisp/net/tramp-sh.el: * lisp/net/tramp-smb.el: * lisp/net/tramp-sshfs.el: * lisp/net/tramp-sudoedit.el: * lisp/net/tramp.el: Use `when-let*', `if-let*' and `and-let*' consequently. (Bug#73441) * lisp/net/tramp-adb.el (tramp-adb-maybe-open-connection): Move setting of sentinel up. * lisp/net/tramp-archive.el (tramp-archive-file-name-p): Add ;;;###tramp-autoload cookie. (tramp-archive-local-file-name): New defun. * lisp/net/tramp-cache.el (tramp-connection-properties): Add link to the Tramp manual in the docstring. (tramp-get-connection-property, tramp-set-connection-property): Don't raise a debug message for the `tramp-cache-version' key. (with-tramp-saved-connection-property) (with-tramp-saved-connection-properties): Add traces. (tramp-dump-connection-properties): Don't save connection property "pw-spec". * lisp/net/tramp-cmds.el (tramp-repository-branch) (tramp-repository-version): Declare. * lisp/net/tramp-gvfs.el (tramp-gvfs-do-copy-or-rename-file): (tramp-gvfs-do-copy-or-rename-file): Don't use the truename. Handle symlinks. (tramp-gvfs-local-file-name): New defun. * lisp/net/tramp-message.el (tramp-repository-branch) (tramp-repository-version): Declare. (tramp-error-with-buffer, tramp-user-error): Don't redisplay in `sit-for'. (Bug#73718) (tramp-warning): Fix `lwarn' call. * lisp/net/tramp.el (tramp-read-passwd): * lisp/net/tramp-sh.el (tramp-maybe-open-connection): * lisp/net/tramp-sudoedit.el (tramp-sudoedit-send-command): Rename connection property "password-vector" to "pw-vector". * lisp/net/tramp-sh.el (tramp-methods) <pscp, psftp>: Adapt `tramp-copy-args' argument. (tramp-get-remote-pipe-buf, tramp-actions-before-shell): Use `tramp-fingerprint-prompt-regexp'. (tramp-sh-handle-copy-directory): Apply `tramp-do-copy-or-rename-file-directly' if possible. (tramp-do-copy-or-rename-file): Refactor. Handle symlinks. (Bug#76678) (tramp-plink-option-exists-p): New defun. (tramp-ssh-or-plink-options): Rename from `tramp-ssh-controlmaster-options'. Adapt further plink options. (tramp-do-copy-or-rename-file-out-of-band) (tramp-maybe-open-connection): Adapt calls. (tramp-sh-handle-make-process): Don't set connection property "remote-pid", it's unused. (tramp-sh-handle-process-file): Do proper quoting. (tramp-vc-file-name-handler): Add `file-directory-p', which is used in `vc-find-root'. (Bug#74026) (tramp-maybe-open-connection): Use connection property "hop-vector". (tramp-get-remote-pipe-buf): Make it more robust. * lisp/net/tramp-smb.el (tramp-smb-errors): Add string. (tramp-smb-handle-copy-directory): Don't check existence of DIRNAME, this is done in `tramp-skeleton-copy-directory' already. (tramp-smb-handle-copy-file, tramp-smb-handle-rename-file): Refactor. * lisp/net/tramp-sshfs.el (tramp-sshfs-handle-process-file): STDERR is not implemented. * lisp/net/tramp-sudoedit.el (tramp-sudoedit-do-copy-or-rename-file): Don't use the truename. Handle symlinks. * lisp/net/tramp.el (tramp-mode): Set to nil on MS-DOS. (tramp-otp-password-prompt-regexp): Add TACC HPC prompt. (tramp-wrong-passwd-regexp): Add fingerprint messages. (tramp-fingerprint-prompt-regexp, tramp-use-fingerprint): New defcustoms. (tramp-string-empty-or-nil-p): Declare `tramp-suppress-trace' property. (tramp-barf-if-file-missing): Accept also symlinks. (tramp-skeleton-file-exists-p) (tramp-handle-file-directory-p): Protect against cyclic symlinks. (tramp-skeleton-make-symbolic-link): Drop volume letter when flushing. (tramp-skeleton-process-file): Raise a warning if STDERR is not implemented. (tramp-skeleton-set-file-modes-times-uid-gid): Fix typo. (tramp-compute-multi-hops): Check for `tramp-sh-file-name-handler-p', it works only for this. (tramp-handle-shell-command): Respect `async-shell-command-display-buffer'. (tramp-action-password, tramp-process-actions): Use connection property "hop-vector". (tramp-action-fingerprint, tramp-action-show-message): New defuns. (tramp-action-show-and-confirm-message): Start check at (point-min). (tramp-wait-for-regexp): Don't redisplay in `sit-for'. (Bug#73718) (tramp-convert-file-attributes): Don't cache "file-attributes-ID-FORMAT". (tramp-read-passwd, tramp-clear-passwd): Rewrite. (Bug#74105) * test/lisp/net/tramp-tests.el (auth-source-cache-expiry) (ert-batch-backtrace-right-margin): Set them to nil. (vc-handled-backends): Suppress if noninteractive. (tramp--test-enabled): Cleanup also `tramp-compat-temporary-file-directory'. (tramp-test11-copy-file, tramp-test12-rename-file) (tramp-test18-file-attributes, tramp--test-deftest-with-stat) (tramp--test-deftest-with-perl, tramp--test-deftest-with-ls) (tramp--test-deftest-without-file-attributes) (tramp-test21-file-links, tramp-test28-process-file) (tramp-test32-shell-command, tramp-test36-vc-registered) (tramp-test39-make-lock-file-name, tramp--test-check-files) (tramp-test42-utf8, tramp-test43-file-system-info) (tramp-test44-file-user-group-ids, tramp-test47-read-password): Adapt tests. (tramp-test47-read-fingerprint): New test.
This commit is contained in:
parent
e6b4c0bceb
commit
10991877c8
23 changed files with 1795 additions and 1181 deletions
|
@ -167,6 +167,7 @@ How file names, directories and localnames are mangled and managed
|
|||
* Temporary directory:: Where temporary files are kept.
|
||||
* Localname deconstruction:: Breaking a localname into its components.
|
||||
* External packages:: Integration with external Lisp packages.
|
||||
* Extension packages:: Adding new methods to @value{tramp}.
|
||||
|
||||
@end detailmenu
|
||||
@end menu
|
||||
|
@ -1112,7 +1113,8 @@ command to transfer is similar to the @option{scp} method.
|
|||
|
||||
@command{rsync} performs much better than @command{scp} when
|
||||
transferring files that exist on both hosts. However, this advantage
|
||||
is lost if the file exists only on one side of the connection.
|
||||
is lost if the file exists only on one side of the connection, during
|
||||
the first file transfer.
|
||||
|
||||
This method supports the @samp{-p} argument.
|
||||
|
||||
|
@ -1934,6 +1936,14 @@ They can be installed with Emacs's Package Manager. This includes
|
|||
@c @item ibuffer-tramp.el
|
||||
@c Contact Svend Sorensen <svend@@ciffer.net>
|
||||
|
||||
@cindex method @option{incus}
|
||||
@cindex @option{incus} method
|
||||
@item incus-tramp
|
||||
Integration for Incus containers. A container is accessed via
|
||||
@file{@trampfn{incus,user@@container,/path/to/file}}, @samp{user} and
|
||||
@samp{container} have the same meaning as with the @option{docker}
|
||||
method.
|
||||
|
||||
@cindex method @option{lxc}
|
||||
@cindex @option{lxc} method
|
||||
@item lxc-tramp
|
||||
|
@ -2211,6 +2221,12 @@ this interactively.
|
|||
@vindex auth-source-do-cache
|
||||
Set @code{auth-source-do-cache} to @code{nil} to disable password caching.
|
||||
|
||||
For connections which use a session-timeout, like @option{sudo},
|
||||
@option{doas} and @option{run0}, the password cache is expired by
|
||||
@value{tramp} when the session expires (@pxref{Predefined connection
|
||||
information}). However, this makes only sense if the password cannot
|
||||
be retrieved from a persistent authentication file or store.
|
||||
|
||||
|
||||
@node Connection caching
|
||||
@section Reusing connection related information
|
||||
|
@ -2332,9 +2348,9 @@ to a remote home directory, like @option{adb}, @option{rclone} and
|
|||
@item @t{"tmpdir"}
|
||||
|
||||
The temporary directory on the remote host. If not specified, the
|
||||
default value is @t{"/data/local/tmp"} for the @option{adb} method,
|
||||
@t{"/C$/Temp"} for the @option{smb} method, and @t{"/tmp"} otherwise.
|
||||
@ref{Temporary directory}.
|
||||
default value is @t{"/data/local/tmp"} for the @option{adb} and
|
||||
@option{androidsu} methods, @t{"/C$/Temp"} for the @option{smb}
|
||||
method, and @t{"/tmp"} otherwise. @ref{Temporary directory}.
|
||||
|
||||
@item @t{"posix"}
|
||||
|
||||
|
@ -2623,7 +2639,7 @@ will help:
|
|||
@example
|
||||
@group
|
||||
if test "$TERM" = "dumb"; then
|
||||
...
|
||||
@dots{}
|
||||
fi
|
||||
@end group
|
||||
@end example
|
||||
|
@ -3312,8 +3328,8 @@ Another option is to create better backup file naming with user and
|
|||
host names prefixed to the file name. For example, transforming
|
||||
@file{/etc/secretfile} to
|
||||
@file{~/.emacs.d/backups/!su:root@@localhost:!etc!secretfile}, set the
|
||||
@value{tramp} user option @code{tramp-backup-directory-alist} from
|
||||
the existing user option @code{backup-directory-alist}.
|
||||
@value{tramp} user option @code{tramp-backup-directory-alist} from the
|
||||
existing user option @code{backup-directory-alist}.
|
||||
|
||||
Then @value{tramp} backs up to a file name that is transformed with a
|
||||
prefix consisting of the DIRECTORY name. This file name prefixing
|
||||
|
@ -3335,10 +3351,12 @@ Example:
|
|||
The backup file name of
|
||||
@file{@trampfn{su,root@@localhost,/etc/secretfile}} would be
|
||||
@ifset unified
|
||||
@file{@trampfn{su,root@@localhost,~/.emacs.d/backups/!su:root@@localhost:!etc!secretfile~}}.
|
||||
@file{@trampfn{su,root@@localhost,~/.emacs.d/backups/@c
|
||||
!su:root@@localhost:!etc!secretfile~}}.
|
||||
@end ifset
|
||||
@ifset separate
|
||||
@file{@trampfn{su,root@@localhost,~/.emacs.d/backups/![su!root@@localhost]!etc!secretfile~}}.
|
||||
@file{@trampfn{su,root@@localhost,~/.emacs.d/backups/@c
|
||||
![su!root@@localhost]!etc!secretfile~}}.
|
||||
@end ifset
|
||||
|
||||
@vindex auto-save-file-name-transforms
|
||||
|
@ -3783,15 +3801,21 @@ ssh@value{postfixhop}you@@remotehost@value{postfix}/path @key{RET}}
|
|||
|
||||
Each involved method must be an inline method (@pxref{Inline methods}).
|
||||
|
||||
@value{tramp} adds the ad-hoc definitions on the fly to
|
||||
@code{tramp-default-proxies-alist} and is available for reuse during
|
||||
that Emacs session. Subsequent @value{tramp} connections to the same
|
||||
remote host can then use the shortcut form:
|
||||
@samp{@trampfn{ssh,you@@remotehost,/path}}.
|
||||
@value{tramp} adds the ad-hoc definitions as an ephemeral record to
|
||||
@code{tramp-default-proxies-alist}, which are available for reuse
|
||||
during that Emacs session. Subsequent @value{tramp} connections to
|
||||
the same remote host can then use the abbreviated form
|
||||
@file{@trampfn{ssh,you@@remotehost,/path}}.
|
||||
|
||||
@anchor{tramp-show-ad-hoc-proxies}
|
||||
@defopt tramp-show-ad-hoc-proxies
|
||||
If this user option is non-@code{nil}, ad-hoc definitions are kept in
|
||||
remote file names instead of showing the shortcuts.
|
||||
remote file names instead of showing the abbreviations. This is
|
||||
useful if the ad-hoc proxy definition shall be used in further Emacs
|
||||
sessions, kept in configuration files of recentf and other packages.
|
||||
|
||||
A non-@code{nil} setting of this option has effect only if set before
|
||||
the connection is established.
|
||||
|
||||
@lisp
|
||||
(customize-set-variable 'tramp-show-ad-hoc-proxies t)
|
||||
|
@ -3802,10 +3826,18 @@ Ad-hoc definitions are removed from @code{tramp-default-proxies-alist}
|
|||
via the command @kbd{M-x tramp-cleanup-all-connections @key{RET}}
|
||||
(@pxref{Cleanup remote connections}).
|
||||
|
||||
@anchor{tramp-save-ad-hoc-proxies}
|
||||
@defopt tramp-save-ad-hoc-proxies
|
||||
For ad-hoc definitions to be saved automatically in
|
||||
@code{tramp-default-proxies-alist} for future Emacs sessions, set
|
||||
@code{tramp-save-ad-hoc-proxies} to non-@code{nil}.
|
||||
@code{tramp-save-ad-hoc-proxies} to non-@code{nil}. The resulting
|
||||
user option @code{tramp-default-proxies-alist} is saved in your
|
||||
@file{.emacs} file.
|
||||
|
||||
If you use saved configuration files with abbreviated ad-hoc proxy
|
||||
definitions on another host, for example by distribution of the
|
||||
@code{recentf-save-file}, you must distribute your @file{.emacs} file
|
||||
as well.
|
||||
|
||||
@lisp
|
||||
(customize-set-variable 'tramp-save-ad-hoc-proxies t)
|
||||
|
@ -4600,7 +4632,9 @@ It cannot be killed via @code{interrupt-process}.
|
|||
It does not report the remote terminal name via @code{process-tty-name}.
|
||||
|
||||
@item
|
||||
It does not set process property @code{remote-pid}.
|
||||
It does not set process property @code{remote-pid}. Consequently,
|
||||
signals cannot be sent to that remote process; they are sent to the
|
||||
local process instead, which establishes the connection.
|
||||
|
||||
@item
|
||||
It fails, when the command is too long. This can happen on
|
||||
|
@ -4622,6 +4656,15 @@ by the connection property @t{"direct-async-process"}. This is still
|
|||
supported but deprecated, and it will be removed in a future
|
||||
@value{tramp} version.
|
||||
|
||||
@strong{Note}: For the @option{ssh} and @option{scp} methods,
|
||||
@value{tramp} does not faithfully pass binary sequences on to the
|
||||
process. You can change this by changing the respective connection
|
||||
argument (@pxref{Predefined connection information}) via
|
||||
|
||||
@lisp
|
||||
(add-to-list 'tramp-connection-properties (list "/ssh:" "direct-async" t))
|
||||
@end lisp
|
||||
|
||||
|
||||
@node Cleanup remote connections
|
||||
@section Cleanup remote connections
|
||||
|
@ -5013,8 +5056,8 @@ An archive file name can be a remote file name, as in
|
|||
Since all file operations are mapped internally to @acronym{GVFS}
|
||||
operations, remote file names supported by @code{tramp-gvfs} perform
|
||||
better, because no local copy of the file archive must be downloaded
|
||||
first. For example, @samp{/sftp:user@@host:...} performs better than
|
||||
the similar @samp{/scp:user@@host:...}. See the constant
|
||||
first. For example, @samp{/sftp:user@@host:@dots{}} performs better
|
||||
than the similar @samp{/scp:user@@host:@dots{}}. See the constant
|
||||
@code{tramp-archive-all-gvfs-methods} for a complete list of
|
||||
@code{tramp-gvfs} supported method names.
|
||||
|
||||
|
@ -5138,6 +5181,17 @@ this stage. Also note that with a verbosity level of 6 or greater, the
|
|||
contents of files and directories will be included in the debug buffer.
|
||||
Passwords typed in @value{tramp} will never be included there.
|
||||
|
||||
If you find, that using @value{tramp} with @command{emacs -Q} doesn't
|
||||
cause any problem, you might check your init file for the suspicious
|
||||
configuration by bisecting it. That is, comment out about half of the
|
||||
init file, and check whether the problem still arises when calling
|
||||
@command{emacs}. If yes, comment out half of the still active code.
|
||||
Otherwise, comment out the active code, and uncomment the just
|
||||
commented code.
|
||||
|
||||
Call @command{emacs}, again. Reiterate, until you find the suspicious
|
||||
configuration.
|
||||
|
||||
|
||||
@node Frequently Asked Questions
|
||||
@chapter Frequently Asked Questions
|
||||
|
@ -5463,6 +5517,23 @@ nitrokey, or titankey.
|
|||
(residential) keys by @command{ssh-agent}. As workaround, you might
|
||||
disable @command{ssh-agent} for such keys.
|
||||
|
||||
|
||||
@item
|
||||
Does @value{tramp} support fingerprint readers?
|
||||
|
||||
Yes. A fingerprint reader can be used as an additional authentication
|
||||
method for @option{sudo}-based logins. @value{tramp} supports the
|
||||
required additional handshaking messages@footnote{It supports
|
||||
fingerprint readers driven by @command{fprintd}.}. If the fingerprint
|
||||
isn't recognized by the fingerprint reader in time, authentication
|
||||
falls back to requesting a password.
|
||||
|
||||
@vindex tramp-use-fingerprint
|
||||
If the user option @code{tramp-use-fingerprint} is @code{nil},
|
||||
@value{tramp} interrupts the fingerprint request, falling back to
|
||||
password authentication immediately.
|
||||
|
||||
|
||||
@item
|
||||
@value{tramp} does not connect to Samba or MS Windows hosts running
|
||||
SMB1 connection protocol
|
||||
|
@ -5646,6 +5717,7 @@ connection-local value.
|
|||
@end group
|
||||
@end lisp
|
||||
|
||||
@vindex XDG_DATA_HOME@r{, environment variable}
|
||||
If Emacs is configured to use the XDG conventions for the trash
|
||||
directory, remote files cannot be restored with the respective tools,
|
||||
because those conventions don't specify remote paths. Such files must
|
||||
|
@ -5895,18 +5967,30 @@ Thanks to @value{tramp} users for contributing to these recipes.
|
|||
|
||||
|
||||
@item
|
||||
Why saved multi-hop file names do not work in a new Emacs session?
|
||||
Why don't saved ad-hoc multi-hop file names work in a new Emacs session?
|
||||
|
||||
When saving ad-hoc multi-hop @value{tramp} file names (@pxref{Ad-hoc
|
||||
multi-hops}) via bookmarks, recent files, filecache, bbdb, or another
|
||||
package, use the full ad-hoc file name including all hops, like
|
||||
@file{@trampfn{ssh,bird@@bastion|ssh@value{postfixhop}@c
|
||||
news.my.domain,/opt/news/etc}}.
|
||||
By default, ad-hoc multi-hop file names are abbreviated after
|
||||
completing the initial connection. These abbreviated forms retain
|
||||
only the final hop, and so only the Emacs session that generated the
|
||||
abbreviated form can understand it. @xref{Ad-hoc multi-hops}.
|
||||
|
||||
Alternatively, when saving abbreviated multi-hop file names
|
||||
@file{@trampfn{ssh,news@@news.my.domain,/opt/news/etc}}, the user
|
||||
option @code{tramp-save-ad-hoc-proxies} must be set non-@code{nil}
|
||||
value.
|
||||
For example, after connecting to @file{@trampfn{ssh,bird@@bastion|@c
|
||||
ssh@value{postfixhop}news@@news.my.domain,/opt/news/etc}}, the file
|
||||
name becomes @file{@trampfn{ssh,news@@news.my.domain,/opt/news/etc}}.
|
||||
If the abbreviated form is saved in a bookmark, the recent files list,
|
||||
bbdb, or similar, a new Emacs session has no way to know that the
|
||||
connection must go through @samp{bird@@bastion} first.
|
||||
|
||||
There are two mechanisms to deal with this. The first is to customize
|
||||
@code{tramp-show-ad-hoc-proxies} to a non-@code{nil} value, which
|
||||
disables abbreviation. Then the fully-qualified ad-hoc multi-hop file
|
||||
name is the one that will be both displayed and saved.
|
||||
@xref{tramp-show-ad-hoc-proxies}.
|
||||
|
||||
Alternatively, you can customize @code{tramp-save-ad-hoc-proxies} to a
|
||||
non-@code{nil} value which means to save the information how an
|
||||
abbreviated multi-hop file name can be expanded.
|
||||
@xref{tramp-save-ad-hoc-proxies}.
|
||||
|
||||
|
||||
@item
|
||||
|
@ -5965,6 +6049,8 @@ $ export EDITOR=/path/to/emacsclient.sh
|
|||
@item
|
||||
How to determine whether a buffer is remote?
|
||||
|
||||
@findex file-remote-p
|
||||
@vindex default-directory
|
||||
The buffer-local variable @code{default-directory} tells this. If the
|
||||
form @code{(file-remote-p default-directory)} returns non-@code{nil},
|
||||
the buffer is remote. See the optional arguments of
|
||||
|
@ -6077,6 +6163,36 @@ as above in your @file{~/.emacs}:
|
|||
@end lisp
|
||||
|
||||
|
||||
@item
|
||||
I get an error @samp{unix_listener: path
|
||||
"/very/long/path/.cache/emacs/tramp.XXX" too long for Unix domain
|
||||
socket} when connecting via @option{ssh} to a remote host.
|
||||
|
||||
@vindex small-temporary-file-directory
|
||||
By default, @value{tramp} uses the directory @file{~/.cache/emacs/}
|
||||
for creation of OpenSSH Unix domain sockets. On GNU/Linux, domain
|
||||
sockets have a much lower maximum path length (currently 107
|
||||
characters) than normal files.
|
||||
|
||||
You can change this directory by setting the user option
|
||||
@code{small-temporary-file-directory} to another name, like
|
||||
|
||||
@lisp
|
||||
@group
|
||||
(unless small-temporary-file-directory
|
||||
(customize-set-variable
|
||||
'small-temporary-file-directory
|
||||
(format "/run/user/%d/emacs/" (user-uid)))
|
||||
(make-directory small-temporary-file-directory t))
|
||||
@end group
|
||||
@end lisp
|
||||
|
||||
@vindex XDG_RUNTIME_DIR@r{, environment variable}
|
||||
@t{"/run/user/UID"} is the value of the environment variable
|
||||
@env{XDG_RUNTIME_DIR}, which you can use instead via @code{(getenv
|
||||
"XDG_RUNTIME_DIR")}.
|
||||
|
||||
|
||||
@item
|
||||
How to ignore errors when changing file attributes?
|
||||
|
||||
|
@ -6209,6 +6325,7 @@ programs.
|
|||
* Temporary directory:: Where temporary files are kept.
|
||||
* Localname deconstruction:: Splitting a localname into its component parts.
|
||||
* External packages:: Integrating with external Lisp packages.
|
||||
* Extension packages:: Adding new methods to @value{tramp}.
|
||||
@end menu
|
||||
|
||||
|
||||
|
@ -6326,7 +6443,7 @@ root directory, it is most likely sufficient to make the
|
|||
@code{default-directory} of the process buffer as the root directory.
|
||||
|
||||
|
||||
@subsection Timers
|
||||
@subsection Timers, process filters, process sentinels, redisplay
|
||||
|
||||
@vindex remote-file-error
|
||||
Timers run asynchronously at any time when Emacs is waiting for
|
||||
|
@ -6345,6 +6462,133 @@ wrapping the timer function body as follows:
|
|||
@end group
|
||||
@end lisp
|
||||
|
||||
A similar problem could happen with process filters, process
|
||||
sentinels, and redisplay (updating the mode line).
|
||||
|
||||
|
||||
@node Extension packages
|
||||
@section Adding new methods to @value{tramp}
|
||||
|
||||
There are two ways to add new methods to @value{tramp}: writing a new
|
||||
backend including an own file name handler, or adding the new method,
|
||||
using the existing @code{tramp-sh-file-name-handler}. The former
|
||||
shall happen inside the @value{tramp} repository, and it isn't
|
||||
discussed here. The latter means usually a new ELPA package.
|
||||
@pxref{Customizing Methods} for some examples.
|
||||
|
||||
|
||||
@subsection Writing an own ELPA package
|
||||
|
||||
An external ELPA package @file{foo-tramp.el}, which intends to
|
||||
provide a new @value{tramp} method, say @option{foo}, must add this
|
||||
new method to the variable @code{tramp-methods}. This variable is an
|
||||
alist with elements @code{(@var{name} @var{param1} @var{param2}
|
||||
@dots{})}.
|
||||
|
||||
@var{name} is the method name, @t{"foo"} in this case.
|
||||
@var{param}@t{x} is a pair of the form @code{(@var{key} @var{value})}.
|
||||
See the docstring of variable @code{tramp-methods} for possible
|
||||
@var{key}s and @var{value}s. An example would be
|
||||
|
||||
@lisp
|
||||
@group
|
||||
(add-to-list
|
||||
'tramp-methods
|
||||
`("foo"
|
||||
(tramp-login-program ,foo-tramp-executable)
|
||||
(tramp-login-args (("exec") ("%h") ("--") ("su - %u")))
|
||||
(tramp-remote-shell "/bin/sh")
|
||||
(tramp-remote-shell-args ("-i" "-c"))))
|
||||
@end group
|
||||
@end lisp
|
||||
|
||||
@code{foo-tramp-executable} in this example would be a Lisp constant,
|
||||
which is the program name of @command{foo}.
|
||||
|
||||
Another initialization could tell @value{tramp} which are the default
|
||||
user and host name for method @option{foo}. This is done by calling
|
||||
@code{tramp-set-completion-function}:
|
||||
|
||||
@lisp
|
||||
@group
|
||||
(tramp-set-completion-function
|
||||
"foo"
|
||||
'((tramp-foo--completion-function @var{arg})))
|
||||
@end group
|
||||
@end lisp
|
||||
|
||||
@code{tramp-foo--completion-function} is a function, which returns
|
||||
completion candidates. @var{arg}, a string, is the argument for the
|
||||
completion function, for example a file name to read from.
|
||||
@pxref{Customizing Completion} for details.
|
||||
|
||||
Finally, it might also be helpful to define default user or host names
|
||||
for method @option{foo}, in case a remote file name leaves them empty.
|
||||
This can be performed by calling
|
||||
|
||||
@lisp
|
||||
@group
|
||||
(add-to-list 'tramp-default-user-alist '("foo" nil "root"))
|
||||
(add-to-list 'tramp-default-host-alist '("foo" nil "localhost"))
|
||||
@end group
|
||||
@end lisp
|
||||
|
||||
@pxref{Default User} and @ref{Default Host} explaining the user options
|
||||
@code{tramp-default-user-alist} and @code{tramp-default-host-alist}.
|
||||
|
||||
|
||||
@subsection Making a customized method optional
|
||||
|
||||
The settings of the previous subsection are global in the package
|
||||
@file{foo-tramp.el}, meaning they are activated when loading
|
||||
@code{foo-tramp}. Sometimes, it is desired to make these settings
|
||||
available without loading the whole package @code{foo-tramp}, but
|
||||
declaring the new method @option{foo} as optional method only. In
|
||||
this case, declare a function @code{tramp-enable-foo-method} which
|
||||
collects the initialization. This function must be auto loaded.
|
||||
|
||||
@lisp
|
||||
@group
|
||||
;;;###autoload
|
||||
(defun tramp-enable-foo-method ()
|
||||
(add-to-list 'tramp-methods '("foo" @dots{}))
|
||||
(tramp-set-completion-function "foo" @dots{})
|
||||
(add-to-list 'tramp-default-user-alist '("foo" @dots{}))
|
||||
(add-to-list 'tramp-default-host-alist '("foo" @dots{})))
|
||||
@end group
|
||||
@end lisp
|
||||
|
||||
Then, you can activate method @option{foo} by calling @kbd{M-x
|
||||
tramp-enable-method @key{RET} foo @key{RET}}. @pxref{Optional methods}.
|
||||
|
||||
|
||||
@subsection Activating a customized method without loading the package
|
||||
|
||||
If you want to make method @option{foo} known after loading
|
||||
@value{tramp}, without loading the package @file{foo-tramp.el}, you
|
||||
must autoload the implementation of function
|
||||
@code{tramp-enable-foo-method}. Add the following code in
|
||||
@file{foo-tramp.el}:
|
||||
|
||||
@lisp
|
||||
@group
|
||||
;;;###autoload
|
||||
(progn
|
||||
(defun tramp-enable-foo-method ()
|
||||
(add-to-list 'tramp-methods '("foo" @dots{}))
|
||||
(tramp-set-completion-function "foo" @dots{})
|
||||
(add-to-list 'tramp-default-user-alist '("foo" @dots{}))
|
||||
(add-to-list 'tramp-default-host-alist '("foo" @dots{}))))
|
||||
|
||||
;;;###autoload
|
||||
(with-eval-after-load 'tramp (tramp-enable-method "foo"))
|
||||
@end group
|
||||
@end lisp
|
||||
|
||||
The trick is to wrap the function definition of
|
||||
@code{tramp-enable-foo-method} with @code{progn} for the
|
||||
@code{;;;###autoload} cookie.
|
||||
|
||||
|
||||
@node Traces and Profiles
|
||||
@chapter How to Customize Traces
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
@c In the Tramp GIT, the version number and the bug report address
|
||||
@c are auto-frobbed from configure.ac.
|
||||
@set trampver 2.7.1.30.1
|
||||
@set trampver 2.7.3-pre
|
||||
@set trampurl https://www.gnu.org/software/tramp/
|
||||
@set tramp-bug-report-address tramp-devel@@gnu.org
|
||||
@set emacsver 27.1
|
||||
|
|
|
@ -201,15 +201,15 @@ It is used for TCP/IP devices."
|
|||
;;;###tramp-autoload
|
||||
(defsubst tramp-adb-file-name-p (vec-or-filename)
|
||||
"Check if it's a VEC-OR-FILENAME for ADB."
|
||||
(when-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename)))
|
||||
(string= (tramp-file-name-method vec) tramp-adb-method)))
|
||||
(and-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename))
|
||||
((string= (tramp-file-name-method vec) tramp-adb-method)))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defun tramp-adb-file-name-handler (operation &rest args)
|
||||
"Invoke the ADB handler for OPERATION.
|
||||
First arg specifies the OPERATION, second arg is a list of
|
||||
arguments to pass to the OPERATION."
|
||||
(if-let ((fn (assoc operation tramp-adb-file-name-handler-alist)))
|
||||
(if-let* ((fn (assoc operation tramp-adb-file-name-handler-alist)))
|
||||
(prog1 (save-match-data (apply (cdr fn) args))
|
||||
(setq tramp-debug-message-fnh-function (cdr fn)))
|
||||
(prog1 (tramp-run-real-handler operation args)
|
||||
|
@ -616,7 +616,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
|||
(tramp-shell-quote-argument l2))
|
||||
"Error copying %s to %s" filename newname))
|
||||
|
||||
(if-let ((tmpfile (file-local-copy filename)))
|
||||
(if-let* ((tmpfile (file-local-copy filename)))
|
||||
;; Remote filename.
|
||||
(condition-case err
|
||||
(rename-file tmpfile newname ok-if-already-exists)
|
||||
|
@ -998,7 +998,7 @@ error and non-nil on success."
|
|||
;; <https://android.stackexchange.com/questions/226638/how-to-use-multibyte-file-names-in-adb-shell/232379#232379>
|
||||
;; mksh uses UTF-8 internally, but is currently limited to the
|
||||
;; BMP (basic multilingua plane), which means U+0000 to
|
||||
;; U+FFFD. If you want to use SMP codepoints (U-00010000 to
|
||||
;; U+FFFD. If you want to use SMP codepoints (U-00010000 to
|
||||
;; U-0010FFFD) on the input line, you currently have to disable
|
||||
;; the UTF-8 mode (sorry).
|
||||
(tramp-adb-execute-adb-command vec "shell" command)
|
||||
|
@ -1125,6 +1125,11 @@ connection if a previous connection has died for some reason."
|
|||
tramp-adb-program args)))
|
||||
(prompt (md5 (concat (prin1-to-string process-environment)
|
||||
(current-time-string)))))
|
||||
|
||||
;; Set sentinel. Initialize variables.
|
||||
(set-process-sentinel p #'tramp-process-sentinel)
|
||||
(tramp-post-process-creation p vec)
|
||||
|
||||
;; Wait for initial prompt. On some devices, it needs
|
||||
;; an initial RET, in order to get it.
|
||||
(sleep-for 0.1)
|
||||
|
@ -1133,10 +1138,6 @@ connection if a previous connection has died for some reason."
|
|||
(unless (process-live-p p)
|
||||
(tramp-error vec 'file-error "Terminated!"))
|
||||
|
||||
;; Set sentinel. Initialize variables.
|
||||
(set-process-sentinel p #'tramp-process-sentinel)
|
||||
(tramp-post-process-creation p vec)
|
||||
|
||||
;; Set connection-local variables.
|
||||
(tramp-set-connection-local-variables vec)
|
||||
|
||||
|
|
|
@ -503,15 +503,15 @@ FUNCTION."
|
|||
;;;###tramp-autoload
|
||||
(defsubst tramp-androidsu-file-name-p (vec-or-filename)
|
||||
"Check whether VEC-OR-FILENAME is for the `androidsu' method."
|
||||
(when-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename)))
|
||||
(equal (tramp-file-name-method vec) tramp-androidsu-method)))
|
||||
(and-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename))
|
||||
((equal (tramp-file-name-method vec) tramp-androidsu-method)))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defun tramp-androidsu-file-name-handler (operation &rest args)
|
||||
"Invoke the `androidsu' handler for OPERATION.
|
||||
First arg specifies the OPERATION, second arg is a list of
|
||||
arguments to pass to the OPERATION."
|
||||
(if-let ((fn (assoc operation tramp-androidsu-file-name-handler-alist)))
|
||||
(if-let* ((fn (assoc operation tramp-androidsu-file-name-handler-alist)))
|
||||
(prog1 (save-match-data (apply (cdr fn) args))
|
||||
(setq tramp-debug-message-fnh-function (cdr fn)))
|
||||
(prog1 (tramp-run-real-handler operation args)
|
||||
|
|
|
@ -426,6 +426,7 @@ arguments to pass to the OPERATION."
|
|||
|
||||
;; File name conversions.
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defun tramp-archive-file-name-p (name)
|
||||
"Return t if NAME is a string with archive file name syntax."
|
||||
(and (stringp name)
|
||||
|
@ -581,6 +582,12 @@ offered."
|
|||
"Return NAME in GVFS syntax."
|
||||
(tramp-make-tramp-file-name (tramp-archive-dissect-file-name name)))
|
||||
|
||||
;; This is used in GNU ELPA package tramp-locproc.el.
|
||||
(defun tramp-archive-local-file-name (filename)
|
||||
"Return local mount name of FILENAME."
|
||||
(let ((tramp-methods (cons `(,tramp-archive-method) tramp-methods)))
|
||||
(tramp-gvfs-local-file-name (tramp-archive-gvfs-file-name filename))))
|
||||
|
||||
|
||||
;; File name primitives.
|
||||
|
||||
|
|
|
@ -68,10 +68,10 @@
|
|||
|
||||
;; Some properties are handled special:
|
||||
;;
|
||||
;; - "process-name", "process-buffer" and "first-password-request" are
|
||||
;; not saved in the file `tramp-persistency-file-name', although
|
||||
;; being connection properties related to a `tramp-file-name'
|
||||
;; structure.
|
||||
;; - "process-name", "process-buffer", "first-password-request" and
|
||||
;; "pw-spec" are not saved in the file
|
||||
;; `tramp-persistency-file-name', although being connection
|
||||
;; properties related to a `tramp-file-name' structure.
|
||||
;;
|
||||
;; - Reusable properties, which should not be saved, are kept in the
|
||||
;; process key retrieved by `tramp-get-process' (the main connection
|
||||
|
@ -97,8 +97,11 @@
|
|||
Every entry has the form (REGEXP PROPERTY VALUE). The regexp
|
||||
matches remote file names. It can be nil. PROPERTY is a string,
|
||||
and VALUE the corresponding value. They are used, if there is no
|
||||
matching entry for PROPERTY in `tramp-cache-data'. For more
|
||||
details see the info pages."
|
||||
matching entry for PROPERTY in `tramp-cache-data'.
|
||||
|
||||
PROPERTY can also be a string representing a parameter in
|
||||
`tramp-methods'. For more details see the Info node `(tramp) Predefined
|
||||
connection information'."
|
||||
:group 'tramp
|
||||
:version "24.4"
|
||||
:type '(repeat (list (choice :tag "File Name regexp" regexp (const nil))
|
||||
|
@ -234,8 +237,8 @@ Return VALUE."
|
|||
"Remove some properties of FILE's upper directory."
|
||||
(when (file-name-absolute-p file)
|
||||
;; `file-name-directory' can return nil, for example for "~".
|
||||
(when-let ((file (file-name-directory file))
|
||||
(file (directory-file-name file)))
|
||||
(when-let* ((file (file-name-directory file))
|
||||
(file (directory-file-name file)))
|
||||
(setq key (tramp-file-name-unify key file))
|
||||
(unless (eq key tramp-cache-undefined)
|
||||
(dolist (property (hash-table-keys (tramp-get-hash-table key)))
|
||||
|
@ -388,7 +391,8 @@ the connection, return DEFAULT."
|
|||
(not (and (processp key) (not (process-live-p key)))))
|
||||
(setq value cached
|
||||
cache-used t))
|
||||
(tramp-message key 7 "%s %s; cache used: %s" property value cache-used)
|
||||
(unless (eq key tramp-cache-version)
|
||||
(tramp-message key 7 "%s %s; cache used: %s" property value cache-used))
|
||||
value))
|
||||
|
||||
;;;###tramp-autoload
|
||||
|
@ -401,11 +405,12 @@ is `tramp-cache-undefined', nothing is set.
|
|||
PROPERTY is set persistent when KEY is a `tramp-file-name' structure.
|
||||
Return VALUE."
|
||||
(setq key (tramp-file-name-unify key))
|
||||
(when-let ((hash (tramp-get-hash-table key)))
|
||||
(when-let* ((hash (tramp-get-hash-table key)))
|
||||
(puthash property value hash))
|
||||
(setq tramp-cache-data-changed
|
||||
(or tramp-cache-data-changed (tramp-file-name-p key)))
|
||||
(tramp-message key 7 "%s %s" property value)
|
||||
(unless (eq key tramp-cache-version)
|
||||
(tramp-message key 7 "%s %s" property value))
|
||||
value)
|
||||
|
||||
;;;###tramp-autoload
|
||||
|
@ -425,7 +430,7 @@ KEY identifies the connection, it is either a process or a
|
|||
used to cache connection properties of the local machine.
|
||||
PROPERTY is set persistent when KEY is a `tramp-file-name' structure."
|
||||
(setq key (tramp-file-name-unify key))
|
||||
(when-let ((hash (tramp-get-hash-table key)))
|
||||
(when-let* ((hash (tramp-get-hash-table key)))
|
||||
(remhash property hash))
|
||||
(setq tramp-cache-data-changed
|
||||
(or tramp-cache-data-changed (tramp-file-name-p key)))
|
||||
|
@ -440,7 +445,7 @@ used to cache connection properties of the local machine."
|
|||
(setq key (tramp-file-name-unify key))
|
||||
(tramp-message
|
||||
key 7 "%s %s" key
|
||||
(when-let ((hash (gethash key tramp-cache-data)))
|
||||
(when-let* ((hash (gethash key tramp-cache-data)))
|
||||
(hash-table-keys hash)))
|
||||
(setq tramp-cache-data-changed
|
||||
(or tramp-cache-data-changed (tramp-file-name-p key)))
|
||||
|
@ -468,8 +473,10 @@ used to cache connection properties of the local machine."
|
|||
(hash (tramp-get-hash-table key))
|
||||
(cached (and (hash-table-p hash)
|
||||
(gethash ,property hash tramp-cache-undefined))))
|
||||
(tramp-message key 7 "Saved %s %s" property cached)
|
||||
(unwind-protect (progn ,@body)
|
||||
;; Reset PROPERTY. Recompute hash, it could have been flushed.
|
||||
(tramp-message key 7 "Restored %s %s" property cached)
|
||||
(setq hash (tramp-get-hash-table key))
|
||||
(if (not (eq cached tramp-cache-undefined))
|
||||
(puthash ,property cached hash)
|
||||
|
@ -486,9 +493,13 @@ PROPERTIES is a list of file properties (strings)."
|
|||
(mapcar
|
||||
(lambda (property)
|
||||
(cons property (gethash property hash tramp-cache-undefined)))
|
||||
,properties)))
|
||||
,properties))
|
||||
;; Avoid superfluous debug buffers during host name completion.
|
||||
(tramp-verbose (if minibuffer-completing-file-name 0 tramp-verbose)))
|
||||
(tramp-message key 7 "Saved %s" values)
|
||||
(unwind-protect (progn ,@body)
|
||||
;; Reset PROPERTIES. Recompute hash, it could have been flushed.
|
||||
(tramp-message key 7 "Restored %s" values)
|
||||
(setq hash (tramp-get-hash-table key))
|
||||
(dolist (value values)
|
||||
(if (not (eq (cdr value) tramp-cache-undefined))
|
||||
|
@ -579,7 +590,8 @@ PROPERTIES is a list of file properties (strings)."
|
|||
(progn
|
||||
(remhash "process-name" value)
|
||||
(remhash "process-buffer" value)
|
||||
(remhash "first-password-request" value))
|
||||
(remhash "first-password-request" value)
|
||||
(remhash "pw-spec" value))
|
||||
(remhash key cache)))
|
||||
cache)
|
||||
;; Dump it.
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
(defvar mm-7bit-chars)
|
||||
(defvar reporter-eval-buffer)
|
||||
(defvar reporter-prompt-for-summary-p)
|
||||
(defvar tramp-repository-branch)
|
||||
(defvar tramp-repository-version)
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defun tramp-change-syntax (&optional syntax)
|
||||
|
@ -609,7 +611,9 @@ If the buffer runs `dired', the buffer is reverted."
|
|||
(interactive)
|
||||
(cond
|
||||
((buffer-file-name)
|
||||
(find-alternate-file (tramp-file-name-with-sudo (buffer-file-name))))
|
||||
(let ((pos (point)))
|
||||
(find-alternate-file (tramp-file-name-with-sudo (buffer-file-name)))
|
||||
(goto-char pos)))
|
||||
((tramp-dired-buffer-p)
|
||||
(dired-unadvertise (expand-file-name default-directory))
|
||||
(setq default-directory (tramp-file-name-with-sudo default-directory)
|
||||
|
@ -644,7 +648,7 @@ This is needed if there are compatibility problems."
|
|||
;; (declare (completion tramp-recompile-elpa-command-completion-p))
|
||||
(interactive)
|
||||
;; We expect just one Tramp package is installed.
|
||||
(when-let
|
||||
(when-let*
|
||||
((dir (tramp-compat-funcall
|
||||
'package-desc-dir
|
||||
(car (alist-get 'tramp (bound-and-true-p package-alist))))))
|
||||
|
@ -741,8 +745,8 @@ buffer in your bug report.
|
|||
|
||||
(defun tramp-reporter-dump-variable (varsym mailbuf)
|
||||
"Pretty-print the value of the variable in symbol VARSYM."
|
||||
(when-let ((reporter-eval-buffer reporter-eval-buffer)
|
||||
(val (buffer-local-value varsym reporter-eval-buffer)))
|
||||
(when-let* ((reporter-eval-buffer reporter-eval-buffer)
|
||||
(val (buffer-local-value varsym reporter-eval-buffer)))
|
||||
|
||||
(if (hash-table-p val)
|
||||
;; Pretty print the cache.
|
||||
|
|
|
@ -76,11 +76,10 @@
|
|||
;; an infloop. We try to follow the XDG specification, for security reasons.
|
||||
(defconst tramp-compat-temporary-file-directory
|
||||
(file-name-as-directory
|
||||
(if-let ((xdg (xdg-cache-home))
|
||||
((file-directory-p xdg))
|
||||
((file-writable-p xdg)))
|
||||
;; We can use `file-name-concat' starting with Emacs 28.1.
|
||||
(prog1 (setq xdg (concat (file-name-as-directory xdg) "emacs"))
|
||||
(if-let* ((xdg (xdg-cache-home))
|
||||
((file-directory-p xdg))
|
||||
((file-writable-p xdg)))
|
||||
(prog1 (setq xdg (expand-file-name "emacs" xdg))
|
||||
(make-directory xdg t))
|
||||
(eval (car (get 'temporary-file-directory 'standard-value)) t)))
|
||||
"The default value of `temporary-file-directory' for Tramp.")
|
||||
|
@ -368,7 +367,7 @@ value is the default binding of the variable."
|
|||
(if (not criteria)
|
||||
,variable
|
||||
(hack-connection-local-variables criteria)
|
||||
(if-let ((result (assq ',variable connection-local-variables-alist)))
|
||||
(if-let* ((result (assq ',variable connection-local-variables-alist)))
|
||||
(cdr result)
|
||||
,variable)))))
|
||||
|
||||
|
|
|
@ -279,19 +279,19 @@ or `tramp-podmancp-method'.
|
|||
This function is used by `tramp-set-completion-function', please
|
||||
see its function help for a description of the format."
|
||||
(tramp-skeleton-completion-function method
|
||||
(when-let ((raw-list
|
||||
(shell-command-to-string
|
||||
(concat program " ps --format '{{.ID}}\t{{.Names}}'")))
|
||||
(lines (split-string raw-list "\n" 'omit))
|
||||
(names
|
||||
(tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (group (1+ nonl))
|
||||
"\t" (? (group (1+ nonl))) eol)
|
||||
line)
|
||||
(or (match-string 2 line) (match-string 1 line))))
|
||||
lines)))
|
||||
(when-let* ((raw-list
|
||||
(shell-command-to-string
|
||||
(concat program " ps --format '{{.ID}}\t{{.Names}}'")))
|
||||
(lines (split-string raw-list "\n" 'omit))
|
||||
(names
|
||||
(tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (group (1+ nonl))
|
||||
"\t" (? (group (1+ nonl))) eol)
|
||||
line)
|
||||
(or (match-string 2 line) (match-string 1 line))))
|
||||
lines)))
|
||||
(mapcar (lambda (name) (list nil name)) names))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
|
@ -301,19 +301,19 @@ see its function help for a description of the format."
|
|||
This function is used by `tramp-set-completion-function', please
|
||||
see its function help for a description of the format."
|
||||
(tramp-skeleton-completion-function method
|
||||
(when-let ((raw-list
|
||||
(shell-command-to-string
|
||||
(concat
|
||||
program " "
|
||||
(tramp-kubernetes--context-namespace vec)
|
||||
" get pods --no-headers"
|
||||
;; We separate pods by "|". Inside a pod, its name
|
||||
;; is separated from the containers by ":".
|
||||
;; Containers are separated by ",".
|
||||
" -o jsonpath='{range .items[*]}{\"|\"}{.metadata.name}"
|
||||
"{\":\"}{range .spec.containers[*]}{.name}{\",\"}"
|
||||
"{end}{end}'")))
|
||||
(lines (split-string raw-list "|" 'omit)))
|
||||
(when-let* ((raw-list
|
||||
(shell-command-to-string
|
||||
(concat
|
||||
program " "
|
||||
(tramp-kubernetes--context-namespace vec)
|
||||
" get pods --no-headers"
|
||||
;; We separate pods by "|". Inside a pod, its name
|
||||
;; is separated from the containers by ":".
|
||||
;; Containers are separated by ",".
|
||||
" -o jsonpath='{range .items[*]}{\"|\"}{.metadata.name}"
|
||||
"{\":\"}{range .spec.containers[*]}{.name}{\",\"}"
|
||||
"{end}{end}'")))
|
||||
(lines (split-string raw-list "|" 'omit)))
|
||||
(let (names)
|
||||
(dolist (line lines)
|
||||
(setq line (split-string line ":" 'omit))
|
||||
|
@ -382,7 +382,7 @@ Obey `tramp-kubernetes-context'"
|
|||
|
||||
(defun tramp-kubernetes--current-context-data (vec)
|
||||
"Return Kubernetes current context data as JSON string."
|
||||
(when-let ((current-context (tramp-kubernetes--current-context vec)))
|
||||
(when-let* ((current-context (tramp-kubernetes--current-context vec)))
|
||||
(tramp-skeleton-kubernetes-vector vec
|
||||
(with-temp-buffer
|
||||
(when (zerop
|
||||
|
@ -398,7 +398,7 @@ Obey `tramp-kubernetes-context'"
|
|||
"The kubectl options for context and namespace as string."
|
||||
(mapconcat
|
||||
#'identity
|
||||
`(,(when-let ((context (tramp-kubernetes--current-context vec)))
|
||||
`(,(when-let* ((context (tramp-kubernetes--current-context vec)))
|
||||
(format "--context=%s" context))
|
||||
,(when tramp-kubernetes-namespace
|
||||
(format "--namespace=%s" tramp-kubernetes-namespace)))
|
||||
|
@ -411,18 +411,18 @@ Obey `tramp-kubernetes-context'"
|
|||
This function is used by `tramp-set-completion-function', please
|
||||
see its function help for a description of the format."
|
||||
(tramp-skeleton-completion-function method
|
||||
(when-let ((raw-list (shell-command-to-string (concat program " list -c")))
|
||||
;; Ignore header line.
|
||||
(lines (cdr (split-string raw-list "\n" 'omit)))
|
||||
;; We do not show container IDs.
|
||||
(names (tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (1+ (not space))
|
||||
(1+ space) (group (1+ (not space))) space)
|
||||
line)
|
||||
(match-string 1 line)))
|
||||
lines)))
|
||||
(when-let* ((raw-list (shell-command-to-string (concat program " list -c")))
|
||||
;; Ignore header line.
|
||||
(lines (cdr (split-string raw-list "\n" 'omit)))
|
||||
;; We do not show container IDs.
|
||||
(names (tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (1+ (not space))
|
||||
(1+ space) (group (1+ (not space))) space)
|
||||
line)
|
||||
(match-string 1 line)))
|
||||
lines)))
|
||||
(mapcar (lambda (name) (list nil name)) names))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
|
@ -432,19 +432,19 @@ see its function help for a description of the format."
|
|||
This function is used by `tramp-set-completion-function', please
|
||||
see its function help for a description of the format."
|
||||
(tramp-skeleton-completion-function method
|
||||
(when-let ((raw-list (shell-command-to-string (concat program " list")))
|
||||
;; Ignore header line.
|
||||
(lines (cdr (split-string raw-list "\n" 'omit)))
|
||||
;; We do not show container IDs.
|
||||
(names (tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (1+ (not space))
|
||||
(1+ space) "|" (1+ space)
|
||||
(group (1+ (not space))) space)
|
||||
line)
|
||||
(match-string 1 line)))
|
||||
lines)))
|
||||
(when-let* ((raw-list (shell-command-to-string (concat program " list")))
|
||||
;; Ignore header line.
|
||||
(lines (cdr (split-string raw-list "\n" 'omit)))
|
||||
;; We do not show container IDs.
|
||||
(names (tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (1+ (not space))
|
||||
(1+ space) "|" (1+ space)
|
||||
(group (1+ (not space))) space)
|
||||
line)
|
||||
(match-string 1 line)))
|
||||
lines)))
|
||||
(mapcar (lambda (name) (list nil name)) names))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
|
@ -456,19 +456,19 @@ ID, instance IDs.
|
|||
This function is used by `tramp-set-completion-function', please
|
||||
see its function help for a description of the format."
|
||||
(tramp-skeleton-completion-function method
|
||||
(when-let ((raw-list
|
||||
(shell-command-to-string
|
||||
;; Ignore header line.
|
||||
(concat program " ps --columns=instance,application | cat -")))
|
||||
(lines (split-string raw-list "\n" 'omit))
|
||||
(names (tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (* space) (group (+ (not space)))
|
||||
(? (+ space) (group (+ (not space)))) eol)
|
||||
line)
|
||||
(or (match-string 2 line) (match-string 1 line))))
|
||||
lines)))
|
||||
(when-let* ((raw-list
|
||||
(shell-command-to-string
|
||||
;; Ignore header line.
|
||||
(concat program " ps --columns=instance,application | cat -")))
|
||||
(lines (split-string raw-list "\n" 'omit))
|
||||
(names (tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (* space) (group (+ (not space)))
|
||||
(? (+ space) (group (+ (not space)))) eol)
|
||||
line)
|
||||
(or (match-string 2 line) (match-string 1 line))))
|
||||
lines)))
|
||||
(mapcar (lambda (name) (list nil name)) names))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
|
@ -478,19 +478,19 @@ see its function help for a description of the format."
|
|||
This function is used by `tramp-set-completion-function', please
|
||||
see its function help for a description of the format."
|
||||
(tramp-skeleton-completion-function method
|
||||
(when-let ((raw-list
|
||||
(shell-command-to-string (concat program " instance list")))
|
||||
;; Ignore header line.
|
||||
(lines (cdr (split-string raw-list "\n" 'omit)))
|
||||
(names (tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (group (1+ (not space)))
|
||||
(1+ space) (1+ (not space))
|
||||
(1+ space) (1+ (not space)))
|
||||
line)
|
||||
(match-string 1 line)))
|
||||
lines)))
|
||||
(when-let* ((raw-list
|
||||
(shell-command-to-string (concat program " instance list")))
|
||||
;; Ignore header line.
|
||||
(lines (cdr (split-string raw-list "\n" 'omit)))
|
||||
(names (tramp-compat-seq-keep
|
||||
(lambda (line)
|
||||
(when (string-match
|
||||
(rx bol (group (1+ (not space)))
|
||||
(1+ space) (1+ (not space))
|
||||
(1+ space) (1+ (not space)))
|
||||
line)
|
||||
(match-string 1 line)))
|
||||
lines)))
|
||||
(mapcar (lambda (name) (list nil name)) names))))
|
||||
|
||||
(defun tramp-nspawn--completion-function (method)
|
||||
|
@ -499,13 +499,13 @@ see its function help for a description of the format."
|
|||
This function is used by `tramp-set-completion-function', please
|
||||
see its function help for a description of the format."
|
||||
(tramp-skeleton-completion-function method
|
||||
(when-let ((raw-list
|
||||
(shell-command-to-string (concat program " list --all -q")))
|
||||
;; Ignore header line.
|
||||
(lines (cdr (split-string raw-list "\n")))
|
||||
(first-words (mapcar (lambda (line) (car (split-string line)))
|
||||
lines))
|
||||
(machines (seq-take-while (lambda (name) name) first-words)))
|
||||
(when-let* ((raw-list
|
||||
(shell-command-to-string (concat program " list --all -q")))
|
||||
;; Ignore header line.
|
||||
(lines (cdr (split-string raw-list "\n")))
|
||||
(first-words
|
||||
(mapcar (lambda (line) (car (split-string line))) lines))
|
||||
(machines (seq-take-while (lambda (name) name) first-words)))
|
||||
(mapcar (lambda (m) (list nil m)) machines))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
|
|
|
@ -277,10 +277,10 @@ arguments to pass to the OPERATION."
|
|||
"Invoke the encrypted remote file related OPERATION.
|
||||
First arg specifies the OPERATION, second arg is a list of
|
||||
arguments to pass to the OPERATION."
|
||||
(if-let ((filename
|
||||
(apply #'tramp-crypt-file-name-for-operation operation args))
|
||||
(fn (and (tramp-crypt-file-name-p filename)
|
||||
(assoc operation tramp-crypt-file-name-handler-alist))))
|
||||
(if-let* ((filename
|
||||
(apply #'tramp-crypt-file-name-for-operation operation args))
|
||||
((tramp-crypt-file-name-p filename))
|
||||
(fn (assoc operation tramp-crypt-file-name-handler-alist)))
|
||||
(prog1 (save-match-data (apply (cdr fn) args))
|
||||
(setq tramp-debug-message-fnh-function (cdr fn)))
|
||||
(prog1 (tramp-crypt-run-real-handler operation args)
|
||||
|
@ -425,11 +425,11 @@ ARGS are the arguments. It returns t if ran successful, and nil otherwise."
|
|||
"Return encrypted / decrypted NAME if NAME belongs to an encrypted directory.
|
||||
OP must be `encrypt' or `decrypt'. Raise an error if this fails.
|
||||
Otherwise, return NAME."
|
||||
(if-let ((tramp-crypt-enabled t)
|
||||
(dir (tramp-crypt-file-name-p name))
|
||||
;; It must be absolute for the cache.
|
||||
(localname (substring name (1- (length dir))))
|
||||
(crypt-vec (tramp-crypt-dissect-file-name dir)))
|
||||
(if-let* ((tramp-crypt-enabled t)
|
||||
(dir (tramp-crypt-file-name-p name))
|
||||
;; It must be absolute for the cache.
|
||||
(localname (substring name (1- (length dir))))
|
||||
(crypt-vec (tramp-crypt-dissect-file-name dir)))
|
||||
;; Preserve trailing "/".
|
||||
(funcall
|
||||
(if (directory-name-p name) #'file-name-as-directory #'identity)
|
||||
|
@ -465,9 +465,9 @@ Otherwise, return NAME."
|
|||
Both files must be local files. OP must be `encrypt' or `decrypt'.
|
||||
If OP is `decrypt', the basename of INFILE must be an encrypted file name.
|
||||
Raise an error if this fails."
|
||||
(when-let ((tramp-crypt-enabled t)
|
||||
(dir (tramp-crypt-file-name-p root))
|
||||
(crypt-vec (tramp-crypt-dissect-file-name dir)))
|
||||
(when-let* ((tramp-crypt-enabled t)
|
||||
(dir (tramp-crypt-file-name-p root))
|
||||
(crypt-vec (tramp-crypt-dissect-file-name dir)))
|
||||
(let ((coding-system-for-read
|
||||
(if (eq op 'decrypt) 'binary coding-system-for-read))
|
||||
(coding-system-for-write
|
||||
|
@ -547,7 +547,7 @@ The structure consists of the `tramp-crypt-method' method, the
|
|||
local user name, the hexlified directory NAME as host, and the
|
||||
localname."
|
||||
(save-match-data
|
||||
(if-let ((dir (tramp-crypt-file-name-p name)))
|
||||
(if-let* ((dir (tramp-crypt-file-name-p name)))
|
||||
(make-tramp-file-name
|
||||
:method tramp-crypt-method :user (user-login-name)
|
||||
:host (url-hexify-string dir))
|
||||
|
|
|
@ -186,8 +186,8 @@ pass to the OPERATION."
|
|||
;;;###tramp-autoload
|
||||
(defsubst tramp-ftp-file-name-p (vec-or-filename)
|
||||
"Check if it's a VEC-OR-FILENAME that should be forwarded to Ange-FTP."
|
||||
(when-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename)))
|
||||
(string= (tramp-file-name-method vec) tramp-ftp-method)))
|
||||
(and-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename))
|
||||
((string= (tramp-file-name-method vec) tramp-ftp-method)))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
(tramp--with-startup
|
||||
|
|
|
@ -129,8 +129,8 @@
|
|||
|
||||
(defun tramp-fuse-mount-spec (vec)
|
||||
"Return local mount spec of VEC."
|
||||
(if-let ((host (tramp-file-name-host vec))
|
||||
(user (tramp-file-name-user vec)))
|
||||
(if-let* ((host (tramp-file-name-host vec))
|
||||
(user (tramp-file-name-user vec)))
|
||||
(format "%s@%s:/" user host)
|
||||
(format "%s:/" host)))
|
||||
|
||||
|
|
|
@ -879,9 +879,9 @@ Operations not mentioned here will be handled by the default Emacs primitives.")
|
|||
;;;###tramp-autoload
|
||||
(defsubst tramp-gvfs-file-name-p (vec-or-filename)
|
||||
"Check if it's a VEC-OR-FILENAME handled by the GVFS daemon."
|
||||
(when-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename)))
|
||||
(let ((method (tramp-file-name-method vec)))
|
||||
(and (stringp method) (member method tramp-gvfs-methods)))))
|
||||
(and-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename))
|
||||
(method (tramp-file-name-method vec))
|
||||
((member method tramp-gvfs-methods)))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defun tramp-gvfs-file-name-handler (operation &rest args)
|
||||
|
@ -891,11 +891,11 @@ arguments to pass to the OPERATION."
|
|||
;; `file-remote-p' must not return an error. (Bug#68976)
|
||||
(unless (or tramp-gvfs-enabled (eq operation 'file-remote-p))
|
||||
(tramp-user-error nil "Package `tramp-gvfs' not supported"))
|
||||
(if-let ((filename (apply #'tramp-file-name-for-operation operation args))
|
||||
(tramp-gvfs-dbus-event-vector
|
||||
(and (tramp-tramp-file-p filename)
|
||||
(tramp-dissect-file-name filename)))
|
||||
(fn (assoc operation tramp-gvfs-file-name-handler-alist)))
|
||||
(if-let* ((filename (apply #'tramp-file-name-for-operation operation args))
|
||||
(tramp-gvfs-dbus-event-vector
|
||||
(and (tramp-tramp-file-p filename)
|
||||
(tramp-dissect-file-name filename)))
|
||||
(fn (assoc operation tramp-gvfs-file-name-handler-alist)))
|
||||
(prog1 (save-match-data (apply (cdr fn) args))
|
||||
(setq tramp-debug-message-fnh-function (cdr fn)))
|
||||
(prog1 (tramp-run-real-handler operation args)
|
||||
|
@ -928,9 +928,9 @@ arguments to pass to the OPERATION."
|
|||
"Like `dbus-byte-array-to-string' but remove trailing \\0 if exists.
|
||||
Return nil for null BYTE-ARRAY."
|
||||
;; The byte array could be a variant. Take care.
|
||||
(when-let ((byte-array
|
||||
(if (and (consp byte-array) (atom (car byte-array)))
|
||||
byte-array (car byte-array))))
|
||||
(when-let* ((byte-array
|
||||
(if (and (consp byte-array) (atom (car byte-array)))
|
||||
byte-array (car byte-array))))
|
||||
(dbus-byte-array-to-string
|
||||
(if (and (consp byte-array) (zerop (car (last byte-array))))
|
||||
(butlast byte-array) byte-array))))
|
||||
|
@ -1042,105 +1042,113 @@ file names."
|
|||
(unless (memq op '(copy rename))
|
||||
(error "Unknown operation `%s', must be `copy' or `rename'" op))
|
||||
|
||||
(setq filename (file-truename filename))
|
||||
;; We cannot use `file-truename', this would fail for symlinks with
|
||||
;; non-existing target.
|
||||
(setq filename (expand-file-name filename))
|
||||
(if (file-directory-p filename)
|
||||
(progn
|
||||
(copy-directory filename newname keep-date t)
|
||||
(when (eq op 'rename) (delete-directory filename 'recursive)))
|
||||
(if (file-symlink-p filename)
|
||||
(progn
|
||||
(make-symbolic-link
|
||||
(file-symlink-p filename) newname ok-if-already-exists)
|
||||
(when (eq op 'rename) (delete-file filename)))
|
||||
|
||||
(let ((t1 (tramp-tramp-file-p filename))
|
||||
(t2 (tramp-tramp-file-p newname))
|
||||
(equal-remote (tramp-equal-remote filename newname))
|
||||
(volatile
|
||||
(and (eq op 'rename) (tramp-gvfs-file-name-p filename)
|
||||
(equal
|
||||
(cdr
|
||||
(assoc
|
||||
"standard::is-volatile"
|
||||
(tramp-gvfs-get-file-attributes filename)))
|
||||
"TRUE")))
|
||||
;; "gvfs-rename" is not trustworthy.
|
||||
(gvfs-operation (if (eq op 'copy) "gvfs-copy" "gvfs-move"))
|
||||
(msg-operation (if (eq op 'copy) "Copying" "Renaming")))
|
||||
(let ((t1 (tramp-tramp-file-p filename))
|
||||
(t2 (tramp-tramp-file-p newname))
|
||||
(equal-remote (tramp-equal-remote filename newname))
|
||||
(volatile
|
||||
(and (eq op 'rename) (tramp-gvfs-file-name-p filename)
|
||||
(equal
|
||||
(cdr
|
||||
(assoc
|
||||
"standard::is-volatile"
|
||||
(tramp-gvfs-get-file-attributes filename)))
|
||||
"TRUE")))
|
||||
;; "gvfs-rename" is not trustworthy.
|
||||
(gvfs-operation (if (eq op 'copy) "gvfs-copy" "gvfs-move"))
|
||||
(msg-operation (if (eq op 'copy) "Copying" "Renaming")))
|
||||
|
||||
(with-parsed-tramp-file-name (if t1 filename newname) nil
|
||||
(tramp-barf-if-file-missing v filename
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
(when (file-regular-p newname)
|
||||
(delete-file newname))
|
||||
(with-parsed-tramp-file-name (if t1 filename newname) nil
|
||||
(tramp-barf-if-file-missing v filename
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
(when (file-regular-p newname)
|
||||
(delete-file newname))
|
||||
|
||||
(cond
|
||||
;; We cannot rename volatile files, as used by Google-drive.
|
||||
((and (not equal-remote) volatile)
|
||||
(prog1 (copy-file
|
||||
filename newname ok-if-already-exists keep-date
|
||||
preserve-uid-gid preserve-extended-attributes)
|
||||
(delete-file filename)))
|
||||
(cond
|
||||
;; We cannot rename volatile files, as used by Google-drive.
|
||||
((and (not equal-remote) volatile)
|
||||
(prog1 (copy-file
|
||||
filename newname ok-if-already-exists keep-date
|
||||
preserve-uid-gid preserve-extended-attributes)
|
||||
(delete-file filename)))
|
||||
|
||||
;; We cannot copy or rename directly.
|
||||
((or (and equal-remote
|
||||
(tramp-get-connection-property v "direct-copy-failed"))
|
||||
(and t1 (not (tramp-gvfs-file-name-p filename)))
|
||||
(and t2 (not (tramp-gvfs-file-name-p newname))))
|
||||
(let ((tmpfile (tramp-compat-make-temp-file filename)))
|
||||
(if (eq op 'copy)
|
||||
(copy-file
|
||||
filename tmpfile t keep-date preserve-uid-gid
|
||||
preserve-extended-attributes)
|
||||
(rename-file filename tmpfile t))
|
||||
(rename-file tmpfile newname ok-if-already-exists)))
|
||||
;; We cannot copy or rename directly.
|
||||
((or (and equal-remote
|
||||
(tramp-get-connection-property v "direct-copy-failed"))
|
||||
(and t1 (not (tramp-gvfs-file-name-p filename)))
|
||||
(and t2 (not (tramp-gvfs-file-name-p newname))))
|
||||
(let ((tmpfile (tramp-compat-make-temp-file filename)))
|
||||
(if (eq op 'copy)
|
||||
(copy-file
|
||||
filename tmpfile t keep-date preserve-uid-gid
|
||||
preserve-extended-attributes)
|
||||
(rename-file filename tmpfile t))
|
||||
(rename-file tmpfile newname ok-if-already-exists)))
|
||||
|
||||
;; Direct action.
|
||||
(t (with-tramp-progress-reporter
|
||||
v 0 (format "%s %s to %s" msg-operation filename newname)
|
||||
(unless
|
||||
(and (apply
|
||||
#'tramp-gvfs-send-command v gvfs-operation
|
||||
(append
|
||||
(and (eq op 'copy) (or keep-date preserve-uid-gid)
|
||||
'("--preserve"))
|
||||
(list
|
||||
(tramp-gvfs-url-file-name filename)
|
||||
(tramp-gvfs-url-file-name newname))))
|
||||
;; Some backends do not return a proper error
|
||||
;; code in case of direct copy/move. Apply
|
||||
;; sanity checks.
|
||||
(or (not equal-remote)
|
||||
(and
|
||||
(tramp-gvfs-info newname)
|
||||
(or (eq op 'copy)
|
||||
(not (tramp-gvfs-info filename))))))
|
||||
;; Direct action.
|
||||
(t (with-tramp-progress-reporter
|
||||
v 0 (format "%s %s to %s" msg-operation filename newname)
|
||||
(unless
|
||||
(and (apply
|
||||
#'tramp-gvfs-send-command v gvfs-operation
|
||||
(append
|
||||
(and (eq op 'copy) (or keep-date preserve-uid-gid)
|
||||
'("--preserve"))
|
||||
(list
|
||||
(tramp-gvfs-url-file-name filename)
|
||||
(tramp-gvfs-url-file-name newname))))
|
||||
;; Some backends do not return a proper
|
||||
;; error code in case of direct copy/move.
|
||||
;; Apply sanity checks.
|
||||
(or (not equal-remote)
|
||||
(and
|
||||
(tramp-gvfs-info newname)
|
||||
(or (eq op 'copy)
|
||||
(not (tramp-gvfs-info filename))))))
|
||||
|
||||
(if (or (not equal-remote)
|
||||
(and equal-remote
|
||||
(tramp-get-connection-property
|
||||
v "direct-copy-failed")))
|
||||
;; Propagate the error.
|
||||
(with-current-buffer (tramp-get-connection-buffer v)
|
||||
(goto-char (point-min))
|
||||
(tramp-error-with-buffer
|
||||
nil v 'file-error
|
||||
"%s failed, see buffer `%s' for details"
|
||||
msg-operation (buffer-name)))
|
||||
(if (or (not equal-remote)
|
||||
(and equal-remote
|
||||
(tramp-get-connection-property
|
||||
v "direct-copy-failed")))
|
||||
;; Propagate the error.
|
||||
(with-current-buffer (tramp-get-connection-buffer v)
|
||||
(goto-char (point-min))
|
||||
(tramp-error-with-buffer
|
||||
nil v 'file-error
|
||||
"%s failed, see buffer `%s' for details"
|
||||
msg-operation (buffer-name)))
|
||||
|
||||
;; Some WebDAV server, like the one from QNAP, do
|
||||
;; not support direct copy/move. Try a fallback.
|
||||
(tramp-set-connection-property v "direct-copy-failed" t)
|
||||
(tramp-gvfs-do-copy-or-rename-file
|
||||
op filename newname ok-if-already-exists keep-date
|
||||
preserve-uid-gid preserve-extended-attributes))))
|
||||
;; Some WebDAV server, like the one from QNAP,
|
||||
;; do not support direct copy/move. Try a
|
||||
;; fallback.
|
||||
(tramp-set-connection-property v "direct-copy-failed" t)
|
||||
(tramp-gvfs-do-copy-or-rename-file
|
||||
op filename newname ok-if-already-exists keep-date
|
||||
preserve-uid-gid preserve-extended-attributes))))
|
||||
|
||||
(when (and t1 (eq op 'rename))
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
(tramp-flush-file-properties v localname)))
|
||||
(when (and t1 (eq op 'rename))
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
(tramp-flush-file-properties v localname)))
|
||||
|
||||
(when t2
|
||||
(with-parsed-tramp-file-name newname nil
|
||||
(tramp-flush-file-properties v localname))))))))))
|
||||
(when t2
|
||||
(with-parsed-tramp-file-name newname nil
|
||||
(tramp-flush-file-properties v localname)))))))))))
|
||||
|
||||
(defun tramp-gvfs-handle-copy-file
|
||||
(filename newname &optional ok-if-already-exists keep-date
|
||||
|
@ -1403,7 +1411,7 @@ If FILE-SYSTEM is non-nil, return file system attributes."
|
|||
(or (cdr (assoc "standard::size" attributes)) "0")))
|
||||
;; ... file mode flags
|
||||
(setq res-filemodes
|
||||
(if-let ((n (cdr (assoc "unix::mode" attributes))))
|
||||
(if-let* ((n (cdr (assoc "unix::mode" attributes))))
|
||||
(tramp-file-mode-from-int (string-to-number n))
|
||||
(format
|
||||
"%s%s%s%s------"
|
||||
|
@ -1419,11 +1427,11 @@ If FILE-SYSTEM is non-nil, return file system attributes."
|
|||
"-" "x"))))
|
||||
;; ... inode and device
|
||||
(setq res-inode
|
||||
(if-let ((n (cdr (assoc "unix::inode" attributes))))
|
||||
(if-let* ((n (cdr (assoc "unix::inode" attributes))))
|
||||
(string-to-number n)
|
||||
(tramp-get-inode (tramp-dissect-file-name filename))))
|
||||
(setq res-device
|
||||
(if-let ((n (cdr (assoc "unix::device" attributes))))
|
||||
(if-let* ((n (cdr (assoc "unix::device" attributes))))
|
||||
(string-to-number n)
|
||||
(tramp-get-device (tramp-dissect-file-name filename))))
|
||||
|
||||
|
@ -1677,19 +1685,21 @@ ID-FORMAT valid values are `string' and `integer'."
|
|||
;; The result is cached in `tramp-get-remote-uid'.
|
||||
(if (equal id-format 'string)
|
||||
(tramp-file-name-user vec)
|
||||
(when-let ((localname
|
||||
(tramp-get-connection-property (tramp-get-process vec) "share")))
|
||||
(file-attribute-user-id
|
||||
(file-attributes (tramp-make-tramp-file-name vec localname) id-format)))))
|
||||
(and-let* ((localname
|
||||
(tramp-get-connection-property (tramp-get-process vec) "share"))
|
||||
((file-attribute-user-id
|
||||
(file-attributes
|
||||
(tramp-make-tramp-file-name vec localname) id-format)))))))
|
||||
|
||||
(defun tramp-gvfs-handle-get-remote-gid (vec id-format)
|
||||
"The gid of the remote connection VEC, in ID-FORMAT.
|
||||
ID-FORMAT valid values are `string' and `integer'."
|
||||
;; The result is cached in `tramp-get-remote-gid'.
|
||||
(when-let ((localname
|
||||
(tramp-get-connection-property (tramp-get-process vec) "share")))
|
||||
(file-attribute-group-id
|
||||
(file-attributes (tramp-make-tramp-file-name vec localname) id-format))))
|
||||
(and-let* ((localname
|
||||
(tramp-get-connection-property (tramp-get-process vec) "share"))
|
||||
((file-attribute-group-id
|
||||
(file-attributes
|
||||
(tramp-make-tramp-file-name vec localname) id-format))))))
|
||||
|
||||
(defun tramp-gvfs-handle-set-file-uid-gid (filename &optional uid gid)
|
||||
"Like `tramp-set-file-uid-gid' for Tramp files."
|
||||
|
@ -1722,12 +1732,12 @@ ID-FORMAT valid values are `string' and `integer'."
|
|||
(setq method "davs"
|
||||
localname
|
||||
(concat (tramp-gvfs-get-remote-prefix v) localname)))
|
||||
(when (string-equal "mtp" method)
|
||||
(when-let
|
||||
((media (tramp-get-connection-property v "media-device")))
|
||||
(setq method (tramp-media-device-method media)
|
||||
host (tramp-media-device-host media)
|
||||
port (tramp-media-device-port media))))
|
||||
(when-let*
|
||||
(((string-equal "mtp" method))
|
||||
(media (tramp-get-connection-property v "media-device")))
|
||||
(setq method (tramp-media-device-method media)
|
||||
host (tramp-media-device-host media)
|
||||
port (tramp-media-device-port media)))
|
||||
(when (and user domain)
|
||||
(setq user (concat domain ";" user)))
|
||||
(url-recreate-url
|
||||
|
@ -1772,6 +1782,24 @@ a downcased host name only."
|
|||
(string-match (rx bol (+ alnum) "://" (group (+ (not (any "/:"))))) url)
|
||||
(match-string 1 url)))
|
||||
|
||||
;; This is used in GNU ELPA package tramp-locproc.el.
|
||||
(defun tramp-gvfs-local-file-name (filename)
|
||||
"Return local mount name of FILENAME."
|
||||
(setq filename (file-name-unquote (expand-file-name filename)))
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
(with-tramp-file-property v localname "local-file-name"
|
||||
;; As long as we call `tramp-gvfs-maybe-open-connection' here,
|
||||
;; we cache the result.
|
||||
(tramp-gvfs-maybe-open-connection v)
|
||||
(let ((quoted (file-name-quoted-p localname))
|
||||
(localname (file-name-unquote localname)))
|
||||
(funcall
|
||||
(if quoted #'file-name-quote #'identity)
|
||||
(expand-file-name
|
||||
(if (file-name-absolute-p localname)
|
||||
(substring localname 1) localname)
|
||||
(tramp-get-file-property v "/" "fuse-mountpoint")))))))
|
||||
|
||||
|
||||
;; D-Bus GVFS functions.
|
||||
|
||||
|
@ -1924,10 +1952,10 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and
|
|||
(when (member method tramp-media-methods)
|
||||
;; Ensure that media devices are cached.
|
||||
(tramp-get-media-devices nil)
|
||||
(when-let ((v (tramp-get-connection-property
|
||||
(make-tramp-media-device
|
||||
:method method :host host :port port)
|
||||
"vector" nil)))
|
||||
(when-let* ((v (tramp-get-connection-property
|
||||
(make-tramp-media-device
|
||||
:method method :host host :port port)
|
||||
"vector" nil)))
|
||||
(setq method (tramp-file-name-method v)
|
||||
host (tramp-file-name-host v)
|
||||
port (tramp-file-name-port v))))
|
||||
|
@ -2024,10 +2052,10 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and
|
|||
(when (member method tramp-media-methods)
|
||||
;; Ensure that media devices are cached.
|
||||
(tramp-get-media-devices vec)
|
||||
(when-let ((v (tramp-get-connection-property
|
||||
(make-tramp-media-device
|
||||
:method method :host host :port port)
|
||||
"vector")))
|
||||
(when-let* ((v (tramp-get-connection-property
|
||||
(make-tramp-media-device
|
||||
:method method :host host :port port)
|
||||
"vector")))
|
||||
(setq method (tramp-file-name-method v)
|
||||
host (tramp-file-name-host v)
|
||||
port (tramp-file-name-port v))))
|
||||
|
@ -2195,7 +2223,7 @@ connection if a previous connection has died for some reason."
|
|||
method '(("smb" . "smb-share")
|
||||
("davs" . "dav")
|
||||
("nextcloud" . "dav")
|
||||
("afp". "afp-volume")
|
||||
("afp" . "afp-volume")
|
||||
("gdrive" . "google-drive")))
|
||||
method)
|
||||
tramp-gvfs-mounttypes)
|
||||
|
@ -2442,8 +2470,8 @@ It checks for registered GNOME Online Accounts."
|
|||
(defun tramp-get-media-device (vec)
|
||||
"Transform VEC into a `tramp-media-device' structure.
|
||||
Check, that respective cache values do exist."
|
||||
(if-let ((media (tramp-get-connection-property vec "media-device"))
|
||||
(prop (tramp-get-connection-property media "vector")))
|
||||
(if-let* ((media (tramp-get-connection-property vec "media-device"))
|
||||
(prop (tramp-get-connection-property media "vector")))
|
||||
media
|
||||
(tramp-get-media-devices vec)
|
||||
(tramp-get-connection-property vec "media-device")))
|
||||
|
|
|
@ -551,11 +551,11 @@ See `tramp-process-attributes-ps-format'.")
|
|||
|
||||
;; Preset default "ps" profile for local hosts, based on system type.
|
||||
|
||||
(when-let ((local-profile
|
||||
(cond ((eq system-type 'darwin)
|
||||
'tramp-connection-local-darwin-ps-profile)
|
||||
;; ... Add other system types here.
|
||||
)))
|
||||
(when-let* ((local-profile
|
||||
(cond ((eq system-type 'darwin)
|
||||
'tramp-connection-local-darwin-ps-profile)
|
||||
;; ... Add other system types here.
|
||||
)))
|
||||
(connection-local-set-profiles
|
||||
`(:application tramp :machine ,(system-name))
|
||||
local-profile)
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
(declare-function tramp-file-name-host-port "tramp")
|
||||
(declare-function tramp-file-name-user-domain "tramp")
|
||||
(declare-function tramp-get-default-directory "tramp")
|
||||
(defvar tramp-repository-branch)
|
||||
(defvar tramp-repository-version)
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defcustom tramp-verbose 3
|
||||
|
@ -422,7 +424,7 @@ an input event arrives. The other arguments are passed to `tramp-error'."
|
|||
;; Show buffer.
|
||||
(pop-to-buffer buf)
|
||||
(discard-input)
|
||||
(sit-for tramp-error-show-message-timeout)))
|
||||
(sit-for tramp-error-show-message-timeout 'nodisp)))
|
||||
;; Reset timestamp. It would be wrong after waiting for a while.
|
||||
(when (tramp-file-name-equal-p vec (car tramp-current-connection))
|
||||
(setcdr tramp-current-connection (current-time)))))))
|
||||
|
@ -444,7 +446,7 @@ an input event arrives. The other arguments are passed to `tramp-error'."
|
|||
;; `tramp-error' does not show messages. So we must do it ourselves.
|
||||
(apply #'message fmt-string arguments)
|
||||
(discard-input)
|
||||
(sit-for tramp-error-show-message-timeout)
|
||||
(sit-for tramp-error-show-message-timeout 'nodisp)
|
||||
;; Reset timestamp. It would be wrong after waiting for a while.
|
||||
(when
|
||||
(tramp-file-name-equal-p vec-or-proc (car tramp-current-connection))
|
||||
|
@ -468,7 +470,7 @@ to `tramp-message'."
|
|||
(declare (tramp-suppress-trace t))
|
||||
(let (signal-hook-function)
|
||||
(apply 'tramp-message vec-or-proc 2 fmt-string arguments)
|
||||
(lwarn 'tramp :warning fmt-string arguments)))
|
||||
(apply 'lwarn 'tramp :warning fmt-string arguments)))
|
||||
|
||||
(defun tramp-test-message (fmt-string &rest arguments)
|
||||
"Emit a Tramp message according `default-directory'."
|
||||
|
@ -486,7 +488,7 @@ to `tramp-message'."
|
|||
"Goto the linked message in debug buffer at place."
|
||||
(declare (tramp-suppress-trace t))
|
||||
(when (mouse-event-p last-input-event) (mouse-set-point last-input-event))
|
||||
(when-let ((point (button-get button 'position)))
|
||||
(when-let* ((point (button-get button 'position)))
|
||||
(goto-char point)))
|
||||
|
||||
(define-button-type 'tramp-debug-button-type
|
||||
|
|
|
@ -166,15 +166,15 @@ Operations not mentioned here will be handled by the default Emacs primitives.")
|
|||
;;;###tramp-autoload
|
||||
(defsubst tramp-rclone-file-name-p (vec-or-filename)
|
||||
"Check if it's a VEC-OR-FILENAME for rclone."
|
||||
(when-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename)))
|
||||
(string= (tramp-file-name-method vec) tramp-rclone-method)))
|
||||
(and-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename))
|
||||
((string= (tramp-file-name-method vec) tramp-rclone-method)))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defun tramp-rclone-file-name-handler (operation &rest args)
|
||||
"Invoke the rclone handler for OPERATION and ARGS.
|
||||
First arg specifies the OPERATION, second arg is a list of
|
||||
arguments to pass to the OPERATION."
|
||||
(if-let ((fn (assoc operation tramp-rclone-file-name-handler-alist)))
|
||||
(if-let* ((fn (assoc operation tramp-rclone-file-name-handler-alist)))
|
||||
(prog1 (save-match-data (apply (cdr fn) args))
|
||||
(setq tramp-debug-message-fnh-function (cdr fn)))
|
||||
(prog1 (tramp-run-real-handler operation args)
|
||||
|
|
|
@ -354,7 +354,7 @@ The string is used in `tramp-methods'.")
|
|||
(tramp-remote-shell-login ("-l"))
|
||||
(tramp-remote-shell-args ("-c"))
|
||||
(tramp-copy-program "pscp")
|
||||
(tramp-copy-args (("-l" "%u") ("-P" "%p") ("-scp")
|
||||
(tramp-copy-args (("-l" "%u") ("-P" "%p") ("-scp") ("%c")
|
||||
("-p" "%k") ("-q") ("-r")))
|
||||
(tramp-copy-keep-date t)
|
||||
(tramp-copy-recursive t)))
|
||||
|
@ -372,7 +372,7 @@ The string is used in `tramp-methods'.")
|
|||
(tramp-remote-shell-login ("-l"))
|
||||
(tramp-remote-shell-args ("-c"))
|
||||
(tramp-copy-program "pscp")
|
||||
(tramp-copy-args (("-l" "%u") ("-P" "%p") ("-sftp")
|
||||
(tramp-copy-args (("-l" "%u") ("-P" "%p") ("-sftp") ("%c")
|
||||
("-p" "%k")))
|
||||
(tramp-copy-keep-date t)))
|
||||
|
||||
|
@ -597,6 +597,7 @@ shell from reading its init file."
|
|||
'((tramp-login-prompt-regexp tramp-action-login)
|
||||
(tramp-password-prompt-regexp tramp-action-password)
|
||||
(tramp-otp-password-prompt-regexp tramp-action-otp-password)
|
||||
(tramp-fingerprint-prompt-regexp tramp-action-fingerprint)
|
||||
(tramp-wrong-passwd-regexp tramp-action-permission-denied)
|
||||
(shell-prompt-pattern tramp-action-succeed)
|
||||
(tramp-shell-prompt-pattern tramp-action-succeed)
|
||||
|
@ -1808,7 +1809,7 @@ ID-FORMAT valid values are `string' and `integer'."
|
|||
;; be expected that this is always a directory.
|
||||
(or (tramp-string-empty-or-nil-p localname)
|
||||
(with-tramp-file-property v localname "file-directory-p"
|
||||
(if-let
|
||||
(if-let*
|
||||
((truename (tramp-get-file-property v localname "file-truename"))
|
||||
((tramp-file-property-p
|
||||
v (tramp-file-local-name truename) "file-attributes")))
|
||||
|
@ -1852,7 +1853,10 @@ ID-FORMAT valid values are `string' and `integer'."
|
|||
;; test.
|
||||
(tramp-check-remote-uname v tramp-bsd-unames)
|
||||
(= (file-attribute-group-id attributes)
|
||||
(tramp-get-remote-gid v 'integer)))))))))
|
||||
(tramp-get-remote-gid v 'integer))
|
||||
;; FIXME: `file-ownership-preserved-p' tests also the
|
||||
;; ownership of the parent directory. We don't.
|
||||
)))))))
|
||||
|
||||
;; Directory listings.
|
||||
|
||||
|
@ -2023,49 +2027,56 @@ ID-FORMAT valid values are `string' and `integer'."
|
|||
(t2 (tramp-tramp-file-p newname))
|
||||
target)
|
||||
(with-parsed-tramp-file-name (if t1 dirname newname) nil
|
||||
(unless (file-exists-p dirname)
|
||||
(tramp-error v 'file-missing dirname))
|
||||
(cond
|
||||
;; `copy-directory-create-symlink' exists since Emacs 28.1.
|
||||
((and (bound-and-true-p copy-directory-create-symlink)
|
||||
(setq target (file-symlink-p dirname))
|
||||
(tramp-equal-remote dirname newname))
|
||||
(make-symbolic-link
|
||||
target
|
||||
(if (directory-name-p newname)
|
||||
(concat newname (file-name-nondirectory dirname)) newname)
|
||||
t))
|
||||
|
||||
;; `copy-directory-create-symlink' exists since Emacs 28.1.
|
||||
(if (and (bound-and-true-p copy-directory-create-symlink)
|
||||
(setq target (file-symlink-p dirname))
|
||||
(tramp-equal-remote dirname newname))
|
||||
(make-symbolic-link
|
||||
target
|
||||
(if (directory-name-p newname)
|
||||
(concat newname (file-name-nondirectory dirname)) newname)
|
||||
t)
|
||||
;; Shortcut: if method, host, user are the same for both
|
||||
;; files, we invoke `cp' on the remote host directly.
|
||||
((and (not copy-contents)
|
||||
(tramp-equal-remote dirname newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(setq dirname (directory-file-name (expand-file-name dirname))
|
||||
newname (directory-file-name (expand-file-name newname)))
|
||||
(tramp-do-copy-or-rename-file-directly
|
||||
'copy dirname newname
|
||||
'ok-if-already-exists keep-date 'preserve-uid-gid))
|
||||
|
||||
(if (and (not copy-contents)
|
||||
(tramp-get-method-parameter v 'tramp-copy-recursive)
|
||||
;; When DIRNAME and NEWNAME are remote, they must
|
||||
;; have the same method.
|
||||
(or (null t1) (null t2)
|
||||
(string-equal
|
||||
(tramp-file-name-method
|
||||
(tramp-dissect-file-name dirname))
|
||||
(tramp-file-name-method
|
||||
(tramp-dissect-file-name newname)))))
|
||||
;; scp or rsync DTRT.
|
||||
(progn
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(setq dirname (directory-file-name (expand-file-name dirname))
|
||||
newname (directory-file-name (expand-file-name newname)))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (string-equal (file-name-nondirectory dirname)
|
||||
(file-name-nondirectory newname))))
|
||||
(setq newname
|
||||
(expand-file-name
|
||||
(file-name-nondirectory dirname) newname)))
|
||||
(unless (file-directory-p (file-name-directory newname))
|
||||
(make-directory (file-name-directory newname) parents))
|
||||
(tramp-do-copy-or-rename-file-out-of-band
|
||||
'copy dirname newname 'ok-if-already-exists keep-date))
|
||||
;; scp or rsync DTRT.
|
||||
((and (not copy-contents)
|
||||
(tramp-get-method-parameter v 'tramp-copy-recursive)
|
||||
;; When DIRNAME and NEWNAME are remote, they must have
|
||||
;; the same method.
|
||||
(or (null t1) (null t2)
|
||||
(string-equal
|
||||
(tramp-file-name-method (tramp-dissect-file-name dirname))
|
||||
(tramp-file-name-method (tramp-dissect-file-name newname)))))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(setq dirname (directory-file-name (expand-file-name dirname))
|
||||
newname (directory-file-name (expand-file-name newname)))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (string-equal (file-name-nondirectory dirname)
|
||||
(file-name-nondirectory newname))))
|
||||
(setq newname
|
||||
(expand-file-name (file-name-nondirectory dirname) newname)))
|
||||
(unless (file-directory-p (file-name-directory newname))
|
||||
(make-directory (file-name-directory newname) parents))
|
||||
(tramp-do-copy-or-rename-file-out-of-band
|
||||
'copy dirname newname 'ok-if-already-exists keep-date))
|
||||
|
||||
;; We must do it file-wise.
|
||||
(tramp-run-real-handler
|
||||
;; We must do it file-wise.
|
||||
(t (tramp-run-real-handler
|
||||
#'copy-directory
|
||||
(list dirname newname keep-date parents copy-contents))))
|
||||
|
||||
|
@ -2117,123 +2128,129 @@ file names."
|
|||
(progn
|
||||
(copy-directory filename newname keep-date t)
|
||||
(when (eq op 'rename) (delete-directory filename 'recursive)))
|
||||
(if (file-symlink-p filename)
|
||||
(progn
|
||||
(make-symbolic-link
|
||||
(file-symlink-p filename) newname ok-if-already-exists)
|
||||
(when (eq op 'rename) (delete-file filename)))
|
||||
|
||||
;; FIXME: This should be optimized. Computing `file-attributes'
|
||||
;; checks already, whether the file exists.
|
||||
(let ((t1 (tramp-tramp-file-p filename))
|
||||
(t2 (tramp-tramp-file-p newname))
|
||||
(length (file-attribute-size
|
||||
(file-attributes (file-truename filename))))
|
||||
(file-times (file-attribute-modification-time
|
||||
(file-attributes filename)))
|
||||
(file-modes (tramp-default-file-modes filename))
|
||||
(msg-operation (if (eq op 'copy) "Copying" "Renaming"))
|
||||
copy-keep-date)
|
||||
;; FIXME: This should be optimized. Computing `file-attributes'
|
||||
;; checks already, whether the file exists.
|
||||
(let ((t1 (tramp-tramp-file-p filename))
|
||||
(t2 (tramp-tramp-file-p newname))
|
||||
(length (or (file-attribute-size
|
||||
(file-attributes (file-truename filename)))
|
||||
;; `filename' doesn't exist, for example due
|
||||
;; to non-existent symlink target.
|
||||
0))
|
||||
(file-times (file-attribute-modification-time
|
||||
(file-attributes filename)))
|
||||
(file-modes (tramp-default-file-modes filename))
|
||||
(msg-operation (if (eq op 'copy) "Copying" "Renaming"))
|
||||
copy-keep-date)
|
||||
|
||||
(with-parsed-tramp-file-name (if t1 filename newname) nil
|
||||
(unless length
|
||||
(tramp-error v 'file-missing filename))
|
||||
(tramp-barf-if-file-missing v filename
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
(with-parsed-tramp-file-name (if t1 filename newname) nil
|
||||
(tramp-barf-if-file-missing v filename
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
|
||||
(with-tramp-progress-reporter
|
||||
v 0 (format "%s %s to %s" msg-operation filename newname)
|
||||
(with-tramp-progress-reporter
|
||||
v 0 (format "%s %s to %s" msg-operation filename newname)
|
||||
|
||||
(cond
|
||||
;; Both are Tramp files.
|
||||
((and t1 t2)
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(cond
|
||||
;; Shortcut: if method, host, user are the same for
|
||||
;; both files, we invoke `cp' or `mv' on the remote
|
||||
;; host directly.
|
||||
((tramp-equal-remote filename newname)
|
||||
(setq copy-keep-date
|
||||
(or (eq op 'rename) keep-date preserve-uid-gid))
|
||||
(tramp-do-copy-or-rename-file-directly
|
||||
op filename newname
|
||||
ok-if-already-exists keep-date preserve-uid-gid))
|
||||
|
||||
;; Try out-of-band operation.
|
||||
((and
|
||||
(tramp-method-out-of-band-p v1 length)
|
||||
(tramp-method-out-of-band-p v2 length))
|
||||
(setq copy-keep-date
|
||||
(tramp-get-method-parameter v 'tramp-copy-keep-date))
|
||||
(tramp-do-copy-or-rename-file-out-of-band
|
||||
op filename newname ok-if-already-exists keep-date))
|
||||
|
||||
;; No shortcut was possible. So we copy the file
|
||||
;; first. If the operation was `rename', we go
|
||||
;; back and delete the original file (if the copy
|
||||
;; was successful). The approach is simple-minded:
|
||||
;; we create a new buffer, insert the contents of
|
||||
;; the source file into it, then write out the
|
||||
;; buffer to the target file. The advantage is
|
||||
;; that it doesn't matter which file name handlers
|
||||
;; are used for the source and target file.
|
||||
(t
|
||||
(tramp-do-copy-or-rename-file-via-buffer
|
||||
op filename newname ok-if-already-exists keep-date))))))
|
||||
|
||||
;; One file is a Tramp file, the other one is local.
|
||||
((or t1 t2)
|
||||
(cond
|
||||
;; Fast track on local machine.
|
||||
((tramp-local-host-p v)
|
||||
(setq copy-keep-date
|
||||
(or (eq op 'rename) keep-date preserve-uid-gid))
|
||||
(tramp-do-copy-or-rename-file-directly
|
||||
op filename newname
|
||||
ok-if-already-exists keep-date preserve-uid-gid))
|
||||
;; Both are Tramp files.
|
||||
((and t1 t2)
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(cond
|
||||
;; Shortcut: if method, host, user are the same
|
||||
;; for both files, we invoke `cp' or `mv' on the
|
||||
;; remote host directly.
|
||||
((tramp-equal-remote filename newname)
|
||||
(setq copy-keep-date
|
||||
(or (eq op 'rename) keep-date preserve-uid-gid))
|
||||
(tramp-do-copy-or-rename-file-directly
|
||||
op filename newname
|
||||
ok-if-already-exists keep-date preserve-uid-gid))
|
||||
|
||||
;; If the Tramp file has an out-of-band method, the
|
||||
;; corresponding copy-program can be invoked.
|
||||
((tramp-method-out-of-band-p v length)
|
||||
(setq copy-keep-date
|
||||
(tramp-get-method-parameter v 'tramp-copy-keep-date))
|
||||
(tramp-do-copy-or-rename-file-out-of-band
|
||||
op filename newname ok-if-already-exists keep-date))
|
||||
;; Try out-of-band operation.
|
||||
((and
|
||||
(tramp-method-out-of-band-p v1 length)
|
||||
(tramp-method-out-of-band-p v2 length))
|
||||
(setq copy-keep-date
|
||||
(tramp-get-method-parameter v 'tramp-copy-keep-date))
|
||||
(tramp-do-copy-or-rename-file-out-of-band
|
||||
op filename newname ok-if-already-exists keep-date))
|
||||
|
||||
;; Use the inline method via a Tramp buffer.
|
||||
(t (tramp-do-copy-or-rename-file-via-buffer
|
||||
op filename newname ok-if-already-exists keep-date))))
|
||||
;; No shortcut was possible. So we copy the file
|
||||
;; first. If the operation was `rename', we go
|
||||
;; back and delete the original file (if the copy
|
||||
;; was successful). The approach is simple-minded:
|
||||
;; we create a new buffer, insert the contents of
|
||||
;; the source file into it, then write out the
|
||||
;; buffer to the target file. The advantage is
|
||||
;; that it doesn't matter which file name handlers
|
||||
;; are used for the source and target file.
|
||||
(t
|
||||
(tramp-do-copy-or-rename-file-via-buffer
|
||||
op filename newname ok-if-already-exists keep-date))))))
|
||||
|
||||
(t
|
||||
;; One of them must be a Tramp file.
|
||||
(error "Tramp implementation says this cannot happen")))
|
||||
;; One file is a Tramp file, the other one is local.
|
||||
((or t1 t2)
|
||||
(cond
|
||||
;; Fast track on local machine.
|
||||
((tramp-local-host-p v)
|
||||
(setq copy-keep-date
|
||||
(or (eq op 'rename) keep-date preserve-uid-gid))
|
||||
(tramp-do-copy-or-rename-file-directly
|
||||
op filename newname
|
||||
ok-if-already-exists keep-date preserve-uid-gid))
|
||||
|
||||
;; In case of `rename', we must flush the cache of the source file.
|
||||
(when (and t1 (eq op 'rename))
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(tramp-flush-file-properties v1 v1-localname)))
|
||||
;; If the Tramp file has an out-of-band method, the
|
||||
;; corresponding copy-program can be invoked.
|
||||
((tramp-method-out-of-band-p v length)
|
||||
(setq copy-keep-date
|
||||
(tramp-get-method-parameter v 'tramp-copy-keep-date))
|
||||
(tramp-do-copy-or-rename-file-out-of-band
|
||||
op filename newname ok-if-already-exists keep-date))
|
||||
|
||||
;; NEWNAME has wrong cached values.
|
||||
(when t2
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(tramp-flush-file-properties v2 v2-localname)))
|
||||
;; Use the inline method via a Tramp buffer.
|
||||
(t (tramp-do-copy-or-rename-file-via-buffer
|
||||
op filename newname ok-if-already-exists keep-date))))
|
||||
|
||||
;; Handle `preserve-extended-attributes'. We ignore
|
||||
;; possible errors, because ACL strings could be
|
||||
;; incompatible.
|
||||
(when-let ((attributes (and preserve-extended-attributes
|
||||
(file-extended-attributes filename))))
|
||||
(ignore-errors
|
||||
(set-file-extended-attributes newname attributes)))
|
||||
(t
|
||||
;; One of them must be a Tramp file.
|
||||
(error "Tramp implementation says this cannot happen")))
|
||||
|
||||
;; KEEP-DATE handling.
|
||||
(when (and keep-date (not copy-keep-date))
|
||||
(tramp-compat-set-file-times
|
||||
newname file-times (unless ok-if-already-exists 'nofollow)))
|
||||
;; In case of `rename', we must flush the cache of the source file.
|
||||
(when (and t1 (eq op 'rename))
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(tramp-flush-file-properties v1 v1-localname)))
|
||||
|
||||
;; Set the mode.
|
||||
(unless (and keep-date copy-keep-date)
|
||||
(set-file-modes newname file-modes))))))))
|
||||
;; NEWNAME has wrong cached values.
|
||||
(when t2
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(tramp-flush-file-properties v2 v2-localname)))
|
||||
|
||||
;; Handle `preserve-extended-attributes'. We ignore
|
||||
;; possible errors, because ACL strings could be
|
||||
;; incompatible.
|
||||
(when-let* ((attributes (and preserve-extended-attributes
|
||||
(file-extended-attributes filename))))
|
||||
(ignore-errors
|
||||
(set-file-extended-attributes newname attributes)))
|
||||
|
||||
;; KEEP-DATE handling.
|
||||
(when (and keep-date (not copy-keep-date))
|
||||
(tramp-compat-set-file-times
|
||||
newname file-times (unless ok-if-already-exists 'nofollow)))
|
||||
|
||||
;; Set the mode.
|
||||
(unless (and keep-date copy-keep-date)
|
||||
(set-file-modes newname file-modes)))))))))
|
||||
|
||||
(defun tramp-do-copy-or-rename-file-via-buffer
|
||||
(op filename newname _ok-if-already-exists _keep-date)
|
||||
|
@ -2474,7 +2491,7 @@ The method used must be an out-of-band method."
|
|||
;; Compose copy command.
|
||||
(setq options
|
||||
(format-spec
|
||||
(tramp-ssh-controlmaster-options v)
|
||||
(tramp-ssh-or-plink-options v)
|
||||
(format-spec-make
|
||||
?t (tramp-get-connection-property
|
||||
(tramp-get-connection-process v) "temp-file" "")))
|
||||
|
@ -2859,7 +2876,7 @@ The method used must be an out-of-band method."
|
|||
(rx bol (group (* blank) "total")) nil t)
|
||||
;; Emacs 29.1 or later.
|
||||
(not (fboundp 'dired--insert-disk-space)))
|
||||
(when-let ((available (get-free-disk-space ".")))
|
||||
(when-let* ((available (get-free-disk-space ".")))
|
||||
;; Replace "total" with "total used", to avoid confusion.
|
||||
(replace-match "\\1 used in directory")
|
||||
(end-of-line)
|
||||
|
@ -3094,8 +3111,7 @@ will be used."
|
|||
;; needed when sending signals remotely.
|
||||
(let ((pid (tramp-send-command-and-read v "echo $$")))
|
||||
(setq p (tramp-get-connection-process v))
|
||||
(process-put p 'remote-pid pid)
|
||||
(tramp-set-connection-property p "remote-pid" pid))
|
||||
(process-put p 'remote-pid pid))
|
||||
(when (memq connection-type '(nil pipe))
|
||||
;; Disable carriage return to newline
|
||||
;; translation. This does not work on
|
||||
|
@ -3110,7 +3126,7 @@ will be used."
|
|||
;; character to read. When a process does
|
||||
;; not read from stdin, like magit, it
|
||||
;; should set a timeout
|
||||
;; instead. See`tramp-pipe-stty-settings'.
|
||||
;; instead. See `tramp-pipe-stty-settings'.
|
||||
;; (Bug#62093)
|
||||
;; FIXME: Shall we rather use "stty raw"?
|
||||
(tramp-send-command
|
||||
|
@ -3269,8 +3285,7 @@ will be used."
|
|||
(setq ret (tramp-send-command-and-check
|
||||
v (format
|
||||
"cd %s && %s"
|
||||
(tramp-unquote-shell-quote-argument localname)
|
||||
command)
|
||||
(tramp-shell-quote-argument localname) command)
|
||||
t t t))
|
||||
(unless (natnump ret) (setq ret 1))
|
||||
;; We should add the output anyway.
|
||||
|
@ -3305,7 +3320,7 @@ will be used."
|
|||
(defun tramp-sh-handle-file-local-copy (filename)
|
||||
"Like `file-local-copy' for Tramp files."
|
||||
(tramp-skeleton-file-local-copy filename
|
||||
(if-let ((size (file-attribute-size (file-attributes filename))))
|
||||
(if-let* ((size (file-attribute-size (file-attributes filename))))
|
||||
(let (rem-enc loc-dec)
|
||||
|
||||
(condition-case err
|
||||
|
@ -3619,14 +3634,14 @@ filled are described in `tramp-bundle-read-file-names'."
|
|||
;; requires a remote command (the file cache must be invalidated).
|
||||
;; Therefore, we apply a kind of optimization. We install the file
|
||||
;; name handler `tramp-vc-file-name-handler', which does nothing but
|
||||
;; remembers all file names for which `file-exists-p' or
|
||||
;; `file-readable-p' has been applied. A first run of `vc-registered'
|
||||
;; is performed. Afterwards, a script is applied for all collected
|
||||
;; file names, using just one remote command. The result of this
|
||||
;; script is used to fill the file cache with actual values. Now we
|
||||
;; can reset the file name handlers, and we make a second run of
|
||||
;; `vc-registered', which returns the expected result without sending
|
||||
;; any other remote command.
|
||||
;; remembers all file names for which `file-exists-p',
|
||||
;; `file-readable-p' or `file-directory-p' has been applied. A first
|
||||
;; run of `vc-registered' is performed. Afterwards, a script is
|
||||
;; applied for all collected file names, using just one remote
|
||||
;; command. The result of this script is used to fill the file cache
|
||||
;; with actual values. Now we can reset the file name handlers, and
|
||||
;; we make a second run of `vc-registered', which returns the expected
|
||||
;; result without sending any other remote command.
|
||||
;; When called during `revert-buffer', it shouldn't spam the echo area
|
||||
;; and the *Messages* buffer.
|
||||
(defun tramp-sh-handle-vc-registered (file)
|
||||
|
@ -3658,10 +3673,11 @@ filled are described in `tramp-bundle-read-file-names'."
|
|||
;; Send just one command, in order to fill the cache.
|
||||
(tramp-bundle-read-file-names v tramp-vc-registered-file-names))
|
||||
|
||||
;; Second run. Now all `file-exists-p' or `file-readable-p'
|
||||
;; calls shall be answered from the file cache. We unset
|
||||
;; `process-file-side-effects' and `remote-file-name-inhibit-cache'
|
||||
;; in order to keep the cache.
|
||||
;; Second run. Now all `file-exists-p', `file-readable-p'
|
||||
;; or `file-directory-p' calls shall be answered from the
|
||||
;; file cache. We unset `process-file-side-effects' and
|
||||
;; `remote-file-name-inhibit-cache' in order to keep the
|
||||
;; cache.
|
||||
(let ((vc-handled-backends (copy-sequence vc-handled-backends))
|
||||
remote-file-name-inhibit-cache process-file-side-effects)
|
||||
;; Reduce `vc-handled-backends' in order to minimize
|
||||
|
@ -3696,7 +3712,7 @@ filled are described in `tramp-bundle-read-file-names'."
|
|||
(defun tramp-sh-file-name-handler (operation &rest args)
|
||||
"Invoke remote-shell Tramp file name handler.
|
||||
Fall back to normal file name handler if no Tramp handler exists."
|
||||
(if-let ((fn (assoc operation tramp-sh-file-name-handler-alist)))
|
||||
(if-let* ((fn (assoc operation tramp-sh-file-name-handler-alist)))
|
||||
(prog1 (save-match-data (apply (cdr fn) args))
|
||||
(setq tramp-debug-message-fnh-function (cdr fn)))
|
||||
(prog1 (tramp-run-real-handler operation args)
|
||||
|
@ -3718,33 +3734,35 @@ Fall back to normal file name handler if no Tramp handler exists."
|
|||
(defun tramp-vc-file-name-handler (operation &rest args)
|
||||
"Invoke special file name handler, which collects files to be handled."
|
||||
(save-match-data
|
||||
(let ((filename
|
||||
(tramp-replace-environment-variables
|
||||
(apply #'tramp-file-name-for-operation operation args)))
|
||||
(fn (assoc operation tramp-sh-file-name-handler-alist)))
|
||||
(if (tramp-tramp-file-p filename)
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
(cond
|
||||
;; That's what we want: file names, for which checks are
|
||||
;; applied. We assume that VC uses only `file-exists-p'
|
||||
;; and `file-readable-p' checks; otherwise we must extend
|
||||
;; the list. We do not perform any action, but return
|
||||
;; nil, in order to keep `vc-registered' running.
|
||||
((and fn (memq operation '(file-exists-p file-readable-p)))
|
||||
(add-to-list 'tramp-vc-registered-file-names localname 'append)
|
||||
nil)
|
||||
;; `process-file' and `start-file-process' shall be ignored.
|
||||
((and fn (eq operation 'process-file) 0))
|
||||
((and fn (eq operation 'start-file-process) nil))
|
||||
;; Tramp file name handlers like `expand-file-name'. They
|
||||
;; must still work.
|
||||
(fn (save-match-data (apply (cdr fn) args)))
|
||||
;; Default file name handlers, we don't care.
|
||||
(t (tramp-run-real-handler operation args))))
|
||||
(if-let* ((filename
|
||||
(tramp-replace-environment-variables
|
||||
(apply #'tramp-file-name-for-operation operation args)))
|
||||
((tramp-tramp-file-p filename))
|
||||
(fn (assoc operation tramp-sh-file-name-handler-alist)))
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
(cond
|
||||
;; That's what we want: file names, for which checks are
|
||||
;; applied. We assume that VC uses only `file-exists-p',
|
||||
;; `file-readable-p' and `file-directory-p' checks;
|
||||
;; otherwise we must extend the list. The respective cache
|
||||
;; value must be set for these functions in
|
||||
;; `tramp-bundle-read-file-names'.
|
||||
;; We do not perform any action, but return nil, in order
|
||||
;; to keep `vc-registered' running.
|
||||
((memq operation '(file-exists-p file-readable-p file-directory-p))
|
||||
(add-to-list 'tramp-vc-registered-file-names localname 'append)
|
||||
nil)
|
||||
;; `process-file' and `start-file-process' shall be ignored.
|
||||
((eq operation 'process-file) 0)
|
||||
((eq operation 'start-file-process) nil)
|
||||
;; Tramp file name handlers like `expand-file-name'. They
|
||||
;; must still work.
|
||||
(t (save-match-data (apply (cdr fn) args)))))
|
||||
|
||||
;; When `tramp-mode' is not enabled, or the file name is
|
||||
;; quoted, we don't do anything.
|
||||
(tramp-run-real-handler operation args)))))
|
||||
;; When `tramp-mode' is not enabled, or the file name is not a
|
||||
;; remote file name, we don't do anything. Same for default
|
||||
;; file name handlers.
|
||||
(tramp-run-real-handler operation args))))
|
||||
|
||||
(defun tramp-sh-handle-file-notify-add-watch (file-name flags _callback)
|
||||
"Like `file-notify-add-watch' for Tramp files."
|
||||
|
@ -4892,41 +4910,60 @@ Goes through the list `tramp-inline-compress-commands'."
|
|||
(zerop
|
||||
(tramp-call-process vec "ssh" nil nil nil "-G" "-o" option "0.0.0.1"))))
|
||||
|
||||
(defun tramp-ssh-controlmaster-options (vec)
|
||||
"Return the Control* arguments of the local ssh."
|
||||
(defun tramp-plink-option-exists-p (vec option)
|
||||
"Check, whether local plink OPTION is applicable."
|
||||
;; We don't want to cache it persistently.
|
||||
(with-tramp-connection-property nil option
|
||||
;; "plink" with valid options returns "plink: no valid host name
|
||||
;; provided". We xcheck for this error message."
|
||||
(with-temp-buffer
|
||||
(tramp-call-process vec "plink" nil t nil option)
|
||||
(not
|
||||
(string-match-p
|
||||
(rx (| (: "plink: unknown option \"" (literal option) "\"" )
|
||||
(: "plink: option \"" (literal option)
|
||||
"\" not available in this tool" )))
|
||||
(buffer-string))))))
|
||||
|
||||
(defun tramp-ssh-or-plink-options (vec)
|
||||
"Return additional arguments of the local ssh or plink."
|
||||
(cond
|
||||
;; No options to be computed.
|
||||
((or (null tramp-use-connection-share)
|
||||
(null (assoc "%c" (tramp-get-method-parameter vec 'tramp-login-args))))
|
||||
"")
|
||||
((null (assoc "%c" (tramp-get-method-parameter vec 'tramp-login-args))) "")
|
||||
|
||||
;; Use plink option.
|
||||
;; Use plink options.
|
||||
((string-match-p
|
||||
(rx "plink" (? ".exe") eol)
|
||||
(tramp-get-method-parameter vec 'tramp-login-program))
|
||||
(if (eq tramp-use-connection-share 'suppress)
|
||||
"-noshare" "-share"))
|
||||
(concat
|
||||
(if (eq tramp-use-connection-share 'suppress)
|
||||
"-noshare" "-share")
|
||||
;; Since PuTTY 0.82.
|
||||
(when (tramp-plink-option-exists-p vec "-legacy-stdio-prompts")
|
||||
" -legacy-stdio-prompts")))
|
||||
|
||||
;; There is already a value to be used.
|
||||
((and (eq tramp-use-connection-share t)
|
||||
(stringp tramp-ssh-controlmaster-options))
|
||||
tramp-ssh-controlmaster-options)
|
||||
|
||||
;; We can't auto-compute the options.
|
||||
((ignore-errors
|
||||
(not (tramp-ssh-option-exists-p vec "ControlMaster=auto")))
|
||||
"")
|
||||
;; Use ssh options.
|
||||
(tramp-use-connection-share
|
||||
;; We can't auto-compute the options.
|
||||
(if (ignore-errors
|
||||
(not (tramp-ssh-option-exists-p vec "ControlMaster=auto")))
|
||||
""
|
||||
|
||||
;; Determine the options.
|
||||
(t (ignore-errors
|
||||
;; ControlMaster and ControlPath options are introduced in OpenSSH 3.9.
|
||||
(concat
|
||||
"-o ControlMaster="
|
||||
(if (eq tramp-use-connection-share 'suppress)
|
||||
;; Determine the options.
|
||||
(ignore-errors
|
||||
;; ControlMaster and ControlPath options are introduced in OpenSSH 3.9.
|
||||
(concat
|
||||
"-o ControlMaster="
|
||||
(if (eq tramp-use-connection-share 'suppress)
|
||||
"no" "auto")
|
||||
|
||||
" -o ControlPath="
|
||||
(if (eq tramp-use-connection-share 'suppress)
|
||||
" -o ControlPath="
|
||||
(if (eq tramp-use-connection-share 'suppress)
|
||||
"none"
|
||||
;; Hashed tokens are introduced in OpenSSH 6.7. On macOS
|
||||
;; we cannot use an absolute file name, it is too long.
|
||||
|
@ -4940,10 +4977,13 @@ Goes through the list `tramp-inline-compress-commands'."
|
|||
(or small-temporary-file-directory
|
||||
tramp-compat-temporary-file-directory))))
|
||||
|
||||
;; ControlPersist option is introduced in OpenSSH 5.6.
|
||||
;; ControlPersist option is introduced in OpenSSH 5.6.
|
||||
(when (and (not (eq tramp-use-connection-share 'suppress))
|
||||
(tramp-ssh-option-exists-p vec "ControlPersist=no"))
|
||||
" -o ControlPersist=no"))))))
|
||||
" -o ControlPersist=no")))))
|
||||
|
||||
;; Return a string, whatsoever.
|
||||
(t "")))
|
||||
|
||||
(defun tramp-scp-strict-file-name-checking (vec)
|
||||
"Return the strict file name checking argument of the local scp."
|
||||
|
@ -5159,9 +5199,9 @@ connection if a previous connection has died for some reason."
|
|||
(let* ((current-host tramp-system-name)
|
||||
(target-alist (tramp-compute-multi-hops vec))
|
||||
(previous-hop tramp-null-hop)
|
||||
;; We will apply `tramp-ssh-controlmaster-options'
|
||||
;; We will apply `tramp-ssh-or-plink-options'
|
||||
;; only for the first hop.
|
||||
(options (tramp-ssh-controlmaster-options vec))
|
||||
(options (tramp-ssh-or-plink-options vec))
|
||||
(process-connection-type tramp-process-connection-type)
|
||||
(process-adaptive-read-buffering nil)
|
||||
;; There are unfortunate settings for "cmdproxy"
|
||||
|
@ -5240,9 +5280,10 @@ connection if a previous connection has died for some reason."
|
|||
(setq r-shell t)))
|
||||
(setq current-host l-host)
|
||||
|
||||
;; Set password prompt vector.
|
||||
;; Set hop and password prompt vector.
|
||||
(tramp-set-connection-property p "hop-vector" hop)
|
||||
(tramp-set-connection-property
|
||||
p "password-vector"
|
||||
p "pw-vector"
|
||||
(if (tramp-get-method-parameter
|
||||
hop 'tramp-password-previous-hop)
|
||||
(let ((pv (copy-tramp-file-name previous-hop)))
|
||||
|
@ -5253,9 +5294,9 @@ connection if a previous connection has died for some reason."
|
|||
:host l-host :port l-port)))
|
||||
|
||||
;; Set session timeout.
|
||||
(when-let ((timeout
|
||||
(tramp-get-method-parameter
|
||||
hop 'tramp-session-timeout)))
|
||||
(when-let* ((timeout
|
||||
(tramp-get-method-parameter
|
||||
hop 'tramp-session-timeout)))
|
||||
(tramp-set-connection-property
|
||||
p "session-timeout" timeout))
|
||||
|
||||
|
@ -5298,6 +5339,8 @@ connection if a previous connection has died for some reason."
|
|||
tramp-actions-before-shell connection-timeout))
|
||||
|
||||
;; Next hop.
|
||||
(tramp-flush-connection-property p "hop-vector")
|
||||
(tramp-flush-connection-property p "pw-vector")
|
||||
(setq options ""
|
||||
target-alist (cdr target-alist)
|
||||
previous-hop hop)))
|
||||
|
@ -5619,7 +5662,7 @@ Nonexistent directories are removed from spec."
|
|||
(lambda (x) (not (tramp-get-file-property vec x "file-directory-p")))
|
||||
remote-path))))))
|
||||
|
||||
;; The PIPE_BUF in POSIX [1] can be as low as 512 [2]. Here are the values
|
||||
;; The PIPE_BUF in POSIX [1] can be as low as 512 [2]. Here are the values
|
||||
;; on various platforms:
|
||||
;; - 512 on macOS, FreeBSD, NetBSD, OpenBSD, MirBSD, native Windows.
|
||||
;; - 4 KiB on Linux, OSF/1, Cygwin, Haiku.
|
||||
|
@ -5627,6 +5670,7 @@ Nonexistent directories are removed from spec."
|
|||
;; - 8 KiB on HP-UX, Plan9.
|
||||
;; - 10 KiB on IRIX.
|
||||
;; - 32 KiB on AIX, Minix.
|
||||
;; - `undefined' on QNX.
|
||||
;; [1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
|
||||
;; [2] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
|
||||
;; See Bug#65324.
|
||||
|
@ -5634,11 +5678,13 @@ Nonexistent directories are removed from spec."
|
|||
(defun tramp-get-remote-pipe-buf (vec)
|
||||
"Return PIPE_BUF config from the remote side."
|
||||
(with-tramp-connection-property vec "pipe-buf"
|
||||
(tramp-send-command-and-read
|
||||
vec
|
||||
(format "getconf PIPE_BUF / 2>%s || echo 4096"
|
||||
(tramp-get-remote-null-device vec))
|
||||
'noerror)))
|
||||
(if-let* ((result
|
||||
(tramp-send-command-and-read
|
||||
vec (format "getconf PIPE_BUF / 2>%s"
|
||||
(tramp-get-remote-null-device vec))
|
||||
'noerror))
|
||||
((natnump result)))
|
||||
result 4096)))
|
||||
|
||||
(defun tramp-get-remote-locale (vec)
|
||||
"Determine remote locale, supporting UTF8 if possible."
|
||||
|
@ -5666,7 +5712,7 @@ Nonexistent directories are removed from spec."
|
|||
(dolist (cmd
|
||||
;; Prefer GNU ls on *BSD and macOS.
|
||||
(if (tramp-check-remote-uname vec tramp-bsd-unames)
|
||||
'( "gls" "ls" "gnuls") '("ls" "gnuls" "gls")))
|
||||
'("gls" "ls" "gnuls") '("ls" "gnuls" "gls")))
|
||||
(let ((dl (tramp-get-remote-path vec))
|
||||
result)
|
||||
(while (and dl (setq result (tramp-find-executable vec cmd dl t t)))
|
||||
|
@ -5903,37 +5949,37 @@ Nonexistent directories are removed from spec."
|
|||
(with-tramp-connection-property vec "awk"
|
||||
(tramp-message vec 5 "Finding a suitable `awk' command")
|
||||
(or (tramp-find-executable vec "awk" (tramp-get-remote-path vec))
|
||||
(let* ((busybox (tramp-get-remote-busybox vec))
|
||||
(command (format "%s %s" busybox "awk")))
|
||||
(and busybox
|
||||
(tramp-send-command-and-check
|
||||
vec (concat command " {} <" (tramp-get-remote-null-device vec)))
|
||||
command)))))
|
||||
(when-let*
|
||||
((busybox (tramp-get-remote-busybox vec))
|
||||
(command (format "%s %s" busybox "awk"))
|
||||
((tramp-send-command-and-check
|
||||
vec (concat command " {} <" (tramp-get-remote-null-device vec)))))
|
||||
command))))
|
||||
|
||||
(defun tramp-get-remote-hexdump (vec)
|
||||
"Determine remote `hexdump' command."
|
||||
(with-tramp-connection-property vec "hexdump"
|
||||
(tramp-message vec 5 "Finding a suitable `hexdump' command")
|
||||
(or (tramp-find-executable vec "hexdump" (tramp-get-remote-path vec))
|
||||
(let* ((busybox (tramp-get-remote-busybox vec))
|
||||
(command (format "%s %s" busybox "hexdump")))
|
||||
(and busybox
|
||||
(tramp-send-command-and-check
|
||||
vec (concat command " <" (tramp-get-remote-null-device vec)))
|
||||
command)))))
|
||||
(when-let*
|
||||
((busybox (tramp-get-remote-busybox vec))
|
||||
(command (format "%s %s" busybox "hexdump"))
|
||||
((tramp-send-command-and-check
|
||||
vec (concat command " <" (tramp-get-remote-null-device vec)))))
|
||||
command))))
|
||||
|
||||
(defun tramp-get-remote-od (vec)
|
||||
"Determine remote `od' command."
|
||||
(with-tramp-connection-property vec "od"
|
||||
(tramp-message vec 5 "Finding a suitable `od' command")
|
||||
(or (tramp-find-executable vec "od" (tramp-get-remote-path vec))
|
||||
(let* ((busybox (tramp-get-remote-busybox vec))
|
||||
(command (format "%s %s" busybox "od")))
|
||||
(and busybox
|
||||
(tramp-send-command-and-check
|
||||
vec
|
||||
(concat command " -A n <" (tramp-get-remote-null-device vec)))
|
||||
command)))))
|
||||
(when-let*
|
||||
((busybox (tramp-get-remote-busybox vec))
|
||||
(command (format "%s %s" busybox "od"))
|
||||
((tramp-send-command-and-check
|
||||
vec
|
||||
(concat command " -A n <" (tramp-get-remote-null-device vec)))))
|
||||
command))))
|
||||
|
||||
(defun tramp-get-remote-chmod-h (vec)
|
||||
"Check whether remote `chmod' supports nofollow argument."
|
||||
|
|
|
@ -114,6 +114,7 @@ this variable \"client min protocol=NT1\"."
|
|||
"Read from server failed, maybe it closed the connection"
|
||||
"Call timed out: server did not respond"
|
||||
(: (+ (not blank)) ": command not found")
|
||||
(: (+ (not blank)) " does not exist")
|
||||
"Server doesn't support UNIX CIFS calls"
|
||||
(| ;; Samba.
|
||||
"ERRDOS"
|
||||
|
@ -340,15 +341,15 @@ This can be used to disable echo etc."
|
|||
;;;###tramp-autoload
|
||||
(defsubst tramp-smb-file-name-p (vec-or-filename)
|
||||
"Check if it's a VEC-OR-FILENAME for SMB servers."
|
||||
(when-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename)))
|
||||
(string= (tramp-file-name-method vec) tramp-smb-method)))
|
||||
(and-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename))
|
||||
((string= (tramp-file-name-method vec) tramp-smb-method)))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defun tramp-smb-file-name-handler (operation &rest args)
|
||||
"Invoke the SMB related OPERATION and ARGS.
|
||||
First arg specifies the OPERATION, second arg is a list of
|
||||
arguments to pass to the OPERATION."
|
||||
(if-let ((fn (assoc operation tramp-smb-file-name-handler-alist)))
|
||||
(if-let* ((fn (assoc operation tramp-smb-file-name-handler-alist)))
|
||||
(prog1 (save-match-data (apply (cdr fn) args))
|
||||
(setq tramp-debug-message-fnh-function (cdr fn)))
|
||||
(prog1 (tramp-run-real-handler operation args)
|
||||
|
@ -428,9 +429,6 @@ arguments to pass to the OPERATION."
|
|||
(t2 (tramp-tramp-file-p newname))
|
||||
target)
|
||||
(with-parsed-tramp-file-name (if t1 dirname newname) nil
|
||||
(unless (file-exists-p dirname)
|
||||
(tramp-error v 'file-missing dirname))
|
||||
|
||||
;; `copy-directory-create-symlink' exists since Emacs 28.1.
|
||||
(if (and (bound-and-true-p copy-directory-create-symlink)
|
||||
(setq target (file-symlink-p dirname))
|
||||
|
@ -600,66 +598,63 @@ KEEP-DATE has no effect in case NEWNAME resides on an SMB server.
|
|||
PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
||||
(setq filename (expand-file-name filename)
|
||||
newname (expand-file-name newname))
|
||||
(with-tramp-progress-reporter
|
||||
(tramp-dissect-file-name
|
||||
(if (tramp-tramp-file-p filename) filename newname))
|
||||
0 (format "Copying %s to %s" filename newname)
|
||||
|
||||
(if (file-directory-p filename)
|
||||
(copy-directory filename newname keep-date 'parents 'copy-contents)
|
||||
(with-parsed-tramp-file-name
|
||||
(if (tramp-tramp-file-p filename) filename newname) nil
|
||||
(with-tramp-progress-reporter
|
||||
v 0 (format "Copying %s to %s" filename newname)
|
||||
|
||||
(unless (file-exists-p filename)
|
||||
(tramp-error
|
||||
(tramp-dissect-file-name
|
||||
(if (tramp-tramp-file-p filename) filename newname))
|
||||
'file-missing filename))
|
||||
(if (file-directory-p filename)
|
||||
(copy-directory filename newname keep-date 'parents 'copy-contents)
|
||||
|
||||
;; `file-local-copy' returns a file name also for a local file
|
||||
;; with `jka-compr-handler', so we cannot trust its result as
|
||||
;; indication for a remote file name.
|
||||
(if-let ((tmpfile
|
||||
(and (tramp-tramp-file-p filename) (file-local-copy filename))))
|
||||
;; Remote filename.
|
||||
(condition-case err
|
||||
(rename-file tmpfile newname ok-if-already-exists)
|
||||
((error quit)
|
||||
(delete-file tmpfile)
|
||||
(signal (car err) (cdr err))))
|
||||
(tramp-barf-if-file-missing v filename
|
||||
;; `file-local-copy' returns a file name also for a local
|
||||
;; file with `jka-compr-handler', so we cannot trust its
|
||||
;; result as indication for a remote file name.
|
||||
(if-let* ((tmpfile
|
||||
(and (tramp-tramp-file-p filename)
|
||||
(file-local-copy filename))))
|
||||
;; Remote filename.
|
||||
(condition-case err
|
||||
(rename-file tmpfile newname ok-if-already-exists)
|
||||
((error quit)
|
||||
(delete-file tmpfile)
|
||||
(signal (car err) (cdr err))))
|
||||
|
||||
;; Remote newname.
|
||||
(when (and (file-directory-p newname)
|
||||
(directory-name-p newname))
|
||||
(setq newname
|
||||
(expand-file-name (file-name-nondirectory filename) newname)))
|
||||
;; Remote newname.
|
||||
(when (and (file-directory-p newname)
|
||||
(directory-name-p newname))
|
||||
(setq newname
|
||||
(expand-file-name
|
||||
(file-name-nondirectory filename) newname)))
|
||||
|
||||
(with-parsed-tramp-file-name newname nil
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
|
||||
(unless (tramp-smb-get-share v)
|
||||
(tramp-error
|
||||
v 'file-error "Target `%s' must contain a share name" newname))
|
||||
(unless (tramp-smb-send-command
|
||||
v (format "put %s %s"
|
||||
(tramp-smb-shell-quote-argument filename)
|
||||
(tramp-smb-shell-quote-localname v)))
|
||||
(tramp-error
|
||||
v 'file-error "Cannot copy `%s' to `%s'" filename newname))
|
||||
(unless (tramp-smb-get-share v)
|
||||
(tramp-error
|
||||
v 'file-error "Target `%s' must contain a share name" newname))
|
||||
(unless (tramp-smb-send-command
|
||||
v (format "put %s %s"
|
||||
(tramp-smb-shell-quote-argument filename)
|
||||
(tramp-smb-shell-quote-localname v)))
|
||||
(tramp-error
|
||||
v 'file-error "Cannot copy `%s' to `%s'" filename newname))
|
||||
|
||||
;; When newname did exist, we have wrong cached values.
|
||||
(when (tramp-tramp-file-p newname)
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(tramp-flush-file-properties v2 v2-localname))))))
|
||||
;; When newname did exist, we have wrong cached values.
|
||||
(when (tramp-tramp-file-p newname)
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(tramp-flush-file-properties v2 v2-localname))))))
|
||||
|
||||
;; KEEP-DATE handling.
|
||||
(when keep-date
|
||||
(tramp-compat-set-file-times
|
||||
newname
|
||||
(file-attribute-modification-time (file-attributes filename))
|
||||
(unless ok-if-already-exists 'nofollow)))))
|
||||
;; KEEP-DATE handling.
|
||||
(when keep-date
|
||||
(tramp-compat-set-file-times
|
||||
newname
|
||||
(file-attribute-modification-time (file-attributes filename))
|
||||
(unless ok-if-already-exists 'nofollow))))))
|
||||
|
||||
(defun tramp-smb-handle-delete-directory (directory &optional recursive trash)
|
||||
"Like `delete-directory' for Tramp files."
|
||||
|
@ -741,7 +736,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
|||
(tramp-error v 'file-error "Cannot expand tilde in file `%s'" name))
|
||||
(unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
|
||||
(setq localname (concat "/" localname)))
|
||||
;; Do not keep "/..".
|
||||
;; Do not keep "/..".
|
||||
(when (string-match-p (rx bos "/" (** 1 2 ".") eos) localname)
|
||||
(setq localname "/"))
|
||||
;; Do normal `expand-file-name' (this does "/./" and "/../"),
|
||||
|
@ -769,7 +764,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
|||
(forward-line)
|
||||
(delete-region (point-min) (point)))
|
||||
(while (and (not (eobp)) (looking-at-p (rx bol (+ nonl) ":" (+ nonl))))
|
||||
(forward-line))
|
||||
(forward-line))
|
||||
(delete-region (point) (point-max))
|
||||
(throw 'tramp-action 'ok))))
|
||||
|
||||
|
@ -865,7 +860,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
|||
"Implement `file-attributes' for Tramp files using `stat' command."
|
||||
(tramp-message
|
||||
vec 5 "file attributes with stat: %s" (tramp-file-name-localname vec))
|
||||
(let* (size id link uid gid atime mtime ctime mode inode)
|
||||
(let (size id link uid gid atime mtime ctime mode inode)
|
||||
(when (tramp-smb-send-command
|
||||
vec (format "stat %s" (tramp-smb-shell-quote-localname vec)))
|
||||
|
||||
|
@ -1311,46 +1306,45 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
|||
|
||||
(with-parsed-tramp-file-name
|
||||
(if (tramp-tramp-file-p filename) filename newname) nil
|
||||
(unless (file-exists-p filename)
|
||||
(tramp-error v 'file-missing filename))
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
(tramp-barf-if-file-missing v filename
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
|
||||
(with-tramp-progress-reporter
|
||||
v 0 (format "Renaming %s to %s" filename newname)
|
||||
(with-tramp-progress-reporter
|
||||
v 0 (format "Renaming %s to %s" filename newname)
|
||||
|
||||
(if (and (not (file-exists-p newname))
|
||||
(tramp-equal-remote filename newname)
|
||||
(string-equal
|
||||
(tramp-smb-get-share (tramp-dissect-file-name filename))
|
||||
(tramp-smb-get-share (tramp-dissect-file-name newname))))
|
||||
;; We can rename directly.
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(if (and (not (file-exists-p newname))
|
||||
(tramp-equal-remote filename newname)
|
||||
(string-equal
|
||||
(tramp-smb-get-share (tramp-dissect-file-name filename))
|
||||
(tramp-smb-get-share (tramp-dissect-file-name newname))))
|
||||
;; We can rename directly.
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
|
||||
;; We must also flush the cache of the directory, because
|
||||
;; `file-attributes' reads the values from there.
|
||||
(tramp-flush-file-properties v1 v1-localname)
|
||||
(tramp-flush-file-properties v2 v2-localname)
|
||||
(unless (tramp-smb-get-share v2)
|
||||
(tramp-error
|
||||
v2 'file-error
|
||||
"Target `%s' must contain a share name" newname))
|
||||
(unless (tramp-smb-send-command
|
||||
v2 (format "rename %s %s"
|
||||
(tramp-smb-shell-quote-localname v1)
|
||||
(tramp-smb-shell-quote-localname v2)))
|
||||
(tramp-error v2 'file-error "Cannot rename `%s'" filename))))
|
||||
;; We must also flush the cache of the directory, because
|
||||
;; `file-attributes' reads the values from there.
|
||||
(tramp-flush-file-properties v1 v1-localname)
|
||||
(tramp-flush-file-properties v2 v2-localname)
|
||||
(unless (tramp-smb-get-share v2)
|
||||
(tramp-error
|
||||
v2 'file-error
|
||||
"Target `%s' must contain a share name" newname))
|
||||
(unless (tramp-smb-send-command
|
||||
v2 (format "rename %s %s"
|
||||
(tramp-smb-shell-quote-localname v1)
|
||||
(tramp-smb-shell-quote-localname v2)))
|
||||
(tramp-error v2 'file-error "Cannot rename `%s'" filename))))
|
||||
|
||||
;; We must rename via copy.
|
||||
(copy-file
|
||||
filename newname ok-if-already-exists 'keep-time 'preserve-uid-gid)
|
||||
(if (file-directory-p filename)
|
||||
(delete-directory filename 'recursive)
|
||||
(delete-file filename))))))
|
||||
;; We must rename via copy.
|
||||
(copy-file
|
||||
filename newname ok-if-already-exists 'keep-time 'preserve-uid-gid)
|
||||
(if (file-directory-p filename)
|
||||
(delete-directory filename 'recursive)
|
||||
(delete-file filename)))))))
|
||||
|
||||
(defun tramp-smb-action-set-acl (proc vec)
|
||||
"Set ACL data."
|
||||
|
|
|
@ -169,15 +169,15 @@ Operations not mentioned here will be handled by the default Emacs primitives.")
|
|||
;;;###tramp-autoload
|
||||
(defsubst tramp-sshfs-file-name-p (vec-or-filename)
|
||||
"Check if it's a VEC-OR-FILENAME for sshfs."
|
||||
(when-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename)))
|
||||
(string= (tramp-file-name-method vec) tramp-sshfs-method)))
|
||||
(and-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename))
|
||||
((string= (tramp-file-name-method vec) tramp-sshfs-method)))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defun tramp-sshfs-file-name-handler (operation &rest args)
|
||||
"Invoke the sshfs handler for OPERATION and ARGS.
|
||||
First arg specifies the OPERATION, second arg is a list of
|
||||
arguments to pass to the OPERATION."
|
||||
(if-let ((fn (assoc operation tramp-sshfs-file-name-handler-alist)))
|
||||
(if-let* ((fn (assoc operation tramp-sshfs-file-name-handler-alist)))
|
||||
(prog1 (save-match-data (apply (cdr fn) args))
|
||||
(setq tramp-debug-message-fnh-function (cdr fn)))
|
||||
(prog1 (tramp-run-real-handler operation args)
|
||||
|
@ -250,6 +250,9 @@ 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."
|
||||
;; STDERR is not impelmemted.
|
||||
(when (consp destination)
|
||||
(setcdr destination `(,tramp-cache-undefined)))
|
||||
(tramp-skeleton-process-file program infile destination display args
|
||||
(let ((coding-system-for-read 'utf-8-dos)) ; Is this correct?
|
||||
|
||||
|
@ -259,25 +262,18 @@ arguments to pass to the OPERATION."
|
|||
(tramp-unquote-shell-quote-argument localname)
|
||||
(mapconcat #'tramp-shell-quote-argument (cons program args) " ")))
|
||||
(when input (setq command (format "%s <%s" command input)))
|
||||
(when stderr (setq command (format "%s 2>%s" command stderr)))
|
||||
|
||||
(unwind-protect
|
||||
(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))))))
|
||||
(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))))))
|
||||
|
||||
(defun tramp-sshfs-handle-rename-file
|
||||
(filename newname &optional ok-if-already-exists)
|
||||
|
|
|
@ -161,15 +161,15 @@ See `tramp-actions-before-shell' for more info.")
|
|||
;;;###tramp-autoload
|
||||
(defsubst tramp-sudoedit-file-name-p (vec-or-filename)
|
||||
"Check if it's a VEC-OR-FILENAME for SUDOEDIT."
|
||||
(when-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename)))
|
||||
(string= (tramp-file-name-method vec) tramp-sudoedit-method)))
|
||||
(and-let* ((vec (tramp-ensure-dissected-file-name vec-or-filename))
|
||||
((string= (tramp-file-name-method vec) tramp-sudoedit-method)))))
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defun tramp-sudoedit-file-name-handler (operation &rest args)
|
||||
"Invoke the SUDOEDIT handler for OPERATION and ARGS.
|
||||
First arg specifies the OPERATION, second arg is a list of
|
||||
arguments to pass to the OPERATION."
|
||||
(if-let ((fn (assoc operation tramp-sudoedit-file-name-handler-alist)))
|
||||
(if-let* ((fn (assoc operation tramp-sudoedit-file-name-handler-alist)))
|
||||
(prog1 (save-match-data (apply (cdr fn) args))
|
||||
(setq tramp-debug-message-fnh-function (cdr fn)))
|
||||
(prog1 (tramp-run-real-handler operation args)
|
||||
|
@ -244,84 +244,88 @@ absolute file names."
|
|||
(unless (memq op '(copy rename))
|
||||
(error "Unknown operation `%s', must be `copy' or `rename'" op))
|
||||
|
||||
(setq filename (file-truename filename))
|
||||
(if (file-directory-p filename)
|
||||
(progn
|
||||
(copy-directory filename newname keep-date t)
|
||||
(when (eq op 'rename) (delete-directory filename 'recursive)))
|
||||
(if (file-symlink-p filename)
|
||||
(progn
|
||||
(make-symbolic-link
|
||||
(file-symlink-p filename) newname ok-if-already-exists)
|
||||
(when (eq op 'rename) (delete-file filename)))
|
||||
|
||||
;; FIXME: This should be optimized. Computing `file-attributes'
|
||||
;; checks already, whether the file exists.
|
||||
(let ((t1 (tramp-sudoedit-file-name-p filename))
|
||||
(t2 (tramp-sudoedit-file-name-p newname))
|
||||
(file-times (file-attribute-modification-time
|
||||
(file-attributes filename)))
|
||||
(file-modes (tramp-default-file-modes filename))
|
||||
(attributes (and preserve-extended-attributes
|
||||
(file-extended-attributes filename)))
|
||||
(sudoedit-operation
|
||||
(cond
|
||||
((and (eq op 'copy) preserve-uid-gid) '("cp" "-f" "-p"))
|
||||
((eq op 'copy) '("cp" "-f"))
|
||||
((eq op 'rename) '("mv" "-f"))))
|
||||
(msg-operation (if (eq op 'copy) "Copying" "Renaming")))
|
||||
;; FIXME: This should be optimized. Computing `file-attributes'
|
||||
;; checks already, whether the file exists.
|
||||
(let ((t1 (tramp-sudoedit-file-name-p filename))
|
||||
(t2 (tramp-sudoedit-file-name-p newname))
|
||||
(file-times (file-attribute-modification-time
|
||||
(file-attributes filename)))
|
||||
(file-modes (tramp-default-file-modes filename))
|
||||
(attributes (and preserve-extended-attributes
|
||||
(file-extended-attributes filename)))
|
||||
(sudoedit-operation
|
||||
(cond
|
||||
((and (eq op 'copy) preserve-uid-gid) '("cp" "-f" "-p"))
|
||||
((eq op 'copy) '("cp" "-f"))
|
||||
((eq op 'rename) '("mv" "-f"))))
|
||||
(msg-operation (if (eq op 'copy) "Copying" "Renaming")))
|
||||
|
||||
(with-parsed-tramp-file-name (if t1 filename newname) nil
|
||||
(tramp-barf-if-file-missing v filename
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
(with-parsed-tramp-file-name (if t1 filename newname) nil
|
||||
(tramp-barf-if-file-missing v filename
|
||||
(when (and (not ok-if-already-exists) (file-exists-p newname))
|
||||
(tramp-error v 'file-already-exists newname))
|
||||
(when (and (file-directory-p newname)
|
||||
(not (directory-name-p newname)))
|
||||
(tramp-error v 'file-error "File is a directory %s" newname))
|
||||
|
||||
(if (or (and (tramp-tramp-file-p filename) (not t1))
|
||||
(and (tramp-tramp-file-p newname) (not t2)))
|
||||
;; We cannot copy or rename directly.
|
||||
(let ((tmpfile (tramp-compat-make-temp-file filename)))
|
||||
(if (eq op 'copy)
|
||||
(copy-file filename tmpfile t)
|
||||
(rename-file filename tmpfile t))
|
||||
(rename-file tmpfile newname ok-if-already-exists))
|
||||
(if (or (and (tramp-tramp-file-p filename) (not t1))
|
||||
(and (tramp-tramp-file-p newname) (not t2)))
|
||||
;; We cannot copy or rename directly.
|
||||
(let ((tmpfile (tramp-compat-make-temp-file filename)))
|
||||
(if (eq op 'copy)
|
||||
(copy-file filename tmpfile t)
|
||||
(rename-file filename tmpfile t))
|
||||
(rename-file tmpfile newname ok-if-already-exists))
|
||||
|
||||
;; Direct action.
|
||||
(with-tramp-progress-reporter
|
||||
v 0 (format "%s %s to %s" msg-operation filename newname)
|
||||
(unless (tramp-sudoedit-send-command
|
||||
v sudoedit-operation
|
||||
(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))))
|
||||
;; Direct action.
|
||||
(with-tramp-progress-reporter
|
||||
v 0 (format "%s %s to %s" msg-operation filename newname)
|
||||
(unless (tramp-sudoedit-send-command
|
||||
v sudoedit-operation
|
||||
(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))))
|
||||
|
||||
;; When `newname' is local, we must change the ownership to
|
||||
;; the local user.
|
||||
(unless (tramp-tramp-file-p newname)
|
||||
(tramp-set-file-uid-gid
|
||||
(concat (file-remote-p filename) newname)
|
||||
(tramp-get-local-uid 'integer)
|
||||
(tramp-get-local-gid 'integer)))
|
||||
;; When `newname' is local, we must change the ownership
|
||||
;; to the local user.
|
||||
(unless (tramp-tramp-file-p newname)
|
||||
(tramp-set-file-uid-gid
|
||||
(concat (file-remote-p filename) newname)
|
||||
(tramp-get-local-uid 'integer)
|
||||
(tramp-get-local-gid 'integer)))
|
||||
|
||||
;; Set the time and mode. Mask possible errors.
|
||||
(when keep-date
|
||||
(ignore-errors
|
||||
(tramp-compat-set-file-times
|
||||
newname file-times (unless ok-if-already-exists 'nofollow))
|
||||
(set-file-modes newname file-modes)))
|
||||
;; Set the time and mode. Mask possible errors.
|
||||
(when keep-date
|
||||
(ignore-errors
|
||||
(tramp-compat-set-file-times
|
||||
newname file-times (unless ok-if-already-exists 'nofollow))
|
||||
(set-file-modes newname file-modes)))
|
||||
|
||||
;; Handle `preserve-extended-attributes'. We ignore possible
|
||||
;; errors, because ACL strings could be incompatible.
|
||||
(when attributes
|
||||
(ignore-errors
|
||||
(set-file-extended-attributes newname attributes)))
|
||||
;; Handle `preserve-extended-attributes'. We ignore possible
|
||||
;; errors, because ACL strings could be incompatible.
|
||||
(when attributes
|
||||
(ignore-errors
|
||||
(set-file-extended-attributes newname attributes)))
|
||||
|
||||
(when (and t1 (eq op 'rename))
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(tramp-flush-file-properties v1 v1-localname)))
|
||||
(when (and t1 (eq op 'rename))
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(tramp-flush-file-properties v1 v1-localname)))
|
||||
|
||||
(when t2
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(tramp-flush-file-properties v2 v2-localname))))))))
|
||||
(when t2
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(tramp-flush-file-properties v2 v2-localname)))))))))
|
||||
|
||||
(defun tramp-sudoedit-handle-copy-file
|
||||
(filename newname &optional ok-if-already-exists keep-date
|
||||
|
@ -785,7 +789,7 @@ in case of error, t otherwise."
|
|||
;; Avoid process status message in output buffer.
|
||||
(set-process-sentinel p #'ignore)
|
||||
(tramp-post-process-creation p vec)
|
||||
(tramp-set-connection-property p "password-vector" tramp-sudoedit-null-hop)
|
||||
(tramp-set-connection-property p "pw-vector" tramp-sudoedit-null-hop)
|
||||
(tramp-process-actions p vec nil tramp-sudoedit-sudo-actions)
|
||||
(tramp-message vec 6 "%s\n%s" (process-exit-status p) (buffer-string))
|
||||
(prog1
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@
|
|||
;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
|
||||
;; Keywords: comm, processes
|
||||
;; Package: tramp
|
||||
;; Version: 2.7.1.30.1
|
||||
;; Version: 2.7.3-pre
|
||||
;; Package-Requires: ((emacs "27.1"))
|
||||
;; Package-Type: multi
|
||||
;; URL: https://www.gnu.org/software/tramp/
|
||||
|
@ -40,14 +40,13 @@
|
|||
;; ./configure" to change them.
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defconst tramp-version "2.7.1.30.1"
|
||||
(defconst tramp-version "2.7.3-pre"
|
||||
"This version of Tramp.")
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defconst tramp-bug-report-address "tramp-devel@gnu.org"
|
||||
"Email address to send bug reports to.")
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defconst tramp-repository-branch
|
||||
(ignore-errors
|
||||
;; Suppress message from `emacs-repository-get-branch'. We must
|
||||
|
@ -61,7 +60,6 @@
|
|||
(emacs-repository-get-branch dir))))
|
||||
"The repository branch of the Tramp sources.")
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defconst tramp-repository-version
|
||||
(ignore-errors
|
||||
;; Suppress message from `emacs-repository-get-version'. We must
|
||||
|
@ -78,7 +76,7 @@
|
|||
;; Check for Emacs version.
|
||||
(let ((x (if (not (string-version-lessp emacs-version "27.1"))
|
||||
"ok"
|
||||
(format "Tramp 2.7.1.30.1 is not fit for %s"
|
||||
(format "Tramp 2.7.3-pre is not fit for %s"
|
||||
(replace-regexp-in-string "\n" "" (emacs-version))))))
|
||||
(unless (string-equal "ok" x) (error "%s" x)))
|
||||
|
||||
|
|
|
@ -179,7 +179,9 @@ A resource file is in the resource directory as per
|
|||
(tramp-dissect-file-name ert-remote-temporary-file-directory))
|
||||
"The used `tramp-file-name' structure.")
|
||||
|
||||
(setq auth-source-save-behavior nil
|
||||
(setq auth-source-cache-expiry nil
|
||||
auth-source-save-behavior nil
|
||||
ert-batch-backtrace-right-margin nil
|
||||
password-cache-expiry nil
|
||||
remote-file-name-inhibit-cache nil
|
||||
tramp-allow-unsafe-temporary-files t
|
||||
|
@ -187,7 +189,8 @@ A resource file is in the resource directory as per
|
|||
tramp-copy-size-limit nil
|
||||
tramp-error-show-message-timeout nil
|
||||
tramp-persistency-file-name nil
|
||||
tramp-verbose 0)
|
||||
tramp-verbose 0
|
||||
vc-handled-backends (unless noninteractive vc-handled-backends))
|
||||
|
||||
(defvar tramp--test-enabled-checked nil
|
||||
"Cached result of `tramp--test-enabled'.
|
||||
|
@ -209,6 +212,7 @@ being the result.")
|
|||
(when (cdr tramp--test-enabled-checked)
|
||||
;; Remove old test files.
|
||||
(dolist (dir `(,temporary-file-directory
|
||||
,tramp-compat-temporary-file-directory
|
||||
,ert-remote-temporary-file-directory))
|
||||
(dolist (file (directory-files dir 'full (rx bos (? ".#") "tramp-test")))
|
||||
(ignore-errors
|
||||
|
@ -217,7 +221,7 @@ being the result.")
|
|||
(delete-file file)))))
|
||||
;; Cleanup connection.
|
||||
(ignore-errors
|
||||
(tramp-cleanup-connection tramp-test-vec nil 'keep-password)))
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)))
|
||||
|
||||
;; Return result.
|
||||
(cdr tramp--test-enabled-checked))
|
||||
|
@ -2176,7 +2180,7 @@ is greater than 10.
|
|||
(when (assoc m tramp-methods)
|
||||
(let (tramp-connection-properties tramp-default-proxies-alist)
|
||||
(ignore-errors
|
||||
(tramp-cleanup-connection tramp-test-vec nil 'keep-password))
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password))
|
||||
;; Single hop. The host name must match `tramp-local-host-regexp'.
|
||||
(should-error
|
||||
(find-file (format "/%s:foo:" m))
|
||||
|
@ -2882,7 +2886,9 @@ This checks also `file-name-as-directory', `file-name-directory',
|
|||
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
|
||||
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
|
||||
(tmp-name2 (tramp--test-make-temp-name nil quoted))
|
||||
(tmp-name3 (tramp--test-make-temp-name 'local quoted)))
|
||||
(tmp-name3 (tramp--test-make-temp-name 'local quoted))
|
||||
(tmp-name4
|
||||
(file-name-nondirectory (tramp--test-make-temp-name 'local quoted))))
|
||||
(dolist (source-target
|
||||
`(;; Copy on remote side.
|
||||
(,tmp-name1 . ,tmp-name2)
|
||||
|
@ -2890,8 +2896,12 @@ This checks also `file-name-as-directory', `file-name-directory',
|
|||
(,tmp-name1 . ,tmp-name3)
|
||||
;; Copy from local side to remote side.
|
||||
(,tmp-name3 . ,tmp-name1)))
|
||||
(let ((source (car source-target))
|
||||
(target (cdr source-target)))
|
||||
(let* ((source (car source-target))
|
||||
(source-link
|
||||
(expand-file-name tmp-name4 (file-name-directory source)))
|
||||
(target (cdr source-target))
|
||||
(target-link
|
||||
(expand-file-name tmp-name4 (file-name-directory target))))
|
||||
|
||||
;; Copy simple file.
|
||||
(unwind-protect
|
||||
|
@ -2916,6 +2926,26 @@ This checks also `file-name-as-directory', `file-name-directory',
|
|||
(ignore-errors (delete-file source))
|
||||
(ignore-errors (delete-file target)))
|
||||
|
||||
;; Copy symlinked file.
|
||||
(unwind-protect
|
||||
(tramp--test-ignore-make-symbolic-link-error
|
||||
(write-region "foo" nil source-link)
|
||||
(should (file-exists-p source-link))
|
||||
(make-symbolic-link tmp-name4 source)
|
||||
(should (file-exists-p source))
|
||||
(should (string-equal (file-symlink-p source) tmp-name4))
|
||||
(copy-file source target)
|
||||
;; Some backends like tramp-gvfs.el do not create the
|
||||
;; link on the target.
|
||||
(when (file-symlink-p target)
|
||||
(should (string-equal (file-symlink-p target) tmp-name4))))
|
||||
|
||||
;; Cleanup.
|
||||
(ignore-errors (delete-file source))
|
||||
(ignore-errors (delete-file source-link))
|
||||
(ignore-errors (delete-file target))
|
||||
(ignore-errors (delete-file target-link)))
|
||||
|
||||
;; Copy file to directory.
|
||||
(unwind-protect
|
||||
;; This doesn't work on FTP.
|
||||
|
@ -2991,7 +3021,9 @@ This checks also `file-name-as-directory', `file-name-directory',
|
|||
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
|
||||
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
|
||||
(tmp-name2 (tramp--test-make-temp-name nil quoted))
|
||||
(tmp-name3 (tramp--test-make-temp-name 'local quoted)))
|
||||
(tmp-name3 (tramp--test-make-temp-name 'local quoted))
|
||||
(tmp-name4
|
||||
(file-name-nondirectory (tramp--test-make-temp-name 'local quoted))))
|
||||
(dolist (source-target
|
||||
`(;; Rename on remote side.
|
||||
(,tmp-name1 . ,tmp-name2)
|
||||
|
@ -2999,8 +3031,12 @@ This checks also `file-name-as-directory', `file-name-directory',
|
|||
(,tmp-name1 . ,tmp-name3)
|
||||
;; Rename from local side to remote side.
|
||||
(,tmp-name3 . ,tmp-name1)))
|
||||
(let ((source (car source-target))
|
||||
(target (cdr source-target)))
|
||||
(let* ((source (car source-target))
|
||||
(source-link
|
||||
(expand-file-name tmp-name4 (file-name-directory source)))
|
||||
(target (cdr source-target))
|
||||
(target-link
|
||||
(expand-file-name tmp-name4 (file-name-directory target))))
|
||||
|
||||
;; Rename simple file.
|
||||
(unwind-protect
|
||||
|
@ -3029,6 +3065,27 @@ This checks also `file-name-as-directory', `file-name-directory',
|
|||
(ignore-errors (delete-file source))
|
||||
(ignore-errors (delete-file target)))
|
||||
|
||||
;; Rename symlinked file.
|
||||
(unwind-protect
|
||||
(tramp--test-ignore-make-symbolic-link-error
|
||||
(write-region "foo" nil source-link)
|
||||
(should (file-exists-p source-link))
|
||||
(make-symbolic-link tmp-name4 source)
|
||||
(should (file-exists-p source))
|
||||
(should (string-equal (file-symlink-p source) tmp-name4))
|
||||
(rename-file source target)
|
||||
(should-not (file-exists-p source))
|
||||
;; Some backends like tramp-gvfs.el do not create the
|
||||
;; link on the target.
|
||||
(when (file-symlink-p target)
|
||||
(should (string-equal (file-symlink-p target) tmp-name4))))
|
||||
|
||||
;; Cleanup.
|
||||
(ignore-errors (delete-file source))
|
||||
(ignore-errors (delete-file source-link))
|
||||
(ignore-errors (delete-file target))
|
||||
(ignore-errors (delete-file target-link)))
|
||||
|
||||
;; Rename file to directory.
|
||||
(unwind-protect
|
||||
(progn
|
||||
|
@ -3809,6 +3866,7 @@ This tests also `access-file', `file-readable-p',
|
|||
(should (stringp (file-attribute-user-id attr)))
|
||||
(should (stringp (file-attribute-group-id attr)))
|
||||
|
||||
;; Symbolic links.
|
||||
(tramp--test-ignore-make-symbolic-link-error
|
||||
(should-error
|
||||
(access-file tmp-name2 "error")
|
||||
|
@ -3828,7 +3886,26 @@ This tests also `access-file', `file-readable-p',
|
|||
(if quoted #'file-name-quote #'identity)
|
||||
(file-attribute-type attr))
|
||||
(file-remote-p (file-truename tmp-name1) 'localname)))
|
||||
(delete-file tmp-name2))
|
||||
(delete-file tmp-name2)
|
||||
|
||||
;; A non-existent or cyclic link target makes the file
|
||||
;; unaccessible.
|
||||
(dolist (target
|
||||
`("does-not-exist" ,(file-name-nondirectory tmp-name2)))
|
||||
(make-symbolic-link target tmp-name2)
|
||||
(should (file-symlink-p tmp-name2))
|
||||
(should-not (file-exists-p tmp-name2))
|
||||
(should-not (file-directory-p tmp-name2))
|
||||
(should-error
|
||||
(access-file tmp-name2 "error")
|
||||
:type
|
||||
(if (string-equal target "does-not-exist")
|
||||
'file-missing 'file-error))
|
||||
;; `file-ownership-preserved-p' should return t for
|
||||
;; symlinked files to a non-existing or cyclic target.
|
||||
(when test-file-ownership-preserved-p
|
||||
(should (file-ownership-preserved-p tmp-name2 'group)))
|
||||
(delete-file tmp-name2)))
|
||||
|
||||
;; Check, that "//" in symlinks are handled properly.
|
||||
(with-temp-buffer
|
||||
|
@ -3891,12 +3968,12 @@ The test is derived from TEST and COMMAND."
|
|||
(skip-unless (tramp--test-enabled))
|
||||
(skip-unless (tramp--test-sh-p))
|
||||
(skip-unless (tramp-get-remote-stat tramp-test-vec))
|
||||
(if-let ((default-directory ert-remote-temporary-file-directory)
|
||||
(ert-test (ert-get-test ',test))
|
||||
(result (ert-test-most-recent-result ert-test))
|
||||
(tramp-connection-properties
|
||||
(cons '(nil "perl" nil)
|
||||
tramp-connection-properties)))
|
||||
(if-let* ((default-directory ert-remote-temporary-file-directory)
|
||||
(ert-test (ert-get-test ',test))
|
||||
(result (ert-test-most-recent-result ert-test))
|
||||
(tramp-connection-properties
|
||||
(cons '(nil "perl" nil)
|
||||
tramp-connection-properties)))
|
||||
(progn
|
||||
(skip-unless (< (ert-test-result-duration result) 300))
|
||||
(funcall (ert-test-body ert-test)))
|
||||
|
@ -3911,17 +3988,17 @@ The test is derived from TEST and COMMAND."
|
|||
(skip-unless (tramp--test-enabled))
|
||||
(skip-unless (tramp--test-sh-p))
|
||||
(skip-unless (tramp-get-remote-perl tramp-test-vec))
|
||||
(if-let ((default-directory ert-remote-temporary-file-directory)
|
||||
(ert-test (ert-get-test ',test))
|
||||
(result (ert-test-most-recent-result ert-test))
|
||||
(tramp-connection-properties
|
||||
(append
|
||||
'((nil "stat" nil)
|
||||
;; See `tramp-sh-handle-file-truename'.
|
||||
(nil "readlink" nil)
|
||||
;; See `tramp-sh-handle-get-remote-*'.
|
||||
(nil "id" nil))
|
||||
tramp-connection-properties)))
|
||||
(if-let* ((default-directory ert-remote-temporary-file-directory)
|
||||
(ert-test (ert-get-test ',test))
|
||||
(result (ert-test-most-recent-result ert-test))
|
||||
(tramp-connection-properties
|
||||
(append
|
||||
'((nil "stat" nil)
|
||||
;; See `tramp-sh-handle-file-truename'.
|
||||
(nil "readlink" nil)
|
||||
;; See `tramp-sh-handle-get-remote-*'.
|
||||
(nil "id" nil))
|
||||
tramp-connection-properties)))
|
||||
(progn
|
||||
(skip-unless (< (ert-test-result-duration result) 300))
|
||||
(funcall (ert-test-body ert-test)))
|
||||
|
@ -3935,16 +4012,16 @@ The test is derived from TEST and COMMAND."
|
|||
(tramp--test-set-ert-test-documentation ',test "ls")
|
||||
(skip-unless (tramp--test-enabled))
|
||||
(skip-unless (tramp--test-sh-p))
|
||||
(if-let ((default-directory ert-remote-temporary-file-directory)
|
||||
(ert-test (ert-get-test ',test))
|
||||
(result (ert-test-most-recent-result ert-test))
|
||||
(tramp-connection-properties
|
||||
(append
|
||||
'((nil "perl" nil)
|
||||
(nil "stat" nil)
|
||||
;; See `tramp-sh-handle-file-truename'.
|
||||
(nil "readlink" nil))
|
||||
tramp-connection-properties)))
|
||||
(if-let* ((default-directory ert-remote-temporary-file-directory)
|
||||
(ert-test (ert-get-test ',test))
|
||||
(result (ert-test-most-recent-result ert-test))
|
||||
(tramp-connection-properties
|
||||
(append
|
||||
'((nil "perl" nil)
|
||||
(nil "stat" nil)
|
||||
;; See `tramp-sh-handle-file-truename'.
|
||||
(nil "readlink" nil))
|
||||
tramp-connection-properties)))
|
||||
(progn
|
||||
(skip-unless (< (ert-test-result-duration result) 300))
|
||||
(funcall (ert-test-body ert-test)))
|
||||
|
@ -3971,9 +4048,9 @@ The test is derived from TEST and COMMAND."
|
|||
(skip-unless (tramp--test-enabled))
|
||||
(skip-unless
|
||||
(or (tramp--test-adb-p) (tramp--test-sh-p) (tramp--test-sudoedit-p)))
|
||||
(if-let ((default-directory ert-remote-temporary-file-directory)
|
||||
(ert-test (ert-get-test ',test))
|
||||
(result (ert-test-most-recent-result ert-test)))
|
||||
(if-let* ((default-directory ert-remote-temporary-file-directory)
|
||||
(ert-test (ert-get-test ',test))
|
||||
(result (ert-test-most-recent-result ert-test)))
|
||||
(progn
|
||||
(skip-unless (< (ert-test-result-duration result) 300))
|
||||
(let (tramp-use-file-attributes)
|
||||
|
@ -4484,13 +4561,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
|
|||
(should (file-symlink-p tmp-name1))
|
||||
(should (file-symlink-p tmp-name2))
|
||||
(should-not (file-regular-p tmp-name1))
|
||||
(should-not (file-regular-p tmp-name2))
|
||||
(should-error
|
||||
(file-truename tmp-name1)
|
||||
:type 'file-error)
|
||||
(should-error
|
||||
(file-truename tmp-name2)
|
||||
:type 'file-error))))
|
||||
(should-not (file-regular-p tmp-name2)))))
|
||||
|
||||
;; Cleanup.
|
||||
(ignore-errors
|
||||
|
@ -4946,7 +5017,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
|
|||
(ert-deftest tramp-test26-interactive-file-name-completion ()
|
||||
"Check interactive completion with different `completion-styles'."
|
||||
;; Method, user and host name in completion mode.
|
||||
(tramp-cleanup-connection tramp-test-vec nil 'keep-password)
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
|
||||
|
||||
(let ((method (file-remote-p ert-remote-temporary-file-directory 'method))
|
||||
(user (file-remote-p ert-remote-temporary-file-directory 'user))
|
||||
|
@ -5270,19 +5341,20 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
|
|||
;; (delete-file tmp-name)))
|
||||
|
||||
;; Check remote and local STDERR.
|
||||
(dolist (local '(nil t))
|
||||
(setq tmp-name (tramp--test-make-temp-name local quoted))
|
||||
(should-not
|
||||
(zerop
|
||||
(process-file "cat" nil `(t ,tmp-name) nil "/does-not-exist")))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents tmp-name)
|
||||
(should
|
||||
(string-match-p
|
||||
(rx "cat:" (* nonl) " No such file or directory")
|
||||
(buffer-string)))
|
||||
(should-not (get-buffer-window (current-buffer) t))
|
||||
(delete-file tmp-name))))
|
||||
(unless (tramp--test-sshfs-p)
|
||||
(dolist (local '(nil t))
|
||||
(setq tmp-name (tramp--test-make-temp-name local quoted))
|
||||
(should-not
|
||||
(zerop
|
||||
(process-file "cat" nil `(t ,tmp-name) nil "/does-not-exist")))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents tmp-name)
|
||||
(should
|
||||
(string-match-p
|
||||
(rx "cat:" (* nonl) " No such file or directory")
|
||||
(buffer-string)))
|
||||
(should-not (get-buffer-window (current-buffer) t))
|
||||
(delete-file tmp-name)))))
|
||||
|
||||
;; Cleanup.
|
||||
(ignore-errors (kill-buffer buffer))
|
||||
|
@ -5293,8 +5365,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
|
|||
"Timeout handler, reporting a failed test."
|
||||
(interactive)
|
||||
(tramp--test-message "proc: %s" (get-buffer-process (current-buffer)))
|
||||
(when-let ((proc (get-buffer-process (current-buffer)))
|
||||
((processp proc)))
|
||||
(when-let* ((proc (get-buffer-process (current-buffer)))
|
||||
((processp proc)))
|
||||
(tramp--test-message "cmd: %s" (process-command proc)))
|
||||
(tramp--test-message "buf: %s\n%s\n---" (current-buffer) (buffer-string))
|
||||
(ert-fail (format "`%s' timed out" (ert-test-name (ert-running-test)))))
|
||||
|
@ -5477,6 +5549,8 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
|
|||
direct-async-process-profile)
|
||||
connection-local-criteria-alist)))
|
||||
(skip-unless (tramp-direct-async-process-p))
|
||||
(when-let* ((result (ert-test-most-recent-result ert-test)))
|
||||
(skip-unless (< (ert-test-result-duration result) 300)))
|
||||
;; We do expect an established connection already,
|
||||
;; `file-truename' does it by side-effect. Suppress
|
||||
;; `tramp--test-enabled', in order to keep the connection.
|
||||
|
@ -5885,8 +5959,8 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
|
|||
(setq command '("sleep" "100")
|
||||
proc (apply #'start-file-process "test" nil command))
|
||||
(while (accept-process-output proc 0))
|
||||
(when-let ((pid (process-get proc 'remote-pid))
|
||||
(attributes (process-attributes pid)))
|
||||
(when-let* ((pid (process-get proc 'remote-pid))
|
||||
(attributes (process-attributes pid)))
|
||||
;; (tramp--test-message "%s" attributes)
|
||||
(should (equal (cdr (assq 'comm attributes)) (car command)))
|
||||
(should (equal (cdr (assq 'args attributes))
|
||||
|
@ -5903,8 +5977,8 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
|
|||
;; `memory-info' is supported since Emacs 29.1.
|
||||
(skip-unless (tramp--test-emacs29-p))
|
||||
|
||||
(when-let ((default-directory ert-remote-temporary-file-directory)
|
||||
(mi (memory-info)))
|
||||
(when-let* ((default-directory ert-remote-temporary-file-directory)
|
||||
(mi (memory-info)))
|
||||
(should (consp mi))
|
||||
(should (tramp-compat-length= mi 4))
|
||||
(dotimes (i (length mi))
|
||||
|
@ -6015,7 +6089,9 @@ INPUT, if non-nil, is a string sent to the process."
|
|||
|
||||
;; Test `async-shell-command-width'.
|
||||
(when (and (tramp--test-asynchronous-processes-p) (tramp--test-sh-p))
|
||||
(let* ((async-shell-command-width 1024)
|
||||
(let* (;; Since Fedora 41, this seems to be the upper limit. Used
|
||||
;; to be 1024 before.
|
||||
(async-shell-command-width 512)
|
||||
(default-directory ert-remote-temporary-file-directory)
|
||||
(cols (ignore-errors
|
||||
(read (tramp--test-shell-command-to-string-asynchronously
|
||||
|
@ -6536,6 +6612,7 @@ INPUT, if non-nil, is a string sent to the process."
|
|||
(tmp-name1 (tramp--test-make-temp-name nil quoted))
|
||||
(tmp-name2 (expand-file-name "foo" tmp-name1))
|
||||
(tramp-remote-process-environment tramp-remote-process-environment)
|
||||
;; Suppress nasty messages.
|
||||
(inhibit-message t)
|
||||
(vc-handled-backends
|
||||
(cond
|
||||
|
@ -6558,9 +6635,7 @@ INPUT, if non-nil, is a string sent to the process."
|
|||
(tramp-cleanup-connection
|
||||
tramp-test-vec 'keep-debug 'keep-password)
|
||||
'(Bzr))
|
||||
(t nil)))
|
||||
;; Suppress nasty messages.
|
||||
(inhibit-message t))
|
||||
(t nil))))
|
||||
(skip-unless vc-handled-backends)
|
||||
(unless quoted (tramp--test-message "%s" vc-handled-backends))
|
||||
|
||||
|
@ -6907,34 +6982,40 @@ INPUT, if non-nil, is a string sent to the process."
|
|||
(should-not (with-no-warnings (file-locked-p tmp-name1)))
|
||||
|
||||
;; `kill-buffer' removes the lock.
|
||||
(with-no-warnings (lock-file tmp-name1))
|
||||
(should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
|
||||
(with-temp-buffer
|
||||
(set-visited-file-name tmp-name1)
|
||||
(insert "foo")
|
||||
(should (buffer-modified-p))
|
||||
(cl-letf (((symbol-function #'read-from-minibuffer)
|
||||
(lambda (&rest _args) "yes")))
|
||||
(kill-buffer)))
|
||||
(should-not (with-no-warnings (file-locked-p tmp-name1)))
|
||||
;; `kill-buffer--possibly-save' exists since Emacs 29.1.
|
||||
(when (fboundp 'kill-buffer--possibly-save)
|
||||
(with-no-warnings (lock-file tmp-name1))
|
||||
(should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
|
||||
(with-temp-buffer
|
||||
(set-visited-file-name tmp-name1)
|
||||
(insert "foo")
|
||||
(should (buffer-modified-p))
|
||||
;; Modifying `read-from-minibuffer' doesn't work on MS Windows.
|
||||
(cl-letf (((symbol-function #'kill-buffer--possibly-save)
|
||||
#'tramp-compat-always))
|
||||
(kill-buffer)))
|
||||
(should-not (with-no-warnings (file-locked-p tmp-name1))))
|
||||
|
||||
;; `kill-buffer' should not remove the lock when the
|
||||
;; connection is broken. See Bug#61663.
|
||||
(with-no-warnings (lock-file tmp-name1))
|
||||
(should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
|
||||
(with-temp-buffer
|
||||
(set-visited-file-name tmp-name1)
|
||||
(insert "foo")
|
||||
(should (buffer-modified-p))
|
||||
(tramp-cleanup-connection
|
||||
tramp-test-vec 'keep-debug 'keep-password)
|
||||
(cl-letf (((symbol-function #'read-from-minibuffer)
|
||||
(lambda (&rest _args) "yes")))
|
||||
(kill-buffer)))
|
||||
;; A new connection changes process id, and also the
|
||||
;; lock file contents. But it still exists.
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
|
||||
(should (stringp (with-no-warnings (file-locked-p tmp-name1))))
|
||||
;; `kill-buffer--possibly-save' exists since Emacs 29.1.
|
||||
(when (fboundp 'kill-buffer--possibly-save)
|
||||
(with-no-warnings (lock-file tmp-name1))
|
||||
(should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
|
||||
(with-temp-buffer
|
||||
(set-visited-file-name tmp-name1)
|
||||
(insert "foo")
|
||||
(should (buffer-modified-p))
|
||||
(tramp-cleanup-connection
|
||||
tramp-test-vec 'keep-debug 'keep-password)
|
||||
;; Modifying `read-from-minibuffer' doesn't work on MS Windows.
|
||||
(cl-letf (((symbol-function #'kill-buffer--possibly-save)
|
||||
#'tramp-compat-always))
|
||||
(kill-buffer)))
|
||||
;; A new connection changes process id, and also the
|
||||
;; lock file contents. But it still exists.
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
|
||||
(should (stringp (with-no-warnings (file-locked-p tmp-name1)))))
|
||||
|
||||
;; When `remote-file-name-inhibit-locks' is set, nothing happens.
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
|
||||
|
@ -6957,35 +7038,43 @@ INPUT, if non-nil, is a string sent to the process."
|
|||
|
||||
;; Steal the file lock.
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
|
||||
(cl-letf (((symbol-function #'read-char) (lambda (&rest _args) ?s)))
|
||||
;; Modifying `read-char' doesn't work on MS Windows.
|
||||
(cl-letf (((symbol-function #'ask-user-about-lock)
|
||||
#'tramp-compat-always))
|
||||
(with-no-warnings (lock-file tmp-name1)))
|
||||
(should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
|
||||
|
||||
;; Ignore the file lock.
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
|
||||
(cl-letf (((symbol-function #'read-char) (lambda (&rest _args) ?p)))
|
||||
;; Modifying `read-char' doesn't work on MS Windows.
|
||||
(cl-letf (((symbol-function #'ask-user-about-lock) #'ignore))
|
||||
(with-no-warnings (lock-file tmp-name1)))
|
||||
(should (stringp (with-no-warnings (file-locked-p tmp-name1))))
|
||||
|
||||
;; Quit the file lock machinery.
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
|
||||
(cl-letf (((symbol-function #'read-char) (lambda (&rest _args) ?q)))
|
||||
(with-no-warnings
|
||||
;; Quit the file lock machinery. There are problems with
|
||||
;; "sftp" and "podman", so we test on Emacs 29.1 only.
|
||||
(when (tramp--test-emacs29-p )
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
|
||||
;; Modifying `read-char' doesn't work on MS Windows.
|
||||
(cl-letf (((symbol-function #'ask-user-about-lock)
|
||||
(lambda (&rest args)
|
||||
(signal 'file-locked args))))
|
||||
(with-no-warnings
|
||||
(should-error
|
||||
(lock-file tmp-name1)
|
||||
:type 'file-locked))
|
||||
;; The same for `write-region'.
|
||||
(should-error
|
||||
(lock-file tmp-name1)
|
||||
:type 'file-locked))
|
||||
;; The same for `write-region'.
|
||||
(should-error
|
||||
(write-region "foo" nil tmp-name1)
|
||||
:type 'file-locked)
|
||||
(should-error
|
||||
(write-region "foo" nil tmp-name1 nil nil tmp-name1)
|
||||
:type 'file-locked)
|
||||
;; The same for `set-visited-file-name'.
|
||||
(with-temp-buffer
|
||||
(should-error
|
||||
(set-visited-file-name tmp-name1)
|
||||
:type 'file-locked)))
|
||||
(write-region "foo" nil tmp-name1)
|
||||
:type 'file-locked)
|
||||
(should-error
|
||||
(write-region "foo" nil tmp-name1 nil nil tmp-name1)
|
||||
:type 'file-locked)
|
||||
;; The same for `set-visited-file-name'.
|
||||
(with-temp-buffer
|
||||
(should-error
|
||||
(set-visited-file-name tmp-name1)
|
||||
:type 'file-locked))))
|
||||
(should (stringp (with-no-warnings (file-locked-p tmp-name1)))))
|
||||
|
||||
;; Cleanup.
|
||||
|
@ -7418,10 +7507,6 @@ This requires restrictions of file name syntax."
|
|||
(if quoted #'file-name-quote #'identity)
|
||||
(file-attribute-type (file-attributes file3)))
|
||||
(file-remote-p (file-truename file1) 'localname)))
|
||||
;; Check file contents.
|
||||
(with-temp-buffer
|
||||
(insert-file-contents file3)
|
||||
(should (string-equal (buffer-string) elt)))
|
||||
(delete-file file3))))
|
||||
|
||||
;; Check file names.
|
||||
|
@ -7447,7 +7532,7 @@ This requires restrictions of file name syntax."
|
|||
(setq buffer (dired-noselect tmp-name1 "--dired -al"))
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(when-let ((name (dired-get-filename 'no-dir 'no-error)))
|
||||
(when-let* ((name (dired-get-filename 'no-dir 'no-error)))
|
||||
(unless
|
||||
(string-match-p name directory-files-no-dot-files-regexp)
|
||||
(should (member name files))))
|
||||
|
@ -7687,7 +7772,7 @@ This requires restrictions of file name syntax."
|
|||
;; to U+1FFFF).
|
||||
"🌈🍒👋")
|
||||
|
||||
(when (tramp--test-expensive-test-p)
|
||||
(when (and (tramp--test-expensive-test-p) (not (tramp--test-windows-nt-p)))
|
||||
(delete-dups
|
||||
(mapcar
|
||||
;; Use all available language specific snippets.
|
||||
|
@ -7727,7 +7812,7 @@ This requires restrictions of file name syntax."
|
|||
"Check that `file-system-info' returns proper values."
|
||||
(skip-unless (tramp--test-enabled))
|
||||
|
||||
(when-let ((fsi (file-system-info ert-remote-temporary-file-directory)))
|
||||
(when-let* ((fsi (file-system-info ert-remote-temporary-file-directory)))
|
||||
(should (consp fsi))
|
||||
(should (tramp-compat-length= fsi 3))
|
||||
(dotimes (i (length fsi))
|
||||
|
@ -7759,10 +7844,10 @@ should all return proper values."
|
|||
(should (or (stringp (tramp-get-remote-gid v 'string))
|
||||
(null (tramp-get-remote-gid v 'string))))
|
||||
|
||||
(when-let ((groups (tramp-get-remote-groups v 'integer)))
|
||||
(when-let* ((groups (tramp-get-remote-groups v 'integer)))
|
||||
(should (consp groups))
|
||||
(dolist (group groups) (should (integerp group))))
|
||||
(when-let ((groups (tramp-get-remote-groups v 'string)))
|
||||
(when-let* ((groups (tramp-get-remote-groups v 'string)))
|
||||
(should (consp groups))
|
||||
(dolist (group groups) (should (stringp group)))))))
|
||||
|
||||
|
@ -7948,9 +8033,9 @@ process sentinels. They shall not disturb each other."
|
|||
buf)
|
||||
(while buffers
|
||||
(setq buf (seq-random-elt buffers))
|
||||
(if-let ((proc (get-buffer-process buf))
|
||||
(file (process-get proc 'foo))
|
||||
(count (process-get proc 'bar)))
|
||||
(if-let* ((proc (get-buffer-process buf))
|
||||
(file (process-get proc 'foo))
|
||||
(count (process-get proc 'bar)))
|
||||
(progn
|
||||
(tramp--test-message
|
||||
"Start action %d %s %s" count buf (current-time-string))
|
||||
|
@ -8063,7 +8148,7 @@ process sentinels. They shall not disturb each other."
|
|||
|
||||
(let ((pass "secret")
|
||||
(mock-entry (copy-tree (assoc "mock" tramp-methods)))
|
||||
mocked-input tramp-methods)
|
||||
mocked-input tramp-methods auth-sources)
|
||||
;; We must mock `read-string', in order to avoid interactive
|
||||
;; arguments.
|
||||
(cl-letf* (((symbol-function #'read-string)
|
||||
|
@ -8107,7 +8192,37 @@ process sentinels. They shall not disturb each other."
|
|||
"machine %s port mock password %s"
|
||||
(file-remote-p ert-remote-temporary-file-directory 'host) pass)
|
||||
(let ((auth-sources `(,netrc-file)))
|
||||
(should (file-exists-p ert-remote-temporary-file-directory)))))))))
|
||||
(should (file-exists-p ert-remote-temporary-file-directory))))))
|
||||
|
||||
;; Checking session-timeout.
|
||||
(with-no-warnings (when (symbol-plist 'ert-with-temp-file)
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug)
|
||||
(let ((tramp-connection-properties
|
||||
(cons '(nil "session-timeout" 1)
|
||||
tramp-connection-properties)))
|
||||
(setq mocked-input nil)
|
||||
(auth-source-forget-all-cached)
|
||||
(ert-with-temp-file netrc-file
|
||||
:prefix "tramp-test" :suffix ""
|
||||
:text (format
|
||||
"machine %s port mock password %s"
|
||||
(file-remote-p ert-remote-temporary-file-directory 'host)
|
||||
pass)
|
||||
(let ((auth-sources `(,netrc-file)))
|
||||
(should (file-exists-p ert-remote-temporary-file-directory))))
|
||||
;; Session established, password cached.
|
||||
(should
|
||||
(password-in-cache-p
|
||||
(auth-source-format-cache-entry
|
||||
(tramp-get-connection-property tramp-test-vec "pw-spec"))))
|
||||
;; We want to see the timeout message.
|
||||
(tramp--test-instrument-test-case 3
|
||||
(sleep-for 2))
|
||||
;; Session canceled, no password in cache.
|
||||
(should-not
|
||||
(password-in-cache-p
|
||||
(auth-source-format-cache-entry
|
||||
(tramp-get-connection-property tramp-test-vec "pw-spec"))))))))))
|
||||
|
||||
(ert-deftest tramp-test47-read-otp-password ()
|
||||
"Check Tramp one-time password handling."
|
||||
|
@ -8168,6 +8283,49 @@ process sentinels. They shall not disturb each other."
|
|||
(should-error
|
||||
(file-exists-p ert-remote-temporary-file-directory)))))))))
|
||||
|
||||
(ert-deftest tramp-test47-read-fingerprint ()
|
||||
"Check Tramp fingerprint handling."
|
||||
:tags '(:expensive-test)
|
||||
(skip-unless (tramp--test-mock-p))
|
||||
|
||||
(let (;; Suppress "exec".
|
||||
(tramp-restricted-shell-hosts-alist `(,tramp-system-name)))
|
||||
|
||||
;; Reading fingerprint works.
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug)
|
||||
(let ((tramp-connection-properties
|
||||
`((nil "login-args"
|
||||
(("-c")
|
||||
(,(tramp-shell-quote-argument
|
||||
"echo Place your finger on the fingerprint reader"))
|
||||
(";") ("sleep" "1")
|
||||
(";") ("sh" "-i"))))))
|
||||
(should (file-exists-p ert-remote-temporary-file-directory)))
|
||||
|
||||
;; Falling back after a timeout works.
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug)
|
||||
(let ((tramp-connection-properties
|
||||
`((nil "login-args"
|
||||
(("-c")
|
||||
(,(tramp-shell-quote-argument
|
||||
"echo Place your finger on the fingerprint reader"))
|
||||
(";") ("sleep" "1")
|
||||
(";") ("echo" "Failed to match fingerprint")
|
||||
(";") ("sh" "-i"))))))
|
||||
(should (file-exists-p ert-remote-temporary-file-directory)))
|
||||
|
||||
;; Interrupting the fingerprint handshaking works.
|
||||
(tramp-cleanup-connection tramp-test-vec 'keep-debug)
|
||||
(let ((tramp-connection-properties
|
||||
`((nil "login-args"
|
||||
(("-c")
|
||||
(,(tramp-shell-quote-argument
|
||||
"echo Place your finger on the fingerprint reader"))
|
||||
(";") ("sleep" "1")
|
||||
(";") ("sh" "-i")))))
|
||||
tramp-use-fingerprint)
|
||||
(should (file-exists-p ert-remote-temporary-file-directory)))))
|
||||
|
||||
;; This test is inspired by Bug#29163.
|
||||
(ert-deftest tramp-test48-auto-load ()
|
||||
"Check that Tramp autoloads properly."
|
||||
|
@ -8388,7 +8546,6 @@ If INTERACTIVE is non-nil, the tests are run interactively."
|
|||
;; * file-equal-p (partly done in `tramp-test21-file-links')
|
||||
;; * file-in-directory-p
|
||||
;; * file-name-case-insensitive-p
|
||||
;; * memory-info
|
||||
;; * tramp-get-home-directory
|
||||
;; * tramp-set-file-uid-gid
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue