2024-04-07 11:52:47 +01:00
|
|
|
#![allow(unused)]
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
ops::Deref,
|
|
|
|
path::PathBuf,
|
|
|
|
sync::{Arc, Mutex},
|
|
|
|
};
|
|
|
|
|
|
|
|
use tempfile::{tempdir, TempDir};
|
2024-04-07 13:26:02 +01:00
|
|
|
use tracing::info;
|
2024-04-07 11:52:47 +01:00
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum FileSystem {
|
|
|
|
Real(RealFileSystemEnv),
|
|
|
|
Temp(TempFileSystemEnv),
|
|
|
|
}
|
|
|
|
impl FileSystem {
|
|
|
|
pub fn new_real(cwd: Option<PathBuf>) -> Self {
|
|
|
|
let cwd = cwd.unwrap_or_default();
|
|
|
|
Self::Real(RealFileSystemEnv::new(cwd))
|
|
|
|
}
|
|
|
|
pub fn new_temp() -> std::io::Result<Self> {
|
|
|
|
TempFileSystemEnv::new().map(Self::Temp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl Deref for FileSystem {
|
|
|
|
type Target = dyn FileSystemEnv;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
match self {
|
|
|
|
Self::Real(env) => env,
|
|
|
|
Self::Temp(env) => env,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait FileSystemEnv: 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);
|
2024-04-07 13:26:02 +01:00
|
|
|
info!("writing to {:?}", path);
|
2024-04-07 11:52:47 +01:00
|
|
|
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()
|
|
|
|
}
|
2024-04-07 13:46:59 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
info!("reading from {:?}", path);
|
|
|
|
let mut file = File::open(path)?;
|
|
|
|
let mut content = String::new();
|
|
|
|
file.read_to_string(&mut content)?;
|
|
|
|
Ok(content)
|
|
|
|
}
|
2024-04-07 11:52:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
|
|
pub struct RealFileSystemEnv {
|
|
|
|
cwd: PathBuf,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct TempFileSystemEnv {
|
|
|
|
cwd: PathBuf,
|
|
|
|
temp_dir: Arc<Mutex<TempDir>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FileSystemEnv for TempFileSystemEnv {
|
|
|
|
fn cwd(&self) -> &PathBuf {
|
|
|
|
&self.cwd
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FileSystemEnv for RealFileSystemEnv {
|
|
|
|
fn cwd(&self) -> &PathBuf {
|
|
|
|
&self.cwd
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RealFileSystemEnv {
|
|
|
|
const fn new(cwd: PathBuf) -> Self {
|
|
|
|
Self { cwd }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TempFileSystemEnv {
|
|
|
|
fn new() -> std::io::Result<Self> {
|
|
|
|
let temp_dir = tempdir()?;
|
2024-04-07 13:26:02 +01:00
|
|
|
info!("temp dir: {:?}", temp_dir.path());
|
2024-04-07 11:52:47 +01:00
|
|
|
let cwd = temp_dir.path().to_path_buf();
|
|
|
|
let temp_dir = Arc::new(Mutex::new(temp_dir));
|
|
|
|
Ok(Self { cwd, 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 = RealFileSystemEnv::new(cwd.clone());
|
|
|
|
assert_eq!(env.cwd(), &cwd);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test_log::test]
|
|
|
|
fn test_create_on_temp_fs() -> std::io::Result<()> {
|
|
|
|
let env = TempFileSystemEnv::new()?;
|
|
|
|
assert!(env.cwd().exists());
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test_log::test]
|
|
|
|
fn test_create_on_real_fs() {
|
|
|
|
let cwd = PathBuf::from("/tmp");
|
|
|
|
let env = RealFileSystemEnv::new(cwd.clone());
|
|
|
|
assert_eq!(env.cwd(), &cwd);
|
|
|
|
}
|
2024-04-07 13:46:59 +01:00
|
|
|
|
|
|
|
#[test_log::test]
|
|
|
|
fn test_write_and_read_file() -> std::io::Result<()> {
|
|
|
|
let env = TempFileSystemEnv::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(())
|
|
|
|
}
|
2024-04-07 11:52:47 +01:00
|
|
|
}
|