omnizip 0.4.7-arm-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (632) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +32 -0
  4. data/.rubocop_todo.yml +293 -0
  5. data/CHANGELOG.md +1647 -0
  6. data/CONTEXT.md +68 -0
  7. data/COPYING +502 -0
  8. data/Gemfile +19 -0
  9. data/LICENSE +12 -0
  10. data/README.adoc +1327 -0
  11. data/Rakefile +15 -0
  12. data/TODO.refactor/00-overview.md +67 -0
  13. data/TODO.refactor/01-registry-base-class.md +81 -0
  14. data/TODO.refactor/02-error-hierarchy.md +57 -0
  15. data/TODO.refactor/03-autoload-entry-point.md +69 -0
  16. data/TODO.refactor/04-filter-base-consolidation.md +49 -0
  17. data/TODO.refactor/05-send-private-methods.md +64 -0
  18. data/TODO.refactor/06-instance-variable-access.md +69 -0
  19. data/TODO.refactor/07-respond-to-replacement.md +237 -0
  20. data/TODO.refactor/08-spec-doubles.md +27 -0
  21. data/TODO.refactor/09-cli-shared-module.md +35 -0
  22. data/TODO.refactor/10-format-detector-ocp.md +34 -0
  23. data/TODO.refactor/11-convenience-decoupling.md +38 -0
  24. data/TODO.refactor/12-thread-safety.md +8 -0
  25. data/TODO.refactor/13-lutaml-model-migration.md +158 -0
  26. data/TODO.refactor/14-add-missing-specs.md +25 -0
  27. data/benchmark/README.md +260 -0
  28. data/benchmark/benchmark_suite.rb +125 -0
  29. data/benchmark/compression_bench.rb +181 -0
  30. data/benchmark/filter_bench.rb +180 -0
  31. data/benchmark/models/benchmark_result.rb +59 -0
  32. data/benchmark/models/comparison_result.rb +69 -0
  33. data/benchmark/profile_suite.rb +167 -0
  34. data/benchmark/reporter.rb +150 -0
  35. data/benchmark/run_benchmarks.rb +66 -0
  36. data/benchmark/test_data.rb +137 -0
  37. data/config/formats/rar3_spec.yml +92 -0
  38. data/config/formats/rar5_spec.yml +102 -0
  39. data/docs/.github/workflows/docs.yml +142 -0
  40. data/docs/.gitignore +21 -0
  41. data/docs/.lychee.toml +67 -0
  42. data/docs/Gemfile +13 -0
  43. data/docs/RAR_WRITE_SUPPORT.md +26 -0
  44. data/docs/README.md +101 -0
  45. data/docs/_config.yml +112 -0
  46. data/docs/assets/logo.svg +1 -0
  47. data/docs/assets/omnizip-logo.pdf +1540 -11
  48. data/docs/comparison/feature-matrix.adoc +694 -0
  49. data/docs/comparison/index.adoc +113 -0
  50. data/docs/comparison/vs-7zip.adoc +309 -0
  51. data/docs/comparison/vs-peazip.adoc +77 -0
  52. data/docs/comparison/vs-rubyzip.adoc +342 -0
  53. data/docs/comparison/vs-winrar.adoc +100 -0
  54. data/docs/compatibility.adoc +579 -0
  55. data/docs/concepts/index.adoc +129 -0
  56. data/docs/developer/architecture.adoc +256 -0
  57. data/docs/developer/contributing.adoc +158 -0
  58. data/docs/developer/index.adoc +25 -0
  59. data/docs/developer/testing.adoc +212 -0
  60. data/docs/getting-started/basic-usage.adoc +263 -0
  61. data/docs/getting-started/index.adoc +42 -0
  62. data/docs/getting-started/installation.adoc +138 -0
  63. data/docs/getting-started/quick-start.adoc +183 -0
  64. data/docs/getting-started/your-first-archive.adoc +219 -0
  65. data/docs/guides/advanced-features/encryption.adoc +277 -0
  66. data/docs/guides/advanced-features/index.adoc +59 -0
  67. data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
  68. data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
  69. data/docs/guides/advanced-features/streaming.adoc +142 -0
  70. data/docs/guides/archive-formats/gzip-format.adoc +105 -0
  71. data/docs/guides/archive-formats/index.adoc +160 -0
  72. data/docs/guides/archive-formats/ole-format.adoc +151 -0
  73. data/docs/guides/archive-formats/rar-format.adoc +104 -0
  74. data/docs/guides/archive-formats/rar5.adoc +521 -0
  75. data/docs/guides/archive-formats/rpm-format.adoc +108 -0
  76. data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
  77. data/docs/guides/archive-formats/tar-format.adoc +106 -0
  78. data/docs/guides/archive-formats/xz-format.adoc +118 -0
  79. data/docs/guides/archive-formats/zip-format.adoc +35 -0
  80. data/docs/guides/compression-algorithms/bzip2.adoc +114 -0
  81. data/docs/guides/compression-algorithms/deflate.adoc +313 -0
  82. data/docs/guides/compression-algorithms/index.adoc +190 -0
  83. data/docs/guides/compression-algorithms/lzma.adoc +394 -0
  84. data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
  85. data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
  86. data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
  87. data/docs/guides/creating-archives.adoc +348 -0
  88. data/docs/guides/extracting-archives.adoc +53 -0
  89. data/docs/guides/format-conversion.adoc +64 -0
  90. data/docs/guides/index.adoc +49 -0
  91. data/docs/guides/migration-rubyzip.adoc +217 -0
  92. data/docs/guides/parity-archives.adoc +605 -0
  93. data/docs/guides/performance-tuning.adoc +88 -0
  94. data/docs/index.adoc +228 -0
  95. data/docs/lychee.toml +67 -0
  96. data/docs/reference/api/overview.adoc +187 -0
  97. data/docs/reference/cli/compress-command.adoc +114 -0
  98. data/docs/reference/cli/overview.adoc +140 -0
  99. data/docs/reference/index.adoc +26 -0
  100. data/docs/resources/faq.adoc +185 -0
  101. data/docs/resources/quick-reference.adoc +222 -0
  102. data/docs/rust-backend.md +0 -0
  103. data/docs/troubleshooting/index.adoc +207 -0
  104. data/docs/xar_format.md +216 -0
  105. data/examples/api_comparison.rb +205 -0
  106. data/examples/deflate64_example.rb +96 -0
  107. data/examples/par2_demo.rb +121 -0
  108. data/examples/quick_start_native.rb +150 -0
  109. data/examples/quick_start_rubyzip.rb +115 -0
  110. data/examples/rubyzip_compatibility_demo.rb +194 -0
  111. data/exe/omnizip +27 -0
  112. data/lib/omnizip/algorithm.rb +176 -0
  113. data/lib/omnizip/algorithm_registry.rb +65 -0
  114. data/lib/omnizip/algorithms/.keep +0 -0
  115. data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
  116. data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
  117. data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
  118. data/lib/omnizip/algorithms/bzip2.rb +108 -0
  119. data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
  120. data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
  121. data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
  122. data/lib/omnizip/algorithms/deflate.rb +135 -0
  123. data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
  124. data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
  125. data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
  126. data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
  127. data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
  128. data/lib/omnizip/algorithms/deflate64.rb +118 -0
  129. data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
  130. data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
  131. data/lib/omnizip/algorithms/lzma/decoder.rb +146 -0
  132. data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
  133. data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
  134. data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
  135. data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
  136. data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
  137. data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
  138. data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
  139. data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
  140. data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -0
  141. data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
  142. data/lib/omnizip/algorithms/lzma/match.rb +32 -0
  143. data/lib/omnizip/algorithms/lzma/match_finder.rb +233 -0
  144. data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
  145. data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
  146. data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
  147. data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
  148. data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
  149. data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
  150. data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
  151. data/lib/omnizip/algorithms/lzma/state.rb +127 -0
  152. data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
  153. data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
  154. data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
  155. data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
  156. data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
  157. data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
  158. data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
  159. data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
  160. data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
  161. data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
  162. data/lib/omnizip/algorithms/lzma.rb +266 -0
  163. data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
  164. data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
  165. data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
  166. data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
  167. data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
  168. data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
  169. data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
  170. data/lib/omnizip/algorithms/lzma2.rb +133 -0
  171. data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
  172. data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
  173. data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
  174. data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
  175. data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
  176. data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
  177. data/lib/omnizip/algorithms/ppmd7.rb +146 -0
  178. data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
  179. data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
  180. data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
  181. data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
  182. data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
  183. data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
  184. data/lib/omnizip/algorithms/ppmd8.rb +122 -0
  185. data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
  186. data/lib/omnizip/algorithms/registration.rb +28 -0
  187. data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
  188. data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
  189. data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
  190. data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
  191. data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
  192. data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
  193. data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
  194. data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
  195. data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
  196. data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
  197. data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
  198. data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
  199. data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
  200. data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
  201. data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
  202. data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
  203. data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
  204. data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
  205. data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
  206. data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
  207. data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
  208. data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
  209. data/lib/omnizip/algorithms/zstandard.rb +210 -0
  210. data/lib/omnizip/algorithms.rb +35 -0
  211. data/lib/omnizip/archive/builder.rb +48 -0
  212. data/lib/omnizip/archive/reader_session.rb +67 -0
  213. data/lib/omnizip/archive.rb +86 -0
  214. data/lib/omnizip/archive_handler.rb +82 -0
  215. data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
  216. data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
  217. data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
  218. data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
  219. data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
  220. data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
  221. data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
  222. data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
  223. data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
  224. data/lib/omnizip/archive_handlers.rb +18 -0
  225. data/lib/omnizip/backends.rb +160 -0
  226. data/lib/omnizip/buffer/memory_archive.rb +246 -0
  227. data/lib/omnizip/buffer/memory_extractor.rb +234 -0
  228. data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
  229. data/lib/omnizip/buffer.rb +187 -0
  230. data/lib/omnizip/checksum_registry.rb +41 -0
  231. data/lib/omnizip/checksums/crc32.rb +101 -0
  232. data/lib/omnizip/checksums/crc64.rb +102 -0
  233. data/lib/omnizip/checksums/crc_base.rb +158 -0
  234. data/lib/omnizip/checksums/registration.rb +16 -0
  235. data/lib/omnizip/checksums/verifier.rb +130 -0
  236. data/lib/omnizip/checksums.rb +11 -0
  237. data/lib/omnizip/chunked/memory_manager.rb +194 -0
  238. data/lib/omnizip/chunked/reader.rb +78 -0
  239. data/lib/omnizip/chunked/writer.rb +123 -0
  240. data/lib/omnizip/chunked.rb +123 -0
  241. data/lib/omnizip/cli/output_formatter.rb +112 -0
  242. data/lib/omnizip/cli.rb +604 -0
  243. data/lib/omnizip/commands/.keep +0 -0
  244. data/lib/omnizip/commands/archive_create_command.rb +245 -0
  245. data/lib/omnizip/commands/archive_extract_command.rb +231 -0
  246. data/lib/omnizip/commands/archive_list_command.rb +204 -0
  247. data/lib/omnizip/commands/archive_repair_command.rb +129 -0
  248. data/lib/omnizip/commands/archive_verify_command.rb +115 -0
  249. data/lib/omnizip/commands/compress_command.rb +115 -0
  250. data/lib/omnizip/commands/decompress_command.rb +149 -0
  251. data/lib/omnizip/commands/list_command.rb +51 -0
  252. data/lib/omnizip/commands/metadata_command.rb +215 -0
  253. data/lib/omnizip/commands/parity_create_command.rb +114 -0
  254. data/lib/omnizip/commands/parity_repair_command.rb +120 -0
  255. data/lib/omnizip/commands/parity_verify_command.rb +122 -0
  256. data/lib/omnizip/commands/profile_list_command.rb +54 -0
  257. data/lib/omnizip/commands/profile_show_command.rb +44 -0
  258. data/lib/omnizip/commands.rb +21 -0
  259. data/lib/omnizip/convenience.rb +389 -0
  260. data/lib/omnizip/converter/conversion_registry.rb +50 -0
  261. data/lib/omnizip/converter/conversion_strategy.rb +108 -0
  262. data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
  263. data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
  264. data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
  265. data/lib/omnizip/converter.rb +124 -0
  266. data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
  267. data/lib/omnizip/crypto/aes256/constants.rb +28 -0
  268. data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
  269. data/lib/omnizip/crypto/aes256.rb +102 -0
  270. data/lib/omnizip/crypto.rb +11 -0
  271. data/lib/omnizip/entry.rb +44 -0
  272. data/lib/omnizip/error.rb +110 -0
  273. data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
  274. data/lib/omnizip/eta/moving_average_estimator.rb +96 -0
  275. data/lib/omnizip/eta/rate_calculator.rb +104 -0
  276. data/lib/omnizip/eta/sample_history.rb +143 -0
  277. data/lib/omnizip/eta/time_estimator.rb +106 -0
  278. data/lib/omnizip/eta.rb +68 -0
  279. data/lib/omnizip/extraction/filter_chain.rb +179 -0
  280. data/lib/omnizip/extraction/glob_pattern.rb +140 -0
  281. data/lib/omnizip/extraction/pattern_matcher.rb +66 -0
  282. data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
  283. data/lib/omnizip/extraction/regex_pattern.rb +50 -0
  284. data/lib/omnizip/extraction/selective_extractor.rb +247 -0
  285. data/lib/omnizip/extraction.rb +115 -0
  286. data/lib/omnizip/file_type/mime_classifier.rb +144 -0
  287. data/lib/omnizip/file_type.rb +117 -0
  288. data/lib/omnizip/filter.rb +141 -0
  289. data/lib/omnizip/filter_pipeline.rb +108 -0
  290. data/lib/omnizip/filter_registry.rb +113 -0
  291. data/lib/omnizip/filters/bcj.rb +277 -0
  292. data/lib/omnizip/filters/bcj2/constants.rb +53 -0
  293. data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
  294. data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
  295. data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
  296. data/lib/omnizip/filters/bcj2.rb +93 -0
  297. data/lib/omnizip/filters/bcj_arm.rb +174 -0
  298. data/lib/omnizip/filters/bcj_arm64.rb +242 -0
  299. data/lib/omnizip/filters/bcj_ia64.rb +194 -0
  300. data/lib/omnizip/filters/bcj_ppc.rb +188 -0
  301. data/lib/omnizip/filters/bcj_sparc.rb +174 -0
  302. data/lib/omnizip/filters/bcj_x86.rb +191 -0
  303. data/lib/omnizip/filters/delta.rb +195 -0
  304. data/lib/omnizip/filters/xz_delta.rb +258 -0
  305. data/lib/omnizip/filters.rb +20 -0
  306. data/lib/omnizip/format_detector.rb +166 -0
  307. data/lib/omnizip/formats/.keep +0 -0
  308. data/lib/omnizip/formats/bzip2_file.rb +159 -0
  309. data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
  310. data/lib/omnizip/formats/cpio/constants.rb +55 -0
  311. data/lib/omnizip/formats/cpio/entry.rb +389 -0
  312. data/lib/omnizip/formats/cpio/reader.rb +194 -0
  313. data/lib/omnizip/formats/cpio/writer.rb +232 -0
  314. data/lib/omnizip/formats/cpio.rb +132 -0
  315. data/lib/omnizip/formats/format_spec_loader.rb +228 -0
  316. data/lib/omnizip/formats/gzip.rb +236 -0
  317. data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
  318. data/lib/omnizip/formats/iso/directory_record.rb +162 -0
  319. data/lib/omnizip/formats/iso/joliet.rb +204 -0
  320. data/lib/omnizip/formats/iso/path_table.rb +125 -0
  321. data/lib/omnizip/formats/iso/reader.rb +194 -0
  322. data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
  323. data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
  324. data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
  325. data/lib/omnizip/formats/iso/writer.rb +543 -0
  326. data/lib/omnizip/formats/iso.rb +133 -0
  327. data/lib/omnizip/formats/lzip.rb +161 -0
  328. data/lib/omnizip/formats/lzma_alone.rb +149 -0
  329. data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
  330. data/lib/omnizip/formats/msi/constants.rb +157 -0
  331. data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
  332. data/lib/omnizip/formats/msi/entry.rb +134 -0
  333. data/lib/omnizip/formats/msi/reader.rb +301 -0
  334. data/lib/omnizip/formats/msi/string_pool.rb +246 -0
  335. data/lib/omnizip/formats/msi/table_parser.rb +244 -0
  336. data/lib/omnizip/formats/msi.rb +73 -0
  337. data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
  338. data/lib/omnizip/formats/ole/constants.rb +61 -0
  339. data/lib/omnizip/formats/ole/dirent.rb +439 -0
  340. data/lib/omnizip/formats/ole/header.rb +199 -0
  341. data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
  342. data/lib/omnizip/formats/ole/storage.rb +482 -0
  343. data/lib/omnizip/formats/ole/types/variant.rb +338 -0
  344. data/lib/omnizip/formats/ole.rb +143 -0
  345. data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
  346. data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
  347. data/lib/omnizip/formats/rar/block_parser.rb +282 -0
  348. data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
  349. data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
  350. data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
  351. data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -0
  352. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
  353. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
  354. data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
  355. data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
  356. data/lib/omnizip/formats/rar/compression/lz77_huffman.rb +25 -0
  357. data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
  358. data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
  359. data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
  360. data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
  361. data/lib/omnizip/formats/rar/compression.rb +17 -0
  362. data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
  363. data/lib/omnizip/formats/rar/constants.rb +88 -0
  364. data/lib/omnizip/formats/rar/decompressor.rb +316 -0
  365. data/lib/omnizip/formats/rar/external_writer.rb +311 -0
  366. data/lib/omnizip/formats/rar/header.rb +209 -0
  367. data/lib/omnizip/formats/rar/license_validator.rb +111 -0
  368. data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
  369. data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
  370. data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
  371. data/lib/omnizip/formats/rar/models.rb +14 -0
  372. data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
  373. data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
  374. data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -0
  375. data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
  376. data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
  377. data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +96 -0
  378. data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
  379. data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
  380. data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
  381. data/lib/omnizip/formats/rar/rar5/header.rb +208 -0
  382. data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
  383. data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
  384. data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
  385. data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
  386. data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
  387. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +260 -0
  388. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
  389. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +176 -0
  390. data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
  391. data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
  392. data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
  393. data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
  394. data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
  395. data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
  396. data/lib/omnizip/formats/rar/reader.rb +377 -0
  397. data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
  398. data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
  399. data/lib/omnizip/formats/rar/writer.rb +437 -0
  400. data/lib/omnizip/formats/rar.rb +193 -0
  401. data/lib/omnizip/formats/rar3/compressor.rb +71 -0
  402. data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
  403. data/lib/omnizip/formats/rar3/reader.rb +107 -0
  404. data/lib/omnizip/formats/rar3/writer.rb +220 -0
  405. data/lib/omnizip/formats/rar3.rb +15 -0
  406. data/lib/omnizip/formats/rar5/compressor.rb +71 -0
  407. data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
  408. data/lib/omnizip/formats/rar5/reader.rb +130 -0
  409. data/lib/omnizip/formats/rar5/writer.rb +65 -0
  410. data/lib/omnizip/formats/rar5.rb +15 -0
  411. data/lib/omnizip/formats/rpm/constants.rb +58 -0
  412. data/lib/omnizip/formats/rpm/entry.rb +106 -0
  413. data/lib/omnizip/formats/rpm/header.rb +106 -0
  414. data/lib/omnizip/formats/rpm/lead.rb +132 -0
  415. data/lib/omnizip/formats/rpm/tag.rb +228 -0
  416. data/lib/omnizip/formats/rpm/writer.rb +652 -0
  417. data/lib/omnizip/formats/rpm.rb +458 -0
  418. data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
  419. data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
  420. data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
  421. data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
  422. data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
  423. data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
  424. data/lib/omnizip/formats/seven_zip/header.rb +102 -0
  425. data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
  426. data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
  427. data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
  428. data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
  429. data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
  430. data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
  431. data/lib/omnizip/formats/seven_zip/models.rb +20 -0
  432. data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
  433. data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
  434. data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
  435. data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
  436. data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
  437. data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
  438. data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
  439. data/lib/omnizip/formats/seven_zip.rb +179 -0
  440. data/lib/omnizip/formats/tar/constants.rb +73 -0
  441. data/lib/omnizip/formats/tar/entry.rb +98 -0
  442. data/lib/omnizip/formats/tar/header.rb +206 -0
  443. data/lib/omnizip/formats/tar/reader.rb +119 -0
  444. data/lib/omnizip/formats/tar/writer.rb +212 -0
  445. data/lib/omnizip/formats/tar.rb +74 -0
  446. data/lib/omnizip/formats/xar/constants.rb +119 -0
  447. data/lib/omnizip/formats/xar/entry.rb +268 -0
  448. data/lib/omnizip/formats/xar/header.rb +223 -0
  449. data/lib/omnizip/formats/xar/reader.rb +400 -0
  450. data/lib/omnizip/formats/xar/toc.rb +570 -0
  451. data/lib/omnizip/formats/xar/writer.rb +461 -0
  452. data/lib/omnizip/formats/xar.rb +145 -0
  453. data/lib/omnizip/formats/xz/reader.rb +121 -0
  454. data/lib/omnizip/formats/xz/writer.rb +416 -0
  455. data/lib/omnizip/formats/xz.rb +210 -0
  456. data/lib/omnizip/formats/xz_const.rb +49 -0
  457. data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
  458. data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
  459. data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
  460. data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
  461. data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
  462. data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
  463. data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
  464. data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
  465. data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
  466. data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
  467. data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
  468. data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
  469. data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
  470. data/lib/omnizip/formats/xz_impl.rb +52 -0
  471. data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
  472. data/lib/omnizip/formats/zip/constants.rb +69 -0
  473. data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
  474. data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
  475. data/lib/omnizip/formats/zip/reader.rb +376 -0
  476. data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
  477. data/lib/omnizip/formats/zip/writer.rb +489 -0
  478. data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
  479. data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
  480. data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
  481. data/lib/omnizip/formats/zip.rb +50 -0
  482. data/lib/omnizip/formats.rb +29 -0
  483. data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
  484. data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
  485. data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
  486. data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
  487. data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
  488. data/lib/omnizip/implementations/base.rb +19 -0
  489. data/lib/omnizip/implementations/rust/archive.rb +93 -0
  490. data/lib/omnizip/implementations/rust/library.rb +221 -0
  491. data/lib/omnizip/implementations/rust.rb +26 -0
  492. data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
  493. data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
  494. data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
  495. data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
  496. data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
  497. data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
  498. data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
  499. data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
  500. data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
  501. data/lib/omnizip/implementations/seven_zip.rb +11 -0
  502. data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
  503. data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
  504. data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
  505. data/lib/omnizip/implementations/xz_utils.rb +10 -0
  506. data/lib/omnizip/implementations.rb +25 -0
  507. data/lib/omnizip/io/buffered_input.rb +147 -0
  508. data/lib/omnizip/io/buffered_output.rb +106 -0
  509. data/lib/omnizip/io/source.rb +143 -0
  510. data/lib/omnizip/io/stream_manager.rb +117 -0
  511. data/lib/omnizip/io.rb +15 -0
  512. data/lib/omnizip/link_handler/hard_link.rb +79 -0
  513. data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
  514. data/lib/omnizip/link_handler.rb +129 -0
  515. data/lib/omnizip/metadata/archive_metadata.rb +114 -0
  516. data/lib/omnizip/metadata/entry_metadata.rb +153 -0
  517. data/lib/omnizip/metadata/metadata_editor.rb +169 -0
  518. data/lib/omnizip/metadata/metadata_registry.rb +71 -0
  519. data/lib/omnizip/metadata/metadata_validator.rb +101 -0
  520. data/lib/omnizip/metadata.rb +58 -0
  521. data/lib/omnizip/models/.keep +0 -0
  522. data/lib/omnizip/models/algorithm_metadata.rb +41 -0
  523. data/lib/omnizip/models/attribute_apply.rb +40 -0
  524. data/lib/omnizip/models/compression_options.rb +53 -0
  525. data/lib/omnizip/models/conversion_options.rb +79 -0
  526. data/lib/omnizip/models/conversion_result.rb +141 -0
  527. data/lib/omnizip/models/eta_result.rb +45 -0
  528. data/lib/omnizip/models/extraction_rule.rb +115 -0
  529. data/lib/omnizip/models/filter_chain.rb +142 -0
  530. data/lib/omnizip/models/filter_config.rb +148 -0
  531. data/lib/omnizip/models/match_result.rb +141 -0
  532. data/lib/omnizip/models/optimization_suggestion.rb +95 -0
  533. data/lib/omnizip/models/parallel_options.rb +116 -0
  534. data/lib/omnizip/models/performance_result.rb +85 -0
  535. data/lib/omnizip/models/profile_report.rb +116 -0
  536. data/lib/omnizip/models/progress_options.rb +39 -0
  537. data/lib/omnizip/models/split_options.rb +116 -0
  538. data/lib/omnizip/optimization_registry.rb +45 -0
  539. data/lib/omnizip/parallel/engine.rb +52 -0
  540. data/lib/omnizip/parallel/job_queue.rb +209 -0
  541. data/lib/omnizip/parallel/job_scheduler.rb +225 -0
  542. data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
  543. data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
  544. data/lib/omnizip/parallel/thread_pool.rb +60 -0
  545. data/lib/omnizip/parallel/worker_pool.rb +227 -0
  546. data/lib/omnizip/parallel.rb +156 -0
  547. data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
  548. data/lib/omnizip/parity/galois16.rb +145 -0
  549. data/lib/omnizip/parity/models/creator_packet.rb +71 -0
  550. data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
  551. data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
  552. data/lib/omnizip/parity/models/main_packet.rb +126 -0
  553. data/lib/omnizip/parity/models/packet.rb +156 -0
  554. data/lib/omnizip/parity/models/packet_registry.rb +102 -0
  555. data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
  556. data/lib/omnizip/parity/models.rb +27 -0
  557. data/lib/omnizip/parity/par2_creator.rb +496 -0
  558. data/lib/omnizip/parity/par2_repairer.rb +409 -0
  559. data/lib/omnizip/parity/par2_verifier.rb +373 -0
  560. data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
  561. data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
  562. data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
  563. data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
  564. data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
  565. data/lib/omnizip/parity.rb +207 -0
  566. data/lib/omnizip/password/encryption_registry.rb +26 -0
  567. data/lib/omnizip/password/encryption_strategy.rb +96 -0
  568. data/lib/omnizip/password/password_validator.rb +129 -0
  569. data/lib/omnizip/password/winzip_aes_strategy.rb +190 -0
  570. data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
  571. data/lib/omnizip/password.rb +88 -0
  572. data/lib/omnizip/pipe/stream_compressor.rb +124 -0
  573. data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
  574. data/lib/omnizip/pipe.rb +120 -0
  575. data/lib/omnizip/platform/ntfs_streams.rb +200 -0
  576. data/lib/omnizip/platform.rb +189 -0
  577. data/lib/omnizip/profile/archive_profile.rb +36 -0
  578. data/lib/omnizip/profile/balanced_profile.rb +31 -0
  579. data/lib/omnizip/profile/binary_profile.rb +33 -0
  580. data/lib/omnizip/profile/compression_profile.rb +157 -0
  581. data/lib/omnizip/profile/custom_profile.rb +155 -0
  582. data/lib/omnizip/profile/fast_profile.rb +31 -0
  583. data/lib/omnizip/profile/maximum_profile.rb +31 -0
  584. data/lib/omnizip/profile/profile_detector.rb +108 -0
  585. data/lib/omnizip/profile/profile_registry.rb +160 -0
  586. data/lib/omnizip/profile/text_profile.rb +33 -0
  587. data/lib/omnizip/profile.rb +261 -0
  588. data/lib/omnizip/profiler/memory_profiler.rb +66 -0
  589. data/lib/omnizip/profiler/method_profiler.rb +49 -0
  590. data/lib/omnizip/profiler/report_generator.rb +158 -0
  591. data/lib/omnizip/profiler.rb +192 -0
  592. data/lib/omnizip/progress/callback_reporter.rb +34 -0
  593. data/lib/omnizip/progress/console_reporter.rb +59 -0
  594. data/lib/omnizip/progress/log_reporter.rb +89 -0
  595. data/lib/omnizip/progress/operation_progress.rb +118 -0
  596. data/lib/omnizip/progress/progress_bar.rb +156 -0
  597. data/lib/omnizip/progress/progress_reporter.rb +40 -0
  598. data/lib/omnizip/progress/progress_tracker.rb +215 -0
  599. data/lib/omnizip/progress/silent_reporter.rb +22 -0
  600. data/lib/omnizip/progress.rb +131 -0
  601. data/lib/omnizip/registry.rb +111 -0
  602. data/lib/omnizip/rubyzip_compat.rb +61 -0
  603. data/lib/omnizip/temp/safe_extract.rb +124 -0
  604. data/lib/omnizip/temp/temp_file.rb +123 -0
  605. data/lib/omnizip/temp/temp_file_pool.rb +109 -0
  606. data/lib/omnizip/temp.rb +184 -0
  607. data/lib/omnizip/version.rb +5 -0
  608. data/lib/omnizip/zip/entry.rb +160 -0
  609. data/lib/omnizip/zip/file.rb +485 -0
  610. data/lib/omnizip/zip/input_stream.rb +270 -0
  611. data/lib/omnizip/zip/output_stream.rb +320 -0
  612. data/lib/omnizip/zip.rb +23 -0
  613. data/lib/omnizip.rb +157 -0
  614. data/lib/tasks/msi_test_files.rake +66 -0
  615. data/lib/tasks/platform_gems.rake +147 -0
  616. data/lib/tasks/rust_backend.rake +48 -0
  617. data/readme-docs/advanced-features.adoc +514 -0
  618. data/readme-docs/api-usage.adoc +445 -0
  619. data/readme-docs/architecture.adoc +450 -0
  620. data/readme-docs/archive-formats.adoc +479 -0
  621. data/readme-docs/cli-usage.adoc +222 -0
  622. data/readme-docs/compression-algorithms.adoc +446 -0
  623. data/readme-docs/compression-profiles.adoc +247 -0
  624. data/readme-docs/encryption-checksums.adoc +328 -0
  625. data/readme-docs/format-converter.adoc +316 -0
  626. data/readme-docs/installation.adoc +228 -0
  627. data/readme-docs/par2-archives.adoc +608 -0
  628. data/readme-docs/performance-profiler.adoc +389 -0
  629. data/readme-docs/preprocessing-filters.adoc +280 -0
  630. data/vendor/libomnizip_ffi.so +0 -0
  631. data/xz-file-format-1.2.1.txt +1174 -0
  632. metadata +768 -0
