2023-12-22 15:20:24 +03:00
|
|
|
use anyhow::Result;
|
2023-04-14 13:25:07 +03:00
|
|
|
|
2023-12-22 14:27:32 +03:00
|
|
|
use crate::lock;
|
|
|
|
|
|
|
|
pub struct DirWriter(lock::Dir);
|
2023-04-12 15:14:39 +03:00
|
|
|
|
2023-05-31 10:29:26 +03:00
|
|
|
impl DirWriter {
|
2023-12-22 14:27:32 +03:00
|
|
|
pub fn open<P: AsRef<std::path::Path>>(root: P) -> Result<Self, std::io::Error> {
|
|
|
|
lock::Dir::new(root).map(Self)
|
2023-04-13 14:37:46 +03:00
|
|
|
}
|
2023-04-12 15:14:39 +03:00
|
|
|
}
|
|
|
|
|
2023-12-20 17:08:24 +03:00
|
|
|
impl DirWriter {
|
2023-12-22 15:20:24 +03:00
|
|
|
fn write<P, C>(&self, path: P, contents: C) -> Result<(), std::io::Error>
|
|
|
|
where
|
|
|
|
P: AsRef<std::path::Path>,
|
|
|
|
C: AsRef<[u8]>,
|
|
|
|
{
|
|
|
|
self.batch(&[BatchTask::Write(path, contents)])
|
2023-04-12 15:14:39 +03:00
|
|
|
}
|
|
|
|
|
2023-12-22 15:20:24 +03:00
|
|
|
pub fn remove<P: AsRef<std::path::Path>>(&self, path: P) -> Result<(), std::io::Error> {
|
2023-12-22 14:27:32 +03:00
|
|
|
self.0.batch(|root| {
|
2023-12-22 15:20:24 +03:00
|
|
|
let path = root.join(path);
|
|
|
|
if path.exists() {
|
|
|
|
if path.is_dir() {
|
|
|
|
std::fs::remove_dir_all(path)
|
|
|
|
} else {
|
|
|
|
std::fs::remove_file(path)
|
2023-12-22 14:27:32 +03:00
|
|
|
}
|
|
|
|
} else {
|
2023-12-22 15:20:24 +03:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
})?
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn batch<P, C>(&self, values: &[BatchTask<P, C>]) -> Result<(), std::io::Error>
|
|
|
|
where
|
|
|
|
P: AsRef<std::path::Path>,
|
|
|
|
C: AsRef<[u8]>,
|
|
|
|
{
|
|
|
|
self.0.batch(|root| {
|
|
|
|
for value in values {
|
|
|
|
match value {
|
|
|
|
BatchTask::Write(path, contents) => {
|
|
|
|
let path = root.join(path);
|
|
|
|
if let Some(dir_path) = path.parent() {
|
|
|
|
if !dir_path.exists() {
|
|
|
|
std::fs::create_dir_all(dir_path)?;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
std::fs::write(path, contents)?;
|
|
|
|
}
|
|
|
|
BatchTask::Remove(path) => {
|
|
|
|
let path = root.join(path);
|
|
|
|
if path.exists() {
|
|
|
|
if path.is_dir() {
|
|
|
|
std::fs::remove_dir_all(path)?;
|
|
|
|
} else {
|
|
|
|
std::fs::remove_file(path)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-12-22 14:27:32 +03:00
|
|
|
}
|
2023-07-01 11:30:00 +03:00
|
|
|
}
|
2023-12-22 15:20:24 +03:00
|
|
|
Ok(())
|
2023-12-22 14:27:32 +03:00
|
|
|
})?
|
2023-06-07 13:43:07 +03:00
|
|
|
}
|
2023-12-20 17:08:24 +03:00
|
|
|
|
2023-12-22 15:20:24 +03:00
|
|
|
pub fn write_usize(&self, path: &str, contents: &usize) -> Result<(), std::io::Error> {
|
2023-12-20 17:08:24 +03:00
|
|
|
self.write_string(path, &contents.to_string())
|
|
|
|
}
|
|
|
|
|
2023-12-22 15:20:24 +03:00
|
|
|
pub fn write_u128(&self, path: &str, contents: &u128) -> Result<(), std::io::Error> {
|
2023-12-20 17:08:24 +03:00
|
|
|
self.write_string(path, &contents.to_string())
|
|
|
|
}
|
|
|
|
|
2023-12-22 15:20:24 +03:00
|
|
|
pub fn write_bool(&self, path: &str, contents: &bool) -> Result<(), std::io::Error> {
|
2023-12-20 17:08:24 +03:00
|
|
|
self.write_string(path, &contents.to_string())
|
|
|
|
}
|
|
|
|
|
2023-12-22 15:20:24 +03:00
|
|
|
pub fn write_string(&self, path: &str, contents: &str) -> Result<(), std::io::Error> {
|
|
|
|
self.write(path, contents)
|
2023-12-20 17:08:24 +03:00
|
|
|
}
|
2023-04-12 15:14:39 +03:00
|
|
|
}
|
2023-06-05 17:12:25 +03:00
|
|
|
|
2023-12-22 15:20:24 +03:00
|
|
|
pub enum BatchTask<P: AsRef<std::path::Path>, C: AsRef<[u8]>> {
|
|
|
|
Write(P, C),
|
|
|
|
Remove(P),
|
|
|
|
}
|
|
|
|
|
2023-06-05 17:12:25 +03:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_write() {
|
|
|
|
let root = tempfile::tempdir().unwrap();
|
2023-12-22 14:27:32 +03:00
|
|
|
let writer = DirWriter::open(root.path()).unwrap();
|
2023-06-05 17:12:25 +03:00
|
|
|
writer.write("foo/bar", b"baz").unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
std::fs::read_to_string(root.path().join("foo/bar")).unwrap(),
|
|
|
|
"baz"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-07 13:43:07 +03:00
|
|
|
#[test]
|
|
|
|
fn test_remove() {
|
|
|
|
let root = tempfile::tempdir().unwrap();
|
2023-12-22 14:27:32 +03:00
|
|
|
let writer = DirWriter::open(root.path()).unwrap();
|
2023-06-07 13:43:07 +03:00
|
|
|
writer.remove("foo/bar").unwrap();
|
|
|
|
assert!(!root.path().join("foo/bar").exists());
|
|
|
|
writer.write("foo/bar", b"baz").unwrap();
|
|
|
|
writer.remove("foo/bar").unwrap();
|
|
|
|
assert!(!root.path().join("foo/bar").exists());
|
2023-07-01 11:30:00 +03:00
|
|
|
writer.write("parent/child", b"baz").unwrap();
|
|
|
|
writer.remove("parent").unwrap();
|
|
|
|
assert!(!root.path().join("parent").exists());
|
2023-06-07 13:43:07 +03:00
|
|
|
}
|
2023-06-05 17:12:25 +03:00
|
|
|
}
|