feat: add diff mode to compare items

This commit is contained in:
Andrew Phillips
2025-05-06 11:00:35 -03:00
committed by Andrew Phillips (aider)
parent f39a781caf
commit c1e04fc9c5

View File

@@ -34,6 +34,7 @@ extern crate lazy_static;
pub mod compression;
pub mod db;
//pub mod item;
use compression::CompressionType;
use compression::program::CompressionEngineProgram;
@@ -87,31 +88,35 @@ struct Args {
#[derive(Parser, Debug)]
struct ModeArgs {
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["get", "list", "update", "delete", "info", "status"]))]
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["get", "diff", "list", "update", "delete", "info", "status"]))]
#[arg(help("Save an item using any tags or metadata provided"))]
save: bool,
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "list", "update", "delete", "info", "status"]))]
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "diff", "list", "update", "delete", "info", "status"]))]
#[arg(help("Get an item either by it's ID or by a combination of matching tags and metatdata"))]
get: bool,
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "update", "delete", "info", "status"]))]
#[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "list", "update", "delete", "info", "status"]))]
#[arg(help("Show a diff between two items by ID"))]
diff: bool,
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "update", "delete", "info", "status"]))]
#[arg(help("List items, filtering on tags or metadata if given"))]
list: bool,
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "list", "delete", "info", "status"]), requires("ids_or_tags"))]
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "status"]), requires("ids_or_tags"))]
#[arg(help("Update a specified item ID's tags and/or metadata"))]
update: bool,
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "list", "update", "info", "status"]), requires("ids_or_tags"))]
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "update", "info", "status"]), requires("ids_or_tags"))]
#[arg(help("Delete items either by ID or by matching tags"))]
delete: bool,
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "list", "update", "delete", "status"]), requires("ids_or_tags"))]
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "update", "delete", "status"]), requires("ids_or_tags"))]
#[arg(help("Get an item either by it's ID or by a combination of matching tags and metatdata"))]
info: bool,
#[arg(group("mode"), help_heading("Mode Options"), short('S'), long, conflicts_with_all(["save", "get", "list", "update", "delete", "info"]))]
#[arg(group("mode"), help_heading("Mode Options"), short('S'), long, conflicts_with_all(["save", "get", "diff", "list", "update", "delete", "info"]))]
#[arg(help("Show status of directories and supported compression algorithms"))]
status: bool
}
@@ -148,7 +153,7 @@ struct OptionsArgs {
verbose: u8,
#[arg(short, long)]
#[arg(help("Do show any messages"))]
#[arg(help("Do not show any messages"))]
quiet: bool,
}
@@ -158,6 +163,7 @@ enum KeepModes {
Unknown,
Save,
Get,
Diff,
List,
Update,
Delete,
@@ -248,6 +254,8 @@ fn main() -> Result<(), Error> {
mode = KeepModes::Save;
} else if args.mode.get {
mode = KeepModes::Get;
} else if args.mode.diff {
mode = KeepModes::Diff;
} else if args.mode.list {
mode = KeepModes::List;
} else if args.mode.delete {
@@ -302,6 +310,7 @@ fn main() -> Result<(), Error> {
match mode {
KeepModes::Save => mode_save(&mut cmd, args, ids, tags, conn, data_path)?,
KeepModes::Get => mode_get(&mut cmd, args, ids, tags, &mut conn, data_path)?,
KeepModes::Diff => mode_diff(&mut cmd, args, ids, tags, &mut conn, data_path)?,
KeepModes::List => mode_list(&mut cmd, args, ids, tags, &mut conn, data_path)?,
KeepModes::Update => mode_update(&mut cmd, args, ids, tags, &mut conn, data_path)?,
KeepModes::Info => mode_info(&mut cmd, args, ids, tags, &mut conn, data_path)?,
@@ -470,6 +479,56 @@ fn mode_get(cmd: &mut Command, args: Args, ids: &mut Vec<i64>, tags: &mut Vec<St
}
fn mode_diff(cmd: &mut Command, args: Args, ids: &mut Vec<i64>, tags: &mut Vec<String>, conn: &mut Connection, data_path: PathBuf) -> Result<()> {
if ! tags.is_empty() {
cmd.error(ErrorKind::InvalidValue, "Tags given, you must supply exactly two IDs when using --diff").exit();
} else if ids.len() > 2 || ids.len() < 1 {
cmd.error(ErrorKind::InvalidValue, "You must supply exactly one or two IDs when using --diff").exit();
}
let item_a: Option<db::Item> = db::get_item(conn, ids[0])?;
let mut item_b: Option<db::Item> = None;
if ids.len() == 2 {
item_b = db::get_item(conn, ids[1])?;
}
if let Some(item_a) = item_a {
debug!("MAIN: Found item A {:?}", item_a);
let mut item_path_a = data_path.clone();
item_path_a.push(item_a.id.unwrap().to_string());
let compression_type_a = CompressionType::from_str(&item_a.compression)?;
debug!("MAIN: Item A has compression type {:?}", compression_type_a.clone());
let compression_engine_a = compression::get_engine(compression_type_a).expect("Unable to get compression engine");
if let Some(item_b) = item_b {
debug!("MAIN: Found item B {:?}", item_b);
let mut item_path_b = data_path.clone();
item_path_b.push(item_b.id.unwrap().to_string());
let compression_type_b = CompressionType::from_str(&item_b.compression)?;
debug!("MAIN: Item B has compression type {:?}", compression_type_b.clone());
let compression_engine_b = compression::get_engine(compression_type_b).expect("Unable to get compression engine");
let program = "diff";
let args = ["-u"];
Ok(())
} else {
Err(anyhow!("Unable to find second item in database"))
}
} else {
Err(anyhow!("Unable to find first item in database"))
}
}
fn mode_list(cmd: &mut Command, args: Args, ids: &mut Vec<i64>, tags: &Vec<String>, conn: &mut Connection, data_path: PathBuf) -> Result<()> {
if ! ids.is_empty() {
cmd.error(ErrorKind::InvalidValue, "ID given, you can only supply tags when using --list").exit();
@@ -907,7 +966,6 @@ fn format_size_human_readable(size: u64) -> String {
humansize::format_size(size, options)
}
fn format_size(size: u64, human_readable: bool) -> String {
match human_readable {
true => format_size_human_readable(size),