Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce dl key to allow per-crate download links #10484

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions crates/cargo-test-support/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ pub struct Package {
rust_version: Option<String>,
cargo_features: Vec<String>,
v: Option<u32>,
dl: Option<String>,
}

type FeatureMap = BTreeMap<String, Vec<String>>;
Expand Down Expand Up @@ -561,6 +562,7 @@ impl Package {
rust_version: None,
cargo_features: Vec::new(),
v: None,
dl: None,
}
}

Expand Down Expand Up @@ -709,6 +711,12 @@ impl Package {
self
}

/// Specifies a different download URI for the package.
pub fn dl(&mut self, dl: &str) -> &mut Package {
self.dl = Some(dl.to_string());
self
}

pub fn cargo_feature(&mut self, feature: &str) -> &mut Package {
self.cargo_features.push(feature.to_owned());
self
Expand Down Expand Up @@ -788,6 +796,9 @@ impl Package {
if let Some(v) = self.v {
json["v"] = serde_json::json!(v);
}
if let Some(dl) = &self.dl {
json["dl"] = serde_json::json!(dl);
}
let line = json.to_string();

let file = make_dep_path(&self.name, false);
Expand Down
4 changes: 4 additions & 0 deletions crates/resolver-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ pub fn resolve_with_config_raw(
deps,
&BTreeMap::new(),
None::<&String>,
None,
)
.unwrap();
let opts = ResolveOpts::everything();
Expand Down Expand Up @@ -581,6 +582,7 @@ pub fn pkg_dep<T: ToPkgId>(name: T, dep: Vec<Dependency>) -> Summary {
dep,
&BTreeMap::new(),
link,
None,
)
.unwrap()
}
Expand Down Expand Up @@ -609,6 +611,7 @@ pub fn pkg_loc(name: &str, loc: &str) -> Summary {
Vec::new(),
&BTreeMap::new(),
link,
None,
)
.unwrap()
}
Expand All @@ -623,6 +626,7 @@ pub fn remove_dep(sum: &Summary, ind: usize) -> Summary {
deps,
&BTreeMap::new(),
sum.links().map(|a| a.as_str()),
None,
)
.unwrap()
}
Expand Down
10 changes: 9 additions & 1 deletion src/cargo/core/resolver/version_prefs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,15 @@ mod test {
let pkg_id = pkgid(name, version);
let config = Config::default().unwrap();
let features = BTreeMap::new();
Summary::new(&config, pkg_id, Vec::new(), &features, None::<&String>).unwrap()
Summary::new(
&config,
pkg_id,
Vec::new(),
&features,
None::<&String>,
None,
)
.unwrap()
}

