Move recursive remove logic to remove function

This commit is contained in:
w3irdrobot 2025-10-07 21:05:53 -04:00
parent 9785689526
commit 3a4b198cef
No known key found for this signature in database
GPG Key ID: 27D529942CDCEA61
4 changed files with 36 additions and 25 deletions

View File

@ -204,7 +204,7 @@ pub struct Query {
)]
pub struct Remove {
#[clap(value_hint = ValueHint::DirPath)]
pub paths: Vec<PathBuf>,
pub paths: Vec<String>,
/// Recursively remove directories
#[clap(short, long, default_value_t = false)]

View File

@ -17,7 +17,7 @@ impl Run for Edit {
match cmd {
EditCommand::Decrement { path } => db.add(path, -1.0, now),
EditCommand::Delete { path } => {
db.remove(path);
db.remove(path, false);
}
EditCommand::Increment { path } => db.add(path, 1.0, now),
EditCommand::Reload => {}

View File

@ -1,5 +1,3 @@
use std::path::PathBuf;
use anyhow::{Result, bail};
use crate::cmd::{Remove, Run};
@ -10,18 +8,13 @@ impl Run for Remove {
fn run(&self) -> Result<()> {
let mut db = Database::open()?;
// Build a unified iterator of PathBufs, whether recursive or not.
let paths: Box<dyn Iterator<Item = PathBuf>> = if self.recursive {
Box::new(self.paths.iter().flat_map(|p| util::walk_dir(p)))
} else {
Box::new(self.paths.iter().cloned())
};
for path in paths {
let path_abs = util::resolve_path(path)?;
let path_abs = util::path_to_str(&path_abs)?;
if !db.remove(path_abs) {
bail!("path not found in database: {}", path_abs)
for path in &self.paths {
if !db.remove(path, self.recursive) {
let path_abs = util::resolve_path(path)?;
let path_abs = util::path_to_str(&path_abs)?;
if path_abs == path || !db.remove(path_abs, self.recursive) {
bail!("path not found in database: {path}")
}
}
}

View File

@ -101,17 +101,35 @@ impl Database {
}
/// Removes the directory with `path` from the store. This does not preserve
/// ordering, but is O(1).
pub fn remove(&mut self, path: impl AsRef<str>) -> bool {
match self.dirs().iter().position(|dir| dir.path == path.as_ref()) {
Some(idx) => {
self.swap_remove(idx);
true
/// ordering, but is O(1). If recursive, this will remove all directories
/// starting with `path`. This is O(n)
pub fn remove(&mut self, path: impl AsRef<str>, recursive: bool) -> bool {
if recursive {
self.remove_recursive(path)
} else {
match self.dirs().iter().position(|dir| dir.path == path.as_ref()) {
Some(idx) => {
self.swap_remove(idx);
true
}
None => false,
}
None => false,
}
}
pub fn remove_recursive(&mut self, path: impl AsRef<str>) -> bool {
let mut removed = false;
self.with_dirs_mut(|dirs| {
dirs.retain(|dir| {
let keep = !dir.path.starts_with(path.as_ref());
removed |= !keep;
keep
});
});
self.with_dirty_mut(|dirty| *dirty = removed);
removed
}
pub fn swap_remove(&mut self, idx: usize) {
self.with_dirs_mut(|dirs| dirs.swap_remove(idx));
self.with_dirty_mut(|dirty| *dirty = true);
@ -273,14 +291,14 @@ mod tests {
{
let mut db = Database::open_dir(data_dir.path()).unwrap();
assert!(db.remove(path));
assert!(db.remove(path, false));
db.save().unwrap();
}
{
let mut db = Database::open_dir(data_dir.path()).unwrap();
assert!(db.dirs().is_empty());
assert!(!db.remove(path));
assert!(!db.remove(path, false));
db.save().unwrap();
}
}