diff --git a/Cargo.lock b/Cargo.lock index a111947..09ec5c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -240,7 +240,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "elan" -version = "0.1.0" +version = "0.2.1" dependencies = [ "clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)", "download 0.4.0", diff --git a/Cargo.toml b/Cargo.toml index d274501..441d100 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "elan" -version = "0.2.0" +version = "0.2.1" authors = [ "Sebastian Ullrich " ] description = "Manage multiple rust installations with ease" diff --git a/src/elan-dist/src/dist.rs b/src/elan-dist/src/dist.rs index 3ce921a..bd8a3f1 100644 --- a/src/elan-dist/src/dist.rs +++ b/src/elan-dist/src/dist.rs @@ -13,6 +13,7 @@ use std::env; use json; use regex::Regex; +use sha2::{Sha256, Digest}; pub const DEFAULT_DIST_SERVER: &'static str = "https://static.lean-lang.org"; @@ -510,12 +511,33 @@ pub fn update_from_dist_<'a>(download: DownloadCfg<'a>, }); } }; + + let mut hasher = Sha256::new(); + for url in &manifest { + hasher.input(url.as_bytes()); + } + let hash = format!("{:x}", hasher.result()); + let partial_hash = &hash[0..20]; + + if let Some(hash_file) = update_hash { + if utils::is_file(hash_file) { + if let Ok(contents) = utils::read_file("update hash", hash_file) { + if contents == partial_hash { + // Skip download, update hash matches + return Ok(None); + } + } /*else { + (self.notify_handler)(Notification::CantReadUpdateHash(hash_file)); + }*/ + } /*else { + (self.notify_handler)(Notification::NoUpdateHash(hash_file)); + }*/ + } + match manifestation.update_v1(&manifest, - update_hash, &download.temp_cfg, download.notify_handler.clone()) { - Ok(None) => Ok(None), - Ok(Some(hash)) => Ok(Some(hash)), + Ok(()) => Ok(()), e @ Err(Error(ErrorKind::Utils(elan_utils::ErrorKind::DownloadNotExists { .. }), _)) => { e.chain_err(|| { format!("could not download nonexistent lean version `{}`", @@ -523,13 +545,12 @@ pub fn update_from_dist_<'a>(download: DownloadCfg<'a>, }) } Err(e) => Err(e), - } + }.map(|()| Some(partial_hash.to_string())) } fn dl_v1_manifest<'a>(download: DownloadCfg<'a>, toolchain: &ToolchainDesc) -> Result> { let manifest_url = toolchain.manifest_v1_url(download.dist_root); - let manifest_dl = try!(download.download_and_check(&manifest_url, None, "")); - let (manifest_file, _) = manifest_dl.unwrap(); + let manifest_file = try!(download.download_and_check(&manifest_url, "")); let manifest_str = try!(utils::read_file("manifest", &manifest_file)); let mut man_json = json::parse(&manifest_str).expect("failed to parse manifest"); if toolchain.channel == "nightly" && toolchain.date.is_none() { diff --git a/src/elan-dist/src/download.rs b/src/elan-dist/src/download.rs index cc16092..7be250f 100644 --- a/src/elan-dist/src/download.rs +++ b/src/elan-dist/src/download.rs @@ -100,70 +100,19 @@ impl<'a> DownloadCfg<'a> { Ok(()) } - fn _download_hash(&self, url: &str) -> Result { - let hash_url = try!(utils::parse_url(&(url.to_owned() + ".sha256"))); - let hash_file = try!(self.temp_cfg.new_file()); - - try!(utils::download_file(&hash_url, - &hash_file, - None, - &|n| (self.notify_handler)(n.into()))); - - Ok(try!(utils::read_file("hash", &hash_file).map(|s| s[0..64].to_owned()))) - } - - /// Downloads a file, sourcing its hash from the same url with a `.sha256` suffix. - /// If `update_hash` is present, then that will be compared to the downloaded hash, - /// and if they match, the download is skipped. pub fn download_and_check(&self, url_str: &str, - _update_hash: Option<&Path>, ext: &str) - -> Result, String)>> { - /*let hash = try!(self.download_hash(url_str)); - /let partial_hash: String = hash.chars().take(UPDATE_HASH_LEN).collect(); - - if let Some(hash_file) = update_hash { - - if utils::is_file(hash_file) { - if let Ok(contents) = utils::read_file("update hash", hash_file) { - if contents == partial_hash { - // Skip download, update hash matches - return Ok(None); - } - } else { - (self.notify_handler)(Notification::CantReadUpdateHash(hash_file)); - } - } else { - (self.notify_handler)(Notification::NoUpdateHash(hash_file)); - } - }*/ - + -> Result> { let url = try!(utils::parse_url(url_str)); let file = try!(self.temp_cfg.new_file_with_ext("", ext)); - let mut hasher = Sha256::new(); try!(utils::download_file(&url, &file, - Some(&mut hasher), + None, &|n| (self.notify_handler)(n.into()))); - let actual_hash = format!("{:x}", hasher.result()); - - /*if hash != actual_hash { - // Incorrect hash - return Err(ErrorKind::ChecksumFailed { - url: url_str.to_owned(), - expected: hash, - calculated: actual_hash, - } - .into()); - } else { - (self.notify_handler)(Notification::ChecksumValid(url_str)); - }*/ - - // TODO: Check the signature of the file - Ok(Some((file, actual_hash))) + Ok(file) } } diff --git a/src/elan-dist/src/manifestation.rs b/src/elan-dist/src/manifestation.rs index e21d1e9..500478c 100644 --- a/src/elan-dist/src/manifestation.rs +++ b/src/elan-dist/src/manifestation.rs @@ -11,7 +11,6 @@ use notifications::*; use elan_utils::utils; use download::{DownloadCfg, File}; use prefix::InstallPrefix; -use std::path::Path; pub const DIST_MANIFEST: &'static str = "multilean-channel-manifest.toml"; pub const CONFIG_FILE: &'static str = "multilean-config.toml"; @@ -303,9 +302,8 @@ impl Manifestation { /// Installation using the legacy v1 manifest format pub fn update_v1(&self, new_manifest: &[String], - update_hash: Option<&Path>, temp_cfg: &temp::Cfg, - notify_handler: &Fn(Notification)) -> Result> { + notify_handler: &Fn(Notification)) -> Result<()> { let informal_target = match self.target_triple.0.as_str() { "x86_64-unknown-linux-gnu" => Some("linux"), "x86_64-apple-darwin" => Some("darwin"), @@ -334,11 +332,7 @@ impl Manifestation { notify_handler: notify_handler }; - let dl = try!(dlcfg.download_and_check(&url, update_hash, ".tar.gz")); - if dl.is_none() { - return Ok(None); - }; - let (installer_file, installer_hash) = dl.unwrap(); + let installer_file = try!(dlcfg.download_and_check(&url, ".tar.gz")); let prefix = self.installation.prefix(); @@ -366,7 +360,7 @@ impl Manifestation { // End transaction tx.commit(); - Ok(Some(installer_hash)) + Ok(()) } // If the previous installation was from a v1 manifest, then it