Improve error message for publish key restriction.

The existing error message didn't really recognize that `publish` can be a
list.

This also adds support for `publish = ["crates-io"]` to restrict publishing
to crates.io only.
This commit is contained in:
Eric Huss 2019-04-11 11:34:00 -07:00
parent 449411f11d
commit bf23a7e430
2 changed files with 65 additions and 28 deletions

View file

@ -8,6 +8,7 @@ use std::{cmp, env};
use crates_io::{NewCrate, NewCrateDependency, Registry};
use curl::easy::{Easy, InfoType, SslOpt};
use failure::{bail, format_err};
use log::{log, Level};
use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
@ -16,7 +17,7 @@ use crate::core::manifest::ManifestMetadata;
use crate::core::source::Source;
use crate::core::{Package, SourceId, Workspace};
use crate::ops;
use crate::sources::{RegistrySource, SourceConfigMap};
use crate::sources::{RegistrySource, SourceConfigMap, CRATES_IO_REGISTRY};
use crate::util::config::{self, Config};
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::important_paths::find_root_manifest_for_wd;
@ -48,14 +49,16 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
let pkg = ws.current()?;
if let Some(ref allowed_registries) = *pkg.publish() {
if !match opts.registry {
Some(ref registry) => allowed_registries.contains(registry),
None => false,
} {
failure::bail!(
"some crates cannot be published.\n\
`{}` is marked as unpublishable",
pkg.name()
let reg_name = opts
.registry
.clone()
.unwrap_or_else(|| CRATES_IO_REGISTRY.to_string());
if !allowed_registries.contains(&reg_name) {
bail!(
"`{}` cannot be published.\n\
The registry `{}` is not listed in the `publish` value in Cargo.toml.",
pkg.name(),
reg_name
);
}
}
@ -112,7 +115,7 @@ fn verify_dependencies(
for dep in pkg.dependencies().iter() {
if dep.source_id().is_path() {
if !dep.specified_req() {
failure::bail!(
bail!(
"all path dependencies must have a version specified \
when publishing.\ndependency `{}` does not specify \
a version",
@ -131,7 +134,7 @@ fn verify_dependencies(
.map(|u| u.host_str() == Some("crates.io"))
.unwrap_or(false);
if registry_src.is_default_registry() || is_crates_io {
failure::bail!("crates cannot be published to crates.io with dependencies sourced from other\n\
bail!("crates cannot be published to crates.io with dependencies sourced from other\n\
registries either publish `{}` on crates.io or pull it into this repository\n\
and specify it with a path and version\n\
(crate `{}` is pulled from {})",
@ -140,7 +143,7 @@ fn verify_dependencies(
dep.source_id());
}
} else {
failure::bail!(
bail!(
"crates cannot be published with dependencies sourced from \
a repository\neither publish `{}` as its own crate and \
specify a version as a dependency or pull it into this \
@ -221,7 +224,7 @@ fn transmit(
};
if let Some(ref file) = *license_file {
if fs::metadata(&pkg.root().join(file)).is_err() {
failure::bail!("the license file `{}` does not exist", file)
bail!("the license file `{}` does not exist", file)
}
}
@ -357,7 +360,7 @@ pub fn registry(
cfg.unwrap()
};
cfg.and_then(|cfg| cfg.api)
.ok_or_else(|| failure::format_err!("{} does not support API commands", sid))?
.ok_or_else(|| format_err!("{} does not support API commands", sid))?
};
let handle = http_handle(config)?;
Ok((Registry::new_handle(api_host, token, handle), sid))
@ -372,13 +375,13 @@ pub fn http_handle(config: &Config) -> CargoResult<Easy> {
pub fn http_handle_and_timeout(config: &Config) -> CargoResult<(Easy, HttpTimeout)> {
if config.frozen() {
failure::bail!(
bail!(
"attempting to make an HTTP request, but --frozen was \
specified"
)
}
if !config.network_allowed() {
failure::bail!("can't make HTTP request in the offline mode")
bail!("can't make HTTP request in the offline mode")
}
// The timeout option for libcurl by default times out the entire transfer,
@ -605,9 +608,9 @@ pub fn modify_owners(config: &Config, opts: &OwnersOptions) -> CargoResult<()> {
if let Some(ref v) = opts.to_add {
let v = v.iter().map(|s| &s[..]).collect::<Vec<_>>();
let msg = registry.add_owners(&name, &v).map_err(|e| {
failure::format_err!("failed to invite owners to crate {}: {}", name, e)
})?;
let msg = registry
.add_owners(&name, &v)
.map_err(|e| format_err!("failed to invite owners to crate {}: {}", name, e))?;
config.shell().status("Owner", msg)?;
}
@ -658,7 +661,7 @@ pub fn yank(
};
let version = match version {
Some(v) => v,
None => failure::bail!("a version must be specified to yank"),
None => bail!("a version must be specified to yank"),
};
let (mut registry, _) = registry(config, token, index, reg, true)?;

View file

@ -354,8 +354,8 @@ fn unpublishable_crate() {
.with_status(101)
.with_stderr(
"\
[ERROR] some crates cannot be published.
`foo` is marked as unpublishable
[ERROR] `foo` cannot be published.
The registry `crates-io` is not listed in the `publish` value in Cargo.toml.
",
)
.run();
@ -644,8 +644,8 @@ fn registry_not_in_publish_list() {
.with_status(101)
.with_stderr(
"\
[ERROR] some crates cannot be published.
`foo` is marked as unpublishable
[ERROR] `foo` cannot be published.
The registry `alternative` is not listed in the `publish` value in Cargo.toml.
",
)
.run();
@ -675,8 +675,8 @@ fn publish_empty_list() {
.with_status(101)
.with_stderr(
"\
[ERROR] some crates cannot be published.
`foo` is marked as unpublishable
[ERROR] `foo` cannot be published.
The registry `alternative` is not listed in the `publish` value in Cargo.toml.
",
)
.run();
@ -745,13 +745,47 @@ fn block_publish_no_registry() {
.with_status(101)
.with_stderr(
"\
[ERROR] some crates cannot be published.
`foo` is marked as unpublishable
[ERROR] `foo` cannot be published.
The registry `alternative` is not listed in the `publish` value in Cargo.toml.
",
)
.run();
}
#[test]
fn publish_with_crates_io_explicit() {
// Explicitly setting `crates-io` in the publish list.
registry::init();
let p = project()
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
description = "foo"
publish = ["crates-io"]
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("publish --registry alternative")
.with_status(101)
.with_stderr(
"\
[ERROR] `foo` cannot be published.
The registry `alternative` is not listed in the `publish` value in Cargo.toml.
",
)
.run();
p.cargo("publish").run();
}
#[test]
fn publish_with_select_features() {
registry::init();