diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 602465918b0..e52aba1ec7e 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -201,6 +201,12 @@ impl<'de> de::Deserialize<'de> for TomlDependency { pub struct DetailedTomlDependency { version: Option, registry: Option, + /// The URL of the `registry` field. + /// This is an internal implementation detail. When Cargo creates a + /// package, it replaces `registry` with `registry-index` so that the + /// manifest contains the correct URL. All users won't have the same + /// registry names configured, so Cargo can't rely on just the name for + /// crates published by other users. registry_index: Option, path: Option, git: Option, @@ -1408,6 +1414,12 @@ impl DetailedTomlDependency { let registry_id = SourceId::alt_registry(cx.config, registry)?; dep.set_registry_id(registry_id); } + if let Some(registry_index) = &self.registry_index { + cx.features.require(Feature::alternative_registries())?; + let url = registry_index.to_url()?; + let registry_id = SourceId::for_registry(&url)?; + dep.set_registry_id(registry_id); + } if let Some(kind) = kind { dep.set_kind(kind); diff --git a/tests/testsuite/alt_registry.rs b/tests/testsuite/alt_registry.rs index 41ac080b640..f99ab93adc6 100644 --- a/tests/testsuite/alt_registry.rs +++ b/tests/testsuite/alt_registry.rs @@ -1063,3 +1063,155 @@ fn alt_reg_metadata() { ) .run(); } + +#[test] +fn unknown_registry() { + // A known registry refers to an unknown registry. + // foo -> bar(crates.io) -> baz(alt) + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["alternative-registries"] + + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies.bar] + version = "0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1") + .alternative(true) + .publish(); + Package::new("bar", "0.0.1") + .registry_dep("baz", "0.0.1") + .publish(); + + // Remove "alternative" from config. + let cfg_path = paths::home().join(".cargo/config"); + let mut config = fs::read_to_string(&cfg_path).unwrap(); + let start = config.find("[registries.alternative]").unwrap(); + config.insert(start, '#'); + let start_index = &config[start..].find("index =").unwrap(); + config.insert(start + start_index, '#'); + fs::write(&cfg_path, config).unwrap(); + + p.cargo("build") + .masquerade_as_nightly_cargo() + .run(); + + // Important parts: + // foo -> bar registry = null + // bar -> baz registry = alternate + p.cargo("metadata --format-version=1") + .masquerade_as_nightly_cargo() + .with_json(r#" + { + "packages": [ + { + "name": "baz", + "version": "0.0.1", + "id": "baz 0.0.1 (registry+file://[..]/alternative-registry)", + "license": null, + "license_file": null, + "description": null, + "source": "registry+file://[..]/alternative-registry", + "dependencies": [], + "targets": "{...}", + "features": {}, + "manifest_path": "[..]", + "metadata": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "edition": "2015", + "links": null + }, + { + "name": "foo", + "version": "0.0.1", + "id": "foo 0.0.1 (path+file://[..]/foo)", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [ + { + "name": "bar", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "req": "^0.0.1", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": null + } + ], + "targets": "{...}", + "features": {}, + "manifest_path": "[..]/foo/Cargo.toml", + "metadata": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "edition": "2015", + "links": null + }, + { + "name": "bar", + "version": "0.0.1", + "id": "bar 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "license": null, + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [ + { + "name": "baz", + "source": "registry+file://[..]/alternative-registry", + "req": "^0.0.1", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": "file:[..]/alternative-registry" + } + ], + "targets": "{...}", + "features": {}, + "manifest_path": "[..]", + "metadata": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "edition": "2015", + "links": null + } + ], + "workspace_members": [ + "foo 0.0.1 (path+file://[..]/foo)" + ], + "resolve": "{...}", + "target_directory": "[..]/foo/target", + "version": 1, + "workspace_root": "[..]/foo" + } + "#) + .run(); +} diff --git a/tests/testsuite/support/registry.rs b/tests/testsuite/support/registry.rs index 82439c15c91..76b641c5384 100644 --- a/tests/testsuite/support/registry.rs +++ b/tests/testsuite/support/registry.rs @@ -454,7 +454,8 @@ impl Package { target, kind, dep.name, dep.vers )); if let Some(registry) = &dep.registry { - manifest.push_str(&format!("registry = \"{}\"", registry)); + assert_eq!(registry, "alternative"); + manifest.push_str(&format!("registry-index = \"{}\"", alt_registry())); } }