mirror of
				https://github.com/WarrenHood/MCModpackManager.git
				synced 2025-11-04 12:38:40 +00:00 
			
		
		
		
	Added WIP support for merging yaml files
This commit is contained in:
		
							parent
							
								
									3e56632ef0
								
							
						
					
					
						commit
						0af0d62639
					
				
							
								
								
									
										20
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										20
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| 
						 | 
					@ -2075,6 +2075,7 @@ dependencies = [
 | 
				
			||||||
 "semver",
 | 
					 "semver",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
 | 
					 "serde_yaml",
 | 
				
			||||||
 "sha1",
 | 
					 "sha1",
 | 
				
			||||||
 "sha2",
 | 
					 "sha2",
 | 
				
			||||||
 "tempfile",
 | 
					 "tempfile",
 | 
				
			||||||
| 
						 | 
					@ -3237,6 +3238,19 @@ dependencies = [
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "serde_yaml"
 | 
				
			||||||
 | 
					version = "0.9.34+deprecated"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "indexmap",
 | 
				
			||||||
 | 
					 "itoa",
 | 
				
			||||||
 | 
					 "ryu",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "unsafe-libyaml",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "sha1"
 | 
					name = "sha1"
 | 
				
			||||||
version = "0.10.6"
 | 
					version = "0.10.6"
 | 
				
			||||||
| 
						 | 
					@ -3923,6 +3937,12 @@ version = "0.2.5"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a"
 | 
					checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "unsafe-libyaml"
 | 
				
			||||||
 | 
					version = "0.2.11"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "untrusted"
 | 
					name = "untrusted"
 | 
				
			||||||
version = "0.9.0"
 | 
					version = "0.9.0"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ reqwest = { version = "0.12.5", features = ["json"] }
 | 
				
			||||||
semver = { version = "1.0.23", features = ["serde"] }
 | 
					semver = { version = "1.0.23", features = ["serde"] }
 | 
				
			||||||
serde = { version = "1.0.207", features = ["derive"] }
 | 
					serde = { version = "1.0.207", features = ["derive"] }
 | 
				
			||||||
serde_json = "1.0.128"
 | 
					serde_json = "1.0.128"
 | 
				
			||||||
 | 
					serde_yaml = "0.9.34"
 | 
				
			||||||
sha1 = "0.10.6"
 | 
					sha1 = "0.10.6"
 | 
				
			||||||
sha2 = "0.10.8"
 | 
					sha2 = "0.10.8"
 | 
				
			||||||
tempfile = "3.12.0"
 | 
					tempfile = "3.12.0"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
use std::{any::Any, default, str::FromStr};
 | 
					use std::str::FromStr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Copy)]
 | 
					#[derive(Debug, Clone, Copy)]
 | 
				
			||||||
pub enum FileType {
 | 
					pub enum FileType {
 | 
				
