use std::collections::HashSet;
use super::ParsedManifest;
pub(super) fn mask_local_crate_versions(
manifests: &mut [ParsedManifest],
lock_file: &mut Option<toml::Value>,
) {
let local_package_names = parse_local_crate_names(manifests);
mask_local_versions_in_manifests(manifests, &local_package_names);
if let Some(l) = lock_file {
mask_local_versions_in_lockfile(l, &local_package_names);
}
}
const CONST_VERSION: &str = "0.0.1";
fn mask_local_versions_in_lockfile(
lock_file: &mut toml::Value,
local_package_names: &HashSet<String>,
) {
if let Some(packages) = lock_file
.get_mut("package")
.and_then(|packages| packages.as_array_mut())
{
packages
.iter_mut()
.filter(|package| {
package
.get("name")
.and_then(|name| name.as_str())
.map(|name| local_package_names.contains(name))
.unwrap_or_default()
&& package.get("source").is_none()
})
.for_each(|package| {
if let Some(version) = package.get_mut("version") {
*version = toml::Value::String(CONST_VERSION.to_string())
}
});
}
}
fn mask_local_versions_in_manifests(
manifests: &mut [ParsedManifest],
local_package_names: &HashSet<String>,
) {
for manifest in manifests.iter_mut() {
if let Some(package) = manifest.contents.get_mut("package") {
if let Some(version) = package.get_mut("version") {
if version.as_str().is_some() {
*version = toml::Value::String(CONST_VERSION.to_string());
}
}
}
mask_local_dependency_versions(local_package_names, manifest);
}
}
fn mask_local_dependency_versions(
local_package_names: &HashSet<String>,
manifest: &mut ParsedManifest,
) {
fn _mask(local_package_names: &HashSet<String>, toml_value: &mut toml::Value) {
for dependency_key in ["dependencies", "dev-dependencies", "build-dependencies"] {
if let Some(dependencies) = toml_value.get_mut(dependency_key) {
if let Some(dependencies) = dependencies.as_table_mut() {
for (key, dependency) in dependencies {
if dependency.get("path").is_none() {
continue;
}
let mut must_mark_version = false;
if let Some(package_name) = dependency.get("package") {
if package_name
.as_str()
.is_some_and(|n| local_package_names.contains(n))
{
must_mark_version = true;
}
} else {
if local_package_names.contains(key.as_str()) {
must_mark_version = true;
}
}
if must_mark_version {
if let Some(version) = dependency.get_mut("version") {
*version = toml::Value::String(CONST_VERSION.to_string());
}
}
}
}
}
}
}
_mask(local_package_names, &mut manifest.contents);
if let Some(targets) = manifest.contents.get_mut("target") {
if let Some(target_table) = targets.as_table_mut() {
for (_, target_config) in target_table.iter_mut() {
_mask(local_package_names, target_config)
}
}
}
if let Some(workspace) = manifest.contents.get_mut("workspace") {
if let Some(package) = workspace.get_mut("package") {
if let Some(version) = package.get_mut("version") {
*version = toml::Value::String(CONST_VERSION.to_string());
}
}
_mask(local_package_names, workspace);
}
}
fn parse_local_crate_names(manifests: &[ParsedManifest]) -> HashSet<String> {
manifests
.iter()
.filter_map(|m| {
m.contents
.get("package")?
.get("name")?
.as_str()
.map(String::from)
})
.collect()
}