pijul 1.0.0-alpha

The sound distributed version control system.
use crate::repository::Repository;
use libpijul::pristine::{Base32, MutTxnT, TxnT};
use libpijul::MutTxnTExt;
use std::path::PathBuf;

#[derive(Clap, Debug)]
pub struct Unrecord {
    #[clap(long = "repository")]
    repo_path: Option<PathBuf>,
    #[clap(long = "channel")]
    channel: Option<String>,
    #[clap(
        about = "identifier of the change (unambiguous prefixes are accepted)",
        multiple = true
    )]
    change_id: Vec<String>,
}

impl Unrecord {
    pub fn run(self) -> Result<(), anyhow::Error> {
        let repo = Repository::find_root(self.repo_path)?;
        debug!("{:?}", repo.config);
        let channel_name = repo.config.get_current_channel(self.channel.as_ref());
        let mut txn = repo.pristine.mut_txn_begin();
        for c in self.change_id.iter() {
            let (hash, change_id) = txn.hash_from_prefix(c)?;
            if let Some(mut channel) = txn.load_channel(channel_name) {
                let mut can_unrecord = true;
                let channel_ = channel.borrow();
                for (p, d) in txn.iter_revdep(change_id) {
                    if p < change_id {
                        continue;
                    } else if p > change_id {
                        break;
                    }
                    if txn.get_changeset(&channel_.changes, d, None).is_some() {
                        if can_unrecord {
                            eprintln!("Cannot unrecord change {}, because the following changes depend on it:", c)
                        }
                        can_unrecord = false;
                        eprintln!("  {}", txn.get_external(d).unwrap().to_base32())
                    }
                }
                std::mem::drop(channel_);
                if can_unrecord {
                    txn.unrecord(&repo.changes, &mut channel, &hash)?;
                }
            }
        }
        txn.commit()?;
        Ok(())
    }
}