Skip to content

Commit 6c6bc32

Browse files
committed
Automatically inherit workspace fields when running cargo new
Signed-off-by: hi-rustin <rustin.liu@gmail.com>
1 parent ee7f4c3 commit 6c6bc32

File tree

1 file changed

+108
-7
lines changed

1 file changed

+108
-7
lines changed

src/cargo/ops/cargo_new.rs

Lines changed: 108 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::core::{Edition, Shell, Workspace};
22
use crate::util::errors::CargoResult;
3+
use crate::util::toml::parse_document;
34
use crate::util::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo};
45
use crate::util::{restricted_names, Config};
56
use anyhow::{anyhow, Context as _};
@@ -866,15 +867,115 @@ mod tests {
866867
}
867868
}
868869
}
869-
870-
if let Err(e) = Workspace::new(&path.join("Cargo.toml"), config) {
871-
crate::display_warning_with_error(
872-
"compiling this new package may not work due to invalid \
870+
match Workspace::new(&path.join("Cargo.toml"), config) {
871+
Ok(ws) => {
872+
// Because we only inherit the package field of workspace for valid members of workspace,
873+
// we did not inherit it directly above.
874+
let root_manifest = paths::read(ws.root_manifest())?;
875+
let workspace_document =
876+
parse_document(root_manifest.as_str(), ws.root_manifest(), config)?;
877+
if let Some(workspace_package_keys) = workspace_document
878+
.get("workspace")
879+
.and_then(|workspace| workspace.get("package"))
880+
.and_then(|package| package.as_table())
881+
{
882+
// Because we need to keep the format of the `Cargo.toml` file,
883+
// we can not use `toml_edit`/`toml` to modify the `Cargo.toml` file directly.
884+
// Instead, we need to rewrite the `Cargo.toml` file with the inherited package fields.
885+
return create_manifest_with_inherited_workspace_package_fields(
886+
opts,
887+
path,
888+
name,
889+
cargotoml_path_specifier.as_str(),
890+
workspace_package_keys,
891+
);
892+
}
893+
}
894+
Err(e) => {
895+
crate::display_warning_with_error(
896+
"compiling this new package may not work due to invalid \
873897
workspace configuration",
874-
&e,
875-
&mut config.shell(),
876-
);
898+
&e,
899+
&mut config.shell(),
900+
);
901+
}
877902
}
878903

879904
Ok(())
880905
}
906+
907+
fn create_manifest_with_inherited_workspace_package_fields(
908+
opts: &MkOptions<'_>,
909+
path: &Path,
910+
name: &str,
911+
cargotoml_path_specifier: &str,
912+
workspace_package_keys: &toml::value::Table,
913+
) -> CargoResult<()> {
914+
if workspace_package_keys.is_empty() {
915+
return Ok(());
916+
}
917+
// Try inherit the edition from the workspace if it is not specified.
918+
let edition = match opts.edition {
919+
Some(edition) => {
920+
format!("edition = {}", toml::Value::String(edition.to_string()))
921+
}
922+
None => {
923+
if workspace_package_keys.contains_key("edition") {
924+
format!("edition.workspace = {}", toml::Value::Boolean(true))
925+
} else {
926+
format!(
927+
"edition = {}",
928+
toml::Value::String(Edition::LATEST_STABLE.to_string())
929+
)
930+
}
931+
}
932+
};
933+
// Try inherit the version from the workspace if it is not specified.
934+
let version = if workspace_package_keys.contains_key("version") {
935+
format!("version.workspace = {}", toml::Value::Boolean(true))
936+
} else {
937+
"version = \"0.1.0\"".to_string()
938+
};
939+
// Try inherit the publish from the workspace if it is not specified.
940+
let publish = match opts.registry {
941+
Some(registry) => format!(
942+
"publish = {}\n",
943+
toml::Value::Array(vec!(toml::Value::String(registry.to_string())))
944+
),
945+
None => {
946+
if workspace_package_keys.contains_key("publish") {
947+
format!("publish.workspace = {}\n", toml::Value::Boolean(true))
948+
} else {
949+
"".to_string()
950+
}
951+
}
952+
};
953+
// Inherit other keys from the workspace.
954+
let workspace_package_fields = workspace_package_keys
955+
.iter()
956+
.filter(|(key, _)| *key != "edition" && *key != "version" && *key != "publish")
957+
.map(|(key, _)| format!("{}.workspace = {}", key, toml::Value::Boolean(true)))
958+
.collect::<Vec<String>>();
959+
paths::write(
960+
&path.join("Cargo.toml"),
961+
format!(
962+
r#"[package]
963+
name = "{}"
964+
{}
965+
{}
966+
{}{}
967+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
968+
969+
[dependencies]
970+
{}"#,
971+
name,
972+
version,
973+
edition,
974+
publish,
975+
workspace_package_fields.join("\n"),
976+
cargotoml_path_specifier
977+
)
978+
.as_bytes(),
979+
)?;
980+
return Ok(());
981+
}

0 commit comments

Comments
 (0)