Skip to content

Commit 5192c95

Browse files
tarkahermo
authored andcommitted
Add include-newer flag for prune
1 parent a4fe8d9 commit 5192c95

File tree

3 files changed

+56
-20
lines changed

3 files changed

+56
-20
lines changed

moss/src/cli/state.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,18 @@ pub fn command() -> Command {
2525
),
2626
)
2727
.subcommand(
28-
Command::new("prune").about("Prune archived states").arg(
29-
arg!(-k --keep "Keep this many states")
30-
.action(ArgAction::Set)
31-
.default_value("10")
32-
.value_parser(clap::value_parser!(u64).range(1..)),
33-
),
28+
Command::new("prune")
29+
.about("Prune archived states")
30+
.arg(
31+
arg!(-k --keep "Keep this many states")
32+
.action(ArgAction::Set)
33+
.default_value("10")
34+
.value_parser(clap::value_parser!(u64).range(1..)),
35+
)
36+
.arg(
37+
arg!(--"include-newer" "Include states newer than the active state when pruning")
38+
.action(ArgAction::SetTrue),
39+
),
3440
)
3541
.subcommand(
3642
Command::new("remove").about("Remove an archived state").arg(
@@ -98,18 +104,21 @@ pub fn activate(args: &ArgMatches, installation: Installation) -> Result<(), Err
98104

99105
pub fn prune(args: &ArgMatches, installation: Installation) -> Result<(), Error> {
100106
let keep = *args.get_one::<u64>("keep").unwrap();
107+
let include_newer = args.get_flag("include-newer");
108+
let yes = args.get_flag("yes");
101109

102110
let client = Client::new(environment::NAME, installation)?;
103-
client.prune(prune::Strategy::KeepRecent(keep))?;
111+
client.prune(prune::Strategy::KeepRecent { keep, include_newer }, yes)?;
104112

105113
Ok(())
106114
}
107115

108116
pub fn remove(args: &ArgMatches, installation: Installation) -> Result<(), Error> {
109117
let id = *args.get_one::<u64>("ID").unwrap() as i64;
118+
let yes = args.get_flag("yes");
110119

111120
let client = Client::new(environment::NAME, installation)?;
112-
client.prune(prune::Strategy::Remove(id.into()))?;
121+
client.prune(prune::Strategy::Remove(id.into()), yes)?;
113122

114123
Ok(())
115124
}

moss/src/client/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ impl Client {
156156
}
157157

158158
/// Prune states with the provided [`prune::Strategy`]
159-
pub fn prune(&self, strategy: prune::Strategy) -> Result<(), Error> {
159+
pub fn prune(&self, strategy: prune::Strategy, yes: bool) -> Result<(), Error> {
160160
if self.scope.is_ephemeral() {
161161
return Err(Error::EphemeralProhibitedOperation);
162162
}
@@ -167,6 +167,7 @@ impl Client {
167167
&self.install_db,
168168
&self.layout_db,
169169
&self.installation,
170+
yes,
170171
)?;
171172
Ok(())
172173
}

moss/src/client/prune.rs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ use std::{
1010

1111
use itertools::Itertools;
1212
use thiserror::Error;
13-
use tui::pretty::print_to_columns;
13+
use tui::{
14+
dialoguer::{theme::ColorfulTheme, Confirm},
15+
pretty::print_to_columns,
16+
};
1417

1518
use crate::{client::cache, db, environment, package, state, Installation, State};
1619

1720
/// The prune strategy for removing old states
1821
#[derive(Debug, Clone, Copy)]
1922
pub enum Strategy {
2023
/// Keep the most recent N states, remove the rest
21-
KeepRecent(u64),
24+
KeepRecent { keep: u64, include_newer: bool },
2225
/// Removes a specific state
2326
Remove(state::Id),
2427
}
@@ -31,6 +34,7 @@ pub fn prune(
3134
install_db: &db::meta::Database,
3235
layout_db: &db::layout::Database,
3336
installation: &Installation,
37+
yes: bool,
3438
) -> Result<(), Error> {
3539
// Only prune if the moss root has an active state (otherwise
3640
// it's probably borked or not setup yet)
@@ -42,20 +46,26 @@ pub fn prune(
4246

4347
// Find each state we need to remove
4448
let removal_ids = match strategy {
45-
Strategy::KeepRecent(keep) => {
46-
// Filter for all states before the current
47-
let old_states = state_ids
49+
Strategy::KeepRecent { keep, include_newer } => {
50+
// Filter for all removal candidates
51+
let candidates = state_ids
4852
.iter()
49-
.filter(|(id, _)| *id < current_state)
53+
.filter(|(id, _)| {
54+
if include_newer {
55+
*id != current_state
56+
} else {
57+
*id < current_state
58+
}
59+
})
5060
.collect::<Vec<_>>();
51-
// Deduct current state from num to keep
52-
let old_limit = (keep as usize).saturating_sub(1);
61+
// Deduct current state from num candidates to keep
62+
let candidate_limit = (keep as usize).saturating_sub(1);
5363

54-
// Calculate how many old states over the limit we are
55-
let num_to_remove = old_states.len().saturating_sub(old_limit);
64+
// Calculate how many candidate states over the limit we are
65+
let num_to_remove = candidates.len().saturating_sub(candidate_limit);
5666

5767
// Sort ascending and assign first `num_to_remove` as `Status::Remove`
58-
old_states
68+
candidates
5969
.into_iter()
6070
.sorted_by_key(|(_, created)| *created)
6171
.enumerate()
@@ -118,6 +128,18 @@ pub fn prune(
118128
print_to_columns(&removals.iter().map(state::ColumnDisplay).collect::<Vec<_>>());
119129
println!();
120130

131+
let result = if yes {
132+
true
133+
} else {
134+
Confirm::with_theme(&ColorfulTheme::default())
135+
.with_prompt(" Do you wish to continue? ")
136+
.default(false)
137+
.interact()?
138+
};
139+
if !result {
140+
return Err(Error::Cancelled);
141+
}
142+
121143
// Prune these states / packages from all dbs
122144
prune_databases(&removals, &package_removals, state_db, install_db, layout_db)?;
123145

@@ -295,6 +317,8 @@ fn remove_empty_dirs(starting: &Path, root: &Path) -> Result<(), io::Error> {
295317

296318
#[derive(Debug, Error)]
297319
pub enum Error {
320+
#[error("cancelled")]
321+
Cancelled,
298322
#[error("no active state found")]
299323
NoActiveState,
300324
#[error("cannot prune the currently active state")]
@@ -307,4 +331,6 @@ pub enum Error {
307331
StateDB(#[from] db::state::Error),
308332
#[error("io")]
309333
Io(#[from] io::Error),
334+
#[error("string processing")]
335+
Dialog(#[from] tui::dialoguer::Error),
310336
}

0 commit comments

Comments
 (0)