Skip to content

Commit 39d8992

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

File tree

1 file changed

+110
-7
lines changed

1 file changed

+110
-7
lines changed

src/cargo/ops/cargo_new.rs

Lines changed: 110 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,117 @@ 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+
// We create a new manifest with the inherited package field.
883+
// We do not use the existing manifest because we do not want
884+
// to couple those two write operations together.
885+
// Moreover, if we want to add the package as a member of the workspace automatically,
886+
// we can directly reuse this function.
887+
return create_manifest_with_inherited_workspace_package_fields(
888+
opts,
889+
path,
890+
name,
891+
cargotoml_path_specifier.as_str(),
892+
workspace_package_keys,
893+
);
894+
}
895+
}
896+
Err(e) => {
897+
crate::display_warning_with_error(
898+
"compiling this new package may not work due to invalid \
873899
workspace configuration",
874-
&e,
875-
&mut config.shell(),
876-
);
900+
&e,
901+
&mut config.shell(),
902+
);
903+
}
877904
}
878905

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

0 commit comments

Comments
 (0)