Skip to content

Commit 99e6db9

Browse files
committed
Automatically inherit workspace fields when running cargo new
Signed-off-by: hi-rustin <[email protected]>
1 parent 7b59dd0 commit 99e6db9

File tree

1 file changed

+85
-10
lines changed

1 file changed

+85
-10
lines changed

src/cargo/ops/cargo_new.rs

Lines changed: 85 additions & 10 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::important_paths::find_root_manifest_for_wd;
34
use crate::util::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo};
45
use crate::util::{restricted_names, Config};
56
use anyhow::{anyhow, Context as _};
@@ -772,12 +773,11 @@ fn mk(config: &Config, opts: &MkOptions<'_>) -> CargoResult<()> {
772773
if let Some(registry) = opts.registry {
773774
let mut array = toml_edit::Array::default();
774775
array.push(registry);
775-
array.decor_mut().set_suffix("\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html");
776776
manifest["package"]["publish"] = toml_edit::value(array);
777-
} else {
778-
manifest["package"]["edition"].as_value_mut().expect("edition is a string value").decor_mut().set_suffix("\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html");
779777
}
780-
manifest["dependencies"] = toml_edit::Item::Table(toml_edit::Table::new());
778+
let mut dep_table = toml_edit::Table::default();
779+
dep_table.decor_mut().set_prefix("\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n");
780+
manifest["dependencies"] = toml_edit::Item::Table(dep_table);
781781

782782
// Calculate what `[lib]` and `[[bin]]`s we need to append to `Cargo.toml`.
783783
for i in &opts.source_files {
@@ -795,15 +795,35 @@ fn mk(config: &Config, opts: &MkOptions<'_>) -> CargoResult<()> {
795795
.push(bin);
796796
}
797797
} else if i.relative_path != "src/lib.rs" {
798-
manifest["lib"]["name"] = toml_edit::value(i.target_name.clone());
799-
manifest["lib"]["path"] = toml_edit::value(i.relative_path.clone());
798+
let mut lib = toml_edit::Table::new();
799+
lib["name"] = toml_edit::value(i.target_name.clone());
800+
lib["path"] = toml_edit::value(i.relative_path.clone());
801+
manifest["lib"] = toml_edit::Item::Table(lib);
802+
}
803+
}
804+
805+
let manifest_path = path.join("Cargo.toml");
806+
if let Ok(root_manifest_path) = find_root_manifest_for_wd(&manifest_path) {
807+
let root_manifest = paths::read(&root_manifest_path)?;
808+
// Sometimes the root manifest is not a valid manifest, so we only try to parse it if it is.
809+
// This should not block the creation of the new project. It is only a best effort to
810+
// inherit the workspace package keys.
811+
if let Ok(workspace_document) = root_manifest.parse::<toml_edit::Document>() {
812+
if let Some(workspace_package_keys) = workspace_document
813+
.get("workspace")
814+
.and_then(|workspace| workspace.get("package"))
815+
.and_then(|package| package.as_table())
816+
{
817+
update_manifest_with_inherited_workspace_package_keys(
818+
opts,
819+
&mut manifest,
820+
workspace_package_keys,
821+
)
822+
}
800823
}
801824
}
802825

803-
paths::write(
804-
&path.join("Cargo.toml"),
805-
format!("{}", manifest.to_string()),
806-
)?;
826+
paths::write(&manifest_path, format!("{}", manifest.to_string()))?;
807827

808828
// Create all specified source files (with respective parent directories) if they don't exist.
809829
for i in &opts.source_files {
@@ -862,3 +882,58 @@ mod tests {
862882

863883
Ok(())
864884
}
885+
886+
fn update_manifest_with_inherited_workspace_package_keys(
887+
opts: &MkOptions<'_>,
888+
manifest: &mut toml_edit::Document,
889+
workspace_package_keys: &toml_edit::Table,
890+
) {
891+
if workspace_package_keys.is_empty() {
892+
return;
893+
}
894+
895+
let remove_package_key = |key: &str, manifest: &mut toml_edit::Document| {
896+
let package = manifest["package"]
897+
.as_table_mut()
898+
.expect("package is a table");
899+
package.remove(key);
900+
};
901+
902+
let set_workspace_inherited_package_key = |key: &str, manifest: &mut toml_edit::Document| {
903+
let package = manifest["package"]
904+
.as_table_mut()
905+
.expect("package is a table");
906+
let mut table = toml_edit::Table::new();
907+
table.set_dotted(true);
908+
table["workspace"] = toml_edit::value(true);
909+
package.insert(key, toml_edit::Item::Table(table));
910+
};
911+
912+
let remove_and_inherit_package_key = |key: &str, manifest: &mut toml_edit::Document| {
913+
remove_package_key(key, manifest);
914+
set_workspace_inherited_package_key(key, manifest);
915+
};
916+
917+
// Try inherit the edition from the workspace if it is not specified.
918+
if opts.edition.is_none() && workspace_package_keys.contains_key("edition") {
919+
remove_and_inherit_package_key("edition", manifest);
920+
}
921+
922+
// Try inherit the version from the workspace.
923+
if workspace_package_keys.contains_key("version") {
924+
remove_and_inherit_package_key("version", manifest);
925+
}
926+
927+
// Try inherit the publish from the workspace if it is not specified.
928+
if opts.registry.is_none() && workspace_package_keys.contains_key("publish") {
929+
remove_and_inherit_package_key("publish", manifest);
930+
}
931+
932+
// Inherit other keys from the workspace.
933+
for (key, _) in workspace_package_keys
934+
.iter()
935+
.filter(|(key, _)| !["edition", "version", "publish"].contains(key))
936+
{
937+
set_workspace_inherited_package_key(key, manifest);
938+
}
939+
}

0 commit comments

Comments
 (0)