From b1d11d92b5b2e6f416cdd18333926f810ef08286 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 13 Apr 2017 08:59:00 -0700 Subject: [PATCH] Allow rustup to handle unavailable packages 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. --- src/rustup-dist/src/manifest.rs | 60 ++++++++++++++++++++-------- src/rustup-dist/src/manifestation.rs | 10 +++-- src/rustup/toolchain.rs | 4 +- tests/cli-v2.rs | 2 +- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/rustup-dist/src/manifest.rs b/src/rustup-dist/src/manifest.rs index 0ad8579925e..e77a6b6faea 100644 --- a/src/rustup-dist/src/manifest.rs +++ b/src/rustup-dist/src/manifest.rs @@ -41,13 +41,17 @@ pub enum PackageTargets { #[derive(Clone, Debug, PartialEq)] pub struct TargetedPackage { - pub available: bool, + pub bins: Option, + pub components: Vec, + pub extensions: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct PackageBins { pub url: String, pub hash: String, pub xz_url: Option, pub xz_hash: Option, - pub components: Vec, - pub extensions: Vec, } #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] @@ -232,17 +236,27 @@ impl TargetedPackage { pub fn from_toml(mut table: toml::Table, path: &str) -> Result { 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); @@ -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> { let mut result = Vec::new(); diff --git a/src/rustup-dist/src/manifestation.rs b/src/rustup-dist/src/manifestation.rs index 0fa581b1c44..c6a34edd6fb 100644 --- a/src/rustup-dist/src/manifestation.rs +++ b/src/rustup-dist/src/manifestation.rs @@ -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() { @@ -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); } diff --git a/src/rustup/toolchain.rs b/src/rustup/toolchain.rs index acc7810eb70..6c19862605a 100644 --- a/src/rustup/toolchain.rs +++ b/src/rustup/toolchain.rs @@ -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(), }); } @@ -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(), }); } diff --git a/tests/cli-v2.rs b/tests/cli-v2.rs index 38aa04f8d64..f5b1422f3f2 100644 --- a/tests/cli-v2.rs +++ b/tests/cli-v2.rs @@ -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();