use clap::ArgMatches;
use libpijul::Repository;
use libpijul::fs_representation::{pristine_dir, find_repo_root};
use std::path::Path;
use std::fs::{metadata, canonicalize};
use error;
use commands::get_wd;
use rand;
#[derive(Debug)]
pub struct Params<'a> {
pub touched_files: Vec<&'a Path>,
pub repository: Option<&'a Path>,
}
use error::Error;
pub fn parse_args<'a>(args: &'a ArgMatches) -> Params<'a> {
let paths = match args.values_of("files") {
Some(l) => l.map(|p| Path::new(p)).collect(),
None => vec![],
};
let repository = args.value_of("repository").and_then(|x| Some(Path::new(x)));
Params {
repository: repository,
touched_files: paths,
}
}
#[derive(Debug)]
pub enum Operation {
Add,
Remove,
}
pub fn run<'a>(args: &Params<'a>, op: Operation) -> Result<Option<()>, error::Error> {
debug!("fs_operation {:?}", op);
let files = &args.touched_files;
let wd = try!(get_wd(args.repository));
let mut rng = rand::thread_rng();
match find_repo_root(&wd) {
None => return Err(error::Error::NotInARepository),
Some(ref r) => {
debug!("repo {:?}", r);
let repo_dir = pristine_dir(r);
let repo = try!(Repository::open(&repo_dir, None).map_err(error::Error::Repository));
let mut txn = try!(repo.mut_txn_begin(&mut rng));
match op {
Operation::Add => {
for file in &files[..] {
let p = try!(canonicalize(wd.join(*file)));
let m = try!(metadata(&p));
if let Ok(file) = p.strip_prefix(r) {
try!(txn.add_file(file, m.is_dir()))
} else {
return Err(Error::InvalidPath(file.to_string_lossy().into_owned()));
}
}
}
Operation::Remove => {
for file in &files[..] {
let p = try!(canonicalize(wd.join(*file)));
if let Ok(file) = p.strip_prefix(r) {
try!(txn.remove_file(file))
} else {
return Err(Error::InvalidPath(file.to_string_lossy().into_owned()));
}
}
}
}
try!(txn.commit());
Ok(Some(()))
}
}
}