A library for writing host-specific, single-binary configuration management and deployment tools
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

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)
}
}