use std::fs;
use std::io;
use std::io::Write;
use std::path;
use globwalk;
use tempfile;
use errors;
use errors::ResultChainExt;
pub use tempfile::TempDir;
pub trait PathChild {
fn child<P>(&self, path: P) -> ChildPath
where
P: AsRef<path::Path>;
}
impl PathChild for tempfile::TempDir {
fn child<P>(&self, path: P) -> ChildPath
where
P: AsRef<path::Path>,
{
ChildPath::new(self.path().join(path.as_ref()))
}
}
pub struct ChildPath {
path: path::PathBuf,
}
impl ChildPath {
pub fn new<P>(path: P) -> Self
where
P: Into<path::PathBuf>,
{
Self { path: path.into() }
}
pub fn path(&self) -> &path::Path {
&self.path
}
}
pub trait FileTouch {
fn touch(&self) -> io::Result<()>;
}
impl FileTouch for ChildPath {
fn touch(&self) -> io::Result<()> {
touch(self.path())
}
}
pub trait FileWriteBin {
fn write_binary(&self, data: &[u8]) -> io::Result<()>;
}
impl FileWriteBin for ChildPath {
fn write_binary(&self, data: &[u8]) -> io::Result<()> {
write_binary(self.path(), data)
}
}
pub trait FileWriteStr {
fn write_str(&self, data: &str) -> io::Result<()>;
}
impl FileWriteStr for ChildPath {
fn write_str(&self, data: &str) -> io::Result<()> {
write_str(self.path(), data)
}
}
pub trait PathCopy {
fn copy_from<P, S>(&self, source: P, patterns: &[S]) -> Result<(), errors::FixtureError>
where
P: AsRef<path::Path>,
S: AsRef<str>;
}
impl PathCopy for tempfile::TempDir {
fn copy_from<P, S>(&self, source: P, patterns: &[S]) -> Result<(), errors::FixtureError>
where
P: AsRef<path::Path>,
S: AsRef<str>,
{
copy_files(self.path(), source.as_ref(), patterns)
}
}
impl PathCopy for ChildPath {
fn copy_from<P, S>(&self, source: P, patterns: &[S]) -> Result<(), errors::FixtureError>
where
P: AsRef<path::Path>,
S: AsRef<str>,
{
copy_files(self.path(), source.as_ref(), patterns)
}
}
fn touch(path: &path::Path) -> io::Result<()> {
fs::File::create(path)?;
Ok(())
}
fn write_binary(path: &path::Path, data: &[u8]) -> io::Result<()> {
let mut file = fs::File::create(path)?;
file.write_all(data)?;
Ok(())
}
fn write_str(path: &path::Path, data: &str) -> io::Result<()> {
write_binary(path, data.as_bytes())
}
fn copy_files<S>(
target: &path::Path,
source: &path::Path,
patterns: &[S],
) -> Result<(), errors::FixtureError>
where
S: AsRef<str>,
{
let source = source
.canonicalize()
.chain(errors::FixtureError::new(errors::FixtureKind::Walk))?;
for entry in globwalk::GlobWalker::from_patterns(&source, patterns)
.chain(errors::FixtureError::new(errors::FixtureKind::Walk))?
.follow_links(true)
{
println!("{:?}", entry);
let entry = entry.chain(errors::FixtureError::new(errors::FixtureKind::Walk))?;
let rel = entry
.path()
.strip_prefix(&source)
.expect("entries to be under `source`");
let target_path = target.join(rel);
if entry.file_type().is_dir() {
fs::create_dir_all(target_path)
.chain(errors::FixtureError::new(errors::FixtureKind::CreateDir))?;
} else if entry.file_type().is_file() {
fs::create_dir_all(target_path.parent().expect("at least `target` exists"))
.chain(errors::FixtureError::new(errors::FixtureKind::CreateDir))?;
fs::copy(entry.path(), target_path)
.chain(errors::FixtureError::new(errors::FixtureKind::CopyFile))?;
}
}
Ok(())
}