mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-04 19:45:34 +08:00
fix(codex): show custom config before common config in merge preview
Replace deep_merge_toml with deep_merge_toml_preserve_order so that custom config keys appear at the top and common-only keys appear below.
This commit is contained in:
@@ -199,32 +199,35 @@ pub fn extract_json_difference(
|
|||||||
// TOML Configuration Merge Functions
|
// TOML Configuration Merge Functions
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
/// Deep merge two TOML tables where `source` overrides `target`.
|
/// Deep merge TOML tables while preserving target's key order (custom first, then common).
|
||||||
fn deep_merge_toml(target: &mut TomlValue, source: &TomlValue) {
|
///
|
||||||
// First check if both are tables without destructuring
|
/// - Keeps target's existing values (target = custom config has priority)
|
||||||
|
/// - Only adds keys from source that don't exist in target (common-only keys)
|
||||||
|
/// - For nested tables, recursively merges while preserving target's keys first
|
||||||
|
fn deep_merge_toml_preserve_order(target: &mut TomlValue, source: &TomlValue) {
|
||||||
let both_tables =
|
let both_tables =
|
||||||
matches!(target, TomlValue::Table(_)) && matches!(source, TomlValue::Table(_));
|
matches!(target, TomlValue::Table(_)) && matches!(source, TomlValue::Table(_));
|
||||||
|
|
||||||
if both_tables {
|
if both_tables {
|
||||||
// Safe to destructure now since we know both are tables
|
|
||||||
if let (TomlValue::Table(target_map), TomlValue::Table(source_map)) = (target, source) {
|
if let (TomlValue::Table(target_map), TomlValue::Table(source_map)) = (target, source) {
|
||||||
for (key, source_value) in source_map {
|
for (key, source_value) in source_map {
|
||||||
match target_map.get_mut(key) {
|
match target_map.get_mut(key) {
|
||||||
Some(target_value) if target_value.is_table() && source_value.is_table() => {
|
Some(target_value) if target_value.is_table() && source_value.is_table() => {
|
||||||
// Nested table: recursive merge
|
// Nested table: recursive merge (preserving target's keys first)
|
||||||
deep_merge_toml(target_value, source_value);
|
deep_merge_toml_preserve_order(target_value, source_value);
|
||||||
}
|
}
|
||||||
_ => {
|
Some(_) => {
|
||||||
// Other cases: source overrides
|
// Key exists in target: keep target's value (custom overrides common)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// Key only in source: add to target (common-only keys appear after)
|
||||||
target_map.insert(key.clone(), source_value.clone());
|
target_map.insert(key.clone(), source_value.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Non-table: source overrides
|
|
||||||
*target = source.clone();
|
|
||||||
}
|
}
|
||||||
|
// Non-table case: keep target as-is (custom has priority)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute final TOML config.
|
/// Compute final TOML config.
|
||||||
@@ -278,11 +281,12 @@ pub fn compute_final_toml_config_str(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Start with common config as base
|
// Start with custom config (so custom keys appear first in output)
|
||||||
let mut result = common_config;
|
let mut result = custom_config;
|
||||||
|
|
||||||
// Merge custom config on top
|
// Add common config keys that don't exist in custom (these appear after custom keys)
|
||||||
deep_merge_toml(&mut result, &custom_config);
|
// Custom values always take priority (they're already in result)
|
||||||
|
deep_merge_toml_preserve_order(&mut result, &common_config);
|
||||||
|
|
||||||
// Serialize back to TOML string
|
// Serialize back to TOML string
|
||||||
match toml::to_string_pretty(&result) {
|
match toml::to_string_pretty(&result) {
|
||||||
@@ -832,6 +836,19 @@ shared_key = "shared"
|
|||||||
assert!(error.is_none());
|
assert!(error.is_none());
|
||||||
assert!(result.contains("custom-model")); // custom wins
|
assert!(result.contains("custom-model")); // custom wins
|
||||||
assert!(result.contains("shared_key")); // from common
|
assert!(result.contains("shared_key")); // from common
|
||||||
|
|
||||||
|
// Verify ordering: custom keys appear before common-only keys
|
||||||
|
let model_pos = result.find("model").unwrap();
|
||||||
|
let custom_section_pos = result.find("custom_section").unwrap();
|
||||||
|
let shared_key_pos = result.find("shared_key").unwrap();
|
||||||
|
assert!(
|
||||||
|
model_pos < shared_key_pos,
|
||||||
|
"custom 'model' should appear before common-only 'shared_key'"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
custom_section_pos < shared_key_pos || model_pos < shared_key_pos,
|
||||||
|
"custom keys should appear before common-only keys"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user