diff --git a/generate-assets/Cargo.lock b/generate-assets/Cargo.lock index 3f5151c063..91ce5249d8 100644 --- a/generate-assets/Cargo.lock +++ b/generate-assets/Cargo.lock @@ -137,12 +137,11 @@ dependencies = [ [[package]] name = "cargo_toml" -version = "0.11.8" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72c3ff59e3b7d24630206bb63a73af65da4ed5df1f76ee84dfafb9fee2ba60e" +checksum = "599aa35200ffff8f04c1925aa1acc92fa2e08874379ef42e210a80e527e60838" dependencies = [ "serde", - "serde_derive", "toml", ] @@ -1088,6 +1087,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1267,11 +1275,36 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.10" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec" dependencies = [ "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] @@ -1588,6 +1621,15 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "winnow" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.10.1" diff --git a/generate-assets/Cargo.toml b/generate-assets/Cargo.toml index 1916dd682b..c5d56c4981 100644 --- a/generate-assets/Cargo.toml +++ b/generate-assets/Cargo.toml @@ -11,11 +11,11 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -toml = "0.5" +toml = "0.7" serde = { version = "1", features = ["derive"] } rand = "0.8" regex = "1" -cargo_toml = "0.11.5" +cargo_toml = "0.15" url = "2.2.2" anyhow = "1.0.58" base64 = "0.13.0" diff --git a/generate-assets/src/lib.rs b/generate-assets/src/lib.rs index f2238adac9..90cac35bb2 100644 --- a/generate-assets/src/lib.rs +++ b/generate-assets/src/lib.rs @@ -325,7 +325,7 @@ fn get_license(cargo_manifest: &cargo_toml::Manifest) -> Option { .. }) = &cargo_manifest.package { - if let Some(license) = license { + if let Some(cargo_toml::Inheritable::Set(license)) = license { Some(license.clone()) } else { license_file.as_ref().map(|_| String::from("non-standard")) @@ -338,11 +338,6 @@ fn get_license(cargo_manifest: &cargo_toml::Manifest) -> Option { /// Find any bevy dependency and get the corresponding bevy version from an asset's manifest /// This makes sure to handle all the bevy_* crates fn get_bevy_version(cargo_manifest: &cargo_toml::Manifest) -> Option { - get_bevy_dependency(cargo_manifest).and_then(get_bevy_dependency_version) -} - -/// Find any bevy dependency from an asset's manifest -fn get_bevy_dependency(cargo_manifest: &cargo_toml::Manifest) -> Option<&cargo_toml::Dependency> { let search_range = OFFICIAL_BEVY_CRATE_PREFIX_RANGE_START.to_owned() ..OFFICIAL_BEVY_CRATE_PREFIX_RANGE_END.to_owned(); @@ -356,28 +351,36 @@ fn get_bevy_dependency(cargo_manifest: &cargo_toml::Manifest) -> Option<&cargo_t // Tries to find an official bevy crate from the asset's dev dependencies // An asset can indirectly depend on bevy through another crate, but would probably depend on bevy directly // for its examples, benchmarks or tests, in its dev dependencies - let dev_dependencies = cargo_manifest.dev_dependencies.range(search_range); + let dev_dependencies = cargo_manifest.dev_dependencies.range(search_range.clone()); bevy_dependency = search_bevy_in_dependencies(dev_dependencies, bevy_crates.clone()); if bevy_dependency.is_none() { - // If everything else fails, try to find any crate with a name starting with bevy - // This can happen if the asset depends only on past or future bevy sub-crates, - // or on third-party crates which name starts with bevy (might yield unaccurate results in that last case) - bevy_dependency = dependencies.next().map(|(_, d)| d); + // Tries to find an official bevy crate from the asset's workspace dependencies + if let Some(ref workspace) = cargo_manifest.workspace { + let workspace_dependencies = workspace.dependencies.range(search_range); + bevy_dependency = search_bevy_in_dependencies(workspace_dependencies, bevy_crates); + } + + if bevy_dependency.is_none() { + // If everything else fails, try to find any crate with a name starting with bevy + // This can happen if the asset depends only on past or future bevy sub-crates, + // or on third-party crates which name starts with bevy (might yield unaccurate results in that last case) + bevy_dependency = dependencies.find_map(|(_, d)| get_bevy_dependency_version(d)); + } } } bevy_dependency } -/// Seach the first official bevy crate found in a collection of dependencies. +/// Seach the first official bevy crate found in a collection of dependencies and return its version. /// If it was a bit more generic, this function could be called find_first_intersect_in_sorted_iterators. /// Both dependencies and bevy_crates are assumed to be sorted (by key for dependencies, they are in this context), /// and we find the first element that intersect both of them using that knowledge fn search_bevy_in_dependencies<'a>( mut dependencies: std::collections::btree_map::Range<'a, String, cargo_toml::Dependency>, mut bevy_crates: std::slice::Iter<&str>, -) -> Option<&'a cargo_toml::Dependency> { +) -> Option { let mut dependency = dependencies.next(); let mut bevy_crate = bevy_crates.next(); @@ -389,9 +392,17 @@ fn search_bevy_in_dependencies<'a>( dependency = dependencies.next(); } else { if dependency_name == bevy_crate_name { - return Some(dependency.unwrap().1); + let dependency_version = get_bevy_dependency_version(dependency.unwrap().1); + if dependency_version.is_some() { + return dependency_version; + } else { + // In this case we found an official bevy crate but we couldn't get a version from it + dependency = dependencies.next(); + bevy_crate = bevy_crates.next(); + } + } else { + bevy_crate = bevy_crates.next(); } - bevy_crate = bevy_crates.next(); } } return None; @@ -416,6 +427,7 @@ fn get_bevy_dependency_version(dep: &cargo_toml::Dependency) -> Option { None } } + cargo_toml::Dependency::Inherited(_) => None, } } @@ -473,3 +485,233 @@ fn get_metadata_from_db_by_crate_name( bail!("Not found in crates.io db: {crate_name}") } } + +#[cfg(test)] +mod tests { + mod get_version { + use super::super::*; + + use cargo_toml::{Dependency, Manifest}; + use std::collections::BTreeMap; + + /* + fn get_manifest( + dependencies: Vec, + dependencies_separated: Vec, + dev_dependencies: Vec, + dev_dependencies_separated: Vec, + ) -> cargo_toml::Manifest { + toml::from_str::(&content)?; + } */ + + fn get_manifest( + dependencies: BTreeMap, + dev_dependencies: BTreeMap, + workspace_dependencies: BTreeMap, + ) -> Manifest { + #[allow(deprecated)] + Manifest { + package: Default::default(), + workspace: Some(cargo_toml::Workspace { + members: Default::default(), + package: Default::default(), + default_members: Default::default(), + exclude: Default::default(), + metadata: Default::default(), + resolver: Default::default(), + dependencies: workspace_dependencies, + }), + dependencies, + dev_dependencies, + build_dependencies: Default::default(), + target: Default::default(), + features: Default::default(), + replace: Default::default(), + patch: Default::default(), + lib: Default::default(), + profile: Default::default(), + badges: Default::default(), + bin: Default::default(), + bench: Default::default(), + test: Default::default(), + example: Default::default(), + } + } + + #[test] + fn from_no_dependency() { + let dependencies = BTreeMap::new(); + let dev_dependencies = BTreeMap::new(); + let workspace_dependencies = BTreeMap::new(); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, None); + } + + #[test] + fn from_other_dependencies() { + let mut dependencies = BTreeMap::new(); + let mut dev_dependencies = BTreeMap::new(); + let workspace_dependencies = BTreeMap::new(); + + dependencies.insert("other".to_string(), Dependency::Simple("0.10".to_string())); + dev_dependencies.insert("other".to_string(), Dependency::Simple("0.10".to_string())); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, None); + } + + #[test] + fn from_main_crate() { + let mut dependencies = BTreeMap::new(); + let dev_dependencies = BTreeMap::new(); + let workspace_dependencies = BTreeMap::new(); + + dependencies.insert("bevy".to_string(), Dependency::Simple("0.10".to_string())); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, Some("0.10".to_string())); + } + + #[test] + fn from_sub_crate() { + let mut dependencies = BTreeMap::new(); + let dev_dependencies = BTreeMap::new(); + let workspace_dependencies = BTreeMap::new(); + + dependencies.insert( + "bevy_transform".to_string(), + Dependency::Simple("0.10".to_string()), + ); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, Some("0.10".to_string())); + } + + #[test] + fn from_dev_dependencies() { + let dependencies = BTreeMap::new(); + let mut dev_dependencies = BTreeMap::new(); + let workspace_dependencies = BTreeMap::new(); + + dev_dependencies.insert("bevy".to_string(), Dependency::Simple("0.10".to_string())); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, Some("0.10".to_string())); + } + + #[test] + fn from_workspace_dependencies() { + let dependencies = BTreeMap::new(); + let dev_dependencies = BTreeMap::new(); + let mut workspace_dependencies = BTreeMap::new(); + + workspace_dependencies + .insert("bevy".to_string(), Dependency::Simple("0.10".to_string())); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, Some("0.10".to_string())); + } + + #[test] + fn from_third_party() { + let mut dependencies = BTreeMap::new(); + let dev_dependencies = BTreeMap::new(); + let workspace_dependencies = BTreeMap::new(); + + dependencies.insert( + "bevy_third_party_crate_example".to_string(), + Dependency::Simple("0.5".to_string()), + ); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + // Note that this result is expected, but potentially wrong + assert_eq!(version, Some("0.5".to_string())); + } + + #[test] + fn from_dependencies_ignore_third_party() { + let mut dependencies = BTreeMap::new(); + let dev_dependencies = BTreeMap::new(); + let workspace_dependencies = BTreeMap::new(); + + dependencies.insert( + "bevy_third_party_crate_example".to_string(), + Dependency::Simple("0.5".to_string()), + ); + dependencies.insert( + "bevy_transform".to_string(), + Dependency::Simple("0.10".to_string()), + ); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, Some("0.10".to_string())); + } + + #[test] + fn from_dev_dependencies_ignore_third_party() { + let mut dependencies = BTreeMap::new(); + let mut dev_dependencies = BTreeMap::new(); + let workspace_dependencies = BTreeMap::new(); + + dependencies.insert( + "bevy_third_party_crate_example".to_string(), + Dependency::Simple("0.5".to_string()), + ); + dev_dependencies.insert("bevy".to_string(), Dependency::Simple("0.10".to_string())); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, Some("0.10".to_string())); + } + + #[test] + fn from_workspace_dependencies_ignore_third_party() { + let mut dependencies = BTreeMap::new(); + let dev_dependencies = BTreeMap::new(); + let mut workspace_dependencies = BTreeMap::new(); + + dependencies.insert( + "bevy_third_party_crate_example".to_string(), + Dependency::Simple("0.5".to_string()), + ); + workspace_dependencies + .insert("bevy".to_string(), Dependency::Simple("0.10".to_string())); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, Some("0.10".to_string())); + } + + #[test] + fn from_dev_dependencies_with_path_dependency() { + let mut dependencies = BTreeMap::new(); + let mut dev_dependencies = BTreeMap::new(); + let workspace_dependencies = BTreeMap::new(); + + dependencies.insert( + "bevy".to_string(), + Dependency::Detailed(cargo_toml::DependencyDetail { + path: Some("fake/path/to/crate".to_string()), + ..Default::default() + }), + ); + dev_dependencies.insert( + "bevy_transform".to_string(), + Dependency::Simple("0.10".to_string()), + ); + + let manifest = get_manifest(dependencies, dev_dependencies, workspace_dependencies); + let version = get_bevy_version(&manifest); + assert_eq!(version, Some("0.10".to_string())); + } + } +}