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
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "pattern_matcher"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Extraction
|
|
7
|
+
# Combines multiple pattern matchers with AND/OR logic
|
|
8
|
+
#
|
|
9
|
+
# Supports include and exclude patterns, allowing complex
|
|
10
|
+
# filtering scenarios like "all .rb files except in test/".
|
|
11
|
+
class FilterChain
|
|
12
|
+
attr_reader :include_patterns, :exclude_patterns,
|
|
13
|
+
:include_predicates, :exclude_predicates
|
|
14
|
+
|
|
15
|
+
# Initialize a new filter chain
|
|
16
|
+
def initialize
|
|
17
|
+
@include_patterns = []
|
|
18
|
+
@exclude_patterns = []
|
|
19
|
+
@include_predicates = []
|
|
20
|
+
@exclude_predicates = []
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Add an include pattern
|
|
24
|
+
#
|
|
25
|
+
# @param pattern [String, Regexp, Proc] Pattern to include
|
|
26
|
+
# @return [self]
|
|
27
|
+
def include_pattern(pattern)
|
|
28
|
+
@include_patterns << PatternMatcher.new(pattern)
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Add an exclude pattern
|
|
33
|
+
#
|
|
34
|
+
# @param pattern [String, Regexp, Proc] Pattern to exclude
|
|
35
|
+
# @return [self]
|
|
36
|
+
def exclude_pattern(pattern)
|
|
37
|
+
@exclude_patterns << PatternMatcher.new(pattern)
|
|
38
|
+
self
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Add an include predicate
|
|
42
|
+
#
|
|
43
|
+
# @yield [entry] Entry to test
|
|
44
|
+
# @yieldreturn [Boolean] Whether to include entry
|
|
45
|
+
# @return [self]
|
|
46
|
+
def include(&predicate)
|
|
47
|
+
@include_predicates << predicate if predicate
|
|
48
|
+
self
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Add an exclude predicate
|
|
52
|
+
#
|
|
53
|
+
# @yield [entry] Entry to test
|
|
54
|
+
# @yieldreturn [Boolean] Whether to exclude entry
|
|
55
|
+
# @return [self]
|
|
56
|
+
def exclude(&predicate)
|
|
57
|
+
@exclude_predicates << predicate if predicate
|
|
58
|
+
self
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Check if an entry matches the filter chain
|
|
62
|
+
#
|
|
63
|
+
# Logic:
|
|
64
|
+
# - If no includes, everything passes (except excludes)
|
|
65
|
+
# - If includes exist, entry must match at least one include
|
|
66
|
+
# - Entry must not match any exclude
|
|
67
|
+
#
|
|
68
|
+
# @param entry [Object] Entry to check (filename or entry object)
|
|
69
|
+
# @param filename [String, nil] Explicit filename (if entry is object)
|
|
70
|
+
# @return [Boolean]
|
|
71
|
+
def match?(entry, filename: nil)
|
|
72
|
+
name = filename || extract_filename(entry)
|
|
73
|
+
|
|
74
|
+
# Check excludes first (faster to reject)
|
|
75
|
+
return false if excluded?(entry, name)
|
|
76
|
+
|
|
77
|
+
# Check includes
|
|
78
|
+
included?(entry, name)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Filter an array of entries
|
|
82
|
+
#
|
|
83
|
+
# @param entries [Array] Entries to filter
|
|
84
|
+
# @return [Array] Matching entries
|
|
85
|
+
def filter(entries)
|
|
86
|
+
entries.select { |entry| match?(entry) }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Check if chain has any conditions
|
|
90
|
+
#
|
|
91
|
+
# @return [Boolean]
|
|
92
|
+
def any?
|
|
93
|
+
!@include_patterns.empty? ||
|
|
94
|
+
!@exclude_patterns.empty? ||
|
|
95
|
+
!@include_predicates.empty? ||
|
|
96
|
+
!@exclude_predicates.empty?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Get count of all conditions
|
|
100
|
+
#
|
|
101
|
+
# @return [Integer]
|
|
102
|
+
def count
|
|
103
|
+
@include_patterns.size +
|
|
104
|
+
@exclude_patterns.size +
|
|
105
|
+
@include_predicates.size +
|
|
106
|
+
@exclude_predicates.size
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
|
|
111
|
+
# Check if entry is included
|
|
112
|
+
#
|
|
113
|
+
# @param entry [Object] Entry to check
|
|
114
|
+
# @param filename [String] Filename
|
|
115
|
+
# @return [Boolean]
|
|
116
|
+
def included?(entry, filename)
|
|
117
|
+
# If no include patterns/predicates, include by default
|
|
118
|
+
has_includes = !@include_patterns.empty? ||
|
|
119
|
+
!@include_predicates.empty?
|
|
120
|
+
return true unless has_includes
|
|
121
|
+
|
|
122
|
+
# Check if matches any include pattern
|
|
123
|
+
pattern_match = @include_patterns.any? do |matcher|
|
|
124
|
+
matcher.match?(filename)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Check if matches any include predicate
|
|
128
|
+
predicate_match = @include_predicates.any? do |predicate|
|
|
129
|
+
predicate.call(entry)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
pattern_match || predicate_match
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Check if entry is excluded
|
|
136
|
+
#
|
|
137
|
+
# @param entry [Object] Entry to check
|
|
138
|
+
# @param filename [String] Filename
|
|
139
|
+
# @return [Boolean]
|
|
140
|
+
def excluded?(entry, filename)
|
|
141
|
+
# Check if matches any exclude pattern
|
|
142
|
+
pattern_match = @exclude_patterns.any? do |matcher|
|
|
143
|
+
matcher.match?(filename)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Check if matches any exclude predicate
|
|
147
|
+
predicate_match = @exclude_predicates.any? do |predicate|
|
|
148
|
+
predicate.call(entry)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
pattern_match || predicate_match
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Extract filename from entry object
|
|
155
|
+
#
|
|
156
|
+
# @param entry [Object] Entry object or string
|
|
157
|
+
# @return [String]
|
|
158
|
+
def extract_filename(entry)
|
|
159
|
+
case entry
|
|
160
|
+
when String
|
|
161
|
+
entry
|
|
162
|
+
else
|
|
163
|
+
# Try common filename methods
|
|
164
|
+
if entry.respond_to?(:name)
|
|
165
|
+
entry.name
|
|
166
|
+
elsif entry.respond_to?(:path)
|
|
167
|
+
entry.path
|
|
168
|
+
elsif entry.respond_to?(:filename)
|
|
169
|
+
entry.filename
|
|
170
|
+
else
|
|
171
|
+
entry.to_s
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Extraction
|
|
5
|
+
# Implements glob pattern matching for file paths
|
|
6
|
+
#
|
|
7
|
+
# Supports:
|
|
8
|
+
# - * - Match any characters except /
|
|
9
|
+
# - ** - Match any characters including /
|
|
10
|
+
# - ? - Match single character
|
|
11
|
+
# - [abc] - Character class
|
|
12
|
+
# - [!abc] - Negated character class
|
|
13
|
+
# - {a,b,c} - Alternation (brace expansion)
|
|
14
|
+
class GlobPattern
|
|
15
|
+
attr_reader :pattern
|
|
16
|
+
|
|
17
|
+
# Initialize a new glob pattern
|
|
18
|
+
#
|
|
19
|
+
# @param pattern [String] Glob pattern string
|
|
20
|
+
def initialize(pattern)
|
|
21
|
+
@pattern = pattern.to_s
|
|
22
|
+
@regex = compile_pattern
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Check if a filename matches the pattern
|
|
26
|
+
#
|
|
27
|
+
# @param filename [String] Filename to check
|
|
28
|
+
# @return [Boolean]
|
|
29
|
+
def match?(filename)
|
|
30
|
+
@regex.match?(filename.to_s)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Convert pattern to string
|
|
34
|
+
#
|
|
35
|
+
# @return [String]
|
|
36
|
+
def to_s
|
|
37
|
+
@pattern
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# Compile glob pattern to regex
|
|
43
|
+
#
|
|
44
|
+
# @return [Regexp]
|
|
45
|
+
def compile_pattern
|
|
46
|
+
# Convert glob to regex (handles braces internally)
|
|
47
|
+
regex_pattern = glob_to_regex(@pattern)
|
|
48
|
+
|
|
49
|
+
# Compile with case-insensitive flag on case-insensitive filesystems
|
|
50
|
+
Regexp.new("\\A#{regex_pattern}\\z", case_sensitive? ? 0 : Regexp::IGNORECASE)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Convert glob pattern to regex
|
|
54
|
+
#
|
|
55
|
+
# @param pattern [String] Glob pattern
|
|
56
|
+
# @return [String] Regex pattern
|
|
57
|
+
def glob_to_regex(pattern)
|
|
58
|
+
result = +""
|
|
59
|
+
i = 0
|
|
60
|
+
|
|
61
|
+
while i < pattern.length
|
|
62
|
+
char = pattern[i]
|
|
63
|
+
|
|
64
|
+
case char
|
|
65
|
+
when "*"
|
|
66
|
+
if pattern[i + 1] == "*"
|
|
67
|
+
# ** matches everything including /
|
|
68
|
+
result << ".*"
|
|
69
|
+
i += 1
|
|
70
|
+
# Skip following / if present (**/foo)
|
|
71
|
+
i += 1 if pattern[i + 1] == "/"
|
|
72
|
+
else
|
|
73
|
+
# * matches everything except /
|
|
74
|
+
result << "[^/]*"
|
|
75
|
+
end
|
|
76
|
+
when "?"
|
|
77
|
+
# ? matches single character except /
|
|
78
|
+
result << "[^/]"
|
|
79
|
+
when "["
|
|
80
|
+
# Character class
|
|
81
|
+
j = i + 1
|
|
82
|
+
j += 1 while j < pattern.length && pattern[j] != "]"
|
|
83
|
+
if j < pattern.length
|
|
84
|
+
class_content = pattern[(i + 1)...j]
|
|
85
|
+
result << if class_content.start_with?("!")
|
|
86
|
+
# Negated class [!abc]
|
|
87
|
+
"[^#{Regexp.escape(class_content[1..])}]"
|
|
88
|
+
else
|
|
89
|
+
# Normal class [abc]
|
|
90
|
+
"[#{Regexp.escape(class_content)}]"
|
|
91
|
+
end
|
|
92
|
+
i = j
|
|
93
|
+
else
|
|
94
|
+
# Unclosed bracket, treat as literal
|
|
95
|
+
result << Regexp.escape(char)
|
|
96
|
+
end
|
|
97
|
+
when "{"
|
|
98
|
+
# Brace expansion {a,b,c}
|
|
99
|
+
j = i + 1
|
|
100
|
+
j += 1 while j < pattern.length && pattern[j] != "}"
|
|
101
|
+
if j < pattern.length
|
|
102
|
+
alternatives = pattern[(i + 1)...j].split(",")
|
|
103
|
+
# Convert each alternative recursively
|
|
104
|
+
alt_patterns = alternatives.map { |alt| glob_to_regex(alt) }
|
|
105
|
+
result << "(?:#{alt_patterns.join('|')})"
|
|
106
|
+
i = j
|
|
107
|
+
else
|
|
108
|
+
# Unclosed brace, treat as literal
|
|
109
|
+
result << Regexp.escape(char)
|
|
110
|
+
end
|
|
111
|
+
when "/"
|
|
112
|
+
# Directory separator
|
|
113
|
+
result << "/"
|
|
114
|
+
else
|
|
115
|
+
# Literal character
|
|
116
|
+
result << Regexp.escape(char)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
i += 1
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
result
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Check if filesystem is case-sensitive
|
|
126
|
+
#
|
|
127
|
+
# @return [Boolean]
|
|
128
|
+
def case_sensitive?
|
|
129
|
+
# On macOS and Windows, filesystems are typically case-insensitive
|
|
130
|
+
# On Linux, they're typically case-sensitive
|
|
131
|
+
case RUBY_PLATFORM
|
|
132
|
+
when /darwin/, /mswin/, /mingw/, /cygwin/
|
|
133
|
+
false
|
|
134
|
+
else
|
|
135
|
+
true
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "glob_pattern"
|
|
4
|
+
require_relative "regex_pattern"
|
|
5
|
+
require_relative "predicate_pattern"
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
module Extraction
|
|
9
|
+
# Coordinates pattern matching across different pattern types
|
|
10
|
+
#
|
|
11
|
+
# Automatically detects pattern type and delegates to appropriate
|
|
12
|
+
# pattern implementation (glob, regex, or predicate).
|
|
13
|
+
class PatternMatcher
|
|
14
|
+
# Initialize a new pattern matcher
|
|
15
|
+
#
|
|
16
|
+
# @param pattern [String, Regexp, Proc, Object] Pattern to match
|
|
17
|
+
def initialize(pattern)
|
|
18
|
+
@pattern = build_pattern(pattern)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Check if a filename matches the pattern
|
|
22
|
+
#
|
|
23
|
+
# @param filename [String] Filename to check
|
|
24
|
+
# @return [Boolean]
|
|
25
|
+
def match?(filename)
|
|
26
|
+
@pattern.match?(filename)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Match against multiple filenames
|
|
30
|
+
#
|
|
31
|
+
# @param filenames [Array<String>] Filenames to check
|
|
32
|
+
# @return [Array<String>] Matching filenames
|
|
33
|
+
def match_all(filenames)
|
|
34
|
+
filenames.select { |filename| match?(filename) }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Get the underlying pattern object
|
|
38
|
+
#
|
|
39
|
+
# @return [GlobPattern, RegexPattern, PredicatePattern]
|
|
40
|
+
attr_reader :pattern
|
|
41
|
+
|
|
42
|
+
# Convert pattern to string
|
|
43
|
+
#
|
|
44
|
+
# @return [String]
|
|
45
|
+
def to_s
|
|
46
|
+
@pattern.to_s
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
# Build appropriate pattern object from input
|
|
52
|
+
#
|
|
53
|
+
# @param pattern [Object] Input pattern
|
|
54
|
+
# @return [GlobPattern, RegexPattern, PredicatePattern]
|
|
55
|
+
def build_pattern(pattern)
|
|
56
|
+
case pattern
|
|
57
|
+
when Regexp
|
|
58
|
+
RegexPattern.new(pattern)
|
|
59
|
+
when Proc
|
|
60
|
+
PredicatePattern.new("custom predicate", &pattern)
|
|
61
|
+
when GlobPattern, RegexPattern, PredicatePattern
|
|
62
|
+
pattern
|
|
63
|
+
else
|
|
64
|
+
# Assume string glob pattern
|
|
65
|
+
GlobPattern.new(pattern.to_s)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Extraction
|
|
5
|
+
# Implements custom predicate pattern matching for archive entries
|
|
6
|
+
#
|
|
7
|
+
# Allows using arbitrary Ruby blocks to determine if an entry matches.
|
|
8
|
+
class PredicatePattern
|
|
9
|
+
attr_reader :predicate, :description
|
|
10
|
+
|
|
11
|
+
# Initialize a new predicate pattern
|
|
12
|
+
#
|
|
13
|
+
# @param description [String] Human-readable description
|
|
14
|
+
# @param predicate [Proc] Block that tests entries
|
|
15
|
+
# @yield [entry] Entry to test
|
|
16
|
+
# @yieldreturn [Boolean] Whether entry matches
|
|
17
|
+
def initialize(description = "custom predicate", &predicate)
|
|
18
|
+
raise ArgumentError, "Block required" unless predicate
|
|
19
|
+
|
|
20
|
+
@description = description
|
|
21
|
+
@predicate = predicate
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Check if an entry matches the predicate
|
|
25
|
+
#
|
|
26
|
+
# @param entry [Object] Entry to check (can be filename or entry object)
|
|
27
|
+
# @return [Boolean]
|
|
28
|
+
def match?(entry)
|
|
29
|
+
@predicate.call(entry)
|
|
30
|
+
rescue StandardError => e
|
|
31
|
+
# If predicate raises error, treat as non-match
|
|
32
|
+
warn "Predicate error for #{entry}: #{e.message}"
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Convert pattern to string
|
|
37
|
+
#
|
|
38
|
+
# @return [String]
|
|
39
|
+
def to_s
|
|
40
|
+
@description
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Call the predicate directly
|
|
44
|
+
#
|
|
45
|
+
# @param entry [Object] Entry to check
|
|
46
|
+
# @return [Boolean]
|
|
47
|
+
def call(entry)
|
|
48
|
+
match?(entry)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Extraction
|
|
5
|
+
# Implements regex pattern matching for file paths
|
|
6
|
+
#
|
|
7
|
+
# Wraps Ruby Regexp objects to provide consistent interface
|
|
8
|
+
# with other pattern types.
|
|
9
|
+
class RegexPattern
|
|
10
|
+
attr_reader :pattern
|
|
11
|
+
|
|
12
|
+
# Initialize a new regex pattern
|
|
13
|
+
#
|
|
14
|
+
# @param pattern [Regexp, String] Regex pattern
|
|
15
|
+
def initialize(pattern)
|
|
16
|
+
@pattern = pattern.is_a?(Regexp) ? pattern : Regexp.new(pattern)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Check if a filename matches the pattern
|
|
20
|
+
#
|
|
21
|
+
# @param filename [String] Filename to check
|
|
22
|
+
# @return [Boolean]
|
|
23
|
+
def match?(filename)
|
|
24
|
+
@pattern.match?(filename.to_s)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Get match data for a filename
|
|
28
|
+
#
|
|
29
|
+
# @param filename [String] Filename to check
|
|
30
|
+
# @return [MatchData, nil]
|
|
31
|
+
def match(filename)
|
|
32
|
+
@pattern.match(filename.to_s)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Convert pattern to string
|
|
36
|
+
#
|
|
37
|
+
# @return [String]
|
|
38
|
+
def to_s
|
|
39
|
+
@pattern.source
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Get the underlying regex
|
|
43
|
+
#
|
|
44
|
+
# @return [Regexp]
|
|
45
|
+
def to_regexp
|
|
46
|
+
@pattern
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|