Skip to content

Commit a6c8597

Browse files
committed
feat(publish): Stabilize multi-package publishing
A user will now be able to use flags like `--workspace` with `cargo publish`. `cargo package` will now also work with those flags without having to pass `--no-verify --exclude-lockfile`. Many release tools have come out that solve this problem. They will still need a lot of the logic that went into that for other parts of the release process. However, a cargo-native solution allows for: - Verification during dry-run - Better strategies for waiting for the publish timeout `cargo publish` is non-atomic at this time. If there is a server side error, network error, or rate limit during the publish, the workspace will be left in a partially published state. Verification is done before any publishing so that won't affect things. There are multiple strategies we can employ for improving this over time, including - atomic publish - `--idempotent` (#13397) - leave this to release tools to manage This includes support for `--dry-run` verification. As release tools didn't have a way to do this before, users may be surprised at how slow this is because a `cargo build` is done instead of a `cargo check`. This is being tracked in #14941. This adds to `cargo package` the `--registry` and `--index` flags to help with resolving dependencies when depending on a package being packaged at that moment. These flags are only needed when a `cargo package --workspace` operation would have failed before due to inability to find a locally created dependency. Regarding the publish timeout, `cargo publish --workspace` publishes packages in batches and we only timeout if nothing in the batch has finished being published within the timeout, deferring the rest to the next wait-for-publish. So for example, if you have packages `a`, `b`, `c` then we'll wait up to 60 seconds and if only `a` and `b` were ready in that time, we'll then wait another 60 seconds for `c`. During testing, users ran into issues with `.crate` checksums that we've not been able to reproduce since: - #1169 (comment) - #14396 By stabilizing this, Cargo's behavior becomes dependent on an overlay registry. When generating a lockfile or verifying a package, we overlay the locally generated `.crate` files on top of the registry so the registry appears as it would and everything works. If there is a conflict with a version, the local version wins which is important for the dry-run mode of release tools as they won't have bumped the version yet. Our concern for the overlay registry is dependency confusion attacks. Considering this is not accessible for general user operations, this should be fine. Fixes #1169 Fixes #10948
1 parent ec0e246 commit a6c8597

File tree

15 files changed

+153
-855
lines changed

15 files changed

+153
-855
lines changed

