Skip to content

Commit e335135

Browse files
authored
Support additional registries (#942)
1 parent 8d7a3c0 commit e335135

File tree

11 files changed

+274
-70
lines changed

11 files changed

+274
-70
lines changed

crate_universe/defs.bzl

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ load("//rust:defs.bzl", "rust_common")
66
load("//rust:repositories.bzl", "DEFAULT_TOOLCHAIN_TRIPLES")
77
load("//rust/platform:triple_mappings.bzl", "system_to_binary_ext", "triple_to_system")
88

9-
DEFAULT_CRATE_REGISTRY_TEMPLATE = "https://crates.io/api/v1/crates/{crate}/{version}/download"
9+
# The default template for download URLs from the default registry (i.e. crates.io).
10+
DEFAULT_DEFAULT_CRATE_DOWNLOAD_URL_TEMPLATE = "https://crates.io/api/v1/crates/{crate}/{version}/download"
1011

11-
def _input_content_template(ctx, name, packages, cargo_toml_files, overrides, registry_template, targets, cargo_bin_path):
12+
def _input_content_template(ctx, name, packages, cargo_toml_files, overrides, default_registry_download_url_template, additional_registries, targets, cargo_bin_path):
1213
"""Generate json encoded dependency info for the crate resolver.
1314
1415
Args:
@@ -17,7 +18,8 @@ def _input_content_template(ctx, name, packages, cargo_toml_files, overrides, re
1718
packages (list): A list of json encoded `crate.spec` entries.
1819
cargo_toml_files (list): A list of `Label`s to Cargo manifests.
1920
overrides (dict): A dict of crate name (`str`) to json encoded `crate.override` data.
20-
registry_template (str): A crate registry url template
21+
default_registry_download_url_template (str): The URL template for downloading crates from the default registry.
22+
additional_registries (dict): Dict of registry name (`str`) to the URL of the index (`str`).
2123
targets (list): A list of target platform triples
2224
cargo_bin_path (path): The label of a Cargo binary.
2325
@@ -43,9 +45,10 @@ def _input_content_template(ctx, name, packages, cargo_toml_files, overrides, re
4345
return "{}\n".format(
4446
json.encode_indent(
4547
struct(
48+
additional_registries = additional_registries,
4649
cargo = str(cargo_bin_path),
4750
cargo_toml_files = encodable_cargo_toml_files,
48-
crate_registry_template = registry_template,
51+
default_registry_download_url_template = default_registry_download_url_template,
4952
overrides = encodable_overrides,
5053
packages = dcoded_pkgs,
5154
repository_name = name,
@@ -104,7 +107,8 @@ def _crate_universe_resolve_impl(repository_ctx):
104107
packages = repository_ctx.attr.packages,
105108
cargo_toml_files = repository_ctx.attr.cargo_toml_files,
106109
overrides = repository_ctx.attr.overrides,
107-
registry_template = repository_ctx.attr.crate_registry_template,
110+
default_registry_download_url_template = repository_ctx.attr.default_registry_download_url_template,
111+
additional_registries = repository_ctx.attr.additional_registries,
108112
targets = repository_ctx.attr.supported_targets,
109113
cargo_bin_path = tools.cargo,
110114
)
@@ -159,13 +163,20 @@ Environment Variables:
159163
""",
160164
implementation = _crate_universe_resolve_impl,
161165
attrs = {
166+
"additional_registries": attr.string_dict(
167+
doc = """\
168+
Additional registries used by Cargo (see https://doc.rust-lang.org/cargo/reference/registries.html).
169+
170+
Dict of registry_name: index_url.
171+
""",
172+
),
162173
"cargo_toml_files": attr.label_list(
163174
doc = "A list of Cargo manifests (`Cargo.toml` files).",
164175
allow_files = True,
165176
),
166-
"crate_registry_template": attr.string(
177+
"default_registry_download_url_template": attr.string(
167178
doc = "A template for where to download crates from for the default crate registry. This must contain `{version}` and `{crate}` templates.",
168-
default = DEFAULT_CRATE_REGISTRY_TEMPLATE,
179+
default = DEFAULT_DEFAULT_CRATE_DOWNLOAD_URL_TEMPLATE,
169180
),
170181
"iso_date": attr.string(
171182
doc = "The iso_date of cargo binary the resolver should use. Note: This can only be set if `version` is `beta` or `nightly`",

crate_universe/src/config.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,32 @@ pub struct Config {
5252
pub cargo_toml_files: BTreeMap<String, PathBuf>,
5353
pub overrides: HashMap<String, Override>,
5454

55-
/// Template of the URL from which to download crates, which are assumed to be gzip'd tar files.
56-
/// This string may contain arbitrarily many instances of {crate} and {version} which will be
57-
/// replaced by crate names and versions.
58-
pub crate_registry_template: String,
59-
6055
pub target_triples: BTreeSet<String>,
56+
6157
pub cargo: PathBuf,
6258

6359
#[serde(default = "default_rules_rust_workspace_name")]
6460
pub rust_rules_workspace_name: String,
65-
#[serde(default = "default_index_url")]
66-
pub index_url: Url,
61+
62+
#[serde(default = "default_default_registry_index_url")]
63+
pub default_registry_index_url: Url,
64+
/// Template of the URL from which to download crates, which are assumed to be gzip'd tar files.
65+
/// This string may contain arbitrarily many instances of {crate} and {version} which will be
66+
/// replaced by crate names and versions.
67+
#[serde(default = "default_default_registry_download_url_template")]
68+
pub default_registry_download_url_template: String,
69+
70+
pub additional_registries: BTreeMap<String, Url>,
6771
}
6872

6973
impl Config {
7074
pub fn preprocess(mut self) -> anyhow::Result<Resolver> {
7175
self.packages.sort();
7276

77+
let known_registries: BTreeSet<_> = self.additional_registries.keys().cloned().collect();
78+
7379
let (toml_contents, label_to_crates) =
74-
merge_cargo_tomls(self.cargo_toml_files, self.packages)?;
80+
merge_cargo_tomls(&known_registries, self.cargo_toml_files, self.packages)?;
7581

7682
let overrides = self
7783
.overrides
@@ -97,12 +103,13 @@ impl Config {
97103
toml_contents.into(),
98104
ResolverConfig {
99105
cargo: self.cargo,
100-
index_url: self.index_url,
106+
default_registry_index_url: self.default_registry_index_url,
107+
default_registry_download_url_template: self.default_registry_download_url_template,
108+
additional_registries: self.additional_registries,
101109
},
102110
ConsolidatorConfig { overrides },
103111
RenderConfig {
104112
repo_rule_name: self.repository_name.clone(),
105-
crate_registry_template: self.crate_registry_template.clone(),
106113
rules_rust_workspace_name: self.rust_rules_workspace_name.clone(),
107114
},
108115
self.target_triples,
@@ -138,6 +145,10 @@ pub fn default_rules_rust_workspace_name() -> String {
138145
String::from("rules_rust")
139146
}
140147

141-
pub fn default_index_url() -> Url {
148+
fn default_default_registry_index_url() -> Url {
142149
Url::parse("https://github.com/rust-lang/crates.io-index").expect("Invalid default index URL")
143150
}
151+
152+
fn default_default_registry_download_url_template() -> String {
153+
String::from("https://crates.io/api/v1/crates/{crate}/{version}/download")
154+
}

crate_universe/src/parser.rs

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ pub struct DepSpec {
5050

5151
#[derive(Debug, PartialEq, Eq)]
5252
pub enum VersionSpec {
53-
Semver(VersionReq),
53+
Semver {
54+
version_req: VersionReq,
55+
registry: Option<String>,
56+
},
5457
Git {
5558
url: String,
5659
rev: Option<String>,
@@ -83,6 +86,7 @@ struct Ignored {
8386
}
8487

8588
pub fn merge_cargo_tomls(
89+
known_registry_names: &BTreeSet<String>,
8690
label_to_path: BTreeMap<String, PathBuf>,
8791
packages: Vec<AdditionalPackage>,
8892
) -> anyhow::Result<(CargoToml, BTreeMap<String, BTreeSet<String>>)> {
@@ -116,6 +120,26 @@ pub fn merge_cargo_tomls(
116120
package: _,
117121
_ignored,
118122
} = cargo_toml;
123+
for dep_spec in dependencies
124+
.values()
125+
.chain(build_dependencies.values())
126+
.chain(dev_dependencies.values())
127+
{
128+
if let VersionSpec::Semver {
129+
registry: Some(registry),
130+
..
131+
} = &dep_spec.version
132+
{
133+
if !known_registry_names.contains(registry) {
134+
anyhow::bail!(
135+
"Saw dep for unknown registry {} - known registry names: {:?}",
136+
registry,
137+
known_registry_names
138+
);
139+
}
140+
}
141+
}
142+
119143
for (dep, dep_spec) in dependencies.into_iter() {
120144
if let VersionSpec::Local(_) = dep_spec.version {
121145
// We ignore local deps.
@@ -211,12 +235,16 @@ pub fn merge_cargo_tomls(
211235
DepSpec {
212236
default_features: true,
213237
features: features.into_iter().collect(),
214-
version: VersionSpec::Semver(VersionReq::parse(&semver).with_context(|| {
215-
format!(
216-
"Failed to parse semver requirement for package {}, semver: {}",
217-
name, semver
218-
)
219-
})?),
238+
version: VersionSpec::Semver {
239+
version_req: VersionReq::parse(&semver).with_context(|| {
240+
format!(
241+
"Failed to parse semver requirement for package {}, semver: {}",
242+
name, semver
243+
)
244+
})?,
245+
// TODO: Support custom registries for additional packages
246+
registry: None,
247+
},
220248
},
221249
);
222250
}
@@ -339,8 +367,27 @@ impl DepSpec {
339367

340368
match (&mut self.version, &other.version) {
341369
(v1, v2) if v1 == v2 => {}
342-
(VersionSpec::Semver(v1), VersionSpec::Semver(v2)) => {
343-
self.version = VersionSpec::Semver(VersionReq::parse(&format!("{}, {}", v1, v2))?)
370+
(
371+
VersionSpec::Semver {
372+
version_req: v1,
373+
registry: registry1,
374+
},
375+
VersionSpec::Semver {
376+
version_req: v2,
377+
registry: registry2,
378+
},
379+
) => {
380+
if registry1 != registry2 {
381+
return Err(anyhow!(
382+
"Can't merge the same package from different registries (saw registries {:?} and {:?})",
383+
registry1,
384+
registry2,
385+
));
386+
}
387+
self.version = VersionSpec::Semver {
388+
version_req: VersionReq::parse(&format!("{}, {}", v1, v2))?,
389+
registry: registry1.clone(),
390+
};
344391
}
345392
(v1 @ VersionSpec::Git { .. }, v2 @ VersionSpec::Git { .. }) => {
346393
return Err(anyhow!(
@@ -377,11 +424,17 @@ impl DepSpec {
377424
toml::Value::Array(features.into_iter().map(toml::Value::String).collect()),
378425
);
379426
match version {
380-
VersionSpec::Semver(version) => {
427+
VersionSpec::Semver {
428+
version_req,
429+
registry,
430+
} => {
381431
v.insert(
382432
String::from("version"),
383-
toml::Value::String(format!("{}", version)),
433+
toml::Value::String(format!("{}", version_req)),
384434
);
435+
if let Some(registry) = registry {
436+
v.insert(String::from("registry"), toml::Value::String(registry));
437+
}
385438
}
386439
VersionSpec::Git { url, rev, tag } => {
387440
v.insert(String::from("git"), toml::Value::String(url));

crate_universe/src/renderer.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use crate::{config, resolver::Dependencies};
1717
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
1818
pub struct RenderConfig {
1919
pub repo_rule_name: String,
20-
pub crate_registry_template: String,
2120
pub rules_rust_workspace_name: String,
2221
}
2322

@@ -406,10 +405,6 @@ impl Renderer {
406405
context.insert("lockfile_hash", &self.context.hash);
407406
context.insert("crates", &self.context.transitive_renderable_packages);
408407
context.insert("repo_rule_name", &self.context.config.repo_rule_name);
409-
context.insert(
410-
"repository_http_template",
411-
&self.context.config.crate_registry_template,
412-
);
413408
let rendered_repository_rules = self
414409
.internal_renderer
415410
.render("templates/defs.bzl.template", &context)?;
@@ -716,9 +711,6 @@ mod tests {
716711
let renderer = Renderer::new(
717712
RenderConfig {
718713
repo_rule_name: String::from("rule_prefix"),
719-
crate_registry_template: String::from(
720-
"https://crates.io/api/v1/crates/{crate}/{version}/download",
721-
),
722714
rules_rust_workspace_name: String::from("rules_rust"),
723715
},
724716
String::from("598"),
@@ -892,9 +884,6 @@ mod tests {
892884
fn default_render_config() -> RenderConfig {
893885
RenderConfig {
894886
repo_rule_name: String::from("rule_prefix"),
895-
crate_registry_template: String::from(
896-
"https://crates.io/api/v1/crates/{crate}/{version}/download",
897-
),
898887
rules_rust_workspace_name: String::from("rules_rust"),
899888
}
900889
}

0 commit comments

Comments
 (0)