pijul 1.0.0-alpha.9

The sound distributed version control system.
use std::collections::HashMap;
use std::path::PathBuf;

use clap::Clap;
use libpijul::changestore::ChangeStore;
use libpijul::{MutTxnT, MutTxnTExt, TxnT};

use crate::repository::Repository;
use crate::Error;

#[derive(Clap, Debug)]
pub struct Apply {
    /// Set the repository where this command should run Defaults to the first ancestor of the current directory that contains a `.pijul` directory.
    #[clap(long = "repository")]
    repo_path: Option<PathBuf>,
    /// Apply change to this channel
    #[clap(long = "channel")]
    channel: Option<String>,
    /// Only apply the dependencies of this change
    #[clap(long = "deps-only")]
    deps_only: bool,
    /// The change that need to be applied
    change: Option<String>,
}

impl Apply {
    pub fn run(self) -> Result<(), anyhow::Error> {
        let mut repo = Repository::find_root(self.repo_path)?;
        let mut txn = repo.pristine.mut_txn_begin();
        let channel_name = repo.config.get_current_channel(self.channel.as_ref());
        let mut channel = if let Some(channel) = txn.load_channel(&channel_name) {
            channel
        } else if self.change.is_some() {
            txn.open_or_create_channel(&channel_name)?
        } else {
            return Err((Error::NoSuchChannel {
                channel: channel_name.to_string(),
            })
            .into());
        };
        let hash = if let Some(ch) = self.change {
            if let Ok(h) = txn.hash_from_prefix(&ch) {
                h.0
            } else {
                let change = libpijul::change::Change::deserialize(&ch, None)?;
                repo.changes.save_change(&change)?
            }
        } else {
            let mut change = std::io::BufReader::new(std::io::stdin());
            let change = libpijul::change::Change::read(&mut change, &mut HashMap::new())?;
            repo.changes.save_change(&change)?
        };
        if self.deps_only {
            txn.apply_deps_rec(&repo.changes, &mut channel, hash)?;
        } else {
            txn.apply_change_rec(&repo.changes, &mut channel, hash)?;
        }
        txn.output_repository_no_pending(
            &mut repo.working_copy,
            &repo.changes,
            &mut channel,
            "",
            true,
        )?;
        txn.commit()?;
        Ok(())
    }
}