fn describe(summaries: &Vec<Summary>) -> String {
Expand Down
6 changes: 6 additions & 0 deletions src/cargo/core/summary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct Inner {
features: Rc<FeatureMap>,
checksum: Option<String>,
links: Option<InternedString>,
dl: Option<InternedString>,
}

impl Summary {
Expand All @@ -34,6 +35,7 @@ impl Summary {
dependencies: Vec<Dependency>,
features: &BTreeMap<InternedString, Vec<InternedString>>,
links: Option<impl Into<InternedString>>,
dl: Option<InternedString>,
) -> CargoResult<Summary> {
// ****CAUTION**** If you change anything here that may raise a new
// error, be sure to coordinate that change with either the index
Expand All @@ -55,6 +57,7 @@ impl Summary {
features: Rc::new(feature_map),
checksum: None,
links: links.map(|l| l.into()),
dl,
}),
})
}
Expand Down Expand Up @@ -84,6 +87,9 @@ impl Summary {
pub fn links(&self) -> Option<InternedString> {
self.inner.links
}
pub fn dl(&self) -> Option<InternedString> {
self.inner.dl
}

pub fn override_id(mut self, id: PackageId) -> Summary {
Rc::make_mut(&mut self.inner).package_id = id;
Expand Down
55 changes: 31 additions & 24 deletions src/cargo/sources/registry/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub(super) fn download(
cache_path: &Filesystem,
config: &Config,
pkg: PackageId,
override_dl: Option<&str>,
checksum: &str,
registry_config: RegistryConfig,
) -> CargoResult<MaybeLock> {
Expand All @@ -44,30 +45,36 @@ pub(super) fn download(
}
}

let mut url = registry_config.dl;
if !url.contains(CRATE_TEMPLATE)
&& !url.contains(VERSION_TEMPLATE)
&& !url.contains(PREFIX_TEMPLATE)
&& !url.contains(LOWER_PREFIX_TEMPLATE)
&& !url.contains(CHECKSUM_TEMPLATE)
{
// Original format before customizing the download URL was supported.
write!(
url,
"/{}/{}/download",
pkg.name(),
pkg.version().to_string()
)
.unwrap();
} else {
let prefix = make_dep_prefix(&*pkg.name());
url = url
.replace(CRATE_TEMPLATE, &*pkg.name())
.replace(VERSION_TEMPLATE, &pkg.version().to_string())
.replace(PREFIX_TEMPLATE, &prefix)
.replace(LOWER_PREFIX_TEMPLATE, &prefix.to_lowercase())
.replace(CHECKSUM_TEMPLATE, checksum);
}
let url = override_dl.map_or_else(
|| {
let mut url = registry_config.dl;
if !url.contains(CRATE_TEMPLATE)
&& !url.contains(VERSION_TEMPLATE)
&& !url.contains(PREFIX_TEMPLATE)
&& !url.contains(LOWER_PREFIX_TEMPLATE)
&& !url.contains(CHECKSUM_TEMPLATE)
{
// Original format before customizing the download URL was supported.
write!(
url,
"/{}/{}/download",
pkg.name(),
pkg.version().to_string()
)
.unwrap();
} else {
let prefix = make_dep_prefix(&*pkg.name());
url = url
.replace(CRATE_TEMPLATE, &*pkg.name())
.replace(VERSION_TEMPLATE, &pkg.version().to_string())
.replace(PREFIX_TEMPLATE, &prefix)
.replace(LOWER_PREFIX_TEMPLATE, &prefix.to_lowercase())
.replace(CHECKSUM_TEMPLATE, checksum);
}
url
},
ToString::to_string,
);

Ok(MaybeLock::Download {
url,
Expand Down
8 changes: 7 additions & 1 deletion src/cargo/sources/registry/http_remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,12 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
self.requested_update = true;
}

fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock> {
fn download(
&mut self,
pkg: PackageId,
override_dl: Option<&str>,
checksum: &str,
) -> CargoResult<MaybeLock> {
let registry_config = loop {
match self.config()? {
Poll::Pending => self.block_until_ready()?,
Expand All @@ -559,6 +564,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
&self.cache_path,
&self.config,
pkg,
override_dl,
checksum,
registry_config,
)
Expand Down
19 changes: 11 additions & 8 deletions src/cargo/sources/registry/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,19 +265,21 @@ impl<'cfg> RegistryIndex<'cfg> {
}
}

/// Returns the hash listed for a specified `PackageId`.
pub fn hash(&mut self, pkg: PackageId, load: &mut dyn RegistryData) -> Poll<CargoResult<&str>> {
/// Returns the package summary for a specified `PackageId`.
pub fn summary(
&mut self,
pkg: PackageId,
load: &mut dyn RegistryData,
) -> Poll<CargoResult<&IndexSummary>> {
let req = OptVersionReq::exact(pkg.version());
let summary = self.summaries(pkg.name(), &req, load)?;
let summary = match summary {
Poll::Ready(mut summary) => summary.next(),
Poll::Pending => return Poll::Pending,
};
Poll::Ready(Ok(summary
.ok_or_else(|| internal(format!("no hash listed for {}", pkg)))?
.summary
.checksum()
.ok_or_else(|| internal(format!("no hash listed for {}", pkg)))?))
Poll::Ready(Ok(
summary.ok_or_else(|| internal(format!("no summary for {}", pkg)))?
))
}

/// Load a list of summaries for `name` package in this registry which
Expand Down Expand Up @@ -854,6 +856,7 @@ impl IndexSummary {
yanked,
links,
v,
dl,
} = serde_json::from_slice(line)?;
let v = v.unwrap_or(1);
log::trace!("json parsed registry {}/{}", name, vers);
Expand All @@ -867,7 +870,7 @@ impl IndexSummary {
features.entry(name).or_default().extend(values);
}
}
let mut summary = Summary::new(config, pkgid, deps, &features, links)?;
let mut summary = Summary::new(config, pkgid, deps, &features, links, dl)?;
summary.set_checksum(cksum);
Ok(IndexSummary {
summary,
Expand Down
7 changes: 6 additions & 1 deletion src/cargo/sources/registry/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,12 @@ impl<'cfg> RegistryData for LocalRegistry<'cfg> {
self.updated
}

fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock> {
fn download(
&mut self,
pkg: PackageId,
_override_dl: Option<&str>,
checksum: &str,
) -> CargoResult<MaybeLock> {
let crate_file = format!("{}-{}.crate", pkg.name(), pkg.version());

// Note that the usage of `into_path_unlocked` here is because the local
Expand Down
34 changes: 27 additions & 7 deletions src/cargo/sources/registry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,10 @@ use tar::Archive;
use crate::core::dependency::{DepKind, Dependency};
use crate::core::source::MaybePackage;
use crate::core::{Package, PackageId, Source, SourceId, Summary};
use crate::sources::registry::index::IndexSummary;
use crate::sources::PathSource;
use crate::util::hex;
use crate::util::internal;
use crate::util::interning::InternedString;
use crate::util::into_url::IntoUrl;
use crate::util::network::PollExt;
Expand Down Expand Up @@ -277,6 +279,8 @@ pub struct RegistryPackage<'a> {
/// Added early 2018 (see <https://github.com/rust-lang/cargo/pull/4978>),
/// can be `None` if published before then.
links: Option<InternedString>,
/// Allows overriding the registry's global `dl` link for this package only.
dl: Option<InternedString>,
/// The schema version for this entry.
///
/// If this is None, it defaults to version 1. Entries with unknown
Expand Down Expand Up @@ -481,7 +485,12 @@ pub trait RegistryData {
/// `finish_download`. For already downloaded `.crate` files, it does not
/// validate the checksum, assuming the filesystem does not suffer from
/// corruption or manipulation.
fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock>;
fn download(
&mut self,
pkg: PackageId,
override_dl: Option<&str>,
checksum: &str,
) -> CargoResult<MaybeLock>;

/// Finish a download by saving a `.crate` file to disk.
///
Expand Down Expand Up @@ -764,13 +773,20 @@ impl<'cfg> Source for RegistrySource<'cfg> {
}

fn download(&mut self, package: PackageId) -> CargoResult<MaybePackage> {
let hash = loop {
match self.index.hash(package, &mut *self.ops)? {
let (hash, override_dl) = loop {
match self.index.summary(package, &mut *self.ops)? {
Poll::Pending => self.block_until_ready()?,
Poll::Ready(hash) => break hash,
Poll::Ready(IndexSummary { ref summary, .. }) => {
break (
summary
.checksum()
.ok_or_else(|| internal(format!("no hash listed for {}", package)))?,
summary.dl(),
)
}
}
};
match self.ops.download(package, hash)? {
match self.ops.download(package, override_dl.as_deref(), hash)? {
MaybeLock::Ready(file) => self.get_pkg(package, &file).map(MaybePackage::Ready),
MaybeLock::Download { url, descriptor } => {
Ok(MaybePackage::Download { url, descriptor })
Expand All @@ -780,9 +796,13 @@ impl<'cfg> Source for RegistrySource<'cfg> {

fn finish_download(&mut self, package: PackageId, data: Vec<u8>) -> CargoResult<Package> {
let hash = loop {
match self.index.hash(package, &mut *self.ops)? {
match self.index.summary(package, &mut *self.ops)? {
Poll::Pending => self.block_until_ready()?,
Poll::Ready(hash) => break hash,
Poll::Ready(IndexSummary { ref summary, .. }) => {
break summary
.checksum()
.ok_or_else(|| internal(format!("no hash listed for {}", package)))?
}
}
};
let file = self.ops.finish_download(package, hash, &data)?;
Expand Down
8 changes: 7 additions & 1 deletion src/cargo/sources/registry/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,12 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
self.updated
}

fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock> {
fn download(
&mut self,
pkg: PackageId,
override_dl: Option<&str>,
checksum: &str,
) -> CargoResult<MaybeLock> {
let registry_config = loop {
match self.config()? {
Poll::Pending => self.block_until_ready()?,
Expand All @@ -308,6 +313,7 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
&self.cache_path,
&self.config,
pkg,
override_dl,
checksum,
registry_config,
)
Expand Down
1 change: 1 addition & 0 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1627,6 +1627,7 @@ impl TomlManifest {
deps,
me.features.as_ref().unwrap_or(&empty_features),
project.links.as_deref(),
None,
)?;

let metadata = ManifestMetadata {
Expand Down
5 changes: 5 additions & 0 deletions src/doc/src/reference/registries.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ explaining the format of the entry.
// The `links` string value from the package's manifest, or null if not
// specified. This field is optional and defaults to null.
"links": null,
// This optional field specifies the download link for this package
// only, overriding the global `dl` link declared in the registry's
// `config.toml`. The `{crate}` markers et al. are not interpolated
// in this context.
"dl": "https://crates.io/api/v1/crates/foo/0.1.0/download"
// An unsigned 32-bit integer value indicating the schema version of this
// entry.
//
Expand Down
Loading