Skip to content

Commit

Permalink
Automatically inherit workspace fields when running cargo new
Browse files Browse the repository at this point in the history
Signed-off-by: hi-rustin <[email protected]>
  • Loading branch information
Rustin170506 committed May 3, 2023
1 parent ee7f4c3 commit 6c6bc32
Showing 1 changed file with 108 additions and 7 deletions.
115 changes: 108 additions & 7 deletions src/cargo/ops/cargo_new.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::core::{Edition, Shell, Workspace};
use crate::util::errors::CargoResult;
use crate::util::toml::parse_document;
use crate::util::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo};
use crate::util::{restricted_names, Config};
use anyhow::{anyhow, Context as _};
Expand Down Expand Up @@ -866,15 +867,115 @@ mod tests {
}
}
}

if let Err(e) = Workspace::new(&path.join("Cargo.toml"), config) {
crate::display_warning_with_error(
"compiling this new package may not work due to invalid \
match Workspace::new(&path.join("Cargo.toml"), config) {
Ok(ws) => {
// Because we only inherit the package field of workspace for valid members of workspace,
// we did not inherit it directly above.
let root_manifest = paths::read(ws.root_manifest())?;
let workspace_document =
parse_document(root_manifest.as_str(), ws.root_manifest(), config)?;
if let Some(workspace_package_keys) = workspace_document
.get("workspace")
.and_then(|workspace| workspace.get("package"))
.and_then(|package| package.as_table())
{
// Because we need to keep the format of the `Cargo.toml` file,
// we can not use `toml_edit`/`toml` to modify the `Cargo.toml` file directly.
// Instead, we need to rewrite the `Cargo.toml` file with the inherited package fields.
return create_manifest_with_inherited_workspace_package_fields(
opts,
path,
name,
cargotoml_path_specifier.as_str(),
workspace_package_keys,
);
}
}
Err(e) => {
crate::display_warning_with_error(
"compiling this new package may not work due to invalid \
workspace configuration",
&e,
&mut config.shell(),
);
&e,
&mut config.shell(),
);
}
}

Ok(())
}

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(());
}
// Try inherit the edition from the workspace if it is not specified.
let edition = match opts.edition {
Some(edition) => {
format!("edition = {}", toml::Value::String(edition.to_string()))
}
None => {
if workspace_package_keys.contains_key("edition") {
format!("edition.workspace = {}", toml::Value::Boolean(true))
} else {
format!(
"edition = {}",
toml::Value::String(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))
} else {
"version = \"0.1.0\"".to_string()
};
// 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())))
),
None => {
if workspace_package_keys.contains_key("publish") {
format!("publish.workspace = {}\n", toml::Value::Boolean(true))
} else {
"".to_string()
}
}
};
// Inherit other keys from the workspace.
let workspace_package_fields = workspace_package_keys
.iter()
.filter(|(key, _)| *key != "edition" && *key != "version" && *key != "publish")
.map(|(key, _)| format!("{}.workspace = {}", key, toml::Value::Boolean(true)))
.collect::<Vec<String>>();
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
[dependencies]
{}"#,
name,
version,
edition,
publish,
workspace_package_fields.join("\n"),
cargotoml_path_specifier
)
.as_bytes(),
)?;
return Ok(());
}

0 comments on commit 6c6bc32

Please sign in to comment.