Skip to content

Commit

Permalink
publish: rework the crates.io detection logic.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ehuss committed Jan 5, 2019
1 parent dcb4360 commit 0a4cfa6
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 19 deletions.
7 changes: 0 additions & 7 deletions src/cargo/core/source/source_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,6 @@ impl SourceId {
}
}

/// Is this source from an alternative registry
/// DEPRECATED: This is not correct if the registry name is not known
/// (for example when loaded from an index).
pub fn is_alt_registry(self) -> bool {
self.is_registry() && self.inner.name.is_some()
}

/// Is this source from a git repository
pub fn is_git(self) -> bool {
match self.inner.kind {
Expand Down
27 changes: 19 additions & 8 deletions src/cargo/ops/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
opts.registry.clone(),
true,
)?;
verify_dependencies(pkg, reg_id)?;
verify_dependencies(pkg, &registry, reg_id)?;

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

fn verify_dependencies(pkg: &Package, registry_src: SourceId) -> CargoResult<()> {
fn verify_dependencies(
pkg: &Package,
registry: &Registry,
registry_src: SourceId,
) -> CargoResult<()> {
for dep in pkg.dependencies().iter() {
if dep.source_id().is_path() {
if !dep.specified_req() {
Expand All @@ -115,9 +119,16 @@ fn verify_dependencies(pkg: &Package, registry_src: SourceId) -> CargoResult<()>
}
} else if dep.source_id() != registry_src {
if dep.source_id().is_registry() {
// Block requests to send to a registry if it is not an alternative
// registry
if !registry_src.is_alt_registry() {
// Block requests to send to crates.io with alt-registry deps.
// This extra hostname check is mostly to assist with testing,
// but also prevents someone using `--index` to specify
// something that points to crates.io.
let is_crates_io = registry
.host()
.to_url()
.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\
registries either publish `{}` on crates.io or pull it into this repository\n\
and specify it with a path and version\n\
Expand All @@ -128,9 +139,9 @@ fn verify_dependencies(pkg: &Package, registry_src: SourceId) -> CargoResult<()>
}
} else {
failure::bail!(
"crates cannot be published to crates.io with dependencies sourced from \
a repository\neither publish `{}` as its own crate on crates.io and \
specify a crates.io version as a dependency or pull it into this \
"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 \
repository and specify it with a path and version\n(crate `{}` has \
repository path `{}`)",
dep.package_name(),
Expand Down
32 changes: 31 additions & 1 deletion tests/testsuite/alt_registry.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::support::publish::validate_alt_upload;
use crate::support::registry::{self, Package};
use crate::support::{basic_manifest, git, paths, project};
use cargo::util::ToUrl;
use std::fs::{self, File};
use std::io::Write;

Expand Down Expand Up @@ -288,6 +289,8 @@ fn registry_incompatible_with_git() {

#[test]
fn cannot_publish_to_crates_io_with_registry_dependency() {
let fakeio_path = paths::root().join("fake.io");
let fakeio_url = fakeio_path.to_url().unwrap();
let p = project()
.file(
"Cargo.toml",
Expand All @@ -303,12 +306,39 @@ fn cannot_publish_to_crates_io_with_registry_dependency() {
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
".cargo/config",
&format!(
r#"
[registries.fakeio]
index = "{}"
"#,
fakeio_url
),
)
.build();

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

// Since this can't really call plain `publish` without fetching the real
// crates.io index, create a fake one that points to the real crates.io.
git::repo(&fakeio_path)
.file(
"config.json",
r#"
{"dl": "https://crates.io/api/v1/crates", "api": "https://crates.io"}
"#,
)
.build();

p.cargo("publish --registry fakeio -Z unstable-options")
.masquerade_as_nightly_cargo()
.with_status(101)
.with_stderr_contains("[ERROR] crates cannot be published to crates.io[..]")
.run();

p.cargo("publish --index")
.arg(registry::registry().to_string())
.arg(fakeio_url.to_string())
.masquerade_as_nightly_cargo()
.with_status(101)
.with_stderr_contains("[ERROR] crates cannot be published to crates.io[..]")
Expand Down
6 changes: 3 additions & 3 deletions tests/testsuite/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,9 @@ fn git_deps() {
.with_stderr(
"\
[UPDATING] [..] index
[ERROR] crates cannot be published to crates.io with dependencies sourced from \
a repository\neither publish `foo` as its own crate on crates.io and \
specify a crates.io version as a dependency or pull it into this \
[ERROR] crates cannot be published with dependencies sourced from \
a repository\neither publish `foo` as its own crate and \
specify a version as a dependency or pull it into this \
repository and specify it with a path and version\n\
(crate `foo` has repository path `git://path/to/nowhere`)\
",
Expand Down

0 comments on commit 0a4cfa6

Please sign in to comment.