Compare commits
2 commits
a629950d4d
...
b101089ebd
Author | SHA1 | Date | |
---|---|---|---|
b101089ebd | |||
b756881a60 |
5 changed files with 26 additions and 203 deletions
|
@ -1,167 +0,0 @@
|
||||||
#![allow(deprecated)]
|
|
||||||
|
|
||||||
use std::{
|
|
||||||
ops::Deref,
|
|
||||||
path::PathBuf,
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
};
|
|
||||||
|
|
||||||
use tempfile::{tempdir, TempDir};
|
|
||||||
use tracing::{debug, info};
|
|
||||||
|
|
||||||
pub fn real(cwd: Option<PathBuf>) -> FileSystem {
|
|
||||||
let cwd = cwd.unwrap_or_default();
|
|
||||||
FileSystem::Real(RealFileSystem::new(cwd))
|
|
||||||
}
|
|
||||||
pub fn temp() -> std::io::Result<FileSystem> {
|
|
||||||
TempFileSystem::new().map(FileSystem::Temp)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
#[deprecated(since = "1.1.0", note = "Use [kxio::fs::FileSystem] instead")]
|
|
||||||
pub enum FileSystem {
|
|
||||||
Real(RealFileSystem),
|
|
||||||
Temp(TempFileSystem),
|
|
||||||
}
|
|
||||||
impl FileSystem {
|
|
||||||
#[deprecated(since = "1.1.0", note = "Use [kxio::filesystem::real()] instead")]
|
|
||||||
pub fn new_real(cwd: Option<PathBuf>) -> Self {
|
|
||||||
real(cwd)
|
|
||||||
}
|
|
||||||
#[deprecated(since = "1.1.0", note = "Use [kxio::filesystem::temp()] instead")]
|
|
||||||
pub fn new_temp() -> std::io::Result<Self> {
|
|
||||||
temp()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Deref for FileSystem {
|
|
||||||
type Target = dyn FileSystemLike;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
match self {
|
|
||||||
Self::Real(env) => env,
|
|
||||||
Self::Temp(env) => env,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait FileSystemLike: Sync + Send + std::fmt::Debug {
|
|
||||||
fn cwd(&self) -> &PathBuf;
|
|
||||||
|
|
||||||
fn in_cwd(&self, name: &str) -> PathBuf {
|
|
||||||
self.cwd().join(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_file(&self, file_name: &str, content: &str) -> std::io::Result<PathBuf> {
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::{LineWriter, Write};
|
|
||||||
|
|
||||||
let path = self.in_cwd(file_name);
|
|
||||||
debug!("writing to {:?}", path);
|
|
||||||
let file = File::create(path.clone())?;
|
|
||||||
let mut file = LineWriter::new(file);
|
|
||||||
file.write_all(content.as_bytes())?;
|
|
||||||
Ok(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn file_exists(&self, name: &PathBuf) -> bool {
|
|
||||||
use std::fs::File;
|
|
||||||
File::open(name).is_ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_file(&self, file_name: &str) -> std::io::Result<String> {
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
let path = self.in_cwd(file_name);
|
|
||||||
debug!("reading from {:?}", path);
|
|
||||||
let mut file = File::open(path)?;
|
|
||||||
let mut content = String::new();
|
|
||||||
file.read_to_string(&mut content)?;
|
|
||||||
Ok(content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
|
||||||
pub struct RealFileSystem {
|
|
||||||
cwd: PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct TempFileSystem {
|
|
||||||
cwd: PathBuf,
|
|
||||||
|
|
||||||
// Handle to the temporary directory
|
|
||||||
// When this handle is dropped the directory is deleted
|
|
||||||
_temp_dir: Arc<Mutex<TempDir>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FileSystemLike for TempFileSystem {
|
|
||||||
fn cwd(&self) -> &PathBuf {
|
|
||||||
&self.cwd
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FileSystemLike for RealFileSystem {
|
|
||||||
fn cwd(&self) -> &PathBuf {
|
|
||||||
&self.cwd
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RealFileSystem {
|
|
||||||
const fn new(cwd: PathBuf) -> Self {
|
|
||||||
Self { cwd }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TempFileSystem {
|
|
||||||
fn new() -> std::io::Result<Self> {
|
|
||||||
let temp_dir = tempdir()?;
|
|
||||||
info!("temp dir: {:?}", temp_dir.path());
|
|
||||||
let cwd = temp_dir.path().to_path_buf();
|
|
||||||
let temp_dir = Arc::new(Mutex::new(temp_dir));
|
|
||||||
Ok(Self {
|
|
||||||
cwd,
|
|
||||||
_temp_dir: temp_dir,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
#[test_log::test]
|
|
||||||
fn test_cwd() {
|
|
||||||
let cwd = PathBuf::from("/tmp");
|
|
||||||
let env = RealFileSystem::new(cwd.clone());
|
|
||||||
assert_eq!(env.cwd(), &cwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test_log::test]
|
|
||||||
fn test_create_on_temp_fs() -> std::io::Result<()> {
|
|
||||||
let env = TempFileSystem::new()?;
|
|
||||||
assert!(env.cwd().exists());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test_log::test]
|
|
||||||
fn test_create_on_real_fs() {
|
|
||||||
let cwd = PathBuf::from("/tmp");
|
|
||||||
let env = RealFileSystem::new(cwd.clone());
|
|
||||||
assert_eq!(env.cwd(), &cwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test_log::test]
|
|
||||||
fn test_write_and_read_file() -> std::io::Result<()> {
|
|
||||||
let env = TempFileSystem::new()?;
|
|
||||||
let file_name = "test.txt";
|
|
||||||
let content = "Hello, World!";
|
|
||||||
let path = env.write_file(file_name, content)?;
|
|
||||||
assert_eq!(env.read_file(file_name)?, content);
|
|
||||||
assert!(path.exists());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +1,16 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use derive_more::From;
|
|
||||||
|
|
||||||
mod real;
|
mod real;
|
||||||
|
mod result;
|
||||||
mod temp;
|
mod temp;
|
||||||
|
|
||||||
mod dir_item;
|
mod dir_item;
|
||||||
pub use dir_item::DirItem;
|
pub use dir_item::DirItem;
|
||||||
pub use dir_item::DirItemIterator;
|
pub use dir_item::DirItemIterator;
|
||||||
use real::FileSystem;
|
use real::FileSystem;
|
||||||
|
pub use result::*;
|
||||||
use temp::TempFileSystem;
|
use temp::TempFileSystem;
|
||||||
|
|
||||||
#[derive(Debug, From, derive_more::Display)]
|
|
||||||
pub enum Error {
|
|
||||||
Io(std::io::Error),
|
|
||||||
|
|
||||||
#[display("Path access attempted outside of base ({base:?}): {path:?}")]
|
|
||||||
PathTraversal {
|
|
||||||
base: PathBuf,
|
|
||||||
path: PathBuf,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[display("Path must be a directory: {path:?}")]
|
|
||||||
NotADirectory {
|
|
||||||
path: PathBuf,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
impl std::error::Error for Error {}
|
|
||||||
|
|
||||||
pub type Result<T> = core::result::Result<T, Error>;
|
|
||||||
|
|
||||||
pub const fn new(base: PathBuf) -> FileSystem {
|
pub const fn new(base: PathBuf) -> FileSystem {
|
||||||
real::new(base)
|
real::new(base)
|
||||||
}
|
}
|
||||||
|
|
23
src/fs/result.rs
Normal file
23
src/fs/result.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use derive_more::From;
|
||||||
|
|
||||||
|
#[derive(Debug, From, derive_more::Display)]
|
||||||
|
pub enum Error {
|
||||||
|
Io(std::io::Error),
|
||||||
|
|
||||||
|
#[display("Path access attempted outside of base ({base:?}): {path:?}")]
|
||||||
|
PathTraversal {
|
||||||
|
base: PathBuf,
|
||||||
|
path: PathBuf,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[display("Path must be a directory: {path:?}")]
|
||||||
|
NotADirectory {
|
||||||
|
path: PathBuf,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
|
pub type Result<T> = core::result::Result<T, Error>;
|
|
@ -1,6 +1,4 @@
|
||||||
#[cfg(feature = "fs")]
|
//
|
||||||
pub mod filesystem;
|
|
||||||
|
|
||||||
#[cfg(feature = "fs")]
|
#[cfg(feature = "fs")]
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
type TestResult = Result<(), Box<dyn std::error::Error>>;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn write_read_file_exists() -> TestResult {
|
|
||||||
let fs = crate::filesystem::temp()?;
|
|
||||||
let pathbuf = fs.write_file("foo", "content")?;
|
|
||||||
let c = fs.read_file("foo")?;
|
|
||||||
assert_eq!(c, "content");
|
|
||||||
assert!(fs.file_exists(&pathbuf));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
Loading…
Reference in a new issue