Skip to content

Commit

Permalink
Multi-package publishing
Browse files Browse the repository at this point in the history
Co-authored-by: Tor Hovland <[email protected]>
Co-authored-by: Ed Page <[email protected]>
  • Loading branch information
3 people committed Sep 6, 2024
1 parent 384e256 commit 69ab815
Show file tree
Hide file tree
Showing 6 changed files with 483 additions and 124 deletions.
74 changes: 39 additions & 35 deletions src/cargo/ops/cargo_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,30 +93,6 @@ struct GitVcsInfo {
dirty: bool,
}

/// Packages a single package in a workspace, returning the resulting tar file.
///
/// # Panics
/// Panics if `opts.list` is true. In that case you probably don't want to
/// actually build the package tarball; you should just make and print the list
/// of files. (We don't currently provide a public API for that, but see how
/// [`package`] does it.)
pub fn package_one(
ws: &Workspace<'_>,
pkg: &Package,
opts: &PackageOpts<'_>,
) -> CargoResult<FileLock> {
assert!(!opts.list);

let ar_files = prepare_archive(ws, pkg, opts)?;
let tarball = create_package(ws, pkg, ar_files, None)?;

if opts.verify {
run_verify(ws, pkg, &tarball, None, opts)?;
}

Ok(tarball)
}

// Builds a tarball and places it in the output directory.
fn create_package(
ws: &Workspace<'_>,
Expand Down Expand Up @@ -193,6 +169,34 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
// So we need filter
pkgs.retain(|(pkg, _feats)| specs.iter().any(|spec| spec.matches(pkg.package_id())));

Ok(do_package(ws, opts, pkgs)?
.into_iter()
.map(|x| x.2)
.collect())
}

/// Packages an entire workspace.
///
/// Returns the generated package files and the dependencies between them. If
/// `opts.list` is true, skips generating package files and returns an empty
/// list.
pub(crate) fn package_with_dep_graph(
ws: &Workspace<'_>,
opts: &PackageOpts<'_>,
pkgs: Vec<(&Package, CliFeatures)>,
) -> CargoResult<LocalDependencies<(CliFeatures, FileLock)>> {
let output = do_package(ws, opts, pkgs)?;

Ok(local_deps(output.into_iter().map(
|(pkg, opts, tarball)| (pkg, (opts.cli_features, tarball)),
)))
}

fn do_package<'a>(
ws: &Workspace<'_>,
opts: &PackageOpts<'a>,
pkgs: Vec<(&Package, CliFeatures)>,
) -> CargoResult<Vec<(Package, PackageOpts<'a>, FileLock)>> {
if ws
.lock_root()
.as_path_unlocked()
Expand Down Expand Up @@ -264,7 +268,7 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
}
}

Ok(outputs.into_iter().map(|x| x.2).collect())
Ok(outputs)
}

/// Determine which registry the packages are for.
Expand Down Expand Up @@ -308,15 +312,14 @@ fn get_registry(
}

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

impl LocalDependencies {
fn sort(&self) -> Vec<(Package, CliFeatures)> {
impl<T: Clone> LocalDependencies<T> {
pub fn sort(&self) -> Vec<(Package, T)> {
self.graph
.sort()
.into_iter()
Expand All @@ -335,9 +338,10 @@ impl LocalDependencies {
/// ignoring dev dependencies.
///
/// We assume that the packages all belong to this workspace.
fn local_deps(packages: impl Iterator<Item = (Package, CliFeatures)>) -> LocalDependencies {
let packages: HashMap<PackageId, (Package, CliFeatures)> =
packages.map(|pkg| (pkg.0.package_id(), pkg)).collect();
fn local_deps<T>(packages: impl Iterator<Item = (Package, T)>) -> LocalDependencies<T> {
let packages: HashMap<PackageId, (Package, T)> = packages
.map(|(pkg, payload)| (pkg.package_id(), (pkg, payload)))
.collect();

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

let mut graph = Graph::new();
for (pkg, _features) in packages.values() {
for (pkg, _payload) in packages.values() {
graph.add(pkg.package_id());
for dep in pkg.dependencies() {
// Ignore local dev-dependencies because they aren't needed for intra-workspace
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use self::cargo_fetch::{fetch, FetchOptions};
pub use self::cargo_install::{install, install_list};
pub use self::cargo_new::{init, new, NewOptions, NewProjectKind, VersionControl};
pub use self::cargo_output_metadata::{output_metadata, ExportInfo, OutputMetadataOptions};
pub use self::cargo_package::{check_yanked, package, package_one, PackageOpts};
pub use self::cargo_package::{check_yanked, package, PackageOpts};
pub use self::cargo_pkgid::pkgid;
pub use self::cargo_read_manifest::read_package;
pub use self::cargo_run::run;
Expand Down
Loading

0 comments on commit 69ab815

Please sign in to comment.