You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.5 KiB
94 lines
2.5 KiB
use std::error::Error;
|
|
use std::fmt;
|
|
use std::io;
|
|
use std::ops::Deref;
|
|
|
|
use symbols::Symbol;
|
|
|
|
#[derive(Debug)]
|
|
pub enum FileError<E: Error> {
|
|
ExecError(E),
|
|
GenericError
|
|
}
|
|
|
|
impl From<io::Error> for FileError<io::Error> {
|
|
fn from(err: io::Error) -> FileError<io::Error> {
|
|
FileError::ExecError(err)
|
|
}
|
|
}
|
|
|
|
impl<E: Error> Error for FileError<E> {
|
|
fn description(&self) -> &str {
|
|
match self {
|
|
&FileError::ExecError(ref e) => e.description(),
|
|
&FileError::GenericError => "Generic error"
|
|
}
|
|
}
|
|
fn cause(&self) -> Option<&Error> {
|
|
match self {
|
|
&FileError::ExecError(ref e) => Some(e),
|
|
_ => None
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<E: Error> fmt::Display for FileError<E> {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
write!(f, "{}", self.description())
|
|
}
|
|
}
|
|
|
|
use std::convert::AsRef;
|
|
|
|
pub struct File<C, D> where C: Deref<Target=str>, D: AsRef<str> + fmt::Display {
|
|
path: D,
|
|
content: C
|
|
}
|
|
|
|
impl<C, D> File<C, D> where C: Deref<Target=str>, D: AsRef<str> + fmt::Display {
|
|
pub fn new(path: D, content: C) -> Self {
|
|
File {
|
|
path: path,
|
|
content: content
|
|
}
|
|
}
|
|
}
|
|
|
|
use std::fs::File as FsFile;
|
|
use std::io::{Read, Write};
|
|
|
|
impl<C, D> Symbol for File<C, D> where C: Deref<Target=str>, D: AsRef<str> + fmt::Display {
|
|
type Error = FileError<io::Error>;
|
|
fn target_reached(&self) -> Result<bool, Self::Error> {
|
|
let file = FsFile::open(self.path.as_ref());
|
|
// Check if file exists
|
|
if let Err(e) = file {
|
|
return if e.kind() == io::ErrorKind::NotFound {
|
|
Ok(false)
|
|
} else {
|
|
Err(e.into())
|
|
};
|
|
}
|
|
// Check if content is the same
|
|
let file_content = file.unwrap().bytes();
|
|
let content_equal = try!(self.content.bytes().zip(file_content).fold(
|
|
Ok(true),
|
|
|state, (target_byte, file_byte_option)| state.and_then(|s| file_byte_option.map(|file_byte| s && file_byte == target_byte))
|
|
));
|
|
return Ok(content_equal)
|
|
}
|
|
|
|
fn execute(&self) -> Result<(), Self::Error> {
|
|
//try!(self.command_runner.run_with_args("mkdir", &["-p", Path::new(&path).parent().unwrap().to_str().unwrap()]));
|
|
// FIXME: Permissions
|
|
// try!(create_dir_all(Path::new(&path).parent().unwrap()));
|
|
try!(try!(FsFile::create(self.path.as_ref())).write_all(self.content.as_bytes()));
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<C, D> fmt::Display for File<C, D> where C: Deref<Target=str>, D: AsRef<str> + fmt::Display {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{
|
|
write!(f, "File {}", self.path)
|
|
}
|
|
}
|