diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 16d67ee8559..0cedcd896c8 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1056,8 +1056,8 @@ pub struct TomlProject { #[serde(rename = "forced-target")] forced_target: Option, links: Option, - exclude: Option>, - include: Option>, + exclude: Option>>, + include: Option>>, publish: Option>, workspace: Option, im_a_teapot: Option, @@ -1123,6 +1123,8 @@ pub struct InheritableFields { publish: Option, edition: Option, badges: Option>>, + exclude: Option>, + include: Option>, #[serde(rename = "rust-version")] rust_version: Option, // We use skip here since it will never be present when deserializing @@ -1271,6 +1273,20 @@ impl InheritableFields { ) } + pub fn exclude(&self) -> CargoResult> { + self.exclude.clone().map_or( + Err(anyhow!("`workspace.package.exclude` was not defined")), + |d| Ok(d), + ) + } + + pub fn include(&self) -> CargoResult> { + self.include.clone().map_or( + Err(anyhow!("`workspace.package.include` was not defined")), + |d| Ok(d), + ) + } + pub fn ws_root(&self) -> &PathBuf { &self.ws_root } @@ -1824,8 +1840,26 @@ impl TomlManifest { } } - let exclude = project.exclude.clone().unwrap_or_default(); - let include = project.include.clone().unwrap_or_default(); + let exclude = project + .exclude + .clone() + .map(|mw| { + mw.resolve(&features, "exclude", || { + get_ws(config, resolved_path.clone(), workspace_config.clone())?.exclude() + }) + }) + .transpose()? + .unwrap_or_default(); + let include = project + .include + .clone() + .map(|mw| { + mw.resolve(&features, "include", || { + get_ws(config, resolved_path.clone(), workspace_config.clone())?.include() + }) + }) + .transpose()? + .unwrap_or_default(); let empty_features = BTreeMap::new(); let summary = Summary::new( @@ -1992,6 +2026,14 @@ impl TomlManifest { .as_ref() .map(|_| MaybeWorkspace::Defined(metadata.categories.clone())); project.rust_version = rust_version.clone().map(|rv| MaybeWorkspace::Defined(rv)); + project.exclude = project + .exclude + .as_ref() + .map(|_| MaybeWorkspace::Defined(exclude.clone())); + project.include = project + .include + .as_ref() + .map(|_| MaybeWorkspace::Defined(include.clone())); let profiles = me.profile.clone(); if let Some(profiles) = &profiles { diff --git a/tests/testsuite/inheritable_workspace_fields.rs b/tests/testsuite/inheritable_workspace_fields.rs index 3f88045e1a6..ca254d65e55 100644 --- a/tests/testsuite/inheritable_workspace_fields.rs +++ b/tests/testsuite/inheritable_workspace_fields.rs @@ -27,6 +27,8 @@ fn permit_additional_workspace_fields() { publish = false edition = "2018" rust-version = "1.60" + exclude = ["foo.txt"] + include = ["bar.txt", "**/*.rs", "Cargo.toml", "LICENSE", "README.md"] [workspace.package.badges] gitlab = { repository = "https://gitlab.com/rust-lang/rust", branch = "master" } @@ -133,6 +135,8 @@ fn inherit_own_workspace_fields() { publish = { workspace = true } edition = { workspace = true } rust-version = { workspace = true } + exclude = { workspace = true } + include = { workspace = true } [workspace] members = [] @@ -149,11 +153,15 @@ fn inherit_own_workspace_fields() { publish = true edition = "2018" rust-version = "1.60" + exclude = ["foo.txt"] + include = ["bar.txt", "**/*.rs", "Cargo.toml"] [workspace.package.badges] gitlab = { repository = "https://gitlab.com/rust-lang/rust", branch = "master" } "#, ) .file("src/main.rs", "fn main() {}") + .file("foo.txt", "") // should be ignored when packaging + .file("bar.txt", "") // should be included when packaging .build(); p.cargo("publish --token sekrit") @@ -190,6 +198,7 @@ fn inherit_own_workspace_fields() { "Cargo.toml.orig", "src/main.rs", ".cargo_vcs_info.json", + "bar.txt", ], &[( "Cargo.toml", @@ -203,6 +212,12 @@ rust-version = "1.60" name = "foo" version = "1.2.3" authors = ["Rustaceans"] +exclude = ["foo.txt"] +include = [ + "bar.txt", + "**/*.rs", + "Cargo.toml", +] publish = true description = "This is a crate" homepage = "https://www.rust-lang.org" @@ -598,6 +613,8 @@ fn inherit_workspace_fields() { publish = true edition = "2018" rust-version = "1.60" + exclude = ["foo.txt"] + include = ["bar.txt", "**/*.rs", "Cargo.toml", "LICENSE", "README.md"] [workspace.package.badges] gitlab = { repository = "https://gitlab.com/rust-lang/rust", branch = "master" } "#, @@ -625,11 +642,15 @@ fn inherit_workspace_fields() { publish = { workspace = true } edition = { workspace = true } rust-version = { workspace = true } + exclude = { workspace = true } + include = { workspace = true } "#, ) .file("LICENSE", "license") .file("README.md", "README.md") .file("bar/src/main.rs", "fn main() {}") + .file("bar/foo.txt", "") // should be ignored when packaging + .file("bar/bar.txt", "") // should be included when packaging .build(); p.cargo("publish --token sekrit") @@ -669,6 +690,7 @@ fn inherit_workspace_fields() { "README.md", "LICENSE", ".cargo_vcs_info.json", + "bar.txt", ], &[( "Cargo.toml", @@ -682,6 +704,14 @@ rust-version = "1.60" name = "bar" version = "1.2.3" authors = ["Rustaceans"] +exclude = ["foo.txt"] +include = [ + "bar.txt", + "**/*.rs", + "Cargo.toml", + "LICENSE", + "README.md", +] publish = true description = "This is a crate" homepage = "https://www.rust-lang.org"