Skip to content

Commit 0a4cfa6

Browse files
committed
publish: rework the crates.io detection logic.
The old code used an unreliable method to detect if `cargo publish` was publishing to crates.io. This should work even if the `--index` flag is used. Also includes a very minor rewording of an error message mentioning crates.io, even for alternative registries.
1 parent dcb4360 commit 0a4cfa6

File tree

4 files changed

+53
-19
lines changed

4 files changed

+53
-19
lines changed

src/cargo/core/source/source_id.rs

-7
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,6 @@ impl SourceId {
248248
}
249249
}
250250

251-
/// Is this source from an alternative registry
252-
/// DEPRECATED: This is not correct if the registry name is not known
253-
/// (for example when loaded from an index).
254-
pub fn is_alt_registry(self) -> bool {
255-
self.is_registry() && self.inner.name.is_some()
256-
}
257-
258251
/// Is this source from a git repository
259252
pub fn is_git(self) -> bool {
260253
match self.inner.kind {

src/cargo/ops/registry.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
6868
opts.registry.clone(),
6969
true,
7070
)?;
71-
verify_dependencies(pkg, reg_id)?;
71+
verify_dependencies(pkg, &registry, reg_id)?;
7272

7373
// Prepare a tarball, with a non-surpressable warning if metadata
7474
// is missing since this is being put online.
@@ -102,7 +102,11 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
102102
Ok(())
103103
}
104104

105-
fn verify_dependencies(pkg: &Package, registry_src: SourceId) -> CargoResult<()> {
105+
fn verify_dependencies(
106+
pkg: &Package,
107+
registry: &Registry,
108+
registry_src: SourceId,
109+
) -> CargoResult<()> {
106110
for dep in pkg.dependencies().iter() {
107111
if dep.source_id().is_path() {
108112
if !dep.specified_req() {
@@ -115,9 +119,16 @@ fn verify_dependencies(pkg: &Package, registry_src: SourceId) -> CargoResult<()>
115119
}
116120
} else if dep.source_id() != registry_src {
117121
if dep.source_id().is_registry() {
118-
// Block requests to send to a registry if it is not an alternative
119-
// registry
120-
if !registry_src.is_alt_registry() {
122+
// Block requests to send to crates.io with alt-registry deps.
123+
// This extra hostname check is mostly to assist with testing,
124+
// but also prevents someone using `--index` to specify
125+
// something that points to crates.io.
126+
let is_crates_io = registry
127+
.host()
128+
.to_url()
129+
.map(|u| u.host_str() == Some("crates.io"))
130+
.unwrap_or(false);
131+
if registry_src.is_default_registry() || is_crates_io {
121132
failure::bail!("crates cannot be published to crates.io with dependencies sourced from other\n\
122133
registries either publish `{}` on crates.io or pull it into this repository\n\
123134
and specify it with a path and version\n\
@@ -128,9 +139,9 @@ fn verify_dependencies(pkg: &Package, registry_src: SourceId) -> CargoResult<()>
128139
}
129140
} else {
130141
failure::bail!(
131-
"crates cannot be published to crates.io with dependencies sourced from \
132-
a repository\neither publish `{}` as its own crate on crates.io and \
133-
specify a crates.io version as a dependency or pull it into this \
142+
"crates cannot be published with dependencies sourced from \
143+
a repository\neither publish `{}` as its own crate and \
144+
specify a version as a dependency or pull it into this \
134145
repository and specify it with a path and version\n(crate `{}` has \
135146
repository path `{}`)",
136147
dep.package_name(),

tests/testsuite/alt_registry.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::support::publish::validate_alt_upload;
22
use crate::support::registry::{self, Package};
33
use crate::support::{basic_manifest, git, paths, project};
4+
use cargo::util::ToUrl;
45
use std::fs::{self, File};
56
use std::io::Write;
67

@@ -288,6 +289,8 @@ fn registry_incompatible_with_git() {
288289

289290
#[test]
290291
fn cannot_publish_to_crates_io_with_registry_dependency() {
292+
let fakeio_path = paths::root().join("fake.io");
293+
let fakeio_url = fakeio_path.to_url().unwrap();
291294
let p = project()
292295
.file(
293296
"Cargo.toml",
@@ -303,12 +306,39 @@ fn cannot_publish_to_crates_io_with_registry_dependency() {
303306
"#,
304307
)
305308
.file("src/main.rs", "fn main() {}")
309+
.file(
310+
".cargo/config",
311+
&format!(
312+
r#"
313+
[registries.fakeio]
314+
index = "{}"
315+
"#,
316+
fakeio_url
317+
),
318+
)
306319
.build();
307320

308321
Package::new("bar", "0.0.1").alternative(true).publish();
309322

323+
// Since this can't really call plain `publish` without fetching the real
324+
// crates.io index, create a fake one that points to the real crates.io.
325+
git::repo(&fakeio_path)
326+
.file(
327+
"config.json",
328+
r#"
329+
{"dl": "https://crates.io/api/v1/crates", "api": "https://crates.io"}
330+
"#,
331+
)
332+
.build();
333+
334+
p.cargo("publish --registry fakeio -Z unstable-options")
335+
.masquerade_as_nightly_cargo()
336+
.with_status(101)
337+
.with_stderr_contains("[ERROR] crates cannot be published to crates.io[..]")
338+
.run();
339+
310340
p.cargo("publish --index")
311-
.arg(registry::registry().to_string())
341+
.arg(fakeio_url.to_string())
312342
.masquerade_as_nightly_cargo()
313343
.with_status(101)
314344
.with_stderr_contains("[ERROR] crates cannot be published to crates.io[..]")

tests/testsuite/publish.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,9 @@ fn git_deps() {
273273
.with_stderr(
274274
"\
275275
[UPDATING] [..] index
276-
[ERROR] crates cannot be published to crates.io with dependencies sourced from \
277-
a repository\neither publish `foo` as its own crate on crates.io and \
278-
specify a crates.io version as a dependency or pull it into this \
276+
[ERROR] crates cannot be published with dependencies sourced from \
277+
a repository\neither publish `foo` as its own crate and \
278+
specify a version as a dependency or pull it into this \
279279
repository and specify it with a path and version\n\
280280
(crate `foo` has repository path `git://path/to/nowhere`)\
281281
",

0 commit comments

Comments
 (0)