pub trait Workspace:
Send
+ Sync
+ Debug
+ 'static {
Show 15 methods
// Required methods
fn stat(&self, path: &Path) -> Result<Stat>;
fn read(&self, path: &Path, limit: u64) -> Result<Contents>;
fn write(&self, path: &Path, bytes: &[u8]) -> Result<()>;
fn remove(&self, path: &Path) -> Result<()>;
fn rename(&self, from: &Path, to: &Path) -> Result<()>;
fn canonical(&self, path: &Path) -> PathBuf;
fn files(
&self,
root: &Path,
glob: Option<&str>,
listing: Listing,
) -> Result<Vec<PathBuf>>;
fn spawn(
&self,
launcher: &Launcher,
dir: Option<&Path>,
program: &OsStr,
args: &[OsString],
how: Spawn,
) -> Result<Process>;
// Provided methods
fn host(&self) -> Option<&str> { ... }
fn read_files(&self, paths: &[PathBuf], limit: u64) -> Vec<Option<Vec<u8>>> { ... }
fn excerpt(
&self,
path: &Path,
first: usize,
count: usize,
) -> Result<Excerpt> { ... }
fn replace(
&self,
path: &Path,
bytes: &[u8],
limit: u64,
) -> Result<Result<Contents>> { ... }
fn write_if(
&self,
path: &Path,
bytes: &[u8],
held: &ContentHash,
) -> Result<Option<Contents>> { ... }
fn join(&self, base: &Path, path: &Path) -> PathBuf { ... }
fn watch(
self: Arc<Self>,
root: &Path,
recursive: bool,
listing: Listing,
) -> Result<Watch> { ... }
}Expand description
The disk and the commands the tools act on: this machine’s (Local),
or another, such as one reached over SSH. Paths are the workspace’s own:
a tool’s base, the paths it resolves and the facts it publishes
(FilesRead,
FilesChanged) name files in it.
Synchronous, as the rest of rig-tools: the tools call it inside
blocking. Code on a thread that must not wait, such
as an app’s main thread, calls it inline only when host
is None, and otherwise off that thread.
A workspace of your own implements every method; Local is the
reference for what each does.
Required Methods§
Sourcefn stat(&self, path: &Path) -> Result<Stat>
fn stat(&self, path: &Path) -> Result<Stat>
What path is, its links followed: a file (its size, whether it is
read-only, when it was last changed), a directory, something else, or
nothing.
Sourcefn read(&self, path: &Path, limit: u64) -> Result<Contents>
fn read(&self, path: &Path, limit: u64) -> Result<Contents>
Up to limit bytes of the regular file path, and its whole size.
Anything but a regular file is refused without being opened: opening
a FIFO or a device can block forever.
Sourcefn write(&self, path: &Path, bytes: &[u8]) -> Result<()>
fn write(&self, path: &Path, bytes: &[u8]) -> Result<()>
Replaces the file path with bytes in one step, creating its
directory, keeping its permissions, and refusing a read-only file or
anything but a regular file (see write_atomic).
Sourcefn rename(&self, from: &Path, to: &Path) -> Result<()>
fn rename(&self, from: &Path, to: &Path) -> Result<()>
Moves the file from to to, creating to’s directory and
replacing a file there.
Sourcefn canonical(&self, path: &Path) -> PathBuf
fn canonical(&self, path: &Path) -> PathBuf
path made absolute, with the links of its longest existing part
followed (the file’s own too, when it exists) and .. folded, so two
spellings of one file come out alike. A footprint is made with it,
which may be on a thread that must not wait: a remote workspace may
answer from a cache, or fold .. only.
Sourcefn files(
&self,
root: &Path,
glob: Option<&str>,
listing: Listing,
) -> Result<Vec<PathBuf>>
fn files( &self, root: &Path, glob: Option<&str>, listing: Listing, ) -> Result<Vec<PathBuf>>
The regular files under root (or root itself when it is a file),
in walk order, as root joined with their path below it: those
listing keeps (Listing), and only those matching glob, such
as *.rs, when it is given. A malformed glob is an
InvalidInput error that says so.
Provided Methods§
Sourcefn host(&self) -> Option<&str>
fn host(&self) -> Option<&str>
Where it is when it is not this machine, such as ssh://dev@box;
None for this machine.
Sourcefn read_files(&self, paths: &[PathBuf], limit: u64) -> Vec<Option<Vec<u8>>>
fn read_files(&self, paths: &[PathBuf], limit: u64) -> Vec<Option<Vec<u8>>>
The whole content of each of paths that is a regular file of at
most limit bytes, in order: None for any other path, and for one
that could not be read. What a search reads; a workspace where each
call costs a round trip, such as a remote one, reads them in one.
Sourcefn excerpt(&self, path: &Path, first: usize, count: usize) -> Result<Excerpt>
fn excerpt(&self, path: &Path, first: usize, count: usize) -> Result<Excerpt>
Lines first (from 1) on, at most count of them, of the regular
text file path, with how many lines it has and the hash of all of
it. Refused, as read_text refuses,
when it is no regular file, larger than MAX_FILE_BYTES (a
FileTooLarge error) or not UTF-8 (an
InvalidData error); a workspace that
sends only the lines asked of a file larger than
MAX_BYTES, such as a remote one, checks only those for UTF-8.
By default the whole file is read and cut here.
Sourcefn replace(
&self,
path: &Path,
bytes: &[u8],
limit: u64,
) -> Result<Result<Contents>>
fn replace( &self, path: &Path, bytes: &[u8], limit: u64, ) -> Result<Result<Contents>>
writes bytes to path and says what the file
held before, as read with limit reads it: a
NotFound error when there was no file, the
file’s own when it could not be read. What a tool that writes a
file diffs against; a workspace where each call costs a round trip,
such as a remote one, does both in one.
By default it reads, then writes.
Sourcefn write_if(
&self,
path: &Path,
bytes: &[u8],
held: &ContentHash,
) -> Result<Option<Contents>>
fn write_if( &self, path: &Path, bytes: &[u8], held: &ContentHash, ) -> Result<Option<Contents>>
writes bytes to the regular file path only
while it holds the text whose content_hash is held: None
when it did. Otherwise nothing is written and it says what the file
holds instead, as read with a limit of
MAX_FILE_BYTES reads it. What an edit made from text seen
before writes with; a workspace where each call costs a round trip,
such as a remote one, checks and writes in one.
By default it reads, then writes.
Sourcefn join(&self, base: &Path, path: &Path) -> PathBuf
fn join(&self, base: &Path, path: &Path) -> PathBuf
path relative to base, as resolve joins them:
base.join(path), so an absolute path stays as it is. A workspace
whose paths can name another machine, such as
Hosts, keeps such a path whole too.
Sourcefn watch(
self: Arc<Self>,
root: &Path,
recursive: bool,
listing: Listing,
) -> Result<Watch>
fn watch( self: Arc<Self>, root: &Path, recursive: bool, listing: Listing, ) -> Result<Watch>
Watches root, a file or a directory (with recursive, every
directory under it too), from now on: a batch of the paths created,
changed or removed each time something changed, of the files
files would list with listing.
Dropping the Watch stops it. To miss nothing, list the files
once after the watch has started.
By default it looks at what files lists every
second, on a thread of its own, comparing each file’s
size and change time (its hash when stat cannot tell
the time). Local hears of changes from the system instead.
Implementations§
Source§impl dyn Workspace
impl dyn Workspace
Sourcepub fn resolve(&self, base: Option<&Path>, path: &str) -> PathBuf
pub fn resolve(&self, base: Option<&Path>, path: &str) -> PathBuf
path as the file tools name it: joined onto base when relative,
then made canonical.
Sourcepub fn place(
&self,
base: Option<&Path>,
confine: bool,
path: &str,
) -> Result<PathBuf, ToolExecutionError>
pub fn place( &self, base: Option<&Path>, confine: bool, path: &str, ) -> Result<PathBuf, ToolExecutionError>
path resolved against base, as a file tool
opens it; with confine, refused before any other I/O when it lies
outside base (None: the working directory).
use rig_tools::workspace::{Local, Workspace};
let local: &dyn Workspace = &Local;
let base = std::fs::canonicalize(".")?;
assert_eq!(local.place(Some(&base), true, "src/../a.rs")?, base.join("a.rs"));
assert!(local.place(Some(&base), true, "../outside.rs").is_err());
assert!(local.place(Some(&base), false, "../outside.rs").is_ok());Sourcepub fn read_text(&self, path: &Path) -> Result<String, ToolExecutionError>
pub fn read_text(&self, path: &Path) -> Result<String, ToolExecutionError>
The regular file path as text, in one read:
refused when it is no regular file or larger than
MAX_FILE_BYTES.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".