diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index c11102017af..ca126172c6e 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -251,43 +251,6 @@ mod tests { assert!(PackageId::new("foo", "", repo).is_err()); } - #[test] - fn debug() { - let loc = CRATES_IO_INDEX.into_url().unwrap(); - let pkg_id = PackageId::new("foo", "1.0.0", SourceId::for_registry(&loc).unwrap()).unwrap(); - assert_eq!( - r#"PackageId { name: "foo", version: "1.0.0", source: "registry `crates-io`" }"#, - format!("{:?}", pkg_id) - ); - - let expected = r#" -PackageId { - name: "foo", - version: "1.0.0", - source: "registry `crates-io`", -} -"# - .trim(); - - // Can be removed once trailing commas in Debug have reached the stable - // channel. - let expected_without_trailing_comma = r#" -PackageId { - name: "foo", - version: "1.0.0", - source: "registry `crates-io`" -} -"# - .trim(); - - let actual = format!("{:#?}", pkg_id); - if actual.ends_with(",\n}") { - assert_eq!(actual, expected); - } else { - assert_eq!(actual, expected_without_trailing_comma); - } - } - #[test] fn display() { let loc = CRATES_IO_INDEX.into_url().unwrap(); diff --git a/src/cargo/core/source_id.rs b/src/cargo/core/source_id.rs index 152c3ad30fa..d688b873914 100644 --- a/src/cargo/core/source_id.rs +++ b/src/cargo/core/source_id.rs @@ -51,14 +51,11 @@ struct SourceIdInner { kind: SourceKind, /// For example, the exact Git revision of the specified branch for a Git Source. precise: Option, - /// Name of the registry source for alternative registries - /// WARNING: this is not always set for alt-registries when the name is - /// not known. - name: Option, - /// Name of the alt registry in the `[registries]` table. - /// WARNING: this is not always set for alt-registries when the name is - /// not known. - alt_registry_key: Option, + /// Name of the remote registry. + /// + /// WARNING: this is not always set when the name is not known, + /// e.g. registry coming from `--index` or Cargo.lock + registry_key: Option, } /// The possible kinds of code source. @@ -93,11 +90,22 @@ pub enum GitReference { DefaultBranch, } +/// Where the remote source key is defined. +/// +/// The purpose of this is to provide better diagnostics for different sources of keys. +#[derive(Debug, Clone, PartialEq, Eq)] +enum KeyOf { + /// Defined in the `[registries]` table or the built-in `crates-io` key. + Registry(String), + /// Defined in the `[source]` replacement table. + Source(String), +} + impl SourceId { /// Creates a `SourceId` object from the kind and URL. /// /// The canonical url will be calculated, but the precise field will not - fn new(kind: SourceKind, url: Url, name: Option<&str>) -> CargoResult { + fn new(kind: SourceKind, url: Url, key: Option) -> CargoResult { if kind == SourceKind::SparseRegistry { // Sparse URLs are different because they store the kind prefix (sparse+) // in the URL. This is because the prefix is necessary to differentiate @@ -111,8 +119,7 @@ impl SourceId { canonical_url: CanonicalUrl::new(&url)?, url, precise: None, - name: name.map(|n| n.into()), - alt_registry_key: None, + registry_key: key, }); Ok(source_id) } @@ -230,10 +237,18 @@ impl SourceId { SourceId::new(kind, url.to_owned(), None) } - /// Creates a `SourceId` from a remote registry URL with given name. - pub fn for_alt_registry(url: &Url, name: &str) -> CargoResult { + /// Creates a `SourceId` for a remote registry from the `[registries]` table or crates.io. + pub fn for_alt_registry(url: &Url, key: &str) -> CargoResult { let kind = Self::remote_source_kind(url); - SourceId::new(kind, url.to_owned(), Some(name)) + let key = KeyOf::Registry(key.into()); + SourceId::new(kind, url.to_owned(), Some(key)) + } + + /// Creates a `SourceId` for a remote registry from the `[source]` replacement table. + pub fn for_source_replacement_registry(url: &Url, key: &str) -> CargoResult { + let kind = Self::remote_source_kind(url); + let key = KeyOf::Source(key.into()); + SourceId::new(kind, url.to_owned(), Some(key)) } /// Creates a `SourceId` from a local registry path. @@ -262,7 +277,8 @@ impl SourceId { if Self::crates_io_is_sparse(config)? { config.check_registry_index_not_set()?; let url = CRATES_IO_HTTP_INDEX.into_url().unwrap(); - SourceId::new(SourceKind::SparseRegistry, url, Some(CRATES_IO_REGISTRY)) + let key = KeyOf::Registry(CRATES_IO_REGISTRY.into()); + SourceId::new(SourceKind::SparseRegistry, url, Some(key)) } else { Self::crates_io(config) } @@ -289,15 +305,7 @@ impl SourceId { return Self::crates_io(config); } let url = config.get_registry_index(key)?; - let kind = Self::remote_source_kind(&url); - Ok(SourceId::wrap(SourceIdInner { - kind, - canonical_url: CanonicalUrl::new(&url)?, - url, - precise: None, - name: Some(key.to_string()), - alt_registry_key: Some(key.to_string()), - })) + Self::for_alt_registry(&url, key) } /// Gets this source URL. @@ -322,10 +330,8 @@ impl SourceId { /// Displays the name of a registry if it has one. Otherwise just the URL. pub fn display_registry_name(self) -> String { - if self.is_crates_io() { - CRATES_IO_REGISTRY.to_string() - } else if let Some(name) = &self.inner.name { - name.clone() + if let Some(key) = self.inner.registry_key.as_ref().map(|k| k.key()) { + key.into() } else if self.precise().is_some() { // We remove `precise` here to retrieve an permissive version of // `SourceIdInner`, which may contain the registry name. @@ -335,11 +341,10 @@ impl SourceId { } } - /// Gets the name of the remote registry as defined in the `[registries]` table. - /// WARNING: alt registries that come from Cargo.lock, or --index will - /// not have a name. + /// Gets the name of the remote registry as defined in the `[registries]` table, + /// or the built-in `crates-io` key. pub fn alt_registry_key(&self) -> Option<&str> { - self.inner.alt_registry_key.as_deref() + self.inner.registry_key.as_ref()?.alternative_registry() } /// Returns `true` if this source is from a filesystem path. @@ -652,10 +657,9 @@ impl Hash for SourceId { /// The hash of `SourceIdInner` is used to retrieve its interned value from /// `SOURCE_ID_CACHE`. We only care about fields that make `SourceIdInner` /// unique. Optional fields not affecting the uniqueness must be excluded, -/// such as [`name`] and [`alt_registry_key`]. That's why this is not derived. +/// such as [`registry_key`]. That's why this is not derived. /// -/// [`name`]: SourceIdInner::name -/// [`alt_registry_key`]: SourceIdInner::alt_registry_key +/// [`registry_key`]: SourceIdInner::registry_key impl Hash for SourceIdInner { fn hash(&self, into: &mut S) { self.kind.hash(into); @@ -868,6 +872,23 @@ impl<'a> fmt::Display for PrettyRef<'a> { } } +impl KeyOf { + /// Gets the underlying key. + fn key(&self) -> &str { + match self { + KeyOf::Registry(k) | KeyOf::Source(k) => k, + } + } + + /// Gets the key if it's from an alternative registry. + fn alternative_registry(&self) -> Option<&str> { + match self { + KeyOf::Registry(k) => Some(k), + _ => None, + } + } +} + #[cfg(test)] mod tests { use super::{GitReference, SourceId, SourceKind}; diff --git a/src/cargo/sources/config.rs b/src/cargo/sources/config.rs index f0c214e16d6..cc7aa9925cb 100644 --- a/src/cargo/sources/config.rs +++ b/src/cargo/sources/config.rs @@ -239,7 +239,7 @@ restore the source replacement configuration to continue the build let mut srcs = Vec::new(); if let Some(registry) = def.registry { let url = url(®istry, &format!("source.{}.registry", name))?; - srcs.push(SourceId::for_alt_registry(&url, &name)?); + srcs.push(SourceId::for_source_replacement_registry(&url, &name)?); } if let Some(local_registry) = def.local_registry { let path = local_registry.resolve_path(self.config); diff --git a/src/cargo/util/auth/mod.rs b/src/cargo/util/auth/mod.rs index 7f60fe7085f..ea82dce0cc2 100644 --- a/src/cargo/util/auth/mod.rs +++ b/src/cargo/util/auth/mod.rs @@ -2,7 +2,6 @@ use crate::{ core::features::cargo_docs_link, - sources::CRATES_IO_REGISTRY, util::{config::ConfigKey, CanonicalUrl, CargoResult, Config, IntoUrl}, }; use anyhow::{bail, Context as _}; @@ -506,11 +505,7 @@ fn credential_action( args: &[&str], require_cred_provider_config: bool, ) -> CargoResult { - let name = if sid.is_crates_io() { - Some(CRATES_IO_REGISTRY) - } else { - sid.alt_registry_key() - }; + let name = sid.alt_registry_key(); let registry = RegistryInfo { index_url: sid.url().as_str(), name, diff --git a/tests/testsuite/source_replacement.rs b/tests/testsuite/source_replacement.rs index 24f2ca3e3e3..ee2db71d8cf 100644 --- a/tests/testsuite/source_replacement.rs +++ b/tests/testsuite/source_replacement.rs @@ -248,3 +248,48 @@ fn undefined_default() { ) .run(); } + +#[cargo_test] +fn source_replacement_with_registry_url() { + let alternative = RegistryBuilder::new().alternative().http_api().build(); + Package::new("bar", "0.0.1").alternative(true).publish(); + + let crates_io = setup_replacement(&format!( + r#" + [source.crates-io] + replace-with = 'using-registry-url' + + [source.using-registry-url] + registry = '{}' + "#, + alternative.index_url() + )); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + [dependencies.bar] + version = "0.0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .replace_crates_io(crates_io.index_url()) + .with_stderr( + "\ +[UPDATING] `using-registry-url` index +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `using-registry-url`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([CWD]) +[FINISHED] dev [..] +", + ) + .run(); +}