forked from rojo-rbx/rojo
129 lines
3.5 KiB
Rust
129 lines
3.5 KiB
Rust
use std::path::Path;
|
|
|
|
use memofs::{DirEntry, IoResultExt, Vfs};
|
|
|
|
use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot};
|
|
|
|
use super::{
|
|
error::SnapshotError,
|
|
meta_file::DirectoryMetadata,
|
|
middleware::{SnapshotInstanceResult, SnapshotMiddleware},
|
|
snapshot_from_vfs,
|
|
};
|
|
|
|
pub struct SnapshotDir;
|
|
|
|
impl SnapshotMiddleware for SnapshotDir {
|
|
fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult {
|
|
let meta = vfs.metadata(path)?;
|
|
|
|
if meta.is_file() {
|
|
return Ok(None);
|
|
}
|
|
|
|
let passes_filter_rules = |child: &DirEntry| {
|
|
context
|
|
.path_ignore_rules
|
|
.iter()
|
|
.all(|rule| rule.passes(child.path()))
|
|
};
|
|
|
|
let mut snapshot_children = Vec::new();
|
|
|
|
for entry in vfs.read_dir(path)? {
|
|
let entry = entry?;
|
|
|
|
if !passes_filter_rules(&entry) {
|
|
continue;
|
|
}
|
|
|
|
if let Some(child_snapshot) = snapshot_from_vfs(context, vfs, entry.path())? {
|
|
snapshot_children.push(child_snapshot);
|
|
}
|
|
}
|
|
|
|
let instance_name = path
|
|
.file_name()
|
|
.expect("Could not extract file name")
|
|
.to_str()
|
|
.ok_or_else(|| SnapshotError::file_name_bad_unicode(path))?
|
|
.to_string();
|
|
|
|
let meta_path = path.join("init.meta.json");
|
|
|
|
let relevant_paths = vec![
|
|
path.to_path_buf(),
|
|
meta_path.clone(),
|
|
// TODO: We shouldn't need to know about Lua existing in this
|
|
// middleware. Should we figure out a way for that function to add
|
|
// relevant paths to this middleware?
|
|
path.join("init.lua"),
|
|
path.join("init.server.lua"),
|
|
path.join("init.client.lua"),
|
|
];
|
|
|
|
let mut snapshot = InstanceSnapshot::new()
|
|
.name(instance_name)
|
|
.class_name("Folder")
|
|
.children(snapshot_children)
|
|
.metadata(
|
|
InstanceMetadata::new()
|
|
.instigating_source(path)
|
|
.relevant_paths(relevant_paths)
|
|
.context(context),
|
|
);
|
|
|
|
if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? {
|
|
let mut metadata = DirectoryMetadata::from_slice(&meta_contents, &meta_path)?;
|
|
metadata.apply_all(&mut snapshot);
|
|
}
|
|
|
|
Ok(Some(snapshot))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
use maplit::hashmap;
|
|
use memofs::{InMemoryFs, VfsSnapshot};
|
|
|
|
#[test]
|
|
fn empty_folder() {
|
|
let mut imfs = InMemoryFs::new();
|
|
imfs.load_snapshot("/foo", VfsSnapshot::empty_dir())
|
|
.unwrap();
|
|
|
|
let mut vfs = Vfs::new(imfs);
|
|
|
|
let instance_snapshot =
|
|
SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo"))
|
|
.unwrap()
|
|
.unwrap();
|
|
|
|
insta::assert_yaml_snapshot!(instance_snapshot);
|
|
}
|
|
|
|
#[test]
|
|
fn folder_in_folder() {
|
|
let mut imfs = InMemoryFs::new();
|
|
imfs.load_snapshot(
|
|
"/foo",
|
|
VfsSnapshot::dir(hashmap! {
|
|
"Child" => VfsSnapshot::empty_dir(),
|
|
}),
|
|
)
|
|
.unwrap();
|
|
|
|
let mut vfs = Vfs::new(imfs);
|
|
|
|
let instance_snapshot =
|
|
SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo"))
|
|
.unwrap()
|
|
.unwrap();
|
|
|
|
insta::assert_yaml_snapshot!(instance_snapshot);
|
|
}
|
|
}
|