diff --git a/Cargo.lock b/Cargo.lock index 7b008bb73a..154da94e64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -343,6 +343,16 @@ name = "log" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lzma-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "markdown" version = "0.2.0" @@ -593,6 +603,7 @@ dependencies = [ "walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -613,6 +624,7 @@ dependencies = [ "walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -980,6 +992,14 @@ dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "xz2" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lzma-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "307c92332867e586720c0222ee9d890bbe8431711efed8a1b06bc5b40fc66bd7" "checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a" @@ -1018,6 +1038,7 @@ dependencies = [ "checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" "checksum libz-sys 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c18b5826abbfafb0160b37e1991e2d327c1fe38c955e496ea306f72c06d7570c" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" +"checksum lzma-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4b539821e4cb7d38539f762580c6620c745fb79d9a03b4bf25eda6739c4ff572" "checksum markdown 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb7e864aa1dccbebb05751e899bc84c639df47490c0c24caf4b1a77770b6566" "checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" @@ -1085,3 +1106,4 @@ dependencies = [ "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winreg 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e63857fb213f619b4c4fff86b158285c76766aac7e7474967e92fb6dbbfeefe9" "checksum xattr 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "06d6f0e8fd6536f3c623afab15488d87cf3a5dbb907361a22c05d739881136d7" +"checksum xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e9510bdf100731599107c61f77daf46713a69a568f75458999c1f9dbf6ba25b0" diff --git a/src/rustup-dist/Cargo.toml b/src/rustup-dist/Cargo.toml index f7b8d802cb..9cfea72b8b 100644 --- a/src/rustup-dist/Cargo.toml +++ b/src/rustup-dist/Cargo.toml @@ -19,6 +19,7 @@ ole32-sys = "0.2.0" url = "1.1.0" tar = "0.4.0" flate2 = "0.2.9" +xz2 = "0.1.3" tempdir = "0.3.4" walkdir = "0.1.5" toml = "0.1.27" diff --git a/src/rustup-dist/src/component/package.rs b/src/rustup-dist/src/component/package.rs index e03b8d2c41..3326231ab0 100644 --- a/src/rustup-dist/src/component/package.rs +++ b/src/rustup-dist/src/component/package.rs @@ -4,6 +4,7 @@ extern crate tar; extern crate flate2; +extern crate xz2; use component::components::*; use component::transaction::*; @@ -261,3 +262,35 @@ impl<'a> Package for TarGzPackage<'a> { self.0.components() } } + +#[derive(Debug)] +pub struct TarXzPackage<'a>(TarPackage<'a>); + +impl<'a> TarXzPackage<'a> { + pub fn new(stream: R, temp_cfg: &'a temp::Cfg) -> Result { + let stream = xz2::read::XzDecoder::new(stream); + + Ok(TarXzPackage(try!(TarPackage::new(stream, temp_cfg)))) + } + pub fn new_file(path: &Path, temp_cfg: &'a temp::Cfg) -> Result { + let file = try!(File::open(path).chain_err(|| ErrorKind::ExtractingPackage)); + Self::new(file, temp_cfg) + } +} + +impl<'a> Package for TarXzPackage<'a> { + fn contains(&self, component: &str, short_name: Option<&str>) -> bool { + self.0.contains(component, short_name) + } + fn install<'b>(&self, + target: &Components, + component: &str, + short_name: Option<&str>, + tx: Transaction<'b>) + -> Result> { + self.0.install(target, component, short_name, tx) + } + fn components(&self) -> Vec { + self.0.components() + } +} diff --git a/src/rustup-dist/src/manifest.rs b/src/rustup-dist/src/manifest.rs index 5fc5404fac..9953ef3239 100644 --- a/src/rustup-dist/src/manifest.rs +++ b/src/rustup-dist/src/manifest.rs @@ -44,6 +44,8 @@ pub struct TargetedPackage { pub available: bool, pub url: String, pub hash: String, + pub xz_url: Option, + pub xz_hash: Option, pub components: Vec, pub extensions: Vec, } @@ -230,6 +232,8 @@ impl 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, diff --git a/src/rustup-dist/src/manifestation.rs b/src/rustup-dist/src/manifestation.rs index 208df01181..0fa581b1c4 100644 --- a/src/rustup-dist/src/manifestation.rs +++ b/src/rustup-dist/src/manifestation.rs @@ -4,7 +4,7 @@ use config::Config; use manifest::{Component, Manifest, TargetedPackage}; use dist::{TargetTriple, DEFAULT_DIST_SERVER}; -use component::{Components, Transaction, TarGzPackage, Package}; +use component::{Components, Transaction, TarGzPackage, TarXzPackage, Package}; use temp; use errors::*; use notifications::*; @@ -16,6 +16,11 @@ use std::path::Path; pub const DIST_MANIFEST: &'static str = "multirust-channel-manifest.toml"; pub const CONFIG_FILE: &'static str = "multirust-config.toml"; +enum Format { + Gz, + Xz, +} + #[derive(Debug)] pub struct Manifestation { installation: Components, @@ -115,20 +120,26 @@ impl Manifestation { } // Map components to urls and hashes - let mut components_urls_and_hashes: Vec<(Component, String, String)> = Vec::new(); + let mut components_urls_and_hashes: Vec<(Component, Format, String, String)> = Vec::new(); 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 c_u_h = (component, target_package.url.clone(), target_package.hash.clone()); + let c_u_h = + if let (Some(url), Some(hash)) = (target_package.xz_url.clone(), + target_package.xz_hash.clone()) { + (component, Format::Xz, url, hash) + } else { + (component, Format::Gz, target_package.url.clone(), target_package.hash.clone()) + }; components_urls_and_hashes.push(c_u_h); } let altered = temp_cfg.dist_server != DEFAULT_DIST_SERVER; // Download component packages and validate hashes - let mut things_to_install: Vec<(Component, File)> = Vec::new(); + let mut things_to_install: Vec<(Component, Format, File)> = Vec::new(); let mut things_downloaded: Vec = Vec::new(); - for (component, url, hash) in components_urls_and_hashes { + for (component, format, url, hash) in components_urls_and_hashes { notify_handler(Notification::DownloadingComponent(&component.pkg, &self.target_triple, @@ -146,7 +157,7 @@ impl Manifestation { })); things_downloaded.push(hash); - things_to_install.push((component, dowloaded_file)); + things_to_install.push((component, format, dowloaded_file)); } // Begin transaction @@ -167,13 +178,24 @@ impl Manifestation { } // Install components - for (component, installer_file) in things_to_install { + for (component, format, installer_file) in things_to_install { notify_handler(Notification::InstallingComponent(&component.pkg, &self.target_triple, component.target.as_ref())); - let package = try!(TarGzPackage::new_file(&installer_file, temp_cfg)); + let gz; + let xz; + let package: &Package = match format { + Format::Gz => { + gz = try!(TarGzPackage::new_file(&installer_file, temp_cfg)); + &gz + } + Format::Xz => { + xz = try!(TarXzPackage::new_file(&installer_file, temp_cfg)); + &xz + } + }; // For historical reasons, the rust-installer component // names are not the same as the dist manifest component diff --git a/src/rustup-dist/tests/dist.rs b/src/rustup-dist/tests/dist.rs index 39c210f504..2e42432703 100644 --- a/src/rustup-dist/tests/dist.rs +++ b/src/rustup-dist/tests/dist.rs @@ -246,7 +246,7 @@ fn mock_dist_server_smoke_test() { let tempdir = TempDir::new("multirust").unwrap(); let path = tempdir.path(); - create_mock_dist_server(&path, None).write(&[ManifestVersion::V2]); + create_mock_dist_server(&path, None).write(&[ManifestVersion::V2], false); assert!(utils::path_exists(path.join("dist/2016-02-01/rustc-nightly-x86_64-apple-darwin.tar.gz"))); assert!(utils::path_exists(path.join("dist/2016-02-01/rustc-nightly-i686-apple-darwin.tar.gz"))); @@ -307,10 +307,10 @@ fn uninstall(toolchain: &ToolchainDesc, prefix: &InstallPrefix, temp_cfg: &temp: Ok(()) } -fn setup(edit: Option<&Fn(&str, &mut MockPackage)>, +fn setup(edit: Option<&Fn(&str, &mut MockPackage)>, enable_xz: bool, f: &Fn(&Url, &ToolchainDesc, &InstallPrefix, &DownloadCfg, &temp::Cfg)) { let dist_tempdir = TempDir::new("multirust").unwrap(); - create_mock_dist_server(dist_tempdir.path(), edit).write(&[ManifestVersion::V2]); + create_mock_dist_server(dist_tempdir.path(), edit).write(&[ManifestVersion::V2], enable_xz); let prefix_tempdir = TempDir::new("multirust").unwrap(); @@ -334,7 +334,17 @@ fn setup(edit: Option<&Fn(&str, &mut MockPackage)>, #[test] fn initial_install() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { + update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); + + assert!(utils::path_exists(&prefix.path().join("bin/rustc"))); + assert!(utils::path_exists(&prefix.path().join("lib/libstd.rlib"))); + }); +} + +#[test] +fn initial_install_xz() { + setup(None, true, &|url, toolchain, prefix, download_cfg, temp_cfg| { update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); assert!(utils::path_exists(&prefix.path().join("bin/rustc"))); @@ -344,7 +354,7 @@ fn initial_install() { #[test] fn test_uninstall() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); uninstall(toolchain, prefix, temp_cfg, &|_| ()).unwrap(); @@ -355,7 +365,7 @@ fn test_uninstall() { #[test] fn uninstall_removes_config_file() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); assert!(utils::path_exists(&prefix.manifest_file("multirust-config.toml"))); uninstall(toolchain, prefix, temp_cfg, &|_| ()).unwrap(); @@ -365,7 +375,7 @@ fn uninstall_removes_config_file() { #[test] fn upgrade() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); assert_eq!("2016-02-01", utils_raw::read_file(&prefix.path().join("bin/rustc")).unwrap()); @@ -387,7 +397,7 @@ fn update_removes_components_that_dont_exist() { }); } }; - setup(Some(edit), &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(Some(edit), false, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); assert!(utils::path_exists(&prefix.path().join("bin/bonus"))); @@ -399,7 +409,7 @@ fn update_removes_components_that_dont_exist() { #[test] fn update_preserves_extensions() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let ref adds = vec![ Component { pkg: "rust-std".to_string(), target: Some(TargetTriple::from_str("i686-apple-darwin")) @@ -441,7 +451,7 @@ fn update_preserves_extensions_that_became_components() { }); } }; - setup(Some(edit), &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(Some(edit), false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let ref adds = vec![ Component { pkg: "bonus".to_string(), target: Some(TargetTriple::from_str("x86_64-apple-darwin")) @@ -477,7 +487,7 @@ fn update_preserves_components_that_became_extensions() { }); } }; - setup(Some(edit), &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(Some(edit), false, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); assert!(utils::path_exists(&prefix.path().join("bin/bonus"))); @@ -489,7 +499,7 @@ fn update_preserves_components_that_became_extensions() { #[test] fn update_makes_no_changes_for_identical_manifest() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let status = update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); assert_eq!(status, UpdateStatus::Changed); let status = update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); @@ -499,7 +509,7 @@ fn update_makes_no_changes_for_identical_manifest() { #[test] fn add_extensions_for_initial_install() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let ref adds = vec![ Component { pkg: "rust-std".to_string(), target: Some(TargetTriple::from_str("i686-apple-darwin")) @@ -517,7 +527,7 @@ fn add_extensions_for_initial_install() { #[test] fn add_extensions_for_same_manifest() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); let ref adds = vec![ @@ -538,7 +548,7 @@ fn add_extensions_for_same_manifest() { #[test] fn add_extensions_for_upgrade() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); @@ -564,7 +574,7 @@ fn add_extensions_for_upgrade() { #[test] #[should_panic] fn add_extension_not_in_manifest() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let ref adds = vec![ Component { pkg: "rust-bogus".to_string(), target: Some(TargetTriple::from_str("i686-apple-darwin")) @@ -578,7 +588,7 @@ fn add_extension_not_in_manifest() { #[test] #[should_panic] fn add_extension_that_is_required_component() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let ref adds = vec![ Component { pkg: "rustc".to_string(), target: Some(TargetTriple::from_str("x86_64-apple-darwin")) @@ -601,7 +611,7 @@ fn add_extensions_for_same_manifest_when_extension_already_installed() { #[test] fn add_extensions_does_not_remove_other_components() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); let ref adds = vec![ @@ -620,7 +630,7 @@ fn add_extensions_does_not_remove_other_components() { #[test] #[should_panic] fn remove_extensions_for_initial_install() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let ref removes = vec![ Component { pkg: "rustc".to_string(), target: Some(TargetTriple::from_str("x86_64-apple-darwin")) @@ -633,7 +643,7 @@ fn remove_extensions_for_initial_install() { #[test] fn remove_extensions_for_same_manifest() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let ref adds = vec![ Component { pkg: "rust-std".to_string(), target: Some(TargetTriple::from_str("i686-apple-darwin")) @@ -660,7 +670,7 @@ fn remove_extensions_for_same_manifest() { #[test] fn remove_extensions_for_upgrade() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); let ref adds = vec![ @@ -692,7 +702,7 @@ fn remove_extensions_for_upgrade() { #[test] #[should_panic] fn remove_extension_not_in_manifest() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); @@ -724,7 +734,7 @@ fn remove_extension_not_in_manifest_but_is_already_installed() { }); } }; - setup(Some(edit), &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(Some(edit), false, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); let ref adds = vec![ @@ -749,7 +759,7 @@ fn remove_extension_not_in_manifest_but_is_already_installed() { #[test] #[should_panic] fn remove_extension_that_is_required_component() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); let ref removes = vec![ @@ -765,7 +775,7 @@ fn remove_extension_that_is_required_component() { #[test] #[should_panic] fn remove_extension_not_installed() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); let ref removes = vec![ @@ -785,7 +795,7 @@ fn remove_extensions_for_same_manifest_does_not_reinstall_other_components() { #[test] fn remove_extensions_does_not_remove_other_components() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let ref adds = vec![ Component { pkg: "rust-std".to_string(), target: Some(TargetTriple::from_str("i686-apple-darwin")) @@ -808,7 +818,7 @@ fn remove_extensions_does_not_remove_other_components() { #[test] fn add_and_remove_for_upgrade() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); let ref adds = vec![ @@ -842,7 +852,7 @@ fn add_and_remove_for_upgrade() { #[test] fn add_and_remove() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let ref adds = vec![ Component { pkg: "rust-std".to_string(), target: Some(TargetTriple::from_str("i686-unknown-linux-gnu")) @@ -873,7 +883,7 @@ fn add_and_remove() { #[test] #[should_panic] fn add_and_remove_same_component() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { update_from_dist(url, toolchain, prefix, &[], &[], download_cfg, temp_cfg).unwrap(); let ref adds = vec![ @@ -894,7 +904,7 @@ fn add_and_remove_same_component() { #[test] fn bad_component_hash() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let path = url.to_file_path().unwrap(); let path = path.join("dist/2016-02-02/rustc-nightly-x86_64-apple-darwin.tar.gz"); utils_raw::write_file(&path, "bogus").unwrap(); @@ -910,7 +920,7 @@ fn bad_component_hash() { #[test] fn unable_to_download_component() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let path = url.to_file_path().unwrap(); let path = path.join("dist/2016-02-02/rustc-nightly-x86_64-apple-darwin.tar.gz"); fs::remove_file(&path).unwrap(); @@ -937,7 +947,7 @@ fn allow_installation(prefix: &InstallPrefix) { #[test] fn reuse_downloaded_file() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { prevent_installation(prefix); @@ -967,7 +977,7 @@ fn reuse_downloaded_file() { #[test] fn checks_files_hashes_before_reuse() { - setup(None, &|url, toolchain, prefix, download_cfg, temp_cfg| { + setup(None, false, &|url, toolchain, prefix, download_cfg, temp_cfg| { let path = url.to_file_path().unwrap(); let target_hash = utils::read_file("target hash", &path.join("dist/2016-02-02/rustc-nightly-x86_64-apple-darwin.tar.gz.sha256")).unwrap()[.. 64].to_owned(); diff --git a/src/rustup-mock/Cargo.toml b/src/rustup-mock/Cargo.toml index 66430f4ee2..719717cfa5 100644 --- a/src/rustup-mock/Cargo.toml +++ b/src/rustup-mock/Cargo.toml @@ -15,6 +15,7 @@ scopeguard = "0.1.2" lazy_static = "0.1.15" walkdir = "0.1.5" flate2 = "0.2.9" +xz2 = "0.1.3" tempdir = "0.3.4" itertools = "0.4.1" tar = "0.4.0" diff --git a/src/rustup-mock/src/clitools.rs b/src/rustup-mock/src/clitools.rs index b29935c0f9..07854d22ff 100644 --- a/src/rustup-mock/src/clitools.rs +++ b/src/rustup-mock/src/clitools.rs @@ -334,7 +334,7 @@ fn create_mock_dist_server(path: &Path, s: Scenario) { MockDistServer { path: path.to_owned(), channels: chans, - }.write(vs); + }.write(vs, true); // Also create the manifests for stable releases by version if s == Scenario::Full || s == Scenario::ArchivesV1 || s == Scenario::ArchivesV2 { diff --git a/src/rustup-mock/src/dist.rs b/src/rustup-mock/src/dist.rs index 1c07f73c20..db82b1299a 100644 --- a/src/rustup-mock/src/dist.rs +++ b/src/rustup-mock/src/dist.rs @@ -11,6 +11,7 @@ use tempdir::TempDir; use sha2::{Sha256, Digest}; use toml; use flate2; +use xz2; use tar; use walkdir; @@ -102,16 +103,22 @@ pub struct MockComponent { pub target: String, } +#[derive(Clone)] +pub struct MockHashes { + pub gz: String, + pub xz: Option, +} + pub enum ManifestVersion { V1, V2 } impl MockDistServer { - pub fn write(&self, vs: &[ManifestVersion]) { + pub fn write(&self, vs: &[ManifestVersion], enable_xz: bool) { fs::create_dir_all(&self.path).unwrap(); for channel in self.channels.iter() { let ref mut hashes = HashMap::new(); for package in &channel.packages { - let new_hashes = self.build_package(&channel, &package); + let new_hashes = self.build_package(&channel, &package, enable_xz); hashes.extend(new_hashes.into_iter()); } for v in vs { @@ -123,16 +130,21 @@ impl MockDistServer { } } - fn build_package(&self, channel: &MockChannel, package: &MockPackage) -> HashMap { + fn build_package(&self, channel: &MockChannel, package: &MockPackage, enable_xz: bool) -> HashMap { let mut hashes = HashMap::new(); for target_package in &package.targets { - let hash = self.build_target_package(channel, package, target_package); + let gz_hash = self.build_target_package(channel, package, target_package, ".tar.gz"); + let xz_hash = if enable_xz { + Some(self.build_target_package(channel, package, target_package, ".tar.xz")) + } else { + None + }; let component = MockComponent { name: package.name.to_string(), target: target_package.target.to_string(), }; - hashes.insert(component, hash); + hashes.insert(component, MockHashes { gz: gz_hash, xz: xz_hash }); } return hashes; @@ -142,7 +154,8 @@ impl MockDistServer { fn build_target_package(&self, channel: &MockChannel, package: &MockPackage, - target_package: &MockTargetedPackage) -> String { + target_package: &MockTargetedPackage, + format: &str) -> String { // This is where the tarball, sums and sigs will go let ref dist_dir = self.path.join("dist"); let ref archive_dir = dist_dir.join(&channel.date); @@ -158,8 +171,8 @@ impl MockDistServer { format!("{}-{}", package.name, channel.name) }; let ref installer_dir = workdir.join(installer_name); - let ref installer_tarball = archive_dir.join(format!("{}.tar.gz", installer_name)); - let ref installer_hash = archive_dir.join(format!("{}.tar.gz.sha256", installer_name)); + let ref installer_tarball = archive_dir.join(format!("{}{}", installer_name, format)); + let ref installer_hash = archive_dir.join(format!("{}{}.sha256", installer_name, format)); fs::create_dir_all(installer_dir).unwrap(); @@ -172,8 +185,8 @@ impl MockDistServer { // Copy from the archive to the main dist directory if package.name == "rust" { - let ref main_installer_tarball = dist_dir.join(format!("{}.tar.gz", installer_name)); - let ref main_installer_hash = dist_dir.join(format!("{}.tar.gz.sha256", installer_name)); + let ref main_installer_tarball = dist_dir.join(format!("{}{}", installer_name, format)); + let ref main_installer_hash = dist_dir.join(format!("{}{}.sha256", installer_name, format)); fs::copy(installer_tarball, main_installer_tarball).unwrap(); fs::copy(installer_hash, main_installer_hash).unwrap(); } @@ -210,7 +223,7 @@ impl MockDistServer { fs::copy(hash_path, archive_hash_path).unwrap(); } - fn write_manifest_v2(&self, channel: &MockChannel, hashes: &HashMap) { + fn write_manifest_v2(&self, channel: &MockChannel, hashes: &HashMap) { let mut toml_manifest = toml::Table::new(); toml_manifest.insert(String::from("manifest-version"), toml::Value::String(MOCK_MANIFEST_VERSION.to_owned())); @@ -235,14 +248,19 @@ impl MockDistServer { }; let path = self.path.join("dist").join(&channel.date).join(package_file_name); let url = format!("file://{}", path.to_string_lossy()); - toml_target.insert(String::from("url"), toml::Value::String(url)); + toml_target.insert(String::from("url"), toml::Value::String(url.clone())); let ref component = MockComponent { name: package.name.to_owned(), target: target.target.to_owned(), }; let hash = hashes[component].clone(); - toml_target.insert(String::from("hash"), toml::Value::String(hash)); + toml_target.insert(String::from("hash"), toml::Value::String(hash.gz)); + + if let Some(xz_hash) = hash.xz { + toml_target.insert(String::from("xz_url"), toml::Value::String(url.replace(".tar.gz", ".tar.xz"))); + toml_target.insert(String::from("xz_hash"), toml::Value::String(xz_hash)); + } // [pkg.*.target.*.components.*] let mut toml_components = toml::Array::new(); @@ -291,8 +309,20 @@ impl MockDistServer { fn create_tarball(relpath: &Path, src: &Path, dst: &Path) { let outfile = File::create(dst).unwrap(); - let gzwriter = flate2::write::GzEncoder::new(outfile, flate2::Compression::None); - let mut tar = tar::Builder::new(gzwriter); + let mut gzwriter; + let mut xzwriter; + let writer: &mut Write = match &dst.to_string_lossy() { + s if s.ends_with(".tar.gz") => { + gzwriter = flate2::write::GzEncoder::new(outfile, flate2::Compression::None); + &mut gzwriter + } + s if s.ends_with(".tar.xz") => { + xzwriter = xz2::write::XzEncoder::new(outfile, 0); + &mut xzwriter + } + _ => panic!("Unsupported archive format"), + }; + let mut tar = tar::Builder::new(writer); for entry in walkdir::WalkDir::new(src) { let entry = entry.unwrap(); let parts: Vec<_> = entry.path().iter().map(|p| p.to_owned()).collect(); diff --git a/src/rustup-mock/src/lib.rs b/src/rustup-mock/src/lib.rs index cf2fe3914b..3a860a001b 100644 --- a/src/rustup-mock/src/lib.rs +++ b/src/rustup-mock/src/lib.rs @@ -6,6 +6,7 @@ extern crate lazy_static; extern crate scopeguard; extern crate walkdir; extern crate flate2; +extern crate xz2; extern crate tempdir; extern crate itertools; extern crate tar; diff --git a/tests/cli-rustup.rs b/tests/cli-rustup.rs index a4f5f7bd7b..0dab4a693e 100644 --- a/tests/cli-rustup.rs +++ b/tests/cli-rustup.rs @@ -11,7 +11,7 @@ use std::process; use rustup_utils::raw; use rustup_mock::clitools::{self, Config, Scenario, expect_ok, expect_ok_ex, - expect_stdout_ok, + expect_stderr_ok, expect_stdout_ok, expect_err, set_current_dist_date, this_host_triple}; @@ -206,6 +206,15 @@ info: default toolchain set to 'nightly-{0}' }); } +#[test] +fn rustup_xz() { + setup(&|config| { + set_current_dist_date(config, "2015-01-01"); + expect_stderr_ok(config, &["rustup", "--verbose", "update", "nightly"], +for_host!(r"dist/2015-01-01/rust-std-nightly-{0}.tar.xz")); + }); +} + #[test] fn add_target() { setup(&|config| { diff --git a/tests/cli-v1.rs b/tests/cli-v1.rs index a75a94a42b..9f23ef6f54 100644 --- a/tests/cli-v1.rs +++ b/tests/cli-v1.rs @@ -165,8 +165,10 @@ fn bad_sha_on_installer() { let dir = config.distdir.join("dist"); for file in fs::read_dir(&dir).unwrap() { let file = file.unwrap(); - if file.path().to_string_lossy().ends_with(".tar.gz") { - rustup_utils::raw::write_file(&file.path(), "xxx").unwrap(); + let path = file.path(); + let filename = path.to_string_lossy(); + if filename.ends_with(".tar.gz") || filename.ends_with(".tar.xz") { + rustup_utils::raw::write_file(&path, "xxx").unwrap(); } } expect_err(config, &["rustup", "default", "nightly"], diff --git a/tests/cli-v2.rs b/tests/cli-v2.rs index dd6da4228d..38aa04f8d6 100644 --- a/tests/cli-v2.rs +++ b/tests/cli-v2.rs @@ -209,8 +209,10 @@ fn bad_sha_on_installer() { let dir = config.distdir.join("dist/2015-01-02"); for file in fs::read_dir(&dir).unwrap() { let file = file.unwrap(); - if file.path().to_string_lossy().ends_with(".tar.gz") { - rustup_utils::raw::write_file(&file.path(), "xxx").unwrap(); + let path = file.path(); + let filename = path.to_string_lossy(); + if filename.ends_with(".tar.gz") || filename.ends_with(".tar.xz") { + rustup_utils::raw::write_file(&path, "xxx").unwrap(); } } expect_err(config, &["rustup", "default", "nightly"],