use clap::{SubCommand, ArgMatches, Arg};
use commands::StaticSubcommand;
use libpijul::{Repository, DEFAULT_BRANCH};
use libpijul::patch::Patch;
use libpijul::fs_representation::{pristine_dir, find_repo_root, repo_dir};
use std::path::Path;
use rand;
use error;
use commands::get_wd;
use super::get_current_branch;
pub fn invocation() -> StaticSubcommand {
return SubCommand::with_name("revert")
.about("Rewrite the working copy from the pristine")
.arg(Arg::with_name("repository")
.long("repository")
.takes_value(true)
.help("Local repository."))
.arg(Arg::with_name("branch")
.help("Branch to revert to.")
.long("branch")
.takes_value(true)
);
}
pub struct Params<'a> {
pub repository: Option<&'a Path>,
pub branch: Option<&'a str>
}
pub fn parse_args<'a>(args: &'a ArgMatches) -> Params<'a> {
Params {
repository: args.value_of("repository").map(Path::new),
branch: args.value_of("branch"),
}
}
pub fn run<'a>(args: &Params<'a>) -> Result<(), error::Error> {
let wd = try!(get_wd(args.repository));
match find_repo_root(&wd) {
None => return Err(error::Error::NotInARepository),
Some(ref r) => {
let repo_dir = repo_dir(r);
let pristine_dir = pristine_dir(r);
let branch = if let Some(b) = args.branch {
b.to_string()
} else if let Ok(b) = get_current_branch(&repo_dir) {
b
} else {
DEFAULT_BRANCH.to_string()
};
let mut size_increase = None;
loop {
match output_repository(r, &pristine_dir, &branch, size_increase) {
Err(ref e) if e.lacks_space() => {
size_increase = Some(Repository::repository_size(&pristine_dir).unwrap())
},
e => return e
}
}
}
}
}
fn output_repository(r: &Path, pristine_dir: &Path, branch: &str, size_increase: Option<u64>) -> Result<(), error::Error> {
let repo = try!(Repository::open(&pristine_dir, size_increase));
let mut txn = try!(repo.mut_txn_begin(rand::thread_rng()));
try!(txn.output_repository(&branch, &r, &Patch::empty(), &Vec::new()));
txn.commit()?;
Ok(())
}