use crate::cargo::manifest_analyzer::DepKind;
use crate::error::{RailError, RailResult};
use toml_edit::{DocumentMut, Item, Table, Value};
use super::workspace_ref::is_package_workspace_inherited;
pub fn transform_dependencies_in_section<F>(doc: &mut DocumentMut, section: &str, mut transform_fn: F) -> RailResult<()>
where
F: FnMut(&str, &mut Item) -> RailResult<()>,
{
if let Some(deps) = doc.get_mut(section).and_then(|d| d.as_table_mut()) {
let dep_names: Vec<String> = deps.iter().map(|(k, _)| k.to_string()).collect();
for dep_name in dep_names {
if let Some(dep_item) = deps.get_mut(&dep_name) {
transform_fn(&dep_name, dep_item)?;
}
}
}
Ok(())
}
pub fn resolve_package_workspace_inheritance(doc: &mut DocumentMut, workspace_package: &Table) -> RailResult<()> {
let fields = [
"version",
"authors",
"edition",
"rust-version",
"license",
"repository",
"description",
"homepage",
"documentation",
"readme",
"keywords",
"categories",
];
if let Some(package) = doc.get_mut("package").and_then(|p| p.as_table_mut()) {
for field in fields {
if let Some(item) = package.get(field)
&& is_package_workspace_inherited(item)
{
if let Some(workspace_value) = workspace_package.get(field) {
package.insert(field, workspace_value.clone());
} else {
package.remove(field);
}
}
}
package.remove("workspace");
}
Ok(())
}
pub fn set_version(item: &mut Item, version: &str) -> RailResult<()> {
if item.as_str().is_some() {
*item = Item::Value(Value::from(version));
return Ok(());
}
if let Some(table) = item.as_inline_table_mut() {
table.insert("version", Value::from(version));
Ok(())
} else if let Some(table) = item.as_table_mut() {
table.insert("version", Item::Value(Value::from(version)));
Ok(())
} else {
Err(RailError::message(
"cannot set version: item is not a valid dependency format",
))
}
}
pub fn dep_kind_to_section(kind: DepKind) -> &'static str {
match kind {
DepKind::Normal => "dependencies",
DepKind::Dev => "dev-dependencies",
DepKind::Build => "build-dependencies",
}
}
#[cfg(test)]
mod tests {
use super::*;
use toml_edit::{DocumentMut, InlineTable, Item, Table, Value};
#[test]
fn test_transform_dependencies_in_section() {
let content = "[dependencies]\nserde = \"1.0\"\ntokio = \"1.0\"\n";
let mut doc: DocumentMut = content.parse().unwrap();
let mut count = 0;
transform_dependencies_in_section(&mut doc, "dependencies", |_name, _item| {
count += 1;
Ok(())
})
.unwrap();
assert_eq!(count, 2);
}
#[test]
fn test_transform_dependencies_can_modify() {
let content = "[dependencies]\nserde = \"1.0\"\n";
let mut doc: DocumentMut = content.parse().unwrap();
transform_dependencies_in_section(&mut doc, "dependencies", |_name, item| {
set_version(item, "2.0")?;
Ok(())
})
.unwrap();
let deps = doc.get("dependencies").unwrap().as_table().unwrap();
let serde = deps.get("serde").unwrap();
assert_eq!(serde.as_str().unwrap(), "2.0");
}
#[test]
fn test_resolve_package_workspace_inheritance() {
let content = "[package]\nname = \"test\"\nversion = { workspace = true }\n";
let mut doc: DocumentMut = content.parse().unwrap();
let mut workspace_package = Table::new();
workspace_package.insert("version", Item::Value(Value::from("1.2.3")));
resolve_package_workspace_inheritance(&mut doc, &workspace_package).unwrap();
let package = doc.get("package").unwrap().as_table().unwrap();
let version = package.get("version").unwrap();
assert_eq!(version.as_value().unwrap().as_str().unwrap(), "1.2.3");
}
#[test]
fn test_set_version_all_formats() {
let mut item1 = Item::Value(Value::from("1.0"));
set_version(&mut item1, "2.0").unwrap();
assert_eq!(item1.as_str().unwrap(), "2.0");
let mut table = InlineTable::new();
table.insert("version", Value::from("1.0"));
let mut item2 = Item::Value(Value::InlineTable(table));
set_version(&mut item2, "3.0").unwrap();
assert_eq!(
item2
.as_inline_table()
.unwrap()
.get("version")
.unwrap()
.as_str()
.unwrap(),
"3.0"
);
}
#[test]
fn test_dep_kind_to_section() {
assert_eq!(dep_kind_to_section(DepKind::Normal), "dependencies");
assert_eq!(dep_kind_to_section(DepKind::Dev), "dev-dependencies");
assert_eq!(dep_kind_to_section(DepKind::Build), "build-dependencies");
}
}