Skip to content

Commit 77a773a

Browse files
committed
Auto merge of #4836 - sfackler:dl-template, r=withoutboats
Template a registry's dl field Previously, crate files were always downloaded from `/{crate}/{version}/download`. However, if the backing crate store for a custom registry is a raw file server rather than an API endpoint that requires every file to be named `download` which is a bit weird. Now a registry's dl URL can be templated with `{crate}` and `{version}` to have more control over the resulting path. For backwards compatibility, we append the default template suffix onto the dl URL if neither of the template parameters are present for backwards compatibility. r? @alexcrichton cc @withoutboats
2 parents 576ac63 + 52f099b commit 77a773a

File tree

4 files changed

+41
-18
lines changed

4 files changed

+41
-18
lines changed

src/cargo/sources/registry/mod.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ use util::hex;
178178
use util::to_url::ToUrl;
179179

180180
const INDEX_LOCK: &'static str = ".cargo-index-lock";
181-
pub static CRATES_IO: &'static str = "https://github.com/rust-lang/crates.io-index";
181+
pub const CRATES_IO: &'static str = "https://github.com/rust-lang/crates.io-index";
182+
const CRATE_TEMPLATE: &'static str = "{crate}";
183+
const VERSION_TEMPLATE: &'static str = "{version}";
182184

183185
pub struct RegistrySource<'cfg> {
184186
source_id: SourceId,
@@ -192,9 +194,17 @@ pub struct RegistrySource<'cfg> {
192194

193195
#[derive(Deserialize)]
194196
pub struct RegistryConfig {
195-
/// Download endpoint for all crates. This will be appended with
196-
/// `/<crate>/<version>/download` and then will be hit with an HTTP GET
197-
/// request to download the tarball for a crate.
197+
/// Download endpoint for all crates.
198+
///
199+
/// The string is a template which will generate the download URL for the
200+
/// tarball of a specific version of a crate. The substrings `{crate}` and
201+
/// `{version}` will be replaced with the crate's name and version
202+
/// respectively.
203+
///
204+
/// For backwards compatibility, if the string does not contain `{crate}` or
205+
/// `{version}`, it will be extended with `/{crate}/{version}/download` to
206+
/// support registries like crates.io which were crated before the
207+
/// templating setup was created.
198208
pub dl: String,
199209

200210
/// API endpoint for the registry. This is what's actually hit to perform

src/cargo/sources/registry/remote.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::cell::{RefCell, Ref, Cell};
2+
use std::fmt::Write as FmtWrite;
23
use std::io::SeekFrom;
34
use std::io::prelude::*;
45
use std::mem;
@@ -11,7 +12,7 @@ use serde_json;
1112

1213
use core::{PackageId, SourceId};
1314
use sources::git;
14-
use sources::registry::{RegistryData, RegistryConfig, INDEX_LOCK};
15+
use sources::registry::{RegistryData, RegistryConfig, INDEX_LOCK, CRATE_TEMPLATE, VERSION_TEMPLATE};
1516
use util::network;
1617
use util::{FileLock, Filesystem, LazyCell};
1718
use util::{Config, Sha256, ToUrl, Progress};
@@ -203,11 +204,14 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
203204
self.config.shell().status("Downloading", pkg)?;
204205

205206
let config = self.config()?.unwrap();
206-
let mut url = config.dl.to_url()?;
207-
url.path_segments_mut().unwrap()
208-
.push(pkg.name())
209-
.push(&pkg.version().to_string())
210-
.push("download");
207+
let mut url = config.dl.clone();
208+
if !url.contains(CRATE_TEMPLATE) && !url.contains(VERSION_TEMPLATE) {
209+
write!(url, "/{}/{}/download", CRATE_TEMPLATE, VERSION_TEMPLATE).unwrap();
210+
}
211+
let url = url
212+
.replace(CRATE_TEMPLATE, pkg.name())
213+
.replace(VERSION_TEMPLATE, &pkg.version().to_string())
214+
.to_url()?;
211215

212216
// TODO: don't download into memory, but ensure that if we ctrl-c a
213217
// download we should resume either from the start or the middle

tests/alt-registry.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ extern crate cargotest;
22
extern crate hamcrest;
33

44
use cargotest::ChannelChanger;
5-
use cargotest::support::registry::{self, Package, alt_dl_path};
5+
use cargotest::support::registry::{self, Package, alt_api_path};
66
use cargotest::support::{project, execs};
77
use hamcrest::assert_that;
88

@@ -374,7 +374,7 @@ fn publish_to_alt_registry() {
374374
execs().with_status(0));
375375

376376
// Ensure that the crate is uploaded
377-
assert!(alt_dl_path().join("api/v1/crates/new").exists());
377+
assert!(alt_api_path().join("api/v1/crates/new").exists());
378378
}
379379

380380
#[test]

tests/cargotest/support/registry.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ pub fn dl_url() -> Url { Url::from_file_path(&*dl_path()).ok().unwrap() }
2121
pub fn alt_registry_path() -> PathBuf { paths::root().join("alternative-registry") }
2222
pub fn alt_registry() -> Url { Url::from_file_path(&*alt_registry_path()).ok().unwrap() }
2323
pub fn alt_dl_path() -> PathBuf { paths::root().join("alt_dl") }
24-
pub fn alt_dl_url() -> Url { Url::from_file_path(&*alt_dl_path()).ok().unwrap() }
24+
pub fn alt_dl_url() -> String {
25+
let base = Url::from_file_path(&*alt_dl_path()).ok().unwrap();
26+
format!("{}/{{crate}}/{{version}}/{{crate}}-{{version}}.crate", base)
27+
}
28+
pub fn alt_api_path() -> PathBuf { paths::root().join("alt_api") }
29+
pub fn alt_api_url() -> Url { Url::from_file_path(&*alt_api_path()).ok().unwrap() }
2530

2631
pub struct Package {
2732
name: String,
@@ -76,10 +81,10 @@ pub fn init() {
7681
// Init an alt registry
7782
repo(&alt_registry_path())
7883
.file("config.json", &format!(r#"
79-
{{"dl":"{0}","api":"{0}"}}
80-
"#, alt_dl_url()))
84+
{{"dl":"{}","api":"{}"}}
85+
"#, alt_dl_url(), alt_api_url()))
8186
.build();
82-
fs::create_dir_all(alt_dl_path().join("api/v1/crates")).unwrap();
87+
fs::create_dir_all(alt_api_path().join("api/v1/crates")).unwrap();
8388
}
8489

8590
impl Package {
@@ -300,9 +305,13 @@ impl Package {
300305
if self.local {
301306
registry_path().join(format!("{}-{}.crate", self.name,
302307
self.vers))
308+
} else if self.alternative {
309+
alt_dl_path()
310+
.join(&self.name)
311+
.join(&self.vers)
312+
.join(&format!("{}-{}.crate", self.name, self.vers))
303313
} else {
304-
let dl_path = if self.alternative { alt_dl_path() } else { dl_path() };
305-
dl_path.join(&self.name).join(&self.vers).join("download")
314+
dl_path().join(&self.name).join(&self.vers).join("download")
306315
}
307316
}
308317
}

0 commit comments

Comments
 (0)