diff options
author | Xavier Vello <xavier.vello@gmail.com> | 2024-02-21 09:42:53 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-21 08:42:53 +0000 |
commit | 3c375cad076e6c5d9b8b38ded781dec58c691fb3 (patch) | |
tree | edcf4b91eb719b0095c35e1d5d3b3abfb3bdbf55 | |
parent | 56b971ae1990f8b03603260801161caf0dfb84d7 (diff) |
feat: add history prune subcommand (#1743)
-rw-r--r-- | atuin/src/command/client/history.rs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/atuin/src/command/client/history.rs b/atuin/src/command/client/history.rs index b0a70b81..26ed7e37 100644 --- a/atuin/src/command/client/history.rs +++ b/atuin/src/command/client/history.rs @@ -109,6 +109,13 @@ pub enum Cmd { }, InitStore, + + /// Delete history entries matching the configured exclusion filters + Prune { + /// List matching history lines without performing the actual deletion. + #[arg(short = 'n', long)] + dry_run: bool, + }, } #[derive(Clone, Copy, Debug)] @@ -413,6 +420,60 @@ impl Cmd { Ok(()) } + async fn handle_prune( + db: &impl Database, + settings: &Settings, + store: SqliteStore, + context: atuin_client::database::Context, + dry_run: bool, + ) -> Result<()> { + // Grab all executed commands and filter them using History::should_save. + // We could iterate or paginate here if memory usage becomes an issue. + let matches: Vec<History> = db + .list(&[Global], &context, None, false, false) + .await? + .into_iter() + .filter(|h| !h.should_save(settings)) + .collect(); + + match matches.len() { + 0 => { + println!("No entries to prune."); + return Ok(()); + } + 1 => println!("Found 1 entry to prune."), + n => println!("Found {n} entries to prune."), + } + + if dry_run { + print_list( + &matches, + ListMode::Human, + Some(settings.history_format.as_str()), + false, + false, + settings.timezone, + ); + } else { + let encryption_key: [u8; 32] = encryption::load_key(settings) + .context("could not load encryption key")? + .into(); + let host_id = Settings::host_id().expect("failed to get host_id"); + let history_store = HistoryStore::new(store.clone(), host_id, encryption_key); + + for entry in matches { + eprintln!("deleting {}", entry.id); + if settings.sync.records { + let (id, _) = history_store.delete(entry.id.clone()).await?; + history_store.incremental_build(db, &[id]).await?; + } else { + db.delete(entry.clone()).await?; + } + } + } + Ok(()) + } + async fn init_store(&self, db: &impl Database, history_store: HistoryStore) -> Result<()> { let context = current_context(); history_store.init_store(context, db).await @@ -481,6 +542,10 @@ impl Cmd { } Self::InitStore => self.init_store(db, history_store).await, + + Self::Prune { dry_run } => { + Self::handle_prune(db, settings, store, context, dry_run).await + } } } } |