Skip to content

Commit

Permalink
Auto merge of #10677 - likzn:fix_publish_p, r=ehuss
Browse files Browse the repository at this point in the history
fix(publish): add more check when use `publish -p <SPEC>`

### Main issue
As issue say #10536 , we need add more check when user use `cargo publish -p <SPEC>`

>`@ehuss` point outs:
>From a behavior standpoint, here are some things to check:
> - In the root of a virtual workspace, it should be an error to run without -p.
>- It should be an error to pass -p for a non-workspace member.
>- It should be an error for -p to match multiple packages.
>- When using -p, it should publish that package, not the one in the current directory (which can be different).
  • Loading branch information
bors committed May 27, 2022
2 parents 8f5500b + b486ada commit e23cf43
Show file tree
Hide file tree
Showing 3 changed files with 341 additions and 25 deletions.
4 changes: 2 additions & 2 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,13 @@ impl Packages {
};
if specs.is_empty() {
if ws.is_virtual() {
anyhow::bail!(
bail!(
"manifest path `{}` contains no package: The manifest is virtual, \
and the workspace has no members.",
ws.root().display()
)
}
anyhow::bail!("no packages to compile")
bail!("no packages to compile")
}
Ok(specs)
}
Expand Down
18 changes: 18 additions & 0 deletions src/cargo/ops/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::core::resolver::CliFeatures;
use crate::core::source::Source;
use crate::core::{Package, SourceId, Workspace};
use crate::ops;
use crate::ops::Packages;
use crate::sources::{RegistrySource, SourceConfigMap, CRATES_IO_DOMAIN, CRATES_IO_REGISTRY};
use crate::util::config::{self, Config, SslVersionConfig, SslVersionConfigRange};
use crate::util::errors::CargoResult;
Expand Down Expand Up @@ -90,7 +91,24 @@ pub struct PublishOpts<'cfg> {

pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
let specs = opts.to_publish.to_package_id_specs(ws)?;
if specs.len() > 1 {
bail!("the `-p` argument must be specified to select a single package to publish")
}
if Packages::Default == opts.to_publish && ws.is_virtual() {
bail!("the `-p` argument must be specified in the root of a virtual workspace")
}
let member_ids = ws.members().map(|p| p.package_id());
// Check that the spec matches exactly one member.
specs[0].query(member_ids)?;
let mut pkgs = ws.members_with_features(&specs, &opts.cli_features)?;
// In `members_with_features_old`, it will add "current" package (determined by the cwd)
// So we need filter
pkgs = pkgs
.into_iter()
.filter(|(m, _)| specs.iter().any(|spec| spec.matches(m.package_id())))
.collect();
// Double check. It is safe theoretically, unless logic has updated.
assert_eq!(pkgs.len(), 1);

let (pkg, cli_features) = pkgs.pop().unwrap();

Expand Down
Loading

0 comments on commit e23cf43

Please sign in to comment.