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,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (C) 2024 Ribose Inc.
5
+ #
6
+ # This file is part of Omnizip.
7
+ #
8
+ # Omnizip is a pure Ruby port of 7-Zip compression algorithms.
9
+ # Based on the 7-Zip LZMA SDK by Igor Pavlov.
10
+ #
11
+ # This library is free software; you can redistribute it and/or
12
+ # modify it under the terms of the GNU Lesser General Public
13
+ # License as published by the Free Software Foundation; either
14
+ # version 2.1 of the License, or (at your option) any later version.
15
+ #
16
+ # See the COPYING file for the complete text of the license.
17
+ #
18
+
19
+ require_relative "../cli/output_formatter"
20
+
21
+ module Omnizip
22
+ module Commands
23
+ # Command to list available compression algorithms.
24
+ class ListCommand
25
+ attr_reader :options
26
+
27
+ # Initialize list command with options.
28
+ #
29
+ # @param options [Hash] Command options from Thor
30
+ def initialize(options = {})
31
+ @options = options
32
+ end
33
+
34
+ # Execute the list command.
35
+ #
36
+ # @return [void]
37
+ def run
38
+ algorithms = fetch_algorithms
39
+ output = CliOutputFormatter.format_algorithms_table(algorithms)
40
+ puts output
41
+ end
42
+
43
+ private
44
+
45
+ def fetch_algorithms
46
+ AlgorithmRegistry.available.map do |name|
47
+ algorithm_class = AlgorithmRegistry.get(name)
48
+ algorithm_class.metadata
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../cli/output_formatter"
4
+
5
+ module Omnizip
6
+ module Commands
7
+ # Metadata command implementation
8
+ class MetadataCommand
9
+ attr_reader :options
10
+
11
+ def initialize(options = {})
12
+ @options = options
13
+ end
14
+
15
+ # Run the metadata command
16
+ # @param archive_path [String] Path to archive
17
+ # @param pattern [String, nil] Optional pattern to match entries
18
+ def run(archive_path, pattern = nil)
19
+ require_relative "../zip/file"
20
+ require_relative "../metadata"
21
+
22
+ unless File.exist?(archive_path)
23
+ raise Errno::ENOENT, "Archive not found: #{archive_path}"
24
+ end
25
+
26
+ Omnizip::Zip::File.open(archive_path) do |archive|
27
+ if options[:show]
28
+ show_metadata(archive, pattern)
29
+ else
30
+ edit_metadata(archive, pattern)
31
+ end
32
+ end
33
+
34
+ puts "Metadata updated successfully" unless options[:show]
35
+ end
36
+
37
+ private
38
+
39
+ def show_metadata(archive, pattern)
40
+ if pattern
41
+ # Show entry metadata
42
+ entry = archive.get_entry(pattern)
43
+ unless entry
44
+ warn "Entry not found: #{pattern}"
45
+ return
46
+ end
47
+
48
+ show_entry_metadata(entry)
49
+ else
50
+ # Show archive metadata
51
+ show_archive_metadata(archive)
52
+ end
53
+ end
54
+
55
+ def show_archive_metadata(archive)
56
+ metadata = archive.metadata
57
+ puts "Archive: #{archive.name}"
58
+ puts "Comment: #{metadata.comment}" unless metadata.comment.empty?
59
+ puts "Created: #{metadata.created_at}" if metadata.created_at
60
+ puts "Modified: #{metadata.modified_at}" if metadata.modified_at
61
+ puts "Entries: #{metadata.entry_count} (#{metadata.file_count} files, #{metadata.directory_count} dirs)"
62
+ puts "Total size: #{format_size(metadata.total_size)}"
63
+ puts "Compressed: #{format_size(metadata.total_compressed_size)}"
64
+ puts "Ratio: #{(metadata.compression_ratio * 100).round(1)}%"
65
+ end
66
+
67
+ def show_entry_metadata(entry)
68
+ metadata = entry.metadata
69
+ puts "Entry: #{entry.name}"
70
+ puts "Comment: #{metadata.comment}" unless metadata.comment.empty?
71
+ puts "Modified: #{metadata.mtime}"
72
+ puts "Permissions: 0#{metadata.unix_permissions.to_s(8)}"
73
+ puts "Size: #{format_size(entry.size)}"
74
+ puts "Compressed: #{format_size(entry.compressed_size)}"
75
+ puts "CRC32: 0x#{entry.crc.to_s(16).upcase}"
76
+ puts "Type: #{entry.directory? ? 'Directory' : 'File'}"
77
+ end
78
+
79
+ def edit_metadata(archive, pattern)
80
+ if pattern
81
+ edit_entry_metadata(archive, pattern)
82
+ else
83
+ edit_archive_metadata(archive)
84
+ end
85
+
86
+ archive.save_metadata
87
+ end
88
+
89
+ def edit_archive_metadata(archive)
90
+ metadata = archive.metadata
91
+
92
+ if options[:comment]
93
+ metadata.comment = options[:comment]
94
+ end
95
+ end
96
+
97
+ def edit_entry_metadata(archive, pattern)
98
+ entries = if pattern.include?("*") || pattern.include?("?")
99
+ # Glob pattern
100
+ archive.entries.select { |e| File.fnmatch(pattern, e.name) }
101
+ else
102
+ # Single entry
103
+ [archive.get_entry(pattern)].compact
104
+ end
105
+
106
+ if entries.empty?
107
+ warn "No entries match pattern: #{pattern}"
108
+ return
109
+ end
110
+
111
+ entries.each do |entry|
112
+ metadata = entry.metadata
113
+
114
+ metadata.comment = options[:comment] if options[:comment]
115
+ metadata.mtime = parse_time(options[:set_mtime]) if options[:set_mtime]
116
+ metadata.unix_permissions = parse_permissions(options[:chmod]) if options[:chmod]
117
+ metadata.attributes = options[:set_attribute].to_sym if options[:set_attribute]
118
+
119
+ entry.save_metadata
120
+ end
121
+
122
+ puts "Updated #{entries.size} #{entries.size == 1 ? 'entry' : 'entries'}" if options[:verbose]
123
+ end
124
+
125
+ def parse_time(time_str)
126
+ return Time.now if time_str == "now"
127
+
128
+ Time.parse(time_str)
129
+ rescue ArgumentError => e
130
+ raise ArgumentError, "Invalid time format: #{time_str} (#{e.message})"
131
+ end
132
+
133
+ def parse_permissions(perms_str)
134
+ # Handle octal (755) or decimal
135
+ if perms_str.start_with?("0")
136
+ perms_str.to_i(8)
137
+ else
138
+ perms_str.to_i
139
+ end
140
+ end
141
+
142
+ def format_size(bytes)
143
+ return "0 B" if bytes.zero?
144
+
145
+ units = %w[B KB MB GB TB]
146
+ exp = (Math.log(bytes) / Math.log(1024)).to_i
147
+ exp = [exp, units.size - 1].min
148
+
149
+ "%.1f %s" % [bytes.to_f / (1024**exp), units[exp]]
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../parity"
4
+
5
+ module Omnizip
6
+ module Commands
7
+ # Command to create PAR2 parity files
8
+ class ParityCreateCommand
9
+ # @return [Array<String>] Files to protect
10
+ attr_reader :files
11
+
12
+ # @return [Hash] Command options
13
+ attr_reader :options
14
+
15
+ # Initialize command
16
+ #
17
+ # @param files [Array<String>] Files or patterns to protect
18
+ # @param options [Hash] Command options
19
+ def initialize(files, options = {})
20
+ @files = files
21
+ @options = default_options.merge(options)
22
+ end
23
+
24
+ # Execute command
25
+ #
26
+ # @return [Integer] Exit code (0 for success)
27
+ def run
28
+ validate_inputs!
29
+
30
+ progress = create_progress_callback if @options[:verbose]
31
+
32
+ created_files = []
33
+ @files.each do |file_pattern|
34
+ par2_files = Parity.create(
35
+ file_pattern,
36
+ redundancy: @options[:redundancy],
37
+ block_size: @options[:block_size],
38
+ output_dir: @options[:output_dir],
39
+ progress: progress,
40
+ )
41
+
42
+ created_files.concat(par2_files)
43
+ end
44
+
45
+ report_success(created_files)
46
+ 0
47
+ rescue StandardError => e
48
+ report_error(e)
49
+ 1
50
+ end
51
+
52
+ private
53
+
54
+ # Default command options
55
+ #
56
+ # @return [Hash] Default options
57
+ def default_options
58
+ {
59
+ redundancy: 5,
60
+ block_size: Parity::Par2Creator::DEFAULT_BLOCK_SIZE,
61
+ output_dir: nil,
62
+ verbose: false,
63
+ }
64
+ end
65
+
66
+ # Validate command inputs
67
+ #
68
+ # @raise [ArgumentError] if inputs invalid
69
+ def validate_inputs!
70
+ raise ArgumentError, "No files specified" if @files.empty?
71
+
72
+ unless @options[:redundancy].between?(0, 100)
73
+ raise ArgumentError, "Redundancy must be 0-100%"
74
+ end
75
+ end
76
+
77
+ # Create progress callback
78
+ #
79
+ # @return [Proc] Progress callback
80
+ def create_progress_callback
81
+ ->(percent, message) do
82
+ puts "[#{percent.to_s.rjust(3)}%] #{message}"
83
+ end
84
+ end
85
+
86
+ # Report successful creation
87
+ #
88
+ # @param files [Array<String>] Created files
89
+ def report_success(files)
90
+ puts "\n✓ Created #{files.size} PAR2 file(s):"
91
+ files.each do |file|
92
+ size = File.size(file)
93
+ puts " - #{File.basename(file)} (#{format_size(size)})"
94
+ end
95
+ puts "\nRedundancy: #{@options[:redundancy]}%"
96
+ puts "Block size: #{format_size(@options[:block_size])}"
97
+ end
98
+
99
+ # Report error
100
+ #
101
+ # @param error [Exception] Error that occurred
102
+ def report_error(error)
103
+ puts "\n✗ Failed to create PAR2 files:"
104
+ puts " #{error.message}"
105
+ end
106
+
107
+ # Format byte size for display
108
+ #
109
+ # @param bytes [Integer] Size in bytes
110
+ # @return [String] Formatted size
111
+ def format_size(bytes)
112
+ if bytes < 1024
113
+ "#{bytes} B"
114
+ elsif bytes < 1024 * 1024
115
+ "#{(bytes / 1024.0).round(1)} KB"
116
+ else
117
+ "#{(bytes / (1024.0 * 1024)).round(1)} MB"
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../parity"
4
+
5
+ module Omnizip
6
+ module Commands
7
+ # Command to repair files using PAR2
8
+ class ParityRepairCommand
9
+ # @return [String] PAR2 file path
10
+ attr_reader :par2_file
11
+
12
+ # @return [Hash] Command options
13
+ attr_reader :options
14
+
15
+ # Initialize command
16
+ #
17
+ # @param par2_file [String] Path to .par2 index file
18
+ # @param options [Hash] Command options
19
+ def initialize(par2_file, options = {})
20
+ @par2_file = par2_file
21
+ @options = default_options.merge(options)
22
+ end
23
+
24
+ # Execute command
25
+ #
26
+ # @return [Integer] Exit code (0 for success)
27
+ def run
28
+ validate_inputs!
29
+
30
+ puts "Repairing files with PAR2: #{File.basename(@par2_file)}"
31
+ puts
32
+
33
+ progress = create_progress_callback if @options[:verbose]
34
+
35
+ result = Parity.repair(
36
+ @par2_file,
37
+ output_dir: @options[:output_dir],
38
+ progress: progress,
39
+ )
40
+
41
+ display_results(result)
42
+
43
+ result.success? ? 0 : 1
44
+ rescue StandardError => e
45
+ report_error(e)
46
+ 1
47
+ end
48
+
49
+ private
50
+
51
+ # Default command options
52
+ #
53
+ # @return [Hash] Default options
54
+ def default_options
55
+ {
56
+ output_dir: nil,
57
+ verbose: false,
58
+ }
59
+ end
60
+
61
+ # Validate command inputs
62
+ #
63
+ # @raise [ArgumentError] if inputs invalid
64
+ def validate_inputs!
65
+ unless File.exist?(@par2_file)
66
+ raise ArgumentError, "PAR2 file not found: #{@par2_file}"
67
+ end
68
+ end
69
+
70
+ # Create progress callback
71
+ #
72
+ # @return [Proc] Progress callback
73
+ def create_progress_callback
74
+ ->(percent, message) do
75
+ puts "[#{percent.to_s.rjust(3)}%] #{message}"
76
+ end
77
+ end
78
+
79
+ # Display repair results
80
+ #
81
+ # @param result [Omnizip::Parity::Par2Repairer::RepairResult]
82
+ def display_results(result)
83
+ if result.success?
84
+ puts "✓ Repair successful"
85
+ puts
86
+
87
+ if result.recovered_files.any?
88
+ puts "Recovered files (#{result.recovered_files.size}):"
89
+ result.recovered_files.each do |file|
90
+ puts " - #{file}"
91
+ end
92
+ else
93
+ puts "No repairs needed - all files were intact"
94
+ end
95
+
96
+ puts
97
+ puts "Recovered blocks: #{result.recovered_blocks}"
98
+ else
99
+ puts "✗ Repair failed"
100
+ puts
101
+ puts "Error: #{result.error_message}"
102
+ puts
103
+
104
+ if result.unrecoverable.any?
105
+ puts "Unrecoverable files (#{result.unrecoverable.size}):"
106
+ result.unrecoverable.each do |file|
107
+ puts " - #{file}"
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ # Report error
114
+ #
115
+ # @param error [Exception] Error that occurred
116
+ def report_error(error)
117
+ puts "\n✗ Repair failed:"
118
+ puts " #{error.message}"
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../parity"
4
+
5
+ module Omnizip
6
+ module Commands
7
+ # Command to verify files using PAR2
8
+ class ParityVerifyCommand
9
+ # @return [String] PAR2 file path
10
+ attr_reader :par2_file
11
+
12
+ # @return [Hash] Command options
13
+ attr_reader :options
14
+
15
+ # Initialize command
16
+ #
17
+ # @param par2_file [String] Path to .par2 index file
18
+ # @param options [Hash] Command options
19
+ def initialize(par2_file, options = {})
20
+ @par2_file = par2_file
21
+ @options = default_options.merge(options)
22
+ end
23
+
24
+ # Execute command
25
+ #
26
+ # @return [Integer] Exit code (0 if all OK, 1 if damage, 2 if error)
27
+ def run
28
+ validate_inputs!
29
+
30
+ puts "Verifying files with PAR2: #{File.basename(@par2_file)}"
31
+ puts
32
+
33
+ result = Parity.verify(@par2_file)
34
+
35
+ display_results(result)
36
+
37
+ # Exit code based on results
38
+ if result.all_ok?
39
+ 0
40
+ elsif result.repairable?
41
+ 1 # Damage but repairable
42
+ else
43
+ 2 # Damage not repairable
44
+ end
45
+ rescue StandardError => e
46
+ report_error(e)
47
+ 2
48
+ end
49
+
50
+ private
51
+
52
+ # Default command options
53
+ #
54
+ # @return [Hash] Default options
55
+ def default_options
56
+ {
57
+ verbose: false,
58
+ }
59
+ end
60
+
61
+ # Validate command inputs
62
+ #
63
+ # @raise [ArgumentError] if inputs invalid
64
+ def validate_inputs!
65
+ unless File.exist?(@par2_file)
66
+ raise ArgumentError, "PAR2 file not found: #{@par2_file}"
67
+ end
68
+ end
69
+
70
+ # Display verification results
71
+ #
72
+ # @param result [Omnizip::Parity::Par2Verifier::VerificationResult]
73
+ def display_results(result)
74
+ if result.all_ok?
75
+ puts "✓ All files verified successfully"
76
+ puts
77
+ puts "Total blocks: #{result.total_blocks}"
78
+ puts "Recovery blocks available: #{result.recovery_blocks}"
79
+ else
80
+ puts "✗ File corruption detected"
81
+ puts
82
+
83
+ if result.damaged_files.any?
84
+ puts "Damaged files (#{result.damaged_files.size}):"
85
+ result.damaged_files.each do |file|
86
+ puts " - #{file}"
87
+ end
88
+ puts
89
+ end
90
+
91
+ if result.missing_files.any?
92
+ puts "Missing files (#{result.missing_files.size}):"
93
+ result.missing_files.each do |file|
94
+ puts " - #{file}"
95
+ end
96
+ puts
97
+ end
98
+
99
+ puts "Damaged blocks: #{result.damaged_blocks.size}"
100
+ puts "Total blocks: #{result.total_blocks}"
101
+ puts "Recovery blocks available: #{result.recovery_blocks}"
102
+ puts
103
+
104
+ if result.repairable?
105
+ puts "✓ Damage is repairable"
106
+ puts " Run repair command to fix files:"
107
+ puts " omnizip parity repair #{@par2_file}"
108
+ else
109
+ puts "✗ Damage exceeds recovery capacity"
110
+ puts " Cannot repair: insufficient recovery blocks"
111
+ end
112
+ end
113
+ end
114
+
115
+ # Report error
116
+ #
117
+ # @param error [Exception] Error that occurred
118
+ def report_error(error)
119
+ puts "\n✗ Verification failed:"
120
+ puts " #{error.message}"
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../cli/output_formatter"
4
+
5
+ module Omnizip
6
+ module Commands
7
+ # Command to list available compression profiles
8
+ class ProfileListCommand
9
+ def initialize(options = {})
10
+ @options = options
11
+ end
12
+
13
+ def run
14
+ profiles = Omnizip::Profile.registry.all.sort_by(&:name)
15
+
16
+ if @options[:verbose]
17
+ list_detailed(profiles)
18
+ else
19
+ list_simple(profiles)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def list_simple(profiles)
26
+ puts "Available compression profiles:"
27
+ puts ""
28
+
29
+ profiles.each do |profile|
30
+ default_marker = profile.name == :balanced ? " [default]" : ""
31
+ puts format(
32
+ " %-12s - %s%s",
33
+ profile.name,
34
+ profile.description,
35
+ default_marker,
36
+ )
37
+ end
38
+ end
39
+
40
+ def list_detailed(profiles)
41
+ puts "Available compression profiles:"
42
+ puts ""
43
+
44
+ profiles.each do |profile|
45
+ puts "Profile: #{profile.name}"
46
+ puts " Algorithm: #{profile.algorithm}"
47
+ puts " Level: #{profile.level}"
48
+ puts " Filter: #{profile.filter || 'none'}"
49
+ puts " Solid: #{profile.solid}"
50
+ puts " Description: #{profile.description}"
51
+ puts ""
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../cli/output_formatter"
4
+
5
+ module Omnizip
6
+ module Commands
7
+ # Command to show details of a specific compression profile
8
+ class ProfileShowCommand
9
+ def initialize(options = {})
10
+ @options = options
11
+ end
12
+
13
+ def run(profile_name)
14
+ profile_sym = profile_name.to_sym
15
+ profile = Omnizip::Profile.get(profile_sym)
16
+
17
+ unless profile
18
+ warn "Profile '#{profile_name}' not found"
19
+ warn ""
20
+ warn "Available profiles:"
21
+ Omnizip::Profile.list.each { |name| warn " - #{name}" }
22
+ exit 1
23
+ end
24
+
25
+ display_profile(profile)
26
+ end
27
+
28
+ private
29
+
30
+ def display_profile(profile)
31
+ puts "Profile: #{profile.name}"
32
+ puts "Algorithm: #{profile.algorithm}"
33
+ puts "Level: #{profile.level}"
34
+ puts "Filter: #{profile.filter || 'none'}"
35
+ puts "Solid: #{profile.solid}"
36
+ puts "Description: #{profile.description}"
37
+
38
+ return unless profile.respond_to?(:base_profile) && profile.base_profile
39
+
40
+ puts "Based on: #{profile.base_profile.name}"
41
+ end
42
+ end
43
+ end
44
+ end