From 5c9a1269113eb34e88f207241ad6a065656c6e67 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 4 Oct 2023 13:00:37 -0500 Subject: [PATCH 1/6] test(toml): Verify existing version-less behavior --- tests/testsuite/check.rs | 29 +++++++++++++++++++ tests/testsuite/metadata.rs | 55 +++++++++++++++++++++++++++++++++++++ tests/testsuite/package.rs | 30 ++++++++++++++++++++ tests/testsuite/publish.rs | 30 ++++++++++++++++++++ 4 files changed, 144 insertions(+) diff --git a/tests/testsuite/check.rs b/tests/testsuite/check.rs index b74bd620996..8391e8eb587 100644 --- a/tests/testsuite/check.rs +++ b/tests/testsuite/check.rs @@ -1496,3 +1496,32 @@ fn check_unused_manifest_keys() { ) .run(); } + +#[cargo_test] +fn versionless_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .with_stderr( + r#"error: failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + TOML parse error at line 2, column 17 + | + 2 | [package] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + missing field `version` +"#, + ) + .with_status(101) + .run(); +} diff --git a/tests/testsuite/metadata.rs b/tests/testsuite/metadata.rs index fbead4dea97..659514b3a1c 100644 --- a/tests/testsuite/metadata.rs +++ b/tests/testsuite/metadata.rs @@ -4257,3 +4257,58 @@ fn workspace_metadata_with_dependencies_no_deps_artifact() { ) .run(); } + +#[cargo_test] +fn versionless_packages() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + + [dependencies] + foobar = "0.0.1" + baz = { path = "../baz/" } + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + + [dependencies] + foobar = "0.0.1" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + Package::new("foobar", "0.0.1").publish(); + + p.cargo("metadata -q --format-version 1") + .with_stderr( + r#"error: failed to load manifest for workspace member `[CWD]/bar` + +Caused by: + failed to parse manifest at `[CWD]/bar/Cargo.toml` + +Caused by: + TOML parse error at line 2, column 17 + | + 2 | [package] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + missing field `version` +"#, + ) + .with_status(101) + .run(); +} diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index 8a7334d890d..fd4f1a20a93 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -3095,3 +3095,33 @@ src/main.rs &[], ); } + +#[cargo_test] +fn versionless_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "foo" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("package") + .with_stderr( + r#"error: failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + TOML parse error at line 2, column 17 + | + 2 | [package] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + missing field `version` +"#, + ) + .with_status(101) + .run(); +} diff --git a/tests/testsuite/publish.rs b/tests/testsuite/publish.rs index 67569bf3b6a..585a3bb6fe2 100644 --- a/tests/testsuite/publish.rs +++ b/tests/testsuite/publish.rs @@ -3004,3 +3004,33 @@ Caused by: .with_status(101) .run(); } + +#[cargo_test] +fn versionless_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "foo" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("publish") + .with_stderr( + r#"error: failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + TOML parse error at line 2, column 17 + | + 2 | [package] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + missing field `version` +"#, + ) + .with_status(101) + .run(); +} From 0b5ebd445b71d209b1ef3f8cad42b82ac3ad1be9 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 4 Oct 2023 12:23:46 -0500 Subject: [PATCH 2/6] refactor(toml): Use explicit deserialize Unsure if we want to generalize the trim policy but this will make it much easier to support an optional version field in future commits since we can just wrap the type in `Option` Strangely, `UntaggedEnumDeserializer` isn't causing bad error messages, so we can keep using it. --- src/cargo/util/toml/mod.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 42562584331..0191576ceea 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1659,7 +1659,6 @@ pub struct TomlPackage { edition: Option, rust_version: Option, name: InternedString, - #[serde(deserialize_with = "version_trim_whitespace")] version: MaybeWorkspaceSemverVersion, authors: Option, build: Option, @@ -1709,22 +1708,6 @@ impl TomlPackage { } } -fn version_trim_whitespace<'de, D>(deserializer: D) -> Result -where - D: de::Deserializer<'de>, -{ - UntaggedEnumVisitor::new() - .expecting("SemVer version") - .string( - |value| match value.trim().parse().map_err(de::Error::custom) { - Ok(parsed) => Ok(MaybeWorkspace::Defined(parsed)), - Err(e) => Err(e), - }, - ) - .map(|value| value.deserialize().map(MaybeWorkspace::Workspace)) - .deserialize(deserializer) -} - /// This Trait exists to make [`MaybeWorkspace::Workspace`] generic. It makes deserialization of /// [`MaybeWorkspace`] much easier, as well as making error messages for /// [`MaybeWorkspace::resolve`] much nicer @@ -1793,6 +1776,23 @@ impl MaybeWorkspace { //. This already has a `Deserialize` impl from version_trim_whitespace type MaybeWorkspaceSemverVersion = MaybeWorkspace; +impl<'de> de::Deserialize<'de> for MaybeWorkspaceSemverVersion { + fn deserialize(d: D) -> Result + where + D: de::Deserializer<'de>, + { + UntaggedEnumVisitor::new() + .expecting("SemVer version") + .string( + |value| match value.trim().parse().map_err(de::Error::custom) { + Ok(parsed) => Ok(MaybeWorkspace::Defined(parsed)), + Err(e) => Err(e), + }, + ) + .map(|value| value.deserialize().map(MaybeWorkspace::Workspace)) + .deserialize(d) + } +} type MaybeWorkspaceString = MaybeWorkspace; impl<'de> de::Deserialize<'de> for MaybeWorkspaceString { From 1923b5b8629f5ed37158335d5ed71edab790d422 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 4 Oct 2023 12:33:35 -0500 Subject: [PATCH 3/6] feat(toml): Allow versionless packages This defaults the version to `0.0.0` for most of cargo. It is an error to lack a version and have a package publishable. That means you have to add `publish = false`. --- src/cargo/util/toml/mod.rs | 18 ++- src/doc/src/reference/manifest.md | 2 + tests/testsuite/check.rs | 15 +- tests/testsuite/metadata.rs | 255 ++++++++++++++++++++++++++++-- tests/testsuite/package.rs | 28 ++-- tests/testsuite/publish.rs | 17 +- 6 files changed, 290 insertions(+), 45 deletions(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 0191576ceea..6c7add9e814 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -550,11 +550,17 @@ impl TomlManifest { let version = package .version .clone() - .resolve("version", || inherit()?.version())?; + .map(|version| version.resolve("version", || inherit()?.version())) + .transpose()?; - package.version = MaybeWorkspace::Defined(version.clone()); + package.version = version.clone().map(MaybeWorkspace::Defined); - let pkgid = package.to_package_id(source_id, version)?; + let pkgid = package.to_package_id( + source_id, + version + .clone() + .unwrap_or_else(|| semver::Version::new(0, 0, 0)), + )?; let edition = if let Some(edition) = package.edition.clone() { let edition: Edition = edition @@ -1009,6 +1015,10 @@ impl TomlManifest { None | Some(VecStringOrBool::Bool(true)) => None, }; + if version.is_none() && publish != Some(vec![]) { + bail!("`package.publish` requires `package.version` be specified"); + } + if summary.features().contains_key("default-features") { warnings.push( "`default-features = [\"..\"]` was found in [features]. \ @@ -1659,7 +1669,7 @@ pub struct TomlPackage { edition: Option, rust_version: Option, name: InternedString, - version: MaybeWorkspaceSemverVersion, + version: Option, authors: Option, build: Option, metabuild: Option, diff --git a/src/doc/src/reference/manifest.md b/src/doc/src/reference/manifest.md index b203f4053d6..2f4920c0ba5 100644 --- a/src/doc/src/reference/manifest.md +++ b/src/doc/src/reference/manifest.md @@ -109,6 +109,8 @@ resolve dependencies, and for guidelines on setting your own version. See the [SemVer compatibility] chapter for more details on exactly what constitutes a breaking change. +This field is optional and defaults to `0.0.0`. + [Resolver]: resolver.md [SemVer compatibility]: semver.md diff --git a/tests/testsuite/check.rs b/tests/testsuite/check.rs index 8391e8eb587..f7c865dedba 100644 --- a/tests/testsuite/check.rs +++ b/tests/testsuite/check.rs @@ -1506,22 +1506,17 @@ fn versionless_package() { [package] name = "foo" description = "foo" + publish = false "#, ) .file("src/lib.rs", "") .build(); p.cargo("check") .with_stderr( - r#"error: failed to parse manifest at `[CWD]/Cargo.toml` - -Caused by: - TOML parse error at line 2, column 17 - | - 2 | [package] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - missing field `version` -"#, + "\ +[CHECKING] foo v0.0.0 ([CWD]) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +", ) - .with_status(101) .run(); } diff --git a/tests/testsuite/metadata.rs b/tests/testsuite/metadata.rs index 659514b3a1c..223a8f70784 100644 --- a/tests/testsuite/metadata.rs +++ b/tests/testsuite/metadata.rs @@ -4273,6 +4273,7 @@ fn versionless_packages() { r#" [package] name = "bar" + publish = false [dependencies] foobar = "0.0.1" @@ -4285,6 +4286,7 @@ fn versionless_packages() { r#" [package] name = "baz" + publish = false [dependencies] foobar = "0.0.1" @@ -4295,20 +4297,247 @@ fn versionless_packages() { Package::new("foobar", "0.0.1").publish(); p.cargo("metadata -q --format-version 1") - .with_stderr( - r#"error: failed to load manifest for workspace member `[CWD]/bar` - -Caused by: - failed to parse manifest at `[CWD]/bar/Cargo.toml` - -Caused by: - TOML parse error at line 2, column 17 - | - 2 | [package] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - missing field `version` + .with_json( + r#" +{ + "packages": [ + { + "name": "bar", + "version": "0.0.0", + "id": "bar 0.0.0 [..]", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [ + { + "name": "baz", + "source": null, + "req": "*", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": null, + "path": "[..]/baz" + }, + { + "name": "foobar", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "req": "^0.0.1", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": null + } + ], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "bar", + "src_path": "[..]/bar/src/lib.rs", + "edition": "2015", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "[..]/bar/Cargo.toml", + "metadata": null, + "publish": [], + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "baz", + "version": "0.0.0", + "id": "baz 0.0.0 [..]", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [ + { + "name": "foobar", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "req": "^0.0.1", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": null + } + ], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "baz", + "src_path": "[..]/baz/src/lib.rs", + "edition": "2015", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "[..]/baz/Cargo.toml", + "metadata": null, + "publish": [], + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "foobar", + "version": "0.0.1", + "id": "foobar 0.0.1 [..]", + "license": null, + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "foobar", + "src_path": "[..]/foobar-0.0.1/src/lib.rs", + "edition": "2015", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "[..]/foobar-0.0.1/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": null + } + ], + "workspace_members": [ + "bar 0.0.0 [..]", + "baz 0.0.0 [..]" + ], + "workspace_default_members": [ + "bar 0.0.0 [..]", + "baz 0.0.0 [..]" + ], + "resolve": { + "nodes": [ + { + "id": "bar 0.0.0 [..]", + "dependencies": [ + "baz 0.0.0 [..]", + "foobar 0.0.1 [..]" + ], + "deps": [ + { + "name": "baz", + "pkg": "baz 0.0.0 [..]", + "dep_kinds": [ + { + "kind": null, + "target": null + } + ] + }, + { + "name": "foobar", + "pkg": "foobar 0.0.1 [..]", + "dep_kinds": [ + { + "kind": null, + "target": null + } + ] + } + ], + "features": [] + }, + { + "id": "baz 0.0.0 [..]", + "dependencies": [ + "foobar 0.0.1 [..]" + ], + "deps": [ + { + "name": "foobar", + "pkg": "foobar 0.0.1 [..]", + "dep_kinds": [ + { + "kind": null, + "target": null + } + ] + } + ], + "features": [] + }, + { + "id": "foobar 0.0.1 [..]", + "dependencies": [], + "deps": [], + "features": [] + } + ], + "root": null + }, + "target_directory": "[..]/foo/target", + "version": 1, + "workspace_root": "[..]", + "metadata": null +} "#, ) - .with_status(101) .run(); } diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index fd4f1a20a93..efaaa01ff61 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -3105,6 +3105,7 @@ fn versionless_package() { [package] name = "foo" description = "foo" + publish = false "#, ) .file("src/main.rs", r#"fn main() { println!("hello"); }"#) @@ -3112,16 +3113,23 @@ fn versionless_package() { p.cargo("package") .with_stderr( - r#"error: failed to parse manifest at `[CWD]/Cargo.toml` - -Caused by: - TOML parse error at line 2, column 17 - | - 2 | [package] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - missing field `version` -"#, + "\ +warning: manifest has no license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. + Packaging foo v0.0.0 ([CWD]) + Verifying foo v0.0.0 ([CWD]) + Compiling foo v0.0.0 ([CWD]/target/package/foo-0.0.0) + Finished dev [unoptimized + debuginfo] target(s) in [..]s + Packaged 4 files, [..]B ([..]B compressed) +", ) - .with_status(101) .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.0.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.0.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + &[], + ); } diff --git a/tests/testsuite/publish.rs b/tests/testsuite/publish.rs index 585a3bb6fe2..7517cea57ef 100644 --- a/tests/testsuite/publish.rs +++ b/tests/testsuite/publish.rs @@ -3007,6 +3007,9 @@ Caused by: #[cargo_test] fn versionless_package() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + let p = project() .file( "Cargo.toml", @@ -3020,17 +3023,15 @@ fn versionless_package() { .build(); p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_status(101) .with_stderr( - r#"error: failed to parse manifest at `[CWD]/Cargo.toml` + "\ +error: failed to parse manifest at `[CWD]/Cargo.toml` Caused by: - TOML parse error at line 2, column 17 - | - 2 | [package] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - missing field `version` -"#, + `package.publish` requires `package.version` be specified +", ) - .with_status(101) .run(); } From cc9be44e94120bbf15ce5065311abf00d41d1a9d Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 6 Oct 2023 12:30:52 -0500 Subject: [PATCH 4/6] fix(embedded): Rely on new defaulted version field --- src/cargo/util/toml/embedded.rs | 6 ------ src/doc/src/reference/unstable.md | 1 - 2 files changed, 7 deletions(-) diff --git a/src/cargo/util/toml/embedded.rs b/src/cargo/util/toml/embedded.rs index 482268923fc..ca587007557 100644 --- a/src/cargo/util/toml/embedded.rs +++ b/src/cargo/util/toml/embedded.rs @@ -6,7 +6,6 @@ use crate::Config; const DEFAULT_EDITION: crate::core::features::Edition = crate::core::features::Edition::LATEST_STABLE; -const DEFAULT_VERSION: &str = "0.0.0"; const DEFAULT_PUBLISH: bool = false; const AUTO_FIELDS: &[&str] = &["autobins", "autoexamples", "autotests", "autobenches"]; @@ -123,9 +122,6 @@ fn expand_manifest_( package .entry("name".to_owned()) .or_insert(toml::Value::String(name)); - package - .entry("version".to_owned()) - .or_insert_with(|| toml::Value::String(DEFAULT_VERSION.to_owned())); package.entry("edition".to_owned()).or_insert_with(|| { let _ = config.shell().warn(format_args!( "`package.edition` is unspecified, defaulting to `{}`", @@ -622,7 +618,6 @@ build = false edition = "2021" name = "test-" publish = false -version = "0.0.0" [profile.release] strip = true @@ -652,7 +647,6 @@ build = false edition = "2021" name = "test-" publish = false -version = "0.0.0" [profile.release] strip = true diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index b66469c8ce5..f73ffe230d5 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1221,7 +1221,6 @@ at the start of the infostring at the top of the file. Inferred / defaulted manifest fields: - `package.name = ` -- `package.version = "0.0.0"` to [call attention to this crate being used in unexpected places](https://matklad.github.io/2021/08/22/large-rust-workspaces.html#Smaller-Tips) - `package.publish = false` to avoid accidental publishes, particularly if we later add support for including them in a workspace. - `package.edition = ` to avoid always having to add an embedded From bfb5d1db0ecb50251d7d940e5fbf50c913e9ef41 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 6 Oct 2023 13:01:58 -0500 Subject: [PATCH 5/6] fix(toml): Default package.publish based on presence of package.version Before the default was hardcoded to `true`. The problem was that means that to remove the `package.version` boilerplate, you had to add `package.publish = false` boilerplate. To make the errors easier to understand in this situation, I err on the side of encouraging people to put `publish = true` in their manifests. By making this change, we also unblock "cargo script" / `Cargo.toml` unifying the handling of `package.publish`. --- src/cargo/ops/registry/publish.rs | 2 +- src/cargo/util/toml/mod.rs | 3 ++- src/doc/src/reference/manifest.md | 19 +++++++++---------- tests/testsuite/check.rs | 1 - tests/testsuite/metadata.rs | 2 -- tests/testsuite/package.rs | 1 - tests/testsuite/publish.rs | 12 +++++------- 7 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/cargo/ops/registry/publish.rs b/src/cargo/ops/registry/publish.rs index 5009c0b67cc..201907bb268 100644 --- a/src/cargo/ops/registry/publish.rs +++ b/src/cargo/ops/registry/publish.rs @@ -103,7 +103,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { if allowed_registries.is_empty() { bail!( "`{}` cannot be published.\n\ - `package.publish` is set to `false` or an empty list in Cargo.toml and prevents publishing.", + `package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish.", pkg.name(), ); } else if !allowed_registries.contains(®_name) { diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 6c7add9e814..52f99bb59dc 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1012,7 +1012,8 @@ impl TomlManifest { let publish = match publish { Some(VecStringOrBool::VecString(ref vecstring)) => Some(vecstring.clone()), Some(VecStringOrBool::Bool(false)) => Some(vec![]), - None | Some(VecStringOrBool::Bool(true)) => None, + Some(VecStringOrBool::Bool(true)) => None, + None => version.is_none().then_some(vec![]), }; if version.is_none() && publish != Some(vec![]) { diff --git a/src/doc/src/reference/manifest.md b/src/doc/src/reference/manifest.md index 2f4920c0ba5..e3168a47fdc 100644 --- a/src/doc/src/reference/manifest.md +++ b/src/doc/src/reference/manifest.md @@ -109,7 +109,7 @@ resolve dependencies, and for guidelines on setting your own version. See the [SemVer compatibility] chapter for more details on exactly what constitutes a breaking change. -This field is optional and defaults to `0.0.0`. +This field is optional and defaults to `0.0.0`. The field is required for publishing packages. [Resolver]: resolver.md [SemVer compatibility]: semver.md @@ -472,23 +472,22 @@ if any of those files change. ### The `publish` field -The `publish` field can be used to prevent a package from being published to a -package registry (like *crates.io*) by mistake, for instance to keep a package -private in a company. - +The `publish` field can be used to control which registries names the package +may be published to: ```toml [package] # ... -publish = false +publish = ["some-registry-name"] ``` -The value may also be an array of strings which are registry names that are -allowed to be published to. - +To prevent a package from being published to a registry (like crates.io) by mistake, +for instance to keep a package private in a company, +you can omit the [`version`](#the-version-field) field. +If you'd like to be more explicit, you can disable publishing: ```toml [package] # ... -publish = ["some-registry-name"] +publish = false ``` If publish array contains a single registry, `cargo publish` command will use diff --git a/tests/testsuite/check.rs b/tests/testsuite/check.rs index f7c865dedba..03611ae67e7 100644 --- a/tests/testsuite/check.rs +++ b/tests/testsuite/check.rs @@ -1506,7 +1506,6 @@ fn versionless_package() { [package] name = "foo" description = "foo" - publish = false "#, ) .file("src/lib.rs", "") diff --git a/tests/testsuite/metadata.rs b/tests/testsuite/metadata.rs index 223a8f70784..888cdce8c0e 100644 --- a/tests/testsuite/metadata.rs +++ b/tests/testsuite/metadata.rs @@ -4273,7 +4273,6 @@ fn versionless_packages() { r#" [package] name = "bar" - publish = false [dependencies] foobar = "0.0.1" @@ -4286,7 +4285,6 @@ fn versionless_packages() { r#" [package] name = "baz" - publish = false [dependencies] foobar = "0.0.1" diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index efaaa01ff61..4ec4fc0d6fc 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -3105,7 +3105,6 @@ fn versionless_package() { [package] name = "foo" description = "foo" - publish = false "#, ) .file("src/main.rs", r#"fn main() { println!("hello"); }"#) diff --git a/tests/testsuite/publish.rs b/tests/testsuite/publish.rs index 7517cea57ef..5d29ac88a91 100644 --- a/tests/testsuite/publish.rs +++ b/tests/testsuite/publish.rs @@ -420,7 +420,7 @@ fn unpublishable_crate() { .with_stderr( "\ [ERROR] `foo` cannot be published. -`package.publish` is set to `false` or an empty list in Cargo.toml and prevents publishing. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. ", ) .run(); @@ -794,7 +794,7 @@ fn publish_empty_list() { .with_stderr( "\ [ERROR] `foo` cannot be published. -`package.publish` is set to `false` or an empty list in Cargo.toml and prevents publishing. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. ", ) .run(); @@ -1020,7 +1020,7 @@ fn block_publish_no_registry() { .with_stderr( "\ [ERROR] `foo` cannot be published. -`package.publish` is set to `false` or an empty list in Cargo.toml and prevents publishing. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. ", ) .run(); @@ -3027,10 +3027,8 @@ fn versionless_package() { .with_status(101) .with_stderr( "\ -error: failed to parse manifest at `[CWD]/Cargo.toml` - -Caused by: - `package.publish` requires `package.version` be specified +error: `foo` cannot be published. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. ", ) .run(); From 7ac49a9238a84a7baf7dc0cbc512034fe9086db0 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 6 Oct 2023 13:54:13 -0500 Subject: [PATCH 6/6] fix(embedded): Rely on package.publish default for scripts --- src/cargo/util/toml/embedded.rs | 6 ------ src/doc/src/reference/unstable.md | 2 -- 2 files changed, 8 deletions(-) diff --git a/src/cargo/util/toml/embedded.rs b/src/cargo/util/toml/embedded.rs index ca587007557..8e3912288bf 100644 --- a/src/cargo/util/toml/embedded.rs +++ b/src/cargo/util/toml/embedded.rs @@ -6,7 +6,6 @@ use crate::Config; const DEFAULT_EDITION: crate::core::features::Edition = crate::core::features::Edition::LATEST_STABLE; -const DEFAULT_PUBLISH: bool = false; const AUTO_FIELDS: &[&str] = &["autobins", "autoexamples", "autotests", "autobenches"]; pub fn expand_manifest( @@ -132,9 +131,6 @@ fn expand_manifest_( package .entry("build".to_owned()) .or_insert_with(|| toml::Value::Boolean(false)); - package - .entry("publish".to_owned()) - .or_insert_with(|| toml::Value::Boolean(DEFAULT_PUBLISH)); for field in AUTO_FIELDS { package .entry(field.to_owned()) @@ -617,7 +613,6 @@ autotests = false build = false edition = "2021" name = "test-" -publish = false [profile.release] strip = true @@ -646,7 +641,6 @@ autotests = false build = false edition = "2021" name = "test-" -publish = false [profile.release] strip = true diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index f73ffe230d5..12a56d72298 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1221,8 +1221,6 @@ at the start of the infostring at the top of the file. Inferred / defaulted manifest fields: - `package.name = ` -- `package.publish = false` to avoid accidental publishes, particularly if we - later add support for including them in a workspace. - `package.edition = ` to avoid always having to add an embedded manifest at the cost of potentially breaking scripts on rust upgrades - Warn when `edition` is unspecified to raise awareness of this