From 3a9da71aeb37c1f8ce163081511d63f2a239a29b Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Sat, 13 May 2023 16:40:17 +0800 Subject: [PATCH] Use toml_edit Signed-off-by: hi-rustin --- src/cargo/ops/cargo_new.rs | 88 ++++++++----------- src/cargo/util/toml_mut/manifest.rs | 32 ++++++- .../out/crates/foo/Cargo.toml | 3 +- .../out/crates/foo/Cargo.toml | 3 +- .../out/crates/foo/Cargo.toml | 5 +- .../out/crates/foo/Cargo.toml | 1 + .../out/crates/foo/Cargo.toml | 3 +- 7 files changed, 78 insertions(+), 57 deletions(-) diff --git a/src/cargo/ops/cargo_new.rs b/src/cargo/ops/cargo_new.rs index 75519ae3d171..24b5bbf96fff 100644 --- a/src/cargo/ops/cargo_new.rs +++ b/src/cargo/ops/cargo_new.rs @@ -1,6 +1,7 @@ use crate::core::{Edition, Shell, Workspace}; use crate::util::errors::CargoResult; use crate::util::toml::parse_document; +use crate::util::toml_mut::manifest::LocalManifest; use crate::util::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo}; use crate::util::{restricted_names, Config}; use anyhow::{anyhow, Context as _}; @@ -879,16 +880,9 @@ mod tests { .and_then(|workspace| workspace.get("package")) .and_then(|package| package.as_table()) { - // We create a new manifest with the inherited package field. - // We do not use the existing manifest because we do not want - // to couple those two write operations together. - // Moreover, if we want to add the package as a member of the workspace automatically, - // we can directly reuse this function. return create_manifest_with_inherited_workspace_package_fields( opts, path, - name, - cargotoml_path_specifier.as_str(), workspace_package_keys, ); } @@ -909,75 +903,67 @@ mod tests { fn create_manifest_with_inherited_workspace_package_fields( opts: &MkOptions<'_>, path: &Path, - name: &str, - cargotoml_path_specifier: &str, workspace_package_keys: &toml::value::Table, ) -> CargoResult<()> { if workspace_package_keys.is_empty() { return Ok(()); } + + let manifest_path = path.join("Cargo.toml"); + let mut manifest = LocalManifest::try_new(&manifest_path)?; + + let remove_and_inherit_package_key = + |key: &str, manifest: &mut LocalManifest| -> CargoResult<()> { + manifest.remove_package_key(key)?; + manifest.set_workspace_inherited_package_key(key)?; + Ok(()) + }; + // Try inherit the edition from the workspace if it is not specified. - let edition = match opts.edition { + match opts.edition { Some(edition) => { - format!("edition = {}", toml::Value::String(edition.to_string())) + manifest.set_package_key("edition", toml_edit::value(edition))?; } None => { if workspace_package_keys.contains_key("edition") { - format!("edition.workspace = {}", toml::Value::Boolean(true)) + remove_and_inherit_package_key("edition", &mut manifest)?; } else { - format!( - "edition = {}", - toml::Value::String(Edition::LATEST_STABLE.to_string()) - ) + manifest.set_package_key( + "edition", + toml_edit::value(Edition::LATEST_STABLE.to_string()), + )?; } } }; // Try inherit the version from the workspace if it is not specified. - let version = if workspace_package_keys.contains_key("version") { - format!("version.workspace = {}", toml::Value::Boolean(true)) + if workspace_package_keys.contains_key("version") { + remove_and_inherit_package_key("version", &mut manifest)?; } else { - "version = \"0.1.0\"".to_string() + manifest.set_package_key("version", toml_edit::value("0.1.0"))?; }; // Try inherit the publish from the workspace if it is not specified. - let publish = match opts.registry { - Some(registry) => format!( - "publish = {}\n", - toml::Value::Array(vec!(toml::Value::String(registry.to_string()))) - ), + match opts.registry { + Some(registry) => { + let mut array = toml_edit::Array::default(); + array.push(registry); + manifest.set_package_key("publish", toml_edit::value(array))?; + } None => { if workspace_package_keys.contains_key("publish") { - format!("publish.workspace = {}\n", toml::Value::Boolean(true)) - } else { - "".to_string() + remove_and_inherit_package_key("publish", &mut manifest)?; } } }; // Inherit other keys from the workspace. - let workspace_package_fields = workspace_package_keys + for (key, _) in workspace_package_keys .iter() .filter(|(key, _)| *key != "edition" && *key != "version" && *key != "publish") - .map(|(key, _)| format!("{}.workspace = {}", key, toml::Value::Boolean(true))) - .collect::>(); - paths::write( - &path.join("Cargo.toml"), - format!( - r#"[package] -name = "{}" -{} -{} -{}{} -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + { + manifest.set_workspace_inherited_package_key(key)?; + } -[dependencies] -{}"#, - name, - version, - edition, - publish, - workspace_package_fields.join("\n"), - cargotoml_path_specifier - ) - .as_bytes(), - )?; - return Ok(()); + // Re-write the `Cargo.toml` file with the inherited fields. + manifest.write()?; + + Ok(()) } diff --git a/src/cargo/util/toml_mut/manifest.rs b/src/cargo/util/toml_mut/manifest.rs index f3fc150e12a4..7e42b7c87e8b 100644 --- a/src/cargo/util/toml_mut/manifest.rs +++ b/src/cargo/util/toml_mut/manifest.rs @@ -4,7 +4,7 @@ use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use std::str; -use anyhow::Context as _; +use anyhow::{Context as _, Ok}; use super::dependency::Dependency; use crate::core::dependency::DepKind; @@ -445,6 +445,36 @@ impl LocalManifest { } status } + + pub fn set_package_key(&mut self, key: &str, value: toml_edit::Item) -> CargoResult<()> { + let package = self.data["package"] + .as_table_mut() + .ok_or_else(parse_manifest_err)?; + package[key] = value; + + Ok(()) + } + + pub fn remove_package_key(&mut self, key: &str) -> CargoResult<()> { + let package = self.data["package"] + .as_table_mut() + .ok_or_else(parse_manifest_err)?; + package.remove(key); + + Ok(()) + } + + pub fn set_workspace_inherited_package_key(&mut self, key: &str) -> CargoResult<()> { + let package = self.data["package"] + .as_table_mut() + .ok_or_else(parse_manifest_err)?; + let mut table = toml_edit::Table::new(); + table.set_dotted(true); + table["workspace"] = toml_edit::value(true); + package.insert(key, toml_edit::Item::Table(table)); + + Ok(()) + } } impl std::fmt::Display for LocalManifest { diff --git a/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/Cargo.toml b/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/Cargo.toml index 32a220e8caad..e8d27a93c079 100644 --- a/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/Cargo.toml +++ b/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "foo" -version.workspace = true edition.workspace = true +version.workspace = true publish.workspace = true authors.workspace = true categories.workspace = true @@ -15,6 +15,7 @@ license.workspace = true readme.workspace = true repository.workspace = true rust-version.workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/Cargo.toml b/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/Cargo.toml index 81ba57c664f0..8c6b906e589e 100644 --- a/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/Cargo.toml +++ b/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "foo" -version.workspace = true edition = "2021" +version.workspace = true publish.workspace = true authors.workspace = true categories.workspace = true @@ -15,6 +15,7 @@ license.workspace = true readme.workspace = true repository.workspace = true rust-version.workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/Cargo.toml b/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/Cargo.toml index e2f3b68dd0f9..55b02763dbeb 100644 --- a/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/Cargo.toml +++ b/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "foo" -version.workspace = true -edition.workspace = true publish = ["foo"] +edition.workspace = true +version.workspace = true authors.workspace = true categories.workspace = true description.workspace = true @@ -15,6 +15,7 @@ license.workspace = true readme.workspace = true repository.workspace = true rust-version.workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/Cargo.toml b/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/Cargo.toml index 1febc7ca3664..a60012046e24 100644 --- a/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/Cargo.toml +++ b/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/Cargo.toml @@ -15,6 +15,7 @@ license.workspace = true readme.workspace = true repository.workspace = true rust-version.workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/Cargo.toml b/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/Cargo.toml index 32a220e8caad..e8d27a93c079 100644 --- a/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/Cargo.toml +++ b/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "foo" -version.workspace = true edition.workspace = true +version.workspace = true publish.workspace = true authors.workspace = true categories.workspace = true @@ -15,6 +15,7 @@ license.workspace = true readme.workspace = true repository.workspace = true rust-version.workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies]