forked from rojo-rbx/rojo
Batch rename: imfs -> vfs
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
//! Defines the process by which changes are pulled from the Imfs, filtered, and
|
//! Defines the process by which changes are pulled from the Vfs, filtered, and
|
||||||
//! used to mutate Rojo's tree during a live session.
|
//! used to mutate Rojo's tree during a live session.
|
||||||
//!
|
//!
|
||||||
//! This object is owned by a ServeSession.
|
//! This object is owned by a ServeSession.
|
||||||
@@ -9,10 +9,10 @@ use crossbeam_channel::{select, Receiver, Sender};
|
|||||||
use jod_thread::JoinHandle;
|
use jod_thread::JoinHandle;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, ImfsEvent, ImfsFetcher},
|
|
||||||
message_queue::MessageQueue,
|
message_queue::MessageQueue,
|
||||||
snapshot::{apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, RojoTree},
|
snapshot::{apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, RojoTree},
|
||||||
snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext},
|
snapshot_middleware::{snapshot_from_vfs, InstanceSnapshotContext},
|
||||||
|
vfs::{Vfs, VfsEvent, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ChangeProcessor {
|
pub struct ChangeProcessor {
|
||||||
@@ -21,10 +21,10 @@ pub struct ChangeProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ChangeProcessor {
|
impl ChangeProcessor {
|
||||||
pub fn start<F: ImfsFetcher + Send + 'static>(
|
pub fn start<F: VfsFetcher + Send + 'static>(
|
||||||
tree: Arc<Mutex<RojoTree>>,
|
tree: Arc<Mutex<RojoTree>>,
|
||||||
message_queue: Arc<MessageQueue<AppliedPatchSet>>,
|
message_queue: Arc<MessageQueue<AppliedPatchSet>>,
|
||||||
imfs: Arc<Mutex<Imfs<F>>>,
|
vfs: Arc<Mutex<Vfs<F>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded(1);
|
let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded(1);
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ impl ChangeProcessor {
|
|||||||
.name("ChangeProcessor thread".to_owned())
|
.name("ChangeProcessor thread".to_owned())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
log::trace!("ChangeProcessor thread started");
|
log::trace!("ChangeProcessor thread started");
|
||||||
Self::main_task(shutdown_receiver, tree, message_queue, imfs);
|
Self::main_task(shutdown_receiver, tree, message_queue, vfs);
|
||||||
log::trace!("ChangeProcessor thread stopped");
|
log::trace!("ChangeProcessor thread stopped");
|
||||||
})
|
})
|
||||||
.expect("Could not start ChangeProcessor thread");
|
.expect("Could not start ChangeProcessor thread");
|
||||||
@@ -43,15 +43,15 @@ impl ChangeProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main_task<F: ImfsFetcher>(
|
fn main_task<F: VfsFetcher>(
|
||||||
shutdown_receiver: Receiver<()>,
|
shutdown_receiver: Receiver<()>,
|
||||||
tree: Arc<Mutex<RojoTree>>,
|
tree: Arc<Mutex<RojoTree>>,
|
||||||
message_queue: Arc<MessageQueue<AppliedPatchSet>>,
|
message_queue: Arc<MessageQueue<AppliedPatchSet>>,
|
||||||
imfs: Arc<Mutex<Imfs<F>>>,
|
vfs: Arc<Mutex<Vfs<F>>>,
|
||||||
) {
|
) {
|
||||||
let imfs_receiver = {
|
let vfs_receiver = {
|
||||||
let imfs = imfs.lock().unwrap();
|
let vfs = vfs.lock().unwrap();
|
||||||
imfs.change_receiver()
|
vfs.change_receiver()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Crossbeam's select macro generates code that Clippy doesn't like, and
|
// Crossbeam's select macro generates code that Clippy doesn't like, and
|
||||||
@@ -59,20 +59,20 @@ impl ChangeProcessor {
|
|||||||
#[allow(clippy::drop_copy)]
|
#[allow(clippy::drop_copy)]
|
||||||
loop {
|
loop {
|
||||||
select! {
|
select! {
|
||||||
recv(imfs_receiver) -> event => {
|
recv(vfs_receiver) -> event => {
|
||||||
let event = event.unwrap();
|
let event = event.unwrap();
|
||||||
|
|
||||||
log::trace!("Imfs event: {:?}", event);
|
log::trace!("Vfs event: {:?}", event);
|
||||||
|
|
||||||
let applied_patches = {
|
let applied_patches = {
|
||||||
let mut imfs = imfs.lock().unwrap();
|
let mut vfs = vfs.lock().unwrap();
|
||||||
imfs.commit_change(&event).expect("Error applying IMFS change");
|
vfs.commit_change(&event).expect("Error applying VFS change");
|
||||||
|
|
||||||
let mut tree = tree.lock().unwrap();
|
let mut tree = tree.lock().unwrap();
|
||||||
let mut applied_patches = Vec::new();
|
let mut applied_patches = Vec::new();
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
ImfsEvent::Created(path) | ImfsEvent::Modified(path) | ImfsEvent::Removed(path) => {
|
VfsEvent::Created(path) | VfsEvent::Modified(path) | VfsEvent::Removed(path) => {
|
||||||
let affected_ids = tree.get_ids_at_path(&path).to_vec();
|
let affected_ids = tree.get_ids_at_path(&path).to_vec();
|
||||||
|
|
||||||
if affected_ids.len() == 0 {
|
if affected_ids.len() == 0 {
|
||||||
@@ -95,14 +95,14 @@ impl ChangeProcessor {
|
|||||||
|
|
||||||
let snapshot = match instigating_source {
|
let snapshot = match instigating_source {
|
||||||
InstigatingSource::Path(path) => {
|
InstigatingSource::Path(path) => {
|
||||||
let entry = imfs
|
let entry = vfs
|
||||||
.get(path)
|
.get(path)
|
||||||
.expect("could not get instigating path from filesystem");
|
.expect("could not get instigating path from filesystem");
|
||||||
|
|
||||||
// TODO: Use persisted snapshot
|
// TODO: Use persisted snapshot
|
||||||
// context struct instead of
|
// context struct instead of
|
||||||
// recreating it every time.
|
// recreating it every time.
|
||||||
let snapshot = snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
let snapshot = snapshot_from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot failed")
|
.expect("snapshot failed")
|
||||||
.expect("snapshot did not return an instance");
|
.expect("snapshot did not return an instance");
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use failure::Fail;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common_setup,
|
common_setup,
|
||||||
imfs::{FsError, Imfs, RealFetcher, WatchMode},
|
|
||||||
project::ProjectLoadError,
|
project::ProjectLoadError,
|
||||||
|
vfs::{FsError, RealFetcher, Vfs, WatchMode},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@@ -81,9 +81,9 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> {
|
|||||||
log::debug!("Hoping to generate file of type {:?}", output_kind);
|
log::debug!("Hoping to generate file of type {:?}", output_kind);
|
||||||
|
|
||||||
log::trace!("Constructing in-memory filesystem");
|
log::trace!("Constructing in-memory filesystem");
|
||||||
let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled));
|
let mut vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled));
|
||||||
|
|
||||||
let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut imfs);
|
let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut vfs);
|
||||||
let root_id = tree.get_root_id();
|
let root_id = tree.get_root_id();
|
||||||
|
|
||||||
log::trace!("Opening output file for write");
|
log::trace!("Opening output file for write");
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ use failure::Fail;
|
|||||||
use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor};
|
use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, RealFetcher, WatchMode},
|
|
||||||
project::ProjectLoadError,
|
project::ProjectLoadError,
|
||||||
serve_session::ServeSession,
|
serve_session::ServeSession,
|
||||||
|
vfs::{RealFetcher, Vfs, WatchMode},
|
||||||
web::LiveServer,
|
web::LiveServer,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -33,9 +33,9 @@ impl_from!(ServeError {
|
|||||||
});
|
});
|
||||||
|
|
||||||
pub fn serve(options: &ServeOptions) -> Result<(), ServeError> {
|
pub fn serve(options: &ServeOptions) -> Result<(), ServeError> {
|
||||||
let imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled));
|
let vfs = Vfs::new(RealFetcher::new(WatchMode::Enabled));
|
||||||
|
|
||||||
let session = Arc::new(ServeSession::new(imfs, &options.fuzzy_project_path));
|
let session = Arc::new(ServeSession::new(vfs, &options.fuzzy_project_path));
|
||||||
|
|
||||||
let port = options
|
let port = options
|
||||||
.port
|
.port
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT};
|
|||||||
use crate::{
|
use crate::{
|
||||||
auth_cookie::get_auth_cookie,
|
auth_cookie::get_auth_cookie,
|
||||||
common_setup,
|
common_setup,
|
||||||
imfs::{Imfs, RealFetcher, WatchMode},
|
vfs::{RealFetcher, Vfs, WatchMode},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Fail)]
|
#[derive(Debug, Fail)]
|
||||||
@@ -44,9 +44,9 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> {
|
|||||||
.ok_or(UploadError::NeedAuthCookie)?;
|
.ok_or(UploadError::NeedAuthCookie)?;
|
||||||
|
|
||||||
log::trace!("Constructing in-memory filesystem");
|
log::trace!("Constructing in-memory filesystem");
|
||||||
let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled));
|
let mut vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled));
|
||||||
|
|
||||||
let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut imfs);
|
let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut vfs);
|
||||||
let root_id = tree.get_root_id();
|
let root_id = tree.get_root_id();
|
||||||
|
|
||||||
let mut buffer = Vec::new();
|
let mut buffer = Vec::new();
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ use std::path::Path;
|
|||||||
use rbx_dom_weak::RbxInstanceProperties;
|
use rbx_dom_weak::RbxInstanceProperties;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, ImfsFetcher},
|
|
||||||
project::{Project, ProjectLoadError},
|
project::{Project, ProjectLoadError},
|
||||||
snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree},
|
snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree},
|
||||||
snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext, SnapshotPluginContext},
|
snapshot_middleware::{snapshot_from_vfs, InstanceSnapshotContext, SnapshotPluginContext},
|
||||||
|
vfs::{Vfs, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn start<F: ImfsFetcher>(
|
pub fn start<F: VfsFetcher>(
|
||||||
fuzzy_project_path: &Path,
|
fuzzy_project_path: &Path,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
) -> (Option<Project>, RojoTree) {
|
) -> (Option<Project>, RojoTree) {
|
||||||
log::trace!("Loading project file from {}", fuzzy_project_path.display());
|
log::trace!("Loading project file from {}", fuzzy_project_path.display());
|
||||||
let maybe_project = match Project::load_fuzzy(fuzzy_project_path) {
|
let maybe_project = match Project::load_fuzzy(fuzzy_project_path) {
|
||||||
@@ -47,12 +47,12 @@ pub fn start<F: ImfsFetcher>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
log::trace!("Reading project root");
|
log::trace!("Reading project root");
|
||||||
let entry = imfs
|
let entry = vfs
|
||||||
.get(fuzzy_project_path)
|
.get(fuzzy_project_path)
|
||||||
.expect("could not get project path");
|
.expect("could not get project path");
|
||||||
|
|
||||||
log::trace!("Generating snapshot of instances from IMFS");
|
log::trace!("Generating snapshot of instances from VFS");
|
||||||
let snapshot = snapshot_from_imfs(&mut snapshot_context, imfs, &entry)
|
let snapshot = snapshot_from_vfs(&mut snapshot_context, vfs, &entry)
|
||||||
.expect("snapshot failed")
|
.expect("snapshot failed")
|
||||||
.expect("snapshot did not return an instance");
|
.expect("snapshot did not return an instance");
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
// This file is non-critical and used for testing, so it's okay if it's unused.
|
|
||||||
#![allow(unused)]
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum ImfsSnapshot {
|
|
||||||
File(FileSnapshot),
|
|
||||||
Directory(DirectorySnapshot),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImfsSnapshot {
|
|
||||||
/// Create a new file ImfsSnapshot with the given contents.
|
|
||||||
pub fn file(contents: impl Into<Vec<u8>>) -> ImfsSnapshot {
|
|
||||||
ImfsSnapshot::File(FileSnapshot {
|
|
||||||
contents: contents.into(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new directory ImfsSnapshot with the given children.
|
|
||||||
pub fn dir<S: Into<String>>(children: HashMap<S, ImfsSnapshot>) -> ImfsSnapshot {
|
|
||||||
let children = children.into_iter().map(|(k, v)| (k.into(), v)).collect();
|
|
||||||
|
|
||||||
ImfsSnapshot::Directory(DirectorySnapshot { children })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn empty_dir() -> ImfsSnapshot {
|
|
||||||
ImfsSnapshot::Directory(DirectorySnapshot {
|
|
||||||
children: Default::default(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct FileSnapshot {
|
|
||||||
pub contents: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct DirectorySnapshot {
|
|
||||||
pub children: HashMap<String, ImfsSnapshot>,
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,6 @@ mod tree_view;
|
|||||||
mod auth_cookie;
|
mod auth_cookie;
|
||||||
mod change_processor;
|
mod change_processor;
|
||||||
mod common_setup;
|
mod common_setup;
|
||||||
mod imfs;
|
|
||||||
mod message_queue;
|
mod message_queue;
|
||||||
mod multimap;
|
mod multimap;
|
||||||
mod path_map;
|
mod path_map;
|
||||||
@@ -27,6 +26,7 @@ mod serve_session;
|
|||||||
mod session_id;
|
mod session_id;
|
||||||
mod snapshot;
|
mod snapshot;
|
||||||
mod snapshot_middleware;
|
mod snapshot_middleware;
|
||||||
|
mod vfs;
|
||||||
mod web;
|
mod web;
|
||||||
|
|
||||||
pub use crate::session_id::SessionId;
|
pub use crate::session_id::SessionId;
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ use std::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
change_processor::ChangeProcessor,
|
change_processor::ChangeProcessor,
|
||||||
common_setup,
|
common_setup,
|
||||||
imfs::{Imfs, ImfsFetcher},
|
|
||||||
message_queue::MessageQueue,
|
message_queue::MessageQueue,
|
||||||
project::Project,
|
project::Project,
|
||||||
session_id::SessionId,
|
session_id::SessionId,
|
||||||
snapshot::{AppliedPatchSet, RojoTree},
|
snapshot::{AppliedPatchSet, RojoTree},
|
||||||
|
vfs::{Vfs, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Contains all of the state for a Rojo serve session.
|
/// Contains all of the state for a Rojo serve session.
|
||||||
@@ -43,7 +43,7 @@ pub struct ServeSession<F> {
|
|||||||
session_id: SessionId,
|
session_id: SessionId,
|
||||||
|
|
||||||
/// The tree of Roblox instances associated with this session that will be
|
/// The tree of Roblox instances associated with this session that will be
|
||||||
/// updated in real-time. This is derived from the session's IMFS and will
|
/// updated in real-time. This is derived from the session's VFS and will
|
||||||
/// eventually be mutable to connected clients.
|
/// eventually be mutable to connected clients.
|
||||||
tree: Arc<Mutex<RojoTree>>,
|
tree: Arc<Mutex<RojoTree>>,
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ pub struct ServeSession<F> {
|
|||||||
///
|
///
|
||||||
/// The main use for accessing it from the session is for debugging issues
|
/// The main use for accessing it from the session is for debugging issues
|
||||||
/// with Rojo's live-sync protocol.
|
/// with Rojo's live-sync protocol.
|
||||||
imfs: Arc<Mutex<Imfs<F>>>,
|
vfs: Arc<Mutex<Vfs<F>>>,
|
||||||
|
|
||||||
/// A queue of changes that have been applied to `tree` that affect clients.
|
/// A queue of changes that have been applied to `tree` that affect clients.
|
||||||
///
|
///
|
||||||
@@ -68,37 +68,37 @@ pub struct ServeSession<F> {
|
|||||||
_change_processor: ChangeProcessor,
|
_change_processor: ChangeProcessor,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Methods that need thread-safety bounds on ImfsFetcher are limited to this
|
/// Methods that need thread-safety bounds on VfsFetcher are limited to this
|
||||||
/// block to prevent needing to spread Send + Sync + 'static into everything
|
/// block to prevent needing to spread Send + Sync + 'static into everything
|
||||||
/// that handles ServeSession.
|
/// that handles ServeSession.
|
||||||
impl<F: ImfsFetcher + Send + 'static> ServeSession<F> {
|
impl<F: VfsFetcher + Send + 'static> ServeSession<F> {
|
||||||
/// Start a new serve session from the given in-memory filesystem and start
|
/// Start a new serve session from the given in-memory filesystem and start
|
||||||
/// path.
|
/// path.
|
||||||
///
|
///
|
||||||
/// The project file is expected to be loaded out-of-band since it's
|
/// The project file is expected to be loaded out-of-band since it's
|
||||||
/// currently loaded from the filesystem directly instead of through the
|
/// currently loaded from the filesystem directly instead of through the
|
||||||
/// in-memory filesystem layer.
|
/// in-memory filesystem layer.
|
||||||
pub fn new<P: AsRef<Path>>(mut imfs: Imfs<F>, start_path: P) -> Self {
|
pub fn new<P: AsRef<Path>>(mut vfs: Vfs<F>, start_path: P) -> Self {
|
||||||
let start_path = start_path.as_ref();
|
let start_path = start_path.as_ref();
|
||||||
|
|
||||||
log::trace!("Starting new ServeSession at path {}", start_path.display(),);
|
log::trace!("Starting new ServeSession at path {}", start_path.display(),);
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
let (root_project, tree) = common_setup::start(start_path, &mut imfs);
|
let (root_project, tree) = common_setup::start(start_path, &mut vfs);
|
||||||
|
|
||||||
let session_id = SessionId::new();
|
let session_id = SessionId::new();
|
||||||
let message_queue = MessageQueue::new();
|
let message_queue = MessageQueue::new();
|
||||||
|
|
||||||
let tree = Arc::new(Mutex::new(tree));
|
let tree = Arc::new(Mutex::new(tree));
|
||||||
let message_queue = Arc::new(message_queue);
|
let message_queue = Arc::new(message_queue);
|
||||||
let imfs = Arc::new(Mutex::new(imfs));
|
let vfs = Arc::new(Mutex::new(vfs));
|
||||||
|
|
||||||
log::trace!("Starting ChangeProcessor");
|
log::trace!("Starting ChangeProcessor");
|
||||||
let change_processor = ChangeProcessor::start(
|
let change_processor = ChangeProcessor::start(
|
||||||
Arc::clone(&tree),
|
Arc::clone(&tree),
|
||||||
Arc::clone(&message_queue),
|
Arc::clone(&message_queue),
|
||||||
Arc::clone(&imfs),
|
Arc::clone(&vfs),
|
||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@@ -107,13 +107,13 @@ impl<F: ImfsFetcher + Send + 'static> ServeSession<F> {
|
|||||||
root_project,
|
root_project,
|
||||||
tree,
|
tree,
|
||||||
message_queue,
|
message_queue,
|
||||||
imfs,
|
vfs,
|
||||||
_change_processor: change_processor,
|
_change_processor: change_processor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher> ServeSession<F> {
|
impl<F: VfsFetcher> ServeSession<F> {
|
||||||
pub fn tree_handle(&self) -> Arc<Mutex<RojoTree>> {
|
pub fn tree_handle(&self) -> Arc<Mutex<RojoTree>> {
|
||||||
Arc::clone(&self.tree)
|
Arc::clone(&self.tree)
|
||||||
}
|
}
|
||||||
@@ -122,8 +122,8 @@ impl<F: ImfsFetcher> ServeSession<F> {
|
|||||||
self.tree.lock().unwrap()
|
self.tree.lock().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn imfs(&self) -> MutexGuard<'_, Imfs<F>> {
|
pub fn vfs(&self) -> MutexGuard<'_, Vfs<F>> {
|
||||||
self.imfs.lock().unwrap()
|
self.vfs.lock().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message_queue(&self) -> &MessageQueue<AppliedPatchSet> {
|
pub fn message_queue(&self) -> &MessageQueue<AppliedPatchSet> {
|
||||||
@@ -173,17 +173,17 @@ mod serve_session {
|
|||||||
use tokio::{runtime::Runtime, timer::Timeout};
|
use tokio::{runtime::Runtime, timer::Timeout};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{ImfsDebug, ImfsEvent, ImfsSnapshot, NoopFetcher, TestFetcher},
|
|
||||||
tree_view::view_tree,
|
tree_view::view_tree,
|
||||||
|
vfs::{NoopFetcher, TestFetcher, VfsDebug, VfsEvent, VfsSnapshot},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn just_folder() {
|
fn just_folder() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", ImfsSnapshot::empty_dir());
|
vfs.debug_load_snapshot("/foo", VfsSnapshot::empty_dir());
|
||||||
|
|
||||||
let session = ServeSession::new(imfs, "/foo");
|
let session = ServeSession::new(vfs, "/foo");
|
||||||
|
|
||||||
let mut rm = RedactionMap::new();
|
let mut rm = RedactionMap::new();
|
||||||
assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm));
|
assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm));
|
||||||
@@ -191,12 +191,12 @@ mod serve_session {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn project_with_folder() {
|
fn project_with_folder() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
|
|
||||||
imfs.debug_load_snapshot(
|
vfs.debug_load_snapshot(
|
||||||
"/foo",
|
"/foo",
|
||||||
ImfsSnapshot::dir(hashmap! {
|
VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => ImfsSnapshot::file(r#"
|
"default.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "HelloWorld",
|
"name": "HelloWorld",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -204,13 +204,13 @@ mod serve_session {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"#),
|
"#),
|
||||||
"src" => ImfsSnapshot::dir(hashmap! {
|
"src" => VfsSnapshot::dir(hashmap! {
|
||||||
"hello.txt" => ImfsSnapshot::file("Hello, world!"),
|
"hello.txt" => VfsSnapshot::file("Hello, world!"),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let session = ServeSession::new(imfs, "/foo");
|
let session = ServeSession::new(vfs, "/foo");
|
||||||
|
|
||||||
let mut rm = RedactionMap::new();
|
let mut rm = RedactionMap::new();
|
||||||
assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm));
|
assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm));
|
||||||
@@ -218,17 +218,17 @@ mod serve_session {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script_with_meta() {
|
fn script_with_meta() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
|
|
||||||
imfs.debug_load_snapshot(
|
vfs.debug_load_snapshot(
|
||||||
"/root",
|
"/root",
|
||||||
ImfsSnapshot::dir(hashmap! {
|
VfsSnapshot::dir(hashmap! {
|
||||||
"test.lua" => ImfsSnapshot::file("This is a test."),
|
"test.lua" => VfsSnapshot::file("This is a test."),
|
||||||
"test.meta.json" => ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#),
|
"test.meta.json" => VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let session = ServeSession::new(imfs, "/root");
|
let session = ServeSession::new(vfs, "/root");
|
||||||
|
|
||||||
let mut rm = RedactionMap::new();
|
let mut rm = RedactionMap::new();
|
||||||
assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm));
|
assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm));
|
||||||
@@ -240,14 +240,14 @@ mod serve_session {
|
|||||||
|
|
||||||
state.load_snapshot(
|
state.load_snapshot(
|
||||||
"/root",
|
"/root",
|
||||||
ImfsSnapshot::dir(hashmap! {
|
VfsSnapshot::dir(hashmap! {
|
||||||
"test.lua" => ImfsSnapshot::file("This is a test."),
|
"test.lua" => VfsSnapshot::file("This is a test."),
|
||||||
"test.meta.json" => ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#),
|
"test.meta.json" => VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let imfs = Imfs::new(fetcher);
|
let vfs = Vfs::new(fetcher);
|
||||||
let session = ServeSession::new(imfs, "/root");
|
let session = ServeSession::new(vfs, "/root");
|
||||||
|
|
||||||
let mut redactions = RedactionMap::new();
|
let mut redactions = RedactionMap::new();
|
||||||
assert_yaml_snapshot!(
|
assert_yaml_snapshot!(
|
||||||
@@ -257,14 +257,14 @@ mod serve_session {
|
|||||||
|
|
||||||
state.load_snapshot(
|
state.load_snapshot(
|
||||||
"/root/test.meta.json",
|
"/root/test.meta.json",
|
||||||
ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": false }"#),
|
VfsSnapshot::file(r#"{ "ignoreUnknownInstances": false }"#),
|
||||||
);
|
);
|
||||||
|
|
||||||
let receiver = Timeout::new(
|
let receiver = Timeout::new(
|
||||||
session.message_queue().subscribe_any(),
|
session.message_queue().subscribe_any(),
|
||||||
Duration::from_millis(200),
|
Duration::from_millis(200),
|
||||||
);
|
);
|
||||||
state.raise_event(ImfsEvent::Modified(PathBuf::from("/root/test.meta.json")));
|
state.raise_event(VfsEvent::Modified(PathBuf::from("/root/test.meta.json")));
|
||||||
|
|
||||||
let mut rt = Runtime::new().unwrap();
|
let mut rt = Runtime::new().unwrap();
|
||||||
let changes = rt.block_on(receiver).unwrap();
|
let changes = rt.block_on(receiver).unwrap();
|
||||||
@@ -283,10 +283,10 @@ mod serve_session {
|
|||||||
fn change_txt_file() {
|
fn change_txt_file() {
|
||||||
let (state, fetcher) = TestFetcher::new();
|
let (state, fetcher) = TestFetcher::new();
|
||||||
|
|
||||||
state.load_snapshot("/foo.txt", ImfsSnapshot::file("Hello!"));
|
state.load_snapshot("/foo.txt", VfsSnapshot::file("Hello!"));
|
||||||
|
|
||||||
let imfs = Imfs::new(fetcher);
|
let vfs = Vfs::new(fetcher);
|
||||||
let session = ServeSession::new(imfs, "/foo.txt");
|
let session = ServeSession::new(vfs, "/foo.txt");
|
||||||
|
|
||||||
let mut redactions = RedactionMap::new();
|
let mut redactions = RedactionMap::new();
|
||||||
assert_yaml_snapshot!(
|
assert_yaml_snapshot!(
|
||||||
@@ -294,11 +294,11 @@ mod serve_session {
|
|||||||
view_tree(&session.tree(), &mut redactions)
|
view_tree(&session.tree(), &mut redactions)
|
||||||
);
|
);
|
||||||
|
|
||||||
state.load_snapshot("/foo.txt", ImfsSnapshot::file("World!"));
|
state.load_snapshot("/foo.txt", VfsSnapshot::file("World!"));
|
||||||
|
|
||||||
let receiver = session.message_queue().subscribe_any();
|
let receiver = session.message_queue().subscribe_any();
|
||||||
|
|
||||||
state.raise_event(ImfsEvent::Modified(PathBuf::from("/foo.txt")));
|
state.raise_event(VfsEvent::Modified(PathBuf::from("/foo.txt")));
|
||||||
|
|
||||||
let receiver = Timeout::new(receiver, Duration::from_millis(200));
|
let receiver = Timeout::new(receiver, Duration::from_millis(200));
|
||||||
|
|
||||||
|
|||||||
@@ -62,4 +62,4 @@ impl<T> Deref for IgnoreDebug<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImfsSnapshotContext;
|
pub struct VfsSnapshotContext;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use rbx_dom_weak::RbxValue;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher},
|
|
||||||
snapshot::{InstanceMetadata, InstanceSnapshot},
|
snapshot::{InstanceMetadata, InstanceSnapshot},
|
||||||
|
vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -19,10 +19,10 @@ use super::{
|
|||||||
pub struct SnapshotCsv;
|
pub struct SnapshotCsv;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotCsv {
|
impl SnapshotMiddleware for SnapshotCsv {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
_context: &mut InstanceSnapshotContext,
|
_context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
if entry.is_directory() {
|
if entry.is_directory() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@@ -37,7 +37,7 @@ impl SnapshotMiddleware for SnapshotCsv {
|
|||||||
.path()
|
.path()
|
||||||
.with_file_name(format!("{}.meta.json", instance_name));
|
.with_file_name(format!("{}.meta.json", instance_name));
|
||||||
|
|
||||||
let table_contents = convert_localization_csv(entry.contents(imfs)?);
|
let table_contents = convert_localization_csv(entry.contents(vfs)?);
|
||||||
|
|
||||||
let mut snapshot = InstanceSnapshot {
|
let mut snapshot = InstanceSnapshot {
|
||||||
snapshot_id: None,
|
snapshot_id: None,
|
||||||
@@ -56,8 +56,8 @@ impl SnapshotMiddleware for SnapshotCsv {
|
|||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? {
|
if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? {
|
||||||
let meta_contents = meta_entry.contents(imfs)?;
|
let meta_contents = meta_entry.contents(vfs)?;
|
||||||
let mut metadata = AdjacentMetadata::from_slice(meta_contents);
|
let mut metadata = AdjacentMetadata::from_slice(meta_contents);
|
||||||
metadata.apply_all(&mut snapshot);
|
metadata.apply_all(&mut snapshot);
|
||||||
}
|
}
|
||||||
@@ -146,23 +146,23 @@ fn convert_localization_csv(contents: &[u8]) -> String {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher};
|
use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot};
|
||||||
use insta::assert_yaml_snapshot;
|
use insta::assert_yaml_snapshot;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn csv_from_imfs() {
|
fn csv_from_vfs() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file(
|
let file = VfsSnapshot::file(
|
||||||
r#"
|
r#"
|
||||||
Key,Source,Context,Example,es
|
Key,Source,Context,Example,es
|
||||||
Ack,Ack!,,An exclamation of despair,¡Ay!"#,
|
Ack,Ack!,,An exclamation of despair,¡Ay!"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.csv", file);
|
vfs.debug_load_snapshot("/foo.csv", file);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.csv").unwrap();
|
let entry = vfs.get("/foo.csv").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotCsv::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotCsv::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -171,20 +171,20 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#,
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn csv_with_meta() {
|
fn csv_with_meta() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file(
|
let file = VfsSnapshot::file(
|
||||||
r#"
|
r#"
|
||||||
Key,Source,Context,Example,es
|
Key,Source,Context,Example,es
|
||||||
Ack,Ack!,,An exclamation of despair,¡Ay!"#,
|
Ack,Ack!,,An exclamation of despair,¡Ay!"#,
|
||||||
);
|
);
|
||||||
let meta = ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#);
|
let meta = VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#);
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.csv", file);
|
vfs.debug_load_snapshot("/foo.csv", file);
|
||||||
imfs.debug_load_snapshot("/foo.meta.json", meta);
|
vfs.debug_load_snapshot("/foo.meta.json", meta);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.csv").unwrap();
|
let entry = vfs.get("/foo.csv").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotCsv::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotCsv::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -3,35 +3,35 @@ use std::{borrow::Cow, collections::HashMap};
|
|||||||
use rbx_dom_weak::{RbxId, RbxTree};
|
use rbx_dom_weak::{RbxId, RbxTree};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{DirectorySnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot},
|
|
||||||
snapshot::{InstanceMetadata, InstanceSnapshot},
|
snapshot::{InstanceMetadata, InstanceSnapshot},
|
||||||
|
vfs::{DirectorySnapshot, Vfs, VfsEntry, VfsFetcher, VfsSnapshot},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
context::InstanceSnapshotContext,
|
context::InstanceSnapshotContext,
|
||||||
error::SnapshotError,
|
error::SnapshotError,
|
||||||
middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware},
|
middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware},
|
||||||
snapshot_from_imfs, snapshot_from_instance,
|
snapshot_from_instance, snapshot_from_vfs,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct SnapshotDir;
|
pub struct SnapshotDir;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotDir {
|
impl SnapshotMiddleware for SnapshotDir {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
context: &mut InstanceSnapshotContext,
|
context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
if entry.is_file() {
|
if entry.is_file() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let children: Vec<ImfsEntry> = entry.children(imfs)?;
|
let children: Vec<VfsEntry> = entry.children(vfs)?;
|
||||||
|
|
||||||
let mut snapshot_children = Vec::new();
|
let mut snapshot_children = Vec::new();
|
||||||
|
|
||||||
for child in children.into_iter() {
|
for child in children.into_iter() {
|
||||||
if let Some(child_snapshot) = snapshot_from_imfs(context, imfs, &child)? {
|
if let Some(child_snapshot) = snapshot_from_vfs(context, vfs, &child)? {
|
||||||
snapshot_children.push(child_snapshot);
|
snapshot_children.push(child_snapshot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ impl SnapshotMiddleware for SnapshotDir {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let snapshot = ImfsSnapshot::Directory(DirectorySnapshot { children });
|
let snapshot = VfsSnapshot::Directory(DirectorySnapshot { children });
|
||||||
|
|
||||||
Some((instance.name.clone(), snapshot))
|
Some((instance.name.clone(), snapshot))
|
||||||
}
|
}
|
||||||
@@ -86,18 +86,18 @@ mod test {
|
|||||||
use insta::assert_yaml_snapshot;
|
use insta::assert_yaml_snapshot;
|
||||||
use maplit::hashmap;
|
use maplit::hashmap;
|
||||||
|
|
||||||
use crate::imfs::{ImfsDebug, NoopFetcher};
|
use crate::vfs::{NoopFetcher, VfsDebug};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_folder() {
|
fn empty_folder() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir::<String>(HashMap::new());
|
let dir = VfsSnapshot::dir::<String>(HashMap::new());
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotDir::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotDir::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -106,16 +106,16 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn folder_in_folder() {
|
fn folder_in_folder() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"Child" => ImfsSnapshot::dir::<String>(HashMap::new()),
|
"Child" => VfsSnapshot::dir::<String>(HashMap::new()),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotDir::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotDir::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::{error::Error, fmt, io, path::PathBuf};
|
use std::{error::Error, fmt, io, path::PathBuf};
|
||||||
|
|
||||||
use crate::imfs::FsError;
|
use crate::vfs::FsError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SnapshotError {
|
pub struct SnapshotError {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use rbx_reflection::try_resolve_value;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, ImfsEntry, ImfsFetcher},
|
|
||||||
snapshot::InstanceSnapshot,
|
snapshot::InstanceSnapshot,
|
||||||
|
vfs::{Vfs, VfsEntry, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -18,10 +18,10 @@ use super::{
|
|||||||
pub struct SnapshotJsonModel;
|
pub struct SnapshotJsonModel;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotJsonModel {
|
impl SnapshotMiddleware for SnapshotJsonModel {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
_context: &mut InstanceSnapshotContext,
|
_context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
if entry.is_directory() {
|
if entry.is_directory() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@@ -33,7 +33,7 @@ impl SnapshotMiddleware for SnapshotJsonModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let instance: JsonModel =
|
let instance: JsonModel =
|
||||||
serde_json::from_slice(entry.contents(imfs)?).expect("TODO: Handle serde_json errors");
|
serde_json::from_slice(entry.contents(vfs)?).expect("TODO: Handle serde_json errors");
|
||||||
|
|
||||||
if let Some(json_name) = &instance.name {
|
if let Some(json_name) = &instance.name {
|
||||||
if json_name != &instance_name {
|
if json_name != &instance_name {
|
||||||
@@ -137,12 +137,12 @@ mod test {
|
|||||||
|
|
||||||
use insta::assert_yaml_snapshot;
|
use insta::assert_yaml_snapshot;
|
||||||
|
|
||||||
use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher};
|
use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn model_from_imfs() {
|
fn model_from_vfs() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file(
|
let file = VfsSnapshot::file(
|
||||||
r#"
|
r#"
|
||||||
{
|
{
|
||||||
"Name": "children",
|
"Name": "children",
|
||||||
@@ -160,16 +160,13 @@ mod test {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.model.json", file);
|
vfs.debug_load_snapshot("/foo.model.json", file);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.model.json").unwrap();
|
let entry = vfs.get("/foo.model.json").unwrap();
|
||||||
let instance_snapshot = SnapshotJsonModel::from_imfs(
|
let instance_snapshot =
|
||||||
&mut InstanceSnapshotContext::default(),
|
SnapshotJsonModel::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
&mut imfs,
|
.unwrap()
|
||||||
&entry,
|
.unwrap();
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_yaml_snapshot!(instance_snapshot);
|
assert_yaml_snapshot!(instance_snapshot);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use maplit::hashmap;
|
|||||||
use rbx_dom_weak::RbxValue;
|
use rbx_dom_weak::RbxValue;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher},
|
|
||||||
snapshot::{InstanceMetadata, InstanceSnapshot},
|
snapshot::{InstanceMetadata, InstanceSnapshot},
|
||||||
|
vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -19,10 +19,10 @@ use super::{
|
|||||||
pub struct SnapshotLua;
|
pub struct SnapshotLua;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotLua {
|
impl SnapshotMiddleware for SnapshotLua {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
context: &mut InstanceSnapshotContext,
|
context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
let file_name = entry.path().file_name().unwrap().to_string_lossy();
|
let file_name = entry.path().file_name().unwrap().to_string_lossy();
|
||||||
|
|
||||||
@@ -34,15 +34,15 @@ impl SnapshotMiddleware for SnapshotLua {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if entry.is_file() {
|
if entry.is_file() {
|
||||||
snapshot_lua_file(imfs, entry)
|
snapshot_lua_file(vfs, entry)
|
||||||
} else {
|
} else {
|
||||||
if let Some(snapshot) = snapshot_init(context, imfs, entry, "init.lua")? {
|
if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.lua")? {
|
||||||
// An `init.lua` file turns its parent into a ModuleScript
|
// An `init.lua` file turns its parent into a ModuleScript
|
||||||
Ok(Some(snapshot))
|
Ok(Some(snapshot))
|
||||||
} else if let Some(snapshot) = snapshot_init(context, imfs, entry, "init.server.lua")? {
|
} else if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.server.lua")? {
|
||||||
// An `init.server.lua` file turns its parent into a Script
|
// An `init.server.lua` file turns its parent into a Script
|
||||||
Ok(Some(snapshot))
|
Ok(Some(snapshot))
|
||||||
} else if let Some(snapshot) = snapshot_init(context, imfs, entry, "init.client.lua")? {
|
} else if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.client.lua")? {
|
||||||
// An `init.client.lua` file turns its parent into a LocalScript
|
// An `init.client.lua` file turns its parent into a LocalScript
|
||||||
Ok(Some(snapshot))
|
Ok(Some(snapshot))
|
||||||
} else {
|
} else {
|
||||||
@@ -53,9 +53,9 @@ impl SnapshotMiddleware for SnapshotLua {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Core routine for turning Lua files into snapshots.
|
/// Core routine for turning Lua files into snapshots.
|
||||||
fn snapshot_lua_file<F: ImfsFetcher>(
|
fn snapshot_lua_file<F: VfsFetcher>(
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
let file_name = entry.path().file_name().unwrap().to_string_lossy();
|
let file_name = entry.path().file_name().unwrap().to_string_lossy();
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ fn snapshot_lua_file<F: ImfsFetcher>(
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
let contents = entry.contents(imfs)?;
|
let contents = entry.contents(vfs)?;
|
||||||
let contents_str = str::from_utf8(contents)
|
let contents_str = str::from_utf8(contents)
|
||||||
// TODO: Turn into error type
|
// TODO: Turn into error type
|
||||||
.expect("File content was not valid UTF-8")
|
.expect("File content was not valid UTF-8")
|
||||||
@@ -101,8 +101,8 @@ fn snapshot_lua_file<F: ImfsFetcher>(
|
|||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? {
|
if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? {
|
||||||
let meta_contents = meta_entry.contents(imfs)?;
|
let meta_contents = meta_entry.contents(vfs)?;
|
||||||
let mut metadata = AdjacentMetadata::from_slice(meta_contents);
|
let mut metadata = AdjacentMetadata::from_slice(meta_contents);
|
||||||
metadata.apply_all(&mut snapshot);
|
metadata.apply_all(&mut snapshot);
|
||||||
}
|
}
|
||||||
@@ -115,17 +115,17 @@ fn snapshot_lua_file<F: ImfsFetcher>(
|
|||||||
///
|
///
|
||||||
/// Scripts named `init.lua`, `init.server.lua`, or `init.client.lua` usurp
|
/// Scripts named `init.lua`, `init.server.lua`, or `init.client.lua` usurp
|
||||||
/// their parents, which acts similarly to `__init__.py` from the Python world.
|
/// their parents, which acts similarly to `__init__.py` from the Python world.
|
||||||
fn snapshot_init<F: ImfsFetcher>(
|
fn snapshot_init<F: VfsFetcher>(
|
||||||
context: &mut InstanceSnapshotContext,
|
context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
folder_entry: &ImfsEntry,
|
folder_entry: &VfsEntry,
|
||||||
init_name: &str,
|
init_name: &str,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
let init_path = folder_entry.path().join(init_name);
|
let init_path = folder_entry.path().join(init_name);
|
||||||
|
|
||||||
if let Some(init_entry) = imfs.get(init_path).with_not_found()? {
|
if let Some(init_entry) = vfs.get(init_path).with_not_found()? {
|
||||||
if let Some(dir_snapshot) = SnapshotDir::from_imfs(context, imfs, folder_entry)? {
|
if let Some(dir_snapshot) = SnapshotDir::from_vfs(context, vfs, folder_entry)? {
|
||||||
if let Some(mut init_snapshot) = snapshot_lua_file(imfs, &init_entry)? {
|
if let Some(mut init_snapshot) = snapshot_lua_file(vfs, &init_entry)? {
|
||||||
init_snapshot.name = dir_snapshot.name;
|
init_snapshot.name = dir_snapshot.name;
|
||||||
init_snapshot.children = dir_snapshot.children;
|
init_snapshot.children = dir_snapshot.children;
|
||||||
// TODO: Metadata
|
// TODO: Metadata
|
||||||
@@ -145,18 +145,18 @@ mod test {
|
|||||||
|
|
||||||
use insta::{assert_yaml_snapshot, with_settings};
|
use insta::{assert_yaml_snapshot, with_settings};
|
||||||
|
|
||||||
use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher};
|
use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn module_from_imfs() {
|
fn module_from_vfs() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file("Hello there!");
|
let file = VfsSnapshot::file("Hello there!");
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.lua", file);
|
vfs.debug_load_snapshot("/foo.lua", file);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.lua").unwrap();
|
let entry = vfs.get("/foo.lua").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -164,15 +164,15 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn server_from_imfs() {
|
fn server_from_vfs() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file("Hello there!");
|
let file = VfsSnapshot::file("Hello there!");
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.server.lua", file);
|
vfs.debug_load_snapshot("/foo.server.lua", file);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.server.lua").unwrap();
|
let entry = vfs.get("/foo.server.lua").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -180,15 +180,15 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn client_from_imfs() {
|
fn client_from_vfs() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file("Hello there!");
|
let file = VfsSnapshot::file("Hello there!");
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.client.lua", file);
|
vfs.debug_load_snapshot("/foo.client.lua", file);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.client.lua").unwrap();
|
let entry = vfs.get("/foo.client.lua").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -197,9 +197,9 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn module_with_meta() {
|
fn module_with_meta() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file("Hello there!");
|
let file = VfsSnapshot::file("Hello there!");
|
||||||
let meta = ImfsSnapshot::file(
|
let meta = VfsSnapshot::file(
|
||||||
r#"
|
r#"
|
||||||
{
|
{
|
||||||
"ignoreUnknownInstances": true
|
"ignoreUnknownInstances": true
|
||||||
@@ -207,12 +207,12 @@ mod test {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.lua", file);
|
vfs.debug_load_snapshot("/foo.lua", file);
|
||||||
imfs.debug_load_snapshot("/foo.meta.json", meta);
|
vfs.debug_load_snapshot("/foo.meta.json", meta);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.lua").unwrap();
|
let entry = vfs.get("/foo.lua").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -221,9 +221,9 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script_with_meta() {
|
fn script_with_meta() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file("Hello there!");
|
let file = VfsSnapshot::file("Hello there!");
|
||||||
let meta = ImfsSnapshot::file(
|
let meta = VfsSnapshot::file(
|
||||||
r#"
|
r#"
|
||||||
{
|
{
|
||||||
"ignoreUnknownInstances": true
|
"ignoreUnknownInstances": true
|
||||||
@@ -231,12 +231,12 @@ mod test {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.server.lua", file);
|
vfs.debug_load_snapshot("/foo.server.lua", file);
|
||||||
imfs.debug_load_snapshot("/foo.meta.json", meta);
|
vfs.debug_load_snapshot("/foo.meta.json", meta);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.server.lua").unwrap();
|
let entry = vfs.get("/foo.server.lua").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -245,9 +245,9 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script_disabled() {
|
fn script_disabled() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file("Hello there!");
|
let file = VfsSnapshot::file("Hello there!");
|
||||||
let meta = ImfsSnapshot::file(
|
let meta = VfsSnapshot::file(
|
||||||
r#"
|
r#"
|
||||||
{
|
{
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -257,12 +257,12 @@ mod test {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/bar.server.lua", file);
|
vfs.debug_load_snapshot("/bar.server.lua", file);
|
||||||
imfs.debug_load_snapshot("/bar.meta.json", meta);
|
vfs.debug_load_snapshot("/bar.meta.json", meta);
|
||||||
|
|
||||||
let entry = imfs.get("/bar.server.lua").unwrap();
|
let entry = vfs.get("/bar.server.lua").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -3,20 +3,20 @@ use std::path::{Path, PathBuf};
|
|||||||
use rbx_dom_weak::{RbxId, RbxTree};
|
use rbx_dom_weak::{RbxId, RbxTree};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot},
|
|
||||||
snapshot::InstanceSnapshot,
|
snapshot::InstanceSnapshot,
|
||||||
|
vfs::{Vfs, VfsEntry, VfsFetcher, VfsSnapshot},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{context::InstanceSnapshotContext, error::SnapshotError};
|
use super::{context::InstanceSnapshotContext, error::SnapshotError};
|
||||||
|
|
||||||
pub type SnapshotInstanceResult<'a> = Result<Option<InstanceSnapshot<'a>>, SnapshotError>;
|
pub type SnapshotInstanceResult<'a> = Result<Option<InstanceSnapshot<'a>>, SnapshotError>;
|
||||||
pub type SnapshotFileResult = Option<(String, ImfsSnapshot)>;
|
pub type SnapshotFileResult = Option<(String, VfsSnapshot)>;
|
||||||
|
|
||||||
pub trait SnapshotMiddleware {
|
pub trait SnapshotMiddleware {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
context: &mut InstanceSnapshotContext,
|
context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static>;
|
) -> SnapshotInstanceResult<'static>;
|
||||||
|
|
||||||
fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult {
|
fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult {
|
||||||
|
|||||||
@@ -37,20 +37,20 @@ use self::{
|
|||||||
txt::SnapshotTxt,
|
txt::SnapshotTxt,
|
||||||
user_plugins::SnapshotUserPlugins,
|
user_plugins::SnapshotUserPlugins,
|
||||||
};
|
};
|
||||||
use crate::imfs::{Imfs, ImfsEntry, ImfsFetcher};
|
use crate::vfs::{Vfs, VfsEntry, VfsFetcher};
|
||||||
|
|
||||||
macro_rules! middlewares {
|
macro_rules! middlewares {
|
||||||
( $($middleware: ident,)* ) => {
|
( $($middleware: ident,)* ) => {
|
||||||
/// Generates a snapshot of instances from the given ImfsEntry.
|
/// Generates a snapshot of instances from the given VfsEntry.
|
||||||
pub fn snapshot_from_imfs<F: ImfsFetcher>(
|
pub fn snapshot_from_vfs<F: VfsFetcher>(
|
||||||
context: &mut InstanceSnapshotContext,
|
context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
$(
|
$(
|
||||||
log::trace!("trying middleware {} on {}", stringify!($middleware), entry.path().display());
|
log::trace!("trying middleware {} on {}", stringify!($middleware), entry.path().display());
|
||||||
|
|
||||||
if let Some(snapshot) = $middleware::from_imfs(context, imfs, entry)? {
|
if let Some(snapshot) = $middleware::from_vfs(context, vfs, entry)? {
|
||||||
log::trace!("middleware {} success on {}", stringify!($middleware), entry.path().display());
|
log::trace!("middleware {} success on {}", stringify!($middleware), entry.path().display());
|
||||||
return Ok(Some(snapshot));
|
return Ok(Some(snapshot));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,16 @@ use std::{borrow::Cow, collections::HashMap};
|
|||||||
use rbx_reflection::try_resolve_value;
|
use rbx_reflection::try_resolve_value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher},
|
|
||||||
project::{Project, ProjectNode},
|
project::{Project, ProjectNode},
|
||||||
snapshot::{InstanceMetadata, InstanceSnapshot, InstigatingSource},
|
snapshot::{InstanceMetadata, InstanceSnapshot, InstigatingSource},
|
||||||
|
vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
context::InstanceSnapshotContext,
|
context::InstanceSnapshotContext,
|
||||||
error::SnapshotError,
|
error::SnapshotError,
|
||||||
middleware::{SnapshotInstanceResult, SnapshotMiddleware},
|
middleware::{SnapshotInstanceResult, SnapshotMiddleware},
|
||||||
snapshot_from_imfs,
|
snapshot_from_vfs,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Handles snapshots for:
|
/// Handles snapshots for:
|
||||||
@@ -21,19 +21,19 @@ use super::{
|
|||||||
pub struct SnapshotProject;
|
pub struct SnapshotProject;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotProject {
|
impl SnapshotMiddleware for SnapshotProject {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
context: &mut InstanceSnapshotContext,
|
context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
if entry.is_directory() {
|
if entry.is_directory() {
|
||||||
let project_path = entry.path().join("default.project.json");
|
let project_path = entry.path().join("default.project.json");
|
||||||
|
|
||||||
match imfs.get(project_path).with_not_found()? {
|
match vfs.get(project_path).with_not_found()? {
|
||||||
// TODO: Do we need to muck with the relevant paths if we're a
|
// TODO: Do we need to muck with the relevant paths if we're a
|
||||||
// project file within a folder? Should the folder path be the
|
// project file within a folder? Should the folder path be the
|
||||||
// relevant path instead of the project file path?
|
// relevant path instead of the project file path?
|
||||||
Some(entry) => return SnapshotProject::from_imfs(context, imfs, &entry),
|
Some(entry) => return SnapshotProject::from_vfs(context, vfs, &entry),
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,13 +43,13 @@ impl SnapshotMiddleware for SnapshotProject {
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let project = Project::load_from_slice(entry.contents(imfs)?, entry.path())
|
let project = Project::load_from_slice(entry.contents(vfs)?, entry.path())
|
||||||
.map_err(|err| SnapshotError::malformed_project(err, entry.path()))?;
|
.map_err(|err| SnapshotError::malformed_project(err, entry.path()))?;
|
||||||
|
|
||||||
// Snapshotting a project should always return an instance, so this
|
// Snapshotting a project should always return an instance, so this
|
||||||
// unwrap is safe.
|
// unwrap is safe.
|
||||||
let mut snapshot =
|
let mut snapshot =
|
||||||
snapshot_project_node(context, &project.name, &project.tree, imfs)?.unwrap();
|
snapshot_project_node(context, &project.name, &project.tree, vfs)?.unwrap();
|
||||||
|
|
||||||
// Setting the instigating source to the project file path is a little
|
// Setting the instigating source to the project file path is a little
|
||||||
// coarse.
|
// coarse.
|
||||||
@@ -76,11 +76,11 @@ impl SnapshotMiddleware for SnapshotProject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn snapshot_project_node<F: ImfsFetcher>(
|
fn snapshot_project_node<F: VfsFetcher>(
|
||||||
context: &mut InstanceSnapshotContext,
|
context: &mut InstanceSnapshotContext,
|
||||||
instance_name: &str,
|
instance_name: &str,
|
||||||
node: &ProjectNode,
|
node: &ProjectNode,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
let name = Cow::Owned(instance_name.to_owned());
|
let name = Cow::Owned(instance_name.to_owned());
|
||||||
let mut class_name = node
|
let mut class_name = node
|
||||||
@@ -92,9 +92,9 @@ fn snapshot_project_node<F: ImfsFetcher>(
|
|||||||
let mut metadata = InstanceMetadata::default();
|
let mut metadata = InstanceMetadata::default();
|
||||||
|
|
||||||
if let Some(path) = &node.path {
|
if let Some(path) = &node.path {
|
||||||
let entry = imfs.get(path)?;
|
let entry = vfs.get(path)?;
|
||||||
|
|
||||||
if let Some(snapshot) = snapshot_from_imfs(context, imfs, &entry)? {
|
if let Some(snapshot) = snapshot_from_vfs(context, vfs, &entry)? {
|
||||||
// If a class name was already specified, then it'll override the
|
// If a class name was already specified, then it'll override the
|
||||||
// class name of this snapshot ONLY if it's a Folder.
|
// class name of this snapshot ONLY if it's a Folder.
|
||||||
//
|
//
|
||||||
@@ -144,7 +144,7 @@ fn snapshot_project_node<F: ImfsFetcher>(
|
|||||||
.expect("$className or $path must be specified");
|
.expect("$className or $path must be specified");
|
||||||
|
|
||||||
for (child_name, child_project_node) in &node.children {
|
for (child_name, child_project_node) in &node.children {
|
||||||
if let Some(child) = snapshot_project_node(context, child_name, child_project_node, imfs)? {
|
if let Some(child) = snapshot_project_node(context, child_name, child_project_node, vfs)? {
|
||||||
children.push(child);
|
children.push(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,15 +192,15 @@ mod test {
|
|||||||
use insta::assert_yaml_snapshot;
|
use insta::assert_yaml_snapshot;
|
||||||
use maplit::hashmap;
|
use maplit::hashmap;
|
||||||
|
|
||||||
use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher};
|
use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn project_from_folder() {
|
fn project_from_folder() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => ImfsSnapshot::file(r#"
|
"default.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "indirect-project",
|
"name": "indirect-project",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -210,11 +210,11 @@ mod test {
|
|||||||
"#),
|
"#),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot error")
|
.expect("snapshot error")
|
||||||
.expect("snapshot returned no instances");
|
.expect("snapshot returned no instances");
|
||||||
|
|
||||||
@@ -225,9 +225,9 @@ mod test {
|
|||||||
fn project_from_direct_file() {
|
fn project_from_direct_file() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"hello.project.json" => ImfsSnapshot::file(r#"
|
"hello.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "direct-project",
|
"name": "direct-project",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -237,11 +237,11 @@ mod test {
|
|||||||
"#),
|
"#),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo/hello.project.json").unwrap();
|
let entry = vfs.get("/foo/hello.project.json").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot error")
|
.expect("snapshot error")
|
||||||
.expect("snapshot returned no instances");
|
.expect("snapshot returned no instances");
|
||||||
|
|
||||||
@@ -252,9 +252,9 @@ mod test {
|
|||||||
fn project_with_resolved_properties() {
|
fn project_with_resolved_properties() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => ImfsSnapshot::file(r#"
|
"default.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "resolved-properties",
|
"name": "resolved-properties",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -270,11 +270,11 @@ mod test {
|
|||||||
"#),
|
"#),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot error")
|
.expect("snapshot error")
|
||||||
.expect("snapshot returned no instances");
|
.expect("snapshot returned no instances");
|
||||||
|
|
||||||
@@ -285,9 +285,9 @@ mod test {
|
|||||||
fn project_with_unresolved_properties() {
|
fn project_with_unresolved_properties() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => ImfsSnapshot::file(r#"
|
"default.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "unresolved-properties",
|
"name": "unresolved-properties",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -300,11 +300,11 @@ mod test {
|
|||||||
"#),
|
"#),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot error")
|
.expect("snapshot error")
|
||||||
.expect("snapshot returned no instances");
|
.expect("snapshot returned no instances");
|
||||||
|
|
||||||
@@ -315,9 +315,9 @@ mod test {
|
|||||||
fn project_with_children() {
|
fn project_with_children() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => ImfsSnapshot::file(r#"
|
"default.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "children",
|
"name": "children",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -331,11 +331,11 @@ mod test {
|
|||||||
"#),
|
"#),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot error")
|
.expect("snapshot error")
|
||||||
.expect("snapshot returned no instances");
|
.expect("snapshot returned no instances");
|
||||||
|
|
||||||
@@ -346,9 +346,9 @@ mod test {
|
|||||||
fn project_with_path_to_txt() {
|
fn project_with_path_to_txt() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => ImfsSnapshot::file(r#"
|
"default.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "path-project",
|
"name": "path-project",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -356,14 +356,14 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"#),
|
"#),
|
||||||
"other.txt" => ImfsSnapshot::file("Hello, world!"),
|
"other.txt" => VfsSnapshot::file("Hello, world!"),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot error")
|
.expect("snapshot error")
|
||||||
.expect("snapshot returned no instances");
|
.expect("snapshot returned no instances");
|
||||||
|
|
||||||
@@ -374,9 +374,9 @@ mod test {
|
|||||||
fn project_with_path_to_project() {
|
fn project_with_path_to_project() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => ImfsSnapshot::file(r#"
|
"default.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "path-project",
|
"name": "path-project",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -384,7 +384,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"#),
|
"#),
|
||||||
"other.project.json" => ImfsSnapshot::file(r#"
|
"other.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "other-project",
|
"name": "other-project",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -394,11 +394,11 @@ mod test {
|
|||||||
"#),
|
"#),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot error")
|
.expect("snapshot error")
|
||||||
.expect("snapshot returned no instances");
|
.expect("snapshot returned no instances");
|
||||||
|
|
||||||
@@ -409,9 +409,9 @@ mod test {
|
|||||||
fn project_with_path_to_project_with_children() {
|
fn project_with_path_to_project_with_children() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => ImfsSnapshot::file(r#"
|
"default.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "path-child-project",
|
"name": "path-child-project",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -419,7 +419,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"#),
|
"#),
|
||||||
"other.project.json" => ImfsSnapshot::file(r#"
|
"other.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "other-project",
|
"name": "other-project",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -433,11 +433,11 @@ mod test {
|
|||||||
"#),
|
"#),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot error")
|
.expect("snapshot error")
|
||||||
.expect("snapshot returned no instances");
|
.expect("snapshot returned no instances");
|
||||||
|
|
||||||
@@ -451,9 +451,9 @@ mod test {
|
|||||||
fn project_path_property_overrides() {
|
fn project_path_property_overrides() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => ImfsSnapshot::file(r#"
|
"default.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "path-property-override",
|
"name": "path-property-override",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -464,7 +464,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"#),
|
"#),
|
||||||
"other.project.json" => ImfsSnapshot::file(r#"
|
"other.project.json" => VfsSnapshot::file(r#"
|
||||||
{
|
{
|
||||||
"name": "other-project",
|
"name": "other-project",
|
||||||
"tree": {
|
"tree": {
|
||||||
@@ -477,11 +477,11 @@ mod test {
|
|||||||
"#),
|
"#),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo", dir);
|
vfs.debug_load_snapshot("/foo", dir);
|
||||||
|
|
||||||
let entry = imfs.get("/foo").unwrap();
|
let entry = vfs.get("/foo").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.expect("snapshot error")
|
.expect("snapshot error")
|
||||||
.expect("snapshot returned no instances");
|
.expect("snapshot returned no instances");
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, ImfsEntry, ImfsFetcher},
|
|
||||||
snapshot::InstanceSnapshot,
|
snapshot::InstanceSnapshot,
|
||||||
|
vfs::{Vfs, VfsEntry, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -14,10 +14,10 @@ use super::{
|
|||||||
pub struct SnapshotRbxlx;
|
pub struct SnapshotRbxlx;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotRbxlx {
|
impl SnapshotMiddleware for SnapshotRbxlx {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
_context: &mut InstanceSnapshotContext,
|
_context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
if entry.is_directory() {
|
if entry.is_directory() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@@ -31,7 +31,7 @@ impl SnapshotMiddleware for SnapshotRbxlx {
|
|||||||
let options = rbx_xml::DecodeOptions::new()
|
let options = rbx_xml::DecodeOptions::new()
|
||||||
.property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown);
|
.property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown);
|
||||||
|
|
||||||
let temp_tree = rbx_xml::from_reader(entry.contents(imfs)?, options)
|
let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?, options)
|
||||||
.expect("TODO: Handle rbx_xml errors");
|
.expect("TODO: Handle rbx_xml errors");
|
||||||
|
|
||||||
let root_id = temp_tree.get_root_id();
|
let root_id = temp_tree.get_root_id();
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ use std::{borrow::Cow, collections::HashMap};
|
|||||||
use rbx_dom_weak::{RbxInstanceProperties, RbxTree};
|
use rbx_dom_weak::{RbxInstanceProperties, RbxTree};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, ImfsEntry, ImfsFetcher},
|
|
||||||
snapshot::InstanceSnapshot,
|
snapshot::InstanceSnapshot,
|
||||||
|
vfs::{Vfs, VfsEntry, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -16,10 +16,10 @@ use super::{
|
|||||||
pub struct SnapshotRbxm;
|
pub struct SnapshotRbxm;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotRbxm {
|
impl SnapshotMiddleware for SnapshotRbxm {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
_context: &mut InstanceSnapshotContext,
|
_context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
if entry.is_directory() {
|
if entry.is_directory() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@@ -37,7 +37,7 @@ impl SnapshotMiddleware for SnapshotRbxm {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let root_id = temp_tree.get_root_id();
|
let root_id = temp_tree.get_root_id();
|
||||||
rbx_binary::decode(&mut temp_tree, root_id, entry.contents(imfs)?)
|
rbx_binary::decode(&mut temp_tree, root_id, entry.contents(vfs)?)
|
||||||
.expect("TODO: Handle rbx_binary errors");
|
.expect("TODO: Handle rbx_binary errors");
|
||||||
|
|
||||||
let root_instance = temp_tree.get_instance(root_id).unwrap();
|
let root_instance = temp_tree.get_instance(root_id).unwrap();
|
||||||
@@ -60,18 +60,18 @@ impl SnapshotMiddleware for SnapshotRbxm {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher};
|
use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn model_from_imfs() {
|
fn model_from_vfs() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file(include_bytes!("../../assets/test-folder.rbxm").to_vec());
|
let file = VfsSnapshot::file(include_bytes!("../../assets/test-folder.rbxm").to_vec());
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.rbxm", file);
|
vfs.debug_load_snapshot("/foo.rbxm", file);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.rbxm").unwrap();
|
let entry = vfs.get("/foo.rbxm").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotRbxm::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotRbxm::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, ImfsEntry, ImfsFetcher},
|
|
||||||
snapshot::InstanceSnapshot,
|
snapshot::InstanceSnapshot,
|
||||||
|
vfs::{Vfs, VfsEntry, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -14,10 +14,10 @@ use super::{
|
|||||||
pub struct SnapshotRbxmx;
|
pub struct SnapshotRbxmx;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotRbxmx {
|
impl SnapshotMiddleware for SnapshotRbxmx {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
_context: &mut InstanceSnapshotContext,
|
_context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
if entry.is_directory() {
|
if entry.is_directory() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@@ -31,7 +31,7 @@ impl SnapshotMiddleware for SnapshotRbxmx {
|
|||||||
let options = rbx_xml::DecodeOptions::new()
|
let options = rbx_xml::DecodeOptions::new()
|
||||||
.property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown);
|
.property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown);
|
||||||
|
|
||||||
let temp_tree = rbx_xml::from_reader(entry.contents(imfs)?, options)
|
let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?, options)
|
||||||
.expect("TODO: Handle rbx_xml errors");
|
.expect("TODO: Handle rbx_xml errors");
|
||||||
|
|
||||||
let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap();
|
let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap();
|
||||||
@@ -56,12 +56,12 @@ mod test {
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher};
|
use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn model_from_imfs() {
|
fn model_from_vfs() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file(
|
let file = VfsSnapshot::file(
|
||||||
r#"
|
r#"
|
||||||
<roblox version="4">
|
<roblox version="4">
|
||||||
<Item class="Folder" referent="0">
|
<Item class="Folder" referent="0">
|
||||||
@@ -73,11 +73,11 @@ mod test {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.rbxmx", file);
|
vfs.debug_load_snapshot("/foo.rbxmx", file);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.rbxmx").unwrap();
|
let entry = vfs.get("/foo.rbxmx").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotRbxmx::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotRbxmx::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use maplit::hashmap;
|
|||||||
use rbx_dom_weak::{RbxId, RbxTree, RbxValue};
|
use rbx_dom_weak::{RbxId, RbxTree, RbxValue};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{FileSnapshot, FsResultExt, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot},
|
|
||||||
snapshot::{InstanceMetadata, InstanceSnapshot},
|
snapshot::{InstanceMetadata, InstanceSnapshot},
|
||||||
|
vfs::{FileSnapshot, FsResultExt, Vfs, VfsEntry, VfsFetcher, VfsSnapshot},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -19,10 +19,10 @@ use super::{
|
|||||||
pub struct SnapshotTxt;
|
pub struct SnapshotTxt;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotTxt {
|
impl SnapshotMiddleware for SnapshotTxt {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
_context: &mut InstanceSnapshotContext,
|
_context: &mut InstanceSnapshotContext,
|
||||||
imfs: &mut Imfs<F>,
|
vfs: &mut Vfs<F>,
|
||||||
entry: &ImfsEntry,
|
entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
if entry.is_directory() {
|
if entry.is_directory() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@@ -33,7 +33,7 @@ impl SnapshotMiddleware for SnapshotTxt {
|
|||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let contents = entry.contents(imfs)?;
|
let contents = entry.contents(vfs)?;
|
||||||
let contents_str = str::from_utf8(contents)
|
let contents_str = str::from_utf8(contents)
|
||||||
.map_err(|err| SnapshotError::file_contents_bad_unicode(err, entry.path()))?
|
.map_err(|err| SnapshotError::file_contents_bad_unicode(err, entry.path()))?
|
||||||
.to_string();
|
.to_string();
|
||||||
@@ -61,8 +61,8 @@ impl SnapshotMiddleware for SnapshotTxt {
|
|||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? {
|
if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? {
|
||||||
let meta_contents = meta_entry.contents(imfs)?;
|
let meta_contents = meta_entry.contents(vfs)?;
|
||||||
let mut metadata = AdjacentMetadata::from_slice(meta_contents);
|
let mut metadata = AdjacentMetadata::from_slice(meta_contents);
|
||||||
metadata.apply_all(&mut snapshot);
|
metadata.apply_all(&mut snapshot);
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ impl SnapshotMiddleware for SnapshotTxt {
|
|||||||
None => String::new(),
|
None => String::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let snapshot = ImfsSnapshot::File(FileSnapshot {
|
let snapshot = VfsSnapshot::File(FileSnapshot {
|
||||||
contents: value.into_bytes(),
|
contents: value.into_bytes(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -106,18 +106,18 @@ mod test {
|
|||||||
use maplit::hashmap;
|
use maplit::hashmap;
|
||||||
use rbx_dom_weak::RbxInstanceProperties;
|
use rbx_dom_weak::RbxInstanceProperties;
|
||||||
|
|
||||||
use crate::imfs::{ImfsDebug, NoopFetcher};
|
use crate::vfs::{NoopFetcher, VfsDebug};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn instance_from_imfs() {
|
fn instance_from_vfs() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file("Hello there!");
|
let file = VfsSnapshot::file("Hello there!");
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/foo.txt", file);
|
vfs.debug_load_snapshot("/foo.txt", file);
|
||||||
|
|
||||||
let entry = imfs.get("/foo.txt").unwrap();
|
let entry = vfs.get("/foo.txt").unwrap();
|
||||||
let instance_snapshot =
|
let instance_snapshot =
|
||||||
SnapshotTxt::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry)
|
SnapshotTxt::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn imfs_from_instance() {
|
fn vfs_from_instance() {
|
||||||
let tree = RbxTree::new(string_value("Root", "Hello, world!"));
|
let tree = RbxTree::new(string_value("Root", "Hello, world!"));
|
||||||
let root_id = tree.get_root_id();
|
let root_id = tree.get_root_id();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::{fs, path::Path};
|
|||||||
|
|
||||||
use rlua::{Lua, RegistryKey};
|
use rlua::{Lua, RegistryKey};
|
||||||
|
|
||||||
use crate::imfs::{Imfs, ImfsEntry, ImfsFetcher};
|
use crate::vfs::{Vfs, VfsEntry, VfsFetcher};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
context::InstanceSnapshotContext,
|
context::InstanceSnapshotContext,
|
||||||
@@ -19,10 +19,10 @@ use super::{
|
|||||||
pub struct SnapshotUserPlugins;
|
pub struct SnapshotUserPlugins;
|
||||||
|
|
||||||
impl SnapshotMiddleware for SnapshotUserPlugins {
|
impl SnapshotMiddleware for SnapshotUserPlugins {
|
||||||
fn from_imfs<F: ImfsFetcher>(
|
fn from_vfs<F: VfsFetcher>(
|
||||||
context: &mut InstanceSnapshotContext,
|
context: &mut InstanceSnapshotContext,
|
||||||
_imfs: &mut Imfs<F>,
|
_vfs: &mut Vfs<F>,
|
||||||
_entry: &ImfsEntry,
|
_entry: &VfsEntry,
|
||||||
) -> SnapshotInstanceResult<'static> {
|
) -> SnapshotInstanceResult<'static> {
|
||||||
// User plugins are only enabled if present on the snapshot context.
|
// User plugins are only enabled if present on the snapshot context.
|
||||||
let plugin_context = match &mut context.plugin_context {
|
let plugin_context = match &mut context.plugin_context {
|
||||||
@@ -52,7 +52,7 @@ impl SnapshotMiddleware for SnapshotUserPlugins {
|
|||||||
// The current plan for plugins here is to make them work
|
// The current plan for plugins here is to make them work
|
||||||
// like Redux/Rodux middleware. A plugin will be a function
|
// like Redux/Rodux middleware. A plugin will be a function
|
||||||
// that accepts the next middleware in the chain as a
|
// that accepts the next middleware in the chain as a
|
||||||
// function and the snapshot subject (the IMFS entry).
|
// function and the snapshot subject (the VFS entry).
|
||||||
//
|
//
|
||||||
// Plugins can (but don't have to) invoke the next snapshot
|
// Plugins can (but don't have to) invoke the next snapshot
|
||||||
// function and may or may not mutate the result. The hope
|
// function and may or may not mutate the result. The hope
|
||||||
@@ -69,7 +69,7 @@ impl SnapshotMiddleware for SnapshotUserPlugins {
|
|||||||
// * Will plugins hurt Rojo's ability to parallelize
|
// * Will plugins hurt Rojo's ability to parallelize
|
||||||
// snapshotting in the future?
|
// snapshotting in the future?
|
||||||
//
|
//
|
||||||
// * Do the mutable handles to the Imfs and the snapshot
|
// * Do the mutable handles to the Vfs and the snapshot
|
||||||
// context prevent plugins from invoking other plugins
|
// context prevent plugins from invoking other plugins
|
||||||
// indirectly?
|
// indirectly?
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ImfsEvent {
|
pub enum VfsEvent {
|
||||||
Modified(PathBuf),
|
Modified(PathBuf),
|
||||||
Created(PathBuf),
|
Created(PathBuf),
|
||||||
Removed(PathBuf),
|
Removed(PathBuf),
|
||||||
@@ -5,7 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use crossbeam_channel::Receiver;
|
use crossbeam_channel::Receiver;
|
||||||
|
|
||||||
use super::event::ImfsEvent;
|
use super::event::VfsEvent;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum FileType {
|
pub enum FileType {
|
||||||
@@ -13,10 +13,10 @@ pub enum FileType {
|
|||||||
Directory,
|
Directory,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The generic interface that `Imfs` uses to lazily read files from the disk.
|
/// The generic interface that `Vfs` uses to lazily read files from the disk.
|
||||||
/// In tests, it's stubbed out to do different versions of absolutely nothing
|
/// In tests, it's stubbed out to do different versions of absolutely nothing
|
||||||
/// depending on the test.
|
/// depending on the test.
|
||||||
pub trait ImfsFetcher {
|
pub trait VfsFetcher {
|
||||||
fn file_type(&mut self, path: &Path) -> io::Result<FileType>;
|
fn file_type(&mut self, path: &Path) -> io::Result<FileType>;
|
||||||
fn read_children(&mut self, path: &Path) -> io::Result<Vec<PathBuf>>;
|
fn read_children(&mut self, path: &Path) -> io::Result<Vec<PathBuf>>;
|
||||||
fn read_contents(&mut self, path: &Path) -> io::Result<Vec<u8>>;
|
fn read_contents(&mut self, path: &Path) -> io::Result<Vec<u8>>;
|
||||||
@@ -27,7 +27,7 @@ pub trait ImfsFetcher {
|
|||||||
|
|
||||||
fn watch(&mut self, path: &Path);
|
fn watch(&mut self, path: &Path);
|
||||||
fn unwatch(&mut self, path: &Path);
|
fn unwatch(&mut self, path: &Path);
|
||||||
fn receiver(&self) -> Receiver<ImfsEvent>;
|
fn receiver(&self) -> Receiver<VfsEvent>;
|
||||||
|
|
||||||
/// A method intended for debugging what paths the fetcher is watching.
|
/// A method intended for debugging what paths the fetcher is watching.
|
||||||
fn watched_paths(&self) -> Vec<&Path> {
|
fn watched_paths(&self) -> Vec<&Path> {
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
mod error;
|
mod error;
|
||||||
mod event;
|
mod event;
|
||||||
mod fetcher;
|
mod fetcher;
|
||||||
mod imfs;
|
|
||||||
mod noop_fetcher;
|
mod noop_fetcher;
|
||||||
mod real_fetcher;
|
mod real_fetcher;
|
||||||
mod snapshot;
|
mod snapshot;
|
||||||
|
mod vfs;
|
||||||
|
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
pub use event::*;
|
pub use event::*;
|
||||||
pub use fetcher::*;
|
pub use fetcher::*;
|
||||||
pub use imfs::*;
|
|
||||||
pub use noop_fetcher::*;
|
pub use noop_fetcher::*;
|
||||||
pub use real_fetcher::*;
|
pub use real_fetcher::*;
|
||||||
pub use snapshot::*;
|
pub use snapshot::*;
|
||||||
|
pub use vfs::*;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_fetcher;
|
mod test_fetcher;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Implements the IMFS fetcher interface for a fake filesystem using Rust's
|
//! Implements the VFS fetcher interface for a fake filesystem using Rust's
|
||||||
//! std::fs interface.
|
//! std::fs interface.
|
||||||
|
|
||||||
// This interface is only used for testing, so it's okay if it isn't used.
|
// This interface is only used for testing, so it's okay if it isn't used.
|
||||||
@@ -12,13 +12,13 @@ use std::{
|
|||||||
use crossbeam_channel::Receiver;
|
use crossbeam_channel::Receiver;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
event::ImfsEvent,
|
event::VfsEvent,
|
||||||
fetcher::{FileType, ImfsFetcher},
|
fetcher::{FileType, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct NoopFetcher;
|
pub struct NoopFetcher;
|
||||||
|
|
||||||
impl ImfsFetcher for NoopFetcher {
|
impl VfsFetcher for NoopFetcher {
|
||||||
fn file_type(&mut self, _path: &Path) -> io::Result<FileType> {
|
fn file_type(&mut self, _path: &Path) -> io::Result<FileType> {
|
||||||
Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::NotFound,
|
io::ErrorKind::NotFound,
|
||||||
@@ -56,7 +56,7 @@ impl ImfsFetcher for NoopFetcher {
|
|||||||
|
|
||||||
fn unwatch(&mut self, _path: &Path) {}
|
fn unwatch(&mut self, _path: &Path) {}
|
||||||
|
|
||||||
fn receiver(&self) -> Receiver<ImfsEvent> {
|
fn receiver(&self) -> Receiver<VfsEvent> {
|
||||||
crossbeam_channel::never()
|
crossbeam_channel::never()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Implements the IMFS fetcher interface for the real filesystem using Rust's
|
//! Implements the VFS fetcher interface for the real filesystem using Rust's
|
||||||
//! std::fs interface and notify as the file watcher.
|
//! std::fs interface and notify as the file watcher.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
@@ -14,8 +14,8 @@ use jod_thread::JoinHandle;
|
|||||||
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
|
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
event::ImfsEvent,
|
event::VfsEvent,
|
||||||
fetcher::{FileType, ImfsFetcher},
|
fetcher::{FileType, VfsFetcher},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Workaround to disable the file watcher for processes that don't need it,
|
/// Workaround to disable the file watcher for processes that don't need it,
|
||||||
@@ -41,7 +41,7 @@ pub struct RealFetcher {
|
|||||||
_converter_thread: JoinHandle<()>,
|
_converter_thread: JoinHandle<()>,
|
||||||
|
|
||||||
/// The crossbeam receiver filled with events from the converter thread.
|
/// The crossbeam receiver filled with events from the converter thread.
|
||||||
receiver: Receiver<ImfsEvent>,
|
receiver: Receiver<VfsEvent>,
|
||||||
|
|
||||||
/// All of the paths that the fetcher is watching, tracked here because
|
/// All of the paths that the fetcher is watching, tracked here because
|
||||||
/// notify does not expose this information.
|
/// notify does not expose this information.
|
||||||
@@ -84,19 +84,19 @@ impl RealFetcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn converter_thread(notify_receiver: mpsc::Receiver<DebouncedEvent>, sender: Sender<ImfsEvent>) {
|
fn converter_thread(notify_receiver: mpsc::Receiver<DebouncedEvent>, sender: Sender<VfsEvent>) {
|
||||||
use DebouncedEvent::*;
|
use DebouncedEvent::*;
|
||||||
|
|
||||||
for event in notify_receiver {
|
for event in notify_receiver {
|
||||||
log::trace!("Notify event: {:?}", event);
|
log::trace!("Notify event: {:?}", event);
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Create(path) => sender.send(ImfsEvent::Created(path)).unwrap(),
|
Create(path) => sender.send(VfsEvent::Created(path)).unwrap(),
|
||||||
Write(path) => sender.send(ImfsEvent::Modified(path)).unwrap(),
|
Write(path) => sender.send(VfsEvent::Modified(path)).unwrap(),
|
||||||
Remove(path) => sender.send(ImfsEvent::Removed(path)).unwrap(),
|
Remove(path) => sender.send(VfsEvent::Removed(path)).unwrap(),
|
||||||
Rename(from_path, to_path) => {
|
Rename(from_path, to_path) => {
|
||||||
sender.send(ImfsEvent::Created(from_path)).unwrap();
|
sender.send(VfsEvent::Created(from_path)).unwrap();
|
||||||
sender.send(ImfsEvent::Removed(to_path)).unwrap();
|
sender.send(VfsEvent::Removed(to_path)).unwrap();
|
||||||
}
|
}
|
||||||
Rescan => {
|
Rescan => {
|
||||||
log::warn!("Unhandled filesystem rescan event.");
|
log::warn!("Unhandled filesystem rescan event.");
|
||||||
@@ -121,7 +121,7 @@ fn converter_thread(notify_receiver: mpsc::Receiver<DebouncedEvent>, sender: Sen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImfsFetcher for RealFetcher {
|
impl VfsFetcher for RealFetcher {
|
||||||
fn file_type(&mut self, path: &Path) -> io::Result<FileType> {
|
fn file_type(&mut self, path: &Path) -> io::Result<FileType> {
|
||||||
let metadata = fs::metadata(path)?;
|
let metadata = fs::metadata(path)?;
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ impl ImfsFetcher for RealFetcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receiver(&self) -> Receiver<ImfsEvent> {
|
fn receiver(&self) -> Receiver<VfsEvent> {
|
||||||
self.receiver.clone()
|
self.receiver.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
42
src/vfs/snapshot.rs
Normal file
42
src/vfs/snapshot.rs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// This file is non-critical and used for testing, so it's okay if it's unused.
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum VfsSnapshot {
|
||||||
|
File(FileSnapshot),
|
||||||
|
Directory(DirectorySnapshot),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VfsSnapshot {
|
||||||
|
/// Create a new file VfsSnapshot with the given contents.
|
||||||
|
pub fn file(contents: impl Into<Vec<u8>>) -> VfsSnapshot {
|
||||||
|
VfsSnapshot::File(FileSnapshot {
|
||||||
|
contents: contents.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new directory VfsSnapshot with the given children.
|
||||||
|
pub fn dir<S: Into<String>>(children: HashMap<S, VfsSnapshot>) -> VfsSnapshot {
|
||||||
|
let children = children.into_iter().map(|(k, v)| (k.into(), v)).collect();
|
||||||
|
|
||||||
|
VfsSnapshot::Directory(DirectorySnapshot { children })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn empty_dir() -> VfsSnapshot {
|
||||||
|
VfsSnapshot::Directory(DirectorySnapshot {
|
||||||
|
children: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FileSnapshot {
|
||||||
|
pub contents: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DirectorySnapshot {
|
||||||
|
pub children: HashMap<String, VfsSnapshot>,
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Implements the IMFS fetcher interface for a fake filesystem that can be
|
//! Implements the VFS fetcher interface for a fake filesystem that can be
|
||||||
//! mutated and have changes signaled through it.
|
//! mutated and have changes signaled through it.
|
||||||
//!
|
//!
|
||||||
//! This is useful for testing how things using Imfs react to changed events
|
//! This is useful for testing how things using Vfs react to changed events
|
||||||
//! without relying on the real filesystem implementation, which is very
|
//! without relying on the real filesystem implementation, which is very
|
||||||
//! platform-specific.
|
//! platform-specific.
|
||||||
|
|
||||||
@@ -19,9 +19,9 @@ use crossbeam_channel::{unbounded, Receiver, Sender};
|
|||||||
use crate::path_map::PathMap;
|
use crate::path_map::PathMap;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
event::ImfsEvent,
|
event::VfsEvent,
|
||||||
fetcher::{FileType, ImfsFetcher},
|
fetcher::{FileType, VfsFetcher},
|
||||||
snapshot::ImfsSnapshot,
|
snapshot::VfsSnapshot,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -30,7 +30,7 @@ pub struct TestFetcherState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TestFetcherState {
|
impl TestFetcherState {
|
||||||
pub fn load_snapshot<P: AsRef<Path>>(&self, path: P, snapshot: ImfsSnapshot) {
|
pub fn load_snapshot<P: AsRef<Path>>(&self, path: P, snapshot: VfsSnapshot) {
|
||||||
let mut inner = self.inner.lock().unwrap();
|
let mut inner = self.inner.lock().unwrap();
|
||||||
inner.load_snapshot(path.as_ref().to_path_buf(), snapshot);
|
inner.load_snapshot(path.as_ref().to_path_buf(), snapshot);
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ impl TestFetcherState {
|
|||||||
inner.remove(path.as_ref());
|
inner.remove(path.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raise_event(&self, event: ImfsEvent) {
|
pub fn raise_event(&self, event: VfsEvent) {
|
||||||
let mut inner = self.inner.lock().unwrap();
|
let mut inner = self.inner.lock().unwrap();
|
||||||
inner.raise_event(event);
|
inner.raise_event(event);
|
||||||
}
|
}
|
||||||
@@ -53,24 +53,24 @@ pub enum TestFetcherEntry {
|
|||||||
|
|
||||||
struct TestFetcherStateInner {
|
struct TestFetcherStateInner {
|
||||||
entries: PathMap<TestFetcherEntry>,
|
entries: PathMap<TestFetcherEntry>,
|
||||||
sender: Sender<ImfsEvent>,
|
sender: Sender<VfsEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestFetcherStateInner {
|
impl TestFetcherStateInner {
|
||||||
fn new(sender: Sender<ImfsEvent>) -> Self {
|
fn new(sender: Sender<VfsEvent>) -> Self {
|
||||||
let mut entries = PathMap::new();
|
let mut entries = PathMap::new();
|
||||||
entries.insert(Path::new("/"), TestFetcherEntry::Dir);
|
entries.insert(Path::new("/"), TestFetcherEntry::Dir);
|
||||||
|
|
||||||
Self { sender, entries }
|
Self { sender, entries }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_snapshot(&mut self, path: PathBuf, snapshot: ImfsSnapshot) {
|
fn load_snapshot(&mut self, path: PathBuf, snapshot: VfsSnapshot) {
|
||||||
match snapshot {
|
match snapshot {
|
||||||
ImfsSnapshot::File(file) => {
|
VfsSnapshot::File(file) => {
|
||||||
self.entries
|
self.entries
|
||||||
.insert(path, TestFetcherEntry::File(file.contents));
|
.insert(path, TestFetcherEntry::File(file.contents));
|
||||||
}
|
}
|
||||||
ImfsSnapshot::Directory(directory) => {
|
VfsSnapshot::Directory(directory) => {
|
||||||
self.entries.insert(path.clone(), TestFetcherEntry::Dir);
|
self.entries.insert(path.clone(), TestFetcherEntry::Dir);
|
||||||
|
|
||||||
for (child_name, child) in directory.children.into_iter() {
|
for (child_name, child) in directory.children.into_iter() {
|
||||||
@@ -84,14 +84,14 @@ impl TestFetcherStateInner {
|
|||||||
self.entries.remove(path);
|
self.entries.remove(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raise_event(&mut self, event: ImfsEvent) {
|
fn raise_event(&mut self, event: VfsEvent) {
|
||||||
self.sender.send(event).unwrap();
|
self.sender.send(event).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestFetcher {
|
pub struct TestFetcher {
|
||||||
state: TestFetcherState,
|
state: TestFetcherState,
|
||||||
receiver: Receiver<ImfsEvent>,
|
receiver: Receiver<VfsEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestFetcher {
|
impl TestFetcher {
|
||||||
@@ -106,7 +106,7 @@ impl TestFetcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImfsFetcher for TestFetcher {
|
impl VfsFetcher for TestFetcher {
|
||||||
fn file_type(&mut self, path: &Path) -> io::Result<FileType> {
|
fn file_type(&mut self, path: &Path) -> io::Result<FileType> {
|
||||||
let inner = self.state.inner.lock().unwrap();
|
let inner = self.state.inner.lock().unwrap();
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ impl ImfsFetcher for TestFetcher {
|
|||||||
|
|
||||||
fn unwatch(&mut self, _path: &Path) {}
|
fn unwatch(&mut self, _path: &Path) {}
|
||||||
|
|
||||||
fn receiver(&self) -> Receiver<ImfsEvent> {
|
fn receiver(&self) -> Receiver<VfsEvent> {
|
||||||
self.receiver.clone()
|
self.receiver.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,48 +9,48 @@ use crate::path_map::PathMap;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
error::{FsError, FsResult},
|
error::{FsError, FsResult},
|
||||||
event::ImfsEvent,
|
event::VfsEvent,
|
||||||
fetcher::{FileType, ImfsFetcher},
|
fetcher::{FileType, VfsFetcher},
|
||||||
snapshot::ImfsSnapshot,
|
snapshot::VfsSnapshot,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An in-memory filesystem that can be incrementally populated and updated as
|
/// An in-memory filesystem that can be incrementally populated and updated as
|
||||||
/// filesystem modification events occur.
|
/// filesystem modification events occur.
|
||||||
///
|
///
|
||||||
/// All operations on the `Imfs` are lazy and do I/O as late as they can to
|
/// All operations on the `Vfs` are lazy and do I/O as late as they can to
|
||||||
/// avoid reading extraneous files or directories from the disk. This means that
|
/// avoid reading extraneous files or directories from the disk. This means that
|
||||||
/// they all take `self` mutably, and means that it isn't possible to hold
|
/// they all take `self` mutably, and means that it isn't possible to hold
|
||||||
/// references to the internal state of the Imfs while traversing it!
|
/// references to the internal state of the Vfs while traversing it!
|
||||||
///
|
///
|
||||||
/// Most operations return `ImfsEntry` objects to work around this, which is
|
/// Most operations return `VfsEntry` objects to work around this, which is
|
||||||
/// effectively a index into the `Imfs`.
|
/// effectively a index into the `Vfs`.
|
||||||
pub struct Imfs<F> {
|
pub struct Vfs<F> {
|
||||||
/// A hierarchical map from paths to items that have been read or partially
|
/// A hierarchical map from paths to items that have been read or partially
|
||||||
/// read into memory by the Imfs.
|
/// read into memory by the Vfs.
|
||||||
inner: PathMap<ImfsItem>,
|
inner: PathMap<VfsItem>,
|
||||||
|
|
||||||
/// This Imfs's fetcher, which is used for all actual interactions with the
|
/// This Vfs's fetcher, which is used for all actual interactions with the
|
||||||
/// filesystem. It's referred to by the type parameter `F` all over, and is
|
/// filesystem. It's referred to by the type parameter `F` all over, and is
|
||||||
/// generic in order to make it feasible to mock.
|
/// generic in order to make it feasible to mock.
|
||||||
fetcher: F,
|
fetcher: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher> Imfs<F> {
|
impl<F: VfsFetcher> Vfs<F> {
|
||||||
pub fn new(fetcher: F) -> Imfs<F> {
|
pub fn new(fetcher: F) -> Vfs<F> {
|
||||||
Imfs {
|
Vfs {
|
||||||
inner: PathMap::new(),
|
inner: PathMap::new(),
|
||||||
fetcher,
|
fetcher,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_receiver(&self) -> Receiver<ImfsEvent> {
|
pub fn change_receiver(&self) -> Receiver<VfsEvent> {
|
||||||
self.fetcher.receiver()
|
self.fetcher.receiver()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commit_change(&mut self, event: &ImfsEvent) -> FsResult<()> {
|
pub fn commit_change(&mut self, event: &VfsEvent) -> FsResult<()> {
|
||||||
use ImfsEvent::*;
|
use VfsEvent::*;
|
||||||
|
|
||||||
log::trace!("Committing Imfs change {:?}", event);
|
log::trace!("Committing Vfs change {:?}", event);
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Created(path) | Modified(path) => {
|
Created(path) | Modified(path) => {
|
||||||
@@ -79,28 +79,28 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
match self.inner.get_mut(path) {
|
match self.inner.get_mut(path) {
|
||||||
Some(existing_item) => {
|
Some(existing_item) => {
|
||||||
match (existing_item, &new_type) {
|
match (existing_item, &new_type) {
|
||||||
(ImfsItem::File(existing_file), FileType::File) => {
|
(VfsItem::File(existing_file), FileType::File) => {
|
||||||
// Invalidate the existing file contents.
|
// Invalidate the existing file contents.
|
||||||
// We can probably be smarter about this by reading the changed file.
|
// We can probably be smarter about this by reading the changed file.
|
||||||
existing_file.contents = None;
|
existing_file.contents = None;
|
||||||
}
|
}
|
||||||
(ImfsItem::Directory(_), FileType::Directory) => {
|
(VfsItem::Directory(_), FileType::Directory) => {
|
||||||
// No changes required, a directory updating doesn't mean anything to us.
|
// No changes required, a directory updating doesn't mean anything to us.
|
||||||
self.fetcher.watch(path);
|
self.fetcher.watch(path);
|
||||||
}
|
}
|
||||||
(ImfsItem::File(_), FileType::Directory) => {
|
(VfsItem::File(_), FileType::Directory) => {
|
||||||
self.inner.remove(path);
|
self.inner.remove(path);
|
||||||
self.inner.insert(
|
self.inner.insert(
|
||||||
path.to_path_buf(),
|
path.to_path_buf(),
|
||||||
ImfsItem::new_from_type(FileType::Directory, path),
|
VfsItem::new_from_type(FileType::Directory, path),
|
||||||
);
|
);
|
||||||
self.fetcher.watch(path);
|
self.fetcher.watch(path);
|
||||||
}
|
}
|
||||||
(ImfsItem::Directory(_), FileType::File) => {
|
(VfsItem::Directory(_), FileType::File) => {
|
||||||
self.inner.remove(path);
|
self.inner.remove(path);
|
||||||
self.inner.insert(
|
self.inner.insert(
|
||||||
path.to_path_buf(),
|
path.to_path_buf(),
|
||||||
ImfsItem::new_from_type(FileType::File, path),
|
VfsItem::new_from_type(FileType::File, path),
|
||||||
);
|
);
|
||||||
self.fetcher.unwatch(path);
|
self.fetcher.unwatch(path);
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.inner
|
self.inner
|
||||||
.insert(path.to_path_buf(), ImfsItem::new_from_type(new_type, path));
|
.insert(path.to_path_buf(), VfsItem::new_from_type(new_type, path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,17 +127,17 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&mut self, path: impl AsRef<Path>) -> FsResult<ImfsEntry> {
|
pub fn get(&mut self, path: impl AsRef<Path>) -> FsResult<VfsEntry> {
|
||||||
self.read_if_not_exists(path.as_ref())?;
|
self.read_if_not_exists(path.as_ref())?;
|
||||||
|
|
||||||
let item = self.inner.get(path.as_ref()).unwrap();
|
let item = self.inner.get(path.as_ref()).unwrap();
|
||||||
|
|
||||||
let is_file = match item {
|
let is_file = match item {
|
||||||
ImfsItem::File(_) => true,
|
VfsItem::File(_) => true,
|
||||||
ImfsItem::Directory(_) => false,
|
VfsItem::Directory(_) => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ImfsEntry {
|
Ok(VfsEntry {
|
||||||
path: item.path().to_path_buf(),
|
path: item.path().to_path_buf(),
|
||||||
is_file,
|
is_file,
|
||||||
})
|
})
|
||||||
@@ -149,7 +149,7 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
self.read_if_not_exists(path)?;
|
self.read_if_not_exists(path)?;
|
||||||
|
|
||||||
match self.inner.get_mut(path).unwrap() {
|
match self.inner.get_mut(path).unwrap() {
|
||||||
ImfsItem::File(file) => {
|
VfsItem::File(file) => {
|
||||||
if file.contents.is_none() {
|
if file.contents.is_none() {
|
||||||
file.contents = Some(
|
file.contents = Some(
|
||||||
self.fetcher
|
self.fetcher
|
||||||
@@ -160,20 +160,20 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
|
|
||||||
Ok(file.contents.as_ref().unwrap())
|
Ok(file.contents.as_ref().unwrap())
|
||||||
}
|
}
|
||||||
ImfsItem::Directory(_) => Err(FsError::new(
|
VfsItem::Directory(_) => Err(FsError::new(
|
||||||
io::Error::new(io::ErrorKind::Other, "Can't read a directory"),
|
io::Error::new(io::ErrorKind::Other, "Can't read a directory"),
|
||||||
path.to_path_buf(),
|
path.to_path_buf(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_children(&mut self, path: impl AsRef<Path>) -> FsResult<Vec<ImfsEntry>> {
|
pub fn get_children(&mut self, path: impl AsRef<Path>) -> FsResult<Vec<VfsEntry>> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
|
|
||||||
self.read_if_not_exists(path)?;
|
self.read_if_not_exists(path)?;
|
||||||
|
|
||||||
match self.inner.get_mut(path).unwrap() {
|
match self.inner.get_mut(path).unwrap() {
|
||||||
ImfsItem::Directory(dir) => {
|
VfsItem::Directory(dir) => {
|
||||||
self.fetcher.watch(path);
|
self.fetcher.watch(path);
|
||||||
|
|
||||||
let enumerated = dir.children_enumerated;
|
let enumerated = dir.children_enumerated;
|
||||||
@@ -187,7 +187,7 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
.collect::<Vec<PathBuf>>() // Collect all PathBufs, since self.get needs to borrow self mutably.
|
.collect::<Vec<PathBuf>>() // Collect all PathBufs, since self.get needs to borrow self mutably.
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|path| self.get(path))
|
.map(|path| self.get(path))
|
||||||
.collect::<FsResult<Vec<ImfsEntry>>>()
|
.collect::<FsResult<Vec<VfsEntry>>>()
|
||||||
} else {
|
} else {
|
||||||
dir.children_enumerated = true;
|
dir.children_enumerated = true;
|
||||||
|
|
||||||
@@ -196,10 +196,10 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
.map_err(|err| FsError::new(err, path.to_path_buf()))?
|
.map_err(|err| FsError::new(err, path.to_path_buf()))?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|path| self.get(path))
|
.map(|path| self.get(path))
|
||||||
.collect::<FsResult<Vec<ImfsEntry>>>()
|
.collect::<FsResult<Vec<VfsEntry>>>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImfsItem::File(_) => Err(FsError::new(
|
VfsItem::File(_) => Err(FsError::new(
|
||||||
io::Error::new(io::ErrorKind::Other, "Can't read a directory"),
|
io::Error::new(io::ErrorKind::Other, "Can't read a directory"),
|
||||||
path.to_path_buf(),
|
path.to_path_buf(),
|
||||||
)),
|
)),
|
||||||
@@ -222,7 +222,7 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(parent) = path.parent() {
|
if let Some(parent) = path.parent() {
|
||||||
if let Some(ImfsItem::Directory(dir)) = self.inner.get(parent) {
|
if let Some(VfsItem::Directory(dir)) = self.inner.get(parent) {
|
||||||
return !dir.children_enumerated;
|
return !dir.children_enumerated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,10 +230,10 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to read the path into the `Imfs` if it doesn't exist.
|
/// Attempts to read the path into the `Vfs` if it doesn't exist.
|
||||||
///
|
///
|
||||||
/// This does not necessitate that file contents or directory children will
|
/// This does not necessitate that file contents or directory children will
|
||||||
/// be read. Depending on the `ImfsFetcher` implementation that the `Imfs`
|
/// be read. Depending on the `VfsFetcher` implementation that the `Vfs`
|
||||||
/// is using, this call may read exactly only the given path and no more.
|
/// is using, this call may read exactly only the given path and no more.
|
||||||
fn read_if_not_exists(&mut self, path: &Path) -> FsResult<()> {
|
fn read_if_not_exists(&mut self, path: &Path) -> FsResult<()> {
|
||||||
if !self.inner.contains_key(path) {
|
if !self.inner.contains_key(path) {
|
||||||
@@ -247,7 +247,7 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.inner
|
self.inner
|
||||||
.insert(path.to_path_buf(), ImfsItem::new_from_type(kind, path));
|
.insert(path.to_path_buf(), VfsItem::new_from_type(kind, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -256,8 +256,8 @@ impl<F: ImfsFetcher> Imfs<F> {
|
|||||||
|
|
||||||
/// Contains extra methods that should only be used for debugging. They're
|
/// Contains extra methods that should only be used for debugging. They're
|
||||||
/// broken out into a separate trait to make it more explicit to depend on them.
|
/// broken out into a separate trait to make it more explicit to depend on them.
|
||||||
pub trait ImfsDebug {
|
pub trait VfsDebug {
|
||||||
fn debug_load_snapshot<P: AsRef<Path>>(&mut self, path: P, snapshot: ImfsSnapshot);
|
fn debug_load_snapshot<P: AsRef<Path>>(&mut self, path: P, snapshot: VfsSnapshot);
|
||||||
fn debug_is_file(&self, path: &Path) -> bool;
|
fn debug_is_file(&self, path: &Path) -> bool;
|
||||||
fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]>;
|
fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]>;
|
||||||
fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)>;
|
fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)>;
|
||||||
@@ -265,24 +265,24 @@ pub trait ImfsDebug {
|
|||||||
fn debug_watched_paths(&self) -> Vec<&Path>;
|
fn debug_watched_paths(&self) -> Vec<&Path>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher> ImfsDebug for Imfs<F> {
|
impl<F: VfsFetcher> VfsDebug for Vfs<F> {
|
||||||
fn debug_load_snapshot<P: AsRef<Path>>(&mut self, path: P, snapshot: ImfsSnapshot) {
|
fn debug_load_snapshot<P: AsRef<Path>>(&mut self, path: P, snapshot: VfsSnapshot) {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
|
|
||||||
match snapshot {
|
match snapshot {
|
||||||
ImfsSnapshot::File(file) => {
|
VfsSnapshot::File(file) => {
|
||||||
self.inner.insert(
|
self.inner.insert(
|
||||||
path.to_path_buf(),
|
path.to_path_buf(),
|
||||||
ImfsItem::File(ImfsFile {
|
VfsItem::File(VfsFile {
|
||||||
path: path.to_path_buf(),
|
path: path.to_path_buf(),
|
||||||
contents: Some(file.contents),
|
contents: Some(file.contents),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ImfsSnapshot::Directory(directory) => {
|
VfsSnapshot::Directory(directory) => {
|
||||||
self.inner.insert(
|
self.inner.insert(
|
||||||
path.to_path_buf(),
|
path.to_path_buf(),
|
||||||
ImfsItem::Directory(ImfsDirectory {
|
VfsItem::Directory(VfsDirectory {
|
||||||
path: path.to_path_buf(),
|
path: path.to_path_buf(),
|
||||||
children_enumerated: true,
|
children_enumerated: true,
|
||||||
}),
|
}),
|
||||||
@@ -297,21 +297,21 @@ impl<F: ImfsFetcher> ImfsDebug for Imfs<F> {
|
|||||||
|
|
||||||
fn debug_is_file(&self, path: &Path) -> bool {
|
fn debug_is_file(&self, path: &Path) -> bool {
|
||||||
match self.inner.get(path) {
|
match self.inner.get(path) {
|
||||||
Some(ImfsItem::File(_)) => true,
|
Some(VfsItem::File(_)) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]> {
|
fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]> {
|
||||||
match self.inner.get(path) {
|
match self.inner.get(path) {
|
||||||
Some(ImfsItem::File(file)) => file.contents.as_ref().map(|vec| vec.as_slice()),
|
Some(VfsItem::File(file)) => file.contents.as_ref().map(|vec| vec.as_slice()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)> {
|
fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)> {
|
||||||
match self.inner.get(path) {
|
match self.inner.get(path) {
|
||||||
Some(ImfsItem::Directory(dir)) => {
|
Some(VfsItem::Directory(dir)) => {
|
||||||
Some((dir.children_enumerated, self.inner.children(path).unwrap()))
|
Some((dir.children_enumerated, self.inner.children(path).unwrap()))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
@@ -327,31 +327,28 @@ impl<F: ImfsFetcher> ImfsDebug for Imfs<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A reference to file or folder in an `Imfs`. Can only be produced by the
|
/// A reference to file or folder in an `Vfs`. Can only be produced by the
|
||||||
/// entry existing in the Imfs, but can later point to nothing if something
|
/// entry existing in the Vfs, but can later point to nothing if something
|
||||||
/// would invalidate that path.
|
/// would invalidate that path.
|
||||||
///
|
///
|
||||||
/// This struct does not borrow from the Imfs since every operation has the
|
/// This struct does not borrow from the Vfs since every operation has the
|
||||||
/// possibility to mutate the underlying data structure and move memory around.
|
/// possibility to mutate the underlying data structure and move memory around.
|
||||||
pub struct ImfsEntry {
|
pub struct VfsEntry {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
is_file: bool,
|
is_file: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImfsEntry {
|
impl VfsEntry {
|
||||||
pub fn path(&self) -> &Path {
|
pub fn path(&self) -> &Path {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contents<'imfs>(
|
pub fn contents<'vfs>(&self, vfs: &'vfs mut Vfs<impl VfsFetcher>) -> FsResult<&'vfs [u8]> {
|
||||||
&self,
|
vfs.get_contents(&self.path)
|
||||||
imfs: &'imfs mut Imfs<impl ImfsFetcher>,
|
|
||||||
) -> FsResult<&'imfs [u8]> {
|
|
||||||
imfs.get_contents(&self.path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn children(&self, imfs: &mut Imfs<impl ImfsFetcher>) -> FsResult<Vec<ImfsEntry>> {
|
pub fn children(&self, vfs: &mut Vfs<impl VfsFetcher>) -> FsResult<Vec<VfsEntry>> {
|
||||||
imfs.get_children(&self.path)
|
vfs.get_children(&self.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_file(&self) -> bool {
|
pub fn is_file(&self) -> bool {
|
||||||
@@ -364,27 +361,27 @@ impl ImfsEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Internal structure describing potentially partially-resident files and
|
/// Internal structure describing potentially partially-resident files and
|
||||||
/// folders in the `Imfs`.
|
/// folders in the `Vfs`.
|
||||||
pub enum ImfsItem {
|
pub enum VfsItem {
|
||||||
File(ImfsFile),
|
File(VfsFile),
|
||||||
Directory(ImfsDirectory),
|
Directory(VfsDirectory),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImfsItem {
|
impl VfsItem {
|
||||||
fn path(&self) -> &Path {
|
fn path(&self) -> &Path {
|
||||||
match self {
|
match self {
|
||||||
ImfsItem::File(file) => &file.path,
|
VfsItem::File(file) => &file.path,
|
||||||
ImfsItem::Directory(dir) => &dir.path,
|
VfsItem::Directory(dir) => &dir.path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_from_type(kind: FileType, path: impl Into<PathBuf>) -> ImfsItem {
|
fn new_from_type(kind: FileType, path: impl Into<PathBuf>) -> VfsItem {
|
||||||
match kind {
|
match kind {
|
||||||
FileType::Directory => ImfsItem::Directory(ImfsDirectory {
|
FileType::Directory => VfsItem::Directory(VfsDirectory {
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
children_enumerated: false,
|
children_enumerated: false,
|
||||||
}),
|
}),
|
||||||
FileType::File => ImfsItem::File(ImfsFile {
|
FileType::File => VfsItem::File(VfsFile {
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
contents: None,
|
contents: None,
|
||||||
}),
|
}),
|
||||||
@@ -392,12 +389,12 @@ impl ImfsItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImfsFile {
|
pub struct VfsFile {
|
||||||
pub(super) path: PathBuf,
|
pub(super) path: PathBuf,
|
||||||
pub(super) contents: Option<Vec<u8>>,
|
pub(super) contents: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImfsDirectory {
|
pub struct VfsDirectory {
|
||||||
pub(super) path: PathBuf,
|
pub(super) path: PathBuf,
|
||||||
pub(super) children_enumerated: bool,
|
pub(super) children_enumerated: bool,
|
||||||
}
|
}
|
||||||
@@ -411,30 +408,30 @@ mod test {
|
|||||||
use crossbeam_channel::Receiver;
|
use crossbeam_channel::Receiver;
|
||||||
use maplit::hashmap;
|
use maplit::hashmap;
|
||||||
|
|
||||||
use super::super::{error::FsErrorKind, event::ImfsEvent, noop_fetcher::NoopFetcher};
|
use super::super::{error::FsErrorKind, event::VfsEvent, noop_fetcher::NoopFetcher};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_snapshot_file() {
|
fn from_snapshot_file() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let file = ImfsSnapshot::file("hello, world!");
|
let file = VfsSnapshot::file("hello, world!");
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/hello.txt", file);
|
vfs.debug_load_snapshot("/hello.txt", file);
|
||||||
|
|
||||||
let entry = imfs.get_contents("/hello.txt").unwrap();
|
let entry = vfs.get_contents("/hello.txt").unwrap();
|
||||||
assert_eq!(entry, b"hello, world!");
|
assert_eq!(entry, b"hello, world!");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_snapshot_dir() {
|
fn from_snapshot_dir() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
let dir = ImfsSnapshot::dir(hashmap! {
|
let dir = VfsSnapshot::dir(hashmap! {
|
||||||
"a.txt" => ImfsSnapshot::file("contents of a.txt"),
|
"a.txt" => VfsSnapshot::file("contents of a.txt"),
|
||||||
"b.lua" => ImfsSnapshot::file("contents of b.lua"),
|
"b.lua" => VfsSnapshot::file("contents of b.lua"),
|
||||||
});
|
});
|
||||||
|
|
||||||
imfs.debug_load_snapshot("/dir", dir);
|
vfs.debug_load_snapshot("/dir", dir);
|
||||||
|
|
||||||
let children = imfs.get_children("/dir").unwrap();
|
let children = vfs.get_children("/dir").unwrap();
|
||||||
|
|
||||||
let mut has_a = false;
|
let mut has_a = false;
|
||||||
let mut has_b = false;
|
let mut has_b = false;
|
||||||
@@ -452,10 +449,10 @@ mod test {
|
|||||||
assert!(has_a, "/dir/a.txt was missing");
|
assert!(has_a, "/dir/a.txt was missing");
|
||||||
assert!(has_b, "/dir/b.lua was missing");
|
assert!(has_b, "/dir/b.lua was missing");
|
||||||
|
|
||||||
let a = imfs.get_contents("/dir/a.txt").unwrap();
|
let a = vfs.get_contents("/dir/a.txt").unwrap();
|
||||||
assert_eq!(a, b"contents of a.txt");
|
assert_eq!(a, b"contents of a.txt");
|
||||||
|
|
||||||
let b = imfs.get_contents("/dir/b.lua").unwrap();
|
let b = vfs.get_contents("/dir/b.lua").unwrap();
|
||||||
assert_eq!(b, b"contents of b.lua");
|
assert_eq!(b, b"contents of b.lua");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,7 +467,7 @@ mod test {
|
|||||||
inner: Rc<RefCell<MockState>>,
|
inner: Rc<RefCell<MockState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImfsFetcher for MockFetcher {
|
impl VfsFetcher for MockFetcher {
|
||||||
fn file_type(&mut self, path: &Path) -> io::Result<FileType> {
|
fn file_type(&mut self, path: &Path) -> io::Result<FileType> {
|
||||||
if path == Path::new("/dir/a.txt") {
|
if path == Path::new("/dir/a.txt") {
|
||||||
return Ok(FileType::File);
|
return Ok(FileType::File);
|
||||||
@@ -509,7 +506,7 @@ mod test {
|
|||||||
|
|
||||||
fn unwatch(&mut self, _path: &Path) {}
|
fn unwatch(&mut self, _path: &Path) {}
|
||||||
|
|
||||||
fn receiver(&self) -> Receiver<ImfsEvent> {
|
fn receiver(&self) -> Receiver<VfsEvent> {
|
||||||
crossbeam_channel::never()
|
crossbeam_channel::never()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,13 +515,13 @@ mod test {
|
|||||||
a_contents: "Initial contents",
|
a_contents: "Initial contents",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut imfs = Imfs::new(MockFetcher {
|
let mut vfs = Vfs::new(MockFetcher {
|
||||||
inner: mock_state.clone(),
|
inner: mock_state.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let a = imfs.get("/dir/a.txt").expect("mock file did not exist");
|
let a = vfs.get("/dir/a.txt").expect("mock file did not exist");
|
||||||
|
|
||||||
let contents = a.contents(&mut imfs).expect("mock file contents error");
|
let contents = a.contents(&mut vfs).expect("mock file contents error");
|
||||||
|
|
||||||
assert_eq!(contents, b"Initial contents");
|
assert_eq!(contents, b"Initial contents");
|
||||||
|
|
||||||
@@ -533,36 +530,36 @@ mod test {
|
|||||||
mock_state.a_contents = "Changed contents";
|
mock_state.a_contents = "Changed contents";
|
||||||
}
|
}
|
||||||
|
|
||||||
imfs.raise_file_changed("/dir/a.txt")
|
vfs.raise_file_changed("/dir/a.txt")
|
||||||
.expect("error processing file change");
|
.expect("error processing file change");
|
||||||
|
|
||||||
let contents = a.contents(&mut imfs).expect("mock file contents error");
|
let contents = a.contents(&mut vfs).expect("mock file contents error");
|
||||||
|
|
||||||
assert_eq!(contents, b"Changed contents");
|
assert_eq!(contents, b"Changed contents");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn removed_event_existing() {
|
fn removed_event_existing() {
|
||||||
let mut imfs = Imfs::new(NoopFetcher);
|
let mut vfs = Vfs::new(NoopFetcher);
|
||||||
|
|
||||||
let file = ImfsSnapshot::file("hello, world!");
|
let file = VfsSnapshot::file("hello, world!");
|
||||||
imfs.debug_load_snapshot("/hello.txt", file);
|
vfs.debug_load_snapshot("/hello.txt", file);
|
||||||
|
|
||||||
let hello = imfs.get("/hello.txt").expect("couldn't get hello.txt");
|
let hello = vfs.get("/hello.txt").expect("couldn't get hello.txt");
|
||||||
|
|
||||||
let contents = hello
|
let contents = hello
|
||||||
.contents(&mut imfs)
|
.contents(&mut vfs)
|
||||||
.expect("couldn't get hello.txt contents");
|
.expect("couldn't get hello.txt contents");
|
||||||
|
|
||||||
assert_eq!(contents, b"hello, world!");
|
assert_eq!(contents, b"hello, world!");
|
||||||
|
|
||||||
imfs.raise_file_removed("/hello.txt")
|
vfs.raise_file_removed("/hello.txt")
|
||||||
.expect("error processing file removal");
|
.expect("error processing file removal");
|
||||||
|
|
||||||
match imfs.get("hello.txt") {
|
match vfs.get("hello.txt") {
|
||||||
Err(ref err) if err.kind() == FsErrorKind::NotFound => {}
|
Err(ref err) if err.kind() == FsErrorKind::NotFound => {}
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
panic!("hello.txt was not removed from Imfs");
|
panic!("hello.txt was not removed from Vfs");
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
panic!("Unexpected error: {:?}", err);
|
panic!("Unexpected error: {:?}", err);
|
||||||
@@ -9,8 +9,8 @@ use hyper::{service::Service, Body, Method, Request, StatusCode};
|
|||||||
use rbx_dom_weak::RbxId;
|
use rbx_dom_weak::RbxId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::ImfsFetcher,
|
|
||||||
serve_session::ServeSession,
|
serve_session::ServeSession,
|
||||||
|
vfs::VfsFetcher,
|
||||||
web::{
|
web::{
|
||||||
interface::{
|
interface::{
|
||||||
ErrorResponse, Instance, InstanceMetadata as WebInstanceMetadata, InstanceUpdate,
|
ErrorResponse, Instance, InstanceMetadata as WebInstanceMetadata, InstanceUpdate,
|
||||||
@@ -25,7 +25,7 @@ pub struct ApiService<F> {
|
|||||||
serve_session: Arc<ServeSession<F>>,
|
serve_session: Arc<ServeSession<F>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher> Service for ApiService<F> {
|
impl<F: VfsFetcher> Service for ApiService<F> {
|
||||||
type ReqBody = Body;
|
type ReqBody = Body;
|
||||||
type ResBody = Body;
|
type ResBody = Body;
|
||||||
type Error = hyper::Error;
|
type Error = hyper::Error;
|
||||||
@@ -49,7 +49,7 @@ impl<F: ImfsFetcher> Service for ApiService<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher> ApiService<F> {
|
impl<F: VfsFetcher> ApiService<F> {
|
||||||
pub fn new(serve_session: Arc<ServeSession<F>>) -> Self {
|
pub fn new(serve_session: Arc<ServeSession<F>>) -> Self {
|
||||||
ApiService { serve_session }
|
ApiService { serve_session }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use futures::{
|
|||||||
use hyper::{service::Service, Body, Request, Response, Server};
|
use hyper::{service::Service, Body, Request, Response, Server};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use crate::{imfs::ImfsFetcher, serve_session::ServeSession};
|
use crate::{serve_session::ServeSession, vfs::VfsFetcher};
|
||||||
|
|
||||||
use self::{api::ApiService, ui::UiService};
|
use self::{api::ApiService, ui::UiService};
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ pub struct RootService<F> {
|
|||||||
ui: UiService<F>,
|
ui: UiService<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher> Service for RootService<F> {
|
impl<F: VfsFetcher> Service for RootService<F> {
|
||||||
type ReqBody = Body;
|
type ReqBody = Body;
|
||||||
type ResBody = Body;
|
type ResBody = Body;
|
||||||
type Error = hyper::Error;
|
type Error = hyper::Error;
|
||||||
@@ -39,7 +39,7 @@ impl<F: ImfsFetcher> Service for RootService<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher> RootService<F> {
|
impl<F: VfsFetcher> RootService<F> {
|
||||||
pub fn new(serve_session: Arc<ServeSession<F>>) -> Self {
|
pub fn new(serve_session: Arc<ServeSession<F>>) -> Self {
|
||||||
RootService {
|
RootService {
|
||||||
api: ApiService::new(Arc::clone(&serve_session)),
|
api: ApiService::new(Arc::clone(&serve_session)),
|
||||||
@@ -52,7 +52,7 @@ pub struct LiveServer<F> {
|
|||||||
serve_session: Arc<ServeSession<F>>,
|
serve_session: Arc<ServeSession<F>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher + Send + Sync + 'static> LiveServer<F> {
|
impl<F: VfsFetcher + Send + Sync + 'static> LiveServer<F> {
|
||||||
pub fn new(serve_session: Arc<ServeSession<F>>) -> Self {
|
pub fn new(serve_session: Arc<ServeSession<F>>) -> Self {
|
||||||
LiveServer { serve_session }
|
LiveServer { serve_session }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ use rbx_dom_weak::{RbxId, RbxValue};
|
|||||||
use ritz::{html, Fragment, HtmlContent, HtmlSelfClosingTag};
|
use ritz::{html, Fragment, HtmlContent, HtmlSelfClosingTag};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, ImfsDebug, ImfsFetcher},
|
|
||||||
serve_session::ServeSession,
|
serve_session::ServeSession,
|
||||||
snapshot::RojoTree,
|
snapshot::RojoTree,
|
||||||
|
vfs::{Vfs, VfsDebug, VfsFetcher},
|
||||||
web::{
|
web::{
|
||||||
assets,
|
assets,
|
||||||
interface::{ErrorResponse, SERVER_VERSION},
|
interface::{ErrorResponse, SERVER_VERSION},
|
||||||
@@ -23,7 +23,7 @@ pub struct UiService<F> {
|
|||||||
serve_session: Arc<ServeSession<F>>,
|
serve_session: Arc<ServeSession<F>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher> Service for UiService<F> {
|
impl<F: VfsFetcher> Service for UiService<F> {
|
||||||
type ReqBody = Body;
|
type ReqBody = Body;
|
||||||
type ResBody = Body;
|
type ResBody = Body;
|
||||||
type Error = hyper::Error;
|
type Error = hyper::Error;
|
||||||
@@ -35,7 +35,7 @@ impl<F: ImfsFetcher> Service for UiService<F> {
|
|||||||
(&Method::GET, "/logo.png") => self.handle_logo(),
|
(&Method::GET, "/logo.png") => self.handle_logo(),
|
||||||
(&Method::GET, "/icon.png") => self.handle_icon(),
|
(&Method::GET, "/icon.png") => self.handle_icon(),
|
||||||
(&Method::GET, "/show-instances") => self.handle_show_instances(),
|
(&Method::GET, "/show-instances") => self.handle_show_instances(),
|
||||||
(&Method::GET, "/show-imfs") => self.handle_show_imfs(),
|
(&Method::GET, "/show-vfs") => self.handle_show_vfs(),
|
||||||
(_method, path) => {
|
(_method, path) => {
|
||||||
return json(
|
return json(
|
||||||
ErrorResponse::not_found(format!("Route not found: {}", path)),
|
ErrorResponse::not_found(format!("Route not found: {}", path)),
|
||||||
@@ -48,7 +48,7 @@ impl<F: ImfsFetcher> Service for UiService<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: ImfsFetcher> UiService<F> {
|
impl<F: VfsFetcher> UiService<F> {
|
||||||
pub fn new(serve_session: Arc<ServeSession<F>>) -> Self {
|
pub fn new(serve_session: Arc<ServeSession<F>>) -> Self {
|
||||||
UiService { serve_session }
|
UiService { serve_session }
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ impl<F: ImfsFetcher> UiService<F> {
|
|||||||
let page = self.normal_page(html! {
|
let page = self.normal_page(html! {
|
||||||
<div class="button-list">
|
<div class="button-list">
|
||||||
{ Self::button("Rojo Documentation", "https://rojo.space/docs") }
|
{ Self::button("Rojo Documentation", "https://rojo.space/docs") }
|
||||||
{ Self::button("View in-memory filesystem state", "/show-imfs") }
|
{ Self::button("View in-memory filesystem state", "/show-vfs") }
|
||||||
{ Self::button("View instance tree state", "/show-instances") }
|
{ Self::button("View instance tree state", "/show-instances") }
|
||||||
</div>
|
</div>
|
||||||
});
|
});
|
||||||
@@ -96,16 +96,16 @@ impl<F: ImfsFetcher> UiService<F> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_show_imfs(&self) -> Response<Body> {
|
fn handle_show_vfs(&self) -> Response<Body> {
|
||||||
let imfs = self.serve_session.imfs();
|
let vfs = self.serve_session.vfs();
|
||||||
|
|
||||||
let orphans: Vec<_> = imfs
|
let orphans: Vec<_> = vfs
|
||||||
.debug_orphans()
|
.debug_orphans()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|path| Self::render_imfs_path(&imfs, path, true))
|
.map(|path| Self::render_vfs_path(&vfs, path, true))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let watched_list: Vec<_> = imfs
|
let watched_list: Vec<_> = vfs
|
||||||
.debug_watched_paths()
|
.debug_watched_paths()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|path| {
|
.map(|path| {
|
||||||
@@ -135,25 +135,25 @@ impl<F: ImfsFetcher> UiService<F> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_imfs_path(imfs: &Imfs<F>, path: &Path, is_root: bool) -> HtmlContent<'static> {
|
fn render_vfs_path(vfs: &Vfs<F>, path: &Path, is_root: bool) -> HtmlContent<'static> {
|
||||||
let is_file = imfs.debug_is_file(path);
|
let is_file = vfs.debug_is_file(path);
|
||||||
|
|
||||||
let (note, children) = if is_file {
|
let (note, children) = if is_file {
|
||||||
(HtmlContent::None, Vec::new())
|
(HtmlContent::None, Vec::new())
|
||||||
} else {
|
} else {
|
||||||
let (is_exhaustive, mut children) = imfs.debug_children(path).unwrap();
|
let (is_exhaustive, mut children) = vfs.debug_children(path).unwrap();
|
||||||
|
|
||||||
// Sort files above directories, then sort how Path does after that.
|
// Sort files above directories, then sort how Path does after that.
|
||||||
children.sort_unstable_by(|a, b| {
|
children.sort_unstable_by(|a, b| {
|
||||||
let a_is_file = imfs.debug_is_file(a);
|
let a_is_file = vfs.debug_is_file(a);
|
||||||
let b_is_file = imfs.debug_is_file(b);
|
let b_is_file = vfs.debug_is_file(b);
|
||||||
|
|
||||||
b_is_file.cmp(&a_is_file).then_with(|| a.cmp(b))
|
b_is_file.cmp(&a_is_file).then_with(|| a.cmp(b))
|
||||||
});
|
});
|
||||||
|
|
||||||
let children: Vec<_> = children
|
let children: Vec<_> = children
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|child| Self::render_imfs_path(imfs, child, false))
|
.map(|child| Self::render_vfs_path(vfs, child, false))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let note = if is_exhaustive {
|
let note = if is_exhaustive {
|
||||||
@@ -178,12 +178,12 @@ impl<F: ImfsFetcher> UiService<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
html! {
|
html! {
|
||||||
<div class="imfs-entry">
|
<div class="vfs-entry">
|
||||||
<div>
|
<div>
|
||||||
<span class="imfs-entry-name">{ name }</span>
|
<span class="vfs-entry-name">{ name }</span>
|
||||||
<span class="imfs-entry-note">{ note }</span>
|
<span class="vfs-entry-note">{ note }</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="imfs-entry-children">
|
<div class="vfs-entry-children">
|
||||||
{ Fragment::new(children) }
|
{ Fragment::new(children) }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user