src/bin/cargo/commands/package.rs

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use cargo::ops::PackageOpts;
77
pub fn cli() -> Command {
88
subcommand("package")
99
.about("Assemble the local package into a distributable tarball")
10-
.arg_index("Registry index URL to prepare the package for (unstable)")
11-
.arg_registry("Registry to prepare the package for (unstable)")
10+
.arg_index("Registry index URL to prepare the package for")
11+
.arg_registry("Registry to prepare the package for")
1212
.arg(
1313
flag(
1414
"list",
@@ -57,22 +57,6 @@ pub fn cli() -> Command {
5757
}
5858

5959
pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
60-
if args._value_of("registry").is_some() {
61-
gctx.cli_unstable().fail_if_stable_opt_custom_z(
62-
"--registry",
63-
13947,
64-
"package-workspace",
65-
gctx.cli_unstable().package_workspace,
66-
)?;
67-
}
68-
if args._value_of("index").is_some() {
69-
gctx.cli_unstable().fail_if_stable_opt_custom_z(
70-
"--index",
71-
13947,
72-
"package-workspace",
73-
gctx.cli_unstable().package_workspace,
74-
)?;
75-
}
7660
let reg_or_index = args.registry_or_index(gctx)?;
7761
let ws = args.workspace(gctx)?;
7862
if ws.root_maybe().is_embedded() {

src/bin/cargo/commands/publish.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ pub fn cli() -> Command {
2020
.arg_silent_suggestion()
2121
.arg_package_spec_no_all(
2222
"Package(s) to publish",
23-
"Publish all packages in the workspace (unstable)",
24-
"Don't publish specified packages (unstable)",
23+
"Publish all packages in the workspace",
24+
"Don't publish specified packages",
2525
)
2626
.arg_features()
2727
.arg_parallel()
@@ -45,23 +45,6 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
4545
.into());
4646
}
4747

48-
let unstable = gctx.cli_unstable();
49-
let enabled = unstable.package_workspace;
50-
if args.get_flag("workspace") {
51-
unstable.fail_if_stable_opt_custom_z("--workspace", 10948, "package-workspace", enabled)?;
52-
}
53-
if args._value_of("exclude").is_some() {
54-
unstable.fail_if_stable_opt_custom_z("--exclude", 10948, "package-workspace", enabled)?;
55-
}
56-
if args._values_of("package").len() > 1 {
57-
unstable.fail_if_stable_opt_custom_z(
58-
"--package (multiple occurrences)",
59-
10948,
60-
"package-workspace",
61-
enabled,
62-
)?;
63-
}
64-
6548
ops::publish(
6649
&ws,
6750
&PublishOpts {

src/cargo/core/features.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,6 @@ unstable_cli_options!(
843843
next_lockfile_bump: bool,
844844
no_embed_metadata: bool = ("Avoid embedding metadata in library artifacts"),
845845
no_index_update: bool = ("Do not update the registry index even if the cache is outdated"),
846-
package_workspace: bool = ("Handle intra-workspace dependencies when packaging"),
847846
panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
848847
profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"),
849848
public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"),
@@ -939,6 +938,9 @@ const STABILIZED_CHECK_CFG: &str =
939938

940939
const STABILIZED_DOCTEST_XCOMPILE: &str = "Doctest cross-compiling is now always enabled.";
941940

941+
const STABILIZED_PACKAGE_WORKSPACE: &str =
942+
"Workspace packaging and publishing (a.k.a. `-Zpackage-workspace`) is now always enabled.";
943+
942944
fn deserialize_comma_separated_list<'de, D>(
943945
deserializer: D,
944946
) -> Result<Option<Vec<String>>, D::Error>
@@ -1320,6 +1322,7 @@ impl CliUnstable {
13201322
"lints" => stabilized_warn(k, "1.74", STABILIZED_LINTS),
13211323
"registry-auth" => stabilized_warn(k, "1.74", STABILIZED_REGISTRY_AUTH),
13221324
"check-cfg" => stabilized_warn(k, "1.80", STABILIZED_CHECK_CFG),
1325+
"package-workspace" => stabilized_warn(k, "1.89", STABILIZED_PACKAGE_WORKSPACE),
13231326

13241327
// Unstable features
13251328
// Sorted alphabetically:
@@ -1363,7 +1366,6 @@ impl CliUnstable {
13631366
"mtime-on-use" => self.mtime_on_use = parse_empty(k, v)?,
13641367
"no-embed-metadata" => self.no_embed_metadata = parse_empty(k, v)?,
13651368
"no-index-update" => self.no_index_update = parse_empty(k, v)?,
1366-
"package-workspace" => self.package_workspace = parse_empty(k, v)?,
13671369
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
13681370
"public-dependency" => self.public_dependency = parse_empty(k, v)?,
13691371
"profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?,

src/cargo/ops/cargo_package/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ fn do_package<'a>(
239239
let deps = local_deps(pkgs.iter().map(|(p, f)| ((*p).clone(), f.clone())));
240240
let just_pkgs: Vec<_> = pkgs.iter().map(|p| p.0).collect();
241241

242-
let mut local_reg = if ws.gctx().cli_unstable().package_workspace {
242+
let mut local_reg = {
243243
// The publish registry doesn't matter unless there are local dependencies that will be
244244
// resolved,
245245
// so only try to get one if we need it. If they explicitly passed a
@@ -256,8 +256,6 @@ fn do_package<'a>(
256256
let reg_dir = ws.build_dir().join("package").join("tmp-registry");
257257
sid.map(|sid| TmpRegistry::new(ws.gctx(), reg_dir, sid))
258258
.transpose()?
259-
} else {
260-
None
261259
};
262260

263261
// Packages need to be created in dependency order, because dependencies must

src/cargo/ops/registry/publish.rs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,8 @@ pub struct PublishOpts<'gctx> {
6868
}
6969

7070
pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
71-
let multi_package_mode = ws.gctx().cli_unstable().package_workspace;
7271
let specs = opts.to_publish.to_package_id_specs(ws)?;
7372

74-
if !multi_package_mode {
75-
if specs.len() > 1 {
76-
bail!("the `-p` argument must be specified to select a single package to publish")
77-
}
78-
if Packages::Default == opts.to_publish && ws.is_virtual() {
79-
bail!("the `-p` argument must be specified in the root of a virtual workspace")
80-
}
81-
}
82-
8373
let member_ids: Vec<_> = ws.members().map(|p| p.package_id()).collect();
8474
// Check that the specs match members.
8575
for spec in &specs {
@@ -96,13 +86,12 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
9686
// If `--workspace` is passed,
9787
// the intent is more like "publish all publisable packages in this workspace",
9888
// so skip `publish=false` packages.
99-
let allow_unpublishable = multi_package_mode
100-
&& match &opts.to_publish {
101-
Packages::Default => ws.is_virtual(),
102-
Packages::All(_) => true,
103-
Packages::OptOut(_) => true,
104-
Packages::Packages(_) => false,
105-
};
89+
let allow_unpublishable = match &opts.to_publish {
90+
Packages::Default => ws.is_virtual(),
91+
Packages::All(_) => true,
92+
Packages::OptOut(_) => true,
93+
Packages::Packages(_) => false,
94+
};
10695
if !unpublishable.is_empty() && !allow_unpublishable {
10796
bail!(
10897
"{} cannot be published.\n\

src/doc/man/cargo-publish.md

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -68,64 +68,7 @@ which defaults to `crates-io`.
6868

6969
{{/options}}
7070

71-
### Package Selection
72-
73-
By default, when no package selection options are given, the packages selected
74-
depend on the selected manifest file (based on the current working directory if
75-
`--manifest-path` is not given). If the manifest is the root of a workspace then
76-
the workspaces default members are selected, otherwise only the package defined
77-
by the manifest will be selected.
78-
79-
The default members of a workspace can be set explicitly with the
80-
`workspace.default-members` key in the root manifest. If this is not set, a
81-
virtual workspace will include all workspace members (equivalent to passing
82-
`--workspace`), and a non-virtual workspace will include only the root crate itself.
83-
84-
Selecting more than one package is unstable and available only on the
85-
[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
86-
and requires the `-Z package-workspace` flag to enable.
87-
See <https://github.com/rust-lang/cargo/issues/10948> for more information.
88-
89-
90-
{{#options}}
91-
92-
{{#option "`-p` _spec_..." "`--package` _spec_..."}}
93-
{{actionverb}} only the specified packages. See {{man "cargo-pkgid" 1}} for the
94-
SPEC format. This flag may be specified multiple times and supports common Unix
95-
glob patterns like `*`, `?` and `[]`. However, to avoid your shell accidentally
96-
expanding glob patterns before Cargo handles them, you must use single quotes or
97-
double quotes around each pattern.
98-
99-
Selecting more than one package with this option is unstable and available only
100-
on the
101-
[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
102-
and requires the `-Z package-workspace` flag to enable.
103-
See <https://github.com/rust-lang/cargo/issues/10948> for more information.
104-
{{/option}}
105-
106-
{{#option "`--workspace`" }}
107-
{{actionverb}} all members in the workspace.
108-
109-
This option is unstable and available only on the
110-
[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
111-
and requires the `-Z package-workspace` flag to enable.
112-
See <https://github.com/rust-lang/cargo/issues/10948> for more information.
113-
{{/option}}
114-
115-
{{#option "`--exclude` _SPEC_..." }}
116-
Exclude the specified packages. Must be used in conjunction with the
117-
`--workspace` flag. This flag may be specified multiple times and supports
118-
common Unix glob patterns like `*`, `?` and `[]`. However, to avoid your shell
119-
accidentally expanding glob patterns before Cargo handles them, you must use
120-
single quotes or double quotes around each pattern.
121-
122-
This option is unstable and available only on the
123-
[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
124-
and requires the `-Z package-workspace` flag to enable.
125-
See <https://github.com/rust-lang/cargo/issues/10948> for more information.
126-
{{/option}}
127-
128-
{{/options}}
71+
{{> section-package-selection }}
12972

13073
### Compilation Options
13174

src/doc/man/generated_txt/cargo-publish.txt

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,6 @@ OPTIONS
8585
passing --workspace), and a non-virtual workspace will include only the
8686
root crate itself.
8787

88-
Selecting more than one package is unstable and available only on the
89-
nightly channel
90-
<https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and
91-
requires the -Z package-workspace flag to enable. See
92-
<https://github.com/rust-lang/cargo/issues/10948> for more information.
93-
9488
-p spec…, --package spec…
9589
Publish only the specified packages. See cargo-pkgid(1) for the SPEC
9690
format. This flag may be specified multiple times and supports
@@ -99,21 +93,11 @@ OPTIONS
9993
them, you must use single quotes or double quotes around each
10094
pattern.
10195

102-
Selecting more than one package with this option is unstable and
103-
available only on the nightly channel
104-
<https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and
105-
requires the -Z package-workspace flag to enable. See
106-
<https://github.com/rust-lang/cargo/issues/10948> for more
107-
information.
108-
10996
--workspace
11097
Publish all members in the workspace.
11198

112-
This option is unstable and available only on the nightly channel
113-
<https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and
114-
requires the -Z package-workspace flag to enable. See
115-
<https://github.com/rust-lang/cargo/issues/10948> for more
116-
information.
99+
--all
100+
Deprecated alias for --workspace.
117101

118102
--exclude SPEC…
119103
Exclude the specified packages. Must be used in conjunction with the
@@ -123,12 +107,6 @@ OPTIONS
123107
handles them, you must use single quotes or double quotes around
124108
each pattern.
125109

126-
This option is unstable and available only on the nightly channel
127-
<https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and
128-
requires the -Z package-workspace flag to enable. See
129-
<https://github.com/rust-lang/cargo/issues/10948> for more
130-
information.
131-
132110
Compilation Options
133111
--target triple
134112
Publish for the given architecture. The default is the host

src/doc/src/commands/cargo-publish.md

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,6 @@ The default members of a workspace can be set explicitly with the
8888
virtual workspace will include all workspace members (equivalent to passing
8989
`--workspace`), and a non-virtual workspace will include only the root crate itself.
9090

91-
Selecting more than one package is unstable and available only on the
92-
[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
93-
and requires the `-Z package-workspace` flag to enable.
94-
See <https://github.com/rust-lang/cargo/issues/10948> for more information.
95-
96-
9791
<dl>
9892

9993
<dt class="option-term" id="option-cargo-publish--p"><a class="option-anchor" href="#option-cargo-publish--p"></a><code>-p</code> <em>spec</em>…</dt>
@@ -102,32 +96,23 @@ See <https://github.com/rust-lang/cargo/issues/10948> for more information.
10296
SPEC format. This flag may be specified multiple times and supports common Unix
10397
glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally
10498
expanding glob patterns before Cargo handles them, you must use single quotes or
105-
double quotes around each pattern.</p>
106-
<p>Selecting more than one package with this option is unstable and available only
107-
on the
108-
<a href="https://doc.rust-lang.org/book/appendix-07-nightly-rust.html">nightly channel</a>
109-
and requires the <code>-Z package-workspace</code> flag to enable.
110-
See <a href="https://github.com/rust-lang/cargo/issues/10948">https://github.com/rust-lang/cargo/issues/10948</a> for more information.</dd>
99+
double quotes around each pattern.</dd>
111100

112101

113102
<dt class="option-term" id="option-cargo-publish---workspace"><a class="option-anchor" href="#option-cargo-publish---workspace"></a><code>--workspace</code></dt>
114-
<dd class="option-desc">Publish all members in the workspace.</p>
115-
<p>This option is unstable and available only on the
116-
<a href="https://doc.rust-lang.org/book/appendix-07-nightly-rust.html">nightly channel</a>
117-
and requires the <code>-Z package-workspace</code> flag to enable.
118-
See <a href="https://github.com/rust-lang/cargo/issues/10948">https://github.com/rust-lang/cargo/issues/10948</a> for more information.</dd>
103+
<dd class="option-desc">Publish all members in the workspace.</dd>
104+
105+
106+
<dt class="option-term" id="option-cargo-publish---all"><a class="option-anchor" href="#option-cargo-publish---all"></a><code>--all</code></dt>
107+
<dd class="option-desc">Deprecated alias for <code>--workspace</code>.</dd>
119108

120109

121110
<dt class="option-term" id="option-cargo-publish---exclude"><a class="option-anchor" href="#option-cargo-publish---exclude"></a><code>--exclude</code> <em>SPEC</em>…</dt>
122111
<dd class="option-desc">Exclude the specified packages. Must be used in conjunction with the
123112
<code>--workspace</code> flag. This flag may be specified multiple times and supports
124113
common Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell
125114
accidentally expanding glob patterns before Cargo handles them, you must use
126-
single quotes or double quotes around each pattern.</p>
127-
<p>This option is unstable and available only on the
128-
<a href="https://doc.rust-lang.org/book/appendix-07-nightly-rust.html">nightly channel</a>
129-
and requires the <code>-Z package-workspace</code> flag to enable.
130-
See <a href="https://github.com/rust-lang/cargo/issues/10948">https://github.com/rust-lang/cargo/issues/10948</a> for more information.</dd>
115+
single quotes or double quotes around each pattern.</dd>
131116

132117

133118
</dl>

src/etc/man/cargo-publish.1

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,6 @@ The default members of a workspace can be set explicitly with the
100100
virtual workspace will include all workspace members (equivalent to passing
101101
\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself.
102102
.sp
103-
Selecting more than one package is unstable and available only on the
104-
\fInightly channel\fR <https://doc.rust\-lang.org/book/appendix\-07\-nightly\-rust.html>
105-
and requires the \fB\-Z package\-workspace\fR flag to enable.
106-
See <https://github.com/rust\-lang/cargo/issues/10948> for more information.
107-
.sp
108103
\fB\-p\fR \fIspec\fR\[u2026],
109104
\fB\-\-package\fR \fIspec\fR\[u2026]
110105
.RS 4
@@ -113,22 +108,16 @@ SPEC format. This flag may be specified multiple times and supports common Unix
113108
glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally
114109
expanding glob patterns before Cargo handles them, you must use single quotes or
115110
double quotes around each pattern.
116-
.sp
117-
Selecting more than one package with this option is unstable and available only
118-
on the
119-
\fInightly channel\fR <https://doc.rust\-lang.org/book/appendix\-07\-nightly\-rust.html>
120-
and requires the \fB\-Z package\-workspace\fR flag to enable.
121-
See <https://github.com/rust\-lang/cargo/issues/10948> for more information.
122111
.RE
123112
.sp
124113
\fB\-\-workspace\fR
125114
.RS 4
126115
Publish all members in the workspace.
116+
.RE
127117
.sp
128-
This option is unstable and available only on the
129-
\fInightly channel\fR <https://doc.rust\-lang.org/book/appendix\-07\-nightly\-rust.html>
130-
and requires the \fB\-Z package\-workspace\fR flag to enable.
131-
See <https://github.com/rust\-lang/cargo/issues/10948> for more information.
118+
\fB\-\-all\fR
119+
.RS 4
120+
Deprecated alias for \fB\-\-workspace\fR\&.
132121
.RE
133122
.sp
134123
\fB\-\-exclude\fR \fISPEC\fR\[u2026]
@@ -138,11 +127,6 @@ Exclude the specified packages. Must be used in conjunction with the
138127
common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell
139128
accidentally expanding glob patterns before Cargo handles them, you must use
140129
single quotes or double quotes around each pattern.
141-
.sp
142-
This option is unstable and available only on the
143-
\fInightly channel\fR <https://doc.rust\-lang.org/book/appendix\-07\-nightly\-rust.html>
144-
and requires the \fB\-Z package\-workspace\fR flag to enable.
145-
See <https://github.com/rust\-lang/cargo/issues/10948> for more information.
146130
.RE
147131
.SS "Compilation Options"
148132
.sp

0 commit comments

Comments
 (0)