Skip to content

Commit be1bbda

Browse files
committed
Auto merge of #14433 - tweag:multi-package-publishing-rebased, r=epage
Publish workspace Adds support for simultaneously publishing multiple (possibly inter-dependent) packages in a workspace, gated by the `-Zpackage-workspace` flag. Questions to be worked out through stabilization: - Are we ok stabilizing this and #10948 at the same time? Currently, they are behind the same flag - What is the desired behavior for the publish timeout? This PR uploads the crates in batches (depending on the dependency graph), and we only timeout if nothing in the batch is available 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`. - What is the desired behavior when some packages in a workspace have `publish = false`? This PR raises an error whenever any of the selected packages has `publish = false`, so it will error on `cargo publish --workspace` in a workspace with an unpublishable package. An alternative interface would implicitly exclude unpublishable packages in this case, but still error out if you explicitly select an unpublishable package with `-p package-name` (see #14356). This PR's behavior is the most conservative one as it can change from an error to implicit excludes later. This is part of #1169
2 parents b687045 + a016e5f commit be1bbda

File tree

6 files changed

+956
-172
lines changed

6 files changed

+956
-172
lines changed

src/cargo/ops/cargo_package.rs

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -93,30 +93,6 @@ struct GitVcsInfo {
9393
dirty: bool,
9494
}
9595

96-
/// Packages a single package in a workspace, returning the resulting tar file.
97-
///
98-
/// # Panics
99-
/// Panics if `opts.list` is true. In that case you probably don't want to
100-
/// actually build the package tarball; you should just make and print the list
101-
/// of files. (We don't currently provide a public API for that, but see how
102-
/// [`package`] does it.)
103-
pub fn package_one(
104-
ws: &Workspace<'_>,
105-
pkg: &Package,
106-
opts: &PackageOpts<'_>,
107-
) -> CargoResult<FileLock> {
108-
assert!(!opts.list);
109-
110-
let ar_files = prepare_archive(ws, pkg, opts)?;
111-
let tarball = create_package(ws, pkg, ar_files, None)?;
112-
113-
if opts.verify {
114-
run_verify(ws, pkg, &tarball, None, opts)?;
115-
}
116-
117-
Ok(tarball)
118-
}
119-
12096
// Builds a tarball and places it in the output directory.
12197
fn create_package(
12298
ws: &Workspace<'_>,
@@ -193,6 +169,34 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
193169
// So we need filter
194170
pkgs.retain(|(pkg, _feats)| specs.iter().any(|spec| spec.matches(pkg.package_id())));
195171

172+
Ok(do_package(ws, opts, pkgs)?
173+
.into_iter()
174+
.map(|x| x.2)
175+
.collect())
176+
}
177+
178+
/// Packages an entire workspace.
179+
///
180+
/// Returns the generated package files and the dependencies between them. If
181+
/// `opts.list` is true, skips generating package files and returns an empty
182+
/// list.
183+
pub(crate) fn package_with_dep_graph(
184+
ws: &Workspace<'_>,
185+
opts: &PackageOpts<'_>,
186+
pkgs: Vec<(&Package, CliFeatures)>,
187+
) -> CargoResult<LocalDependencies<(CliFeatures, FileLock)>> {
188+
let output = do_package(ws, opts, pkgs)?;
189+
190+
Ok(local_deps(output.into_iter().map(
191+
|(pkg, opts, tarball)| (pkg, (opts.cli_features, tarball)),
192+
)))
193+
}
194+
195+
fn do_package<'a>(
196+
ws: &Workspace<'_>,
197+
opts: &PackageOpts<'a>,
198+
pkgs: Vec<(&Package, CliFeatures)>,
199+
) -> CargoResult<Vec<(Package, PackageOpts<'a>, FileLock)>> {
196200
if ws
197201
.lock_root()
198202
.as_path_unlocked()
@@ -264,7 +268,7 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
264268
}
265269
}
266270

267-
Ok(outputs.into_iter().map(|x| x.2).collect())
271+
Ok(outputs)
268272
}
269273

270274
/// Determine which registry the packages are for.
@@ -308,15 +312,14 @@ fn get_registry(
308312
}
309313

310314
/// Just the part of the dependency graph that's between the packages we're packaging.
311-
/// (Is the package name a good key? Does it uniquely identify packages?)
312315
#[derive(Clone, Debug, Default)]
313-
struct LocalDependencies {
314-
packages: HashMap<PackageId, (Package, CliFeatures)>,
315-
graph: Graph<PackageId, ()>,
316+
pub(crate) struct LocalDependencies<T> {
317+
pub packages: HashMap<PackageId, (Package, T)>,
318+
pub graph: Graph<PackageId, ()>,
316319
}
317320

318-
impl LocalDependencies {
319-
fn sort(&self) -> Vec<(Package, CliFeatures)> {
321+
impl<T: Clone> LocalDependencies<T> {
322+
pub fn sort(&self) -> Vec<(Package, T)> {
320323
self.graph
321324
.sort()
322325
.into_iter()
@@ -335,9 +338,10 @@ impl LocalDependencies {
335338
/// ignoring dev dependencies.
336339
///
337340
/// We assume that the packages all belong to this workspace.
338-
fn local_deps(packages: impl Iterator<Item = (Package, CliFeatures)>) -> LocalDependencies {
339-
let packages: HashMap<PackageId, (Package, CliFeatures)> =
340-
packages.map(|pkg| (pkg.0.package_id(), pkg)).collect();
341+
fn local_deps<T>(packages: impl Iterator<Item = (Package, T)>) -> LocalDependencies<T> {
342+
let packages: HashMap<PackageId, (Package, T)> = packages
343+
.map(|(pkg, payload)| (pkg.package_id(), (pkg, payload)))
344+
.collect();
341345

342346
// Dependencies have source ids but not package ids. We draw an edge
343347
// whenever a dependency's source id matches one of our packages. This is
@@ -349,7 +353,7 @@ fn local_deps(packages: impl Iterator<Item = (Package, CliFeatures)>) -> LocalDe
349353
.collect();
350354

351355
let mut graph = Graph::new();
352-
for (pkg, _features) in packages.values() {
356+
for (pkg, _payload) in packages.values() {
353357
graph.add(pkg.package_id());
354358
for dep in pkg.dependencies() {
355359
// Ignore local dev-dependencies because they aren't needed for intra-workspace

src/cargo/ops/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub use self::cargo_fetch::{fetch, FetchOptions};
1010
pub use self::cargo_install::{install, install_list};
1111
pub use self::cargo_new::{init, new, NewOptions, NewProjectKind, VersionControl};
1212
pub use self::cargo_output_metadata::{output_metadata, ExportInfo, OutputMetadataOptions};
13-
pub use self::cargo_package::{check_yanked, package, package_one, PackageOpts};
13+
pub use self::cargo_package::{check_yanked, package, PackageOpts};
1414
pub use self::cargo_pkgid::pkgid;
1515
pub use self::cargo_read_manifest::read_package;
1616
pub use self::cargo_run::run;

0 commit comments

Comments
 (0)