omnizip 0.4.7-arm-linux
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 +293 -0
- data/CHANGELOG.md +1647 -0
- data/CONTEXT.md +68 -0
- data/COPYING +502 -0
- data/Gemfile +19 -0
- data/LICENSE +12 -0
- data/README.adoc +1327 -0
- data/Rakefile +15 -0
- data/TODO.refactor/00-overview.md +67 -0
- data/TODO.refactor/01-registry-base-class.md +81 -0
- data/TODO.refactor/02-error-hierarchy.md +57 -0
- data/TODO.refactor/03-autoload-entry-point.md +69 -0
- data/TODO.refactor/04-filter-base-consolidation.md +49 -0
- data/TODO.refactor/05-send-private-methods.md +64 -0
- data/TODO.refactor/06-instance-variable-access.md +69 -0
- data/TODO.refactor/07-respond-to-replacement.md +237 -0
- data/TODO.refactor/08-spec-doubles.md +27 -0
- data/TODO.refactor/09-cli-shared-module.md +35 -0
- data/TODO.refactor/10-format-detector-ocp.md +34 -0
- data/TODO.refactor/11-convenience-decoupling.md +38 -0
- data/TODO.refactor/12-thread-safety.md +8 -0
- data/TODO.refactor/13-lutaml-model-migration.md +158 -0
- data/TODO.refactor/14-add-missing-specs.md +25 -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 +92 -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 +263 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +183 -0
- data/docs/getting-started/your-first-archive.adoc +219 -0
- data/docs/guides/advanced-features/encryption.adoc +277 -0
- data/docs/guides/advanced-features/index.adoc +59 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
- data/docs/guides/advanced-features/streaming.adoc +142 -0
- data/docs/guides/archive-formats/gzip-format.adoc +105 -0
- data/docs/guides/archive-formats/index.adoc +160 -0
- data/docs/guides/archive-formats/ole-format.adoc +151 -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/rpm-format.adoc +108 -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 +114 -0
- data/docs/guides/compression-algorithms/deflate.adoc +313 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +394 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
- data/docs/guides/creating-archives.adoc +348 -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 +228 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +187 -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/rust-backend.md +0 -0
- data/docs/troubleshooting/index.adoc +207 -0
- data/docs/xar_format.md +216 -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 +176 -0
- data/lib/omnizip/algorithm_registry.rb +65 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
- data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
- data/lib/omnizip/algorithms/bzip2.rb +108 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
- data/lib/omnizip/algorithms/deflate.rb +135 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
- data/lib/omnizip/algorithms/deflate64.rb +118 -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 +146 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
- data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -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 +233 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
- data/lib/omnizip/algorithms/lzma.rb +266 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +133 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +146 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +122 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
- data/lib/omnizip/algorithms/registration.rb +28 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
- data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
- data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
- data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
- data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
- data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
- data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
- data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
- data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +210 -0
- data/lib/omnizip/algorithms.rb +35 -0
- data/lib/omnizip/archive/builder.rb +48 -0
- data/lib/omnizip/archive/reader_session.rb +67 -0
- data/lib/omnizip/archive.rb +86 -0
- data/lib/omnizip/archive_handler.rb +82 -0
- data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
- data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
- data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
- data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
- data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
- data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
- data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
- data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
- data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
- data/lib/omnizip/archive_handlers.rb +18 -0
- data/lib/omnizip/backends.rb +160 -0
- data/lib/omnizip/buffer/memory_archive.rb +246 -0
- data/lib/omnizip/buffer/memory_extractor.rb +234 -0
- data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
- data/lib/omnizip/buffer.rb +187 -0
- data/lib/omnizip/checksum_registry.rb +41 -0
- data/lib/omnizip/checksums/crc32.rb +101 -0
- data/lib/omnizip/checksums/crc64.rb +102 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/registration.rb +16 -0
- data/lib/omnizip/checksums/verifier.rb +130 -0
- data/lib/omnizip/checksums.rb +11 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +123 -0
- data/lib/omnizip/chunked.rb +123 -0
- data/lib/omnizip/cli/output_formatter.rb +112 -0
- data/lib/omnizip/cli.rb +604 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +245 -0
- data/lib/omnizip/commands/archive_extract_command.rb +231 -0
- data/lib/omnizip/commands/archive_list_command.rb +204 -0
- data/lib/omnizip/commands/archive_repair_command.rb +129 -0
- data/lib/omnizip/commands/archive_verify_command.rb +115 -0
- data/lib/omnizip/commands/compress_command.rb +115 -0
- data/lib/omnizip/commands/decompress_command.rb +149 -0
- data/lib/omnizip/commands/list_command.rb +51 -0
- data/lib/omnizip/commands/metadata_command.rb +215 -0
- data/lib/omnizip/commands/parity_create_command.rb +114 -0
- data/lib/omnizip/commands/parity_repair_command.rb +120 -0
- data/lib/omnizip/commands/parity_verify_command.rb +122 -0
- data/lib/omnizip/commands/profile_list_command.rb +54 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/commands.rb +21 -0
- data/lib/omnizip/convenience.rb +389 -0
- data/lib/omnizip/converter/conversion_registry.rb +50 -0
- data/lib/omnizip/converter/conversion_strategy.rb +108 -0
- data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
- data/lib/omnizip/converter.rb +124 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/crypto.rb +11 -0
- data/lib/omnizip/entry.rb +44 -0
- data/lib/omnizip/error.rb +110 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +96 -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 +68 -0
- data/lib/omnizip/extraction/filter_chain.rb +179 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +66 -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 +247 -0
- data/lib/omnizip/extraction.rb +115 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +117 -0
- data/lib/omnizip/filter.rb +141 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +113 -0
- data/lib/omnizip/filters/bcj.rb +277 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
- data/lib/omnizip/filters/bcj2.rb +93 -0
- data/lib/omnizip/filters/bcj_arm.rb +174 -0
- data/lib/omnizip/filters/bcj_arm64.rb +242 -0
- data/lib/omnizip/filters/bcj_ia64.rb +194 -0
- data/lib/omnizip/filters/bcj_ppc.rb +188 -0
- data/lib/omnizip/filters/bcj_sparc.rb +174 -0
- data/lib/omnizip/filters/bcj_x86.rb +191 -0
- data/lib/omnizip/filters/delta.rb +195 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/filters.rb +20 -0
- data/lib/omnizip/format_detector.rb +166 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +159 -0
- data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +389 -0
- data/lib/omnizip/formats/cpio/reader.rb +194 -0
- data/lib/omnizip/formats/cpio/writer.rb +232 -0
- data/lib/omnizip/formats/cpio.rb +132 -0
- data/lib/omnizip/formats/format_spec_loader.rb +228 -0
- data/lib/omnizip/formats/gzip.rb +236 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
- data/lib/omnizip/formats/iso/directory_record.rb +162 -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 +194 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +543 -0
- data/lib/omnizip/formats/iso.rb +133 -0
- data/lib/omnizip/formats/lzip.rb +161 -0
- data/lib/omnizip/formats/lzma_alone.rb +149 -0
- data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
- data/lib/omnizip/formats/msi/constants.rb +157 -0
- data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
- data/lib/omnizip/formats/msi/entry.rb +134 -0
- data/lib/omnizip/formats/msi/reader.rb +301 -0
- data/lib/omnizip/formats/msi/string_pool.rb +246 -0
- data/lib/omnizip/formats/msi/table_parser.rb +244 -0
- data/lib/omnizip/formats/msi.rb +73 -0
- data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
- data/lib/omnizip/formats/ole/constants.rb +61 -0
- data/lib/omnizip/formats/ole/dirent.rb +439 -0
- data/lib/omnizip/formats/ole/header.rb +199 -0
- data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
- data/lib/omnizip/formats/ole/storage.rb +482 -0
- data/lib/omnizip/formats/ole/types/variant.rb +338 -0
- data/lib/omnizip/formats/ole.rb +143 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
- data/lib/omnizip/formats/rar/block_parser.rb +282 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -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/lz77_huffman.rb +25 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
- data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
- data/lib/omnizip/formats/rar/compression.rb +17 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +88 -0
- data/lib/omnizip/formats/rar/decompressor.rb +316 -0
- data/lib/omnizip/formats/rar/external_writer.rb +311 -0
- data/lib/omnizip/formats/rar/header.rb +209 -0
- data/lib/omnizip/formats/rar/license_validator.rb +111 -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/models.rb +14 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -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 +96 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +208 -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 +260 -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 +176 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
- data/lib/omnizip/formats/rar/reader.rb +377 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
- data/lib/omnizip/formats/rar/writer.rb +437 -0
- data/lib/omnizip/formats/rar.rb +193 -0
- data/lib/omnizip/formats/rar3/compressor.rb +71 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar3/reader.rb +107 -0
- data/lib/omnizip/formats/rar3/writer.rb +220 -0
- data/lib/omnizip/formats/rar3.rb +15 -0
- data/lib/omnizip/formats/rar5/compressor.rb +71 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar5/reader.rb +130 -0
- data/lib/omnizip/formats/rar5/writer.rb +65 -0
- data/lib/omnizip/formats/rar5.rb +15 -0
- data/lib/omnizip/formats/rpm/constants.rb +58 -0
- data/lib/omnizip/formats/rpm/entry.rb +106 -0
- data/lib/omnizip/formats/rpm/header.rb +106 -0
- data/lib/omnizip/formats/rpm/lead.rb +132 -0
- data/lib/omnizip/formats/rpm/tag.rb +228 -0
- data/lib/omnizip/formats/rpm/writer.rb +652 -0
- data/lib/omnizip/formats/rpm.rb +458 -0
- data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
- data/lib/omnizip/formats/seven_zip/header.rb +102 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/models.rb +20 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
- data/lib/omnizip/formats/seven_zip.rb +179 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +98 -0
- data/lib/omnizip/formats/tar/header.rb +206 -0
- data/lib/omnizip/formats/tar/reader.rb +119 -0
- data/lib/omnizip/formats/tar/writer.rb +212 -0
- data/lib/omnizip/formats/tar.rb +74 -0
- data/lib/omnizip/formats/xar/constants.rb +119 -0
- data/lib/omnizip/formats/xar/entry.rb +268 -0
- data/lib/omnizip/formats/xar/header.rb +223 -0
- data/lib/omnizip/formats/xar/reader.rb +400 -0
- data/lib/omnizip/formats/xar/toc.rb +570 -0
- data/lib/omnizip/formats/xar/writer.rb +461 -0
- data/lib/omnizip/formats/xar.rb +145 -0
- data/lib/omnizip/formats/xz/reader.rb +121 -0
- data/lib/omnizip/formats/xz/writer.rb +416 -0
- data/lib/omnizip/formats/xz.rb +210 -0
- data/lib/omnizip/formats/xz_const.rb +49 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl.rb +52 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
- data/lib/omnizip/formats/zip/reader.rb +376 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +489 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/formats.rb +29 -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/base.rb +19 -0
- data/lib/omnizip/implementations/rust/archive.rb +93 -0
- data/lib/omnizip/implementations/rust/library.rb +221 -0
- data/lib/omnizip/implementations/rust.rb +26 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
- data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
- data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
- data/lib/omnizip/implementations/seven_zip.rb +11 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
- data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
- data/lib/omnizip/implementations/xz_utils.rb +10 -0
- data/lib/omnizip/implementations.rb +25 -0
- data/lib/omnizip/io/buffered_input.rb +147 -0
- data/lib/omnizip/io/buffered_output.rb +106 -0
- data/lib/omnizip/io/source.rb +143 -0
- data/lib/omnizip/io/stream_manager.rb +117 -0
- data/lib/omnizip/io.rb +15 -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 +129 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +153 -0
- data/lib/omnizip/metadata/metadata_editor.rb +169 -0
- data/lib/omnizip/metadata/metadata_registry.rb +71 -0
- data/lib/omnizip/metadata/metadata_validator.rb +101 -0
- data/lib/omnizip/metadata.rb +58 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +41 -0
- data/lib/omnizip/models/attribute_apply.rb +40 -0
- data/lib/omnizip/models/compression_options.rb +53 -0
- data/lib/omnizip/models/conversion_options.rb +79 -0
- data/lib/omnizip/models/conversion_result.rb +141 -0
- data/lib/omnizip/models/eta_result.rb +45 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +142 -0
- data/lib/omnizip/models/filter_config.rb +148 -0
- data/lib/omnizip/models/match_result.rb +141 -0
- data/lib/omnizip/models/optimization_suggestion.rb +95 -0
- data/lib/omnizip/models/parallel_options.rb +116 -0
- data/lib/omnizip/models/performance_result.rb +85 -0
- data/lib/omnizip/models/profile_report.rb +116 -0
- data/lib/omnizip/models/progress_options.rb +39 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +45 -0
- data/lib/omnizip/parallel/engine.rb +52 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +225 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
- data/lib/omnizip/parallel/thread_pool.rb +60 -0
- data/lib/omnizip/parallel/worker_pool.rb +227 -0
- data/lib/omnizip/parallel.rb +156 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +71 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
- data/lib/omnizip/parity/models/main_packet.rb +126 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +102 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
- data/lib/omnizip/parity/models.rb +27 -0
- data/lib/omnizip/parity/par2_creator.rb +496 -0
- data/lib/omnizip/parity/par2_repairer.rb +409 -0
- data/lib/omnizip/parity/par2_verifier.rb +373 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
- data/lib/omnizip/parity.rb +207 -0
- data/lib/omnizip/password/encryption_registry.rb +26 -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 +190 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
- data/lib/omnizip/password.rb +88 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
- data/lib/omnizip/pipe.rb +120 -0
- data/lib/omnizip/platform/ntfs_streams.rb +200 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +36 -0
- data/lib/omnizip/profile/balanced_profile.rb +31 -0
- data/lib/omnizip/profile/binary_profile.rb +33 -0
- data/lib/omnizip/profile/compression_profile.rb +157 -0
- data/lib/omnizip/profile/custom_profile.rb +155 -0
- data/lib/omnizip/profile/fast_profile.rb +31 -0
- data/lib/omnizip/profile/maximum_profile.rb +31 -0
- data/lib/omnizip/profile/profile_detector.rb +108 -0
- data/lib/omnizip/profile/profile_registry.rb +160 -0
- data/lib/omnizip/profile/text_profile.rb +33 -0
- data/lib/omnizip/profile.rb +261 -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 +158 -0
- data/lib/omnizip/profiler.rb +192 -0
- data/lib/omnizip/progress/callback_reporter.rb +34 -0
- data/lib/omnizip/progress/console_reporter.rb +59 -0
- data/lib/omnizip/progress/log_reporter.rb +89 -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 +215 -0
- data/lib/omnizip/progress/silent_reporter.rb +22 -0
- data/lib/omnizip/progress.rb +131 -0
- data/lib/omnizip/registry.rb +111 -0
- data/lib/omnizip/rubyzip_compat.rb +61 -0
- data/lib/omnizip/temp/safe_extract.rb +124 -0
- data/lib/omnizip/temp/temp_file.rb +123 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +184 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +160 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +270 -0
- data/lib/omnizip/zip/output_stream.rb +320 -0
- data/lib/omnizip/zip.rb +23 -0
- data/lib/omnizip.rb +157 -0
- data/lib/tasks/msi_test_files.rake +66 -0
- data/lib/tasks/platform_gems.rake +147 -0
- data/lib/tasks/rust_backend.rake +48 -0
- data/readme-docs/advanced-features.adoc +514 -0
- data/readme-docs/api-usage.adoc +445 -0
- data/readme-docs/architecture.adoc +450 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +446 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +316 -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/vendor/libomnizip_ffi.so +0 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +768 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module LinkHandler
|
|
5
|
+
# Model for symbolic links
|
|
6
|
+
class SymbolicLink
|
|
7
|
+
attr_reader :target, :path
|
|
8
|
+
|
|
9
|
+
# Unix permissions for symbolic links (0120777)
|
|
10
|
+
SYMLINK_PERMISSIONS = 0o120777
|
|
11
|
+
|
|
12
|
+
def initialize(target:, path: nil)
|
|
13
|
+
@target = target
|
|
14
|
+
@path = path
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Create the symbolic link on the filesystem
|
|
18
|
+
def create(link_path)
|
|
19
|
+
LinkHandler.create_symlink(@target, link_path)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Get Unix permissions for symbolic links
|
|
23
|
+
def permissions
|
|
24
|
+
SYMLINK_PERMISSIONS
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Serialize for archive storage (returns the target path)
|
|
28
|
+
def serialize
|
|
29
|
+
@target
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Deserialize from archive storage
|
|
33
|
+
def self.deserialize(target_data, path: nil)
|
|
34
|
+
new(target: target_data, path: path)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Check if this is a symbolic link
|
|
38
|
+
def symlink?
|
|
39
|
+
true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Check if this is a hard link
|
|
43
|
+
def hardlink?
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Get the link type as string
|
|
48
|
+
def link_type
|
|
49
|
+
"symlink"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Convert to hash representation
|
|
53
|
+
def to_h
|
|
54
|
+
{
|
|
55
|
+
type: :symlink,
|
|
56
|
+
target: @target,
|
|
57
|
+
path: @path,
|
|
58
|
+
permissions: permissions,
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# String representation
|
|
63
|
+
def to_s
|
|
64
|
+
"#{@path} -> #{@target} (symlink)"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Inspect representation
|
|
68
|
+
def inspect
|
|
69
|
+
"#<Omnizip::LinkHandler::SymbolicLink target=#{@target.inspect} " \
|
|
70
|
+
"path=#{@path.inspect}>"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
# Handles symbolic and hard link operations with platform detection
|
|
7
|
+
module LinkHandler
|
|
8
|
+
autoload :SymbolicLink, "omnizip/link_handler/symbolic_link"
|
|
9
|
+
autoload :HardLink, "omnizip/link_handler/hard_link"
|
|
10
|
+
class << self
|
|
11
|
+
# Check if the platform supports symbolic links
|
|
12
|
+
def supported?
|
|
13
|
+
!windows_platform?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Check if symbolic links are supported on this platform.
|
|
17
|
+
# Delegates to Platform but also gates on LinkHandler#supported?
|
|
18
|
+
# (Windows is treated as unsupported here for historical
|
|
19
|
+
# compatibility — even if Windows Developer Mode would allow
|
|
20
|
+
# symlinks, callers should opt into that explicitly via Platform).
|
|
21
|
+
def symlink_supported?
|
|
22
|
+
supported? && Omnizip::Platform.supports_symlinks?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Check if hard links are supported
|
|
26
|
+
def hardlink_supported?
|
|
27
|
+
supported? && Omnizip::Platform.supports_hardlinks?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Detect if a path is a symbolic link
|
|
31
|
+
def symlink?(path)
|
|
32
|
+
return false unless symlink_supported?
|
|
33
|
+
|
|
34
|
+
File.symlink?(path)
|
|
35
|
+
rescue StandardError
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Detect if a path is a hard link
|
|
40
|
+
def hardlink?(path)
|
|
41
|
+
return false unless hardlink_supported?
|
|
42
|
+
return false unless File.exist?(path)
|
|
43
|
+
return false if File.directory?(path)
|
|
44
|
+
|
|
45
|
+
stat = File.stat(path)
|
|
46
|
+
stat.nlink > 1
|
|
47
|
+
rescue StandardError
|
|
48
|
+
false
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Detect the type of link (or nil if not a link)
|
|
52
|
+
def detect_link(path)
|
|
53
|
+
return nil unless supported?
|
|
54
|
+
return :symlink if symlink?(path)
|
|
55
|
+
return :hardlink if hardlink?(path)
|
|
56
|
+
|
|
57
|
+
nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Create a symbolic link
|
|
61
|
+
def create_symlink(target, link_path)
|
|
62
|
+
unless symlink_supported?
|
|
63
|
+
raise Omnizip::Error,
|
|
64
|
+
"Symbolic links are not supported on #{RUBY_PLATFORM}"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
FileUtils.mkdir_p(File.dirname(link_path))
|
|
68
|
+
File.symlink(target, link_path)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Create a hard link
|
|
72
|
+
def create_hardlink(target, link_path)
|
|
73
|
+
unless hardlink_supported?
|
|
74
|
+
raise Omnizip::Error,
|
|
75
|
+
"Hard links are not supported on #{RUBY_PLATFORM}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
FileUtils.mkdir_p(File.dirname(link_path))
|
|
79
|
+
File.link(target, link_path)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Read the target of a symbolic link
|
|
83
|
+
def read_link_target(link_path)
|
|
84
|
+
unless symlink_supported?
|
|
85
|
+
raise Omnizip::Error,
|
|
86
|
+
"Symbolic links are not supported on #{RUBY_PLATFORM}"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
File.readlink(link_path)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Get inode number for hard link tracking
|
|
93
|
+
def inode_number(path)
|
|
94
|
+
return nil unless hardlink_supported?
|
|
95
|
+
return nil unless File.exist?(path)
|
|
96
|
+
|
|
97
|
+
File.stat(path).ino
|
|
98
|
+
rescue StandardError
|
|
99
|
+
nil
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Create a SymbolicLink instance from a filesystem path
|
|
103
|
+
def symbolic_link_from_path(path)
|
|
104
|
+
return nil unless symlink?(path)
|
|
105
|
+
|
|
106
|
+
target = read_link_target(path)
|
|
107
|
+
SymbolicLink.new(target: target, path: path)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Create a HardLink instance from a filesystem path
|
|
111
|
+
def hard_link_from_path(path, original_path)
|
|
112
|
+
return nil unless hardlink?(path)
|
|
113
|
+
|
|
114
|
+
HardLink.new(
|
|
115
|
+
target: original_path,
|
|
116
|
+
path: path,
|
|
117
|
+
inode: inode_number(path),
|
|
118
|
+
)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
# Check if running on Windows platform
|
|
124
|
+
def windows_platform?
|
|
125
|
+
RUBY_PLATFORM.match?(/mswin|mingw|cygwin/)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Metadata
|
|
5
|
+
# Model for archive-level metadata
|
|
6
|
+
class ArchiveMetadata
|
|
7
|
+
attr_reader :archive
|
|
8
|
+
|
|
9
|
+
# Initialize archive metadata
|
|
10
|
+
# @param archive [Omnizip::Zip::File] The archive to manage metadata for
|
|
11
|
+
def initialize(archive)
|
|
12
|
+
@archive = archive
|
|
13
|
+
@modified = false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Get archive comment
|
|
17
|
+
# @return [String] Archive comment
|
|
18
|
+
def comment
|
|
19
|
+
archive.comment
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Set archive comment
|
|
23
|
+
# @param value [String] New comment
|
|
24
|
+
def comment=(value)
|
|
25
|
+
archive.comment = value.to_s
|
|
26
|
+
@modified = true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Get creation date (approximated from first entry)
|
|
30
|
+
# @return [Time, nil] Creation date or nil
|
|
31
|
+
def created_at
|
|
32
|
+
return nil if archive.entries.empty?
|
|
33
|
+
|
|
34
|
+
archive.entries.map(&:time).min
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Get modification date (from newest entry)
|
|
38
|
+
# @return [Time, nil] Modification date or nil
|
|
39
|
+
def modified_at
|
|
40
|
+
return nil if archive.entries.empty?
|
|
41
|
+
|
|
42
|
+
archive.entries.map(&:time).max
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Get total uncompressed size
|
|
46
|
+
# @return [Integer] Total uncompressed size in bytes
|
|
47
|
+
def total_size
|
|
48
|
+
archive.entries.sum(&:size)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Get total compressed size
|
|
52
|
+
# @return [Integer] Total compressed size in bytes
|
|
53
|
+
def total_compressed_size
|
|
54
|
+
archive.entries.sum(&:compressed_size)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Get compression ratio
|
|
58
|
+
# @return [Float] Compression ratio (0.0 to 1.0)
|
|
59
|
+
def compression_ratio
|
|
60
|
+
return 0.0 if total_size.zero?
|
|
61
|
+
|
|
62
|
+
ratio = 1.0 - (total_compressed_size.to_f / total_size)
|
|
63
|
+
# Clamp ratio between 0.0 and 1.0 (compressed size can exceed
|
|
64
|
+
# original size for small files or incompressible data)
|
|
65
|
+
[[ratio, 0.0].max, 1.0].min
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Get entry count
|
|
69
|
+
# @return [Integer] Number of entries
|
|
70
|
+
def entry_count
|
|
71
|
+
archive.entries.size
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Get file count (excluding directories)
|
|
75
|
+
# @return [Integer] Number of files
|
|
76
|
+
def file_count
|
|
77
|
+
archive.entries.count(&:file?)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Get directory count
|
|
81
|
+
# @return [Integer] Number of directories
|
|
82
|
+
def directory_count
|
|
83
|
+
archive.entries.count(&:directory?)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Check if metadata has been modified
|
|
87
|
+
# @return [Boolean] True if modified
|
|
88
|
+
def modified?
|
|
89
|
+
@modified
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Reset modified flag
|
|
93
|
+
def reset_modified
|
|
94
|
+
@modified = false
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Get all metadata as a hash
|
|
98
|
+
# @return [Hash] Metadata hash
|
|
99
|
+
def to_h
|
|
100
|
+
{
|
|
101
|
+
comment: comment,
|
|
102
|
+
created_at: created_at,
|
|
103
|
+
modified_at: modified_at,
|
|
104
|
+
total_size: total_size,
|
|
105
|
+
total_compressed_size: total_compressed_size,
|
|
106
|
+
compression_ratio: compression_ratio,
|
|
107
|
+
entry_count: entry_count,
|
|
108
|
+
file_count: file_count,
|
|
109
|
+
directory_count: directory_count,
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Metadata
|
|
5
|
+
# Model for file entry metadata
|
|
6
|
+
# Wraps CentralDirectoryHeader with a cleaner metadata API
|
|
7
|
+
class EntryMetadata
|
|
8
|
+
include Omnizip::Entry
|
|
9
|
+
|
|
10
|
+
attr_reader :entry
|
|
11
|
+
|
|
12
|
+
def entry_name = entry.name
|
|
13
|
+
def entry_directory? = entry.directory?
|
|
14
|
+
def entry_size = entry.size
|
|
15
|
+
def entry_mtime = entry.time
|
|
16
|
+
|
|
17
|
+
# Initialize metadata for an entry
|
|
18
|
+
# @param entry [Omnizip::Zip::Entry] The entry to manage metadata for
|
|
19
|
+
def initialize(entry)
|
|
20
|
+
@entry = entry
|
|
21
|
+
@modified = false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Get entry comment
|
|
25
|
+
# @return [String] Entry comment
|
|
26
|
+
def comment
|
|
27
|
+
entry.comment
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Set entry comment
|
|
31
|
+
# @param value [String] New comment
|
|
32
|
+
def comment=(value)
|
|
33
|
+
entry.comment = value.to_s
|
|
34
|
+
@modified = true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Get modification time
|
|
38
|
+
# @return [Time] Modification time
|
|
39
|
+
def mtime
|
|
40
|
+
entry.time
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Set modification time
|
|
44
|
+
# @param value [Time] New modification time
|
|
45
|
+
def mtime=(value)
|
|
46
|
+
unless value.is_a?(Time)
|
|
47
|
+
raise ArgumentError,
|
|
48
|
+
"mtime must be a Time object"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
entry.header.last_mod_time = dos_time(value)
|
|
52
|
+
entry.header.last_mod_date = dos_date(value)
|
|
53
|
+
@modified = true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Get Unix permissions
|
|
57
|
+
# @return [Integer] Unix permissions (e.g., 0644)
|
|
58
|
+
def unix_permissions
|
|
59
|
+
entry.unix_perms
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Set Unix permissions
|
|
63
|
+
# @param perms [Integer] Unix permissions (e.g., 0644, 0755)
|
|
64
|
+
def unix_permissions=(perms)
|
|
65
|
+
unless perms.is_a?(Integer)
|
|
66
|
+
raise ArgumentError,
|
|
67
|
+
"permissions must be an integer"
|
|
68
|
+
end
|
|
69
|
+
unless (0..0o777).cover?(perms)
|
|
70
|
+
raise ArgumentError,
|
|
71
|
+
"permissions out of range"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
entry.unix_perms = perms
|
|
75
|
+
@modified = true
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Get external attributes
|
|
79
|
+
# @return [Integer] External attributes
|
|
80
|
+
def attributes
|
|
81
|
+
entry.header.external_attributes
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Set external attributes
|
|
85
|
+
# @param value [Integer, Symbol] External attributes or symbol like :readonly
|
|
86
|
+
def attributes=(value)
|
|
87
|
+
case value
|
|
88
|
+
when Integer
|
|
89
|
+
entry.header.external_attributes = value
|
|
90
|
+
when Symbol
|
|
91
|
+
set_attribute_flag(value)
|
|
92
|
+
else
|
|
93
|
+
raise ArgumentError, "attributes must be Integer or Symbol"
|
|
94
|
+
end
|
|
95
|
+
@modified = true
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Check if metadata has been modified
|
|
99
|
+
# @return [Boolean] True if modified
|
|
100
|
+
def modified?
|
|
101
|
+
@modified
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Reset modified flag
|
|
105
|
+
def reset_modified
|
|
106
|
+
@modified = false
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Get all metadata as a hash
|
|
110
|
+
# @return [Hash] Metadata hash
|
|
111
|
+
def to_h
|
|
112
|
+
{
|
|
113
|
+
name: entry.name,
|
|
114
|
+
comment: comment,
|
|
115
|
+
mtime: mtime,
|
|
116
|
+
unix_permissions: unix_permissions,
|
|
117
|
+
size: entry.size,
|
|
118
|
+
compressed_size: entry.compressed_size,
|
|
119
|
+
crc: entry.crc,
|
|
120
|
+
directory: entry.directory?,
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
private
|
|
125
|
+
|
|
126
|
+
# Set attribute flag
|
|
127
|
+
def set_attribute_flag(flag)
|
|
128
|
+
case flag
|
|
129
|
+
when :readonly
|
|
130
|
+
entry.header.external_attributes |= 0x01
|
|
131
|
+
when :hidden
|
|
132
|
+
entry.header.external_attributes |= 0x02
|
|
133
|
+
when :system
|
|
134
|
+
entry.header.external_attributes |= 0x04
|
|
135
|
+
when :archive
|
|
136
|
+
entry.header.external_attributes |= 0x20
|
|
137
|
+
else
|
|
138
|
+
raise ArgumentError, "Unknown attribute flag: #{flag}"
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Convert Time to DOS time format
|
|
143
|
+
def dos_time(time)
|
|
144
|
+
((time.hour << 11) | (time.min << 5) | (time.sec / 2)) & 0xFFFF
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Convert Time to DOS date format
|
|
148
|
+
def dos_date(time)
|
|
149
|
+
(((time.year - 1980) << 9) | (time.month << 5) | time.day) & 0xFFFF
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Metadata
|
|
5
|
+
# Coordinates metadata editing operations
|
|
6
|
+
class MetadataEditor
|
|
7
|
+
attr_reader :archive, :validator
|
|
8
|
+
|
|
9
|
+
# Initialize metadata editor
|
|
10
|
+
# @param archive [Omnizip::Zip::File] Archive to edit
|
|
11
|
+
def initialize(archive)
|
|
12
|
+
@archive = archive
|
|
13
|
+
@validator = MetadataValidator.new
|
|
14
|
+
@changes = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Set timestamps for all entries
|
|
18
|
+
# @param time [Time] Time to set
|
|
19
|
+
# @param filter [Proc] Optional filter to select entries
|
|
20
|
+
def set_all_timestamps(time, &filter)
|
|
21
|
+
validator.validate_time(time)
|
|
22
|
+
|
|
23
|
+
entries = filter ? archive.entries.select(&filter) : archive.entries
|
|
24
|
+
|
|
25
|
+
entries.each do |entry|
|
|
26
|
+
next if entry.directory?
|
|
27
|
+
|
|
28
|
+
metadata = EntryMetadata.new(entry)
|
|
29
|
+
metadata.mtime = time
|
|
30
|
+
@changes << { entry: entry, field: :mtime, value: time }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Normalize permissions (set sensible defaults)
|
|
37
|
+
# @param file_perms [Integer] Permissions for files (default: 0644)
|
|
38
|
+
# @param dir_perms [Integer] Permissions for directories (default: 0755)
|
|
39
|
+
def normalize_permissions(file_perms: 0o644, dir_perms: 0o755)
|
|
40
|
+
validator.validate_permissions(file_perms)
|
|
41
|
+
validator.validate_permissions(dir_perms)
|
|
42
|
+
|
|
43
|
+
archive.entries.each do |entry|
|
|
44
|
+
metadata = EntryMetadata.new(entry)
|
|
45
|
+
perms = entry.directory? ? dir_perms : file_perms
|
|
46
|
+
metadata.unix_permissions = perms
|
|
47
|
+
@changes << { entry: entry, field: :permissions, value: perms }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Strip all comments from entries and archive
|
|
54
|
+
def strip_comments
|
|
55
|
+
archive.entries.each do |entry|
|
|
56
|
+
metadata = EntryMetadata.new(entry)
|
|
57
|
+
metadata.comment = ""
|
|
58
|
+
@changes << { entry: entry, field: :comment, value: "" }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
archive.comment = ""
|
|
62
|
+
@changes << { entry: :archive, field: :comment, value: "" }
|
|
63
|
+
|
|
64
|
+
self
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Set comment for entries matching a pattern
|
|
68
|
+
# @param pattern [String, Regexp] Pattern to match
|
|
69
|
+
# @param comment [String] Comment to set
|
|
70
|
+
def set_comment_matching(pattern, comment)
|
|
71
|
+
validator.validate_comment(comment)
|
|
72
|
+
|
|
73
|
+
matching_entries = if pattern.is_a?(Regexp)
|
|
74
|
+
archive.entries.select { |e| e.name =~ pattern }
|
|
75
|
+
else
|
|
76
|
+
archive.entries.select do |e|
|
|
77
|
+
::File.fnmatch(pattern, e.name)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
matching_entries.each do |entry|
|
|
82
|
+
metadata = EntryMetadata.new(entry)
|
|
83
|
+
metadata.comment = comment
|
|
84
|
+
@changes << { entry: entry, field: :comment, value: comment }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
self
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Set permissions for entries matching a pattern
|
|
91
|
+
# @param pattern [String, Regexp] Pattern to match
|
|
92
|
+
# @param perms [Integer] Permissions to set
|
|
93
|
+
def set_permissions_matching(pattern, perms)
|
|
94
|
+
validator.validate_permissions(perms)
|
|
95
|
+
|
|
96
|
+
matching_entries = if pattern.is_a?(Regexp)
|
|
97
|
+
archive.entries.select { |e| e.name =~ pattern }
|
|
98
|
+
else
|
|
99
|
+
archive.entries.select do |e|
|
|
100
|
+
::File.fnmatch(pattern, e.name)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
matching_entries.each do |entry|
|
|
105
|
+
next if entry.directory?
|
|
106
|
+
|
|
107
|
+
metadata = EntryMetadata.new(entry)
|
|
108
|
+
metadata.unix_permissions = perms
|
|
109
|
+
@changes << { entry: entry, field: :permissions, value: perms }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
self
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Update timestamps to preserve relative ordering
|
|
116
|
+
# Useful for maintaining build timestamps while updating absolute times
|
|
117
|
+
# @param base_time [Time] Base time for earliest file
|
|
118
|
+
def preserve_relative_timestamps(base_time = Time.now)
|
|
119
|
+
validator.validate_time(base_time)
|
|
120
|
+
|
|
121
|
+
# Find earliest timestamp
|
|
122
|
+
earliest = archive.entries.map(&:time).min
|
|
123
|
+
return self unless earliest
|
|
124
|
+
|
|
125
|
+
# Calculate offset
|
|
126
|
+
offset = base_time.to_i - earliest.to_i
|
|
127
|
+
|
|
128
|
+
archive.entries.each do |entry|
|
|
129
|
+
next if entry.directory?
|
|
130
|
+
|
|
131
|
+
new_time = Time.at(entry.time.to_i + offset)
|
|
132
|
+
metadata = EntryMetadata.new(entry)
|
|
133
|
+
metadata.mtime = new_time
|
|
134
|
+
@changes << { entry: entry, field: :mtime, value: new_time }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
self
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Get list of pending changes
|
|
141
|
+
# @return [Array<Hash>] List of changes
|
|
142
|
+
def pending_changes
|
|
143
|
+
@changes
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Check if there are pending changes
|
|
147
|
+
# @return [Boolean] True if there are changes
|
|
148
|
+
def modified?
|
|
149
|
+
!@changes.empty?
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Clear pending changes
|
|
153
|
+
def clear_changes
|
|
154
|
+
@changes = []
|
|
155
|
+
self
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Commit all changes to archive
|
|
159
|
+
# This marks the archive as modified and saves on close
|
|
160
|
+
def commit
|
|
161
|
+
# Changes are already applied to entries
|
|
162
|
+
# Just mark archive as modified
|
|
163
|
+
archive.modified! if modified?
|
|
164
|
+
@changes = []
|
|
165
|
+
self
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Metadata
|
|
5
|
+
# Registry of supported metadata per archive format
|
|
6
|
+
class MetadataRegistry
|
|
7
|
+
@registry = {}
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
# Register metadata support for a format
|
|
11
|
+
# @param format [Symbol] Format name (e.g., :zip, :seven_zip)
|
|
12
|
+
# @param supported_fields [Array<Symbol>] Supported metadata fields
|
|
13
|
+
def register(format, supported_fields)
|
|
14
|
+
@registry[format] = supported_fields
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Check if a format supports a metadata field
|
|
18
|
+
# @param format [Symbol] Format name
|
|
19
|
+
# @param field [Symbol] Metadata field name
|
|
20
|
+
# @return [Boolean] True if supported
|
|
21
|
+
def supports?(format, field)
|
|
22
|
+
fields = @registry[format]
|
|
23
|
+
return false unless fields
|
|
24
|
+
|
|
25
|
+
fields.include?(field)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Get all supported fields for a format
|
|
29
|
+
# @param format [Symbol] Format name
|
|
30
|
+
# @return [Array<Symbol>] List of supported fields
|
|
31
|
+
def supported_fields(format)
|
|
32
|
+
@registry[format] || []
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Get all registered formats
|
|
36
|
+
# @return [Array<Symbol>] List of formats
|
|
37
|
+
def formats
|
|
38
|
+
@registry.keys
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Reset registry (for testing)
|
|
42
|
+
def reset
|
|
43
|
+
@registry = {}
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Register ZIP format metadata support
|
|
49
|
+
MetadataRegistry.register(:zip, %i[
|
|
50
|
+
comment
|
|
51
|
+
mtime
|
|
52
|
+
unix_permissions
|
|
53
|
+
external_attributes
|
|
54
|
+
filename
|
|
55
|
+
extra_field
|
|
56
|
+
])
|
|
57
|
+
|
|
58
|
+
# Register 7z format metadata support: the readable fields the
|
|
59
|
+
# handler detail contract carries (name/size/directory always
|
|
60
|
+
# present; compressed_size when tracked, mtime/crc when stored).
|
|
61
|
+
# Editing is ZIP-only — the metadata command raises truthfully.
|
|
62
|
+
MetadataRegistry.register(:seven_zip, %i[
|
|
63
|
+
name
|
|
64
|
+
size
|
|
65
|
+
directory
|
|
66
|
+
compressed_size
|
|
67
|
+
mtime
|
|
68
|
+
crc
|
|
69
|
+
])
|
|
70
|
+
end
|
|
71
|
+
end
|