Files
keep/src/modes/delete.rs
Andrew Phillips 9b7cbd5244 fix: resolve doctest failures, database bugs, and remove dead code
- Fix all 96 doctest failures across 20 files by adding hidden imports and
  proper test setup (68 pass, 33 intentionally ignored)
- Fix set_item_tags: wrap in transaction and replace item.id.unwrap() with
  proper error handling
- Fix get_items_matching: replace N+1 per-item meta queries with batch
  get_meta_for_items() call
- Fix get_item_matching: apply meta filtering instead of ignoring the parameter
- Remove duplicate doc comment in store_meta
- Remove dead code files: plugin.rs, plugins.rs, binary_detection.rs
  (never declared as modules)
- Apply cargo fmt formatting fixes
- Add keep.db to .gitignore
2026-03-12 11:58:44 -03:00

79 lines
2.4 KiB
Rust

use anyhow::Result;
use std::path::PathBuf;
use crate::config;
use crate::services::error::CoreError;
use crate::services::item_service::ItemService;
use clap::Command;
use log::warn;
use rusqlite::Connection;
/// Handles the delete mode: removes items by ID from the database and storage.
///
/// This function processes a list of item IDs, attempting to delete each from
/// both the database and the underlying file storage. It skips items that are
/// not found and logs warnings for them. Validation of arguments (e.g., ensuring
/// IDs are provided and tags are empty) is handled at the clap parsing level.
///
/// # Arguments
///
/// * `_cmd` - Clap command for error handling (unused).
/// * `_settings` - Global settings (unused).
/// * `_config` - Configuration settings (unused).
/// * `ids` - List of item IDs to delete.
/// * `_tags` - Tags (unused, as delete only supports IDs).
/// * `conn` - Database connection.
/// * `data_path` - Path to data directory for storage cleanup.
///
/// # Returns
///
/// `Result<()>` on success, or an error if deletion fails for any item.
///
/// # Errors
///
/// Returns an `anyhow::Error` if a deletion operation fails due to database
/// or I/O issues (excluding `ItemNotFound`, which is handled gracefully).
///
/// # Examples
///
/// ```ignore
/// // This would be called from main after parsing args
/// mode_delete(&mut cmd, &settings, &config, &mut vec![1, 2], &mut vec![], &mut conn, data_path)?;
/// ```
///
/// # Panics
///
/// None.
pub fn mode_delete(
_cmd: &mut Command,
_settings: &config::Settings,
_config: &config::Settings,
ids: &mut [i64],
_tags: &mut [String],
conn: &mut Connection,
data_path: PathBuf,
) -> Result<()> {
// Validation is now handled at the argument parsing level
// So we can assume ids is not empty and tags is empty
let item_service = ItemService::new(data_path);
for item_id in ids.iter() {
match item_service.delete_item(conn, *item_id) {
Ok(_) => {}
Err(e) => match e {
CoreError::ItemNotFound(_) => {
warn!("Unable to find item {item_id} in database");
}
_ => {
return Err(
anyhow::Error::from(e).context(format!("Failed to delete item {item_id}"))
);
}
},
}
}
Ok(())
}