use crate::{
Application, RUSTIC_APP,
repository::{OpenRepo, get_snapots_from_ids},
status_err,
};
use abscissa_core::{Command, Runnable, Shutdown};
use anyhow::Result;
use jiff::Zoned;
use log::info;
use rustic_core::{SnapshotOptions, last_modified_node, repofile::SnapshotFile};
#[derive(clap::Parser, Default, Command, Debug)]
pub(super) struct MergeCmd {
#[clap(value_name = "ID")]
ids: Vec<String>,
#[clap(long)]
json: bool,
#[clap(long)]
delete: bool,
#[clap(flatten, next_help_heading = "Snapshot options")]
snap_opts: SnapshotOptions,
}
impl Runnable for MergeCmd {
fn run(&self) {
if let Err(err) = RUSTIC_APP
.config()
.repository
.run_open(|repo| self.inner_run(repo))
{
status_err!("{}", err);
RUSTIC_APP.shutdown(Shutdown::Crash);
};
}
}
impl MergeCmd {
fn inner_run(&self, repo: OpenRepo) -> Result<()> {
let config = RUSTIC_APP.config();
let repo = repo.to_indexed_ids()?;
let snapshots = get_snapots_from_ids(&repo, &self.ids)?;
if config.global.dry_run {
println!("would have modified the following snapshots:\n {snapshots:?}");
return Ok(());
}
let snap = SnapshotFile::from_options(&self.snap_opts)?;
let snap = repo.merge_snapshots(&snapshots, &last_modified_node, snap)?;
if self.json {
let mut stdout = std::io::stdout();
serde_json::to_writer_pretty(&mut stdout, &snap)?;
}
info!("saved new snapshot as {}.", snap.id);
if self.delete {
let now = Zoned::now();
let snap_ids: Vec<_> = snapshots
.iter()
.filter(|sn| !sn.must_keep(&now))
.map(|sn| sn.id)
.collect();
repo.delete_snapshots(&snap_ids)?;
}
Ok(())
}
}