Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(publish): add more check when use publish -p <SPEC> #10677

Merged
merged 13 commits into from May 27, 2022
4 changes: 2 additions & 2 deletions src/cargo/ops/cargo_compile.rs
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
16 changes: 16 additions & 0 deletions src/cargo/ops/registry.rs
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::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,22 @@ pub struct PublishOpts<'cfg> {

pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
let specs = opts.to_publish.to_package_id_specs(ws)?;

if let Packages(_) = &opts.to_publish {
if specs.len() > 1 {
bail!("the `-p` argument must be specified to select a single package to publish");
}
likzn marked this conversation as resolved.
Show resolved Hide resolved
} else {
if ws.is_virtual() {
bail!("must use `-p` argument in virtual manifest")
likzn marked this conversation as resolved.
Show resolved Hide resolved
}
}
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)?;
// Double check
assert_eq!(pkgs.len(), 1);

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

Expand Down
204 changes: 178 additions & 26 deletions tests/testsuite/publish.rs
Expand Up @@ -56,30 +56,30 @@ fn validate_upload_foo() {
);
}

fn validate_upload_bar() {
fn validate_upload_li() {
publish::validate_upload(
r#"
{
"authors": [],
"badges": {},
"categories": [],
"deps": [],
"description": "bar",
"description": "li",
"documentation": null,
"features": {},
"homepage": null,
"keywords": [],
"license": "MIT",
"license_file": null,
"links": null,
"name": "bar",
"name": "li",
"readme": null,
"readme_file": null,
"repository": null,
"vers": "0.0.1"
}
"#,
"bar-0.0.1.crate",
"li-0.0.1.crate",
&["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
);
}
Expand Down Expand Up @@ -1665,15 +1665,60 @@ Caused by:
}

#[cargo_test]
fn in_workspace() {
fn in_package_workspace() {
registry::init();

let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2021"
[workspace]
members = ["foo", "bar"]
members = ["li"]
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
"li/Cargo.toml",
r#"
[package]
name = "li"
version = "0.0.1"
description = "li"
license = "MIT"
"#,
)
.file("li/src/main.rs", "fn main() {}")
.build();

p.cargo("publish -p li --no-verify --token sekrit")
.with_stderr(
"\
[UPDATING] [..]
[WARNING] manifest has no documentation, homepage or repository.
See [..]
[PACKAGING] li v0.0.1 ([CWD]/li)
[UPLOADING] li v0.0.1 ([CWD]/li)
",
)
.run();

validate_upload_li();
}

#[cargo_test]
fn in_virtual_workspace() {
registry::init();

let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo"]
"#,
)
.file(
Expand All @@ -1688,46 +1733,153 @@ fn in_workspace() {
"#,
)
.file("foo/src/main.rs", "fn main() {}")
.build();

p.cargo("publish --no-verify --token sekrit")
.with_status(101)
.with_stderr("error: must use `-p` argument in virtual manifest")
.run();
}

#[cargo_test]
fn in_package_workspace_not_found() {
registry::init();

let p = project()
.file(
"bar/Cargo.toml",
"Cargo.toml",
r#"
[project]
name = "bar"
[package]
name = "foo"
version = "0.1.0"
edition = "2021"
[workspace]
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
"li/Cargo.toml",
r#"
[package]
name = "li"
version = "0.0.1"
edition = "2021"
authors = []
license = "MIT"
description = "bar"
workspace = ".."
description = "li"
"#,
)
.file("bar/src/main.rs", "fn main() {}")
.file("li/src/main.rs", "fn main() {}")
.build();

p.cargo("publish --no-verify --token sekrit -p foo")
p.cargo("publish -p li --no-verify --token sekrit ")
.with_status(101)
.with_stderr(
"\
[UPDATING] [..]
[WARNING] manifest has no documentation, [..]
See [..]
[PACKAGING] foo v0.0.1 ([CWD]/foo)
[UPLOADING] foo v0.0.1 ([CWD]/foo)
error: package ID specification `li` did not match any packages

<tab>Did you mean `foo`?
",
)
.run();
}

validate_upload_foo();
#[cargo_test]
fn in_package_workspace_found_multiple() {
registry::init();

p.cargo("publish --no-verify --token sekrit -p bar")
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2021"
[workspace]
members = ["li","lii"]
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
"li/Cargo.toml",
r#"
[package]
name = "li"
version = "0.0.1"
edition = "2021"
authors = []
license = "MIT"
description = "li"
"#,
)
.file("li/src/main.rs", "fn main() {}")
.file(
"lii/Cargo.toml",
r#"
[package]
name = "lii"
version = "0.0.1"
edition = "2021"
authors = []
license = "MIT"
description = "lii"
"#,
)
.file("lii/src/main.rs", "fn main() {}")
.build();

p.cargo("publish -p li* --no-verify --token sekrit ")
.with_status(101)
.with_stderr(
"\
[UPDATING] [..]
[WARNING] manifest has no documentation, [..]
See [..]
[PACKAGING] bar v0.0.1 ([CWD]/bar)
[UPLOADING] bar v0.0.1 ([CWD]/bar)
error: the `-p` argument must be specified to select a single package to publish
",
)
.run();
}

validate_upload_bar();
#[cargo_test]
// https://github.com/rust-lang/cargo/issues/10536
fn publish_path_dependency_without_workspace() {
registry::init();

let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2021"
[dependencies.bar]
path = "bar"
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.0.1"
edition = "2021"
authors = []
license = "MIT"
description = "bar"
"#,
)
.file("bar/src/main.rs", "fn main() {}")
.build();

p.cargo("publish -p bar --no-verify --token sekrit ")
.with_status(101)
.with_stderr(
"\
error: package ID specification `bar` did not match any packages

<tab>Did you mean `foo`?
",
)
.run();
}