From 39b1b4998564d26abfc395f865c2930115fa5200 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 22 Apr 2025 18:13:00 -0600 Subject: [PATCH] cli: Add --config arg to report generate --- objdiff-cli/src/cmd/diff.rs | 30 +++--------------------------- objdiff-cli/src/cmd/mod.rs | 31 +++++++++++++++++++++++++++++++ objdiff-cli/src/cmd/report.rs | 27 +++++++++++++++++---------- 3 files changed, 51 insertions(+), 37 deletions(-) diff --git a/objdiff-cli/src/cmd/diff.rs b/objdiff-cli/src/cmd/diff.rs index 30d501c..0d79f35 100644 --- a/objdiff-cli/src/cmd/diff.rs +++ b/objdiff-cli/src/cmd/diff.rs @@ -1,7 +1,6 @@ use std::{ io::stdout, mem, - str::FromStr, sync::{ Arc, atomic::{AtomicBool, Ordering}, @@ -29,10 +28,7 @@ use objdiff_core::{ ProjectConfig, ProjectObject, ProjectObjectMetadata, build_globset, path::{check_path_buf, platform_path, platform_path_serde_option}, }, - diff::{ - self, ConfigEnum, ConfigPropertyId, ConfigPropertyKind, DiffObjConfig, MappingConfig, - ObjectDiff, - }, + diff::{self, DiffObjConfig, MappingConfig, ObjectDiff}, jobs::{ Job, JobQueue, JobResult, objdiff::{ObjDiffConfig, start_build}, @@ -43,6 +39,7 @@ use ratatui::prelude::*; use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf}; use crate::{ + cmd::apply_config_args, util::{ output::{OutputFormat, write_output}, term::crossterm_panic_handler, @@ -183,28 +180,7 @@ pub fn run(args: Args) -> Result<()> { fn build_config_from_args(args: &Args) -> Result<(DiffObjConfig, MappingConfig)> { let mut diff_config = DiffObjConfig::default(); - for config in &args.config { - let (key, value) = config.split_once('=').context("--config expects \"key=value\"")?; - let property_id = ConfigPropertyId::from_str(key) - .map_err(|()| anyhow!("Invalid configuration property: {}", key))?; - diff_config.set_property_value_str(property_id, value).map_err(|()| { - let mut options = String::new(); - match property_id.kind() { - ConfigPropertyKind::Boolean => { - options = "true, false".to_string(); - } - ConfigPropertyKind::Choice(variants) => { - for (i, variant) in variants.iter().enumerate() { - if i > 0 { - options.push_str(", "); - } - options.push_str(variant.value); - } - } - } - anyhow!("Invalid value for {}. Expected one of: {}", property_id.name(), options) - })?; - } + apply_config_args(&mut diff_config, &args.config)?; let mut mapping_config = MappingConfig { mappings: Default::default(), selecting_left: args.selecting_left.clone(), diff --git a/objdiff-cli/src/cmd/mod.rs b/objdiff-cli/src/cmd/mod.rs index 406f9dc..95417cb 100644 --- a/objdiff-cli/src/cmd/mod.rs +++ b/objdiff-cli/src/cmd/mod.rs @@ -1,2 +1,33 @@ pub mod diff; pub mod report; + +use std::str::FromStr; + +use anyhow::{Context, Result, anyhow}; +use objdiff_core::diff::{ConfigEnum, ConfigPropertyId, ConfigPropertyKind, DiffObjConfig}; + +pub fn apply_config_args(diff_config: &mut DiffObjConfig, args: &[String]) -> Result<()> { + for config in args { + let (key, value) = config.split_once('=').context("--config expects \"key=value\"")?; + let property_id = ConfigPropertyId::from_str(key) + .map_err(|()| anyhow!("Invalid configuration property: {}", key))?; + diff_config.set_property_value_str(property_id, value).map_err(|()| { + let mut options = String::new(); + match property_id.kind() { + ConfigPropertyKind::Boolean => { + options = "true, false".to_string(); + } + ConfigPropertyKind::Choice(variants) => { + for (i, variant) in variants.iter().enumerate() { + if i > 0 { + options.push_str(", "); + } + options.push_str(variant.value); + } + } + } + anyhow!("Invalid value for {}. Expected one of: {}", property_id.name(), options) + })?; + } + Ok(()) +} diff --git a/objdiff-cli/src/cmd/report.rs b/objdiff-cli/src/cmd/report.rs index 3510d39..d760e74 100644 --- a/objdiff-cli/src/cmd/report.rs +++ b/objdiff-cli/src/cmd/report.rs @@ -17,7 +17,7 @@ use tracing::{info, warn}; use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf}; use crate::{ - cmd::diff::ObjectConfig, + cmd::{apply_config_args, diff::ObjectConfig}, util::output::{OutputFormat, write_output}, }; @@ -52,6 +52,9 @@ pub struct GenerateArgs { #[argp(option, short = 'f')] /// Output format (json, json-pretty, proto) (default: json) format: Option, + #[argp(option, short = 'c')] + /// Configuration property (key=value) + config: Vec, } #[derive(FromArgs, PartialEq, Debug)] @@ -80,6 +83,12 @@ pub fn run(args: Args) -> Result<()> { } fn generate(args: GenerateArgs) -> Result<()> { + let mut diff_config = diff::DiffObjConfig { + function_reloc_diffs: diff::FunctionRelocDiffs::None, + ..Default::default() + }; + apply_config_args(&mut diff_config, &args.config)?; + let output_format = OutputFormat::from_option(args.format.as_deref())?; let project_dir = args.project.as_deref().unwrap_or_else(|| Utf8PlatformPath::new(".")); info!("Loading project {}", project_dir); @@ -114,14 +123,15 @@ fn generate(args: GenerateArgs) -> Result<()> { if args.deduplicate { // If deduplicating, we need to run single-threaded for object in &objects { - if let Some(unit) = report_object(object, Some(&mut existing_functions))? { + if let Some(unit) = report_object(object, &diff_config, Some(&mut existing_functions))? + { units.push(unit); } } } else { let vec = objects .par_iter() - .map(|object| report_object(object, None)) + .map(|object| report_object(object, &diff_config, None)) .collect::>>>()?; units = vec.into_iter().flatten().collect(); } @@ -145,6 +155,7 @@ fn generate(args: GenerateArgs) -> Result<()> { fn report_object( object: &ObjectConfig, + diff_config: &diff::DiffObjConfig, mut existing_functions: Option<&mut HashSet>, ) -> Result> { match (&object.target_path, &object.base_path) { @@ -158,16 +169,12 @@ fn report_object( } _ => {} } - let diff_config = diff::DiffObjConfig { - function_reloc_diffs: diff::FunctionRelocDiffs::None, - ..Default::default() - }; let mapping_config = diff::MappingConfig::default(); let target = object .target_path .as_ref() .map(|p| { - obj::read::read(p.as_ref(), &diff_config) + obj::read::read(p.as_ref(), diff_config) .with_context(|| format!("Failed to open {}", p)) }) .transpose()?; @@ -175,12 +182,12 @@ fn report_object( .base_path .as_ref() .map(|p| { - obj::read::read(p.as_ref(), &diff_config) + obj::read::read(p.as_ref(), diff_config) .with_context(|| format!("Failed to open {}", p)) }) .transpose()?; let result = - diff::diff_objs(target.as_ref(), base.as_ref(), None, &diff_config, &mapping_config)?; + diff::diff_objs(target.as_ref(), base.as_ref(), None, diff_config, &mapping_config)?; let metadata = ReportUnitMetadata { complete: object.metadata.complete,