diff --git a/src/modes/diff.rs b/src/modes/diff.rs index cf63c84..3022c9b 100644 --- a/src/modes/diff.rs +++ b/src/modes/diff.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use clap::Command; use std::io::Read; use std::os::fd::FromRawFd; @@ -23,22 +23,26 @@ fn validate_diff_args(cmd: &mut Command, ids: &Vec, tags: &Vec) { } use crate::core::item_service::ItemService; +use crate::core::types::ItemWithMeta; fn fetch_and_validate_items( conn: &mut rusqlite::Connection, ids: &Vec, -) -> Result<(crate::db::Item, crate::db::Item), anyhow::Error> { + item_service: &ItemService, +) -> Result<(ItemWithMeta, ItemWithMeta)> { // Fetch items, ensuring they exist. - let item_a = crate::db::get_item(conn, ids[0])? - .ok_or_else(|| anyhow::anyhow!("Unable to find first item (ID: {}) in database", ids[0]))?; - let item_b = crate::db::get_item(conn, ids[1])? - .ok_or_else(|| anyhow::anyhow!("Unable to find second item (ID: {}) in database", ids[1]))?; + let item_a = item_service + .get_item(conn, ids[0]) + .with_context(|| format!("Unable to find first item (ID: {}) in database", ids[0]))?; + let item_b = item_service + .get_item(conn, ids[1]) + .with_context(|| format!("Unable to find second item (ID: {}) in database", ids[1]))?; - log::debug!("MAIN: Found item A {:?}", item_a); - log::debug!("MAIN: Found item B {:?}", item_b); + log::debug!("MAIN: Found item A {:?}", item_a.item); + log::debug!("MAIN: Found item B {:?}", item_b.item); - let item_a_id = item_a.id.ok_or_else(|| anyhow!("Item A missing ID"))?; - let item_b_id = item_b.id.ok_or_else(|| anyhow!("Item B missing ID"))?; + let item_a_id = item_a.item.id.ok_or_else(|| anyhow!("Item A missing ID"))?; + let item_b_id = item_b.item.id.ok_or_else(|| anyhow!("Item B missing ID"))?; // Validate that item IDs are positive to prevent path traversal issues if item_a_id <= 0 || item_b_id <= 0 { @@ -52,30 +56,29 @@ fn fetch_and_validate_items( Ok((item_a, item_b)) } -fn get_item_tags(conn: &mut rusqlite::Connection, item: &crate::db::Item) -> Result> { - let tags: Vec = crate::db::get_item_tags(conn, item)? - .into_iter() - .map(|x| x.name) - .collect(); - Ok(tags) -} - fn setup_diff_paths_and_compression( data_path: &std::path::PathBuf, - item_a: &crate::db::Item, - item_b: &crate::db::Item, -) -> Result<(std::path::PathBuf, crate::compression_engine::CompressionType, std::path::PathBuf, crate::compression_engine::CompressionType), anyhow::Error> { - let item_a_id = item_a.id.ok_or_else(|| anyhow::anyhow!("Item A missing ID"))?; - let item_b_id = item_b.id.ok_or_else(|| anyhow::anyhow!("Item B missing ID"))?; + item_a: &ItemWithMeta, + item_b: &ItemWithMeta, +) -> Result<( + std::path::PathBuf, + crate::compression_engine::CompressionType, + std::path::PathBuf, + crate::compression_engine::CompressionType, +)> { + let item_a_id = item_a.item.id.ok_or_else(|| anyhow::anyhow!("Item A missing ID"))?; + let item_b_id = item_b.item.id.ok_or_else(|| anyhow::anyhow!("Item B missing ID"))?; let mut item_path_a = data_path.clone(); item_path_a.push(item_a_id.to_string()); - let compression_type_a = crate::compression_engine::CompressionType::from_str(&item_a.compression)?; + let compression_type_a = + crate::compression_engine::CompressionType::from_str(&item_a.item.compression)?; log::debug!("MAIN: Item A has compression type {:?}", compression_type_a); let mut item_path_b = data_path.clone(); item_path_b.push(item_b_id.to_string()); - let compression_type_b = crate::compression_engine::CompressionType::from_str(&item_b.compression)?; + let compression_type_b = + crate::compression_engine::CompressionType::from_str(&item_b.item.compression)?; log::debug!("MAIN: Item B has compression type {:?}", compression_type_b); Ok((item_path_a, compression_type_a, item_path_b, compression_type_b)) @@ -306,21 +309,22 @@ pub fn mode_diff( tags: &mut Vec, conn: &mut rusqlite::Connection, data_path: std::path::PathBuf, -) -> Result<(), anyhow::Error> { +) -> Result<()> { validate_diff_args(cmd, ids, tags); - let (item_a, item_b) = fetch_and_validate_items(conn, ids)?; + let item_service = ItemService::new(data_path.clone()); + let (item_a, item_b) = fetch_and_validate_items(conn, ids, &item_service)?; - let item_a_tags = get_item_tags(conn, &item_a)?; - let item_b_tags = get_item_tags(conn, &item_b)?; + let item_a_tags: Vec = item_a.tags.iter().map(|t| t.name.clone()).collect(); + let item_b_tags: Vec = item_b.tags.iter().map(|t| t.name.clone()).collect(); - let (item_path_a, compression_type_a, item_path_b, compression_type_b) = + let (item_path_a, compression_type_a, item_path_b, compression_type_b) = setup_diff_paths_and_compression(&data_path, &item_a, &item_b)?; let ((fd_a_read, fd_a_write), (fd_b_read, fd_b_write)) = setup_diff_pipes()?; let (_fd_a_read_guard, _fd_b_read_guard) = setup_fd_guards(fd_a_read, fd_b_read); - let item_a_id = item_a.id.ok_or_else(|| anyhow::anyhow!("Item A missing ID"))?; - let item_b_id = item_b.id.ok_or_else(|| anyhow::anyhow!("Item B missing ID"))?; + let item_a_id = item_a.item.id.ok_or_else(|| anyhow::anyhow!("Item A missing ID"))?; + let item_b_id = item_b.item.id.ok_or_else(|| anyhow::anyhow!("Item B missing ID"))?; let mut child_process = spawn_diff_process( item_a_id,