omnizip 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (511) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +32 -0
  4. data/.rubocop_todo.yml +754 -0
  5. data/COPYING +502 -0
  6. data/Gemfile +17 -0
  7. data/LICENSE +12 -0
  8. data/README.adoc +1045 -0
  9. data/Rakefile +12 -0
  10. data/benchmark/README.md +260 -0
  11. data/benchmark/benchmark_suite.rb +125 -0
  12. data/benchmark/compression_bench.rb +181 -0
  13. data/benchmark/filter_bench.rb +180 -0
  14. data/benchmark/models/benchmark_result.rb +59 -0
  15. data/benchmark/models/comparison_result.rb +69 -0
  16. data/benchmark/profile_suite.rb +167 -0
  17. data/benchmark/reporter.rb +150 -0
  18. data/benchmark/run_benchmarks.rb +66 -0
  19. data/benchmark/test_data.rb +137 -0
  20. data/config/formats/rar3_spec.yml +91 -0
  21. data/config/formats/rar5_spec.yml +102 -0
  22. data/docs/.github/workflows/docs.yml +142 -0
  23. data/docs/.gitignore +21 -0
  24. data/docs/.lychee.toml +67 -0
  25. data/docs/Gemfile +13 -0
  26. data/docs/RAR_WRITE_SUPPORT.md +26 -0
  27. data/docs/README.md +101 -0
  28. data/docs/_config.yml +112 -0
  29. data/docs/assets/logo.svg +1 -0
  30. data/docs/assets/omnizip-logo.pdf +1540 -11
  31. data/docs/comparison/feature-matrix.adoc +694 -0
  32. data/docs/comparison/index.adoc +113 -0
  33. data/docs/comparison/vs-7zip.adoc +309 -0
  34. data/docs/comparison/vs-peazip.adoc +77 -0
  35. data/docs/comparison/vs-rubyzip.adoc +342 -0
  36. data/docs/comparison/vs-winrar.adoc +100 -0
  37. data/docs/compatibility.adoc +579 -0
  38. data/docs/concepts/index.adoc +129 -0
  39. data/docs/developer/architecture.adoc +256 -0
  40. data/docs/developer/contributing.adoc +158 -0
  41. data/docs/developer/index.adoc +25 -0
  42. data/docs/developer/testing.adoc +212 -0
  43. data/docs/getting-started/basic-usage.adoc +271 -0
  44. data/docs/getting-started/index.adoc +42 -0
  45. data/docs/getting-started/installation.adoc +138 -0
  46. data/docs/getting-started/quick-start.adoc +185 -0
  47. data/docs/getting-started/your-first-archive.adoc +218 -0
  48. data/docs/guides/advanced-features/encryption.adoc +300 -0
  49. data/docs/guides/advanced-features/index.adoc +49 -0
  50. data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
  51. data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
  52. data/docs/guides/advanced-features/streaming.adoc +212 -0
  53. data/docs/guides/archive-formats/gzip-format.adoc +107 -0
  54. data/docs/guides/archive-formats/index.adoc +130 -0
  55. data/docs/guides/archive-formats/rar-format.adoc +104 -0
  56. data/docs/guides/archive-formats/rar5.adoc +521 -0
  57. data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
  58. data/docs/guides/archive-formats/tar-format.adoc +106 -0
  59. data/docs/guides/archive-formats/xz-format.adoc +118 -0
  60. data/docs/guides/archive-formats/zip-format.adoc +35 -0
  61. data/docs/guides/compression-algorithms/bzip2.adoc +113 -0
  62. data/docs/guides/compression-algorithms/deflate.adoc +319 -0
  63. data/docs/guides/compression-algorithms/index.adoc +190 -0
  64. data/docs/guides/compression-algorithms/lzma.adoc +398 -0
  65. data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
  66. data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
  67. data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
  68. data/docs/guides/creating-archives.adoc +354 -0
  69. data/docs/guides/extracting-archives.adoc +53 -0
  70. data/docs/guides/format-conversion.adoc +64 -0
  71. data/docs/guides/index.adoc +49 -0
  72. data/docs/guides/migration-rubyzip.adoc +217 -0
  73. data/docs/guides/parity-archives.adoc +605 -0
  74. data/docs/guides/performance-tuning.adoc +88 -0
  75. data/docs/index.adoc +218 -0
  76. data/docs/lychee.toml +67 -0
  77. data/docs/reference/api/overview.adoc +188 -0
  78. data/docs/reference/cli/compress-command.adoc +114 -0
  79. data/docs/reference/cli/overview.adoc +140 -0
  80. data/docs/reference/index.adoc +26 -0
  81. data/docs/resources/faq.adoc +185 -0
  82. data/docs/resources/quick-reference.adoc +222 -0
  83. data/docs/troubleshooting/index.adoc +208 -0
  84. data/examples/api_comparison.rb +205 -0
  85. data/examples/deflate64_example.rb +96 -0
  86. data/examples/par2_demo.rb +121 -0
  87. data/examples/quick_start_native.rb +150 -0
  88. data/examples/quick_start_rubyzip.rb +115 -0
  89. data/examples/rubyzip_compatibility_demo.rb +194 -0
  90. data/exe/omnizip +27 -0
  91. data/lib/omnizip/algorithm.rb +130 -0
  92. data/lib/omnizip/algorithm_registry.rb +86 -0
  93. data/lib/omnizip/algorithms/.keep +0 -0
  94. data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
  95. data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
  96. data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
  97. data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
  98. data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
  99. data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
  100. data/lib/omnizip/algorithms/bzip2.rb +130 -0
  101. data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
  102. data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
  103. data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
  104. data/lib/omnizip/algorithms/deflate.rb +128 -0
  105. data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
  106. data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
  107. data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
  108. data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
  109. data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
  110. data/lib/omnizip/algorithms/deflate64.rb +109 -0
  111. data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
  112. data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
  113. data/lib/omnizip/algorithms/lzma/decoder.rb +148 -0
  114. data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
  115. data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
  116. data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
  117. data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
  118. data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
  119. data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
  120. data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
  121. data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -0
  122. data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
  123. data/lib/omnizip/algorithms/lzma/match.rb +32 -0
  124. data/lib/omnizip/algorithms/lzma/match_finder.rb +205 -0
  125. data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
  126. data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
  127. data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
  128. data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
  129. data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
  130. data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
  131. data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
  132. data/lib/omnizip/algorithms/lzma/state.rb +127 -0
  133. data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
  134. data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
  135. data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
  136. data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
  137. data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
  138. data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
  139. data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
  140. data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
  141. data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
  142. data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
  143. data/lib/omnizip/algorithms/lzma.rb +238 -0
  144. data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
  145. data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
  146. data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
  147. data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
  148. data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
  149. data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
  150. data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
  151. data/lib/omnizip/algorithms/lzma2.rb +141 -0
  152. data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
  153. data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
  154. data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
  155. data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
  156. data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
  157. data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
  158. data/lib/omnizip/algorithms/ppmd7.rb +116 -0
  159. data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
  160. data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
  161. data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
  162. data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
  163. data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
  164. data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
  165. data/lib/omnizip/algorithms/ppmd8.rb +82 -0
  166. data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
  167. data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
  168. data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
  169. data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
  170. data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
  171. data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
  172. data/lib/omnizip/algorithms/zstandard.rb +138 -0
  173. data/lib/omnizip/buffer/memory_archive.rb +251 -0
  174. data/lib/omnizip/buffer/memory_extractor.rb +224 -0
  175. data/lib/omnizip/buffer.rb +176 -0
  176. data/lib/omnizip/checksum_registry.rb +114 -0
  177. data/lib/omnizip/checksums/crc32.rb +100 -0
  178. data/lib/omnizip/checksums/crc64.rb +101 -0
  179. data/lib/omnizip/checksums/crc_base.rb +158 -0
  180. data/lib/omnizip/checksums/verifier.rb +131 -0
  181. data/lib/omnizip/chunked/memory_manager.rb +194 -0
  182. data/lib/omnizip/chunked/reader.rb +78 -0
  183. data/lib/omnizip/chunked/writer.rb +120 -0
  184. data/lib/omnizip/chunked.rb +129 -0
  185. data/lib/omnizip/cli/output_formatter.rb +104 -0
  186. data/lib/omnizip/cli.rb +572 -0
  187. data/lib/omnizip/commands/.keep +0 -0
  188. data/lib/omnizip/commands/archive_create_command.rb +427 -0
  189. data/lib/omnizip/commands/archive_extract_command.rb +272 -0
  190. data/lib/omnizip/commands/archive_list_command.rb +218 -0
  191. data/lib/omnizip/commands/archive_repair_command.rb +131 -0
  192. data/lib/omnizip/commands/archive_verify_command.rb +117 -0
  193. data/lib/omnizip/commands/compress_command.rb +117 -0
  194. data/lib/omnizip/commands/decompress_command.rb +120 -0
  195. data/lib/omnizip/commands/list_command.rb +53 -0
  196. data/lib/omnizip/commands/metadata_command.rb +153 -0
  197. data/lib/omnizip/commands/parity_create_command.rb +122 -0
  198. data/lib/omnizip/commands/parity_repair_command.rb +122 -0
  199. data/lib/omnizip/commands/parity_verify_command.rb +124 -0
  200. data/lib/omnizip/commands/profile_list_command.rb +56 -0
  201. data/lib/omnizip/commands/profile_show_command.rb +44 -0
  202. data/lib/omnizip/convenience.rb +359 -0
  203. data/lib/omnizip/converter/conversion_registry.rb +49 -0
  204. data/lib/omnizip/converter/conversion_strategy.rb +121 -0
  205. data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
  206. data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
  207. data/lib/omnizip/converter.rb +105 -0
  208. data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
  209. data/lib/omnizip/crypto/aes256/constants.rb +28 -0
  210. data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
  211. data/lib/omnizip/crypto/aes256.rb +102 -0
  212. data/lib/omnizip/error.rb +106 -0
  213. data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
  214. data/lib/omnizip/eta/moving_average_estimator.rb +99 -0
  215. data/lib/omnizip/eta/rate_calculator.rb +104 -0
  216. data/lib/omnizip/eta/sample_history.rb +143 -0
  217. data/lib/omnizip/eta/time_estimator.rb +106 -0
  218. data/lib/omnizip/eta.rb +63 -0
  219. data/lib/omnizip/extraction/filter_chain.rb +177 -0
  220. data/lib/omnizip/extraction/glob_pattern.rb +140 -0
  221. data/lib/omnizip/extraction/pattern_matcher.rb +70 -0
  222. data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
  223. data/lib/omnizip/extraction/regex_pattern.rb +50 -0
  224. data/lib/omnizip/extraction/selective_extractor.rb +240 -0
  225. data/lib/omnizip/extraction.rb +111 -0
  226. data/lib/omnizip/file_type/mime_classifier.rb +144 -0
  227. data/lib/omnizip/file_type.rb +113 -0
  228. data/lib/omnizip/filter.rb +139 -0
  229. data/lib/omnizip/filter_pipeline.rb +108 -0
  230. data/lib/omnizip/filter_registry.rb +166 -0
  231. data/lib/omnizip/filters/bcj.rb +279 -0
  232. data/lib/omnizip/filters/bcj2/constants.rb +53 -0
  233. data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
  234. data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
  235. data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
  236. data/lib/omnizip/filters/bcj2.rb +99 -0
  237. data/lib/omnizip/filters/bcj_arm.rb +176 -0
  238. data/lib/omnizip/filters/bcj_arm64.rb +244 -0
  239. data/lib/omnizip/filters/bcj_ia64.rb +196 -0
  240. data/lib/omnizip/filters/bcj_ppc.rb +190 -0
  241. data/lib/omnizip/filters/bcj_sparc.rb +176 -0
  242. data/lib/omnizip/filters/bcj_x86.rb +193 -0
  243. data/lib/omnizip/filters/delta.rb +196 -0
  244. data/lib/omnizip/filters/filter_base.rb +72 -0
  245. data/lib/omnizip/filters/registry.rb +123 -0
  246. data/lib/omnizip/filters/xz_delta.rb +258 -0
  247. data/lib/omnizip/format_detector.rb +162 -0
  248. data/lib/omnizip/format_registry.rb +59 -0
  249. data/lib/omnizip/formats/.keep +0 -0
  250. data/lib/omnizip/formats/bzip2_file.rb +172 -0
  251. data/lib/omnizip/formats/cpio/constants.rb +55 -0
  252. data/lib/omnizip/formats/cpio/entry.rb +385 -0
  253. data/lib/omnizip/formats/cpio/reader.rb +196 -0
  254. data/lib/omnizip/formats/cpio/writer.rb +234 -0
  255. data/lib/omnizip/formats/cpio.rb +140 -0
  256. data/lib/omnizip/formats/format_spec_loader.rb +230 -0
  257. data/lib/omnizip/formats/gzip.rb +238 -0
  258. data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
  259. data/lib/omnizip/formats/iso/directory_record.rb +152 -0
  260. data/lib/omnizip/formats/iso/joliet.rb +204 -0
  261. data/lib/omnizip/formats/iso/path_table.rb +125 -0
  262. data/lib/omnizip/formats/iso/reader.rb +197 -0
  263. data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
  264. data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
  265. data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
  266. data/lib/omnizip/formats/iso/writer.rb +530 -0
  267. data/lib/omnizip/formats/iso.rb +140 -0
  268. data/lib/omnizip/formats/lzip.rb +175 -0
  269. data/lib/omnizip/formats/lzma_alone.rb +171 -0
  270. data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
  271. data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
  272. data/lib/omnizip/formats/rar/block_parser.rb +243 -0
  273. data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
  274. data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
  275. data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
  276. data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -0
  277. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
  278. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
  279. data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
  280. data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
  281. data/lib/omnizip/formats/rar/compression/ppmd/context.rb +105 -0
  282. data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
  283. data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
  284. data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
  285. data/lib/omnizip/formats/rar/constants.rb +82 -0
  286. data/lib/omnizip/formats/rar/decompressor.rb +238 -0
  287. data/lib/omnizip/formats/rar/external_writer.rb +312 -0
  288. data/lib/omnizip/formats/rar/header.rb +192 -0
  289. data/lib/omnizip/formats/rar/license_validator.rb +109 -0
  290. data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
  291. data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
  292. data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
  293. data/lib/omnizip/formats/rar/parity_handler.rb +292 -0
  294. data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
  295. data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -0
  296. data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
  297. data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
  298. data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +97 -0
  299. data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
  300. data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
  301. data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
  302. data/lib/omnizip/formats/rar/rar5/header.rb +187 -0
  303. data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
  304. data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
  305. data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
  306. data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
  307. data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
  308. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +264 -0
  309. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
  310. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +194 -0
  311. data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
  312. data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
  313. data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
  314. data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
  315. data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
  316. data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
  317. data/lib/omnizip/formats/rar/reader.rb +366 -0
  318. data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
  319. data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
  320. data/lib/omnizip/formats/rar/writer.rb +431 -0
  321. data/lib/omnizip/formats/rar.rb +205 -0
  322. data/lib/omnizip/formats/rar3/compressor.rb +73 -0
  323. data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
  324. data/lib/omnizip/formats/rar3/reader.rb +386 -0
  325. data/lib/omnizip/formats/rar3/writer.rb +219 -0
  326. data/lib/omnizip/formats/rar5/compressor.rb +73 -0
  327. data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
  328. data/lib/omnizip/formats/rar5/reader.rb +342 -0
  329. data/lib/omnizip/formats/rar5/writer.rb +214 -0
  330. data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
  331. data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
  332. data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
  333. data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
  334. data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
  335. data/lib/omnizip/formats/seven_zip/header.rb +106 -0
  336. data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
  337. data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
  338. data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
  339. data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
  340. data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
  341. data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
  342. data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
  343. data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
  344. data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
  345. data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
  346. data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
  347. data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
  348. data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
  349. data/lib/omnizip/formats/seven_zip.rb +93 -0
  350. data/lib/omnizip/formats/tar/constants.rb +73 -0
  351. data/lib/omnizip/formats/tar/entry.rb +94 -0
  352. data/lib/omnizip/formats/tar/header.rb +168 -0
  353. data/lib/omnizip/formats/tar/reader.rb +121 -0
  354. data/lib/omnizip/formats/tar/writer.rb +216 -0
  355. data/lib/omnizip/formats/tar.rb +84 -0
  356. data/lib/omnizip/formats/xz/reader.rb +116 -0
  357. data/lib/omnizip/formats/xz.rb +237 -0
  358. data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
  359. data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
  360. data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
  361. data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
  362. data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
  363. data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
  364. data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
  365. data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
  366. data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
  367. data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
  368. data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
  369. data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
  370. data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
  371. data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
  372. data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
  373. data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
  374. data/lib/omnizip/formats/zip/constants.rb +69 -0
  375. data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
  376. data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
  377. data/lib/omnizip/formats/zip/reader.rb +250 -0
  378. data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
  379. data/lib/omnizip/formats/zip/writer.rb +375 -0
  380. data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
  381. data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
  382. data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
  383. data/lib/omnizip/formats/zip.rb +50 -0
  384. data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
  385. data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
  386. data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
  387. data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
  388. data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
  389. data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +421 -0
  390. data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
  391. data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
  392. data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
  393. data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
  394. data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
  395. data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
  396. data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
  397. data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
  398. data/lib/omnizip/io/buffered_input.rb +146 -0
  399. data/lib/omnizip/io/buffered_output.rb +105 -0
  400. data/lib/omnizip/io/stream_manager.rb +115 -0
  401. data/lib/omnizip/link_handler/hard_link.rb +79 -0
  402. data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
  403. data/lib/omnizip/link_handler.rb +124 -0
  404. data/lib/omnizip/metadata/archive_metadata.rb +114 -0
  405. data/lib/omnizip/metadata/entry_metadata.rb +146 -0
  406. data/lib/omnizip/metadata/metadata_editor.rb +171 -0
  407. data/lib/omnizip/metadata/metadata_registry.rb +64 -0
  408. data/lib/omnizip/metadata/metadata_validator.rb +99 -0
  409. data/lib/omnizip/metadata.rb +57 -0
  410. data/lib/omnizip/models/.keep +0 -0
  411. data/lib/omnizip/models/algorithm_metadata.rb +73 -0
  412. data/lib/omnizip/models/compression_options.rb +71 -0
  413. data/lib/omnizip/models/conversion_options.rb +87 -0
  414. data/lib/omnizip/models/conversion_result.rb +135 -0
  415. data/lib/omnizip/models/eta_result.rb +46 -0
  416. data/lib/omnizip/models/extraction_rule.rb +115 -0
  417. data/lib/omnizip/models/filter_chain.rb +144 -0
  418. data/lib/omnizip/models/filter_config.rb +183 -0
  419. data/lib/omnizip/models/match_result.rb +124 -0
  420. data/lib/omnizip/models/optimization_suggestion.rb +91 -0
  421. data/lib/omnizip/models/parallel_options.rb +104 -0
  422. data/lib/omnizip/models/performance_result.rb +79 -0
  423. data/lib/omnizip/models/profile_report.rb +82 -0
  424. data/lib/omnizip/models/progress_options.rb +38 -0
  425. data/lib/omnizip/models/split_options.rb +116 -0
  426. data/lib/omnizip/optimization_registry.rb +81 -0
  427. data/lib/omnizip/parallel/job_queue.rb +209 -0
  428. data/lib/omnizip/parallel/job_scheduler.rb +203 -0
  429. data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
  430. data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
  431. data/lib/omnizip/parallel/worker_pool.rb +223 -0
  432. data/lib/omnizip/parallel.rb +149 -0
  433. data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
  434. data/lib/omnizip/parity/galois16.rb +145 -0
  435. data/lib/omnizip/parity/models/creator_packet.rb +73 -0
  436. data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
  437. data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
  438. data/lib/omnizip/parity/models/main_packet.rb +128 -0
  439. data/lib/omnizip/parity/models/packet.rb +156 -0
  440. data/lib/omnizip/parity/models/packet_registry.rb +109 -0
  441. data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
  442. data/lib/omnizip/parity/par2_creator.rb +531 -0
  443. data/lib/omnizip/parity/par2_repairer.rb +407 -0
  444. data/lib/omnizip/parity/par2_verifier.rb +364 -0
  445. data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
  446. data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
  447. data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
  448. data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
  449. data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
  450. data/lib/omnizip/parity.rb +186 -0
  451. data/lib/omnizip/password/encryption_registry.rb +65 -0
  452. data/lib/omnizip/password/encryption_strategy.rb +96 -0
  453. data/lib/omnizip/password/password_validator.rb +129 -0
  454. data/lib/omnizip/password/winzip_aes_strategy.rb +192 -0
  455. data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
  456. data/lib/omnizip/password.rb +87 -0
  457. data/lib/omnizip/pipe/stream_compressor.rb +124 -0
  458. data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
  459. data/lib/omnizip/pipe.rb +121 -0
  460. data/lib/omnizip/platform/ntfs_streams.rb +201 -0
  461. data/lib/omnizip/platform.rb +189 -0
  462. data/lib/omnizip/profile/archive_profile.rb +39 -0
  463. data/lib/omnizip/profile/balanced_profile.rb +33 -0
  464. data/lib/omnizip/profile/binary_profile.rb +36 -0
  465. data/lib/omnizip/profile/compression_profile.rb +158 -0
  466. data/lib/omnizip/profile/custom_profile.rb +157 -0
  467. data/lib/omnizip/profile/fast_profile.rb +33 -0
  468. data/lib/omnizip/profile/maximum_profile.rb +33 -0
  469. data/lib/omnizip/profile/profile_detector.rb +110 -0
  470. data/lib/omnizip/profile/profile_registry.rb +161 -0
  471. data/lib/omnizip/profile/text_profile.rb +36 -0
  472. data/lib/omnizip/profile.rb +190 -0
  473. data/lib/omnizip/profiler/memory_profiler.rb +66 -0
  474. data/lib/omnizip/profiler/method_profiler.rb +49 -0
  475. data/lib/omnizip/profiler/report_generator.rb +169 -0
  476. data/lib/omnizip/profiler.rb +204 -0
  477. data/lib/omnizip/progress/callback_reporter.rb +36 -0
  478. data/lib/omnizip/progress/console_reporter.rb +62 -0
  479. data/lib/omnizip/progress/log_reporter.rb +91 -0
  480. data/lib/omnizip/progress/operation_progress.rb +118 -0
  481. data/lib/omnizip/progress/progress_bar.rb +156 -0
  482. data/lib/omnizip/progress/progress_reporter.rb +40 -0
  483. data/lib/omnizip/progress/progress_tracker.rb +190 -0
  484. data/lib/omnizip/progress/silent_reporter.rb +24 -0
  485. data/lib/omnizip/progress.rb +127 -0
  486. data/lib/omnizip/rubyzip_compat.rb +63 -0
  487. data/lib/omnizip/temp/safe_extract.rb +168 -0
  488. data/lib/omnizip/temp/temp_file.rb +124 -0
  489. data/lib/omnizip/temp/temp_file_pool.rb +109 -0
  490. data/lib/omnizip/temp.rb +181 -0
  491. data/lib/omnizip/version.rb +5 -0
  492. data/lib/omnizip/zip/entry.rb +156 -0
  493. data/lib/omnizip/zip/file.rb +485 -0
  494. data/lib/omnizip/zip/input_stream.rb +273 -0
  495. data/lib/omnizip/zip/output_stream.rb +324 -0
  496. data/lib/omnizip.rb +156 -0
  497. data/readme-docs/advanced-features.adoc +515 -0
  498. data/readme-docs/api-usage.adoc +444 -0
  499. data/readme-docs/architecture.adoc +449 -0
  500. data/readme-docs/archive-formats.adoc +479 -0
  501. data/readme-docs/cli-usage.adoc +222 -0
  502. data/readme-docs/compression-algorithms.adoc +442 -0
  503. data/readme-docs/compression-profiles.adoc +247 -0
  504. data/readme-docs/encryption-checksums.adoc +328 -0
  505. data/readme-docs/format-converter.adoc +325 -0
  506. data/readme-docs/installation.adoc +228 -0
  507. data/readme-docs/par2-archives.adoc +608 -0
  508. data/readme-docs/performance-profiler.adoc +389 -0
  509. data/readme-docs/preprocessing-filters.adoc +280 -0
  510. data/xz-file-format-1.2.1.txt +1174 -0
  511. metadata +617 -0
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (C) 2025 Ribose Inc.
5
+ #
6
+
7
+ require_relative "operation_progress"
8
+ require_relative "../eta"
9
+
10
+ module Omnizip
11
+ module Progress
12
+ # Central progress tracking coordinator.
13
+ #
14
+ # This class tracks operation progress, calculates rates and ETA,
15
+ # and reports progress to configured reporters. It integrates the
16
+ # OperationProgress model with ETA calculation.
17
+ class ProgressTracker
18
+ attr_reader :operation_progress, :eta_estimator, :reporters,
19
+ :update_interval, :last_report_time
20
+
21
+ # Initialize a new progress tracker
22
+ #
23
+ # @param total_files [Integer] Total number of files to process
24
+ # @param total_bytes [Integer] Total bytes to process
25
+ # @param reporters [Array<ProgressReporter>] Progress reporters
26
+ # @param update_interval [Float] Minimum seconds between reports
27
+ # @param eta_strategy [Symbol] ETA estimation strategy
28
+ def initialize(total_files:, total_bytes:, reporters: [],
29
+ update_interval: 0.5, eta_strategy: :exponential_smoothing)
30
+ @operation_progress = OperationProgress.new(
31
+ total_files: total_files,
32
+ total_bytes: total_bytes,
33
+ )
34
+ @eta_estimator = ETA.create_estimator(eta_strategy)
35
+ @reporters = Array(reporters)
36
+ @update_interval = update_interval
37
+ @last_report_time = Time.now - update_interval # Allow immediate first report
38
+ @mutex = Mutex.new # Thread safety
39
+ end
40
+
41
+ # Update progress with new values
42
+ #
43
+ # @param files [Integer] Number of files completed
44
+ # @param bytes [Integer] Number of bytes processed
45
+ # @param current_file [String] Name of file currently processing
46
+ def update(files:, bytes:, current_file: nil)
47
+ @mutex.synchronize do
48
+ # Update operation progress
49
+ operation_progress.update(
50
+ files: files,
51
+ bytes: bytes,
52
+ current_file: current_file,
53
+ )
54
+
55
+ # Add sample to ETA estimator
56
+ eta_estimator.add_sample(
57
+ bytes_processed: bytes,
58
+ files_processed: files,
59
+ )
60
+
61
+ # Report if enough time has passed
62
+ report_if_needed
63
+ end
64
+ end
65
+
66
+ # Get current completion percentage
67
+ #
68
+ # @return [Float] Percentage complete (0.0-100.0)
69
+ def percentage
70
+ operation_progress.percentage
71
+ end
72
+
73
+ # Get number of files processed
74
+ #
75
+ # @return [Integer] Files processed
76
+ def files_processed
77
+ operation_progress.files_done
78
+ end
79
+
80
+ # Get number of bytes processed
81
+ #
82
+ # @return [Integer] Bytes processed
83
+ def bytes_processed
84
+ operation_progress.bytes_done
85
+ end
86
+
87
+ # Get current file being processed
88
+ #
89
+ # @return [String, nil] Current file name
90
+ def current_file
91
+ operation_progress.current_file
92
+ end
93
+
94
+ # Get processing rate in MB/s
95
+ #
96
+ # @return [Float] Megabytes per second
97
+ def rate_mbps
98
+ eta_estimator.rate_calculator.megabytes_per_second
99
+ end
100
+
101
+ # Get processing rate in bytes/s
102
+ #
103
+ # @return [Float] Bytes per second
104
+ def rate_bps
105
+ eta_estimator.rate_calculator.bytes_per_second
106
+ end
107
+
108
+ # Get formatted rate string
109
+ #
110
+ # @return [String] Formatted rate (e.g., "2.5 MB/s")
111
+ def rate_formatted
112
+ eta_estimator.rate_calculator.format_rate
113
+ end
114
+
115
+ # Get ETA in seconds
116
+ #
117
+ # @return [Float] Estimated seconds remaining
118
+ def eta_seconds
119
+ result = eta_estimator.estimate(operation_progress.remaining_bytes)
120
+ result.seconds_remaining
121
+ end
122
+
123
+ # Get formatted ETA string
124
+ #
125
+ # @return [String] Formatted ETA (e.g., "2m 30s")
126
+ def eta_formatted
127
+ result = eta_estimator.estimate(operation_progress.remaining_bytes)
128
+ result.formatted
129
+ end
130
+
131
+ # Get full ETA result with confidence
132
+ #
133
+ # @return [Models::ETAResult] Complete ETA result
134
+ def eta_result
135
+ eta_estimator.estimate(operation_progress.remaining_bytes)
136
+ end
137
+
138
+ # Force a progress report (regardless of interval)
139
+ def report
140
+ @mutex.synchronize do
141
+ reporters.each { |reporter| reporter.report(self) }
142
+ @last_report_time = Time.now
143
+ end
144
+ end
145
+
146
+ # Add a reporter
147
+ #
148
+ # @param reporter [ProgressReporter] Reporter to add
149
+ def add_reporter(reporter)
150
+ @mutex.synchronize do
151
+ @reporters << reporter
152
+ end
153
+ end
154
+
155
+ # Remove a reporter
156
+ #
157
+ # @param reporter [ProgressReporter] Reporter to remove
158
+ def remove_reporter(reporter)
159
+ @mutex.synchronize do
160
+ @reporters.delete(reporter)
161
+ end
162
+ end
163
+
164
+ # Check if operation is complete
165
+ #
166
+ # @return [Boolean] true if complete
167
+ def complete?
168
+ operation_progress.complete?
169
+ end
170
+
171
+ # Get elapsed time
172
+ #
173
+ # @return [Float] Seconds elapsed
174
+ def elapsed_seconds
175
+ operation_progress.elapsed_seconds
176
+ end
177
+
178
+ private
179
+
180
+ # Report progress if enough time has passed since last report
181
+ def report_if_needed
182
+ now = Time.now
183
+ return unless now - last_report_time >= update_interval
184
+
185
+ reporters.each { |reporter| reporter.report(self) }
186
+ @last_report_time = now
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (C) 2025 Ribose Inc.
5
+ #
6
+
7
+ require_relative "progress_reporter"
8
+
9
+ module Omnizip
10
+ module Progress
11
+ # Silent progress reporter that produces no output.
12
+ #
13
+ # This reporter is useful when you want to track progress internally
14
+ # but don't want any visible output.
15
+ class SilentReporter < ProgressReporter
16
+ # Report progress (does nothing)
17
+ #
18
+ # @param _progress [ProgressTracker] Progress tracker (ignored)
19
+ def report(_progress)
20
+ # Intentionally does nothing
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (C) 2025 Ribose Inc.
5
+ #
6
+
7
+ require_relative "progress/operation_progress"
8
+ require_relative "progress/progress_tracker"
9
+ require_relative "progress/progress_reporter"
10
+ require_relative "progress/silent_reporter"
11
+ require_relative "progress/callback_reporter"
12
+ require_relative "progress/log_reporter"
13
+ require_relative "progress/progress_bar"
14
+ require_relative "progress/console_reporter"
15
+
16
+ module Omnizip
17
+ # Progress tracking module.
18
+ #
19
+ # This module provides real-time progress tracking for long-running
20
+ # operations with multiple reporting strategies (console, callback,
21
+ # log file, etc.) and integrated ETA calculation.
22
+ #
23
+ # @example Basic progress tracking
24
+ # tracker = Omnizip::Progress.track(total_files: 100, total_bytes: 1.gigabyte)
25
+ # # Update progress as work is done
26
+ # tracker.update(files: 10, bytes: 100.megabytes, current_file: "file.txt")
27
+ # puts tracker.percentage # => 10.0
28
+ # puts tracker.eta_formatted # => "2m 30s"
29
+ #
30
+ # @example With console progress bar
31
+ # tracker = Omnizip::Progress.track(
32
+ # total_files: 100,
33
+ # total_bytes: 1.gigabyte,
34
+ # reporter: :console
35
+ # )
36
+ #
37
+ # @example With custom callback
38
+ # tracker = Omnizip::Progress.track(
39
+ # total_files: 100,
40
+ # total_bytes: 1.gigabyte
41
+ # ) do |progress|
42
+ # puts "#{progress.percentage}% complete"
43
+ # end
44
+ module Progress
45
+ # Track an operation's progress
46
+ #
47
+ # @param total_files [Integer] Total number of files to process
48
+ # @param total_bytes [Integer] Total bytes to process
49
+ # @param reporter [Symbol, ProgressReporter, Array] Reporter(s) to use
50
+ # @param update_interval [Float] Minimum seconds between reports
51
+ # @param eta_strategy [Symbol] ETA estimation strategy
52
+ # @yield [progress] Optional callback block for custom reporting
53
+ # @return [ProgressTracker] Configured progress tracker
54
+ def self.track(total_files:, total_bytes:, reporter: :auto,
55
+ update_interval: 0.5, eta_strategy: :exponential_smoothing,
56
+ &block)
57
+ reporters = build_reporters(reporter, block)
58
+
59
+ ProgressTracker.new(
60
+ total_files: total_files,
61
+ total_bytes: total_bytes,
62
+ reporters: reporters,
63
+ update_interval: update_interval,
64
+ eta_strategy: eta_strategy,
65
+ )
66
+ end
67
+
68
+ # Configure global progress settings
69
+ #
70
+ # @yield [config] Configuration block
71
+ def self.configure
72
+ yield configuration
73
+ end
74
+
75
+ # Get global configuration
76
+ #
77
+ # @return [Configuration] Configuration object
78
+ def self.configuration
79
+ @configuration ||= Configuration.new
80
+ end
81
+
82
+ # Build reporters from various input formats
83
+ #
84
+ # @param reporter [Symbol, ProgressReporter, Array] Reporter specification
85
+ # @param block [Proc] Optional callback block
86
+ # @return [Array<ProgressReporter>] Array of reporters
87
+ def self.build_reporters(reporter, block)
88
+ reporters = []
89
+
90
+ # Handle callback block
91
+ reporters << CallbackReporter.new(&block) if block
92
+
93
+ # Handle reporter parameter
94
+ case reporter
95
+ when :auto
96
+ reporters << ConsoleReporter.new if $stdout.tty?
97
+ when :console
98
+ reporters << ConsoleReporter.new
99
+ when :silent
100
+ reporters << SilentReporter.new
101
+ when Array
102
+ reporters.concat(reporter)
103
+ when ProgressReporter
104
+ reporters << reporter
105
+ when Symbol
106
+ raise ArgumentError, "Unknown reporter type: #{reporter}"
107
+ end
108
+
109
+ # Default to silent if no reporters
110
+ reporters << SilentReporter.new if reporters.empty?
111
+
112
+ reporters
113
+ end
114
+
115
+ # Global configuration class
116
+ class Configuration
117
+ attr_accessor :default_reporter, :default_update_interval,
118
+ :default_eta_strategy
119
+
120
+ def initialize
121
+ @default_reporter = :auto
122
+ @default_update_interval = 0.5
123
+ @default_eta_strategy = :exponential_smoothing
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Rubyzip Compatibility Layer
5
+ #
6
+ # This file provides a drop-in replacement for the 'zip' gem (rubyzip).
7
+ # Simply require 'omnizip/rubyzip_compat' instead of 'zip' to use Omnizip
8
+ # with existing rubyzip code.
9
+ #
10
+ # Usage:
11
+ # require 'omnizip/rubyzip_compat'
12
+ #
13
+ # Zip::File.open('archive.zip') do |zip|
14
+ # zip.each { |entry| puts entry.name }
15
+ # end
16
+ #
17
+
18
+ require_relative "../omnizip"
19
+
20
+ # Create Zip namespace as alias for Omnizip::Zip
21
+ module Zip
22
+ # Rubyzip-compatible File class
23
+ File = Omnizip::Zip::File
24
+
25
+ # Rubyzip-compatible Entry class
26
+ Entry = Omnizip::Zip::Entry
27
+
28
+ # Rubyzip-compatible OutputStream class
29
+ OutputStream = Omnizip::Zip::OutputStream
30
+
31
+ # Rubyzip-compatible InputStream class
32
+ InputStream = Omnizip::Zip::InputStream
33
+
34
+ # Error classes for compatibility
35
+ Error = Omnizip::Error
36
+ FormatError = Omnizip::FormatError
37
+ CompressionError = Omnizip::CompressionError
38
+ DecompressionError = Omnizip::DecompressionError
39
+ ChecksumError = Omnizip::ChecksumError
40
+
41
+ # Version information
42
+ VERSION = Omnizip::VERSION
43
+
44
+ class << self
45
+ # Legacy compatibility method
46
+ # @deprecated Use Zip::File.open instead
47
+ def open(...)
48
+ File.open(...)
49
+ end
50
+
51
+ # Legacy compatibility method
52
+ # @deprecated Use Zip::File.create instead
53
+ def create(...)
54
+ File.create(...)
55
+ end
56
+ end
57
+ end
58
+
59
+ # Compatibility note
60
+ if $VERBOSE
61
+ warn "Omnizip: Using Omnizip rubyzip compatibility layer. " \
62
+ "API is compatible with rubyzip, but implementation differs."
63
+ end
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require "tmpdir"
5
+
6
+ module Omnizip
7
+ module Temp
8
+ # Safe extraction with atomic move to destination
9
+ # Provides rollback capability on failure
10
+ class SafeExtract
11
+ # Error raised when extraction verification fails
12
+ class VerificationError < Omnizip::Error; end
13
+
14
+ attr_reader :archive_path, :dest_path
15
+
16
+ # Create new safe extractor
17
+ # @param archive_path [String] Path to archive
18
+ # @param dest_path [String] Destination path
19
+ def initialize(archive_path, dest_path)
20
+ @archive_path = archive_path
21
+ @dest_path = dest_path
22
+ end
23
+
24
+ # Extract safely with verification
25
+ # @yield [temp_dir] Block for verification (return truthy to proceed)
26
+ # @return [String] Destination path
27
+ def extract
28
+ unless File.exist?(@archive_path)
29
+ raise Errno::ENOENT, "Archive not found: #{@archive_path}"
30
+ end
31
+
32
+ Dir.mktmpdir("omniz_extract_") do |temp_dir|
33
+ # Extract to temp directory
34
+ extract_to_temp(temp_dir)
35
+
36
+ # User verification if block given
37
+ if block_given?
38
+ result = yield(temp_dir)
39
+ unless result
40
+ raise VerificationError, "Extraction verification failed"
41
+ end
42
+ end
43
+
44
+ # Atomic move to destination
45
+ move_to_destination(temp_dir)
46
+ end
47
+
48
+ @dest_path
49
+ end
50
+
51
+ # Extract with checksum verification
52
+ # @param expected_checksums [Hash] Map of filename => CRC32
53
+ # @return [String] Destination path
54
+ def extract_verified(expected_checksums)
55
+ extract do |temp_dir|
56
+ verify_checksums(temp_dir, expected_checksums)
57
+ end
58
+ end
59
+
60
+ # Extract with file count verification
61
+ # @param expected_count [Integer] Expected number of files
62
+ # @return [String] Destination path
63
+ def extract_with_count(expected_count)
64
+ extract do |temp_dir|
65
+ actual_count = count_files(temp_dir)
66
+ actual_count == expected_count
67
+ end
68
+ end
69
+
70
+ # Class method for quick safe extraction
71
+ # @param archive_path [String] Archive to extract
72
+ # @param dest_path [String] Destination
73
+ # @yield [temp_dir] Verification block
74
+ # @return [String] Destination path
75
+ def self.extract_safe(archive_path, dest_path, &block)
76
+ new(archive_path, dest_path).extract(&block)
77
+ end
78
+
79
+ private
80
+
81
+ def extract_to_temp(temp_dir)
82
+ # Detect archive format and extract
83
+ case detect_format
84
+ when :zip
85
+ extract_zip(temp_dir)
86
+ when :seven_zip
87
+ extract_7z(temp_dir)
88
+ else
89
+ raise Omnizip::UnsupportedFormatError,
90
+ "Unknown archive format: #{@archive_path}"
91
+ end
92
+ end
93
+
94
+ def extract_zip(dest)
95
+ require_relative "../zip/file"
96
+
97
+ Omnizip::Zip::File.open(@archive_path) do |zip|
98
+ zip.each do |entry|
99
+ entry_path = File.join(dest, entry.name)
100
+
101
+ if entry.directory?
102
+ FileUtils.mkdir_p(entry_path)
103
+ else
104
+ FileUtils.mkdir_p(File.dirname(entry_path))
105
+ zip.extract(entry, entry_path)
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ def extract_7z(dest)
112
+ # Placeholder for 7z extraction
113
+ # Would use Omnizip::SevenZip::File when available
114
+ raise NotImplementedError, "7z extraction not yet implemented"
115
+ end
116
+
117
+ def move_to_destination(temp_dir)
118
+ # Ensure parent directory exists
119
+ FileUtils.mkdir_p(File.dirname(@dest_path))
120
+
121
+ # Remove destination if it exists
122
+ FileUtils.rm_rf(@dest_path)
123
+
124
+ # Copy contents (can't move since Dir.mktmpdir will try to clean up)
125
+ FileUtils.cp_r(temp_dir, @dest_path)
126
+ end
127
+
128
+ def verify_checksums(dir, expected)
129
+ require_relative "../checksums/crc32"
130
+
131
+ expected.all? do |file, expected_sum|
132
+ file_path = File.join(dir, file)
133
+ next false unless File.exist?(file_path)
134
+
135
+ # Calculate checksum
136
+ crc = Omnizip::Checksums::Crc32.new
137
+ File.open(file_path, "rb") do |f|
138
+ while (chunk = f.read(64 * 1024))
139
+ crc.update(chunk)
140
+ end
141
+ end
142
+
143
+ crc.finalize == expected_sum
144
+ end
145
+ end
146
+
147
+ def count_files(dir)
148
+ count = 0
149
+ Dir.glob(File.join(dir, "**", "*")) do |path|
150
+ count += 1 unless File.directory?(path)
151
+ end
152
+ count
153
+ end
154
+
155
+ def detect_format
156
+ File.open(@archive_path, "rb") do |f|
157
+ magic = f.read(4)
158
+ case magic
159
+ when "PK\x03\x04"
160
+ :zip
161
+ when "7z\xBC\xAF"
162
+ :seven_zip
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tempfile"
4
+
5
+ module Omnizip
6
+ module Temp
7
+ # RAII-pattern temporary file with automatic cleanup
8
+ class TempFile
9
+ attr_reader :path
10
+
11
+ # Create new temporary file
12
+ # @param prefix [String] Filename prefix
13
+ # @param suffix [String] Filename suffix
14
+ # @param directory [String, nil] Directory (nil = system default)
15
+ def initialize(prefix: "omniz_", suffix: "", directory: nil)
16
+ @prefix = prefix
17
+ @suffix = suffix
18
+ @directory = directory
19
+ @tempfile = nil
20
+ @path = nil
21
+ @kept = false
22
+ @finalized = false
23
+
24
+ create
25
+ setup_finalizer
26
+ end
27
+
28
+ # Get the underlying Tempfile object
29
+ # @return [Tempfile] The tempfile
30
+ def file
31
+ @tempfile
32
+ end
33
+
34
+ # Write data to temp file
35
+ # @param data [String] Data to write
36
+ # @return [Integer] Bytes written
37
+ def write(data)
38
+ @tempfile.write(data)
39
+ end
40
+
41
+ # Read data from temp file
42
+ # @param length [Integer, nil] Number of bytes to read
43
+ # @return [String, nil] Data read
44
+ def read(length = nil)
45
+ @tempfile.read(length)
46
+ end
47
+
48
+ # Rewind to beginning of file
49
+ def rewind
50
+ @tempfile.rewind
51
+ end
52
+
53
+ # Close the temp file
54
+ def close
55
+ @tempfile.close if @tempfile && !@tempfile.closed?
56
+ end
57
+
58
+ # Delete the temp file
59
+ def unlink
60
+ return if @finalized || @kept
61
+
62
+ if @tempfile
63
+ @tempfile.close unless @tempfile.closed?
64
+ @tempfile.unlink
65
+ @finalized = true
66
+ end
67
+ rescue StandardError
68
+ # Ignore errors during cleanup
69
+ nil
70
+ end
71
+
72
+ # Prevent automatic deletion
73
+ def keep!
74
+ @kept = true
75
+ end
76
+
77
+ # Check if file will be kept
78
+ # @return [Boolean] True if file won't be auto-deleted
79
+ def kept?
80
+ @kept
81
+ end
82
+
83
+ # Check if file has been finalized
84
+ # @return [Boolean] True if finalized
85
+ def finalized?
86
+ @finalized
87
+ end
88
+
89
+ private
90
+
91
+ def create
92
+ @tempfile = if @directory
93
+ ::Tempfile.new(
94
+ [@prefix, @suffix],
95
+ @directory,
96
+ binmode: true,
97
+ )
98
+ else
99
+ ::Tempfile.new(
100
+ [@prefix, @suffix],
101
+ binmode: true,
102
+ )
103
+ end
104
+ @path = @tempfile.path
105
+ end
106
+
107
+ def setup_finalizer
108
+ ObjectSpace.define_finalizer(self, self.class.finalizer(@tempfile))
109
+ end
110
+
111
+ # rubocop:disable Lint/IneffectiveAccessModifier
112
+ def self.finalizer(tempfile)
113
+ proc do
114
+ tempfile.close unless tempfile.closed?
115
+ tempfile.unlink
116
+ rescue StandardError
117
+ # Ignore errors in finalizer
118
+ nil
119
+ end
120
+ end
121
+ # rubocop:enable Lint/IneffectiveAccessModifier
122
+ end
123
+ end
124
+ end