			||||||
| 
						 | 
					@ -81,50 +81,164 @@ fn test_merge_json() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert!(
 | 
					    assert!(
 | 
				
			||||||
        merged_overwrite["b"]["y"]["test"] == "thing",
 | 
					        merged_overwrite["b"]["y"]["test"] == "thing",
 | 
				
			||||||
        "//b/y/test wasn't overwritten with \"thing\". src={}, dst={}",
 | 
					        "//b/y/test wasn't overwritten with \"thing\". src={:#?}, dst={:#?}",
 | 
				
			||||||
        src,
 | 
					        src,
 | 
				
			||||||
        merged_overwrite
 | 
					        merged_overwrite
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    assert!(
 | 
					    assert!(
 | 
				
			||||||
        merged_overwrite["a"] == 3,
 | 
					        merged_overwrite["a"] == 3,
 | 
				
			||||||
        "//a was not set to 3. src={}, dst={}",
 | 
					        "//a was not set to 3. src={:#?}, dst={:#?}",
 | 
				
			||||||
        src,
 | 
					        src,
 | 
				
			||||||
        merged_overwrite
 | 
					        merged_overwrite
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    assert!(
 | 
					    assert!(
 | 
				
			||||||
        merged_overwrite["b"]["x"].is_object(),
 | 
					        merged_overwrite["b"]["x"].is_object(),
 | 
				
			||||||
        "//b/x is not an object. src={}, dst={}",
 | 
					        "//b/x is not an object. src={:#?}, dst={:#?}",
 | 
				
			||||||
        src,
 | 
					        src,
 | 
				
			||||||
        merged_overwrite
 | 
					        merged_overwrite
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    assert!(
 | 
					    assert!(
 | 
				
			||||||
        merged_overwrite["c"]["foo"] == "bar",
 | 
					        merged_overwrite["c"]["foo"] == "bar",
 | 
				
			||||||
        "//c/foo != bar. src={}, dst={}",
 | 
					        "//c/foo != bar. src={:#?}, dst={:#?}",
 | 
				
			||||||
        src,
 | 
					        src,
 | 
				
			||||||
        merged_overwrite
 | 
					        merged_overwrite
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert!(
 | 
					    assert!(
 | 
				
			||||||
        merged_retained["b"]["y"]["test"] == "something",
 | 
					        merged_retained["b"]["y"]["test"] == "something",
 | 
				
			||||||
        "//b/y/test was overwritten. src={}, dst={}",
 | 
					        "//b/y/test was overwritten. src={:#?}, dst={:#?}",
 | 
				
			||||||
        src,
 | 
					        src,
 | 
				
			||||||
        merged_retained
 | 
					        merged_retained
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    assert!(
 | 
					    assert!(
 | 
				
			||||||
        merged_retained["a"] == 3,
 | 
					        merged_retained["a"] == 3,
 | 
				
			||||||
        "//a was not set to 3. src={}, dst={}",
 | 
					        "//a was not set to 3. src={:#?}, dst={:#?}",
 | 
				
			||||||
        src,
 | 
					        src,
 | 
				
			||||||
        merged_retained
 | 
					        merged_retained
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    assert!(
 | 
					    assert!(
 | 
				
			||||||
        merged_retained["b"]["x"].is_object(),
 | 
					        merged_retained["b"]["x"].is_object(),
 | 
				
			||||||
        "//b/x is not an object. src={}, dst={}",
 | 
					        "//b/x is not an object. src={:#?}, dst={:#?}",
 | 
				
			||||||
        src,
 | 
					        src,
 | 
				
			||||||
        merged_retained
 | 
					        merged_retained
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    assert!(
 | 
					    assert!(
 | 
				
			||||||
        merged_retained["c"]["foo"] == "bar",
 | 
					        merged_retained["c"]["foo"] == "bar",
 | 
				
			||||||
        "//c/foo != bar. src={}, dst={}",
 | 
					        "//c/foo != bar. src={:#?}, dst={:#?}",
 | 
				
			||||||
 | 
					        src,
 | 
				
			||||||
 | 
					        merged_retained
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn merge_yaml(
 | 
				
			||||||
 | 
					    src: &serde_yaml::Value,
 | 
				
			||||||
 | 
					    dst: &mut serde_yaml::Value,
 | 
				
			||||||
 | 
					    overwrite_existing: bool,
 | 
				
			||||||
 | 
					) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    if src.is_mapping() && dst.is_mapping() {
 | 
				
			||||||
 | 
					        let src = src.as_mapping().unwrap();
 | 
				
			||||||
 | 
					        let dst = dst.as_mapping_mut().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (k, v) in src.iter() {
 | 
				
			||||||
 | 
					            if v.is_mapping() {
 | 
				
			||||||
 | 
					                let dst_v = dst.entry(k.clone()).or_insert(serde_yaml::from_str("{}")?);
 | 
				
			||||||
 | 
					                merge_yaml(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_yaml() {
 | 
				
			||||||
 | 
					    let src = serde_yaml::from_str(
 | 
				
			||||||
 | 
					        r#"{
 | 
				
			||||||
 | 
					        "a": 3,
 | 
				
			||||||
 | 
					        "b": {
 | 
				
			||||||
 | 
					            "x": {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "y": {
 | 
				
			||||||
 | 
					                "test": "thing"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "c": {}
 | 
				
			||||||
 | 
					    }"#,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let dst: serde_yaml::Value = serde_yaml::from_str(
 | 
				
			||||||
 | 
					        r#"{
 | 
				
			||||||
 | 
					        "b": {
 | 
				
			||||||
 | 
					            "y": {
 | 
				
			||||||
 | 
					                "test": "something"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "c": {
 | 
				
			||||||
 | 
					            "foo": "bar"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }"#,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut merged_overwrite = dst.clone();
 | 
				
			||||||
 | 
					    let mut merged_retained = dst.clone();
 | 
				
			||||||
 | 
					    merge_yaml(&src, &mut merged_overwrite, true).unwrap();
 | 
				
			||||||
 | 
					    merge_yaml(&src, &mut merged_retained, false).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert!(
 | 
				
			||||||
 | 
					        merged_overwrite["b"]["y"]["test"] == "thing",
 | 
				
			||||||
 | 
					        "//b/y/test wasn't overwritten with \"thing\". src={:#?}, dst={:#?}",
 | 
				
			||||||
 | 
					        src,
 | 
				
			||||||
 | 
					        merged_overwrite
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert!(
 | 
				
			||||||
 | 
					        merged_overwrite["a"] == 3,
 | 
				
			||||||
 | 
					        "//a was not set to 3. src={:#?}, dst={:#?}",
 | 
				
			||||||
 | 
					        src,
 | 
				
			||||||
 | 
					        merged_overwrite
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert!(
 | 
				
			||||||
 | 
					        merged_overwrite["b"]["x"].is_mapping(),
 | 
				
			||||||
 | 
					        "//b/x is not a mapping. src={:#?}, dst={:#?}",
 | 
				
			||||||
 | 
					        src,
 | 
				
			||||||
 | 
					        merged_overwrite
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert!(
 | 
				
			||||||
 | 
					        merged_overwrite["c"]["foo"] == "bar",
 | 
				
			||||||
 | 
					        "//c/foo != bar. src={:#?}, dst={:#?}",
 | 
				
			||||||
 | 
					        src,
 | 
				
			||||||
 | 
					        merged_overwrite
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert!(
 | 
				
			||||||
 | 
					        merged_retained["b"]["y"]["test"] == "something",
 | 
				
			||||||
 | 
					        "//b/y/test was overwritten. src={:#?}, dst={:#?}",
 | 
				
			||||||
 | 
					        src,
 | 
				
			||||||
 | 
					        merged_retained
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert!(
 | 
				
			||||||
 | 
					        merged_retained["a"] == 3,
 | 
				
			||||||
 | 
					        "//a was not set to 3. src={:#?}, dst={:#?}",
 | 
				
			||||||
 | 
					        src,
 | 
				
			||||||
 | 
					        merged_retained
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert!(
 | 
				
			||||||
 | 
					        merged_retained["b"]["x"].is_mapping(),
 | 
				
			||||||
 | 
					        "//b/x is not a mapping. src={:#?}, dst={:#?}",
 | 
				
			||||||
 | 
					        src,
 | 
				
			||||||
 | 
					        merged_retained
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert!(
 | 
				
			||||||
 | 
					        merged_retained["c"]["foo"] == "bar",
 | 
				
			||||||
 | 
					        "//c/foo != bar. src={:#?}, dst={:#?}",
 | 
				
			||||||
        src,
 | 
					        src,
 | 
				
			||||||
        merged_retained
 | 
					        merged_retained
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
| 
						 | 
					@ -144,7 +258,12 @@ fn merge_files(
 | 
				
			||||||
            merge_json(&src_val, &mut dst_val, overwrite_existing)?;
 | 
					            merge_json(&src_val, &mut dst_val, overwrite_existing)?;
 | 
				
			||||||
            dst_val.to_string()
 | 
					            dst_val.to_string()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        FileType::Yaml => todo!(),
 | 
					        FileType::Yaml => {
 | 
				
			||||||
 | 
					            let src_val = serde_yaml::Value::from(src);
 | 
				
			||||||
 | 
					            let mut dst_val = serde_yaml::Value::from(dst);
 | 
				
			||||||
 | 
					            merge_yaml(&src_val, &mut dst_val, overwrite_existing)?;
 | 
				
			||||||
 | 
					            serde_yaml::to_string(&dst_val)?
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        FileType::Toml => todo!(),
 | 
					        FileType::Toml => todo!(),
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue