forked from rojo-rbx/rojo
Rework Imfs and expand tests a bit
This commit is contained in:
@@ -64,23 +64,14 @@ impl Imfs {
|
||||
|
||||
self.roots.insert(path.to_path_buf());
|
||||
|
||||
ImfsItem::read_from_disk(self, path)?;
|
||||
Ok(())
|
||||
self.read_from_disk(path)
|
||||
}
|
||||
|
||||
pub fn path_created(&mut self, path: &Path) -> io::Result<()> {
|
||||
debug_assert!(path.is_absolute());
|
||||
debug_assert!(self.is_within_roots(path));
|
||||
|
||||
if let Some(parent_path) = path.parent() {
|
||||
if self.is_within_roots(parent_path) && self.get(parent_path).is_none() {
|
||||
self.path_created(parent_path)?;
|
||||
}
|
||||
} else {
|
||||
ImfsItem::read_from_disk(self, path)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
self.read_from_disk(path)
|
||||
}
|
||||
|
||||
pub fn path_updated(&mut self, path: &Path) -> io::Result<()> {
|
||||
@@ -92,7 +83,7 @@ impl Imfs {
|
||||
self.path_created(parent_path)?;
|
||||
}
|
||||
} else {
|
||||
ImfsItem::read_from_disk(self, path)?;
|
||||
self.read_from_disk(path)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -103,11 +94,7 @@ impl Imfs {
|
||||
debug_assert!(self.is_within_roots(path));
|
||||
|
||||
if let Some(parent_path) = path.parent() {
|
||||
if self.is_within_roots(parent_path) {
|
||||
if let Some(ImfsItem::Directory(parent)) = self.items.get_mut(parent_path) {
|
||||
parent.children.remove(path);
|
||||
}
|
||||
}
|
||||
self.unlink_child(parent_path, path);
|
||||
}
|
||||
|
||||
if let Some(ImfsItem::Directory(directory)) = self.items.remove(path) {
|
||||
@@ -130,37 +117,35 @@ impl Imfs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_within_roots(&self, path: &Path) -> bool {
|
||||
for root_path in &self.roots {
|
||||
if path.starts_with(root_path) {
|
||||
return true;
|
||||
fn unlink_child(&mut self, parent: &Path, child: &Path) {
|
||||
let parent_item = self.items.get_mut(parent);
|
||||
|
||||
match parent_item {
|
||||
Some(ImfsItem::Directory(directory)) => {
|
||||
directory.children.remove(child);
|
||||
},
|
||||
_ => {
|
||||
panic!("Tried to unlink child of path that wasn't a directory!");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn link_child(&mut self, parent: &Path, child: &Path) {
|
||||
if self.is_within_roots(parent) {
|
||||
let parent_item = self.items.get_mut(parent);
|
||||
|
||||
match parent_item {
|
||||
Some(ImfsItem::Directory(directory)) => {
|
||||
directory.children.insert(child.to_path_buf());
|
||||
},
|
||||
_ => {
|
||||
panic!("Tried to link child of path that wasn't a directory!");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ImfsFile {
|
||||
pub path: PathBuf,
|
||||
pub contents: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ImfsDirectory {
|
||||
pub path: PathBuf,
|
||||
pub children: HashSet<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ImfsItem {
|
||||
File(ImfsFile),
|
||||
Directory(ImfsDirectory),
|
||||
}
|
||||
|
||||
impl ImfsItem {
|
||||
fn read_from_disk<'a, 'b>(vfs: &'a mut Imfs, path: &'b Path) -> io::Result<&'a ImfsItem> {
|
||||
fn read_from_disk(&mut self, path: &Path) -> io::Result<()> {
|
||||
let metadata = fs::metadata(path)?;
|
||||
|
||||
if metadata.is_file() {
|
||||
@@ -170,31 +155,80 @@ impl ImfsItem {
|
||||
contents,
|
||||
});
|
||||
|
||||
vfs.items.insert(path.to_path_buf(), item);
|
||||
self.items.insert(path.to_path_buf(), item);
|
||||
|
||||
Ok(&vfs.items[path])
|
||||
if let Some(parent_path) = path.parent() {
|
||||
self.link_child(parent_path, path);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else if metadata.is_dir() {
|
||||
let mut children = HashSet::new();
|
||||
let item = ImfsItem::Directory(ImfsDirectory {
|
||||
path: path.to_path_buf(),
|
||||
children: HashSet::new(),
|
||||
});
|
||||
|
||||
self.items.insert(path.to_path_buf(), item);
|
||||
|
||||
for entry in fs::read_dir(path)? {
|
||||
let entry = entry?;
|
||||
let child_path = entry.path();
|
||||
|
||||
ImfsItem::read_from_disk(vfs, &child_path)?;
|
||||
|
||||
children.insert(child_path);
|
||||
self.read_from_disk(&child_path)?;
|
||||
}
|
||||
|
||||
let item = ImfsItem::Directory(ImfsDirectory {
|
||||
path: path.to_path_buf(),
|
||||
children,
|
||||
});
|
||||
if let Some(parent_path) = path.parent() {
|
||||
self.link_child(parent_path, path);
|
||||
}
|
||||
|
||||
vfs.items.insert(path.to_path_buf(), item);
|
||||
|
||||
Ok(&vfs.items[path])
|
||||
Ok(())
|
||||
} else {
|
||||
panic!("Unexpected non-file, non-directory item");
|
||||
}
|
||||
}
|
||||
|
||||
fn is_within_roots(&self, path: &Path) -> bool {
|
||||
let kind = self.classify_path(path);
|
||||
|
||||
kind == PathKind::Root || kind == PathKind::InRoot
|
||||
}
|
||||
|
||||
fn classify_path(&self, path: &Path) -> PathKind {
|
||||
for root_path in &self.roots {
|
||||
if root_path == path {
|
||||
return PathKind::Root;
|
||||
}
|
||||
|
||||
if path.starts_with(root_path) {
|
||||
return PathKind::InRoot;
|
||||
}
|
||||
}
|
||||
|
||||
PathKind::NotInRoot
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
enum PathKind {
|
||||
Root,
|
||||
InRoot,
|
||||
NotInRoot,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ImfsFile {
|
||||
pub path: PathBuf,
|
||||
pub contents: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ImfsDirectory {
|
||||
pub path: PathBuf,
|
||||
pub children: HashSet<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ImfsItem {
|
||||
File(ImfsFile),
|
||||
Directory(ImfsDirectory),
|
||||
}
|
||||
@@ -5,7 +5,7 @@ use std::{
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use tempfile::tempdir;
|
||||
use tempfile::{TempDir, tempdir};
|
||||
|
||||
use librojo::{
|
||||
imfs::{Imfs, ImfsItem, ImfsFile, ImfsDirectory},
|
||||
@@ -16,18 +16,30 @@ struct ExpectedImfs {
|
||||
items: HashMap<PathBuf, ImfsItem>,
|
||||
}
|
||||
|
||||
struct TestResources {
|
||||
foo_path: PathBuf,
|
||||
bar_path: PathBuf,
|
||||
baz_path: PathBuf,
|
||||
}
|
||||
|
||||
fn check_expected(real: &Imfs, expected: &ExpectedImfs) {
|
||||
assert_eq!(real.get_roots(), &expected.roots);
|
||||
assert_eq!(real.get_items(), &expected.items);
|
||||
}
|
||||
|
||||
fn base_tree() -> io::Result<(Imfs, ExpectedImfs)> {
|
||||
fn base_tree() -> io::Result<(TempDir, Imfs, ExpectedImfs, TestResources)> {
|
||||
let root = tempdir()?;
|
||||
|
||||
let foo_path = root.path().join("foo");
|
||||
let bar_path = root.path().join("bar.txt");
|
||||
let baz_path = foo_path.join("baz.txt");
|
||||
|
||||
let resources = TestResources {
|
||||
foo_path: foo_path.clone(),
|
||||
bar_path: bar_path.clone(),
|
||||
baz_path: baz_path.clone(),
|
||||
};
|
||||
|
||||
fs::create_dir(&foo_path)?;
|
||||
fs::write(&bar_path, b"bar")?;
|
||||
fs::write(&baz_path, b"baz")?;
|
||||
@@ -80,12 +92,60 @@ fn base_tree() -> io::Result<(Imfs, ExpectedImfs)> {
|
||||
items: expected_items,
|
||||
};
|
||||
|
||||
Ok((imfs, expected_imfs))
|
||||
Ok((root, imfs, expected_imfs, resources))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn initial_read() -> io::Result<()> {
|
||||
let (imfs, expected_imfs) = base_tree()?;
|
||||
let (root, imfs, expected_imfs, _) = base_tree()?;
|
||||
|
||||
check_expected(&imfs, &expected_imfs);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn adding_files() -> io::Result<()> {
|
||||
let (root, mut imfs, mut expected_imfs, resources) = base_tree()?;
|
||||
|
||||
check_expected(&imfs, &expected_imfs);
|
||||
|
||||
let add_one_path = root.path().join("add_one.txt");
|
||||
let add_two_path = resources.foo_path.join("add_two.txt");
|
||||
|
||||
fs::write(&add_one_path, b"add_one")?;
|
||||
fs::write(&add_two_path, b"add_two")?;
|
||||
|
||||
imfs.path_created(&add_one_path)?;
|
||||
imfs.path_created(&add_two_path)?;
|
||||
|
||||
match expected_imfs.items.get_mut(root.path()) {
|
||||
Some(ImfsItem::Directory(directory)) => {
|
||||
directory.children.insert(add_one_path.clone());
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
match expected_imfs.items.get_mut(&resources.foo_path) {
|
||||
Some(ImfsItem::Directory(directory)) => {
|
||||
directory.children.insert(add_two_path.clone());
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
expected_imfs.items.insert(add_one_path.clone(), ImfsItem::File(ImfsFile {
|
||||
path: add_one_path.clone(),
|
||||
contents: b"add_one".to_vec(),
|
||||
}));
|
||||
|
||||
expected_imfs.items.insert(add_two_path.clone(), ImfsItem::File(ImfsFile {
|
||||
path: add_two_path.clone(),
|
||||
contents: b"add_two".to_vec(),
|
||||
}));
|
||||
|
||||
println!("{}", serde_json::to_string(imfs.get_items()).unwrap());
|
||||
println!("---------------------------------------------------------------");
|
||||
println!("{}", serde_json::to_string(&expected_imfs.items).unwrap());
|
||||
|
||||
check_expected(&imfs, &expected_imfs);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user