Skip to content

Commit bf23a7e

Browse files
committed
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.
1 parent 449411f commit bf23a7e

File tree

2 files changed

+65
-28
lines changed

2 files changed

+65
-28
lines changed

src/cargo/ops/registry.rs

+23-20
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::{cmp, env};
88

99
use crates_io::{NewCrate, NewCrateDependency, Registry};
1010
use curl::easy::{Easy, InfoType, SslOpt};
11+
use failure::{bail, format_err};
1112
use log::{log, Level};
1213
use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
1314

@@ -16,7 +17,7 @@ use crate::core::manifest::ManifestMetadata;
1617
use crate::core::source::Source;
1718
use crate::core::{Package, SourceId, Workspace};
1819
use crate::ops;
19-
use crate::sources::{RegistrySource, SourceConfigMap};
20+
use crate::sources::{RegistrySource, SourceConfigMap, CRATES_IO_REGISTRY};
2021
use crate::util::config::{self, Config};
2122
use crate::util::errors::{CargoResult, CargoResultExt};
2223
use crate::util::important_paths::find_root_manifest_for_wd;
@@ -48,14 +49,16 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
4849
let pkg = ws.current()?;
4950

5051
if let Some(ref allowed_registries) = *pkg.publish() {
51-
if !match opts.registry {
52-
Some(ref registry) => allowed_registries.contains(registry),
53-
None => false,
54-
} {
55-
failure::bail!(
56-
"some crates cannot be published.\n\
57-
`{}` is marked as unpublishable",
58-
pkg.name()
52+
let reg_name = opts
53+
.registry
54+
.clone()
55+
.unwrap_or_else(|| CRATES_IO_REGISTRY.to_string());
56+
if !allowed_registries.contains(&reg_name) {
57+
bail!(
58+
"`{}` cannot be published.\n\
59+
The registry `{}` is not listed in the `publish` value in Cargo.toml.",
60+
pkg.name(),
61+
reg_name
5962
);
6063
}
6164
}
@@ -112,7 +115,7 @@ fn verify_dependencies(
112115
for dep in pkg.dependencies().iter() {
113116
if dep.source_id().is_path() {
114117
if !dep.specified_req() {
115-
failure::bail!(
118+
bail!(
116119
"all path dependencies must have a version specified \
117120
when publishing.\ndependency `{}` does not specify \
118121
a version",
@@ -131,7 +134,7 @@ fn verify_dependencies(
131134
.map(|u| u.host_str() == Some("crates.io"))
132135
.unwrap_or(false);
133136
if registry_src.is_default_registry() || is_crates_io {
134-
failure::bail!("crates cannot be published to crates.io with dependencies sourced from other\n\
137+
bail!("crates cannot be published to crates.io with dependencies sourced from other\n\
135138
registries either publish `{}` on crates.io or pull it into this repository\n\
136139
and specify it with a path and version\n\
137140
(crate `{}` is pulled from {})",
@@ -140,7 +143,7 @@ fn verify_dependencies(
140143
dep.source_id());
141144
}
142145
} else {
143-
failure::bail!(
146+
bail!(
144147
"crates cannot be published with dependencies sourced from \
145148
a repository\neither publish `{}` as its own crate and \
146149
specify a version as a dependency or pull it into this \
@@ -221,7 +224,7 @@ fn transmit(
221224
};
222225
if let Some(ref file) = *license_file {
223226
if fs::metadata(&pkg.root().join(file)).is_err() {
224-
failure::bail!("the license file `{}` does not exist", file)
227+
bail!("the license file `{}` does not exist", file)
225228
}
226229
}
227230

@@ -357,7 +360,7 @@ pub fn registry(
357360
cfg.unwrap()
358361
};
359362
cfg.and_then(|cfg| cfg.api)
360-
.ok_or_else(|| failure::format_err!("{} does not support API commands", sid))?
363+
.ok_or_else(|| format_err!("{} does not support API commands", sid))?
361364
};
362365
let handle = http_handle(config)?;
363366
Ok((Registry::new_handle(api_host, token, handle), sid))
@@ -372,13 +375,13 @@ pub fn http_handle(config: &Config) -> CargoResult<Easy> {
372375

373376
pub fn http_handle_and_timeout(config: &Config) -> CargoResult<(Easy, HttpTimeout)> {
374377
if config.frozen() {
375-
failure::bail!(
378+
bail!(
376379
"attempting to make an HTTP request, but --frozen was \
377380
specified"
378381
)
379382
}
380383
if !config.network_allowed() {
381-
failure::bail!("can't make HTTP request in the offline mode")
384+
bail!("can't make HTTP request in the offline mode")
382385
}
383386

384387
// 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<()> {
605608

606609
if let Some(ref v) = opts.to_add {
607610
let v = v.iter().map(|s| &s[..]).collect::<Vec<_>>();
608-
let msg = registry.add_owners(&name, &v).map_err(|e| {
609-
failure::format_err!("failed to invite owners to crate {}: {}", name, e)
610-
})?;
611+
let msg = registry
612+
.add_owners(&name, &v)
613+
.map_err(|e| format_err!("failed to invite owners to crate {}: {}", name, e))?;
611614

612615
config.shell().status("Owner", msg)?;
613616
}
@@ -658,7 +661,7 @@ pub fn yank(
658661
};
659662
let version = match version {
660663
Some(v) => v,
661-
None => failure::bail!("a version must be specified to yank"),
664+
None => bail!("a version must be specified to yank"),
662665
};
663666

664667
let (mut registry, _) = registry(config, token, index, reg, true)?;

tests/testsuite/publish.rs

+42-8
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,8 @@ fn unpublishable_crate() {
354354
.with_status(101)
355355
.with_stderr(
356356
"\
357-
[ERROR] some crates cannot be published.
358-
`foo` is marked as unpublishable
357+
[ERROR] `foo` cannot be published.
358+
The registry `crates-io` is not listed in the `publish` value in Cargo.toml.
359359
",
360360
)
361361
.run();
@@ -644,8 +644,8 @@ fn registry_not_in_publish_list() {
644644
.with_status(101)
645645
.with_stderr(
646646
"\
647-
[ERROR] some crates cannot be published.
648-
`foo` is marked as unpublishable
647+
[ERROR] `foo` cannot be published.
648+
The registry `alternative` is not listed in the `publish` value in Cargo.toml.
649649
",
650650
)
651651
.run();
@@ -675,8 +675,8 @@ fn publish_empty_list() {
675675
.with_status(101)
676676
.with_stderr(
677677
"\
678-
[ERROR] some crates cannot be published.
679-
`foo` is marked as unpublishable
678+
[ERROR] `foo` cannot be published.
679+
The registry `alternative` is not listed in the `publish` value in Cargo.toml.
680680
",
681681
)
682682
.run();
@@ -745,13 +745,47 @@ fn block_publish_no_registry() {
745745
.with_status(101)
746746
.with_stderr(
747747
"\
748-
[ERROR] some crates cannot be published.
749-
`foo` is marked as unpublishable
748+
[ERROR] `foo` cannot be published.
749+
The registry `alternative` is not listed in the `publish` value in Cargo.toml.
750750
",
751751
)
752752
.run();
753753
}
754754

755+
#[test]
756+
fn publish_with_crates_io_explicit() {
757+
// Explicitly setting `crates-io` in the publish list.
758+
registry::init();
759+
760+
let p = project()
761+
.file(
762+
"Cargo.toml",
763+
r#"
764+
[project]
765+
name = "foo"
766+
version = "0.0.1"
767+
authors = []
768+
license = "MIT"
769+
description = "foo"
770+
publish = ["crates-io"]
771+
"#,
772+
)
773+
.file("src/main.rs", "fn main() {}")
774+
.build();
775+
776+
p.cargo("publish --registry alternative")
777+
.with_status(101)
778+
.with_stderr(
779+
"\
780+
[ERROR] `foo` cannot be published.
781+
The registry `alternative` is not listed in the `publish` value in Cargo.toml.
782+
",
783+
)
784+
.run();
785+
786+
p.cargo("publish").run();
787+
}
788+
755789
#[test]
756790
fn publish_with_select_features() {
757791
registry::init();

0 commit comments

Comments
 (0)