pijul 0.7.2

A patch-based distributed version control system, easy to use and fast. Command-line interface.
extern crate tempdir;
extern crate env_logger;
use commands::{init, record, add, revert, unrecord};
use error;
use std::fs;
use std;
use std::io::prelude::*;
use libpijul;
use libpijul::DEFAULT_BRANCH;

fn mk_tmp_repos(n: usize) -> (tempdir::TempDir, Vec<std::path::PathBuf>) {
    env_logger::init().unwrap_or(());
    let dir = tempdir::TempDir::new("pijul").unwrap();
    let mut v = Vec::new();
    for i in 0..n {
        let dir_a = dir.path().join(format!("{}", i));
        {
            fs::create_dir(&dir_a).unwrap();
            let init_params_a = init::Params {
                location: Some(&dir_a),
                allow_nested: false,
            };
            init::run(&init_params_a).unwrap();
        }
        v.push(dir_a)
    }
    (dir, v)
}

fn add_one_file(repo: &std::path::Path, file: &std::path::Path) -> Result<(), error::Error> {

    let add_params = add::Params {
        repository: Some(&repo),
        touched_files: vec![&file],
    };
    add::run(&add_params)
}

fn record_all(repo: &std::path::Path,
              name: Option<&str>)
              -> Result<Option<libpijul::Hash>, error::Error> {
    let record_params = record::Params {
        repository: Some(repo),
        yes_to_all: true,
        authors: Some(vec!["Olympe de Gouges", "Ὑπατία"]),
        patch_name: name,
        branch: Some(DEFAULT_BRANCH),
        prefix: None,
    };
    debug!("record_all!");
    record::run(&record_params)
}

fn revert(repo: &std::path::Path) -> Result<(), error::Error> {

    let params = revert::Params {
        repository: Some(repo),
        yes_to_all: true,
        branch: Some(DEFAULT_BRANCH),
        prefix: None,
    };
    debug!("revert!");
    revert::run(&params)
}

fn unrecord_last(repo: &std::path::Path) -> Result<(), error::Error> {
    use libpijul::fs_representation::pristine_dir;
    use libpijul::{DEFAULT_BRANCH, Repository};

    let hash = {
        let repo_dir = pristine_dir(repo);
        let repo = try!(Repository::open(&repo_dir, None));
        let txn = try!(repo.txn_begin());
        let branch = txn.get_branch(&DEFAULT_BRANCH).unwrap();
        let patchid = txn.rev_iter_applied(&branch, None).next().unwrap().1;
        txn.get_external(patchid).unwrap().to_owned()
    };

    let params = unrecord::Params {
        repository: Some(repo),
        yes_to_all: false,
        branch: Some(DEFAULT_BRANCH),
        patches: Some(std::iter::once(hash).collect()),
    };
    debug!("unrecord!");
    unrecord::run(&params)

}

#[test]
fn unrecord_del() {
    let (dir, dirs) = mk_tmp_repos(1);
    println!("dir = {:?}", dir);
    let dir_a = &dirs[0];
    let toto_path = &dir_a.join("toto");

    let mut f = std::fs::File::create(&toto_path).unwrap();
    write!(f, "a\nb\nc\nd\ne\nf\n").unwrap();
    std::mem::drop(f);
    add_one_file(&dir_a, toto_path).unwrap();
    record_all(&dir_a, Some("add toto")).unwrap();

    let mut f = std::fs::File::create(&toto_path).unwrap();
    write!(f, "a\nd\ne\nf\n").unwrap();
    std::mem::drop(f);
    record_all(&dir_a, Some("-bc")).unwrap();

    let mut f = std::fs::File::create(&toto_path).unwrap();
    write!(f, "a\nf\n").unwrap();
    std::mem::drop(f);
    record_all(&dir_a, Some("-de")).unwrap();

    unrecord_last(&dir_a).unwrap();
    revert(&dir_a).unwrap();

    let mut f = std::fs::File::open(&toto_path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();
    assert_eq!(s.as_str(), "a\nd\ne\nf\n")
}


#[test]
fn unrecord_add() {
    let (dir, dirs) = mk_tmp_repos(1);
    println!("dir = {:?}", dir);
    let dir_a = &dirs[0];
    let toto_path = &dir_a.join("toto");

    let mut f = std::fs::File::create(&toto_path).unwrap();
    write!(f, "a\nf\n").unwrap();
    std::mem::drop(f);
    add_one_file(&dir_a, toto_path).unwrap();
    record_all(&dir_a, Some("add toto")).unwrap();

    let mut f = std::fs::File::create(&toto_path).unwrap();
    write!(f, "a\nb\nc\nf\n").unwrap();
    std::mem::drop(f);
    record_all(&dir_a, Some("+bc")).unwrap();

    let mut f = std::fs::File::create(&toto_path).unwrap();
    write!(f, "a\nc\nd\ne\nf\n").unwrap();
    std::mem::drop(f);
    record_all(&dir_a, Some("+de")).unwrap();


    unrecord_last(&dir_a).unwrap();
    revert(&dir_a).unwrap();

    let mut f = std::fs::File::open(&toto_path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();
    assert_eq!(s.as_str(), "a\nb\nc\nf\n")
}