@@ -0,0 +1,389 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ # Convenience methods for common archive operations.
5
+ #
6
+ # All public methods accept an optional +format:+ keyword (default
7
+ # +:zip+) that selects the underlying archive handler via
8
+ # +Omnizip::ArchiveHandler+. New formats gain access to the convenience
9
+ # API by registering a handler; no edits to this file are needed.
10
+ module Convenience
11
+ DEFAULT_FORMAT = :zip
12
+
13
+ # Compress a single file into an archive.
14
+ #
15
+ # @param input_path [String] Path to input file
16
+ # @param output_path [String] Path to output archive
17
+ # @param format [Symbol] Archive format (default +:zip+)
18
+ # @param options [Hash] Compression / format-specific options
19
+ # @return [String] +output_path+
20
+ def compress_file(input_path, output_path, format: DEFAULT_FORMAT, **options)
21
+ unless ::File.exist?(input_path)
22
+ raise Errno::ENOENT, "Input file not found: #{input_path}"
23
+ end
24
+ if ::File.directory?(input_path)
25
+ raise ArgumentError, "Input is a directory: #{input_path}"
26
+ end
27
+
28
+ options = Omnizip::Profile.apply(options, paths: input_path)
29
+
30
+ if options[:chunked]
31
+ return Omnizip::Chunked.compress_file(input_path, output_path, **options)
32
+ end
33
+
34
+ # Single-file compression formats route by output extension
35
+ # (unless an archive format was requested explicitly): writing
36
+ # output.lzma through the archive path silently produced a ZIP
37
+ # under a foreign extension.
38
+ if format == DEFAULT_FORMAT && (handler = single_file_handler(output_path))
39
+ handler.call(input_path, output_path, options)
40
+ return output_path
41
+ end
42
+
43
+ Omnizip::ArchiveHandler.for(resolve_archive_format(output_path, format)).create(output_path, **options) do |archive|
44
+ archive.add(::File.basename(input_path), input_path)
45
+ end
46
+
47
+ output_path
48
+ end
49
+
50
+ # Decompress a single-file compressed stream (the counterpart of
51
+ # #compress_file). The format is resolved from the input
52
+ # extension: .gz, .bz2, .xz, .lzma, .lz.
53
+ #
54
+ # @param compressed_path [String] Path to the compressed file
55
+ # @param output_path [String] Path to write the decompressed data
56
+ # @return [String] +output_path+
57
+ def decompress_file(compressed_path, output_path)
58
+ require_archive!(compressed_path)
59
+
60
+ decompressor = SINGLE_FILE_DECOMPRESSORS[::File.extname(compressed_path).downcase]
61
+ unless decompressor
62
+ raise Omnizip::UnsupportedFormatError,
63
+ "decompress_file supports #{SINGLE_FILE_DECOMPRESSORS.keys.join(', ')}; " \
64
+ "use extract_archive for archive formats"
65
+ end
66
+
67
+ decompressor.call(compressed_path, output_path)
68
+ output_path
69
+ end
70
+
71
+ # Compress a directory into an archive.
72
+ #
73
+ # @param input_dir [String] Path to input directory
74
+ # @param output_path [String] Path to output archive
75
+ # @param format [Symbol] Archive format (default +:zip+)
76
+ # @param recursive [Boolean] Include subdirectories (default +true+)
77
+ # @param options [Hash] Compression / format-specific options
78
+ # @return [String] +output_path+
79
+ def compress_directory(input_dir, output_path, format: DEFAULT_FORMAT,
80
+ recursive: true, **options)
81
+ unless ::File.exist?(input_dir)
82
+ raise Errno::ENOENT, "Input directory not found: #{input_dir}"
83
+ end
84
+ unless ::File.directory?(input_dir)
85
+ raise ArgumentError, "Input is not a directory: #{input_dir}"
86
+ end
87
+
88
+ # A directory cannot be written through a single-file stream
89
+ # format; routing it to the default would silently produce a
90
+ # ZIP under a foreign extension.
91
+ if format == DEFAULT_FORMAT && single_file_handler(output_path)
92
+ raise Omnizip::UnsupportedFormatError,
93
+ "#{::File.extname(output_path).downcase} is a single-file " \
94
+ "stream format and cannot contain a directory; use an " \
95
+ "archive format (.zip/.tar/.7z) or compress entries " \
96
+ "individually"
97
+ end
98
+
99
+ options = Omnizip::Profile.apply(options, paths: input_dir)
100
+
101
+ Omnizip::ArchiveHandler.for(resolve_archive_format(output_path, format)).create(output_path, **options) do |archive|
102
+ add_directory_contents(archive, input_dir, "", recursive: recursive)
103
+ end
104
+
105
+ output_path
106
+ end
107
+
108
+ # Extract an archive to a directory.
109
+ #
110
+ # @param archive_path [String] Path to archive
111
+ # @param output_dir [String] Output directory
112
+ # @param format [Symbol] Archive format (default +:zip+)
113
+ # @param overwrite [Boolean] Overwrite existing files (default +false+)
114
+ # @param options [Hash] Format-specific extraction options
115
+ # @return [Array<String>] Extracted file paths
116
+ def extract_archive(archive_path, output_dir, format: DEFAULT_FORMAT,
117
+ overwrite: false, **options)
118
+ require_archive!(archive_path)
119
+ Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format, writing: false))
120
+ .extract_to(archive_path, output_dir,
121
+ overwrite: overwrite, **options)
122
+ end
123
+
124
+ # List contents of an archive.
125
+ #
126
+ # @param archive_path [String] Path to archive
127
+ # @param format [Symbol] Archive format (default +:zip+)
128
+ # @param details [Boolean] Include detailed info (default +false+)
129
+ # @param options [Hash] Format-specific listing options
130
+ # @return [Array<String>, Array<Hash>]
131
+ def list_archive(archive_path, format: DEFAULT_FORMAT, details: false,
132
+ **options)
133
+ require_archive!(archive_path)
134
+ Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format, writing: false))
135
+ .list(archive_path, details: details, **options)
136
+ end
137
+
138
+ # Read a single entry from an archive.
139
+ #
140
+ # @param archive_path [String] Path to archive
141
+ # @param entry_name [String] Entry to read
142
+ # @param format [Symbol] Archive format (default +:zip+)
143
+ # @return [String] Entry contents
144
+ def read_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT)
145
+ require_archive!(archive_path)
146
+ Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format, writing: false)).read_entry(archive_path, entry_name)
147
+ end
148
+
149
+ # Add a file to an existing archive.
150
+ #
151
+ # @param archive_path [String] Path to archive
152
+ # @param entry_name [String] Entry name in archive
153
+ # @param source_path [String] Path to source file
154
+ # @param format [Symbol] Archive format (default +:zip+)
155
+ # @return [String] +archive_path+
156
+ def add_to_archive(archive_path, entry_name, source_path,
157
+ format: DEFAULT_FORMAT)
158
+ require_archive!(archive_path)
159
+ unless ::File.exist?(source_path)
160
+ raise Errno::ENOENT, "Source file not found: #{source_path}"
161
+ end
162
+
163
+ resolved = resolve_archive_format(archive_path, format)
164
+ handler = Omnizip::ArchiveHandler.for(resolved)
165
+ # allowed: handler is a registered duck; missing add_entry raises below
166
+ if handler.respond_to?(:add_entry)
167
+ handler.add_entry(archive_path, entry_name, source_path)
168
+ else
169
+ raise Omnizip::UnsupportedFormatError,
170
+ "Format #{resolved.inspect} does not support adding entries"
171
+ end
172
+
173
+ archive_path
174
+ end
175
+
176
+ # Remove an entry from an existing archive.
177
+ #
178
+ # @param archive_path [String] Path to archive
179
+ # @param entry_name [String] Entry to remove
180
+ # @param format [Symbol] Archive format (default +:zip+)
181
+ # @return [String] +archive_path+
182
+ def remove_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT)
183
+ require_archive!(archive_path)
184
+ resolved = resolve_archive_format(archive_path, format)
185
+ handler = Omnizip::ArchiveHandler.for(resolved)
186
+ # allowed: handler is a registered duck; missing remove_entry raises below
187
+ unless handler.respond_to?(:remove_entry)
188
+ raise Omnizip::UnsupportedFormatError,
189
+ "Format #{resolved.inspect} does not support removing entries"
190
+ end
191
+
192
+ handler.remove_entry(archive_path, entry_name)
193
+ archive_path
194
+ end
195
+
196
+ # Create a RAR archive through the RAR handler. RAR5 unless
197
+ # +version: 4+; the block yields the same generic writer
198
+ # interface as +Archive.create+ (+add+/+add_data+/+add_directory+).
199
+ #
200
+ # @param archive_path [String] Path to output archive
201
+ # @param options [Hash] RAR writer options
202
+ # @return [String, Array<String>] Path(s) of the created archive
203
+ # rubocop:disable-next Naming/BlockForwarding, Style/ArgumentsForwarding -- Ruby 3.0 compatibility
204
+ def create_rar(archive_path, **options, &block)
205
+ options[:version] ||= 5
206
+ Omnizip::ArchiveHandler.for(:rar).create(archive_path, **options, &block)
207
+ end
208
+
209
+ # Extension -> single-file compressor map. Each lambda takes
210
+ # (input_path, output_path, options). These formats are streams,
211
+ # not archives, so they bypass ArchiveHandler.
212
+ # Extensions naming archive formats with a registered handler;
213
+ # routed when the caller did not pass an explicit +format:+.
214
+ ARCHIVE_FORMAT_EXTENSIONS = {
215
+ ".zip" => :zip,
216
+ ".tar" => :tar,
217
+ ".7z" => :seven_zip,
218
+ ".rar" => :rar,
219
+ }.freeze
220
+
221
+ # Extensions naming formats with read-only convenience routing.
222
+ # Writing them a ZIP under a foreign name was silent corruption;
223
+ # creation raises truthfully instead (the format-level writers
224
+ # exist for CPIO/ISO but are not part of the archive API; RAR
225
+ # moved to the writable routes when its handler gained create).
226
+ READ_ONLY_FORMAT_EXTENSIONS = %w[.iso .cpio .rpm .xar .msi].freeze
227
+
228
+ # Extensions whose format has a READ-ONLY handler: extraction and
229
+ # listing route to it, while creation keeps raising.
230
+ READ_ARCHIVE_FORMAT_EXTENSIONS = {
231
+ ".rar" => :rar,
232
+ ".cpio" => :cpio,
233
+ ".iso" => :iso,
234
+ ".rpm" => :rpm,
235
+ ".xar" => :xar,
236
+ ".msi" => :ole,
237
+ }.freeze
238
+
239
+ # Extension -> single-file decompressor. Each lambda takes
240
+ # (compressed_path, output_path) and writes the decompressed
241
+ # bytes; these formats are streams, not archives, so they bypass
242
+ # ArchiveHandler (mirrors SINGLE_FILE_COMPRESSORS). Xz exposes a
243
+ # path-based decompress rather than a stream one.
244
+ SINGLE_FILE_DECOMPRESSORS = {
245
+ ".gz" => lambda do |compressed, output|
246
+ ::File.open(compressed, "rb") do |input_io|
247
+ ::File.open(output, "wb") do |output_io|
248
+ Omnizip::Formats::Gzip.decompress_stream(input_io, output_io)
249
+ end
250
+ end
251
+ end,
252
+ ".bz2" => lambda do |compressed, output|
253
+ ::File.open(compressed, "rb") do |input_io|
254
+ ::File.open(output, "wb") do |output_io|
255
+ Omnizip::Formats::Bzip2File.decompress_stream(input_io, output_io)
256
+ end
257
+ end
258
+ end,
259
+ ".xz" => lambda do |compressed, output|
260
+ ::File.binwrite(output, Omnizip::Formats::Xz.decompress(compressed))
261
+ end,
262
+ ".lzma" => lambda do |compressed, output|
263
+ ::File.open(compressed, "rb") do |input_io|
264
+ ::File.open(output, "wb") do |output_io|
265
+ Omnizip::Formats::LzmaAlone.decompress_stream(input_io, output_io)
266
+ end
267
+ end
268
+ end,
269
+ ".lz" => lambda do |compressed, output|
270
+ ::File.open(compressed, "rb") do |input_io|
271
+ ::File.open(output, "wb") do |output_io|
272
+ Omnizip::Formats::Lzip.decompress_stream(input_io, output_io)
273
+ end
274
+ end
275
+ end,
276
+ ".zst" => lambda do |compressed, output|
277
+ ::File.open(compressed, "rb") do |input_io|
278
+ ::File.open(output, "wb") do |output_io|
279
+ Omnizip::Algorithms::Zstandard.new.decompress(input_io, output_io)
280
+ end
281
+ end
282
+ end,
283
+ }.freeze
284
+
285
+ SINGLE_FILE_COMPRESSORS = {
286
+ ".gz" => lambda do |input, output, options|
287
+ Omnizip::Formats::Gzip.compress(input, output, options)
288
+ end,
289
+ ".bz2" => lambda do |input, output, options|
290
+ Omnizip::Formats::Bzip2File.compress(input, output, options)
291
+ end,
292
+ ".xz" => lambda do |input, output, options|
293
+ Omnizip::Formats::Xz.create(::File.binread(input), output, options)
294
+ end,
295
+ ".lzma" => lambda do |input, output, options|
296
+ ::File.open(input, "rb") do |input_io|
297
+ ::File.open(output, "wb") do |output_io|
298
+ Omnizip::Formats::LzmaAlone.compress_stream(input_io, output_io,
299
+ options)
300
+ end
301
+ end
302
+ end,
303
+ ".lz" => lambda do |input, output, options|
304
+ ::File.open(input, "rb") do |input_io|
305
+ ::File.open(output, "wb") do |output_io|
306
+ Omnizip::Formats::Lzip.compress_stream(input_io, output_io,
307
+ options)
308
+ end
309
+ end
310
+ end,
311
+ ".zst" => lambda do |input, output, options|
312
+ ::File.open(input, "rb") do |input_io|
313
+ ::File.open(output, "wb") do |output_io|
314
+ Omnizip::Algorithms::Zstandard.new.compress(input_io, output_io,
315
+ options)
316
+ end
317
+ end
318
+ end,
319
+ }.freeze
320
+
321
+ # The single-file compressor matching the output extension, or nil.
322
+ def single_file_handler(output_path)
323
+ ext = ::File.extname(output_path).downcase
324
+ SINGLE_FILE_COMPRESSORS[ext]
325
+ end
326
+
327
+ # Archive format for a path: an explicit +format+ wins unless it
328
+ # is the default; otherwise the extension routes. Known-but-
329
+ # unwritable extensions raise instead of receiving a mislabeled
330
+ # ZIP. +writing:+ false (read operations) additionally routes
331
+ # extensions with read-only handlers.
332
+ def resolve_archive_format(path, format, writing: true)
333
+ return format unless format == DEFAULT_FORMAT
334
+
335
+ ext = ::File.extname(path).downcase
336
+ routed = ARCHIVE_FORMAT_EXTENSIONS[ext]
337
+ routed ||= READ_ARCHIVE_FORMAT_EXTENSIONS[ext] unless writing
338
+ return routed if routed
339
+
340
+ if READ_ONLY_FORMAT_EXTENSIONS.include?(ext)
341
+ raise Omnizip::UnsupportedFormatError,
342
+ "#{ext} archives cannot be written by the convenience " \
343
+ "API (read-only support); use the format-specific reader"
344
+ end
345
+
346
+ DEFAULT_FORMAT
347
+ end
348
+
349
+ private
350
+
351
+ def require_archive!(archive_path)
352
+ return if ::File.exist?(archive_path)
353
+
354
+ raise Errno::ENOENT, "Archive not found: #{archive_path}"
355
+ end
356
+
357
+ # Recursively add directory contents to an archive. The +archive+
358
+ # argument is whatever the handler's +#create+ block yields (e.g.
359
+ # +Omnizip::Zip::File+ or +Omnizip::Formats::Tar::Writer+) and must
360
+ # respond to +#add(entry_name, src_path = nil)+.
361
+ def add_directory_contents(archive, base_dir, relative_path, recursive: true)
362
+ dir_path = ::File.join(base_dir, relative_path)
363
+
364
+ Dir.foreach(dir_path) do |entry|
365
+ next if [".", ".."].include?(entry)
366
+
367
+ full_path = ::File.join(dir_path, entry)
368
+ archive_path = if relative_path.empty?
369
+ entry
370
+ else
371
+ ::File.join(relative_path, entry)
372
+ end
373
+
374
+ if ::File.directory?(full_path)
375
+ dir_entry_name = archive_path.end_with?("/") ? archive_path : "#{archive_path}/"
376
+ archive.add(dir_entry_name)
377
+ if recursive
378
+ add_directory_contents(archive, base_dir, archive_path,
379
+ recursive: recursive)
380
+ end
381
+ else
382
+ archive.add(archive_path, full_path)
383
+ end
384
+ end
385
+ end
386
+ end
387
+
388
+ extend Convenience
389
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Converter
5
+ # Registry for conversion strategies
6
+ class ConversionRegistry
7
+ @strategies = []
8
+
9
+ class << self
10
+ # Register a conversion strategy
11
+ # @param strategy_class [Class] Strategy class
12
+ def register(strategy_class)
13
+ @strategies << strategy_class unless @strategies.include?(strategy_class)
14
+ end
15
+
16
+ # Find strategy for source and target formats
17
+ # @param source [String] Source file path
18
+ # @param target [String] Target file path
19
+ # @return [Class, nil] Strategy class or nil
20
+ def find_strategy(source, target)
21
+ @strategies.find { |strategy| strategy.can_convert?(source, target) }
22
+ end
23
+
24
+ # Get all registered strategies
25
+ # @return [Array<Class>] List of strategy classes
26
+ def strategies
27
+ @strategies
28
+ end
29
+
30
+ # Check if conversion is supported
31
+ # @param source [String] Source file path
32
+ # @param target [String] Target file path
33
+ # @return [Boolean] True if supported
34
+ def supported?(source, target)
35
+ !find_strategy(source, target).nil?
36
+ end
37
+
38
+ # Reset registry (for testing)
39
+ def reset
40
+ @strategies = []
41
+ end
42
+ end
43
+ end
44
+
45
+ # Register built-in strategies
46
+ ConversionRegistry.register(ZipToSevenZipStrategy)
47
+ ConversionRegistry.register(SevenZipToZipStrategy)
48
+ ConversionRegistry.register(ExtractRepackStrategy)
49
+ end
50
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Converter
5
+ # Base class for archive format conversion strategies
6
+ class ConversionStrategy
7
+ attr_reader :source_path, :target_path, :options
8
+
9
+ # Initialize conversion strategy
10
+ # @param source_path [String] Source archive path
11
+ # @param target_path [String] Target archive path
12
+ # @param options [ConversionOptions] Conversion options
13
+ def initialize(source_path, target_path, options)
14
+ @source_path = source_path
15
+ @target_path = target_path
16
+ @options = options
17
+ @warnings = []
18
+ end
19
+
20
+ # Perform the conversion
21
+ # @return [ConversionResult] Conversion result
22
+ # @raise [NotImplementedError] Subclasses must implement
23
+ def convert
24
+ raise NotImplementedError, "#{self.class} must implement #convert"
25
+ end
26
+
27
+ # Get source format
28
+ # @return [Symbol] Source format
29
+ # @raise [NotImplementedError] Subclasses must implement
30
+ def source_format
31
+ raise NotImplementedError, "#{self.class} must implement #source_format"
32
+ end
33
+
34
+ # Get target format
35
+ # @return [Symbol] Target format
36
+ # @raise [NotImplementedError] Subclasses must implement
37
+ def target_format
38
+ raise NotImplementedError, "#{self.class} must implement #target_format"
39
+ end
40
+
41
+ # Check if this strategy can handle the conversion
42
+ # @param source [String] Source file path
43
+ # @param target [String] Target file path
44
+ # @return [Boolean] True if can handle
45
+ def self.can_convert?(_source, _target)
46
+ false
47
+ end
48
+
49
+ protected
50
+
51
+ # Add a warning message
52
+ # @param message [String] Warning message
53
+ def add_warning(message)
54
+ @warnings << message
55
+ end
56
+
57
+ # Get all warnings
58
+ # @return [Array<String>] List of warnings
59
+ def warnings
60
+ @warnings
61
+ end
62
+
63
+ # Repack the extracted tree under +extracted_dir+ into a new
64
+ # archive at +target_path+ through the Archive facade (the
65
+ # format is resolved from the target's extension). Directory
66
+ # entries are implied by file paths, matching every strategy's
67
+ # treatment. Returns the number of file entries written.
68
+ #
69
+ # @param extracted_dir [String] Directory of extracted entries
70
+ # @param write_options [Hash] Format writer options
71
+ # @return [Integer] Number of file entries written
72
+ def repack_tree(extracted_dir, **write_options)
73
+ count = 0
74
+ Omnizip::Archive.create(target_path, **write_options) do |archive|
75
+ Dir.glob(File.join(extracted_dir, "**", "*")).each do |path|
76
+ next if File.directory?(path)
77
+
78
+ archive.add_file(path, path.delete_prefix("#{extracted_dir}/"))
79
+ count += 1
80
+ end
81
+ end
82
+ count
83
+ end
84
+
85
+ # Create conversion result
86
+ # @param start_time [Time] Start time
87
+ # @param entry_count [Integer] Number of entries
88
+ # @return [ConversionResult] Result object
89
+ def create_result(start_time, entry_count)
90
+ duration = Time.now - start_time
91
+ source_size = File.size(source_path)
92
+ target_size = File.size(target_path)
93
+
94
+ Omnizip::Models::ConversionResult.new(
95
+ source_path: source_path,
96
+ target_path: target_path,
97
+ source_format: source_format,
98
+ target_format: target_format,
99
+ source_size: source_size,
100
+ target_size: target_size,
101
+ duration: duration,
102
+ entry_count: entry_count,
103
+ warnings: warnings,
104
+ )
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string: true
2
+
3
+ require "tmpdir"
4
+
5
+ module Omnizip
6
+ module Converter
7
+ # Fallback conversion strategy: extract any routed source format
8
+ # and repack the tree into any writable target format, both
9
+ # through the handler registry. Registered after the direct
10
+ # entry-copy strategies, which keep precedence for their pairs.
11
+ class ExtractRepackStrategy < ConversionStrategy
12
+ WRITABLE_FORMATS = %i[zip seven_zip tar rar].freeze
13
+
14
+ # Any routed source extension converts to any writable target
15
+ def self.can_convert?(source, _target)
16
+ !source_format_for(source).nil? &&
17
+ WRITABLE_FORMATS.include?(target_format_for(_target))
18
+ end
19
+
20
+ # Routed read-side format for an extension, or nil
21
+ def self.source_format_for(path)
22
+ ext = File.extname(path).downcase
23
+ Convenience::ARCHIVE_FORMAT_EXTENSIONS[ext] ||
24
+ Convenience::READ_ARCHIVE_FORMAT_EXTENSIONS[ext]
25
+ end
26
+
27
+ # Writable format for a target extension, or nil
28
+ def self.target_format_for(path)
29
+ Convenience::ARCHIVE_FORMAT_EXTENSIONS[File.extname(path).downcase]
30
+ end
31
+
32
+ def convert
33
+ start_time = Time.now
34
+
35
+ Dir.mktmpdir("omnizip_convert_repack") do |tmp|
36
+ extracted = Omnizip.extract_archive(source_path, tmp)
37
+ repack_tree(tmp)
38
+ create_result(start_time, extracted.size)
39
+ end
40
+ end
41
+
42
+ def source_format
43
+ self.class.source_format_for(source_path) || :unknown
44
+ end
45
+
46
+ def target_format
47
+ self.class.target_format_for(target_path) || :unknown
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tmpdir"
4
+
5
+ module Omnizip
6
+ module Converter
7
+ # Convert 7-Zip archives to ZIP format
8
+ class SevenZipToZipStrategy < ConversionStrategy
9
+ # Perform 7z to ZIP conversion
10
+ # @return [ConversionResult] Conversion result
11
+ def convert
12
+ start_time = Time.now
13
+
14
+ entry_count = Dir.mktmpdir("omnizip_convert") do |tmp|
15
+ Omnizip.extract_archive(source_path, tmp)
16
+ repack_tree(tmp)
17
+ end
18
+
19
+ create_result(start_time, entry_count)
20
+ end
21
+
22
+ # Get source format
23
+ # @return [Symbol] Source format (:seven_zip)
24
+ def source_format
25
+ :seven_zip
26
+ end
27
+
28
+ # Get target format
29
+ # @return [Symbol] Target format (:zip)
30
+ def target_format
31
+ :zip
32
+ end
33
+
34
+ # Check if can convert
35
+ # @param source [String] Source file
36
+ # @param target [String] Target file
37
+ # @return [Boolean] True if can convert
38
+ def self.can_convert?(source, target)
39
+ source.end_with?(".7z") && target.end_with?(".zip")
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tmpdir"
4
+
5
+ module Omnizip
6
+ module Converter
7
+ # Convert ZIP archives to 7-Zip format
8
+ class ZipToSevenZipStrategy < ConversionStrategy
9
+ # Perform ZIP to 7z conversion
10
+ # @return [ConversionResult] Conversion result
11
+ def convert
12
+ start_time = Time.now
13
+
14
+ entry_count = Dir.mktmpdir("omnizip_convert_zip") do |tmp|
15
+ # Directories are implied by extracted file paths
16
+ Omnizip.extract_archive(source_path, tmp)
17
+ repack_tree(tmp, **writer_options)
18
+ end
19
+
20
+ create_result(start_time, entry_count)
21
+ end
22
+
23
+ # Get source format
24
+ # @return [Symbol] Source format (:zip)
25
+ def source_format
26
+ :zip
27
+ end
28
+
29
+ # Get target format
30
+ # @return [Symbol] Target format (:seven_zip)
31
+ def target_format
32
+ :seven_zip
33
+ end
34
+
35
+ # Check if can convert
36
+ # @param source [String] Source file
37
+ # @param target [String] Target file
38
+ # @return [Boolean] True if can convert
39
+ def self.can_convert?(source, target)
40
+ source.end_with?(".zip") && target.end_with?(".7z")
41
+ end
42
+
43
+ private
44
+
45
+ # SevenZip::Writer takes algorithm/level/solid as keywords
46
+ def writer_options
47
+ {
48
+ algorithm: options.compression || :lzma2,
49
+ level: options.compression_level || 5,
50
+ }
51
+ end
52
+ end
53
+ end
54
+ end