diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index c51a67c5074..a7304d25d79 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -1,5 +1,5 @@ use crate::core::PackageId; -use crate::sources::registry::CRATES_IO_HTTP_INDEX; +use crate::sources::registry::{RegistryConfig, CRATES_IO_HTTP_INDEX}; use crate::sources::{DirectorySource, CRATES_IO_DOMAIN, CRATES_IO_INDEX, CRATES_IO_REGISTRY}; use crate::sources::{GitSource, PathSource, RegistrySource}; use crate::util::{CanonicalUrl, CargoResult, Config, IntoUrl}; @@ -39,6 +39,9 @@ struct SourceIdInner { /// WARNING: this is not always set for alt-registries when the name is /// not known. name: Option, + /// The registry config. This config is set by cargo config file and will + /// override config.json of the registry. + registry_config: Option, } /// The possible kinds of code source. Along with `SourceIdInner`, this fully defines the @@ -81,6 +84,27 @@ impl SourceId { url, precise: None, name: name.map(|n| n.into()), + registry_config: None, + }); + Ok(source_id) + } + + /// Creates a `SourceId` object from the kind, URL and a RegistryConfig. + /// + /// The provided RegistryConfig will override config.json of the registry. + fn new_with_registry_config( + kind: SourceKind, + url: Url, + name: Option<&str>, + registry_config: Option, + ) -> CargoResult { + let source_id = SourceId::wrap(SourceIdInner { + kind, + canonical_url: CanonicalUrl::new(&url)?, + url, + precise: None, + name: name.map(|n| n.into()), + registry_config, }); Ok(source_id) } @@ -178,9 +202,27 @@ impl SourceId { SourceId::new(SourceKind::Registry, url.clone(), None) } - /// Creates a `SourceId` from a remote registry URL with given name. - pub fn for_alt_registry(url: &Url, name: &str) -> CargoResult { - SourceId::new(SourceKind::Registry, url.clone(), Some(name)) + /// Creates a `SourceId` from a remote registry URL with given name and the optional + /// registry config(dl and api). + pub fn for_alt_registry( + url: &Url, + name: &str, + dl: Option<&str>, + api: Option<&str>, + ) -> CargoResult { + SourceId::new_with_registry_config( + SourceKind::Registry, + url.clone(), + Some(name), + if let Some(dl) = dl { + Some(RegistryConfig { + dl: dl.into(), + api: api.map(|api| api.into()), + }) + } else { + None + }, + ) } /// Creates a SourceId from a local registry path. @@ -228,6 +270,7 @@ impl SourceId { url, precise: None, name: Some(key.to_string()), + registry_config: None, })) } @@ -294,6 +337,29 @@ impl SourceId { matches!(self.inner.kind, SourceKind::Registry) } + /// Return `RegistryConfig` set by cargo config file. + pub fn get_registry_config(&self) -> Option { + self.inner.registry_config.clone() + } + + /// Override ori_config with the `RegistryConfig` which set by cargo config file, + /// return the overrided version of `RegistryConfig`. + pub fn override_registry_config( + &self, + ori_config: Option, + ) -> Option { + let registry_config = self.get_registry_config(); + ori_config.map_or(registry_config.clone(), |mut v| { + if let Some(registry_config) = registry_config { + v.dl = registry_config.dl.clone(); + if registry_config.api.is_some() { + v.api = registry_config.api; + } + } + Some(v) + }) + } + /// Returns `true` if this source from a Git repository. pub fn is_git(self) -> bool { matches!(self.inner.kind, SourceKind::Git(_)) diff --git a/src/cargo/sources/config.rs b/src/cargo/sources/config.rs index 6d6c7ee3944..5e9aebdd706 100644 --- a/src/cargo/sources/config.rs +++ b/src/cargo/sources/config.rs @@ -33,6 +33,10 @@ struct SourceConfigDef { directory: Option, /// A registry source. Value is a URL. registry: OptValue, + /// A URL to download crates. Override the dl field in config.json. + dl: OptValue, + /// A URL to for registry api. Override the api field value in config.json. + api: OptValue, /// A local registry source. local_registry: Option, /// A git source. Value is a URL. @@ -216,7 +220,14 @@ 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)?); + let dl = def.dl.map(|v| v.val.clone()); + let api = def.api.map(|v| v.val.clone()); + srcs.push(SourceId::for_alt_registry( + &url, + &name, + dl.as_deref(), + api.as_deref(), + )?); } if let Some(local_registry) = def.local_registry { let path = local_registry.resolve_path(self.config); diff --git a/src/cargo/sources/registry/http_remote.rs b/src/cargo/sources/registry/http_remote.rs index 1124e5fd181..ea5a6d98b63 100644 --- a/src/cargo/sources/registry/http_remote.rs +++ b/src/cargo/sources/registry/http_remote.rs @@ -503,7 +503,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> { match fs::read(&config_json_path) { Ok(raw_data) => match serde_json::from_slice(&raw_data) { Ok(json) => { - self.registry_config = Some(json); + self.registry_config = self.source_id.override_registry_config(Some(json)); return Poll::Ready(Ok(self.registry_config.clone())); } Err(e) => log::debug!("failed to decode cached config.json: {}", e), diff --git a/src/cargo/sources/registry/remote.rs b/src/cargo/sources/registry/remote.rs index e5f506bfca3..cd4944511ca 100644 --- a/src/cargo/sources/registry/remote.rs +++ b/src/cargo/sources/registry/remote.rs @@ -239,7 +239,9 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> { match ready!(self.load(Path::new(""), Path::new("config.json"), None)?) { LoadResponse::Data { raw_data, .. } => { trace!("config loaded"); - Poll::Ready(Ok(Some(serde_json::from_slice(&raw_data)?))) + Poll::Ready(Ok(self + .source_id + .override_registry_config(Some(serde_json::from_slice(&raw_data)?)))) } _ => Poll::Ready(Ok(None)), }