Added WIP initial toml merging

This commit is contained in:
Warren Hood 2024-10-09 00:42:50 +02:00
parent 0af0d62639
commit 4d7f6ed14e

View file

@ -244,8 +244,119 @@ fn test_merge_yaml() {
);
}
fn merge_toml(
src: &toml::Value,
dst: &mut toml::Value,
overwrite_existing: bool,
) -> anyhow::Result<()> {
if src.is_table() && dst.is_table() {
let src = src.as_table().unwrap();
let dst = dst.as_table_mut().unwrap();
for (k, v) in src.iter() {
if v.is_table() {
let dst_v = dst.entry(k.clone()).or_insert(serde_yaml::from_str("{}")?);
merge_toml(v, dst_v, overwrite_existing)?;
} else {
if overwrite_existing || !dst.contains_key(k) {
dst.insert(k.clone(), v.clone());
}
}
}
} else {
// TODO: Keep track of path for better errors
anyhow::bail!("Cannot merge non-objects: {src:#?} and {dst:#?}")
}
Ok(())
}
#[test]
fn test_merge_toml() {
let src: toml::Value = toml::from_str(
r#"
a = 3
[b]
[b.x]
[b.y]
test = "thing"
[c]
"#,
)
.unwrap();
let mut dst: toml::Value = toml::from_str(
r#"
[b]
[b.y]
test = "something"
[c]
foo = "bar"
"#,
)
.unwrap();
let mut merged_overwrite = dst.clone();
let mut merged_retained = dst.clone();
merge_toml(&src, &mut merged_overwrite, true).unwrap();
merge_toml(&src, &mut merged_retained, false).unwrap();
assert!(
merged_overwrite["b"]["y"]["test"] == "thing".into(),
"//b/y/test wasn't overwritten with \"thing\". src={:#?}, dst={:#?}",
src,
merged_overwrite
);
assert!(
merged_overwrite["a"] == 3.into(),
"//a was not set to 3. src={:#?}, dst={:#?}",
src,
merged_overwrite
);
assert!(
merged_overwrite["b"]["x"].is_table(),
"//b/x is not a mapping. src={:#?}, dst={:#?}",
src,
merged_overwrite
);
assert!(
merged_overwrite["c"]["foo"] == "bar".into(),
"//c/foo != bar. src={:#?}, dst={:#?}",
src,
merged_overwrite
);
assert!(
merged_retained["b"]["y"]["test"] == "something".into(),
"//b/y/test was overwritten. src={:#?}, dst={:#?}",
src,
merged_retained
);
assert!(
merged_retained["a"] == 3.into(),
"//a was not set to 3. src={:#?}, dst={:#?}",
src,
merged_retained
);
assert!(
merged_retained["b"]["x"].is_table(),
"//b/x is not a mapping. src={:#?}, dst={:#?}",
src,
merged_retained
);
assert!(
merged_retained["c"]["foo"] == "bar".into(),
"//c/foo != bar. src={:#?}, dst={:#?}",
src,
merged_retained
);
}
/// Merge `src` into `dst` if it is a supported file type
fn merge_files(
pub fn merge_files(
src: &str,
dst: &str,
overwrite_existing: bool,
@ -264,6 +375,11 @@ fn merge_files(
merge_yaml(&src_val, &mut dst_val, overwrite_existing)?;
serde_yaml::to_string(&dst_val)?
}
FileType::Toml => todo!(),
FileType::Toml => {
let src_val: toml::Value = toml::from_str(src)?;
let mut dst_val: toml::Value = toml::from_str(dst)?;
merge_toml(&src_val, &mut dst_val, overwrite_existing)?;
dst_val.to_string()
}
})
}