Add Tramp sshfs method
* doc/misc/tramp.texi (Top, Configuration): Insert sections 'FUSE-based methods' and 'FUSE setup' in menu. (Quick Start Guide): Fix @anchors. Add doas. Extend section 'Using @command{rclone}' to 'Using @acronym{FUSE}-based methods'. (External methods): Remove rclone paragraph. (FUSE-based methods, FUSE setup): New nodes. (Predefined connection information): Mention "mount-point". * etc/NEWS: Mention Tramp sshfs method. Fix typos and other oddities. * lisp/net/tramp-fuse.el: New file. * lisp/net/tramp-rclone.el (tramp-fuse): Require. (tramp-rclone-file-name-handler-alist): Replace `tramp-rclone-handle-*' by `tramp-fuse-handle-*' where appropriate. (tramp-rclone-handle-delete-directory) (tramp-rclone-handle-delete-file) (tramp-rclone-handle-directory-files) (tramp-rclone-handle-file-attributes) (tramp-rclone-handle-file-executable-p) (tramp-rclone-handle-file-name-all-completions) (tramp-rclone-handle-file-readable-p) (tramp-rclone-handle-insert-directory) (tramp-rclone-handle-insert-file-contents) (tramp-rclone-handle-make-directory, tramp-rclone-mount-point) (tramp-rclone-mounted-p, tramp-rclone-local-file-name): Remove. Functionality moved to tramp-fuse.el. (tramp-rclone-remote-file-name) (tramp-rclone-maybe-open-connection): Use `tramp-fuse-*' functions. * lisp/net/tramp-sh.el (tramp-do-copy-or-rename-file-out-of-band): Simplify check. * lisp/net/tramp-sshfs.el: New file. * lisp/net/tramp.el: Remove TODO item. * test/lisp/net/tramp-tests.el (tramp--test-sshfs-p): New defun. (tramp-test14-delete-directory): Use it.
This commit is contained in:
parent
a190bc9f30
commit
11d3af3c7b
8 changed files with 789 additions and 292 deletions
|
@ -126,6 +126,7 @@ Configuring @value{tramp} for use
|
|||
* Inline methods:: Inline methods.
|
||||
* External methods:: External methods.
|
||||
* GVFS-based methods:: @acronym{GVFS}-based external methods.
|
||||
* FUSE-based methods:: @acronym{FUSE}-based external methods.
|
||||
* Default Method:: Selecting a default method.
|
||||
* Default User:: Selecting a default user.
|
||||
* Default Host:: Selecting a default host.
|
||||
|
@ -139,6 +140,7 @@ Configuring @value{tramp} for use
|
|||
Setting own connection related information.
|
||||
* Remote programs:: How @value{tramp} finds and uses programs on the remote host.
|
||||
* Remote shell setup:: Remote shell setup hints.
|
||||
* FUSE setup:: @acronym{FUSE} setup hints.
|
||||
* Android shell setup:: Android shell setup hints.
|
||||
* Auto-save and Backup:: Auto-save and Backup.
|
||||
* Keeping files encrypted:: Protect remote files by encryption.
|
||||
|
@ -433,7 +435,7 @@ remote host, when the buffer you call the process from has a remote
|
|||
@code{default-directory}.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: File name syntax}
|
||||
@anchor{Quick Start Guide File name syntax}
|
||||
@section File name syntax
|
||||
@cindex file name syntax
|
||||
|
||||
|
@ -459,7 +461,7 @@ connection methods also support a notation for the port to be used, in
|
|||
which case it is written as @code{host#port}.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: @option{ssh} and @option{plink} methods}
|
||||
@anchor{Quick Start Guide ssh and plink methods}
|
||||
@section Using @option{ssh} and @option{plink}
|
||||
@cindex method @option{ssh}
|
||||
@cindex @option{ssh} method
|
||||
|
@ -478,28 +480,31 @@ an @command{ssh} server:
|
|||
@file{@trampfn{plink,user@@host,/path/to/file}}.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: @option{su}, @option{sudo} and @option{sg} methods}
|
||||
@section Using @option{su}, @option{sudo} and @option{sg}
|
||||
@anchor{Quick Start Guide su, sudo, doas and sg methods}
|
||||
@section Using @option{su}, @option{sudo}, @option{doas} and @option{sg}
|
||||
@cindex method @option{su}
|
||||
@cindex @option{su} method
|
||||
@cindex method @option{sudo}
|
||||
@cindex @option{sudo} method
|
||||
@cindex method @option{doas}
|
||||
@cindex @option{doas} method
|
||||
@cindex method @option{sg}
|
||||
@cindex @option{sg} method
|
||||
|
||||
Sometimes, it is necessary to work on your local host under different
|
||||
permissions. For this, you can use the @option{su} or @option{sudo}
|
||||
connection method. Both methods use @samp{root} as default user name
|
||||
and the return value of @code{(system-name)} as default host name.
|
||||
Therefore, it is convenient to open a file as
|
||||
connection method. On OpenBSD systems, the @option{doas} connection
|
||||
method offers the same functionality. These methods use @samp{root}
|
||||
as default user name and the return value of @code{(system-name)} as
|
||||
default host name. Therefore, it is convenient to open a file as
|
||||
@file{@trampfn{sudo,,/path/to/file}}.
|
||||
|
||||
The method @option{sg} stands for ``switch group''; here the user name
|
||||
is used as the group to change to. The default host name is the same.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: @option{ssh}, @option{plink}, @option{su}, @option{sudo} and @option{sg} methods}
|
||||
@section Combining @option{ssh} or @option{plink} with @option{su} or @option{sudo}
|
||||
@anchor{Quick Start Guide Combining ssh, plink, su, sudo and doas methods}
|
||||
@section Combining @option{ssh} or @option{plink} with @option{su}, @option{sudo} or @option{doas}
|
||||
@cindex method @option{ssh}
|
||||
@cindex @option{ssh} method
|
||||
@cindex method @option{plink}
|
||||
|
@ -508,18 +513,20 @@ is used as the group to change to. The default host name is the same.
|
|||
@cindex @option{su} method
|
||||
@cindex method @option{sudo}
|
||||
@cindex @option{sudo} method
|
||||
@cindex method @option{doas}
|
||||
@cindex @option{doas} method
|
||||
|
||||
If the @option{su} or @option{sudo} option should be performed on
|
||||
another host, it can be comnbined with a leading @option{ssh} or
|
||||
@option{plink} option. That means that @value{tramp} connects first to
|
||||
the other host with non-administrative credentials, and changes to
|
||||
administrative credentials on that host afterwards. In a simple case,
|
||||
the syntax looks like
|
||||
If the @option{su}, @option{sudo} or @option{doas} option should be
|
||||
performed on another host, it can be comnbined with a leading
|
||||
@option{ssh} or @option{plink} option. That means that @value{tramp}
|
||||
connects first to the other host with non-administrative credentials,
|
||||
and changes to administrative credentials on that host afterwards. In
|
||||
a simple case, the syntax looks like
|
||||
@file{@value{prefix}ssh@value{postfixhop}user@@host|sudo@value{postfixhop}@value{postfix}/path/to/file}.
|
||||
@xref{Ad-hoc multi-hops}.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: @option{sudoedit} method}
|
||||
@anchor{Quick Start Guide sudoedit method}
|
||||
@section Using @command{sudoedit}
|
||||
@cindex method @option{sudoedit}
|
||||
@cindex @option{sudoedit} method
|
||||
|
@ -532,7 +539,7 @@ method, it is restricted to @samp{localhost} only, and it does not
|
|||
support external processes.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: @option{smb} method}
|
||||
@anchor{Quick Start Guide smb method}
|
||||
@section Using @command{smbclient}
|
||||
@cindex method @option{smb}
|
||||
@cindex @option{smb} method
|
||||
|
@ -546,7 +553,7 @@ of the local file name is the share exported by the remote host,
|
|||
@samp{path} in this example.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: GVFS-based methods}
|
||||
@anchor{Quick Start Guide GVFS-based methods}
|
||||
@section Using @acronym{GVFS}-based methods
|
||||
@cindex methods, gvfs
|
||||
@cindex gvfs-based methods
|
||||
|
@ -570,7 +577,7 @@ file system), @file{@trampfn{dav,user@@host,/path/to/file}},
|
|||
@file{@trampfn{mtp,device,/path/to/file}} (for media devices).
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: GNOME Online Accounts based methods}
|
||||
@anchor{Quick Start Guide GNOME Online Accounts based methods}
|
||||
@section Using @acronym{GNOME} Online Accounts based methods
|
||||
@cindex @acronym{GNOME} Online Accounts
|
||||
@cindex method @option{gdrive}
|
||||
|
@ -590,7 +597,34 @@ account), or @file{@trampfn{nextcloud,user@@host#8081,/path/to/file}}
|
|||
(@samp{8081} stands for the port number) for OwnCloud/NextCloud files.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: Android}
|
||||
@anchor{Quick Start Guide FUSE-based methods}
|
||||
@section Using @acronym{FUSE}-based methods
|
||||
@cindex methods, fuse
|
||||
@cindex fuse-based methods
|
||||
@cindex method @option{rclone}
|
||||
@cindex @option{rclone} method
|
||||
@cindex method @option{sshfs}
|
||||
@cindex @option{sshfs} method
|
||||
|
||||
@acronym{FUSE, Filesystem in Userspace} allows users to mount a
|
||||
virtual file system. It is also used by @acronym{GVFS} internally,
|
||||
but here we discuss methods which do not use the @acronym{GVFS} API.
|
||||
|
||||
A convenient way to access system storages is the @command{rclone}
|
||||
program. If you have configured a storage in @command{rclone} under a
|
||||
name @samp{storage} (for example), you can access it via the remote
|
||||
file name syntax @file{@trampfn{rclone,storage,/path/to/file}}. User
|
||||
names are not needed.
|
||||
|
||||
On local hosts which have installed the @command{sshfs} client for
|
||||
mounting a file system based on @command{sftp}, this method can be
|
||||
used. All remote files are available via the local mount point.
|
||||
@value{tramp} aids in mounting the file system if it isn't mounted
|
||||
yet, and it supports the access with the usual file name syntax
|
||||
@file{@trampfn{sshfs,user@@host,/path/to/file}}.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide Android}
|
||||
@section Using Android
|
||||
@cindex method @option{adb}
|
||||
@cindex @option{adb} method
|
||||
|
@ -601,18 +635,6 @@ be accessed via the @command{adb} command. No user or host name is
|
|||
needed. The file name syntax is @file{@trampfn{adb,,/path/to/file}}.
|
||||
|
||||
|
||||
@anchor{Quick Start Guide: @option{rclone} method}
|
||||
@section Using @command{rclone}
|
||||
@cindex method @option{rclone}
|
||||
@cindex @option{rclone} method
|
||||
|
||||
A convenient way to access system storages is the @command{rclone}
|
||||
program. If you have configured a storage in @command{rclone} under a
|
||||
name @samp{storage} (for example), you can access it via the remote
|
||||
file name syntax @file{@trampfn{rclone,storage,/path/to/file}}. User
|
||||
names are not needed.
|
||||
|
||||
|
||||
@node Configuration
|
||||
@chapter Configuring @value{tramp}
|
||||
@cindex configuration
|
||||
|
@ -650,6 +672,7 @@ may be used in your init file:
|
|||
* Inline methods:: Inline methods.
|
||||
* External methods:: External methods.
|
||||
* GVFS-based methods:: @acronym{GVFS}-based external methods.
|
||||
* FUSE-based methods:: @acronym{FUSE}-based external methods.
|
||||
* Default Method:: Selecting a default method.
|
||||
Here we also try to help those who
|
||||
don't have the foggiest which method
|
||||
|
@ -666,6 +689,7 @@ may be used in your init file:
|
|||
Setting own connection related information.
|
||||
* Remote programs:: How @value{tramp} finds and uses programs on the remote host.
|
||||
* Remote shell setup:: Remote shell setup hints.
|
||||
* FUSE setup:: @acronym{FUSE} setup hints.
|
||||
* Android shell setup:: Android shell setup hints.
|
||||
* Auto-save and Backup:: Auto-save and Backup.
|
||||
* Keeping files encrypted:: Protect remote files by encryption.
|
||||
|
@ -1110,7 +1134,6 @@ UNC file name specification does not allow the specification of a
|
|||
different user name for authentication like the @command{smbclient}
|
||||
can.
|
||||
|
||||
|
||||
@item @option{adb}
|
||||
@cindex method @option{adb}
|
||||
@cindex @option{adb} method
|
||||
|
@ -1150,45 +1173,6 @@ specified using @file{device#42} host name syntax or @value{tramp} can
|
|||
use the default value as declared in @command{adb} command. Port
|
||||
numbers are not applicable to Android devices connected through USB@.
|
||||
|
||||
|
||||
@item @option{rclone}
|
||||
@cindex method @option{rclone}
|
||||
@cindex @option{rclone} method
|
||||
|
||||
@vindex tramp-rclone-program
|
||||
The program @command{rclone} allows to access different system
|
||||
storages in the cloud, see @url{https://rclone.org/} for a list of
|
||||
supported systems. If the @command{rclone} program isn't found in
|
||||
your @env{PATH} environment variable, you can tell @value{tramp} its
|
||||
absolute path via the user option @code{tramp-rclone-program}.
|
||||
|
||||
A system storage must be configured via the @command{rclone config}
|
||||
command, outside Emacs. If you have configured a storage in
|
||||
@command{rclone} under a name @samp{storage} (for example), you could
|
||||
access it via the remote file name
|
||||
|
||||
@example
|
||||
@trampfn{rclone,storage,/path/to/file}
|
||||
@end example
|
||||
|
||||
User names are part of the @command{rclone} configuration, and not
|
||||
needed in the remote file name. If a user name is contained in the
|
||||
remote file name, it is ignored.
|
||||
|
||||
Internally, @value{tramp} mounts the remote system storage at location
|
||||
@file{/tmp/tramp.rclone.storage}, with @file{storage} being the name
|
||||
of the configured system storage.
|
||||
|
||||
Optional flags to the different @option{rclone} operations could be
|
||||
passed as connection property, @xref{Predefined connection
|
||||
information}. Supported properties are @t{"mount-args"},
|
||||
@t{"copyto-args"}, @t{"moveto-args"} and @t{"about-args"}.
|
||||
|
||||
Access via @option{rclone} is slow. If you have an alternative method
|
||||
for accessing the system storage, you should use it.
|
||||
@ref{GVFS-based methods} for example, methods @option{gdrive} and
|
||||
@option{nextcloud}.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
|
@ -1200,8 +1184,8 @@ for accessing the system storage, you should use it.
|
|||
|
||||
@acronym{GVFS} is the virtual file system for the @acronym{GNOME}
|
||||
Desktop, @uref{https://en.wikipedia.org/wiki/GVFS}. Remote files on
|
||||
@acronym{GVFS} are mounted locally through FUSE and @value{tramp} uses
|
||||
this locally mounted directory internally.
|
||||
@acronym{GVFS} are mounted locally through @acronym{FUSE} and
|
||||
@value{tramp} uses this locally mounted directory internally.
|
||||
|
||||
Emacs uses the D-Bus mechanism to communicate with @acronym{GVFS}@.
|
||||
Emacs must have the message bus system, D-Bus integration active,
|
||||
|
@ -1317,6 +1301,88 @@ respectively:
|
|||
@end defopt
|
||||
|
||||
|
||||
@node FUSE-based methods
|
||||
@section @acronym{FUSE}-based external methods
|
||||
@cindex methods, fuse
|
||||
@cindex fuse-based methods
|
||||
|
||||
Besides @acronym{GVFS}, there are other virtual file systems using the
|
||||
@acronym{FUSE} interface. Remote files are mounted locally through
|
||||
@acronym{FUSE} and @value{tramp} uses this locally mounted directory
|
||||
internally. When possible, @value{tramp} maps the remote file names
|
||||
to their respective local file name, and applies the file name
|
||||
operation on them. For some of the file name operations this is not
|
||||
possible, @value{tramp} emulates those operations otherwise.
|
||||
|
||||
@table @asis
|
||||
@item @option{rclone}
|
||||
@cindex method @option{rclone}
|
||||
@cindex @option{rclone} method
|
||||
|
||||
@vindex tramp-rclone-program
|
||||
The program @command{rclone} allows to access different system
|
||||
storages in the cloud, see @url{https://rclone.org/} for a list of
|
||||
supported systems. If the @command{rclone} program isn't found in
|
||||
your @env{PATH} environment variable, you can tell @value{tramp} its
|
||||
absolute path via the user option @code{tramp-rclone-program}.
|
||||
|
||||
A system storage must be configured via the @command{rclone config}
|
||||
command, outside Emacs. If you have configured a storage in
|
||||
@command{rclone} under a name @samp{storage} (for example), you could
|
||||
access it via the remote file name
|
||||
|
||||
@example
|
||||
@trampfn{rclone,storage,/path/to/file}
|
||||
@end example
|
||||
|
||||
User names are part of the @command{rclone} configuration, and not
|
||||
needed in the remote file name. If a user name is contained in the
|
||||
remote file name, it is ignored.
|
||||
|
||||
Internally, @value{tramp} mounts the remote system storage at location
|
||||
@file{/tmp/tramp.rclone.storage}, with @file{storage} being the name
|
||||
of the configured system storage.
|
||||
|
||||
The mount point and optional flags to the different @option{rclone}
|
||||
operations could be passed as connection properties, @xref{Setup of
|
||||
rclone method}.
|
||||
|
||||
Access via @option{rclone} is slow. If you have an alternative method
|
||||
for accessing the system storage, you should use it.
|
||||
@ref{GVFS-based methods} for example, methods @option{gdrive} and
|
||||
@option{nextcloud}.
|
||||
|
||||
@item @option{sshfs}
|
||||
@cindex method @option{sshfs}
|
||||
@cindex @option{sshfs} method
|
||||
|
||||
@vindex tramp-sshfs-program
|
||||
On local hosts which have installed the @command{sshfs} client for
|
||||
mounting a file system based on @command{sftp}, this method can be
|
||||
used, see
|
||||
@url{https://github.com/libfuse/sshfs/blob/master/README.rst/}. If
|
||||
the @command{sshfs} program isn't found in your @env{PATH} environment
|
||||
variable, you can tell @value{tramp} its absolute path via the user
|
||||
option @code{tramp-sshfs-program}.
|
||||
|
||||
All remote files are available via the local mount point.
|
||||
@value{tramp} aids in mounting the file system if it isn't mounted
|
||||
yet. The remote file name syntax is
|
||||
|
||||
@example
|
||||
@trampfn{sshfs,user@@host#port,/path/to/file}
|
||||
@end example
|
||||
|
||||
User name and port number are optional. This method does not support
|
||||
password handling, the file system must either be mounted already, or
|
||||
the connection must be established passwordless via ssh keys.
|
||||
|
||||
The mount point and mount arguments could be passed as connection
|
||||
properties, @xref{Setup of sshfs method}.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
@node Default Method
|
||||
@section Selecting a default method
|
||||
@cindex default method
|
||||
|
@ -2102,6 +2168,13 @@ The default value of this property is @code{t} (not specified in
|
|||
@code{tramp-methods}). If the remote host runs native MS Windows,
|
||||
this propery has no effect.
|
||||
|
||||
@item @t{"mount-point"}
|
||||
|
||||
The directory file name an @acronym{FUSE}-based file system is mounted
|
||||
on. The default value of this property is
|
||||
@t{"/tmp/tramp.method.user@@host#port"} (not specified in
|
||||
@code{tramp-methods}).
|
||||
|
||||
@item @t{"mount-args"}@*
|
||||
@t{"copyto-args"}@*
|
||||
@t{"moveto-args"}@*
|
||||
|
@ -2430,7 +2503,6 @@ match the end of the connection buffer. Due to performance reasons,
|
|||
this search starts at the end of the buffer, and it is limited to 256
|
||||
characters backwards.
|
||||
|
||||
|
||||
@item Conflicting names for users and variables in @file{.profile}
|
||||
|
||||
When a user name is the same as a variable name in a local file, such
|
||||
|
@ -2440,7 +2512,6 @@ variable name to something different from the user name. For example,
|
|||
if the user name is @env{FRUMPLE}, then change the variable name to
|
||||
@env{FRUMPLE_DIR}.
|
||||
|
||||
|
||||
@item Non-Bourne commands in @file{.profile}
|
||||
|
||||
When the remote host's @file{.profile} is also used for shells other
|
||||
|
@ -2465,7 +2536,6 @@ To accommodate using non-Bourne shells on that remote, use other
|
|||
shell-specific config files. For example, bash can use
|
||||
@file{~/.bash_profile} and ignore @file{.profile}.
|
||||
|
||||
|
||||
@item Interactive shell prompt
|
||||
|
||||
@vindex INSIDE_EMACS@r{, environment variable}
|
||||
|
@ -2533,6 +2603,57 @@ where @samp{192.168.0.1} is the remote host IP address
|
|||
@end table
|
||||
|
||||
|
||||
@node FUSE setup
|
||||
@section @acronym{FUSE} setup hints
|
||||
|
||||
The @acronym{FUSE} file systems are mounted per default at
|
||||
@file{/tmp/tramp.method.user@@host#port}. The user name and port
|
||||
number are optional. If the file system is already mounted, it will
|
||||
be used as it is. If the mount point does not exist yet,
|
||||
@value{tramp} creates this directory.
|
||||
|
||||
The mount point can be overwritten by the connection property
|
||||
@t{"mount-point"}, @ref{Predefined connection information}.
|
||||
Example:
|
||||
|
||||
@lisp
|
||||
@group
|
||||
(add-to-list 'tramp-connection-properties
|
||||
`(,(regexp-quote "@trampfn{sshfs,user@@host,}")
|
||||
"mount-point"
|
||||
,(expand-file-name "sshfs.user@@host" user-emacs-directory)))
|
||||
@end group
|
||||
@end lisp
|
||||
|
||||
|
||||
@anchor{Setup of rclone method}
|
||||
@subsection @option{rclone} setup
|
||||
@cindex rclone setup
|
||||
|
||||
The default arguments of the @command{rclone} operations
|
||||
@command{mount}, @command{coopyto}, @command{moveto} and
|
||||
@command{about} are declared in the variable @code{tramp-methods} as
|
||||
method specific parameters. Usually, they don't need to be overwritten.
|
||||
|
||||
If needed, these parameters can be overwritten as connection
|
||||
properties @t{"mount-args"}, @t{"copyto-args"}, @t{"moveto-args"} and
|
||||
@t{"about-args"}, @xref{Predefined connection information}. All of
|
||||
them are list of strings.
|
||||
|
||||
Be careful changing @t{"--dir-cache-time"}, this could delay
|
||||
visibility of files.
|
||||
|
||||
|
||||
@anchor{Setup of sshfs method}
|
||||
@subsection @option{sshfs} setup
|
||||
@cindex sshfs setup
|
||||
|
||||
The method @option{sshfs} declares only the mount arguments, passed to
|
||||
the @command{sshfs} command. This is a list of list of strings, and
|
||||
can be overwritten by the connection property @t{"mount-args"},
|
||||
@xref{Predefined connection information}.
|
||||
|
||||
|
||||
@node Android shell setup
|
||||
@section Android shell setup hints
|
||||
@cindex android shell setup for ssh
|
||||
|
@ -4197,6 +4318,7 @@ Disable excessive traces. Set @code{tramp-verbose} to 3 or lower,
|
|||
default being 3. Increase trace levels temporarily when hunting for
|
||||
bugs.
|
||||
|
||||
|
||||
@item
|
||||
@value{tramp} does not connect to the remote host
|
||||
|
||||
|
@ -4448,6 +4570,7 @@ disable @samp{--color=yes} or @samp{--color=auto} in the remote host's
|
|||
@file{.bashrc} or @file{.profile}. Turn this alias on and off to see
|
||||
if file name completion works.
|
||||
|
||||
|
||||
@item
|
||||
File name completion does not work in directories with large number of
|
||||
files
|
||||
|
@ -4846,6 +4969,7 @@ In BBDB buffer, access an entry by pressing the key @kbd{F}.
|
|||
|
||||
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?
|
||||
|
||||
|
|
66
etc/NEWS
66
etc/NEWS
|
@ -266,8 +266,8 @@ current mode.
|
|||
|
||||
+++
|
||||
** New user option 'read-extended-command-predicate'.
|
||||
This option controls how 'M-x' performs completion of commands when
|
||||
you type TAB. By default, any command that matches what you have
|
||||
This user option controls how 'M-x' performs completion of commands when
|
||||
you type 'TAB'. By default, any command that matches what you have
|
||||
typed is considered a completion candidate, but you can customize this
|
||||
option to exclude commands that are not applicable to the current
|
||||
buffer's major and minor modes, and respect the command's completion
|
||||
|
@ -369,25 +369,26 @@ Typing 'TAB' on a heading line cycles the current section between
|
|||
anywhere in the buffer cycles the whole buffer between "only top-level
|
||||
headings", "all headings and subheadings", and "show all" states.
|
||||
|
||||
*** New option 'outline-minor-mode-cycle'.
|
||||
This option customizes 'outline-minor-mode', with the difference
|
||||
*** New user option 'outline-minor-mode-cycle'.
|
||||
This user option customizes 'outline-minor-mode', with the difference
|
||||
that 'TAB' and 'S-TAB' on heading lines cycle heading visibility.
|
||||
Typing 'TAB' on a heading line cycles the current section between
|
||||
"hide all", "subheadings", and "show all" states. Typing 'S-TAB' on a
|
||||
heading line cycles the whole buffer between "only top-level
|
||||
headings", "all headings and subheadings", and "show all" states.
|
||||
|
||||
*** New option 'outline-minor-mode-highlight'.
|
||||
This option customizes 'outline-minor-mode'. It puts highlighting
|
||||
on heading lines using standard outline faces. This works well only
|
||||
when there are no conflicts with faces used by the major mode.
|
||||
*** New user option 'outline-minor-mode-highlight'.
|
||||
This user option customizes 'outline-minor-mode'. It puts
|
||||
highlighting on heading lines using standard outline faces. This
|
||||
works well only when there are no conflicts with faces used by the
|
||||
major mode.
|
||||
|
||||
|
||||
* Changes in Specialized Modes and Packages in Emacs 28.1
|
||||
|
||||
** Macroexp
|
||||
---
|
||||
*** New function 'macroexp-file-name' to know the name of the current file
|
||||
*** New function 'macroexp-file-name' to know the name of the current file.
|
||||
---
|
||||
*** New function 'macroexp-compiling-p' to know if we're compiling.
|
||||
---
|
||||
|
@ -400,17 +401,18 @@ It used to be enabled when Emacs is started in GUI mode but not when started
|
|||
in text mode. The cursor still only actually blinks in GUI frames.
|
||||
|
||||
** Bindat
|
||||
|
||||
+++
|
||||
*** New 'Bindat type expression' description language.
|
||||
This new system is provided by the new macro 'bindat-type' and
|
||||
obsoletes the old data layout specifications. It supports
|
||||
arbitrary-size integers, recursive types, and more. See the Info node
|
||||
'Byte Packing' in the ELisp manual for more details.
|
||||
"(elisp) Byte Packing" in the ELisp manual for more details.
|
||||
|
||||
** pcase
|
||||
|
||||
+++
|
||||
*** The 'or' pattern now binds the union of the vars of its sub-patterns
|
||||
*** The 'or' pattern now binds the union of the vars of its sub-patterns.
|
||||
If a variable is not bound by the subpattern that matched, it gets bound
|
||||
to nil. This was already sometimes the case, but it is now guaranteed.
|
||||
|
||||
|
@ -1031,10 +1033,9 @@ To customize obsolete user options, use 'customize-option' or
|
|||
|
||||
** Edebug
|
||||
|
||||
---
|
||||
*** Obsoletions
|
||||
---
|
||||
**** 'get-edebug-spec' is obsolete, replaced by 'edebug-get-spec'.
|
||||
|
||||
+++
|
||||
**** The spec operator ':name NAME' is obsolete, use '&name' instead.
|
||||
+++
|
||||
|
@ -1066,7 +1067,7 @@ use) and HEAD is the code that matched SPEC.
|
|||
+++
|
||||
*** New user option 'eldoc-echo-area-display-truncation-message'.
|
||||
If non-nil (the default), eldoc will display a message saying
|
||||
something like "(Documentation truncated. Use `M-x eldoc-doc-buffer'
|
||||
something like "(Documentation truncated. Use `M-x eldoc-doc-buffer'
|
||||
to see rest)" when a message has been truncated. If nil, truncated
|
||||
messages will be marked with just "..." at the end.
|
||||
|
||||
|
@ -1134,6 +1135,10 @@ preferred over the eudcb-mab.el backend.
|
|||
*** New connection method "mtp", which allows accessing media devices
|
||||
like cell phones, tablets or cameras.
|
||||
|
||||
+++
|
||||
*** New connection method "sshfs", which allows accessing remote files
|
||||
via a file system mounted with 'sshfs'.
|
||||
|
||||
+++
|
||||
*** Trashed remote files are moved to the local trash directory.
|
||||
All remote files, which are trashed, are moved to the local trash
|
||||
|
@ -1555,7 +1560,7 @@ have been renamed to have "proper" public names and documented
|
|||
'xref-show-definitions-buffer-at-bottom').
|
||||
|
||||
*** New command 'xref-quit-and-pop-marker-stack' and a binding for it
|
||||
in "*xref*" buffers ('M-,'). This combination is easy to press
|
||||
in "*xref*" buffers ('M-,'). This combination is easy to press
|
||||
semi-accidentally if the user wants to go back in the middle of
|
||||
choosing the exact definition to go to, and this should do TRT.
|
||||
|
||||
|
@ -2138,7 +2143,7 @@ messages, contain the error name of that message now.
|
|||
+++
|
||||
*** D-Bus events have changed their internal structure.
|
||||
They carry now the destination and the error-name of an event. They
|
||||
also keep the type information of their arguments. Use the
|
||||
also keep the type information of their arguments. Use the
|
||||
'dbus-event-*' accessor functions.
|
||||
|
||||
** CPerl Mode
|
||||
|
@ -2180,7 +2185,7 @@ You can type 'C-x u u' instead of 'C-x u C-x u' to undo many changes,
|
|||
'C-x { { } } ^ ^ v v' to resize the selected window interactively,
|
||||
'M-g n n p p' to navigate next-error matches. Any other key exits
|
||||
transient mode and then is executed normally. 'repeat-exit-key'
|
||||
defines an additional key to exit mode like 'isearch-exit' (RET).
|
||||
defines an additional key to exit mode like 'isearch-exit' ('RET').
|
||||
|
||||
|
||||
* New Modes and Packages in Emacs 28.1
|
||||
|
@ -2296,7 +2301,7 @@ by mistake and were not useful to Lisp code.
|
|||
|
||||
---
|
||||
** Loading 'generic-x' unconditionally loads all modes.
|
||||
The user option `generic-extras-enable-list' is now obsolete, and
|
||||
The user option 'generic-extras-enable-list' is now obsolete, and
|
||||
setting it has no effect.
|
||||
|
||||
---
|
||||
|
@ -2343,8 +2348,8 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
|
|||
'dirtrack-debug-toggle', 'dynamic-completion-table',
|
||||
'easy-menu-precalculate-equivalent-keybindings',
|
||||
'epa-display-verify-result', 'epg-passphrase-callback-function',
|
||||
'erc-announced-server-name', 'erc-process',
|
||||
'erc-default-coding-system', 'erc-send-command', 'eshell-report-bug',
|
||||
'erc-announced-server-name', 'erc-default-coding-system',
|
||||
'erc-process', 'erc-send-command', 'eshell-report-bug',
|
||||
'eval-next-after-load', 'exchange-dot-and-mark', 'ffap-bug',
|
||||
'ffap-submit-bug', 'ffap-version', 'file-cache-choose-completion',
|
||||
'forward-point', 'generic-char-p', 'global-highlight-changes',
|
||||
|
@ -2391,7 +2396,7 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
|
|||
'semantic-toplevel-bovine-table', 'semanticdb-mode-hooks',
|
||||
'set-coding-priority', 'set-process-filter-multibyte',
|
||||
'shadows-compare-text-p', 'shell-dirtrack-toggle',
|
||||
'speedbar-update-speed', 'speedbar-navigating-speed', 't-mouse-mode',
|
||||
'speedbar-navigating-speed', 'speedbar-update-speed', 't-mouse-mode',
|
||||
'term-dynamic-simple-complete', 'tooltip-hook', 'tpu-have-ispell',
|
||||
'url-generate-unique-filename', 'url-temporary-directory',
|
||||
'vc-arch-command', 'vc-default-working-revision' (variable),
|
||||
|
@ -2413,6 +2418,8 @@ back in Emacs 23.1. The affected functions are: 'make-obsolete',
|
|||
|
||||
** The variable 'keyboard-type' is obsolete and not dynamically scoped any more.
|
||||
|
||||
** The 'values' variable is now obsolete.
|
||||
|
||||
|
||||
* Lisp Changes in Emacs 28.1
|
||||
|
||||
|
@ -2449,13 +2456,13 @@ This variable holds a list of currently enabled global minor modes (as
|
|||
a list of symbols).
|
||||
|
||||
+++
|
||||
** 'define-minor-mode' now takes an :interactive argument.
|
||||
** 'define-minor-mode' now takes an ':interactive' argument.
|
||||
This can be used for specifying which modes this minor mode is meant
|
||||
for, or to make the new minor mode non-interactive. The default value
|
||||
is t.
|
||||
|
||||
+++
|
||||
** 'define-derived-mode' now takes an :interactive argument.
|
||||
** 'define-derived-mode' now takes an ':interactive' argument.
|
||||
This can be used to control whether the defined mode is a command
|
||||
or not, and is useful when defining commands that aren't meant to be
|
||||
used by users directly.
|
||||
|
@ -2463,8 +2470,6 @@ used by users directly.
|
|||
---
|
||||
** The 'easymenu' library is now preloaded.
|
||||
|
||||
** The 'values' variable is now obsolete.
|
||||
|
||||
---
|
||||
** New variable 'indent-line-ignored-functions'.
|
||||
This allows modes to cycle through a set of indentation functions
|
||||
|
@ -2495,10 +2500,11 @@ When non-nil, then functions 'read-char-choice' and 'y-or-n-p' (respectively)
|
|||
use the function 'read-key' to read a character instead of using the minibuffer.
|
||||
|
||||
---
|
||||
** New variable 'use-short-answers' to use 'y-or-n-p' instead of 'yes-or-no-p'.
|
||||
This eliminates the need to define an alias that maps one to another
|
||||
in the init file. The same variable also controls whether the
|
||||
function 'read-answer' accepts short answers.
|
||||
** New user option 'use-short-answers'.
|
||||
When non-nil, the function 'y-or-n-p' is used instead of
|
||||
'yes-or-no-p'. This eliminates the need to define an alias that maps
|
||||
one to another in the init file. The same user option also controls
|
||||
whether the function 'read-answer' accepts short answers.
|
||||
|
||||
+++
|
||||
** 'set-window-configuration' now takes an optional 'dont-set-frame'
|
||||
|
@ -2700,7 +2706,7 @@ menu handling.
|
|||
It is meant as an (experimental) aid for converting Emacs Lisp code
|
||||
to lexical binding, where dynamic (special) variables bound in one
|
||||
file can affect code in another. For details, see the manual section
|
||||
"(Elisp) Converting to Lexical Binding".
|
||||
"(elisp) Converting to Lexical Binding".
|
||||
|
||||
+++
|
||||
*** 'byte-recompile-directory' can now compile symlinked ".el" files.
|
||||
|
|
205
lisp/net/tramp-fuse.el
Normal file
205
lisp/net/tramp-fuse.el
Normal file
|
@ -0,0 +1,205 @@
|
|||
;;; tramp-fuse.el --- Tramp access functions for FUSE mounts -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Michael Albinus <michael.albinus@gmx.de>
|
||||
;; Keywords: comm, processes
|
||||
;; Package: tramp
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; These are helper functions for FUSE file systems.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'tramp)
|
||||
|
||||
;; File name primitives.
|
||||
|
||||
(defun tramp-fuse-handle-delete-directory
|
||||
(directory &optional recursive trash)
|
||||
"Like `delete-directory' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name directory) nil
|
||||
(tramp-flush-directory-properties v localname)
|
||||
(delete-directory (tramp-fuse-local-file-name directory) recursive trash)))
|
||||
|
||||
(defun tramp-fuse-handle-delete-file (filename &optional trash)
|
||||
"Like `delete-file' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name filename) nil
|
||||
(delete-file (tramp-fuse-local-file-name filename) trash)
|
||||
(tramp-flush-file-properties v localname)))
|
||||
|
||||
(defun tramp-fuse-handle-directory-files
|
||||
(directory &optional full match nosort count)
|
||||
"Like `directory-files' for Tramp files."
|
||||
(unless (file-exists-p directory)
|
||||
(tramp-compat-file-missing (tramp-dissect-file-name directory) directory))
|
||||
(when (file-directory-p directory)
|
||||
(setq directory (file-name-as-directory (expand-file-name directory)))
|
||||
(with-parsed-tramp-file-name directory nil
|
||||
(let ((result
|
||||
(tramp-compat-directory-files
|
||||
(tramp-fuse-local-file-name directory) full match nosort count)))
|
||||
;; Massage the result.
|
||||
(when full
|
||||
(let ((local (concat "^" (regexp-quote (tramp-fuse-mount-point v))))
|
||||
(remote (directory-file-name
|
||||
(funcall
|
||||
(if (tramp-compat-file-name-quoted-p directory)
|
||||
#'tramp-compat-file-name-quote #'identity)
|
||||
(file-remote-p directory)))))
|
||||
(setq result
|
||||
(mapcar
|
||||
(lambda (x) (replace-regexp-in-string local remote x))
|
||||
result))))
|
||||
;; Some storage systems do not return "." and "..".
|
||||
(dolist (item '(".." "."))
|
||||
(when (and (string-match-p (or match (regexp-quote item)) item)
|
||||
(not
|
||||
(member (if full (setq item (concat directory item)) item)
|
||||
result)))
|
||||
(setq result (cons item result))))
|
||||
;; Return result.
|
||||
(if nosort result (sort result #'string<))))))
|
||||
|
||||
(defun tramp-fuse-handle-file-attributes (filename &optional id-format)
|
||||
"Like `file-attributes' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name filename) nil
|
||||
(with-tramp-file-property
|
||||
v localname (format "file-attributes-%s" id-format)
|
||||
(file-attributes (tramp-fuse-local-file-name filename) id-format))))
|
||||
|
||||
(defun tramp-fuse-handle-file-executable-p (filename)
|
||||
"Like `file-executable-p' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name filename) nil
|
||||
(with-tramp-file-property v localname "file-executable-p"
|
||||
(file-executable-p (tramp-fuse-local-file-name filename)))))
|
||||
|
||||
(defun tramp-fuse-handle-file-name-all-completions (filename directory)
|
||||
"Like `file-name-all-completions' for Tramp files."
|
||||
(all-completions
|
||||
filename
|
||||
(delete-dups
|
||||
(append
|
||||
(file-name-all-completions
|
||||
filename (tramp-fuse-local-file-name directory))
|
||||
;; Some storage systems do not return "." and "..".
|
||||
(let (result)
|
||||
(dolist (item '(".." ".") result)
|
||||
(when (string-prefix-p filename item)
|
||||
(catch 'match
|
||||
(dolist (elt completion-regexp-list)
|
||||
(unless (string-match-p elt item) (throw 'match nil)))
|
||||
(setq result (cons (concat item "/") result))))))))))
|
||||
|
||||
(defun tramp-fuse-handle-file-readable-p (filename)
|
||||
"Like `file-readable-p' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name filename) nil
|
||||
(with-tramp-file-property v localname "file-readable-p"
|
||||
(file-readable-p (tramp-fuse-local-file-name filename)))))
|
||||
|
||||
;; This function isn't used.
|
||||
(defun tramp-fuse-handle-insert-directory
|
||||
(filename switches &optional wildcard full-directory-p)
|
||||
"Like `insert-directory' for Tramp files."
|
||||
(insert-directory
|
||||
(tramp-fuse-local-file-name filename) switches wildcard full-directory-p)
|
||||
(goto-char (point-min))
|
||||
(while (search-forward (tramp-fuse-local-file-name filename) nil 'noerror)
|
||||
(replace-match filename)))
|
||||
|
||||
(defun tramp-fuse-handle-make-directory (dir &optional parents)
|
||||
"Like `make-directory' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name dir) nil
|
||||
(make-directory (tramp-fuse-local-file-name dir) parents)
|
||||
;; When PARENTS is non-nil, DIR could be a chain of non-existent
|
||||
;; directories a/b/c/... Instead of checking, we simply flush the
|
||||
;; whole file cache.
|
||||
(tramp-flush-file-properties v localname)
|
||||
(tramp-flush-directory-properties
|
||||
v (if parents "/" (file-name-directory localname)))))
|
||||
|
||||
|
||||
;; File name helper functions.
|
||||
|
||||
(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)))
|
||||
(format "%s@%s:/" user host)
|
||||
(format "%s:/" host)))
|
||||
|
||||
(defun tramp-fuse-mount-point (vec)
|
||||
"Return local mount point of VEC."
|
||||
(or (tramp-get-connection-property vec "mount-point" nil)
|
||||
(expand-file-name
|
||||
(concat
|
||||
tramp-temp-name-prefix
|
||||
(tramp-file-name-method vec) "."
|
||||
(when (tramp-file-name-user vec)
|
||||
(concat (tramp-file-name-user-domain vec) "@"))
|
||||
(tramp-file-name-host-port vec))
|
||||
(tramp-compat-temporary-file-directory))))
|
||||
|
||||
(defun tramp-fuse-mounted-p (vec)
|
||||
"Check, whether fuse volume determined by VEC is mounted."
|
||||
(when (tramp-get-connection-process vec)
|
||||
;; We cannot use `with-connection-property', because we don't want
|
||||
;; to cache a nil result.
|
||||
(or (tramp-get-connection-property
|
||||
(tramp-get-connection-process vec) "mounted" nil)
|
||||
(let* ((default-directory (tramp-compat-temporary-file-directory))
|
||||
(fuse (concat "fuse." (tramp-file-name-method vec)))
|
||||
(mount (shell-command-to-string (format "mount -t %s" fuse))))
|
||||
(tramp-message vec 6 "%s %s" "mount -t" fuse)
|
||||
(tramp-message vec 6 "\n%s" mount)
|
||||
(tramp-set-connection-property
|
||||
(tramp-get-connection-process vec) "mounted"
|
||||
(when (string-match
|
||||
(format
|
||||
"^\\(%s\\)\\s-" (regexp-quote (tramp-fuse-mount-spec vec)))
|
||||
mount)
|
||||
(match-string 1 mount)))))))
|
||||
|
||||
(defun tramp-fuse-local-file-name (filename)
|
||||
"Return local mount name of FILENAME."
|
||||
(setq filename (tramp-compat-file-name-unquote (expand-file-name filename)))
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
;; As long as we call `tramp-*-maybe-open-connection' here,
|
||||
;; we cache the result.
|
||||
(with-tramp-file-property v localname "local-file-name"
|
||||
(funcall
|
||||
(intern
|
||||
(format "tramp-%s-maybe-open-connection" (tramp-file-name-method v)))
|
||||
v)
|
||||
(let ((quoted (tramp-compat-file-name-quoted-p localname))
|
||||
(localname (tramp-compat-file-name-unquote localname)))
|
||||
(funcall
|
||||
(if quoted #'tramp-compat-file-name-quote #'identity)
|
||||
(expand-file-name
|
||||
(if (file-name-absolute-p localname)
|
||||
(substring localname 1) localname)
|
||||
(tramp-fuse-mount-point v)))))))
|
||||
|
||||
(add-hook 'tramp-unload-hook
|
||||
(lambda ()
|
||||
(unload-feature 'tramp-fuse 'force)))
|
||||
|
||||
(provide 'tramp-fuse)
|
||||
|
||||
;;; tramp-fuse.el ends here
|
|
@ -35,8 +35,8 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(eval-when-compile (require 'cl-lib))
|
||||
(require 'tramp)
|
||||
(require 'tramp-fuse)
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defconst tramp-rclone-method "rclone"
|
||||
|
@ -77,11 +77,11 @@
|
|||
;; `byte-compiler-base-file-name' performed by default handler.
|
||||
(copy-directory . tramp-handle-copy-directory)
|
||||
(copy-file . tramp-rclone-handle-copy-file)
|
||||
(delete-directory . tramp-rclone-handle-delete-directory)
|
||||
(delete-file . tramp-rclone-handle-delete-file)
|
||||
(delete-directory . tramp-fuse-handle-delete-directory)
|
||||
(delete-file . tramp-fuse-handle-delete-file)
|
||||
;; `diff-latest-backup-file' performed by default handler.
|
||||
(directory-file-name . tramp-handle-directory-file-name)
|
||||
(directory-files . tramp-rclone-handle-directory-files)
|
||||
(directory-files . tramp-fuse-handle-directory-files)
|
||||
(directory-files-and-attributes
|
||||
. tramp-handle-directory-files-and-attributes)
|
||||
(dired-compress-file . ignore)
|
||||
|
@ -90,15 +90,15 @@
|
|||
(expand-file-name . tramp-handle-expand-file-name)
|
||||
(file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
|
||||
(file-acl . ignore)
|
||||
(file-attributes . tramp-rclone-handle-file-attributes)
|
||||
(file-attributes . tramp-fuse-handle-file-attributes)
|
||||
(file-directory-p . tramp-handle-file-directory-p)
|
||||
(file-equal-p . tramp-handle-file-equal-p)
|
||||
(file-executable-p . tramp-rclone-handle-file-executable-p)
|
||||
(file-executable-p . tramp-fuse-handle-file-executable-p)
|
||||
(file-exists-p . tramp-handle-file-exists-p)
|
||||
(file-in-directory-p . tramp-handle-file-in-directory-p)
|
||||
(file-local-copy . tramp-handle-file-local-copy)
|
||||
(file-modes . tramp-handle-file-modes)
|
||||
(file-name-all-completions . tramp-rclone-handle-file-name-all-completions)
|
||||
(file-name-all-completions . tramp-fuse-handle-file-name-all-completions)
|
||||
(file-name-as-directory . tramp-handle-file-name-as-directory)
|
||||
(file-name-case-insensitive-p . tramp-handle-file-name-case-insensitive-p)
|
||||
(file-name-completion . tramp-handle-file-name-completion)
|
||||
|
@ -110,7 +110,7 @@
|
|||
(file-notify-rm-watch . ignore)
|
||||
(file-notify-valid-p . ignore)
|
||||
(file-ownership-preserved-p . ignore)
|
||||
(file-readable-p . tramp-rclone-handle-file-readable-p)
|
||||
(file-readable-p . tramp-fuse-handle-file-readable-p)
|
||||
(file-regular-p . tramp-handle-file-regular-p)
|
||||
(file-remote-p . tramp-handle-file-remote-p)
|
||||
(file-selinux-context . tramp-handle-file-selinux-context)
|
||||
|
@ -124,7 +124,7 @@
|
|||
(insert-file-contents . tramp-handle-insert-file-contents)
|
||||
(load . tramp-handle-load)
|
||||
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
|
||||
(make-directory . tramp-rclone-handle-make-directory)
|
||||
(make-directory . tramp-fuse-handle-make-directory)
|
||||
(make-directory-internal . ignore)
|
||||
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
|
||||
(make-process . ignore)
|
||||
|
@ -277,86 +277,6 @@ file names."
|
|||
(list filename newname ok-if-already-exists keep-date
|
||||
preserve-uid-gid preserve-extended-attributes))))
|
||||
|
||||
(defun tramp-rclone-handle-delete-directory
|
||||
(directory &optional recursive trash)
|
||||
"Like `delete-directory' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name directory) nil
|
||||
(tramp-flush-directory-properties v localname)
|
||||
(delete-directory (tramp-rclone-local-file-name directory) recursive trash)))
|
||||
|
||||
(defun tramp-rclone-handle-delete-file (filename &optional trash)
|
||||
"Like `delete-file' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name filename) nil
|
||||
(delete-file (tramp-rclone-local-file-name filename) trash)
|
||||
(tramp-flush-file-properties v localname)))
|
||||
|
||||
(defun tramp-rclone-handle-directory-files
|
||||
(directory &optional full match nosort count)
|
||||
"Like `directory-files' for Tramp files."
|
||||
(unless (file-exists-p directory)
|
||||
(tramp-compat-file-missing (tramp-dissect-file-name directory) directory))
|
||||
(when (file-directory-p directory)
|
||||
(setq directory (file-name-as-directory (expand-file-name directory)))
|
||||
(with-parsed-tramp-file-name directory nil
|
||||
(let ((result
|
||||
(tramp-compat-directory-files
|
||||
(tramp-rclone-local-file-name directory) full match nosort count)))
|
||||
;; Massage the result.
|
||||
(when full
|
||||
(let ((local (concat "^" (regexp-quote (tramp-rclone-mount-point v))))
|
||||
(remote (funcall (if (tramp-compat-file-name-quoted-p directory)
|
||||
#'tramp-compat-file-name-quote #'identity)
|
||||
(file-remote-p directory))))
|
||||
(setq result
|
||||
(mapcar
|
||||
(lambda (x) (replace-regexp-in-string local remote x))
|
||||
result))))
|
||||
;; Some storage systems do not return "." and "..".
|
||||
(dolist (item '(".." "."))
|
||||
(when (and (string-match-p (or match (regexp-quote item)) item)
|
||||
(not
|
||||
(member (if full (setq item (concat directory item)) item)
|
||||
result)))
|
||||
(setq result (cons item result))))
|
||||
;; Return result.
|
||||
(if nosort result (sort result #'string<))))))
|
||||
|
||||
(defun tramp-rclone-handle-file-attributes (filename &optional id-format)
|
||||
"Like `file-attributes' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name filename) nil
|
||||
(with-tramp-file-property
|
||||
v localname (format "file-attributes-%s" id-format)
|
||||
(file-attributes (tramp-rclone-local-file-name filename) id-format))))
|
||||
|
||||
(defun tramp-rclone-handle-file-executable-p (filename)
|
||||
"Like `file-executable-p' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name filename) nil
|
||||
(with-tramp-file-property v localname "file-executable-p"
|
||||
(file-executable-p (tramp-rclone-local-file-name filename)))))
|
||||
|
||||
(defun tramp-rclone-handle-file-name-all-completions (filename directory)
|
||||
"Like `file-name-all-completions' for Tramp files."
|
||||
(all-completions
|
||||
filename
|
||||
(delete-dups
|
||||
(append
|
||||
(file-name-all-completions
|
||||
filename (tramp-rclone-local-file-name directory))
|
||||
;; Some storage systems do not return "." and "..".
|
||||
(let (result)
|
||||
(dolist (item '(".." ".") result)
|
||||
(when (string-prefix-p filename item)
|
||||
(catch 'match
|
||||
(dolist (elt completion-regexp-list)
|
||||
(unless (string-match-p elt item) (throw 'match nil)))
|
||||
(setq result (cons (concat item "/") result))))))))))
|
||||
|
||||
(defun tramp-rclone-handle-file-readable-p (filename)
|
||||
"Like `file-readable-p' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name filename) nil
|
||||
(with-tramp-file-property v localname "file-readable-p"
|
||||
(file-readable-p (tramp-rclone-local-file-name filename)))))
|
||||
|
||||
(defun tramp-rclone-handle-file-system-info (filename)
|
||||
"Like `file-system-info' for Tramp files."
|
||||
(ignore-errors
|
||||
|
@ -384,36 +304,6 @@ file names."
|
|||
(when (and total free)
|
||||
(list total free (- total free))))))))
|
||||
|
||||
(defun tramp-rclone-handle-insert-directory
|
||||
(filename switches &optional wildcard full-directory-p)
|
||||
"Like `insert-directory' for Tramp files."
|
||||
(insert-directory
|
||||
(tramp-rclone-local-file-name filename) switches wildcard full-directory-p)
|
||||
(goto-char (point-min))
|
||||
(while (search-forward (tramp-rclone-local-file-name filename) nil 'noerror)
|
||||
(replace-match filename)))
|
||||
|
||||
(defun tramp-rclone-handle-insert-file-contents
|
||||
(filename &optional visit beg end replace)
|
||||
"Like `insert-file-contents' for Tramp files."
|
||||
(let ((result
|
||||
(insert-file-contents
|
||||
(tramp-rclone-local-file-name filename) visit beg end replace)))
|
||||
(prog1
|
||||
(list (expand-file-name filename) (cadr result))
|
||||
(when visit (setq buffer-file-name filename)))))
|
||||
|
||||
(defun tramp-rclone-handle-make-directory (dir &optional parents)
|
||||
"Like `make-directory' for Tramp files."
|
||||
(with-parsed-tramp-file-name (expand-file-name dir) nil
|
||||
(make-directory (tramp-rclone-local-file-name dir) parents)
|
||||
;; When PARENTS is non-nil, DIR could be a chain of non-existent
|
||||
;; directories a/b/c/... Instead of checking, we simply flush the
|
||||
;; whole file cache.
|
||||
(tramp-flush-file-properties v localname)
|
||||
(tramp-flush-directory-properties
|
||||
v (if parents "/" (file-name-directory localname)))))
|
||||
|
||||
(defun tramp-rclone-handle-rename-file
|
||||
(filename newname &optional ok-if-already-exists)
|
||||
"Like `rename-file' for Tramp files."
|
||||
|
@ -431,50 +321,6 @@ file names."
|
|||
|
||||
;; File name conversions.
|
||||
|
||||
(defun tramp-rclone-mount-point (vec)
|
||||
"Return local mount point of VEC."
|
||||
(expand-file-name
|
||||
(concat
|
||||
tramp-temp-name-prefix (tramp-file-name-method vec)
|
||||
"." (tramp-file-name-host vec))
|
||||
(tramp-compat-temporary-file-directory)))
|
||||
|
||||
(defun tramp-rclone-mounted-p (vec)
|
||||
"Check, whether storage system determined by VEC is mounted."
|
||||
(when (tramp-get-connection-process vec)
|
||||
;; We cannot use `with-connection-property', because we don't want
|
||||
;; to cache a nil result.
|
||||
(or (tramp-get-connection-property
|
||||
(tramp-get-connection-process vec) "mounted" nil)
|
||||
(let* ((default-directory (tramp-compat-temporary-file-directory))
|
||||
(mount (shell-command-to-string "mount -t fuse.rclone")))
|
||||
(tramp-message vec 6 "%s" "mount -t fuse.rclone")
|
||||
(tramp-message vec 6 "\n%s" mount)
|
||||
(tramp-set-connection-property
|
||||
(tramp-get-connection-process vec) "mounted"
|
||||
(when (string-match
|
||||
(format
|
||||
"^\\(%s:\\S-*\\)" (regexp-quote (tramp-file-name-host vec)))
|
||||
mount)
|
||||
(match-string 1 mount)))))))
|
||||
|
||||
(defun tramp-rclone-local-file-name (filename)
|
||||
"Return local mount name of FILENAME."
|
||||
(setq filename (tramp-compat-file-name-unquote (expand-file-name filename)))
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
;; As long as we call `tramp-rclone-maybe-open-connection' here,
|
||||
;; we cache the result.
|
||||
(with-tramp-file-property v localname "local-file-name"
|
||||
(tramp-rclone-maybe-open-connection v)
|
||||
(let ((quoted (tramp-compat-file-name-quoted-p localname))
|
||||
(localname (tramp-compat-file-name-unquote localname)))
|
||||
(funcall
|
||||
(if quoted #'tramp-compat-file-name-quote #'identity)
|
||||
(expand-file-name
|
||||
(if (file-name-absolute-p localname)
|
||||
(substring localname 1) localname)
|
||||
(tramp-rclone-mount-point v)))))))
|
||||
|
||||
(defun tramp-rclone-remote-file-name (filename)
|
||||
"Return FILENAME as used in the `rclone' command."
|
||||
(setq filename (tramp-compat-file-name-unquote (expand-file-name filename)))
|
||||
|
@ -487,7 +333,7 @@ file names."
|
|||
;; TODO: This shall be handled by `expand-file-name'.
|
||||
(setq localname
|
||||
(replace-regexp-in-string "^\\." "" (or localname "")))
|
||||
(format "%s%s" (tramp-rclone-mounted-p v) localname)))
|
||||
(format "%s%s" (tramp-fuse-mounted-p v) localname)))
|
||||
;; It is a local file name.
|
||||
filename))
|
||||
|
||||
|
@ -517,20 +363,18 @@ connection if a previous connection has died for some reason."
|
|||
(tramp-set-connection-local-variables vec)))
|
||||
|
||||
;; Create directory.
|
||||
(unless (file-directory-p (tramp-rclone-mount-point vec))
|
||||
(make-directory (tramp-rclone-mount-point vec) 'parents))
|
||||
(unless (file-directory-p (tramp-fuse-mount-point vec))
|
||||
(make-directory (tramp-fuse-mount-point vec) 'parents))
|
||||
|
||||
;; Mount. This command does not return, so we use 0 as
|
||||
;; DESTINATION of `tramp-call-process'.
|
||||
(unless (tramp-rclone-mounted-p vec)
|
||||
(unless (tramp-fuse-mounted-p vec)
|
||||
(apply
|
||||
#'tramp-call-process
|
||||
vec tramp-rclone-program nil 0 nil
|
||||
(delq nil
|
||||
`("mount" ,(concat host ":/")
|
||||
,(tramp-rclone-mount-point vec)
|
||||
;; This could be nil.
|
||||
,@(tramp-get-method-parameter vec 'tramp-mount-args))))
|
||||
"mount" (tramp-fuse-mount-spec vec)
|
||||
(tramp-fuse-mount-point vec)
|
||||
(tramp-get-method-parameter vec 'tramp-mount-args))
|
||||
(while (not (file-exists-p (tramp-make-tramp-file-name vec 'noloc)))
|
||||
(tramp-cleanup-connection vec 'keep-debug 'keep-password))
|
||||
|
||||
|
|
|
@ -2397,7 +2397,7 @@ The method used must be an out-of-band method."
|
|||
(append
|
||||
copy-args
|
||||
(let ((y (mapcar (lambda (z) (format-spec z spec)) x)))
|
||||
(if (member "" y) '(" ") y))))))
|
||||
(unless (member "" y) y))))))
|
||||
|
||||
copy-env
|
||||
(delq
|
||||
|
@ -2416,7 +2416,7 @@ The method used must be an out-of-band method."
|
|||
(append
|
||||
remote-copy-args
|
||||
(let ((y (mapcar (lambda (z) (format-spec z spec)) x)))
|
||||
(if (member "" y) '(" ") y)))))
|
||||
(unless (member "" y) y)))))
|
||||
|
||||
;; Check for local copy program.
|
||||
(unless (executable-find copy-program)
|
||||
|
|
318
lisp/net/tramp-sshfs.el
Normal file
318
lisp/net/tramp-sshfs.el
Normal file
|
@ -0,0 +1,318 @@
|
|||
;;; tramp-sshfs.el --- Tramp access functions via sshfs -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Michael Albinus <michael.albinus@gmx.de>
|
||||
;; Keywords: comm, processes
|
||||
;; Package: tramp
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; sshfs is a program to mount a virtual file system, based on an sftp
|
||||
;; connection. Tramp uses its mount utility to access files and
|
||||
;; directories there.
|
||||
|
||||
;; A remote file under sshfs control has the form
|
||||
;; "/sshfs:user@host#port:/path/to/file". User name and port number
|
||||
;; are optional.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'tramp)
|
||||
(require 'tramp-fuse)
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defconst tramp-sshfs-method "sshfs"
|
||||
"Tramp method for sshfs mounts.")
|
||||
|
||||
;;;###tramp-autoload
|
||||
(defcustom tramp-sshfs-program "sshfs"
|
||||
"The sshfs mount command."
|
||||
:group 'tramp
|
||||
:version "28.1"
|
||||
:type 'string)
|
||||
|
||||
;;;###tramp-autoload
|
||||
(tramp--with-startup
|
||||
(add-to-list 'tramp-methods
|
||||
`(,tramp-sshfs-method
|
||||
(tramp-mount-args
|
||||
(("-p" "%p")
|
||||
("-o" "idmap=user,reconnect")))))
|
||||
|
||||
(tramp-set-completion-function
|
||||
tramp-sshfs-method tramp-completion-function-alist-ssh))
|
||||
|
||||
|
||||
;; New handlers should be added here.
|
||||
;;;###tramp-autoload
|
||||
(defconst tramp-sshfs-file-name-handler-alist
|
||||
'((access-file . tramp-handle-access-file)
|
||||
(add-name-to-file . tramp-handle-add-name-to-file)
|
||||
;; `byte-compiler-base-file-name' performed by default handler.
|
||||
(copy-directory . tramp-handle-copy-directory)
|
||||
(copy-file . tramp-sshfs-handle-copy-file)
|
||||
(delete-directory . tramp-fuse-handle-delete-directory)
|
||||
(delete-file . tramp-fuse-handle-delete-file)
|
||||
;; `diff-latest-backup-file' performed by default handler.
|
||||
(directory-file-name . tramp-handle-directory-file-name)
|
||||
(directory-files . tramp-fuse-handle-directory-files)
|
||||
(directory-files-and-attributes
|
||||
. tramp-handle-directory-files-and-attributes)
|
||||
(dired-compress-file . ignore)
|
||||
(dired-uncache . tramp-handle-dired-uncache)
|
||||
;; (exec-path . ignore)
|
||||
(expand-file-name . tramp-handle-expand-file-name)
|
||||
(file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
|
||||
(file-acl . ignore)
|
||||
(file-attributes . tramp-fuse-handle-file-attributes)
|
||||
(file-directory-p . tramp-handle-file-directory-p)
|
||||
(file-equal-p . tramp-handle-file-equal-p)
|
||||
(file-executable-p . tramp-fuse-handle-file-executable-p)
|
||||
(file-exists-p . tramp-handle-file-exists-p)
|
||||
(file-in-directory-p . tramp-handle-file-in-directory-p)
|
||||
(file-local-copy . tramp-handle-file-local-copy)
|
||||
(file-modes . tramp-handle-file-modes)
|
||||
(file-name-all-completions . tramp-fuse-handle-file-name-all-completions)
|
||||
(file-name-as-directory . tramp-handle-file-name-as-directory)
|
||||
(file-name-case-insensitive-p . tramp-handle-file-name-case-insensitive-p)
|
||||
(file-name-completion . tramp-handle-file-name-completion)
|
||||
(file-name-directory . tramp-handle-file-name-directory)
|
||||
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
|
||||
;; `file-name-sans-versions' performed by default handler.
|
||||
(file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
|
||||
(file-notify-add-watch . ignore)
|
||||
(file-notify-rm-watch . ignore)
|
||||
(file-notify-valid-p . ignore)
|
||||
(file-ownership-preserved-p . ignore)
|
||||
(file-readable-p . tramp-fuse-handle-file-readable-p)
|
||||
(file-regular-p . tramp-handle-file-regular-p)
|
||||
(file-remote-p . tramp-handle-file-remote-p)
|
||||
(file-selinux-context . tramp-handle-file-selinux-context)
|
||||
(file-symlink-p . tramp-handle-file-symlink-p)
|
||||
(file-system-info . tramp-sshfs-handle-file-system-info)
|
||||
(file-truename . tramp-handle-file-truename)
|
||||
(file-writable-p . tramp-handle-file-writable-p)
|
||||
(find-backup-file-name . tramp-handle-find-backup-file-name)
|
||||
;; `get-file-buffer' performed by default handler.
|
||||
(insert-directory . tramp-handle-insert-directory)
|
||||
(insert-file-contents . tramp-sshfs-handle-insert-file-contents)
|
||||
(load . tramp-handle-load)
|
||||
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
|
||||
(make-directory . tramp-fuse-handle-make-directory)
|
||||
(make-directory-internal . ignore)
|
||||
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
|
||||
;; (make-process . ignore)
|
||||
(make-symbolic-link . tramp-handle-make-symbolic-link)
|
||||
;; (process-file . ignore)
|
||||
(rename-file . tramp-sshfs-handle-rename-file)
|
||||
(set-file-acl . ignore)
|
||||
(set-file-modes . ignore)
|
||||
(set-file-selinux-context . ignore)
|
||||
(set-file-times . ignore)
|
||||
(set-visited-file-modtime . tramp-handle-set-visited-file-modtime)
|
||||
;; (shell-command . ignore)
|
||||
;; (start-file-process . ignore)
|
||||
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
|
||||
(temporary-file-directory . tramp-handle-temporary-file-directory)
|
||||
;; (tramp-get-remote-gid . ignore)
|
||||
;; (tramp-get-remote-uid . ignore)
|
||||
;; (tramp-set-file-uid-gid . ignore)
|
||||
(unhandled-file-name-directory . ignore)
|
||||
(vc-registered . ignore)
|
||||
(verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime)
|
||||
(write-region . tramp-sshfs-handle-write-region))
|
||||
"Alist of handler functions for Tramp SSHFS method.
|
||||
Operations not mentioned here will be handled by the default Emacs primitives.")
|
||||
|
||||
;; It must be a `defsubst' in order to push the whole code into
|
||||
;; tramp-loaddefs.el. Otherwise, there would be recursive autoloading.
|
||||
;;;###tramp-autoload
|
||||
(defsubst tramp-sshfs-file-name-p (filename)
|
||||
"Check if it's a FILENAME for sshfs."
|
||||
(and (tramp-tramp-file-p filename)
|
||||
(string= (tramp-file-name-method (tramp-dissect-file-name filename))
|
||||
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)))
|
||||
(save-match-data (apply (cdr fn) args))
|
||||
(tramp-run-real-handler operation args)))
|
||||
|
||||
;;;###tramp-autoload
|
||||
(tramp--with-startup
|
||||
(tramp-register-foreign-file-name-handler
|
||||
#'tramp-sshfs-file-name-p #'tramp-sshfs-file-name-handler))
|
||||
|
||||
|
||||
;; File name primitives.
|
||||
|
||||
(defun tramp-sshfs-handle-copy-file
|
||||
(filename newname &optional ok-if-already-exists keep-date
|
||||
preserve-uid-gid preserve-extended-attributes)
|
||||
"Like `copy-file' for Tramp files."
|
||||
(setq filename (expand-file-name filename)
|
||||
newname (expand-file-name newname))
|
||||
(if (file-directory-p filename)
|
||||
(copy-directory filename newname keep-date t)
|
||||
(copy-file
|
||||
(if (tramp-sshfs-file-name-p filename)
|
||||
(tramp-fuse-local-file-name filename) filename)
|
||||
(if (tramp-sshfs-file-name-p newname)
|
||||
(tramp-fuse-local-file-name newname) newname)
|
||||
ok-if-already-exists keep-date
|
||||
preserve-uid-gid preserve-extended-attributes)
|
||||
(when (tramp-sshfs-file-name-p newname)
|
||||
(with-parsed-tramp-file-name newname nil
|
||||
(tramp-flush-file-properties v localname)))))
|
||||
|
||||
(defun tramp-sshfs-handle-file-system-info (filename)
|
||||
"Like `file-system-info' for Tramp files."
|
||||
;;`file-system-info' exists since Emacs 27.1.
|
||||
(tramp-compat-funcall 'file-system-info (tramp-fuse-local-file-name filename)))
|
||||
|
||||
(defun tramp-sshfs-handle-insert-file-contents
|
||||
(filename &optional visit beg end replace)
|
||||
"Like `insert-file-contents' for Tramp files."
|
||||
(let ((result
|
||||
(insert-file-contents
|
||||
(tramp-fuse-local-file-name filename) visit beg end replace)))
|
||||
(when visit (setq buffer-file-name filename))
|
||||
(cons (expand-file-name filename) (cdr result))))
|
||||
|
||||
(defun tramp-sshfs-handle-rename-file
|
||||
(filename newname &optional ok-if-already-exists)
|
||||
"Like `rename-file' for Tramp files."
|
||||
(setq filename (expand-file-name filename)
|
||||
newname (expand-file-name newname))
|
||||
(rename-file
|
||||
(if (tramp-sshfs-file-name-p filename)
|
||||
(tramp-fuse-local-file-name filename) filename)
|
||||
(if (tramp-sshfs-file-name-p newname)
|
||||
(tramp-fuse-local-file-name newname) newname)
|
||||
ok-if-already-exists)
|
||||
(when (tramp-sshfs-file-name-p filename)
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
(tramp-flush-file-properties v localname)))
|
||||
(when (tramp-sshfs-file-name-p newname)
|
||||
(with-parsed-tramp-file-name newname nil
|
||||
(tramp-flush-file-properties v localname))))
|
||||
|
||||
(defun tramp-sshfs-handle-write-region
|
||||
(start end filename &optional append visit lockname mustbenew)
|
||||
"Like `write-region' for Tramp files."
|
||||
(setq filename (expand-file-name filename))
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
(when (and mustbenew (file-exists-p filename)
|
||||
(or (eq mustbenew 'excl)
|
||||
(not
|
||||
(y-or-n-p
|
||||
(format "File %s exists; overwrite anyway? " filename)))))
|
||||
(tramp-error v 'file-already-exists filename))
|
||||
|
||||
(write-region
|
||||
start end (tramp-fuse-local-file-name filename) append 'nomessage lockname)
|
||||
(tramp-flush-file-properties v localname)
|
||||
|
||||
;; The end.
|
||||
(when (and (null noninteractive)
|
||||
(or (eq visit t) (null visit) (stringp visit)))
|
||||
(tramp-message v 0 "Wrote %s" filename))
|
||||
(run-hooks 'tramp-handle-write-region-hook)))
|
||||
|
||||
|
||||
;; File name conversions.
|
||||
|
||||
(defun tramp-sshfs-maybe-open-connection (vec)
|
||||
"Maybe open a connection VEC.
|
||||
Does not do anything if a connection is already open, but re-opens the
|
||||
connection if a previous connection has died for some reason."
|
||||
;; During completion, don't reopen a new connection.
|
||||
(unless (tramp-connectable-p vec)
|
||||
(throw 'non-essential 'non-essential))
|
||||
|
||||
;; We need a process bound to the connection buffer. Therefore, we
|
||||
;; create a dummy process. Maybe there is a better solution?
|
||||
(unless (get-buffer-process (tramp-get-connection-buffer vec))
|
||||
(let ((p (make-network-process
|
||||
:name (tramp-get-connection-name vec)
|
||||
:buffer (tramp-get-connection-buffer vec)
|
||||
:server t :host 'local :service t :noquery t)))
|
||||
(process-put p 'vector vec)
|
||||
(set-process-query-on-exit-flag p nil)
|
||||
|
||||
;; Set connection-local variables.
|
||||
(tramp-set-connection-local-variables vec)
|
||||
|
||||
;; Create directory.
|
||||
(unless (file-directory-p (tramp-fuse-mount-point vec))
|
||||
(make-directory (tramp-fuse-mount-point vec) 'parents))
|
||||
|
||||
(unless
|
||||
(or (tramp-fuse-mounted-p vec)
|
||||
(let* ((port (or (tramp-file-name-port vec) ""))
|
||||
(spec (format-spec-make ?p port))
|
||||
mount-args
|
||||
(mount-args
|
||||
(dolist
|
||||
(x
|
||||
(tramp-get-method-parameter vec 'tramp-mount-args)
|
||||
mount-args)
|
||||
(setq mount-args
|
||||
(append
|
||||
mount-args
|
||||
(let ((y (mapcar
|
||||
(lambda (z) (format-spec z spec))
|
||||
x)))
|
||||
(unless (member "" y) y)))))))
|
||||
(with-temp-buffer
|
||||
(zerop
|
||||
(apply
|
||||
#'tramp-call-process
|
||||
vec tramp-sshfs-program nil t nil
|
||||
(tramp-fuse-mount-spec vec)
|
||||
(tramp-fuse-mount-point vec) mount-args))))
|
||||
(tramp-error
|
||||
vec 'file-error "Error mounting %s" (tramp-fuse-mount-spec vec))))
|
||||
|
||||
;; Mark it as connected.
|
||||
(tramp-set-connection-property
|
||||
(tramp-get-connection-process vec) "connected" t)))
|
||||
|
||||
;; In `tramp-check-cached-permissions', the connection properties
|
||||
;; "{uid,gid}-{integer,string}" are used. We set them to proper values.
|
||||
(with-tramp-connection-property
|
||||
vec "uid-integer" (tramp-get-local-uid 'integer))
|
||||
(with-tramp-connection-property
|
||||
vec "gid-integer" (tramp-get-local-gid 'integer))
|
||||
(with-tramp-connection-property
|
||||
vec "uid-string" (tramp-get-local-uid 'string))
|
||||
(with-tramp-connection-property
|
||||
vec "gid-string" (tramp-get-local-gid 'string)))
|
||||
|
||||
(add-hook 'tramp-unload-hook
|
||||
(lambda ()
|
||||
(unload-feature 'tramp-sshfs 'force)))
|
||||
|
||||
(provide 'tramp-sshfs)
|
||||
|
||||
;;; tramp-sshfs.el ends here
|
|
@ -5447,11 +5447,6 @@ BODY is the backend specific code."
|
|||
;; strange when doing zerop, we should kill the process and start
|
||||
;; again. (Greg Stark)
|
||||
;;
|
||||
;; * I was wondering if it would be possible to use tramp even if I'm
|
||||
;; actually using sshfs. But when I launch a command I would like
|
||||
;; to get it executed on the remote machine where the files really
|
||||
;; are. (Andrea Crotti)
|
||||
;;
|
||||
;; * Run emerge on two remote files. Bug is described here:
|
||||
;; <https://www.mail-archive.com/tramp-devel@nongnu.org/msg01041.html>.
|
||||
;; (Bug#6850)
|
||||
|
|
|
@ -2824,9 +2824,10 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
|
|||
(should (file-exists-p (expand-file-name "bla" tmp-name2)))
|
||||
(should-error
|
||||
(delete-directory tmp-name1 nil 'trash)
|
||||
;; tramp-rclone.el calls the local `delete-directory'.
|
||||
;; This raises another error.
|
||||
:type (if (tramp--test-rclone-p) 'error 'file-error))
|
||||
;; tramp-rclone.el and tramp-sshfs.el call the local
|
||||
;; `delete-directory'. This raises another error.
|
||||
:type (if (or (tramp--test-rclone-p) (tramp--test-sshfs-p))
|
||||
'error 'file-error))
|
||||
(delete-directory tmp-name1 'recursive 'trash)
|
||||
(should-not (file-directory-p tmp-name1))
|
||||
(should
|
||||
|
@ -3254,8 +3255,8 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
|
|||
(ignore-errors (delete-directory tmp-name1 'recursive))))))
|
||||
|
||||
;; Method "smb" supports `make-symbolic-link' only if the remote host
|
||||
;; has CIFS capabilities. tramp-adb.el, tramp-gvfs.el and
|
||||
;; tramp-rclone.el do not support symbolic links at all.
|
||||
;; has CIFS capabilities. tramp-adb.el, tramp-gvfs.el, tramp-rclone.el
|
||||
;; and tramp-sshfs.el do not support symbolic links at all.
|
||||
(defmacro tramp--test-ignore-make-symbolic-link-error (&rest body)
|
||||
"Run BODY, ignoring \"make-symbolic-link not supported\" file error."
|
||||
(declare (indent defun) (debug (body)))
|
||||
|
@ -5819,6 +5820,11 @@ Additionally, ls does not support \"--dired\"."
|
|||
"^\\(afp\\|davs?\\|smb\\)$"
|
||||
(file-remote-p tramp-test-temporary-file-directory 'method))))
|
||||
|
||||
(defun tramp--test-sshfs-p ()
|
||||
"Check, whether the remote host is offered by sshfs.
|
||||
This requires restrictions of file name syntax."
|
||||
(tramp-sshfs-file-name-p tramp-test-temporary-file-directory))
|
||||
|
||||
(defun tramp--test-sudoedit-p ()
|
||||
"Check, whether the sudoedit method is used."
|
||||
(tramp-sudoedit-file-name-p tramp-test-temporary-file-directory))
|
||||
|
@ -6761,7 +6767,6 @@ If INTERACTIVE is non-nil, the tests are run interactively."
|
|||
;; * Fix `tramp-test06-directory-file-name' for `ftp'.
|
||||
;; * Implement `tramp-test31-interrupt-process' for `adb' and for
|
||||
;; direct async processes.
|
||||
;; * Fix `tramp-test44-threads'.
|
||||
|
||||
(provide 'tramp-tests)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue