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(())
}
}