refactor: update diff mode to use ItemService and ItemWithMeta

Co-authored-by: aider (openai/andrew/openrouter/google/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
Andrew Phillips
2025-08-25 12:31:36 -03:00
parent 89fa9bee6f
commit a0c8363852

View File

@@ -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<i64>, tags: &Vec<String>) {
}
use crate::core::item_service::ItemService;
use crate::core::types::ItemWithMeta;
fn fetch_and_validate_items(
conn: &mut rusqlite::Connection,
ids: &Vec<i64>,
) -> 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<Vec<String>> {
let tags: Vec<String> = 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,12 +309,13 @@ pub fn mode_diff(
tags: &mut Vec<String>,
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<String> = item_a.tags.iter().map(|t| t.name.clone()).collect();
let item_b_tags: Vec<String> = item_b.tags.iter().map(|t| t.name.clone()).collect();
let (item_path_a, compression_type_a, item_path_b, compression_type_b) =
setup_diff_paths_and_compression(&data_path, &item_a, &item_b)?;
@@ -319,8 +323,8 @@ pub fn mode_diff(
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,