mirror of
https://github.com/encounter/objdiff.git
synced 2025-12-09 13:37:55 +00:00
Support overriding diff options in project config (& for individual units) (#263)
* Support loading diff options from project config * Support per-unit option overrides
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
pub mod path;
|
||||
|
||||
use alloc::{
|
||||
borrow::Cow,
|
||||
collections::BTreeMap,
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
@@ -45,6 +46,8 @@ pub struct ProjectConfig {
|
||||
pub units: Option<Vec<ProjectObject>>,
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub progress_categories: Option<Vec<ProjectProgressCategory>>,
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub options: Option<ProjectOptions>,
|
||||
}
|
||||
|
||||
impl ProjectConfig {
|
||||
@@ -116,6 +119,8 @@ pub struct ProjectObject {
|
||||
pub metadata: Option<ProjectObjectMetadata>,
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub symbol_mappings: Option<BTreeMap<String, String>>,
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub options: Option<ProjectOptions>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
@@ -143,6 +148,15 @@ pub struct ProjectProgressCategory {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
pub type ProjectOptions = BTreeMap<String, ProjectOptionValue>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(untagged))]
|
||||
pub enum ProjectOptionValue {
|
||||
Bool(bool),
|
||||
String(String),
|
||||
}
|
||||
|
||||
impl ProjectObject {
|
||||
pub fn name(&self) -> &str {
|
||||
if let Some(name) = &self.name {
|
||||
@@ -179,6 +193,8 @@ impl ProjectObject {
|
||||
pub fn auto_generated(&self) -> Option<bool> {
|
||||
self.metadata.as_ref().and_then(|m| m.auto_generated)
|
||||
}
|
||||
|
||||
pub fn options(&self) -> Option<&ProjectOptions> { self.options.as_ref() }
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Eq, PartialEq)]
|
||||
@@ -310,3 +326,47 @@ pub fn build_globset(vec: &[Glob]) -> Result<GlobSet, globset::Error> {
|
||||
}
|
||||
builder.build()
|
||||
}
|
||||
|
||||
#[cfg(feature = "any-arch")]
|
||||
pub fn apply_project_options(
|
||||
diff_config: &mut crate::diff::DiffObjConfig,
|
||||
options: &ProjectOptions,
|
||||
) -> Result<()> {
|
||||
use core::str::FromStr;
|
||||
|
||||
use crate::diff::{ConfigEnum, ConfigPropertyId, ConfigPropertyKind};
|
||||
|
||||
let mut result = Ok(());
|
||||
for (key, value) in options.iter() {
|
||||
let property_id = ConfigPropertyId::from_str(key)
|
||||
.map_err(|()| anyhow!("Invalid configuration property: {key}"))?;
|
||||
let value = match value {
|
||||
ProjectOptionValue::Bool(value) => Cow::Borrowed(if *value { "true" } else { "false" }),
|
||||
ProjectOptionValue::String(value) => Cow::Borrowed(value.as_str()),
|
||||
};
|
||||
if diff_config.set_property_value_str(property_id, &value).is_err() {
|
||||
if result.is_err() {
|
||||
// Already returning an error, skip further errors
|
||||
continue;
|
||||
}
|
||||
let mut expected = String::new();
|
||||
match property_id.kind() {
|
||||
ConfigPropertyKind::Boolean => expected.push_str("true, false"),
|
||||
ConfigPropertyKind::Choice(variants) => {
|
||||
for (idx, variant) in variants.iter().enumerate() {
|
||||
if idx > 0 {
|
||||
expected.push_str(", ");
|
||||
}
|
||||
expected.push_str(variant.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
result = Err(anyhow!(
|
||||
"Invalid value for {}. Expected one of: {}",
|
||||
property_id.name(),
|
||||
expected
|
||||
));
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user