omnizip 0.4.7-aarch64-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,156 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
module Progress
|
|
9
|
+
# Visual progress bar for terminal output.
|
|
10
|
+
#
|
|
11
|
+
# This class renders a progress bar with percentage, file counts,
|
|
12
|
+
# rate, and ETA information. It supports color output and automatic
|
|
13
|
+
# width detection.
|
|
14
|
+
class ProgressBar
|
|
15
|
+
attr_reader :width, :use_color
|
|
16
|
+
|
|
17
|
+
# Initialize a new progress bar
|
|
18
|
+
#
|
|
19
|
+
# @param width [Integer] Bar width in characters (auto-detect if nil)
|
|
20
|
+
# @param use_color [Boolean] Enable color output
|
|
21
|
+
def initialize(width: nil, use_color: true)
|
|
22
|
+
@width = width || detect_terminal_width
|
|
23
|
+
@use_color = use_color && color_supported?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Render progress bar string
|
|
27
|
+
#
|
|
28
|
+
# @param progress [ProgressTracker] Progress tracker
|
|
29
|
+
# @return [String] Formatted progress bar
|
|
30
|
+
def render(progress)
|
|
31
|
+
bar = build_bar(progress.percentage)
|
|
32
|
+
info = build_info(progress)
|
|
33
|
+
|
|
34
|
+
"\r#{bar} #{info}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Clear the progress bar line
|
|
38
|
+
#
|
|
39
|
+
# @return [String] Clear string
|
|
40
|
+
def clear
|
|
41
|
+
"\r#{' ' * width}\r"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
# Build the progress bar component
|
|
47
|
+
#
|
|
48
|
+
# @param percentage [Float] Completion percentage (0.0-100.0)
|
|
49
|
+
# @return [String] Progress bar string
|
|
50
|
+
def build_bar(percentage)
|
|
51
|
+
bar_width = 20
|
|
52
|
+
filled = ((percentage / 100.0) * bar_width).round
|
|
53
|
+
empty = bar_width - filled
|
|
54
|
+
|
|
55
|
+
bar = "[#{'=' * filled}#{'>' if filled.positive?}#{' ' * [empty - 1,
|
|
56
|
+
0].max}]"
|
|
57
|
+
|
|
58
|
+
if use_color
|
|
59
|
+
colorize(bar, :green)
|
|
60
|
+
else
|
|
61
|
+
bar
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Build the info component (percentage, files, rate, ETA)
|
|
66
|
+
#
|
|
67
|
+
# @param progress [ProgressTracker] Progress tracker
|
|
68
|
+
# @return [String] Info string
|
|
69
|
+
def build_info(progress)
|
|
70
|
+
parts = []
|
|
71
|
+
|
|
72
|
+
# Percentage
|
|
73
|
+
parts << format("%3.0f%%", progress.percentage)
|
|
74
|
+
|
|
75
|
+
# File count
|
|
76
|
+
parts << format(
|
|
77
|
+
"(%d/%d files)",
|
|
78
|
+
progress.files_processed,
|
|
79
|
+
progress.operation_progress.total_files,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Current file (truncate if too long)
|
|
83
|
+
if progress.current_file
|
|
84
|
+
filename = truncate_filename(progress.current_file, 30)
|
|
85
|
+
parts << filename
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Rate
|
|
89
|
+
parts << progress.rate_formatted if progress.rate_bps.positive?
|
|
90
|
+
|
|
91
|
+
# ETA
|
|
92
|
+
eta = progress.eta_formatted
|
|
93
|
+
parts << "ETA: #{eta}" unless eta == "calculating..."
|
|
94
|
+
|
|
95
|
+
parts.join(" - ")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Truncate filename to fit width
|
|
99
|
+
#
|
|
100
|
+
# @param filename [String] Filename to truncate
|
|
101
|
+
# @param max_length [Integer] Maximum length
|
|
102
|
+
# @return [String] Truncated filename
|
|
103
|
+
def truncate_filename(filename, max_length)
|
|
104
|
+
return filename if filename.length <= max_length
|
|
105
|
+
|
|
106
|
+
"...#{filename[(-max_length + 3)..]}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Detect terminal width
|
|
110
|
+
#
|
|
111
|
+
# @return [Integer] Terminal width in characters
|
|
112
|
+
def detect_terminal_width
|
|
113
|
+
if ENV["COLUMNS"]
|
|
114
|
+
ENV["COLUMNS"].to_i
|
|
115
|
+
elsif $stdout.tty?
|
|
116
|
+
begin
|
|
117
|
+
require "io/console"
|
|
118
|
+
$stdout.winsize[1]
|
|
119
|
+
rescue LoadError, NoMethodError
|
|
120
|
+
80 # Default fallback
|
|
121
|
+
end
|
|
122
|
+
else
|
|
123
|
+
80
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Check if terminal supports color
|
|
128
|
+
#
|
|
129
|
+
# @return [Boolean] true if color is supported
|
|
130
|
+
def color_supported?
|
|
131
|
+
return false unless $stdout.tty?
|
|
132
|
+
return false if ENV["TERM"] == "dumb"
|
|
133
|
+
|
|
134
|
+
true
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Colorize string with ANSI color codes
|
|
138
|
+
#
|
|
139
|
+
# @param text [String] Text to colorize
|
|
140
|
+
# @param color [Symbol] Color name (:green, :yellow, :red, etc.)
|
|
141
|
+
# @return [String] Colorized string
|
|
142
|
+
def colorize(text, color)
|
|
143
|
+
color_codes = {
|
|
144
|
+
green: 32,
|
|
145
|
+
yellow: 33,
|
|
146
|
+
red: 31,
|
|
147
|
+
blue: 34,
|
|
148
|
+
cyan: 36,
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
code = color_codes[color] || 0
|
|
152
|
+
"\e[#{code}m#{text}\e[0m"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
module Progress
|
|
9
|
+
# Abstract base class for progress reporters.
|
|
10
|
+
#
|
|
11
|
+
# This class defines the interface for progress reporting strategies.
|
|
12
|
+
# Subclasses implement specific reporting mechanisms (console, callback,
|
|
13
|
+
# log file, etc.).
|
|
14
|
+
#
|
|
15
|
+
# @abstract Subclass and override {#report} to implement a reporter
|
|
16
|
+
class ProgressReporter
|
|
17
|
+
# Report progress to the output mechanism
|
|
18
|
+
#
|
|
19
|
+
# @param progress [ProgressTracker] Progress tracker with current state
|
|
20
|
+
# @raise [NotImplementedError] if not implemented by subclass
|
|
21
|
+
def report(progress)
|
|
22
|
+
raise NotImplementedError, "#{self.class} must implement #report"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Called when operation starts (optional hook)
|
|
26
|
+
#
|
|
27
|
+
# @param progress [ProgressTracker] Progress tracker
|
|
28
|
+
def start(progress)
|
|
29
|
+
# Optional hook for subclasses
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Called when operation completes (optional hook)
|
|
33
|
+
#
|
|
34
|
+
# @param progress [ProgressTracker] Progress tracker
|
|
35
|
+
def finish(progress)
|
|
36
|
+
# Optional hook for subclasses
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
module Progress
|
|
9
|
+
# Central progress tracking coordinator.
|
|
10
|
+
#
|
|
11
|
+
# This class tracks operation progress, calculates rates and ETA,
|
|
12
|
+
# and reports progress to configured reporters. It integrates the
|
|
13
|
+
# OperationProgress model with ETA calculation.
|
|
14
|
+
class ProgressTracker
|
|
15
|
+
attr_reader :operation_progress, :eta_estimator, :reporters,
|
|
16
|
+
:update_interval, :last_report_time
|
|
17
|
+
|
|
18
|
+
# Initialize a new progress tracker
|
|
19
|
+
#
|
|
20
|
+
# @param total_files [Integer] Total number of files to process
|
|
21
|
+
# @param total_bytes [Integer] Total bytes to process
|
|
22
|
+
# @param reporters [Array<ProgressReporter>] Progress reporters
|
|
23
|
+
# @param update_interval [Float] Minimum seconds between reports
|
|
24
|
+
# @param eta_strategy [Symbol] ETA estimation strategy
|
|
25
|
+
def initialize(total_files:, total_bytes:, reporters: [],
|
|
26
|
+
update_interval: 0.5, eta_strategy: :exponential_smoothing)
|
|
27
|
+
@operation_progress = OperationProgress.new(
|
|
28
|
+
total_files: total_files,
|
|
29
|
+
total_bytes: total_bytes,
|
|
30
|
+
)
|
|
31
|
+
@eta_estimator = ETA.create_estimator(eta_strategy)
|
|
32
|
+
@reporters = Array(reporters)
|
|
33
|
+
@update_interval = update_interval
|
|
34
|
+
@last_report_time = Time.now - update_interval # Allow immediate first report
|
|
35
|
+
@mutex = Mutex.new # Thread safety
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Announce the operation to every reporter (#start hooks).
|
|
39
|
+
# Call once before the first #update.
|
|
40
|
+
#
|
|
41
|
+
# @return [self]
|
|
42
|
+
def start
|
|
43
|
+
@mutex.synchronize { @started = true }
|
|
44
|
+
reporters.each { |reporter| reporter.start(self) }
|
|
45
|
+
self
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Complete the operation: fire a final report and the #finish
|
|
49
|
+
# hooks. Idempotent — a second call is a no-op.
|
|
50
|
+
#
|
|
51
|
+
# @return [self]
|
|
52
|
+
def finish
|
|
53
|
+
@mutex.synchronize do
|
|
54
|
+
return self if @finished
|
|
55
|
+
|
|
56
|
+
@finished = true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
reporters.each do |reporter|
|
|
60
|
+
reporter.report(self)
|
|
61
|
+
reporter.finish(self)
|
|
62
|
+
end
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Update progress with new values
|
|
67
|
+
#
|
|
68
|
+
# @param files [Integer] Number of files completed
|
|
69
|
+
# @param bytes [Integer] Number of bytes processed
|
|
70
|
+
# @param current_file [String] Name of file currently processing
|
|
71
|
+
def update(files:, bytes:, current_file: nil)
|
|
72
|
+
@mutex.synchronize do
|
|
73
|
+
# Update operation progress
|
|
74
|
+
operation_progress.update(
|
|
75
|
+
files: files,
|
|
76
|
+
bytes: bytes,
|
|
77
|
+
current_file: current_file,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Add sample to ETA estimator
|
|
81
|
+
eta_estimator.add_sample(
|
|
82
|
+
bytes_processed: bytes,
|
|
83
|
+
files_processed: files,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Report if enough time has passed
|
|
87
|
+
report_if_needed
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Get current completion percentage
|
|
92
|
+
#
|
|
93
|
+
# @return [Float] Percentage complete (0.0-100.0)
|
|
94
|
+
def percentage
|
|
95
|
+
operation_progress.percentage
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Get number of files processed
|
|
99
|
+
#
|
|
100
|
+
# @return [Integer] Files processed
|
|
101
|
+
def files_processed
|
|
102
|
+
operation_progress.files_done
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Get number of bytes processed
|
|
106
|
+
#
|
|
107
|
+
# @return [Integer] Bytes processed
|
|
108
|
+
def bytes_processed
|
|
109
|
+
operation_progress.bytes_done
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Get current file being processed
|
|
113
|
+
#
|
|
114
|
+
# @return [String, nil] Current file name
|
|
115
|
+
def current_file
|
|
116
|
+
operation_progress.current_file
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Get processing rate in MB/s
|
|
120
|
+
#
|
|
121
|
+
# @return [Float] Megabytes per second
|
|
122
|
+
def rate_mbps
|
|
123
|
+
eta_estimator.rate_calculator.megabytes_per_second
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Get processing rate in bytes/s
|
|
127
|
+
#
|
|
128
|
+
# @return [Float] Bytes per second
|
|
129
|
+
def rate_bps
|
|
130
|
+
eta_estimator.rate_calculator.bytes_per_second
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Get formatted rate string
|
|
134
|
+
#
|
|
135
|
+
# @return [String] Formatted rate (e.g., "2.5 MB/s")
|
|
136
|
+
def rate_formatted
|
|
137
|
+
eta_estimator.rate_calculator.format_rate
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Get ETA in seconds
|
|
141
|
+
#
|
|
142
|
+
# @return [Float] Estimated seconds remaining
|
|
143
|
+
def eta_seconds
|
|
144
|
+
result = eta_estimator.estimate(operation_progress.remaining_bytes)
|
|
145
|
+
result.seconds_remaining
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Get formatted ETA string
|
|
149
|
+
#
|
|
150
|
+
# @return [String] Formatted ETA (e.g., "2m 30s")
|
|
151
|
+
def eta_formatted
|
|
152
|
+
result = eta_estimator.estimate(operation_progress.remaining_bytes)
|
|
153
|
+
result.formatted
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Get full ETA result with confidence
|
|
157
|
+
#
|
|
158
|
+
# @return [Models::ETAResult] Complete ETA result
|
|
159
|
+
def eta_result
|
|
160
|
+
eta_estimator.estimate(operation_progress.remaining_bytes)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Force a progress report (regardless of interval)
|
|
164
|
+
def report
|
|
165
|
+
@mutex.synchronize do
|
|
166
|
+
reporters.each { |reporter| reporter.report(self) }
|
|
167
|
+
@last_report_time = Time.now
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Add a reporter
|
|
172
|
+
#
|
|
173
|
+
# @param reporter [ProgressReporter] Reporter to add
|
|
174
|
+
def add_reporter(reporter)
|
|
175
|
+
@mutex.synchronize do
|
|
176
|
+
@reporters << reporter
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Remove a reporter
|
|
181
|
+
#
|
|
182
|
+
# @param reporter [ProgressReporter] Reporter to remove
|
|
183
|
+
def remove_reporter(reporter)
|
|
184
|
+
@mutex.synchronize do
|
|
185
|
+
@reporters.delete(reporter)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Check if operation is complete
|
|
190
|
+
#
|
|
191
|
+
# @return [Boolean] true if complete
|
|
192
|
+
def complete?
|
|
193
|
+
operation_progress.complete?
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Get elapsed time
|
|
197
|
+
#
|
|
198
|
+
# @return [Float] Seconds elapsed
|
|
199
|
+
def elapsed_seconds
|
|
200
|
+
operation_progress.elapsed_seconds
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
private
|
|
204
|
+
|
|
205
|
+
# Report progress if enough time has passed since last report
|
|
206
|
+
def report_if_needed
|
|
207
|
+
now = Time.now
|
|
208
|
+
return unless now - last_report_time >= update_interval
|
|
209
|
+
|
|
210
|
+
reporters.each { |reporter| reporter.report(self) }
|
|
211
|
+
@last_report_time = now
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
module Progress
|
|
9
|
+
# Silent progress reporter that produces no output.
|
|
10
|
+
#
|
|
11
|
+
# This reporter is useful when you want to track progress internally
|
|
12
|
+
# but don't want any visible output.
|
|
13
|
+
class SilentReporter < ProgressReporter
|
|
14
|
+
# Report progress (does nothing)
|
|
15
|
+
#
|
|
16
|
+
# @param _progress [ProgressTracker] Progress tracker (ignored)
|
|
17
|
+
def report(_progress)
|
|
18
|
+
# Intentionally does nothing
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
# Progress tracking module.
|
|
9
|
+
#
|
|
10
|
+
# This module provides real-time progress tracking for long-running
|
|
11
|
+
# operations with multiple reporting strategies (console, callback,
|
|
12
|
+
# log file, etc.) and integrated ETA calculation.
|
|
13
|
+
#
|
|
14
|
+
# @example Basic progress tracking
|
|
15
|
+
# tracker = Omnizip::Progress.track(total_files: 100, total_bytes: 1.gigabyte)
|
|
16
|
+
# # Update progress as work is done
|
|
17
|
+
# tracker.update(files: 10, bytes: 100.megabytes, current_file: "file.txt")
|
|
18
|
+
# puts tracker.percentage # => 10.0
|
|
19
|
+
# puts tracker.eta_formatted # => "2m 30s"
|
|
20
|
+
#
|
|
21
|
+
# @example With console progress bar
|
|
22
|
+
# tracker = Omnizip::Progress.track(
|
|
23
|
+
# total_files: 100,
|
|
24
|
+
# total_bytes: 1.gigabyte,
|
|
25
|
+
# reporter: :console
|
|
26
|
+
# )
|
|
27
|
+
#
|
|
28
|
+
# @example With custom callback
|
|
29
|
+
# tracker = Omnizip::Progress.track(
|
|
30
|
+
# total_files: 100,
|
|
31
|
+
# total_bytes: 1.gigabyte
|
|
32
|
+
# ) do |progress|
|
|
33
|
+
# puts "#{progress.percentage}% complete"
|
|
34
|
+
# end
|
|
35
|
+
module Progress
|
|
36
|
+
# Nested classes - autoloaded
|
|
37
|
+
autoload :OperationProgress, "omnizip/progress/operation_progress"
|
|
38
|
+
autoload :ProgressTracker, "omnizip/progress/progress_tracker"
|
|
39
|
+
autoload :ProgressReporter, "omnizip/progress/progress_reporter"
|
|
40
|
+
autoload :SilentReporter, "omnizip/progress/silent_reporter"
|
|
41
|
+
autoload :CallbackReporter, "omnizip/progress/callback_reporter"
|
|
42
|
+
autoload :LogReporter, "omnizip/progress/log_reporter"
|
|
43
|
+
autoload :ProgressBar, "omnizip/progress/progress_bar"
|
|
44
|
+
autoload :ConsoleReporter, "omnizip/progress/console_reporter"
|
|
45
|
+
|
|
46
|
+
# Cross-namespace dependencies - autoloaded
|
|
47
|
+
autoload :Eta, "omnizip/eta"
|
|
48
|
+
|
|
49
|
+
# Track an operation's progress
|
|
50
|
+
#
|
|
51
|
+
# @param total_files [Integer] Total number of files to process
|
|
52
|
+
# @param total_bytes [Integer] Total bytes to process
|
|
53
|
+
# @param reporter [Symbol, ProgressReporter, Array] Reporter(s) to use
|
|
54
|
+
# @param update_interval [Float] Minimum seconds between reports
|
|
55
|
+
# @param eta_strategy [Symbol] ETA estimation strategy
|
|
56
|
+
# @yield [progress] Optional callback block for custom reporting
|
|
57
|
+
# @return [ProgressTracker] Configured progress tracker
|
|
58
|
+
def self.track(total_files:, total_bytes:, reporter: :auto,
|
|
59
|
+
update_interval: 0.5, eta_strategy: :exponential_smoothing,
|
|
60
|
+
&block)
|
|
61
|
+
reporters = build_reporters(reporter, block)
|
|
62
|
+
|
|
63
|
+
ProgressTracker.new(
|
|
64
|
+
total_files: total_files,
|
|
65
|
+
total_bytes: total_bytes,
|
|
66
|
+
reporters: reporters,
|
|
67
|
+
update_interval: update_interval,
|
|
68
|
+
eta_strategy: eta_strategy,
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Configure global progress settings
|
|
73
|
+
#
|
|
74
|
+
# @yield [config] Configuration block
|
|
75
|
+
def self.configure
|
|
76
|
+
yield configuration
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Get global configuration
|
|
80
|
+
#
|
|
81
|
+
# @return [Configuration] Configuration object
|
|
82
|
+
def self.configuration
|
|
83
|
+
@configuration ||= Configuration.new
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Build reporters from various input formats
|
|
87
|
+
#
|
|
88
|
+
# @param reporter [Symbol, ProgressReporter, Array] Reporter specification
|
|
89
|
+
# @param block [Proc] Optional callback block
|
|
90
|
+
# @return [Array<ProgressReporter>] Array of reporters
|
|
91
|
+
def self.build_reporters(reporter, block)
|
|
92
|
+
reporters = []
|
|
93
|
+
|
|
94
|
+
# Handle callback block
|
|
95
|
+
reporters << CallbackReporter.new(&block) if block
|
|
96
|
+
|
|
97
|
+
# Handle reporter parameter
|
|
98
|
+
case reporter
|
|
99
|
+
when :auto
|
|
100
|
+
reporters << ConsoleReporter.new if $stdout.tty?
|
|
101
|
+
when :console
|
|
102
|
+
reporters << ConsoleReporter.new
|
|
103
|
+
when :silent
|
|
104
|
+
reporters << SilentReporter.new
|
|
105
|
+
when Array
|
|
106
|
+
reporters.concat(reporter)
|
|
107
|
+
when ProgressReporter
|
|
108
|
+
reporters << reporter
|
|
109
|
+
when Symbol
|
|
110
|
+
raise ArgumentError, "Unknown reporter type: #{reporter}"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Default to silent if no reporters
|
|
114
|
+
reporters << SilentReporter.new if reporters.empty?
|
|
115
|
+
|
|
116
|
+
reporters
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Global configuration class
|
|
120
|
+
class Configuration
|
|
121
|
+
attr_accessor :default_reporter, :default_update_interval,
|
|
122
|
+
:default_eta_strategy
|
|
123
|
+
|
|
124
|
+
def initialize
|
|
125
|
+
@default_reporter = :auto
|
|
126
|
+
@default_update_interval = 0.5
|
|
127
|
+
@default_eta_strategy = :exponential_smoothing
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
# Generic, thread-safe registry base class.
|
|
5
|
+
#
|
|
6
|
+
# Subclasses override the hooks +#not_found_error_class+,
|
|
7
|
+
# +#normalize_key+, and +#label+ to specialize behavior. They may also
|
|
8
|
+
# override +#register+ / +#get+ to add domain-specific arguments
|
|
9
|
+
# (e.g., +#register_with_formats+ on FilterRegistry).
|
|
10
|
+
#
|
|
11
|
+
# The base class is intentionally minimal: it owns a Hash store and a
|
|
12
|
+
# Mutex, and exposes the canonical CRUD quintet (+register+, +get+,
|
|
13
|
+
# +registered?+, +available+, +reset!+). Backward-compat aliases are
|
|
14
|
+
# provided so existing call sites keep working.
|
|
15
|
+
class Registry
|
|
16
|
+
class << self
|
|
17
|
+
def not_found_error_class
|
|
18
|
+
Omnizip::Error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def normalize_key(key)
|
|
22
|
+
key.to_sym
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def label
|
|
26
|
+
return "Item" unless name
|
|
27
|
+
|
|
28
|
+
name.gsub(/^Omnizip::/, "")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def register(key, value)
|
|
32
|
+
synchronize { storage[normalize_key(key)] = value }
|
|
33
|
+
value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Register a lazy trigger for +key+. When +get(key)+ is called and
|
|
37
|
+
# the key isn't yet in storage, the block is invoked. The block is
|
|
38
|
+
# expected to trigger autoload of the implementation file (e.g., by
|
|
39
|
+
# referencing a constant), which then self-registers.
|
|
40
|
+
def register_lazy(key, &trigger)
|
|
41
|
+
lazy_triggers[normalize_key(key)] = trigger
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def get(key)
|
|
45
|
+
normalized = normalize_key(key)
|
|
46
|
+
value = storage[normalized]
|
|
47
|
+
return value if value
|
|
48
|
+
|
|
49
|
+
trigger = lazy_triggers[normalized]
|
|
50
|
+
if trigger
|
|
51
|
+
trigger.call
|
|
52
|
+
value = storage[normalized]
|
|
53
|
+
return value if value
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
raise not_found_error_class,
|
|
57
|
+
"#{label} not registered: #{key.inspect}. " \
|
|
58
|
+
"Available: #{available.join(', ')}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def registered?(key)
|
|
62
|
+
normalized = normalize_key(key)
|
|
63
|
+
storage.key?(normalized) || lazy_triggers.key?(normalized)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def available
|
|
67
|
+
storage.keys
|
|
68
|
+
end
|
|
69
|
+
alias all available
|
|
70
|
+
alias strategies available
|
|
71
|
+
|
|
72
|
+
def reset!
|
|
73
|
+
# Clear stored entries but keep lazy triggers — the builtin
|
|
74
|
+
# autoload list should survive a reset so subsequent +get+ calls
|
|
75
|
+
# for builtins still trigger the autoload (which re-registers).
|
|
76
|
+
synchronize { storage.clear }
|
|
77
|
+
end
|
|
78
|
+
alias clear reset!
|
|
79
|
+
alias clear! reset!
|
|
80
|
+
alias reset reset!
|
|
81
|
+
|
|
82
|
+
def entries
|
|
83
|
+
synchronize { storage.dup }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def each(&block)
|
|
87
|
+
return to_enum(:each) unless block
|
|
88
|
+
|
|
89
|
+
entries.each(&block)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def storage
|
|
95
|
+
@storage ||= {}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def lazy_triggers
|
|
99
|
+
@lazy_triggers ||= {}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def synchronize(&block)
|
|
103
|
+
mutex.synchronize(&block)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def mutex
|
|
107
|
+
@mutex ||= Mutex.new
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|