rustic_rs/commands/
merge.rs1use crate::commands::program_version;
4use crate::{
5 Application, RUSTIC_APP,
6 repository::{OpenRepo, get_snapots_from_ids},
7 status_err,
8};
9use abscissa_core::{Command, Runnable, Shutdown};
10use anyhow::Result;
11use jiff::Zoned;
12use log::info;
13
14use rustic_core::{SnapshotOptions, last_modified_node, repofile::SnapshotFile};
15
16#[derive(clap::Parser, Default, Command, Debug)]
18pub(super) struct MergeCmd {
19 #[clap(value_name = "ID")]
21 ids: Vec<String>,
22
23 #[clap(long)]
25 json: bool,
26
27 #[clap(long)]
29 delete: bool,
30
31 #[clap(flatten, next_help_heading = "Snapshot options")]
33 snap_opts: SnapshotOptions,
34}
35
36impl Runnable for MergeCmd {
37 fn run(&self) {
38 if let Err(err) = RUSTIC_APP
39 .config()
40 .repository
41 .run_open(|repo| self.inner_run(repo))
42 {
43 status_err!("{}", err);
44 RUSTIC_APP.shutdown(Shutdown::Crash);
45 };
46 }
47}
48
49impl MergeCmd {
50 fn inner_run(&self, repo: OpenRepo) -> Result<()> {
51 let config = RUSTIC_APP.config();
52 let repo = repo.to_indexed_ids()?;
53
54 let snapshots = get_snapots_from_ids(&repo, &self.ids)?;
55
56 if config.global.dry_run {
58 println!("would have modified the following snapshots:\n {snapshots:?}");
59 return Ok(());
60 }
61
62 let mut snap = SnapshotFile::from_options(&self.snap_opts)?;
63 snap.program_version = program_version();
64 let snap = repo.merge_snapshots(&snapshots, &last_modified_node, snap)?;
65
66 if self.json {
67 let mut stdout = std::io::stdout();
68 serde_json::to_writer_pretty(&mut stdout, &snap)?;
69 }
70 info!("saved new snapshot as {}.", snap.id);
71
72 if self.delete {
73 let now = Zoned::now();
74 let snap_ids: Vec<_> = snapshots
76 .iter()
77 .filter(|sn| !sn.must_keep(&now))
78 .map(|sn| sn.id)
79 .collect();
80 repo.delete_snapshots(&snap_ids)?;
81 }
82
83 Ok(())
84 }
85}