diff --git a/.github/workflows/build-artifacts-and-run-tests.yml b/.github/workflows/build-artifacts-and-run-tests.yml index 3b84f9d..3b53cff 100644 --- a/.github/workflows/build-artifacts-and-run-tests.yml +++ b/.github/workflows/build-artifacts-and-run-tests.yml @@ -25,7 +25,7 @@ on: type: boolean required: true artifact_upload_mode: - description: "Control which artifacts to upload: 'none' for no uploads, 'with_default_features' to upload only artifacts with default features (use_zlib+use_zstd_thin+unrar), or 'all' to upload all feature combinations." + description: "Control which artifacts to upload: 'none' for no uploads, 'with_default_features' to upload only artifacts with default features (use_zlib+use_zstd_thin+unrar+bzip3), or 'all' to upload all feature combinations." type: string required: true @@ -37,7 +37,8 @@ jobs: strategy: fail-fast: false matrix: - feature-unrar: ${{ inputs.matrix_all_combinations && fromJSON('[true, false]') || fromJSON('[false]')}} + feature-unrar: ${{ inputs.matrix_all_combinations && fromJSON('[true, false]') || fromJSON('[true]')}} + feature-bzip3: ${{ inputs.matrix_all_combinations && fromJSON('[true, false]') || fromJSON('[true]')}} feature-use-zlib: ${{ inputs.matrix_all_combinations && fromJSON('[true, false]') || fromJSON('[false]')}} feature-use-zstd-thin: ${{ inputs.matrix_all_combinations && fromJSON('[true, false]') || fromJSON('[false]')}} target: @@ -76,12 +77,14 @@ jobs: - target: armv7-unknown-linux-musleabihf use-cross: true # features (unless `matrix_all_combinations` is true, we only run these on linux-gnu) - - feature-unrar: true + - feature-unrar: false target: x86_64-unknown-linux-gnu - feature-use-zlib: true target: x86_64-unknown-linux-gnu - feature-use-zstd-thin: true target: x86_64-unknown-linux-gnu + - feature-bzip3: false + target: x86_64-unknown-linux-gnu steps: - name: Checkout @@ -105,6 +108,7 @@ jobs: if [[ "${{ matrix.feature-unrar }}" == true ]]; then FEATURES+=(unrar); fi if [[ "${{ matrix.feature-use-zlib }}" == true ]]; then FEATURES+=(use_zlib); fi if [[ "${{ matrix.feature-use-zstd-thin }}" == true ]]; then FEATURES+=(use_zstd_thin); fi + if [[ "${{ matrix.feature-bzip3 }}" == true ]]; then FEATURES+=(bzip3); fi # Output plus-separated list for artifact names IFS='+' echo "FEATURES_PLUS=${FEATURES[*]}" >> $GITHUB_OUTPUT @@ -127,7 +131,7 @@ jobs: - uses: Swatinem/rust-cache@v2 with: - key: "${{ matrix.target }}-${{ matrix.feature-unrar }}-${{ matrix.feature-use-zlib }}-${{ matrix.feature-use-zstd-thin }}" + key: "${{ matrix.target }}-${{ matrix.feature-unrar }}-${{ matrix.feature-use-zlib }}-${{ matrix.feature-use-zstd-thin }}-${{ matrix.feature-bzip3 }}" - name: Test on stable # there's no way to run tests for ARM64 Windows for now @@ -146,7 +150,7 @@ jobs: if: | ${{ inputs.artifact_upload_mode != 'none' && (inputs.artifact_upload_mode == 'all' || - (matrix.feature-unrar && matrix.feature-use-zlib && matrix.feature-use-zstd-thin)) }} + (matrix.feature-unrar && matrix.feature-use-zlib && matrix.feature-use-zstd-thin && matrix.feature-bzip3)) }} uses: actions/upload-artifact@v4 with: name: ouch-${{ matrix.target }}${{ steps.concat-features.outputs.FEATURES_PLUS != '' && format('-{0}', steps.concat-features.outputs.FEATURES_PLUS) || '' }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 734e684..432b703 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ Categories Used: ### Bug Fixes ### Tweaks +- Make `.bz3` opt-out [\#814](https://github.com/ouch-org/ouch/pull/814) ([amyspark](https://github.com/amyspark)) + ## [0.6.1](https://github.com/ouch-org/ouch/compare/0.6.0...0.6.1) - Fix .zip crash when file mode isn't present [\#804](https://github.com/ouch-org/ouch/pull/804) ([marcospb19](https://github.com/marcospb19)) diff --git a/Cargo.toml b/Cargo.toml index 835e55f..3577a2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ brotli = "7.0.0" bstr = { version = "1.10.0", default-features = false, features = ["std"] } bytesize = "1.3.0" bzip2 = "0.4.4" -bzip3 = { version = "0.9.0", features = ["bundled"] } +bzip3 = { version = "0.9.0", features = ["bundled"] , optional = true } clap = { version = "4.5.20", features = ["derive", "env"] } filetime_creation = "0.2" flate2 = { version = "1.0.30", default-features = false } @@ -70,7 +70,7 @@ regex = "1.10.4" test-strategy = "0.4.0" [features] -default = ["unrar", "use_zlib", "use_zstd_thin"] +default = ["unrar", "use_zlib", "use_zstd_thin", "bzip3"] use_zlib = ["flate2/zlib", "gzp/deflate_zlib", "zip/deflate-zlib"] use_zstd_thin = ["zstd/thin"] allow_piped_choice = [] diff --git a/scripts/package-release-assets.sh b/scripts/package-release-assets.sh index 621f28e..9ae9f02 100755 --- a/scripts/package-release-assets.sh +++ b/scripts/package-release-assets.sh @@ -21,7 +21,7 @@ PLATFORMS=( "x86_64-unknown-linux-musl" ) # TODO: remove allow_piped_choice later -DEFAULT_FEATURES="allow_piped_choice+unrar+use_zlib+use_zstd_thin" +DEFAULT_FEATURES="allow_piped_choice+unrar+use_zlib+use_zstd_thin+bzip3" for platform in "${PLATFORMS[@]}"; do path="ouch-${platform}" diff --git a/src/archive/bzip3_stub.rs b/src/archive/bzip3_stub.rs new file mode 100644 index 0000000..e1db197 --- /dev/null +++ b/src/archive/bzip3_stub.rs @@ -0,0 +1,7 @@ +use crate::Error; + +pub fn no_support() -> Error { + Error::UnsupportedFormat { + reason: "BZip3 support is disabled for this build, possibly due to missing bindgen-cli dependency.".into(), + } +} diff --git a/src/archive/mod.rs b/src/archive/mod.rs index 4cfacc0..6412a8a 100644 --- a/src/archive/mod.rs +++ b/src/archive/mod.rs @@ -1,5 +1,7 @@ //! Archive compression algorithms +#[cfg(not(feature = "bzip3"))] +pub mod bzip3_stub; #[cfg(feature = "unrar")] pub mod rar; #[cfg(not(feature = "unrar"))] diff --git a/src/commands/compress.rs b/src/commands/compress.rs index b6f7042..15880bd 100644 --- a/src/commands/compress.rs +++ b/src/commands/compress.rs @@ -57,10 +57,16 @@ pub fn compress_files( encoder, level.map_or_else(Default::default, |l| bzip2::Compression::new((l as u32).clamp(1, 9))), )), - Bzip3 => Box::new( - // Use block size of 16 MiB - bzip3::write::Bz3Encoder::new(encoder, 16 * 2_usize.pow(20))?, - ), + Bzip3 => { + #[cfg(not(feature = "bzip3"))] + return Err(archive::bzip3_stub::no_support()); + + #[cfg(feature = "bzip3")] + Box::new( + // Use block size of 16 MiB + bzip3::write::Bz3Encoder::new(encoder, 16 * 2_usize.pow(20))?, + ) + } Lz4 => Box::new(lz4_flex::frame::FrameEncoder::new(encoder).auto_finish()), Lzma => Box::new(xz2::write::XzEncoder::new( encoder, diff --git a/src/commands/decompress.rs b/src/commands/decompress.rs index 36c8658..a108c16 100644 --- a/src/commands/decompress.rs +++ b/src/commands/decompress.rs @@ -6,6 +6,8 @@ use std::{ use fs_err as fs; +#[cfg(not(feature = "bzip3"))] +use crate::archive; use crate::{ commands::{warn_user_about_loading_sevenz_in_memory, warn_user_about_loading_zip_in_memory}, extension::{ @@ -118,7 +120,13 @@ pub fn decompress_file(options: DecompressOptions) -> crate::Result<()> { let decoder: Box = match format { Gzip => Box::new(flate2::read::GzDecoder::new(decoder)), Bzip => Box::new(bzip2::read::BzDecoder::new(decoder)), - Bzip3 => Box::new(bzip3::read::Bz3Decoder::new(decoder)?), + Bzip3 => { + #[cfg(not(feature = "bzip3"))] + return Err(archive::bzip3_stub::no_support()); + + #[cfg(feature = "bzip3")] + Box::new(bzip3::read::Bz3Decoder::new(decoder)?) + } Lz4 => Box::new(lz4_flex::frame::FrameDecoder::new(decoder)), Lzma => Box::new(xz2::read::XzDecoder::new(decoder)), Snappy => Box::new(snap::read::FrameDecoder::new(decoder)), diff --git a/src/commands/list.rs b/src/commands/list.rs index a64c55c..b3405b4 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -6,7 +6,7 @@ use std::{ use fs_err as fs; use crate::{ - archive::sevenz, + archive, commands::warn_user_about_loading_zip_in_memory, extension::CompressionFormat::{self, *}, list::{self, FileInArchive, ListOptions}, @@ -50,7 +50,13 @@ pub fn list_archive_contents( let decoder: Box = match format { Gzip => Box::new(flate2::read::GzDecoder::new(decoder)), Bzip => Box::new(bzip2::read::BzDecoder::new(decoder)), - Bzip3 => Box::new(bzip3::read::Bz3Decoder::new(decoder).unwrap()), + Bzip3 => { + #[cfg(not(feature = "bzip3"))] + return Err(archive::bzip3_stub::no_support()); + + #[cfg(feature = "bzip3")] + Box::new(bzip3::read::Bz3Decoder::new(decoder).unwrap()) + } Lz4 => Box::new(lz4_flex::frame::FrameDecoder::new(decoder)), Lzma => Box::new(xz2::read::XzDecoder::new(decoder)), Snappy => Box::new(snap::read::FrameDecoder::new(decoder)), @@ -111,7 +117,7 @@ pub fn list_archive_contents( } } - Box::new(sevenz::list_archive(archive_path, password)?) + Box::new(archive::sevenz::list_archive(archive_path, password)?) } Gzip | Bzip | Bzip3 | Lz4 | Lzma | Snappy | Zstd | Brotli => { panic!("Not an archive! This should never happen, if it does, something is wrong with `CompressionFormat::is_archive()`. Please report this error!"); diff --git a/src/error.rs b/src/error.rs index 3f5bc3e..b3c33df 100644 --- a/src/error.rs +++ b/src/error.rs @@ -200,6 +200,7 @@ impl From for Error { } } +#[cfg(feature = "bzip3")] impl From for Error { fn from(err: bzip3::Error) -> Self { use bzip3::Error as Bz3Error; diff --git a/src/extension.rs b/src/extension.rs index 7250a57..55cdc58 100644 --- a/src/extension.rs +++ b/src/extension.rs @@ -286,7 +286,7 @@ mod tests { #[test] /// Test extension parsing for input/output files fn test_separate_known_extensions_from_name() { - let _handler = spawn_logger_thread(); + spawn_logger_thread(); assert_eq!( separate_known_extensions_from_name("file".as_ref()), ("file".as_ref(), vec![]) diff --git a/src/utils/fs.rs b/src/utils/fs.rs index eb40625..f65f152 100644 --- a/src/utils/fs.rs +++ b/src/utils/fs.rs @@ -133,7 +133,7 @@ pub fn try_infer_extension(path: &Path) -> Option { buf.starts_with(&[0x42, 0x5A, 0x68]) } fn is_bz3(buf: &[u8]) -> bool { - buf.starts_with(bzip3::MAGIC_NUMBER) + buf.starts_with(b"BZ3v1") } fn is_xz(buf: &[u8]) -> bool { buf.starts_with(&[0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00]) diff --git a/tests/integration.rs b/tests/integration.rs index f85e254..7536b15 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -25,6 +25,7 @@ enum DirectoryExtension { Tar, Tbz, Tbz2, + #[cfg(feature = "bzip3")] Tbz3, Tgz, Tlz4, @@ -41,6 +42,7 @@ enum DirectoryExtension { enum FileExtension { Bz, Bz2, + #[cfg(feature = "bzip3")] Bz3, Gz, Lz4, @@ -59,9 +61,9 @@ enum Extension { } /// Converts a list of extension structs to string -fn merge_extensions(ext: impl ToString, exts: &Vec) -> String { +fn merge_extensions(ext: impl ToString, exts: &[FileExtension]) -> String { once(ext.to_string()) - .chain(exts.into_iter().map(|x| x.to_string())) + .chain(exts.iter().map(|x| x.to_string())) .collect::>() .join(".") } @@ -89,6 +91,7 @@ fn create_random_files(dir: impl Into, depth: u8, rng: &mut SmallRng) { } /// Create n random files on directory dir +#[cfg_attr(not(feature = "allow_piped_choice"), allow(dead_code))] fn create_n_random_files(n: usize, dir: impl Into, rng: &mut SmallRng) { let dir: &PathBuf = &dir.into(); diff --git a/tests/ui.rs b/tests/ui.rs index 9492d1a..6df0794 100644 --- a/tests/ui.rs +++ b/tests/ui.rs @@ -2,7 +2,6 @@ /// /// See CONTRIBUTING.md for a brief guide on how to use [`insta`] for these tests. /// [`insta`]: https://docs.rs/insta - #[macro_use] mod utils;