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:
@@ -1,4 +1,4 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::os::fd::FromRawFd;
|
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::item_service::ItemService;
|
||||||
|
use crate::core::types::ItemWithMeta;
|
||||||
|
|
||||||
fn fetch_and_validate_items(
|
fn fetch_and_validate_items(
|
||||||
conn: &mut rusqlite::Connection,
|
conn: &mut rusqlite::Connection,
|
||||||
ids: &Vec<i64>,
|
ids: &Vec<i64>,
|
||||||
) -> Result<(crate::db::Item, crate::db::Item), anyhow::Error> {
|
item_service: &ItemService,
|
||||||
|
) -> Result<(ItemWithMeta, ItemWithMeta)> {
|
||||||
// Fetch items, ensuring they exist.
|
// Fetch items, ensuring they exist.
|
||||||
let item_a = crate::db::get_item(conn, ids[0])?
|
let item_a = item_service
|
||||||
.ok_or_else(|| anyhow::anyhow!("Unable to find first item (ID: {}) in database", ids[0]))?;
|
.get_item(conn, ids[0])
|
||||||
let item_b = crate::db::get_item(conn, ids[1])?
|
.with_context(|| format!("Unable to find first item (ID: {}) in database", ids[0]))?;
|
||||||
.ok_or_else(|| anyhow::anyhow!("Unable to find second item (ID: {}) in database", ids[1]))?;
|
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 A {:?}", item_a.item);
|
||||||
log::debug!("MAIN: Found item B {:?}", item_b);
|
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_a_id = item_a.item.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_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
|
// Validate that item IDs are positive to prevent path traversal issues
|
||||||
if item_a_id <= 0 || item_b_id <= 0 {
|
if item_a_id <= 0 || item_b_id <= 0 {
|
||||||
@@ -52,30 +56,29 @@ fn fetch_and_validate_items(
|
|||||||
Ok((item_a, item_b))
|
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(
|
fn setup_diff_paths_and_compression(
|
||||||
data_path: &std::path::PathBuf,
|
data_path: &std::path::PathBuf,
|
||||||
item_a: &crate::db::Item,
|
item_a: &ItemWithMeta,
|
||||||
item_b: &crate::db::Item,
|
item_b: &ItemWithMeta,
|
||||||
) -> Result<(std::path::PathBuf, crate::compression_engine::CompressionType, std::path::PathBuf, crate::compression_engine::CompressionType), anyhow::Error> {
|
) -> Result<(
|
||||||
let item_a_id = item_a.id.ok_or_else(|| anyhow::anyhow!("Item A missing ID"))?;
|
std::path::PathBuf,
|
||||||
let item_b_id = item_b.id.ok_or_else(|| anyhow::anyhow!("Item B missing ID"))?;
|
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();
|
let mut item_path_a = data_path.clone();
|
||||||
item_path_a.push(item_a_id.to_string());
|
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);
|
log::debug!("MAIN: Item A has compression type {:?}", compression_type_a);
|
||||||
|
|
||||||
let mut item_path_b = data_path.clone();
|
let mut item_path_b = data_path.clone();
|
||||||
item_path_b.push(item_b_id.to_string());
|
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);
|
log::debug!("MAIN: Item B has compression type {:?}", compression_type_b);
|
||||||
|
|
||||||
Ok((item_path_a, compression_type_a, item_path_b, 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<String>,
|
tags: &mut Vec<String>,
|
||||||
conn: &mut rusqlite::Connection,
|
conn: &mut rusqlite::Connection,
|
||||||
data_path: std::path::PathBuf,
|
data_path: std::path::PathBuf,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<()> {
|
||||||
validate_diff_args(cmd, ids, tags);
|
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_a_tags: Vec<String> = item_a.tags.iter().map(|t| t.name.clone()).collect();
|
||||||
let item_b_tags = get_item_tags(conn, &item_b)?;
|
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) =
|
let (item_path_a, compression_type_a, item_path_b, compression_type_b) =
|
||||||
setup_diff_paths_and_compression(&data_path, &item_a, &item_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, 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 (_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_a_id = item_a.item.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_b_id = item_b.item.id.ok_or_else(|| anyhow::anyhow!("Item B missing ID"))?;
|
||||||
|
|
||||||
let mut child_process = spawn_diff_process(
|
let mut child_process = spawn_diff_process(
|
||||||
item_a_id,
|
item_a_id,
|
||||||
|
|||||||
Reference in New Issue
Block a user