Skip to content

Commit

Permalink
Allow rustup to handle unavailable packages
Browse files Browse the repository at this point in the history
Before this, if a package was unavailable (like nightly is at the moment),
it would error out with a message like "error: missing key: 'url'" because
at the moment a few of the rust-analysis packages didn't build. This resulted
in the `channel-rust-nightly.toml` to be created with blocks like this:

```toml
[pkg.rust-analysis.target.aarch64-apple-ios]
available = false

[pkg.rust-analysis.target.aarch64-linux-android]
available = false

[pkg.rust-analysis.target.aarch64-unknown-fuchsia]
available = false

[pkg.rust-analysis.target.aarch64-unknown-linux-gnu]
available = true
hash = "be50ffa6f94770929b53bae553977cb6d78b03506f033d14a7251c7b0cdb9035"
url = "https://static.rust-lang.org/dist/2017-04-13/rust-analysis-nightly-aarch64-unknown-linux-gnu.tar.gz"
```

rustup assumed that there'd always be a `hash` and `url`, which is not
the case when packages are unavaible. This patch then just updates
rustup to handle their absence.
  • Loading branch information
erickt authored and brson committed Jun 22, 2017
1 parent 2d8e6c0 commit ea39fe0
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 28 deletions.
60 changes: 43 additions & 17 deletions src/rustup-dist/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,17 @@ pub enum PackageTargets {

#[derive(Clone, Debug, PartialEq)]
pub struct TargetedPackage {
pub available: bool,
pub bins: Option<PackageBins>,
pub components: Vec<Component>,
pub extensions: Vec<Component>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct PackageBins {
pub url: String,
pub hash: String,
pub xz_url: Option<String>,
pub xz_hash: Option<String>,
pub components: Vec<Component>,
pub extensions: Vec<Component>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
Expand Down Expand Up @@ -232,17 +236,27 @@ impl TargetedPackage {
pub fn from_toml(mut table: toml::Table, path: &str) -> Result<Self> {
let components = try!(get_array(&mut table, "components", path));
let extensions = try!(get_array(&mut table, "extensions", path));
Ok(TargetedPackage {
available: try!(get_bool(&mut table, "available", path)),
url: try!(get_string(&mut table, "url", path)),
hash: try!(get_string(&mut table, "hash", path)),
xz_url: get_string(&mut table, "xz_url", path).ok(),
xz_hash: get_string(&mut table, "xz_hash", path).ok(),
components: try!(Self::toml_to_components(components,
&format!("{}{}.", path, "components"))),
extensions: try!(Self::toml_to_components(extensions,
&format!("{}{}.", path, "extensions"))),
})

if try!(get_bool(&mut table, "available", path)) {
Ok(TargetedPackage {
bins: Some(PackageBins {
url: try!(get_string(&mut table, "url", path)),
hash: try!(get_string(&mut table, "hash", path)),
xz_url: get_string(&mut table, "xz_url", path).ok(),
xz_hash: get_string(&mut table, "xz_hash", path).ok(),
}),
components: try!(Self::toml_to_components(components,
&format!("{}{}.", path, "components"))),
extensions: try!(Self::toml_to_components(extensions,
&format!("{}{}.", path, "extensions"))),
})
} else {
Ok(TargetedPackage {
bins: None,
components: vec![],
extensions: vec![],
})
}
}
pub fn to_toml(self) -> toml::Table {
let extensions = Self::components_to_toml(self.extensions);
Expand All @@ -254,12 +268,24 @@ impl TargetedPackage {
if !components.is_empty() {
result.insert("components".to_owned(), toml::Value::Array(components));
}
result.insert("hash".to_owned(), toml::Value::String(self.hash));
result.insert("url".to_owned(), toml::Value::String(self.url));
result.insert("available".to_owned(), toml::Value::Boolean(self.available));
if let Some(bins) = self.bins.clone() {
result.insert("hash".to_owned(), toml::Value::String(bins.hash));
result.insert("url".to_owned(), toml::Value::String(bins.url));
if let (Some(xz_hash), Some(xz_url)) = (bins.xz_hash, bins.xz_url) {
result.insert("xz_hash".to_owned(), toml::Value::String(xz_hash));
result.insert("xz_url".to_owned(), toml::Value::String(xz_url));
}
result.insert("available".to_owned(), toml::Value::Boolean(true));
} else {
result.insert("available".to_owned(), toml::Value::Boolean(false));
}
result
}

pub fn available(&self) -> bool {
self.bins.is_some()
}

fn toml_to_components(arr: toml::Array, path: &str) -> Result<Vec<Component>> {
let mut result = Vec::new();

Expand Down
10 changes: 6 additions & 4 deletions src/rustup-dist/src/manifestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl Manifestation {
use manifest::*;
let pkg: Option<&Package> = new_manifest.get_package(&c.pkg).ok();
let target_pkg: Option<&TargetedPackage> = pkg.and_then(|p| p.get_target(c.target.as_ref()).ok());
target_pkg.map(|tp| tp.available) != Some(true)
target_pkg.map(|tp| tp.available()) != Some(true)
}).cloned().collect();

if !unavailable_components.is_empty() {
Expand All @@ -124,12 +124,14 @@ impl Manifestation {
for component in components_to_install {
let package = try!(new_manifest.get_package(&component.pkg));
let target_package = try!(package.get_target(component.target.as_ref()));

let bins = target_package.bins.as_ref().expect("components available");
let c_u_h =
if let (Some(url), Some(hash)) = (target_package.xz_url.clone(),
target_package.xz_hash.clone()) {
if let (Some(url), Some(hash)) = (bins.xz_url.clone(),
bins.xz_hash.clone()) {
(component, Format::Xz, url, hash)
} else {
(component, Format::Gz, target_package.url.clone(), target_package.hash.clone())
(component, Format::Gz, bins.url.clone(), bins.hash.clone())
};
components_urls_and_hashes.push(c_u_h);
}
Expand Down
8 changes: 4 additions & 4 deletions src/rustup-dist/tests/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ fn parse_smoke_test() {
assert!(rust_pkg.version.contains("1.3.0"));

let rust_target_pkg = rust_pkg.get_target(Some(&x86_64_unknown_linux_gnu)).unwrap();
assert_eq!(rust_target_pkg.available, true);
assert_eq!(rust_target_pkg.url, "example.com");
assert_eq!(rust_target_pkg.hash, "...");
assert_eq!(rust_target_pkg.available(), true);
assert_eq!(rust_target_pkg.bins.clone().unwrap().url, "example.com");
assert_eq!(rust_target_pkg.bins.clone().unwrap().hash, "...");

let ref component = rust_target_pkg.components[0];
assert_eq!(component.pkg, "rustc");
Expand All @@ -40,7 +40,7 @@ fn parse_smoke_test() {

let docs_pkg = pkg.get_package("rust-docs").unwrap();
let docs_target_pkg = docs_pkg.get_target(Some(&x86_64_unknown_linux_gnu)).unwrap();
assert_eq!(docs_target_pkg.url, "example.com");
assert_eq!(docs_target_pkg.bins.clone().unwrap().url, "example.com");
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions src/rustup/toolchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ impl<'a> Toolchain<'a> {
component: component.clone(),
required: true,
installed: installed,
available: component_target_pkg.available,
available: component_target_pkg.available(),
});
}

Expand All @@ -510,7 +510,7 @@ impl<'a> Toolchain<'a> {
component: extension.clone(),
required: false,
installed: installed,
available: extension_target_pkg.available,
available: extension_target_pkg.available(),
});
}

Expand Down
2 changes: 1 addition & 1 deletion tests/cli-v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ fn make_component_unavailable(config: &Config, name: &str, target: &TargetTriple
{
let mut std_pkg = manifest.packages.get_mut(name).unwrap();
let mut target_pkg = std_pkg.targets.get_mut(target).unwrap();
target_pkg.available = false;
target_pkg.bins = None;
}
let ref manifest_str = manifest.stringify();
rustup_utils::raw::write_file(manifest_path, manifest_str).unwrap();
Expand Down

0 comments on commit ea39fe0

Please sign in to comment.