Stabilize workspace inheritance

This commit is contained in:
Scott Schafer 2022-07-23 09:36:49 -05:00
parent 168747c028
commit 2c810afda9
45 changed files with 165 additions and 277 deletions

View File

@ -416,7 +416,7 @@ features! {
(unstable, profile_rustflags, "", "reference/unstable.html#profile-rustflags-option"), (unstable, profile_rustflags, "", "reference/unstable.html#profile-rustflags-option"),
// Allow specifying rustflags directly in a profile // Allow specifying rustflags directly in a profile
(unstable, workspace_inheritance, "", "reference/unstable.html#workspace-inheritance"), (stable, workspace_inheritance, "1.64", "reference/unstable.html#workspace-inheritance"),
} }
pub struct Feature { pub struct Feature {

View File

@ -1017,19 +1017,16 @@ pub enum MaybeWorkspace<T> {
impl<T> MaybeWorkspace<T> { impl<T> MaybeWorkspace<T> {
fn resolve<'a>( fn resolve<'a>(
self, self,
cargo_features: &Features,
label: &str, label: &str,
get_ws_field: impl FnOnce() -> CargoResult<T>, get_ws_field: impl FnOnce() -> CargoResult<T>,
) -> CargoResult<T> { ) -> CargoResult<T> {
match self { match self {
MaybeWorkspace::Defined(value) => Ok(value), MaybeWorkspace::Defined(value) => Ok(value),
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => { MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => get_ws_field()
cargo_features.require(Feature::workspace_inheritance())?; .context(format!(
get_ws_field().context(format!(
"error inheriting `{}` from workspace root manifest's `workspace.package.{}`", "error inheriting `{}` from workspace root manifest's `workspace.package.{}`",
label, label label, label
)) )),
}
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: false }) => Err(anyhow!( MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: false }) => Err(anyhow!(
"`workspace=false` is unsupported for `package.{}`", "`workspace=false` is unsupported for `package.{}`",
label, label,
@ -1592,7 +1589,7 @@ impl TomlManifest {
let version = project let version = project
.version .version
.clone() .clone()
.resolve(&features, "version", || inherit()?.version())?; .resolve("version", || inherit()?.version())?;
project.version = MaybeWorkspace::Defined(version.clone()); project.version = MaybeWorkspace::Defined(version.clone());
@ -1600,7 +1597,7 @@ impl TomlManifest {
let edition = if let Some(edition) = project.edition.clone() { let edition = if let Some(edition) = project.edition.clone() {
let edition: Edition = edition let edition: Edition = edition
.resolve(&features, "edition", || inherit()?.edition())? .resolve("edition", || inherit()?.edition())?
.parse() .parse()
.with_context(|| "failed to parse the `edition` key")?; .with_context(|| "failed to parse the `edition` key")?;
project.edition = Some(MaybeWorkspace::Defined(edition.to_string())); project.edition = Some(MaybeWorkspace::Defined(edition.to_string()));
@ -1625,7 +1622,7 @@ impl TomlManifest {
let rust_version = if let Some(rust_version) = &project.rust_version { let rust_version = if let Some(rust_version) = &project.rust_version {
let rust_version = rust_version let rust_version = rust_version
.clone() .clone()
.resolve(&features, "rust_version", || inherit()?.rust_version())?; .resolve("rust_version", || inherit()?.rust_version())?;
let req = match semver::VersionReq::parse(&rust_version) { let req = match semver::VersionReq::parse(&rust_version) {
// Exclude semver operators like `^` and pre-release identifiers // Exclude semver operators like `^` and pre-release identifiers
Ok(req) if rust_version.chars().all(|c| c.is_ascii_digit() || c == '.') => req, Ok(req) if rust_version.chars().all(|c| c.is_ascii_digit() || c == '.') => req,
@ -1716,7 +1713,6 @@ impl TomlManifest {
}; };
fn process_dependencies( fn process_dependencies(
features: &Features,
cx: &mut Context<'_, '_>, cx: &mut Context<'_, '_>,
new_deps: Option<&BTreeMap<String, TomlDependency>>, new_deps: Option<&BTreeMap<String, TomlDependency>>,
kind: Option<DepKind>, kind: Option<DepKind>,
@ -1736,7 +1732,7 @@ impl TomlManifest {
let mut deps: BTreeMap<String, TomlDependency> = BTreeMap::new(); let mut deps: BTreeMap<String, TomlDependency> = BTreeMap::new();
for (n, v) in dependencies.iter() { for (n, v) in dependencies.iter() {
let resolved = v.clone().resolve(features, n, cx, || inherit())?; let resolved = v.clone().resolve(n, cx, || inherit())?;
let dep = resolved.to_dependency(n, cx, kind)?; let dep = resolved.to_dependency(n, cx, kind)?;
validate_package_name(dep.name_in_toml().as_str(), "dependency name", "")?; validate_package_name(dep.name_in_toml().as_str(), "dependency name", "")?;
cx.deps.push(dep); cx.deps.push(dep);
@ -1747,7 +1743,6 @@ impl TomlManifest {
// Collect the dependencies. // Collect the dependencies.
let dependencies = process_dependencies( let dependencies = process_dependencies(
&features,
&mut cx, &mut cx,
me.dependencies.as_ref(), me.dependencies.as_ref(),
None, None,
@ -1762,7 +1757,6 @@ impl TomlManifest {
.as_ref() .as_ref()
.or_else(|| me.dev_dependencies2.as_ref()); .or_else(|| me.dev_dependencies2.as_ref());
let dev_deps = process_dependencies( let dev_deps = process_dependencies(
&features,
&mut cx, &mut cx,
dev_deps, dev_deps,
Some(DepKind::Development), Some(DepKind::Development),
@ -1777,7 +1771,6 @@ impl TomlManifest {
.as_ref() .as_ref()
.or_else(|| me.build_dependencies2.as_ref()); .or_else(|| me.build_dependencies2.as_ref());
let build_deps = process_dependencies( let build_deps = process_dependencies(
&features,
&mut cx, &mut cx,
build_deps, build_deps,
Some(DepKind::Build), Some(DepKind::Build),
@ -1793,7 +1786,6 @@ impl TomlManifest {
Some(platform) Some(platform)
}; };
let deps = process_dependencies( let deps = process_dependencies(
&features,
&mut cx, &mut cx,
platform.dependencies.as_ref(), platform.dependencies.as_ref(),
None, None,
@ -1809,7 +1801,6 @@ impl TomlManifest {
.as_ref() .as_ref()
.or_else(|| platform.build_dependencies2.as_ref()); .or_else(|| platform.build_dependencies2.as_ref());
let build_deps = process_dependencies( let build_deps = process_dependencies(
&features,
&mut cx, &mut cx,
build_deps, build_deps,
Some(DepKind::Build), Some(DepKind::Build),
@ -1825,7 +1816,6 @@ impl TomlManifest {
.as_ref() .as_ref()
.or_else(|| platform.dev_dependencies2.as_ref()); .or_else(|| platform.dev_dependencies2.as_ref());
let dev_deps = process_dependencies( let dev_deps = process_dependencies(
&features,
&mut cx, &mut cx,
dev_deps, dev_deps,
Some(DepKind::Development), Some(DepKind::Development),
@ -1872,13 +1862,13 @@ impl TomlManifest {
let exclude = project let exclude = project
.exclude .exclude
.clone() .clone()
.map(|mw| mw.resolve(&features, "exclude", || inherit()?.exclude())) .map(|mw| mw.resolve("exclude", || inherit()?.exclude()))
.transpose()? .transpose()?
.unwrap_or_default(); .unwrap_or_default();
let include = project let include = project
.include .include
.clone() .clone()
.map(|mw| mw.resolve(&features, "include", || inherit()?.include())) .map(|mw| mw.resolve("include", || inherit()?.include()))
.transpose()? .transpose()?
.unwrap_or_default(); .unwrap_or_default();
let empty_features = BTreeMap::new(); let empty_features = BTreeMap::new();
@ -1895,67 +1885,63 @@ impl TomlManifest {
description: project description: project
.description .description
.clone() .clone()
.map(|mw| mw.resolve(&features, "description", || inherit()?.description())) .map(|mw| mw.resolve("description", || inherit()?.description()))
.transpose()?, .transpose()?,
homepage: project homepage: project
.homepage .homepage
.clone() .clone()
.map(|mw| mw.resolve(&features, "homepage", || inherit()?.homepage())) .map(|mw| mw.resolve("homepage", || inherit()?.homepage()))
.transpose()?, .transpose()?,
documentation: project documentation: project
.documentation .documentation
.clone() .clone()
.map(|mw| mw.resolve(&features, "documentation", || inherit()?.documentation())) .map(|mw| mw.resolve("documentation", || inherit()?.documentation()))
.transpose()?, .transpose()?,
readme: readme_for_project( readme: readme_for_project(
package_root, package_root,
project project
.readme .readme
.clone() .clone()
.map(|mw| mw.resolve(&features, "readme", || inherit()?.readme(package_root))) .map(|mw| mw.resolve("readme", || inherit()?.readme(package_root)))
.transpose()?, .transpose()?,
), ),
authors: project authors: project
.authors .authors
.clone() .clone()
.map(|mw| mw.resolve(&features, "authors", || inherit()?.authors())) .map(|mw| mw.resolve("authors", || inherit()?.authors()))
.transpose()? .transpose()?
.unwrap_or_default(), .unwrap_or_default(),
license: project license: project
.license .license
.clone() .clone()
.map(|mw| mw.resolve(&features, "license", || inherit()?.license())) .map(|mw| mw.resolve("license", || inherit()?.license()))
.transpose()?, .transpose()?,
license_file: project license_file: project
.license_file .license_file
.clone() .clone()
.map(|mw| { .map(|mw| mw.resolve("license", || inherit()?.license_file(package_root)))
mw.resolve(&features, "license", || {
inherit()?.license_file(package_root)
})
})
.transpose()?, .transpose()?,
repository: project repository: project
.repository .repository
.clone() .clone()
.map(|mw| mw.resolve(&features, "repository", || inherit()?.repository())) .map(|mw| mw.resolve("repository", || inherit()?.repository()))
.transpose()?, .transpose()?,
keywords: project keywords: project
.keywords .keywords
.clone() .clone()
.map(|mw| mw.resolve(&features, "keywords", || inherit()?.keywords())) .map(|mw| mw.resolve("keywords", || inherit()?.keywords()))
.transpose()? .transpose()?
.unwrap_or_default(), .unwrap_or_default(),
categories: project categories: project
.categories .categories
.clone() .clone()
.map(|mw| mw.resolve(&features, "categories", || inherit()?.categories())) .map(|mw| mw.resolve("categories", || inherit()?.categories()))
.transpose()? .transpose()?
.unwrap_or_default(), .unwrap_or_default(),
badges: me badges: me
.badges .badges
.clone() .clone()
.map(|mw| mw.resolve(&features, "badges", || inherit()?.badges())) .map(|mw| mw.resolve("badges", || inherit()?.badges()))
.transpose()? .transpose()?
.unwrap_or_default(), .unwrap_or_default(),
links: project.links.clone(), links: project.links.clone(),
@ -2015,11 +2001,10 @@ impl TomlManifest {
profiles.validate(&features, &mut warnings)?; profiles.validate(&features, &mut warnings)?;
} }
let publish = project.publish.clone().map(|publish| { let publish = project
publish .publish
.resolve(&features, "publish", || inherit()?.publish()) .clone()
.unwrap() .map(|publish| publish.resolve("publish", || inherit()?.publish()).unwrap());
});
project.publish = publish.clone().map(|p| MaybeWorkspace::Defined(p)); project.publish = publish.clone().map(|p| MaybeWorkspace::Defined(p));
@ -2479,7 +2464,6 @@ impl<P: ResolveToPath + Clone> TomlDependency<P> {
impl TomlDependency { impl TomlDependency {
fn resolve<'a>( fn resolve<'a>(
self, self,
cargo_features: &Features,
label: &str, label: &str,
cx: &mut Context<'_, '_>, cx: &mut Context<'_, '_>,
get_inheritable: impl FnOnce() -> CargoResult<&'a InheritableFields>, get_inheritable: impl FnOnce() -> CargoResult<&'a InheritableFields>,
@ -2492,7 +2476,6 @@ impl TomlDependency {
features, features,
optional, optional,
}) => { }) => {
cargo_features.require(Feature::workspace_inheritance())?;
let inheritable = get_inheritable()?; let inheritable = get_inheritable()?;
inheritable.get_dependency(label).context(format!( inheritable.get_dependency(label).context(format!(
"error reading `dependencies.{}` from workspace root manifest's `workspace.dependencies.{}`", "error reading `dependencies.{}` from workspace root manifest's `workspace.dependencies.{}`",

View File

@ -454,8 +454,44 @@ following to the above manifest:
log-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error! log-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error!
``` ```
### Inheriting a dependency from a workspace
Dependencies can be inherited from a workspace by specifying the
dependency in the workspace's [`[workspace.dependencies]`][workspace.dependencies] table.
After that add it to the `[dependencies]` table with `workspace = true`.
Along with the `workspace` key, dependencies can also include these keys:
- [`optional`][optional]: Note that the`[workspace.dependencies]` table is not allowed to specify `optional`.
- [`features`][features]: These are additive with the features declared in the `[workspace.dependencies]`
Other than `optional` and `features`, inherited dependencies cannot use any other
dependency key (such as `version` or `default-features`).
Dependencies in the `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`, and
`[target."...".dependencies]` sections support the ability to reference the
`[workspace.dependencies]` definition of dependencies.
```toml
[project]
name = "bar"
version = "0.2.0"
[dependencies]
regex = { workspace = true, features = ["unicode"] }
[build-dependencies]
cc.workspace = true
[dev-dependencies]
rand = { workspace = true, optional = true }
```
[crates.io]: https://crates.io/ [crates.io]: https://crates.io/
[dev-dependencies]: #development-dependencies [dev-dependencies]: #development-dependencies
[workspace.dependencies]: workspaces.md#the-workspacedependencies-table
[optional]: features.md#optional-dependencies
[features]: features.md
<script> <script>
(function() { (function() {

View File

@ -68,7 +68,6 @@ Each new feature described below should explain how to use it.
* [avoid-dev-deps](#avoid-dev-deps) — Prevents the resolver from including dev-dependencies during resolution. * [avoid-dev-deps](#avoid-dev-deps) — Prevents the resolver from including dev-dependencies during resolution.
* [minimal-versions](#minimal-versions) — Forces the resolver to use the lowest compatible version instead of the highest. * [minimal-versions](#minimal-versions) — Forces the resolver to use the lowest compatible version instead of the highest.
* [public-dependency](#public-dependency) — Allows dependencies to be classified as either public or private. * [public-dependency](#public-dependency) — Allows dependencies to be classified as either public or private.
* [workspace-inheritance](#workspace-inheritance) - Allow workspace members to share fields and dependencies
* Output behavior * Output behavior
* [out-dir](#out-dir) — Adds a directory where artifacts are copied to. * [out-dir](#out-dir) — Adds a directory where artifacts are copied to.
* [terminal-width](#terminal-width) — Tells rustc the width of the terminal so that long diagnostic messages can be truncated to be more readable. * [terminal-width](#terminal-width) — Tells rustc the width of the terminal so that long diagnostic messages can be truncated to be more readable.
@ -1536,3 +1535,12 @@ setting the default target platform triples.
The `--crate-type` flag for `cargo rustc` has been stabilized in the 1.64 The `--crate-type` flag for `cargo rustc` has been stabilized in the 1.64
release. See the [`cargo rustc` documentation](../commands/cargo-rustc.md) release. See the [`cargo rustc` documentation](../commands/cargo-rustc.md)
for more information. for more information.
### Workspace Inheritance
Workspace Inheritance has been stabilized in the 1.64 release.
See [workspace.package](workspaces.md#the-workspacepackage-table),
[workspace.dependencies](workspaces.md#the-workspacedependencies-table),
and [inheriting-a-dependency-from-a-workspace](specifying-dependencies.md#inheriting-a-dependency-from-a-workspace)
for more information.

View File

@ -112,6 +112,90 @@ external tools may wish to use them in a consistent fashion, such as referring
to the data in `workspace.metadata` if data is missing from `package.metadata`, to the data in `workspace.metadata` if data is missing from `package.metadata`,
if that makes sense for the tool in question. if that makes sense for the tool in question.
### The `workspace.package` table
The `workspace.package` table is where you define keys that can be
inherited by members of a workspace. These keys can be inherited by
defining them in the member package with `{key}.workspace = true`.
Keys that are supported:
| | |
|----------------|-----------------|
| `authors` | `categories` |
| `description` | `documentation` |
| `edition` | `exclude` |
| `homepage` | `include` |
| `keywords` | `license` |
| `license-file` | `publish` |
| `readme` | `repository` |
| `rust-version` | `version` |
- `license-file` and `readme` are relative to the workspace root
- `include` and `exclude` are relative to your package root
Example:
```toml
# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["bar"]
[workspace.package]
version = "1.2.3"
authors = ["Nice Folks"]
description = "A short description of my package"
documentation = "https://example.com/bar"
```
```toml
# [PROJECT_DIR]/bar/Cargo.toml
[package]
name = "bar"
version.workspace = true
authors.workspace = true
description.workspace = true
documentation.workspace = true
```
### The `workspace.dependencies` table
The `workspace.dependencies` table is where you define dependencies to be
inherited by members of a workspace.
Specifying a workspace dependency is similar to [package dependencies][specifying-dependencies] except:
- Dependencies from this table cannot be declared as `optional`
- [`features`][features] declared in this table are additive with the `features` from `[dependencies]`
You can then [inherit the workspace dependency as a package dependency][inheriting-a-dependency-from-a-workspace]
Example:
```toml
# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["bar"]
[workspace.dependencies]
cc = "1.0.73"
rand = "0.8.5"
regex = { version = "1.6.0", default-features = false, features = ["std"] }
```
```toml
# [PROJECT_DIR]/bar/Cargo.toml
[project]
name = "bar"
version = "0.2.0"
[dependencies]
regex = { workspace = true, features = ["unicode"] }
[build-dependencies]
cc.workspace = true
[dev-dependencies]
rand.workspace = true
```
[package]: manifest.md#the-package-section [package]: manifest.md#the-package-section
[package-metadata]: manifest.md#the-metadata-table [package-metadata]: manifest.md#the-metadata-table
[output directory]: ../guide/build-cache.md [output directory]: ../guide/build-cache.md
@ -122,3 +206,6 @@ if that makes sense for the tool in question.
[`package.workspace`]: manifest.md#the-workspace-field [`package.workspace`]: manifest.md#the-workspace-field
[globs]: https://docs.rs/glob/0.3.0/glob/struct.Pattern.html [globs]: https://docs.rs/glob/0.3.0/glob/struct.Pattern.html
[`cargo build`]: ../commands/cargo-build.md [`cargo build`]: ../commands/cargo-build.md
[specifying-dependencies]: specifying-dependencies.md
[features]: features.md
[inheriting-a-dependency-from-a-workspace]: specifying-dependencies.md#inheriting-a-dependency-from-a-workspace

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -13,7 +13,6 @@ fn detect_workspace_inherit() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "-p", "bar"]) .args(["foo", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -13,7 +13,6 @@ fn detect_workspace_inherit_features() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "-p", "bar", "--features", "test"]) .args(["foo", "-p", "bar", "--features", "test"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -13,7 +13,6 @@ fn detect_workspace_inherit_optional() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "-p", "bar", "--optional"]) .args(["foo", "-p", "bar", "--optional"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -11,7 +11,6 @@ fn invalid_key_inherit_dependency() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "--default-features", "-p", "bar"]) .args(["foo", "--default-features", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -11,7 +11,6 @@ fn invalid_key_overwrite_inherit_dependency() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "--default-features", "-p", "bar"]) .args(["foo", "--default-features", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -11,7 +11,6 @@ fn invalid_key_rename_inherit_dependency() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["--rename", "foo", "foo-alt", "-p", "bar"]) .args(["--rename", "foo", "foo-alt", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -11,7 +11,6 @@ fn merge_activated_features() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["zworkspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "-p", "bar"]) .args(["foo", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -11,7 +11,6 @@ fn overwrite_inherit_features_noop() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "-p", "bar"]) .args(["foo", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -13,7 +13,6 @@ fn overwrite_inherit_noop() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "-p", "bar"]) .args(["foo", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -13,7 +13,6 @@ fn overwrite_inherit_optional_noop() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "-p", "bar"]) .args(["foo", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -13,7 +13,6 @@ fn overwrite_workspace_dep() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["zworkspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "--path", "./dependency", "-p", "bar"]) .args(["foo", "--path", "./dependency", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -13,7 +13,6 @@ fn overwrite_workspace_dep_features() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "--path", "./dependency", "-p", "bar"]) .args(["foo", "--path", "./dependency", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -11,7 +11,6 @@ fn unknown_inherited_feature() {
let cwd = &project_root; let cwd = &project_root;
snapbox::cmd::Command::cargo_ui() snapbox::cmd::Command::cargo_ui()
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.arg("add") .arg("add")
.args(["foo", "-p", "bar"]) .args(["foo", "-p", "bar"])
.current_dir(cwd) .current_dir(cwd)

View File

@ -1,5 +1,3 @@
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.0.0" version = "0.0.0"

View File

@ -71,8 +71,6 @@ fn deny_optional_dependencies() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[workspace] [workspace]
members = ["bar"] members = ["bar"]
@ -104,7 +102,6 @@ Caused by:
dep1 is optional, but workspace dependencies cannot be optional dep1 is optional, but workspace dependencies cannot be optional
", ",
) )
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.run(); .run();
} }
@ -118,7 +115,6 @@ fn inherit_own_workspace_fields() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
badges.workspace = true badges.workspace = true
[package] [package]
@ -164,9 +160,7 @@ fn inherit_own_workspace_fields() {
.file("bar.txt", "") // should be included when packaging .file("bar.txt", "") // should be included when packaging
.build(); .build();
p.cargo("publish --token sekrit") p.cargo("publish --token sekrit").run();
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.run();
publish::validate_upload_with_contents( publish::validate_upload_with_contents(
r#" r#"
{ {
@ -204,8 +198,6 @@ fn inherit_own_workspace_fields() {
"Cargo.toml", "Cargo.toml",
&format!( &format!(
r#"{} r#"{}
cargo-features = ["workspace-inheritance"]
[package] [package]
edition = "2018" edition = "2018"
rust-version = "1.60" rust-version = "1.60"
@ -243,8 +235,6 @@ fn inherit_own_dependencies() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[project] [project]
name = "bar" name = "bar"
version = "0.2.0" version = "0.2.0"
@ -276,7 +266,6 @@ fn inherit_own_dependencies() {
Package::new("dep-dev", "0.5.2").publish(); Package::new("dep-dev", "0.5.2").publish();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_stderr( .with_stderr(
"\ "\
[UPDATING] `[..]` index [UPDATING] `[..]` index
@ -290,16 +279,12 @@ fn inherit_own_dependencies() {
) )
.run(); .run();
p.cargo("check") p.cargo("check").run();
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.run();
let lockfile = p.read_lockfile(); let lockfile = p.read_lockfile();
assert!(lockfile.contains("dep")); assert!(lockfile.contains("dep"));
assert!(lockfile.contains("dep-dev")); assert!(lockfile.contains("dep-dev"));
assert!(lockfile.contains("dep-build")); assert!(lockfile.contains("dep-build"));
p.cargo("publish --token sekrit") p.cargo("publish --token sekrit").run();
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.run();
publish::validate_upload_with_contents( publish::validate_upload_with_contents(
r#" r#"
{ {
@ -359,8 +344,6 @@ fn inherit_own_dependencies() {
"Cargo.toml", "Cargo.toml",
&format!( &format!(
r#"{} r#"{}
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.2.0" version = "0.2.0"
@ -387,8 +370,6 @@ fn inherit_own_detailed_dependencies() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[project] [project]
name = "bar" name = "bar"
version = "0.2.0" version = "0.2.0"
@ -412,7 +393,6 @@ fn inherit_own_detailed_dependencies() {
.publish(); .publish();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_stderr( .with_stderr(
"\ "\
[UPDATING] `[..]` index [UPDATING] `[..]` index
@ -425,14 +405,10 @@ fn inherit_own_detailed_dependencies() {
) )
.run(); .run();
p.cargo("check") p.cargo("check").run();
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.run();
let lockfile = p.read_lockfile(); let lockfile = p.read_lockfile();
assert!(lockfile.contains("dep")); assert!(lockfile.contains("dep"));
p.cargo("publish --token sekrit") p.cargo("publish --token sekrit").run();
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.run();
publish::validate_upload_with_contents( publish::validate_upload_with_contents(
r#" r#"
{ {
@ -472,8 +448,6 @@ fn inherit_own_detailed_dependencies() {
"Cargo.toml", "Cargo.toml",
&format!( &format!(
r#"{} r#"{}
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.2.0" version = "0.2.0"
@ -499,8 +473,6 @@ fn inherit_from_own_undefined_field() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "foo" name = "foo"
version = "1.2.5" version = "1.2.5"
@ -515,7 +487,6 @@ fn inherit_from_own_undefined_field() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
"\ "\
@ -548,8 +519,6 @@ fn inherited_dependencies_union_features() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[project] [project]
name = "bar" name = "bar"
version = "0.2.0" version = "0.2.0"
@ -567,7 +536,6 @@ fn inherited_dependencies_union_features() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_stderr( .with_stderr(
"\ "\
[UPDATING] `[..]` index [UPDATING] `[..]` index
@ -628,7 +596,6 @@ fn inherit_workspace_fields() {
"bar/Cargo.toml", "bar/Cargo.toml",
r#" r#"
badges.workspace = true badges.workspace = true
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
workspace = ".." workspace = ".."
@ -657,10 +624,7 @@ fn inherit_workspace_fields() {
.file("bar/bar.txt", "") // should be included when packaging .file("bar/bar.txt", "") // should be included when packaging
.build(); .build();
p.cargo("publish --token sekrit") p.cargo("publish --token sekrit").cwd("bar").run();
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.cwd("bar")
.run();
publish::validate_upload_with_contents( publish::validate_upload_with_contents(
r#" r#"
{ {
@ -700,8 +664,6 @@ fn inherit_workspace_fields() {
"Cargo.toml", "Cargo.toml",
&format!( &format!(
r#"{} r#"{}
cargo-features = ["workspace-inheritance"]
[package] [package]
edition = "2018" edition = "2018"
rust-version = "1.60" rust-version = "1.60"
@ -754,8 +716,6 @@ fn inherit_dependencies() {
.file( .file(
"bar/Cargo.toml", "bar/Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[project] [project]
workspace = ".." workspace = ".."
name = "bar" name = "bar"
@ -777,7 +737,6 @@ fn inherit_dependencies() {
Package::new("dep-dev", "0.5.2").publish(); Package::new("dep-dev", "0.5.2").publish();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_stderr( .with_stderr(
"\ "\
[UPDATING] `[..]` index [UPDATING] `[..]` index
@ -791,17 +750,12 @@ fn inherit_dependencies() {
) )
.run(); .run();
p.cargo("check") p.cargo("check").run();
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.run();
let lockfile = p.read_lockfile(); let lockfile = p.read_lockfile();
assert!(lockfile.contains("dep")); assert!(lockfile.contains("dep"));
assert!(lockfile.contains("dep-dev")); assert!(lockfile.contains("dep-dev"));
assert!(lockfile.contains("dep-build")); assert!(lockfile.contains("dep-build"));
p.cargo("publish --token sekrit") p.cargo("publish --token sekrit").cwd("bar").run();
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.cwd("bar")
.run();
publish::validate_upload_with_contents( publish::validate_upload_with_contents(
r#" r#"
{ {
@ -861,8 +815,6 @@ fn inherit_dependencies() {
"Cargo.toml", "Cargo.toml",
&format!( &format!(
r#"{} r#"{}
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "0.2.0" version = "0.2.0"
@ -898,8 +850,6 @@ fn inherit_target_dependencies() {
.file( .file(
"bar/Cargo.toml", "bar/Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[project] [project]
workspace = ".." workspace = ".."
name = "bar" name = "bar"
@ -917,7 +867,6 @@ fn inherit_target_dependencies() {
Package::new("dep", "0.1.2").publish(); Package::new("dep", "0.1.2").publish();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_stderr( .with_stderr(
"\ "\
[UPDATING] `[..]` index [UPDATING] `[..]` index
@ -951,8 +900,6 @@ fn inherit_dependency_override_optional() {
.file( .file(
"bar/Cargo.toml", "bar/Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[project] [project]
workspace = ".." workspace = ".."
name = "bar" name = "bar"
@ -966,7 +913,6 @@ fn inherit_dependency_override_optional() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_stderr( .with_stderr(
"\ "\
[UPDATING] `[..]` index [UPDATING] `[..]` index
@ -992,8 +938,6 @@ fn inherit_dependency_features() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[project] [project]
name = "bar" name = "bar"
version = "0.2.0" version = "0.2.0"
@ -1011,7 +955,6 @@ fn inherit_dependency_features() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_stderr( .with_stderr(
"\ "\
[UPDATING] `[..]` index [UPDATING] `[..]` index
@ -1068,8 +1011,6 @@ fn inherit_detailed_dependencies() {
.file( .file(
"bar/Cargo.toml", "bar/Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[project] [project]
workspace = ".." workspace = ".."
name = "bar" name = "bar"
@ -1085,7 +1026,6 @@ fn inherit_detailed_dependencies() {
let git_root = git_project.root(); let git_root = git_project.root();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_stderr(&format!( .with_stderr(&format!(
"\ "\
[UPDATING] git repository `{}`\n\ [UPDATING] git repository `{}`\n\
@ -1113,8 +1053,6 @@ fn inherit_path_dependencies() {
.file( .file(
"bar/Cargo.toml", "bar/Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[project] [project]
workspace = ".." workspace = ".."
name = "bar" name = "bar"
@ -1130,7 +1068,6 @@ fn inherit_path_dependencies() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_stderr( .with_stderr(
"\ "\
[COMPILING] dep v0.9.0 ([CWD]/dep) [COMPILING] dep v0.9.0 ([CWD]/dep)
@ -1174,7 +1111,6 @@ fn error_workspace_false() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.cwd("bar") .cwd("bar")
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
@ -1198,7 +1134,6 @@ fn error_workspace_dependency_looked_for_workspace_itself() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
version = "1.2.3" version = "1.2.3"
@ -1219,7 +1154,6 @@ fn error_workspace_dependency_looked_for_workspace_itself() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
"\ "\
@ -1251,8 +1185,6 @@ fn error_malformed_workspace_root() {
.file( .file(
"bar/Cargo.toml", "bar/Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
workspace = ".." workspace = ".."
@ -1264,7 +1196,6 @@ fn error_malformed_workspace_root() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.cwd("bar") .cwd("bar")
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
@ -1296,8 +1227,6 @@ fn error_no_root_workspace() {
.file( .file(
"bar/Cargo.toml", "bar/Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
workspace = ".." workspace = ".."
@ -1311,7 +1240,6 @@ fn error_no_root_workspace() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.cwd("bar") .cwd("bar")
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
@ -1344,8 +1272,6 @@ fn error_inherit_unspecified_dependency() {
.file( .file(
"bar/Cargo.toml", "bar/Cargo.toml",
r#" r#"
cargo-features = ["workspace-inheritance"]
[package] [package]
name = "bar" name = "bar"
workspace = ".." workspace = ".."
@ -1359,7 +1285,6 @@ fn error_inherit_unspecified_dependency() {
.build(); .build();
p.cargo("build") p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.cwd("bar") .cwd("bar")
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
@ -1375,89 +1300,3 @@ Caused by:
) )
.run(); .run();
} }
#[cargo_test]
fn workspace_inheritance_not_enabled() {
registry::init();
let p = project().build();
let _ = git::repo(&paths::root().join("foo"))
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "1.2.5"
authors = ["rustaceans"]
description.workspace = true
[workspace]
members = []
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build")
.masquerade_as_nightly_cargo(&["workspace-inheritance"])
.with_status(101)
.with_stderr(
"\
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
Caused by:
feature `workspace-inheritance` is required
The package requires the Cargo feature called `workspace-inheritance`, \
but that feature is not stabilized in this version of Cargo (1.[..]).
Consider adding `cargo-features = [\"workspace-inheritance\"]` to the top of Cargo.toml \
(above the [package] table) to tell Cargo you are opting in to use this unstable feature.
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#workspace-inheritance \
for more information about the status of this feature.
",
)
.run();
}
#[cargo_test]
fn nightly_required() {
registry::init();
let p = project().build();
let _ = git::repo(&paths::root().join("foo"))
.file(
"Cargo.toml",
r#"
cargo-features = ["workspace-inheritance"]
[package]
name = "foo"
version = "1.2.5"
authors = ["rustaceans"]
description.workspace = true
[workspace]
members = []
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build")
.with_status(101)
.with_stderr(
"\
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
Caused by:
the cargo feature `workspace-inheritance` requires a nightly version of Cargo, \
but this is the `stable` channel
See [..]
See https://doc.rust-lang.org/[..]cargo/reference/unstable.html#workspace-inheritance \
for more information about using this feature.
",
)
.run();
}