diff --git a/Cargo.lock b/Cargo.lock index 58e6027c1c..6e186724c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,6 +235,9 @@ name = "cc" version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +dependencies = [ + "jobserver", +] [[package]] name = "cfb-mode" @@ -779,6 +782,12 @@ dependencies = [ "syn", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "h2" version = "0.3.0" @@ -946,12 +955,30 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +[[package]] +name = "jobserver" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.47" @@ -1777,6 +1804,7 @@ dependencies = [ "winapi", "winreg 0.8.0", "xz2", + "zstd", ] [[package]] @@ -2622,3 +2650,34 @@ dependencies = [ "syn", "synstructure", ] + +[[package]] +name = "zstd" +version = "0.6.0+zstd.1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e44664feba7f2f1a9f300c1f6157f2d1bfc3c15c6f3cf4beabf3f5abe9c237" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "3.0.0+zstd.1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9447afcd795693ad59918c7bbffe42fdd6e467d708f3537e3dc14dc598c573f" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "1.4.19+zstd.1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec24a9273d24437afb8e71b16f3d9a5d569193cccdb7896213b59f552f387674" +dependencies = [ + "cc", + "glob", + "itertools", + "libc", +] diff --git a/Cargo.toml b/Cargo.toml index 4b9c2ccfce..1944ca272f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,6 +63,7 @@ toml = "0.5" url = "2.1" wait-timeout = "0.2" xz2 = "0.1.3" +zstd = "0.6" [dependencies.retry] default-features = false diff --git a/src/dist/component/package.rs b/src/dist/component/package.rs index ca8843eb9f..3888b5f876 100644 --- a/src/dist/component/package.rs +++ b/src/dist/component/package.rs @@ -572,3 +572,39 @@ impl<'a> Package for TarXzPackage<'a> { self.0.components() } } + +#[derive(Debug)] +pub struct TarZStdPackage<'a>(TarPackage<'a>); + +impl<'a> TarZStdPackage<'a> { + pub fn new( + stream: R, + temp_cfg: &'a temp::Cfg, + notify_handler: Option<&'a dyn Fn(Notification<'_>)>, + ) -> Result { + let stream = zstd::stream::read::Decoder::new(stream)?; + Ok(TarZStdPackage(TarPackage::new( + stream, + temp_cfg, + notify_handler, + )?)) + } +} + +impl<'a> Package for TarZStdPackage<'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/dist/manifest.rs b/src/dist/manifest.rs index f54fc7f894..3af5385a57 100644 --- a/src/dist/manifest.rs +++ b/src/dist/manifest.rs @@ -55,18 +55,23 @@ pub struct TargetedPackage { pub enum CompressionKind { GZip, XZ, + ZStd, } /// Each compression kind, in order of preference for use, from most desirable /// to least desirable. -static COMPRESSION_KIND_PREFERENCE_ORDER: &[CompressionKind] = - &[CompressionKind::XZ, CompressionKind::GZip]; +static COMPRESSION_KIND_PREFERENCE_ORDER: &[CompressionKind] = &[ + CompressionKind::ZStd, + CompressionKind::XZ, + CompressionKind::GZip, +]; impl CompressionKind { const fn key_prefix(self) -> &'static str { match self { Self::GZip => "", Self::XZ => "xz_", + Self::ZStd => "zst_", } } } diff --git a/src/dist/manifestation.rs b/src/dist/manifestation.rs index b3621fc3d7..5a9f369e0e 100644 --- a/src/dist/manifestation.rs +++ b/src/dist/manifestation.rs @@ -7,7 +7,9 @@ use retry::delay::NoDelay; use retry::{retry, OperationResult}; use crate::config::PgpPublicKey; -use crate::dist::component::{Components, Package, TarGzPackage, TarXzPackage, Transaction}; +use crate::dist::component::{ + Components, Package, TarGzPackage, TarXzPackage, TarZStdPackage, Transaction, +}; use crate::dist::config::Config; use crate::dist::dist::{Profile, TargetTriple, DEFAULT_DIST_SERVER}; use crate::dist::download::{DownloadCfg, File}; @@ -238,6 +240,7 @@ impl Manifestation { }; let gz; let xz; + let zst; let reader = utils::FileReaderWithProgress::new_file(&installer_file, ¬ification_converter)?; let package: &dyn Package = match format { @@ -249,6 +252,10 @@ impl Manifestation { xz = TarXzPackage::new(reader, temp_cfg, Some(¬ification_converter))?; &xz } + CompressionKind::ZStd => { + zst = TarZStdPackage::new(reader, temp_cfg, Some(¬ification_converter))?; + &zst + } }; // If the package doesn't contain the component that the diff --git a/tests/cli-rustup.rs b/tests/cli-rustup.rs index 1ebfd7e53a..ae4a7e92ff 100644 --- a/tests/cli-rustup.rs +++ b/tests/cli-rustup.rs @@ -323,7 +323,7 @@ info: note that the toolchain 'nightly-{0}' is currently in use (directory overr } #[test] -fn rustup_xz() { +fn rustup_zstd() { setup(&|config| { set_current_dist_date(config, "2015-01-01"); expect_stderr_ok( @@ -335,7 +335,7 @@ fn rustup_xz() { "nightly", "--no-self-update", ], - for_host!(r"dist/2015-01-01/rust-std-nightly-{0}.tar.xz"), + for_host!(r"dist/2015-01-01/rust-std-nightly-{0}.tar.zst"), ); }); } diff --git a/tests/cli-v2.rs b/tests/cli-v2.rs index 03d59501ad..a415e1db49 100644 --- a/tests/cli-v2.rs +++ b/tests/cli-v2.rs @@ -328,7 +328,10 @@ fn bad_sha_on_installer() { let file = file.unwrap(); let path = file.path(); let filename = path.to_string_lossy(); - if filename.ends_with(".tar.gz") || filename.ends_with(".tar.xz") { + if filename.ends_with(".tar.gz") + || filename.ends_with(".tar.xz") + || filename.ends_with(".tar.zst") + { rustup::utils::raw::write_file(&path, "xxx").unwrap(); } } diff --git a/tests/dist.rs b/tests/dist.rs index 4fec2c56c7..0906f98ec2 100644 --- a/tests/dist.rs +++ b/tests/dist.rs @@ -231,7 +231,7 @@ fn mock_dist_server_smoke_test() { let tempdir = tempfile::Builder::new().prefix("rustup").tempdir().unwrap(); let path = tempdir.path(); - create_mock_dist_server(&path, None).write(&[ManifestVersion::V2], false); + create_mock_dist_server(&path, None).write(&[ManifestVersion::V2], false, false); assert!(utils::path_exists(path.join( "dist/2016-02-01/rustc-nightly-x86_64-apple-darwin.tar.gz" @@ -314,7 +314,7 @@ fn rename_component() { setup_from_dist_server( mock_dist_server, &url, - false, + GZOnly, &|url, toolchain, prefix, download_cfg, temp_cfg| { let adds = [Component::new( "bonus".to_string(), @@ -379,7 +379,7 @@ fn rename_component_new() { setup_from_dist_server( mock_dist_server, &url, - false, + GZOnly, &|url, toolchain, prefix, download_cfg, temp_cfg| { let adds = [Component::new( "bobo".to_string(), @@ -496,24 +496,47 @@ fn uninstall( Ok(()) } +#[derive(Copy, Clone, Debug)] +enum Compressions { + GZOnly, + AddXZ, + AddZStd, + AddXZAndZStd, +} +use Compressions::*; + +impl Compressions { + fn enable_xz(self) -> bool { + matches!(self, AddXZ | AddXZAndZStd) + } + + fn enable_zst(self) -> bool { + matches!(self, AddZStd | AddXZAndZStd) + } +} + fn setup( edit: Option<&dyn Fn(&str, &mut MockChannel)>, - enable_xz: bool, + comps: Compressions, f: &dyn Fn(&Url, &ToolchainDesc, &InstallPrefix, &DownloadCfg<'_>, &temp::Cfg), ) { let dist_tempdir = tempfile::Builder::new().prefix("rustup").tempdir().unwrap(); let mock_dist_server = create_mock_dist_server(dist_tempdir.path(), edit); let url = Url::parse(&format!("file://{}", dist_tempdir.path().to_string_lossy())).unwrap(); - setup_from_dist_server(mock_dist_server, &url, enable_xz, f); + setup_from_dist_server(mock_dist_server, &url, comps, f); } fn setup_from_dist_server( server: MockDistServer, url: &Url, - enable_xz: bool, + comps: Compressions, f: &dyn Fn(&Url, &ToolchainDesc, &InstallPrefix, &DownloadCfg<'_>, &temp::Cfg), ) { - server.write(&[ManifestVersion::V2], enable_xz); + server.write( + &[ManifestVersion::V2], + comps.enable_xz(), + comps.enable_zst(), + ); let prefix_tempdir = tempfile::Builder::new().prefix("rustup").tempdir().unwrap(); @@ -550,9 +573,8 @@ fn setup_from_dist_server( ); } -#[test] -fn initial_install() { - setup(None, false, &|url, +fn initial_install(comps: Compressions) { + setup(None, comps, &|url, toolchain, prefix, download_cfg, @@ -574,37 +596,28 @@ fn initial_install() { }); } +#[test] +fn initial_install_gziponly() { + initial_install(GZOnly); +} + #[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, - false, - ) - .unwrap(); + initial_install(AddXZ); +} - assert!(utils::path_exists(&prefix.path().join("bin/rustc"))); - assert!(utils::path_exists(&prefix.path().join("lib/libstd.rlib"))); - }); +#[test] +fn initial_install_zst() { + initial_install(AddZStd); } #[test] fn test_uninstall() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { update_from_dist( url, toolchain, @@ -625,11 +638,11 @@ fn test_uninstall() { #[test] fn uninstall_removes_config_file() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { update_from_dist( url, toolchain, @@ -653,11 +666,11 @@ fn uninstall_removes_config_file() { #[test] fn upgrade() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); update_from_dist( url, @@ -727,7 +740,7 @@ fn unavailable_component() { setup( Some(edit), - false, + GZOnly, &|url, toolchain, prefix, download_cfg, temp_cfg| { let adds = [Component::new( "bonus".to_string(), @@ -794,7 +807,7 @@ fn unavailable_component_from_profile() { setup( Some(edit), - false, + GZOnly, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); // Update with rustc. @@ -868,7 +881,7 @@ fn removed_component() { setup( Some(edit), - false, + GZOnly, &|url, toolchain, prefix, download_cfg, temp_cfg| { let adds = [Component::new( "bonus".to_string(), @@ -934,7 +947,7 @@ fn unavailable_components_is_target() { setup( Some(edit), - false, + GZOnly, &|url, toolchain, prefix, download_cfg, temp_cfg| { let adds = [ Component::new( @@ -1031,7 +1044,7 @@ fn unavailable_components_with_same_target() { setup( Some(edit), - false, + GZOnly, &|url, toolchain, prefix, download_cfg, temp_cfg| { // Update with rust-std and rustc change_channel_date(url, "nightly", "2016-02-01"); @@ -1077,11 +1090,11 @@ fn unavailable_components_with_same_target() { #[test] fn update_preserves_extensions() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let adds = vec![ Component::new( "rust-std".to_string(), @@ -1139,11 +1152,11 @@ fn update_preserves_extensions() { #[test] fn update_makes_no_changes_for_identical_manifest() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let status = update_from_dist( url, toolchain, @@ -1173,11 +1186,11 @@ fn update_makes_no_changes_for_identical_manifest() { #[test] fn add_extensions_for_initial_install() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let adds = vec![ Component::new( "rust-std".to_string(), @@ -1213,11 +1226,11 @@ fn add_extensions_for_initial_install() { #[test] fn add_extensions_for_same_manifest() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { update_from_dist( url, toolchain, @@ -1266,11 +1279,11 @@ fn add_extensions_for_same_manifest() { #[test] fn add_extensions_for_upgrade() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); update_from_dist( @@ -1324,11 +1337,11 @@ fn add_extensions_for_upgrade() { #[test] #[should_panic] fn add_extension_not_in_manifest() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let adds = vec![Component::new( "rust-bogus".to_string(), Some(TargetTriple::new("i686-apple-darwin")), @@ -1352,11 +1365,11 @@ fn add_extension_not_in_manifest() { #[test] #[should_panic] fn add_extension_that_is_required_component() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let adds = vec![Component::new( "rustc".to_string(), Some(TargetTriple::new("x86_64-apple-darwin")), @@ -1387,11 +1400,11 @@ fn add_extensions_for_same_manifest_when_extension_already_installed() {} #[test] fn add_extensions_does_not_remove_other_components() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { update_from_dist( url, toolchain, @@ -1430,11 +1443,11 @@ fn add_extensions_does_not_remove_other_components() { #[test] #[should_panic] fn remove_extensions_for_initial_install() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let removes = vec![Component::new( "rustc".to_string(), Some(TargetTriple::new("x86_64-apple-darwin")), @@ -1457,11 +1470,11 @@ fn remove_extensions_for_initial_install() { #[test] fn remove_extensions_for_same_manifest() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let adds = vec![ Component::new( "rust-std".to_string(), @@ -1516,11 +1529,11 @@ fn remove_extensions_for_same_manifest() { #[test] fn remove_extensions_for_upgrade() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); let adds = vec![ @@ -1580,11 +1593,11 @@ fn remove_extensions_for_upgrade() { #[test] #[should_panic] fn remove_extension_not_in_manifest() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); update_from_dist( @@ -1643,7 +1656,7 @@ fn remove_extension_not_in_manifest_but_is_already_installed() { }; setup( Some(edit), - false, + GZOnly, &|url, toolchain, prefix, download_cfg, temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); @@ -1690,11 +1703,11 @@ fn remove_extension_not_in_manifest_but_is_already_installed() { #[test] #[should_panic] fn remove_extension_that_is_required_component() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { update_from_dist( url, toolchain, @@ -1730,11 +1743,11 @@ fn remove_extension_that_is_required_component() { #[test] #[should_panic] fn remove_extension_not_installed() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { update_from_dist( url, toolchain, @@ -1773,11 +1786,11 @@ fn remove_extensions_for_same_manifest_does_not_reinstall_other_components() {} #[test] fn remove_extensions_does_not_remove_other_components() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let adds = vec![Component::new( "rust-std".to_string(), Some(TargetTriple::new("i686-apple-darwin")), @@ -1820,11 +1833,11 @@ fn remove_extensions_does_not_remove_other_components() { #[test] fn add_and_remove_for_upgrade() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { change_channel_date(url, "nightly", "2016-02-01"); let adds = vec![Component::new( @@ -1882,11 +1895,11 @@ fn add_and_remove_for_upgrade() { #[test] fn add_and_remove() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let adds = vec![Component::new( "rust-std".to_string(), Some(TargetTriple::new("i686-unknown-linux-gnu")), @@ -1940,11 +1953,11 @@ fn add_and_remove() { #[test] fn add_and_remove_same_component() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { update_from_dist( url, toolchain, @@ -1985,11 +1998,11 @@ fn add_and_remove_same_component() { #[test] fn bad_component_hash() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|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(); @@ -2015,11 +2028,11 @@ fn bad_component_hash() { #[test] fn unable_to_download_component() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|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(); @@ -2061,11 +2074,11 @@ fn allow_installation(prefix: &InstallPrefix) { #[test] fn reuse_downloaded_file() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { prevent_installation(prefix); let reuse_notification_fired = Arc::new(Cell::new(false)); @@ -2118,11 +2131,11 @@ fn reuse_downloaded_file() { #[test] fn checks_files_hashes_before_reuse() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { let path = url.to_file_path().unwrap(); let target_hash = utils::read_file( "target hash", @@ -2174,11 +2187,11 @@ fn checks_files_hashes_before_reuse() { #[test] fn handle_corrupt_partial_downloads() { - setup(None, false, &|url, - toolchain, - prefix, - download_cfg, - temp_cfg| { + setup(None, GZOnly, &|url, + toolchain, + prefix, + download_cfg, + temp_cfg| { // write a corrupt partial out let path = url.to_file_path().unwrap(); let target_hash = utils::read_file( diff --git a/tests/mock/clitools.rs b/tests/mock/clitools.rs index 4285e439ea..3b33b774c0 100644 --- a/tests/mock/clitools.rs +++ b/tests/mock/clitools.rs @@ -911,7 +911,7 @@ fn create_mock_dist_server(path: &Path, s: Scenario) { path: path.to_owned(), channels: chans.iter().map(|c| c.mock()).collect(), } - .write(&vs, true); + .write(&vs, true, true); for chan in &chans { chan.link(path) diff --git a/tests/mock/dist.rs b/tests/mock/dist.rs index 0a5efeaa93..437f261304 100644 --- a/tests/mock/dist.rs +++ b/tests/mock/dist.rs @@ -112,6 +112,7 @@ pub struct MockComponent { pub struct MockHashes { pub gz: String, pub xz: Option, + pub zst: Option, } pub enum ManifestVersion { @@ -120,13 +121,13 @@ pub enum ManifestVersion { } impl MockDistServer { - pub fn write(&self, vs: &[ManifestVersion], enable_xz: bool) { + pub fn write(&self, vs: &[ManifestVersion], enable_xz: bool, enable_zst: bool) { fs::create_dir_all(&self.path).unwrap(); for channel in self.channels.iter() { let mut hashes = HashMap::new(); for package in &channel.packages { - let new_hashes = self.build_package(&channel, &package, enable_xz); + let new_hashes = self.build_package(&channel, &package, enable_xz, enable_zst); hashes.extend(new_hashes.into_iter()); } for v in vs { @@ -143,6 +144,7 @@ impl MockDistServer { channel: &MockChannel, package: &MockPackage, enable_xz: bool, + enable_zst: bool, ) -> HashMap { let mut hashes = HashMap::new(); @@ -153,6 +155,11 @@ impl MockDistServer { } else { None }; + let zst_hash = if enable_zst { + Some(self.build_target_package(channel, package, target_package, ".tar.zst")) + } else { + None + }; let component = MockComponent { name: package.name.to_string(), target: target_package.target.to_string(), @@ -163,6 +170,7 @@ impl MockDistServer { MockHashes { gz: gz_hash, xz: xz_hash, + zst: zst_hash, }, ); } @@ -356,6 +364,13 @@ impl MockDistServer { ); toml_target.insert(String::from("xz_hash"), toml::Value::String(xz_hash)); } + if let Some(zst_hash) = hash.zst { + toml_target.insert( + String::from("zst_url"), + toml::Value::String(url.replace(".tar.gz", ".tar.zst")), + ); + toml_target.insert(String::from("zst_hash"), toml::Value::String(zst_hash)); + } // [pkg.*.target.*.components.*] and [pkg.*.target.*.extensions.*] let mut toml_components = toml::value::Array::new(); @@ -457,6 +472,7 @@ fn create_tarball(relpath: &Path, src: &Path, dst: &Path) -> io::Result<()> { let outfile = File::create(dst)?; let mut gzwriter; let mut xzwriter; + let mut zstwriter; let writer: &mut dyn Write = match &dst.to_string_lossy() { s if s.ends_with(".tar.gz") => { gzwriter = flate2::write::GzEncoder::new(outfile, flate2::Compression::none()); @@ -466,6 +482,10 @@ fn create_tarball(relpath: &Path, src: &Path, dst: &Path) -> io::Result<()> { xzwriter = xz2::write::XzEncoder::new(outfile, 0); &mut xzwriter } + s if s.ends_with(".tar.zst") => { + zstwriter = zstd::stream::write::Encoder::new(outfile, 0)?.auto_finish(); + &mut zstwriter + } _ => panic!("Unsupported archive format"), }; let mut tar = tar::Builder::new(writer);