diff --git a/src/core/instance/tests.rs b/src/core/instance/tests.rs index 3ffe47c..9e18292 100644 --- a/src/core/instance/tests.rs +++ b/src/core/instance/tests.rs @@ -5,6 +5,40 @@ use crate::item::IntoItemData; use super::*; + +#[test] +fn test_sort_keys() -> MizeResult<()> { + + let mut data = ItemData::from_toml(r#" + [hi] + test = 4 + + [config] + zzz = "hiiii" + hi = "hello from config/hi" + + [config.test] + inner = "inner" + "#)?; + + let data_sorted = ItemData::from_toml(r#" + [config] + hi = "hello from config/hi" + test = { inner = "inner" } + zzz = "hiiii" + + [hi] + test = 4 + "#)?; + + data.sort_keys()?; + + assert_eq!(data.to_json()?, data_sorted.to_json()?); + + + Ok(()) +} + #[test] fn test_get_module_hash() -> MizeResult<()> { let mut instance = Instance::empty()?; @@ -18,9 +52,10 @@ fn test_get_module_hash() -> MizeResult<()> { instance.set_blocking("0/config/selector", ItemData::from_toml(&selector_toml)?)?; - let hash = get_module_hash(&mut instance, "String", ItemData::new())?; + let (hash, selector) = get_module_hash(&mut instance, "String", ItemData::new())?; test_println!("hash: {}", hash); + test_println!("selector: {}", selector); assert_eq!(hash, "e96edf60216688314efc263c1aa8d6ce".to_owned()); diff --git a/src/core/item.rs b/src/core/item.rs index 3ab53f7..e37158c 100644 --- a/src/core/item.rs +++ b/src/core/item.rs @@ -189,6 +189,10 @@ impl ItemData { ItemData (cbor) } + pub fn sort_keys(&mut self) -> MizeResult<()> { + item_data_sort_keys(&mut self.0) + } + pub fn null() -> CborValue { CborValue::Null } @@ -254,6 +258,38 @@ pub fn item_data_get_path(data: &CborValue, path: Vec) -> MizeResult<&Cb item_data_get_path(sub_data, path_iter.collect()) } +pub fn item_data_sort_keys(data: &mut CborValue) -> MizeResult<()> { + + // for a list, sort each item of the list + if data.is_array() { + for el in data.as_array_mut().unwrap().iter_mut() { + item_data_sort_keys(el)? + } + } + + // sort the keys of a map + if data.is_map() { + let map: &mut Vec<(CborValue, CborValue)> = data.as_map_mut().unwrap(); + //map.sort_by_key(|el| el.0); + map.sort_by(|a,b| { + match a.0.partial_cmp(&b.0) { + Some(val) => val, + None => { + // just say the two values are equal, if they can't be ordered + std::cmp::Ordering::Equal + } + } + }); + + // also sort every sub value + for (key, val) in map { + item_data_sort_keys(val)? + } + } + + Ok(()) +} + pub fn item_data_set_path(data: &mut CborValue, path: Vec, data_to_set: &CborValue) -> MizeResult<()> { //trace!("[ {} ] item_data_set_path()", "CALL".yellow()); //trace!("[ {} ] data: {}", "ARG".yellow(), data.clone().into_item_data()); diff --git a/src/platform/os/mod.rs b/src/platform/os/mod.rs index 1e56184..cf0ad23 100644 --- a/src/platform/os/mod.rs +++ b/src/platform/os/mod.rs @@ -146,19 +146,21 @@ pub fn seconds_since_modification(path: &Path) -> MizeResult { Ok(duration.as_secs()) } -pub fn get_module_hash(instance: &mut Instance, name: &str, mut options: ItemData) -> MizeResult { +pub fn get_module_hash(instance: &mut Instance, name: &str, mut options: ItemData) -> MizeResult<(String, String)> { let mut selector_data = instance.get("0/config/selector")?.as_data_full()?; - selector_data.set_path("name", name)?; + selector_data.set_path("modName", name)?; selector_data.merge(options); + selector_data.sort_keys(); + let selector_str = selector_data.to_json()?; let mut hasher = Sha256::new(); - hasher.update(selector_str.as_bytes()); + hasher.update(selector_str.clone().as_bytes()); let result = hasher.finalize(); @@ -169,16 +171,23 @@ pub fn get_module_hash(instance: &mut Instance, name: &str, mut options: ItemDat hex.truncate(32); - return Ok(hex); + return Ok((hex, selector_str)); } -fn fetch_module(instance: &mut Instance, store_path: &str, module_url: &str, module_hash: &str, module_name: &str) -> MizeResult<()> { +fn fetch_module(instance: &mut Instance, store_path: &str, module_url: &str, module_hash: &str, module_name: &str, module_selector: &str) -> MizeResult<()> { let tmp_file_path_gz = format!("{}/{}.tar.gz", store_path, module_hash); let mut tmp_gz_file = File::create(&tmp_file_path_gz)?; - http_req::request::get(format!("http://{}/mize/dist/{}-{}.tar.gz", module_url, module_hash, module_name), &mut tmp_gz_file)?; + debug!("fetching module '{}' with hash: {}", module_name, module_hash); + + let response = http_req::request::get(format!("http://{}/mize/dist/{}-{}.tar.gz", module_url, module_hash, module_name), &mut tmp_gz_file)?; + + let code = response.status_code(); + if code != 200.into() { + return Err(mize_err!("failed to get module '{}' with hash '{}' and selector: {}", module_name, module_hash, module_selector).msg(format!("the http request to fetch the module returned a status code of: {}", code))); + } let tar = GzDecoder::new(tmp_gz_file); let mut archive = Archive::new(tar); @@ -207,11 +216,11 @@ pub fn load_module(instance: &mut Instance, module_name: &str, path: Option) -> ()> = unsafe { lib.get(format!("get_mize_module_{}", name).as_bytes())? }; + let func: libloading::Symbol) -> ()> = unsafe { lib.get(format!("get_mize_module_{}", module_name).as_bytes())? }; let mut module: Box = Box::new(EmptyModule {}); @@ -235,7 +244,7 @@ pub fn load_module(instance: &mut Instance, module_name: &str, path: Option