omnizip 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +32 -0
- data/.rubocop_todo.yml +754 -0
- data/COPYING +502 -0
- data/Gemfile +17 -0
- data/LICENSE +12 -0
- data/README.adoc +1045 -0
- data/Rakefile +12 -0
- data/benchmark/README.md +260 -0
- data/benchmark/benchmark_suite.rb +125 -0
- data/benchmark/compression_bench.rb +181 -0
- data/benchmark/filter_bench.rb +180 -0
- data/benchmark/models/benchmark_result.rb +59 -0
- data/benchmark/models/comparison_result.rb +69 -0
- data/benchmark/profile_suite.rb +167 -0
- data/benchmark/reporter.rb +150 -0
- data/benchmark/run_benchmarks.rb +66 -0
- data/benchmark/test_data.rb +137 -0
- data/config/formats/rar3_spec.yml +91 -0
- data/config/formats/rar5_spec.yml +102 -0
- data/docs/.github/workflows/docs.yml +142 -0
- data/docs/.gitignore +21 -0
- data/docs/.lychee.toml +67 -0
- data/docs/Gemfile +13 -0
- data/docs/RAR_WRITE_SUPPORT.md +26 -0
- data/docs/README.md +101 -0
- data/docs/_config.yml +112 -0
- data/docs/assets/logo.svg +1 -0
- data/docs/assets/omnizip-logo.pdf +1540 -11
- data/docs/comparison/feature-matrix.adoc +694 -0
- data/docs/comparison/index.adoc +113 -0
- data/docs/comparison/vs-7zip.adoc +309 -0
- data/docs/comparison/vs-peazip.adoc +77 -0
- data/docs/comparison/vs-rubyzip.adoc +342 -0
- data/docs/comparison/vs-winrar.adoc +100 -0
- data/docs/compatibility.adoc +579 -0
- data/docs/concepts/index.adoc +129 -0
- data/docs/developer/architecture.adoc +256 -0
- data/docs/developer/contributing.adoc +158 -0
- data/docs/developer/index.adoc +25 -0
- data/docs/developer/testing.adoc +212 -0
- data/docs/getting-started/basic-usage.adoc +271 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +185 -0
- data/docs/getting-started/your-first-archive.adoc +218 -0
- data/docs/guides/advanced-features/encryption.adoc +300 -0
- data/docs/guides/advanced-features/index.adoc +49 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
- data/docs/guides/advanced-features/streaming.adoc +212 -0
- data/docs/guides/archive-formats/gzip-format.adoc +107 -0
- data/docs/guides/archive-formats/index.adoc +130 -0
- data/docs/guides/archive-formats/rar-format.adoc +104 -0
- data/docs/guides/archive-formats/rar5.adoc +521 -0
- data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
- data/docs/guides/archive-formats/tar-format.adoc +106 -0
- data/docs/guides/archive-formats/xz-format.adoc +118 -0
- data/docs/guides/archive-formats/zip-format.adoc +35 -0
- data/docs/guides/compression-algorithms/bzip2.adoc +113 -0
- data/docs/guides/compression-algorithms/deflate.adoc +319 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +398 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
- data/docs/guides/creating-archives.adoc +354 -0
- data/docs/guides/extracting-archives.adoc +53 -0
- data/docs/guides/format-conversion.adoc +64 -0
- data/docs/guides/index.adoc +49 -0
- data/docs/guides/migration-rubyzip.adoc +217 -0
- data/docs/guides/parity-archives.adoc +605 -0
- data/docs/guides/performance-tuning.adoc +88 -0
- data/docs/index.adoc +218 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +188 -0
- data/docs/reference/cli/compress-command.adoc +114 -0
- data/docs/reference/cli/overview.adoc +140 -0
- data/docs/reference/index.adoc +26 -0
- data/docs/resources/faq.adoc +185 -0
- data/docs/resources/quick-reference.adoc +222 -0
- data/docs/troubleshooting/index.adoc +208 -0
- data/examples/api_comparison.rb +205 -0
- data/examples/deflate64_example.rb +96 -0
- data/examples/par2_demo.rb +121 -0
- data/examples/quick_start_native.rb +150 -0
- data/examples/quick_start_rubyzip.rb +115 -0
- data/examples/rubyzip_compatibility_demo.rb +194 -0
- data/exe/omnizip +27 -0
- data/lib/omnizip/algorithm.rb +130 -0
- data/lib/omnizip/algorithm_registry.rb +86 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
- data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
- data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
- data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
- data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
- data/lib/omnizip/algorithms/bzip2.rb +130 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
- data/lib/omnizip/algorithms/deflate.rb +128 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
- data/lib/omnizip/algorithms/deflate64.rb +109 -0
- data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
- data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
- data/lib/omnizip/algorithms/lzma/decoder.rb +148 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -0
- data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
- data/lib/omnizip/algorithms/lzma/match.rb +32 -0
- data/lib/omnizip/algorithms/lzma/match_finder.rb +205 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
- data/lib/omnizip/algorithms/lzma.rb +238 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +141 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +116 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +82 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
- data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
- data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
- data/lib/omnizip/algorithms/zstandard.rb +138 -0
- data/lib/omnizip/buffer/memory_archive.rb +251 -0
- data/lib/omnizip/buffer/memory_extractor.rb +224 -0
- data/lib/omnizip/buffer.rb +176 -0
- data/lib/omnizip/checksum_registry.rb +114 -0
- data/lib/omnizip/checksums/crc32.rb +100 -0
- data/lib/omnizip/checksums/crc64.rb +101 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/verifier.rb +131 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +120 -0
- data/lib/omnizip/chunked.rb +129 -0
- data/lib/omnizip/cli/output_formatter.rb +104 -0
- data/lib/omnizip/cli.rb +572 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +427 -0
- data/lib/omnizip/commands/archive_extract_command.rb +272 -0
- data/lib/omnizip/commands/archive_list_command.rb +218 -0
- data/lib/omnizip/commands/archive_repair_command.rb +131 -0
- data/lib/omnizip/commands/archive_verify_command.rb +117 -0
- data/lib/omnizip/commands/compress_command.rb +117 -0
- data/lib/omnizip/commands/decompress_command.rb +120 -0
- data/lib/omnizip/commands/list_command.rb +53 -0
- data/lib/omnizip/commands/metadata_command.rb +153 -0
- data/lib/omnizip/commands/parity_create_command.rb +122 -0
- data/lib/omnizip/commands/parity_repair_command.rb +122 -0
- data/lib/omnizip/commands/parity_verify_command.rb +124 -0
- data/lib/omnizip/commands/profile_list_command.rb +56 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/convenience.rb +359 -0
- data/lib/omnizip/converter/conversion_registry.rb +49 -0
- data/lib/omnizip/converter/conversion_strategy.rb +121 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
- data/lib/omnizip/converter.rb +105 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/error.rb +106 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +99 -0
- data/lib/omnizip/eta/rate_calculator.rb +104 -0
- data/lib/omnizip/eta/sample_history.rb +143 -0
- data/lib/omnizip/eta/time_estimator.rb +106 -0
- data/lib/omnizip/eta.rb +63 -0
- data/lib/omnizip/extraction/filter_chain.rb +177 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +70 -0
- data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
- data/lib/omnizip/extraction/regex_pattern.rb +50 -0
- data/lib/omnizip/extraction/selective_extractor.rb +240 -0
- data/lib/omnizip/extraction.rb +111 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +113 -0
- data/lib/omnizip/filter.rb +139 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +166 -0
- data/lib/omnizip/filters/bcj.rb +279 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
- data/lib/omnizip/filters/bcj2.rb +99 -0
- data/lib/omnizip/filters/bcj_arm.rb +176 -0
- data/lib/omnizip/filters/bcj_arm64.rb +244 -0
- data/lib/omnizip/filters/bcj_ia64.rb +196 -0
- data/lib/omnizip/filters/bcj_ppc.rb +190 -0
- data/lib/omnizip/filters/bcj_sparc.rb +176 -0
- data/lib/omnizip/filters/bcj_x86.rb +193 -0
- data/lib/omnizip/filters/delta.rb +196 -0
- data/lib/omnizip/filters/filter_base.rb +72 -0
- data/lib/omnizip/filters/registry.rb +123 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/format_detector.rb +162 -0
- data/lib/omnizip/format_registry.rb +59 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +172 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +385 -0
- data/lib/omnizip/formats/cpio/reader.rb +196 -0
- data/lib/omnizip/formats/cpio/writer.rb +234 -0
- data/lib/omnizip/formats/cpio.rb +140 -0
- data/lib/omnizip/formats/format_spec_loader.rb +230 -0
- data/lib/omnizip/formats/gzip.rb +238 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
- data/lib/omnizip/formats/iso/directory_record.rb +152 -0
- data/lib/omnizip/formats/iso/joliet.rb +204 -0
- data/lib/omnizip/formats/iso/path_table.rb +125 -0
- data/lib/omnizip/formats/iso/reader.rb +197 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +530 -0
- data/lib/omnizip/formats/iso.rb +140 -0
- data/lib/omnizip/formats/lzip.rb +175 -0
- data/lib/omnizip/formats/lzma_alone.rb +171 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
- data/lib/omnizip/formats/rar/block_parser.rb +243 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +105 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +82 -0
- data/lib/omnizip/formats/rar/decompressor.rb +238 -0
- data/lib/omnizip/formats/rar/external_writer.rb +312 -0
- data/lib/omnizip/formats/rar/header.rb +192 -0
- data/lib/omnizip/formats/rar/license_validator.rb +109 -0
- data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
- data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
- data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +292 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -0
- data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
- data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
- data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +187 -0
- data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +264 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +194 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
- data/lib/omnizip/formats/rar/reader.rb +366 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
- data/lib/omnizip/formats/rar/writer.rb +431 -0
- data/lib/omnizip/formats/rar.rb +205 -0
- data/lib/omnizip/formats/rar3/compressor.rb +73 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar3/reader.rb +386 -0
- data/lib/omnizip/formats/rar3/writer.rb +219 -0
- data/lib/omnizip/formats/rar5/compressor.rb +73 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar5/reader.rb +342 -0
- data/lib/omnizip/formats/rar5/writer.rb +214 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
- data/lib/omnizip/formats/seven_zip/header.rb +106 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
- data/lib/omnizip/formats/seven_zip.rb +93 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +94 -0
- data/lib/omnizip/formats/tar/header.rb +168 -0
- data/lib/omnizip/formats/tar/reader.rb +121 -0
- data/lib/omnizip/formats/tar/writer.rb +216 -0
- data/lib/omnizip/formats/tar.rb +84 -0
- data/lib/omnizip/formats/xz/reader.rb +116 -0
- data/lib/omnizip/formats/xz.rb +237 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
- data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
- data/lib/omnizip/formats/zip/reader.rb +250 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +375 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
- data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
- data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
- data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
- data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +421 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
- data/lib/omnizip/io/buffered_input.rb +146 -0
- data/lib/omnizip/io/buffered_output.rb +105 -0
- data/lib/omnizip/io/stream_manager.rb +115 -0
- data/lib/omnizip/link_handler/hard_link.rb +79 -0
- data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
- data/lib/omnizip/link_handler.rb +124 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +146 -0
- data/lib/omnizip/metadata/metadata_editor.rb +171 -0
- data/lib/omnizip/metadata/metadata_registry.rb +64 -0
- data/lib/omnizip/metadata/metadata_validator.rb +99 -0
- data/lib/omnizip/metadata.rb +57 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +73 -0
- data/lib/omnizip/models/compression_options.rb +71 -0
- data/lib/omnizip/models/conversion_options.rb +87 -0
- data/lib/omnizip/models/conversion_result.rb +135 -0
- data/lib/omnizip/models/eta_result.rb +46 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +144 -0
- data/lib/omnizip/models/filter_config.rb +183 -0
- data/lib/omnizip/models/match_result.rb +124 -0
- data/lib/omnizip/models/optimization_suggestion.rb +91 -0
- data/lib/omnizip/models/parallel_options.rb +104 -0
- data/lib/omnizip/models/performance_result.rb +79 -0
- data/lib/omnizip/models/profile_report.rb +82 -0
- data/lib/omnizip/models/progress_options.rb +38 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +81 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +203 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
- data/lib/omnizip/parallel/worker_pool.rb +223 -0
- data/lib/omnizip/parallel.rb +149 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +73 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
- data/lib/omnizip/parity/models/main_packet.rb +128 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +109 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
- data/lib/omnizip/parity/par2_creator.rb +531 -0
- data/lib/omnizip/parity/par2_repairer.rb +407 -0
- data/lib/omnizip/parity/par2_verifier.rb +364 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
- data/lib/omnizip/parity.rb +186 -0
- data/lib/omnizip/password/encryption_registry.rb +65 -0
- data/lib/omnizip/password/encryption_strategy.rb +96 -0
- data/lib/omnizip/password/password_validator.rb +129 -0
- data/lib/omnizip/password/winzip_aes_strategy.rb +192 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
- data/lib/omnizip/password.rb +87 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
- data/lib/omnizip/pipe.rb +121 -0
- data/lib/omnizip/platform/ntfs_streams.rb +201 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +39 -0
- data/lib/omnizip/profile/balanced_profile.rb +33 -0
- data/lib/omnizip/profile/binary_profile.rb +36 -0
- data/lib/omnizip/profile/compression_profile.rb +158 -0
- data/lib/omnizip/profile/custom_profile.rb +157 -0
- data/lib/omnizip/profile/fast_profile.rb +33 -0
- data/lib/omnizip/profile/maximum_profile.rb +33 -0
- data/lib/omnizip/profile/profile_detector.rb +110 -0
- data/lib/omnizip/profile/profile_registry.rb +161 -0
- data/lib/omnizip/profile/text_profile.rb +36 -0
- data/lib/omnizip/profile.rb +190 -0
- data/lib/omnizip/profiler/memory_profiler.rb +66 -0
- data/lib/omnizip/profiler/method_profiler.rb +49 -0
- data/lib/omnizip/profiler/report_generator.rb +169 -0
- data/lib/omnizip/profiler.rb +204 -0
- data/lib/omnizip/progress/callback_reporter.rb +36 -0
- data/lib/omnizip/progress/console_reporter.rb +62 -0
- data/lib/omnizip/progress/log_reporter.rb +91 -0
- data/lib/omnizip/progress/operation_progress.rb +118 -0
- data/lib/omnizip/progress/progress_bar.rb +156 -0
- data/lib/omnizip/progress/progress_reporter.rb +40 -0
- data/lib/omnizip/progress/progress_tracker.rb +190 -0
- data/lib/omnizip/progress/silent_reporter.rb +24 -0
- data/lib/omnizip/progress.rb +127 -0
- data/lib/omnizip/rubyzip_compat.rb +63 -0
- data/lib/omnizip/temp/safe_extract.rb +168 -0
- data/lib/omnizip/temp/temp_file.rb +124 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +181 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +156 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +273 -0
- data/lib/omnizip/zip/output_stream.rb +324 -0
- data/lib/omnizip.rb +156 -0
- data/readme-docs/advanced-features.adoc +515 -0
- data/readme-docs/api-usage.adoc +444 -0
- data/readme-docs/architecture.adoc +449 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +442 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +325 -0
- data/readme-docs/installation.adoc +228 -0
- data/readme-docs/par2-archives.adoc +608 -0
- data/readme-docs/performance-profiler.adoc +389 -0
- data/readme-docs/preprocessing-filters.adoc +280 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +617 -0
data/lib/omnizip/cli.rb
ADDED
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2024 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of Omnizip.
|
|
7
|
+
#
|
|
8
|
+
# Omnizip is a pure Ruby port of 7-Zip compression algorithms.
|
|
9
|
+
# Based on the 7-Zip LZMA SDK by Igor Pavlov.
|
|
10
|
+
#
|
|
11
|
+
# This library is free software; you can redistribute it and/or
|
|
12
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
# License as published by the Free Software Foundation; either
|
|
14
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# See the COPYING file for the complete text of the license.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
require "thor"
|
|
20
|
+
require_relative "commands/compress_command"
|
|
21
|
+
require_relative "commands/decompress_command"
|
|
22
|
+
require_relative "commands/list_command"
|
|
23
|
+
require_relative "commands/archive_create_command"
|
|
24
|
+
require_relative "commands/archive_extract_command"
|
|
25
|
+
require_relative "commands/archive_list_command"
|
|
26
|
+
require_relative "commands/profile_list_command"
|
|
27
|
+
require_relative "commands/profile_show_command"
|
|
28
|
+
require_relative "commands/metadata_command"
|
|
29
|
+
require_relative "commands/archive_verify_command"
|
|
30
|
+
require_relative "commands/archive_repair_command"
|
|
31
|
+
require_relative "cli/output_formatter"
|
|
32
|
+
|
|
33
|
+
module Omnizip
|
|
34
|
+
# Profile commands subcommand group
|
|
35
|
+
class ProfileCommands < Thor
|
|
36
|
+
class << self
|
|
37
|
+
def exit_on_failure?
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
desc "list", "List available compression profiles"
|
|
43
|
+
long_desc <<~DESC
|
|
44
|
+
List all available compression profiles with their descriptions.
|
|
45
|
+
|
|
46
|
+
Examples:
|
|
47
|
+
|
|
48
|
+
$ omnizip profile list
|
|
49
|
+
|
|
50
|
+
$ omnizip profile list --verbose
|
|
51
|
+
DESC
|
|
52
|
+
option :verbose, type: :boolean, default: false,
|
|
53
|
+
aliases: "-v",
|
|
54
|
+
desc: "Show detailed information"
|
|
55
|
+
def list
|
|
56
|
+
Omnizip::Commands::ProfileListCommand.new(options).run
|
|
57
|
+
rescue StandardError => e
|
|
58
|
+
handle_error(e)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
desc "show PROFILE", "Show profile details"
|
|
62
|
+
long_desc <<~DESC
|
|
63
|
+
Show detailed information about a specific compression profile.
|
|
64
|
+
|
|
65
|
+
PROFILE is the name of the profile to show.
|
|
66
|
+
|
|
67
|
+
Examples:
|
|
68
|
+
|
|
69
|
+
$ omnizip profile show maximum
|
|
70
|
+
|
|
71
|
+
$ omnizip profile show fast
|
|
72
|
+
DESC
|
|
73
|
+
def show(profile_name)
|
|
74
|
+
Omnizip::Commands::ProfileShowCommand.new(options).run(profile_name)
|
|
75
|
+
rescue StandardError => e
|
|
76
|
+
handle_error(e)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def handle_error(error)
|
|
82
|
+
warn Omnizip::CliOutputFormatter.format_error(error)
|
|
83
|
+
exit 1
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Archive commands subcommand group
|
|
88
|
+
class ArchiveCommands < Thor
|
|
89
|
+
class << self
|
|
90
|
+
def exit_on_failure?
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
desc "create OUTPUT INPUT...", "Create .7z or .rar archive"
|
|
96
|
+
long_desc <<~DESC
|
|
97
|
+
Create a .7z or .rar archive from files and directories.
|
|
98
|
+
|
|
99
|
+
OUTPUT is the path to the archive to create (.7z or .rar extension).
|
|
100
|
+
INPUT can be one or more files or directories to archive.
|
|
101
|
+
|
|
102
|
+
For split archives, OUTPUT should end with .001 (e.g., backup.7z.001).
|
|
103
|
+
|
|
104
|
+
RAR5 archives are created using pure Ruby (no external tools needed).
|
|
105
|
+
RAR5 currently supports individual files only (not directories).
|
|
106
|
+
|
|
107
|
+
Examples:
|
|
108
|
+
|
|
109
|
+
$ omnizip archive create archive.7z file1.txt file2.txt
|
|
110
|
+
|
|
111
|
+
$ omnizip archive create archive.7z dir/ --algorithm lzma2 \\
|
|
112
|
+
--level 9
|
|
113
|
+
|
|
114
|
+
$ omnizip archive create archive.7z file.txt --no-solid \\
|
|
115
|
+
--filters bcj_x86
|
|
116
|
+
|
|
117
|
+
$ omnizip archive create backup.7z.001 large_data/ --volume-size 100M
|
|
118
|
+
|
|
119
|
+
$ omnizip archive create backup.7z.001 files/ --volume-size 4.7GB
|
|
120
|
+
|
|
121
|
+
$ omnizip archive create archive.rar file1.txt file2.txt
|
|
122
|
+
|
|
123
|
+
$ omnizip archive create archive.rar data.txt --rar-compression lzma \\
|
|
124
|
+
--level 5 --include-mtime --include-crc32
|
|
125
|
+
|
|
126
|
+
$ omnizip archive create secure.rar data.txt --rar-compression lzma \\
|
|
127
|
+
--level 5 --password "SecurePass123!" --kdf-iterations 262144
|
|
128
|
+
|
|
129
|
+
$ omnizip archive create backup.rar files/ --rar-compression lzma \\
|
|
130
|
+
--level 5 --solid --multi-volume --volume-size 100M
|
|
131
|
+
|
|
132
|
+
$ omnizip archive create critical.rar data/ --rar-compression lzma \\
|
|
133
|
+
--level 5 --password "Secure2025!" --recovery --recovery-percent 10
|
|
134
|
+
DESC
|
|
135
|
+
option :format, type: :string,
|
|
136
|
+
desc: "Archive format (7z or rar, default: auto-detect from extension)"
|
|
137
|
+
option :profile, type: :string,
|
|
138
|
+
desc: "Compression profile (fast, balanced, maximum, text, binary, archive, auto)"
|
|
139
|
+
option :algorithm, type: :string, default: "lzma2",
|
|
140
|
+
desc: "Compression algorithm for 7z (lzma, lzma2, ppmd7, bzip2)"
|
|
141
|
+
option :level, type: :numeric, default: 5,
|
|
142
|
+
desc: "Compression level (1-9 for 7z, 1-5 for RAR5)"
|
|
143
|
+
option :solid, type: :boolean, default: true,
|
|
144
|
+
desc: "Use solid compression (default: true for 7z, false for RAR)"
|
|
145
|
+
option :filters, type: :string,
|
|
146
|
+
desc: "Filter chain for 7z (e.g., bcj_x86,delta)"
|
|
147
|
+
option :volume_size, type: :string,
|
|
148
|
+
desc: "Volume size for split archives (e.g., 100M, 650MB, 4.7GB)"
|
|
149
|
+
option :password, type: :string,
|
|
150
|
+
desc: "Password for encryption (7z: header encryption, RAR5: AES-256-CBC)"
|
|
151
|
+
option :encrypt_headers, type: :boolean, default: false,
|
|
152
|
+
desc: "Encrypt archive headers (7z only, hides filenames)"
|
|
153
|
+
option :preserve_ntfs_streams, type: :boolean, default: false,
|
|
154
|
+
desc: "Preserve NTFS alternate data streams (Windows only, 7z only)"
|
|
155
|
+
option :rar_version, type: :numeric, default: 5,
|
|
156
|
+
desc: "RAR version (4 or 5, default: 5 for pure Ruby)"
|
|
157
|
+
option :rar_compression, type: :string, default: "store",
|
|
158
|
+
desc: "RAR compression method (store, lzma, auto)"
|
|
159
|
+
option :include_mtime, type: :boolean, default: false,
|
|
160
|
+
desc: "Include modification time in RAR5 file headers"
|
|
161
|
+
option :include_crc32, type: :boolean, default: false,
|
|
162
|
+
desc: "Include CRC32 checksum in RAR5 file headers"
|
|
163
|
+
option :multi_volume, type: :boolean, default: false,
|
|
164
|
+
desc: "Create multi-volume RAR5 archive (requires --volume-size)"
|
|
165
|
+
option :volume_naming, type: :string, default: "part",
|
|
166
|
+
desc: "Volume naming pattern for RAR5 (part, volume, numeric)"
|
|
167
|
+
option :kdf_iterations, type: :numeric, default: 262_144,
|
|
168
|
+
desc: "PBKDF2 iterations for RAR5 encryption (65536-1048576, default: 262144)"
|
|
169
|
+
option :recovery, type: :boolean, default: false,
|
|
170
|
+
desc: "Generate PAR2 recovery records for RAR5"
|
|
171
|
+
option :recovery_percent, type: :numeric, default: 5,
|
|
172
|
+
desc: "PAR2 redundancy percentage for RAR5 (0-100, default: 5)"
|
|
173
|
+
option :verbose, type: :boolean, default: false,
|
|
174
|
+
aliases: "-v",
|
|
175
|
+
desc: "Enable verbose output"
|
|
176
|
+
def create(output, *inputs)
|
|
177
|
+
Omnizip::Commands::ArchiveCreateCommand.new(options).run(output, *inputs)
|
|
178
|
+
rescue StandardError => e
|
|
179
|
+
handle_error(e)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
desc "extract ARCHIVE [OUTPUT_DIR]", "Extract archive"
|
|
183
|
+
long_desc <<~DESC
|
|
184
|
+
Extract a .7z, .zip, or .rar archive to a directory.
|
|
185
|
+
|
|
186
|
+
ARCHIVE is the path to the archive to extract.
|
|
187
|
+
OUTPUT_DIR is the directory to extract to (default: current directory).
|
|
188
|
+
|
|
189
|
+
Pattern extraction options allow selective extraction of files.
|
|
190
|
+
|
|
191
|
+
Examples:
|
|
192
|
+
|
|
193
|
+
$ omnizip archive extract archive.zip
|
|
194
|
+
|
|
195
|
+
$ omnizip archive extract archive.zip output/ --verbose
|
|
196
|
+
|
|
197
|
+
$ omnizip archive extract archive.zip output/ --pattern '**/*.txt'
|
|
198
|
+
|
|
199
|
+
$ omnizip archive extract archive.zip output/ \\
|
|
200
|
+
--pattern '*.txt' --pattern '*.md'
|
|
201
|
+
|
|
202
|
+
$ omnizip archive extract archive.zip output/ \\
|
|
203
|
+
--pattern '**/*' --exclude '**/*.tmp' --exclude '**/test/**'
|
|
204
|
+
|
|
205
|
+
$ omnizip archive extract archive.zip output/ \\
|
|
206
|
+
--regex '\\.log$'
|
|
207
|
+
|
|
208
|
+
$ omnizip archive extract archive.zip output/ \\
|
|
209
|
+
--pattern 'src/**/*.rb' --flatten
|
|
210
|
+
DESC
|
|
211
|
+
option :verbose, type: :boolean, default: false,
|
|
212
|
+
aliases: "-v",
|
|
213
|
+
desc: "Enable verbose output"
|
|
214
|
+
option :pattern, type: :array,
|
|
215
|
+
desc: "Include pattern(s) for selective extraction"
|
|
216
|
+
option :exclude, type: :array,
|
|
217
|
+
desc: "Exclude pattern(s) for selective extraction"
|
|
218
|
+
option :regex, type: :string,
|
|
219
|
+
desc: "Regular expression pattern for selective extraction"
|
|
220
|
+
option :flatten, type: :boolean, default: false,
|
|
221
|
+
desc: "Extract all files to output root (ignore paths)"
|
|
222
|
+
option :count, type: :boolean, default: false,
|
|
223
|
+
desc: "Count matches without extracting"
|
|
224
|
+
def extract(archive, output_dir = nil)
|
|
225
|
+
Omnizip::Commands::ArchiveExtractCommand.new(options).run(archive,
|
|
226
|
+
output_dir)
|
|
227
|
+
rescue StandardError => e
|
|
228
|
+
handle_error(e)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
desc "list ARCHIVE", "List archive contents"
|
|
232
|
+
long_desc <<~DESC
|
|
233
|
+
List the contents of a .7z, .zip, or .rar archive.
|
|
234
|
+
|
|
235
|
+
ARCHIVE is the path to the archive to list.
|
|
236
|
+
|
|
237
|
+
Pattern filtering options allow listing only matching files.
|
|
238
|
+
|
|
239
|
+
Examples:
|
|
240
|
+
|
|
241
|
+
$ omnizip archive list archive.zip
|
|
242
|
+
|
|
243
|
+
$ omnizip archive list archive.zip --verbose
|
|
244
|
+
|
|
245
|
+
$ omnizip archive list archive.zip --pattern '**/*.rb'
|
|
246
|
+
|
|
247
|
+
$ omnizip archive list archive.zip --pattern '*.txt' --count
|
|
248
|
+
DESC
|
|
249
|
+
option :verbose, type: :boolean, default: false,
|
|
250
|
+
aliases: "-v",
|
|
251
|
+
desc: "Enable verbose output"
|
|
252
|
+
option :pattern, type: :array,
|
|
253
|
+
desc: "Include pattern(s) for filtering"
|
|
254
|
+
option :exclude, type: :array,
|
|
255
|
+
desc: "Exclude pattern(s) for filtering"
|
|
256
|
+
option :count, type: :boolean, default: false,
|
|
257
|
+
desc: "Show count of matches"
|
|
258
|
+
def list(archive)
|
|
259
|
+
Omnizip::Commands::ArchiveListCommand.new(options).run(archive)
|
|
260
|
+
rescue StandardError => e
|
|
261
|
+
handle_error(e)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
desc "metadata ARCHIVE [PATTERN]", "View or edit archive metadata"
|
|
265
|
+
long_desc <<~DESC
|
|
266
|
+
View or edit metadata for archives and entries.
|
|
267
|
+
|
|
268
|
+
ARCHIVE is the path to the archive.
|
|
269
|
+
PATTERN is an optional entry name or glob pattern.
|
|
270
|
+
|
|
271
|
+
Examples:
|
|
272
|
+
|
|
273
|
+
# View archive metadata
|
|
274
|
+
$ omnizip archive metadata archive.zip --show
|
|
275
|
+
|
|
276
|
+
# View entry metadata
|
|
277
|
+
$ omnizip archive metadata archive.zip file.txt --show
|
|
278
|
+
|
|
279
|
+
# Set archive comment
|
|
280
|
+
$ omnizip archive metadata archive.zip --comment "My backup"
|
|
281
|
+
|
|
282
|
+
# Set entry comment
|
|
283
|
+
$ omnizip archive metadata archive.zip file.txt --comment "Important"
|
|
284
|
+
|
|
285
|
+
# Set modification time
|
|
286
|
+
$ omnizip archive metadata archive.zip file.txt --set-mtime now
|
|
287
|
+
|
|
288
|
+
# Set permissions
|
|
289
|
+
$ omnizip archive metadata archive.zip '*.rb' --chmod 755
|
|
290
|
+
DESC
|
|
291
|
+
option :show, type: :boolean, default: false,
|
|
292
|
+
desc: "Show metadata (read-only)"
|
|
293
|
+
option :comment, type: :string,
|
|
294
|
+
desc: "Set comment"
|
|
295
|
+
option :set_mtime, type: :string,
|
|
296
|
+
desc: "Set modification time (e.g., 'now', '2024-01-01')"
|
|
297
|
+
option :chmod, type: :string,
|
|
298
|
+
desc: "Set Unix permissions (e.g., '755', '0644')"
|
|
299
|
+
option :set_attribute, type: :string,
|
|
300
|
+
desc: "Set attribute flag (readonly, hidden, system, archive)"
|
|
301
|
+
option :verbose, type: :boolean, default: false,
|
|
302
|
+
aliases: "-v",
|
|
303
|
+
desc: "Enable verbose output"
|
|
304
|
+
def metadata(archive, pattern = nil)
|
|
305
|
+
Omnizip::Commands::MetadataCommand.new(options).run(archive, pattern)
|
|
306
|
+
rescue StandardError => e
|
|
307
|
+
handle_error(e)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
private
|
|
311
|
+
|
|
312
|
+
def handle_error(error)
|
|
313
|
+
warn Omnizip::CliOutputFormatter.format_error(error)
|
|
314
|
+
exit 1
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Command-line interface for Omnizip.
|
|
319
|
+
#
|
|
320
|
+
# Provides Thor-based CLI commands for compressing and decompressing
|
|
321
|
+
# files using various compression algorithms.
|
|
322
|
+
class Cli < Thor
|
|
323
|
+
class << self
|
|
324
|
+
def exit_on_failure?
|
|
325
|
+
true
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
desc "compress INPUT OUTPUT", "Compress a file or stream"
|
|
330
|
+
long_desc <<~DESC
|
|
331
|
+
Compress INPUT file and write the result to OUTPUT file.
|
|
332
|
+
|
|
333
|
+
Use '-' for INPUT to read from stdin or OUTPUT to write to stdout.
|
|
334
|
+
This enables Unix pipeline integration for streaming workflows.
|
|
335
|
+
|
|
336
|
+
The compression algorithm and level can be specified with options.
|
|
337
|
+
By default, LZMA compression is used with level 5.
|
|
338
|
+
|
|
339
|
+
Examples:
|
|
340
|
+
|
|
341
|
+
$ omnizip compress input.txt output.lzma
|
|
342
|
+
|
|
343
|
+
$ omnizip compress input.txt output.lzma --level 9 --verbose
|
|
344
|
+
|
|
345
|
+
$ cat input.txt | omnizip compress - output.zip --format zip
|
|
346
|
+
|
|
347
|
+
$ omnizip compress input.txt - --format zip > output.zip
|
|
348
|
+
|
|
349
|
+
$ cat data.txt | omnizip compress - - --format zip > out.zip
|
|
350
|
+
DESC
|
|
351
|
+
option :algorithm, type: :string, default: "lzma",
|
|
352
|
+
desc: "Compression algorithm to use"
|
|
353
|
+
option :format, type: :string, default: nil,
|
|
354
|
+
desc: "Archive format (zip, 7z) - enables pipe mode"
|
|
355
|
+
option :level, type: :numeric, default: 5,
|
|
356
|
+
desc: "Compression level (1-9)"
|
|
357
|
+
option :entry_name, type: :string, default: nil,
|
|
358
|
+
desc: "Entry name in archive (pipe mode only)"
|
|
359
|
+
option :verbose, type: :boolean, default: false,
|
|
360
|
+
aliases: "-v",
|
|
361
|
+
desc: "Enable verbose output"
|
|
362
|
+
def compress(input, output)
|
|
363
|
+
# Pipe mode: use streaming compression
|
|
364
|
+
if Omnizip::Pipe.stdin?(input) || Omnizip::Pipe.stdout?(output)
|
|
365
|
+
compress_pipe(input, output)
|
|
366
|
+
else
|
|
367
|
+
Commands::CompressCommand.new(options).run(input, output)
|
|
368
|
+
end
|
|
369
|
+
rescue StandardError => e
|
|
370
|
+
handle_error(e)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
desc "decompress INPUT OUTPUT", "Decompress a file or stream"
|
|
374
|
+
long_desc <<~DESC
|
|
375
|
+
Decompress INPUT file and write the result to OUTPUT file or directory.
|
|
376
|
+
|
|
377
|
+
Use '-' for INPUT to read from stdin. If OUTPUT is a directory,
|
|
378
|
+
extracts all files. If OUTPUT is '-', streams first file to stdout.
|
|
379
|
+
|
|
380
|
+
The algorithm will be auto-detected from the compressed file,
|
|
381
|
+
or can be explicitly specified with the --algorithm option.
|
|
382
|
+
|
|
383
|
+
Examples:
|
|
384
|
+
|
|
385
|
+
$ omnizip decompress output.lzma restored.txt
|
|
386
|
+
|
|
387
|
+
$ omnizip decompress output.lzma restored.txt --verbose
|
|
388
|
+
|
|
389
|
+
$ cat archive.zip | omnizip decompress - extracted/
|
|
390
|
+
|
|
391
|
+
$ omnizip decompress - - < archive.zip > output.txt
|
|
392
|
+
|
|
393
|
+
$ cat archive.zip | omnizip decompress - extracted/ --verbose
|
|
394
|
+
DESC
|
|
395
|
+
option :algorithm, type: :string,
|
|
396
|
+
desc: "Decompression algorithm (auto-detect if omitted)"
|
|
397
|
+
option :verbose, type: :boolean, default: false,
|
|
398
|
+
aliases: "-v",
|
|
399
|
+
desc: "Enable verbose output"
|
|
400
|
+
def decompress(input, output)
|
|
401
|
+
# Pipe mode: use streaming decompression
|
|
402
|
+
if Omnizip::Pipe.stdin?(input) || Omnizip::Pipe.stdout?(output)
|
|
403
|
+
decompress_pipe(input, output)
|
|
404
|
+
else
|
|
405
|
+
Commands::DecompressCommand.new(options).run(input, output)
|
|
406
|
+
end
|
|
407
|
+
rescue StandardError => e
|
|
408
|
+
handle_error(e)
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
desc "list", "List available compression algorithms"
|
|
412
|
+
long_desc <<~DESC
|
|
413
|
+
List all registered compression algorithms with their metadata.
|
|
414
|
+
|
|
415
|
+
Displays algorithm name, description, and version information.
|
|
416
|
+
|
|
417
|
+
Example:
|
|
418
|
+
|
|
419
|
+
$ omnizip list
|
|
420
|
+
DESC
|
|
421
|
+
option :verbose, type: :boolean, default: false,
|
|
422
|
+
aliases: "-v",
|
|
423
|
+
desc: "Enable verbose output"
|
|
424
|
+
def list
|
|
425
|
+
Commands::ListCommand.new(options).run
|
|
426
|
+
rescue StandardError => e
|
|
427
|
+
handle_error(e)
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
desc "version", "Display version information"
|
|
431
|
+
def version
|
|
432
|
+
puts "Omnizip v#{Omnizip::VERSION}"
|
|
433
|
+
puts "Pure Ruby implementation of LZMA compression"
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
desc "profile SUBCOMMAND ...ARGS", "Manage compression profiles"
|
|
437
|
+
subcommand "profile", ProfileCommands
|
|
438
|
+
|
|
439
|
+
desc "archive SUBCOMMAND ...ARGS", "Manage .7z archives"
|
|
440
|
+
subcommand "archive", ArchiveCommands
|
|
441
|
+
desc "convert SOURCE TARGET", "Convert archive between formats"
|
|
442
|
+
long_desc <<~DESC
|
|
443
|
+
Convert an archive from one format to another.
|
|
444
|
+
|
|
445
|
+
SOURCE is the path to the source archive (ZIP, 7z, or RAR).
|
|
446
|
+
TARGET is the path to the target archive (ZIP or 7z).
|
|
447
|
+
Note: RAR can only be a source (read-only), not a target.
|
|
448
|
+
|
|
449
|
+
Examples:
|
|
450
|
+
|
|
451
|
+
$ omnizip convert archive.zip archive.7z
|
|
452
|
+
|
|
453
|
+
$ omnizip convert archive.7z backup.zip
|
|
454
|
+
|
|
455
|
+
$ omnizip convert archive.zip archive.7z --compression lzma2 --level 9
|
|
456
|
+
|
|
457
|
+
$ omnizip convert archive.zip archive.7z --no-solid
|
|
458
|
+
DESC
|
|
459
|
+
option :compression, type: :string,
|
|
460
|
+
desc: "Compression algorithm (lzma, lzma2, ppmd7, bzip2)"
|
|
461
|
+
option :level, type: :numeric, default: 5,
|
|
462
|
+
desc: "Compression level (1-9)"
|
|
463
|
+
option :filter, type: :string,
|
|
464
|
+
desc: "Filter to apply (bcj-x86, delta, etc.)"
|
|
465
|
+
option :solid, type: :boolean, default: true,
|
|
466
|
+
desc: "Use solid compression for 7z (default: true)"
|
|
467
|
+
option :preserve_metadata, type: :boolean, default: true,
|
|
468
|
+
desc: "Preserve metadata (default: true)"
|
|
469
|
+
option :delete_source, type: :boolean, default: false,
|
|
470
|
+
desc: "Delete source after conversion"
|
|
471
|
+
option :verbose, type: :boolean, default: false,
|
|
472
|
+
aliases: "-v",
|
|
473
|
+
desc: "Enable verbose output"
|
|
474
|
+
def convert(source, target)
|
|
475
|
+
require_relative "converter"
|
|
476
|
+
|
|
477
|
+
puts "Converting #{source} to #{target}..." if options[:verbose]
|
|
478
|
+
|
|
479
|
+
result = Omnizip::Converter.convert(
|
|
480
|
+
source,
|
|
481
|
+
target,
|
|
482
|
+
compression: options[:compression]&.to_sym,
|
|
483
|
+
compression_level: options[:level],
|
|
484
|
+
filter: options[:filter]&.to_sym,
|
|
485
|
+
solid: options[:solid],
|
|
486
|
+
preserve_metadata: options[:preserve_metadata],
|
|
487
|
+
delete_source: options[:delete_source],
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
puts "Conversion complete!"
|
|
491
|
+
puts "Source: #{result.source_path} (#{format_bytes(result.source_size)})"
|
|
492
|
+
puts "Target: #{result.target_path} (#{format_bytes(result.target_size)})"
|
|
493
|
+
puts "Size change: #{result.size_reduction.round(1)}%"
|
|
494
|
+
puts "Duration: #{result.duration.round(2)}s"
|
|
495
|
+
puts "Entries: #{result.entry_count}"
|
|
496
|
+
|
|
497
|
+
if result.warnings?
|
|
498
|
+
puts "\nWarnings:"
|
|
499
|
+
result.warnings.each { |w| puts " - #{w}" }
|
|
500
|
+
end
|
|
501
|
+
rescue StandardError => e
|
|
502
|
+
handle_error(e)
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
map %w[-v --version] => :version
|
|
506
|
+
|
|
507
|
+
private
|
|
508
|
+
|
|
509
|
+
def compress_pipe(input, output)
|
|
510
|
+
input_io = input == "-" ? $stdin : File.open(input, "rb")
|
|
511
|
+
output_io = output == "-" ? $stdout : File.open(output, "wb")
|
|
512
|
+
|
|
513
|
+
format = (options[:format] || :zip).to_sym
|
|
514
|
+
compression = options[:algorithm]&.to_sym
|
|
515
|
+
entry_name = options[:entry_name] || File.basename(input == "-" ? "stream.dat" : input)
|
|
516
|
+
|
|
517
|
+
if options[:verbose]
|
|
518
|
+
warn "Compressing from #{input == '-' ? 'stdin' : input} to #{output == '-' ? 'stdout' : output}"
|
|
519
|
+
warn "Format: #{format}, Entry: #{entry_name}"
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
Omnizip::Pipe.compress(
|
|
523
|
+
input_io,
|
|
524
|
+
output_io,
|
|
525
|
+
format: format,
|
|
526
|
+
compression: compression,
|
|
527
|
+
entry_name: entry_name,
|
|
528
|
+
level: options[:level],
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
warn "Compression complete" if options[:verbose]
|
|
532
|
+
ensure
|
|
533
|
+
input_io.close if input_io && input != "-"
|
|
534
|
+
output_io.close if output_io && output != "-"
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def decompress_pipe(input, output)
|
|
538
|
+
input_io = input == "-" ? $stdin : File.open(input, "rb")
|
|
539
|
+
|
|
540
|
+
if options[:verbose]
|
|
541
|
+
warn "Decompressing from #{input == '-' ? 'stdin' : input}"
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
if output == "-"
|
|
545
|
+
# Stream to stdout
|
|
546
|
+
Omnizip::Pipe.decompress(input_io, output: $stdout)
|
|
547
|
+
else
|
|
548
|
+
# Extract to directory
|
|
549
|
+
Omnizip::Pipe.decompress(input_io, output_dir: output)
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
warn "Decompression complete" if options[:verbose]
|
|
553
|
+
ensure
|
|
554
|
+
input_io.close if input_io && input != "-"
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
def handle_error(error)
|
|
558
|
+
warn CliOutputFormatter.format_error(error)
|
|
559
|
+
exit 1
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def format_bytes(bytes)
|
|
563
|
+
return "0 B" if bytes.zero?
|
|
564
|
+
|
|
565
|
+
units = %w[B KB MB GB TB]
|
|
566
|
+
exp = (Math.log(bytes) / Math.log(1024)).to_i
|
|
567
|
+
exp = [exp, units.size - 1].min
|
|
568
|
+
|
|
569
|
+
"%.1f %s" % [bytes.to_f / (1024**exp), units[exp]]
|
|
570
|
+
end
|
|
571
|
+
end
|
|
572
|
+
end
|
|
File without changes
|