omnizip 0.3.32 → 0.3.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a20cd2785f3068dabfe29b7cb3e9b88503b151839ea076fd4d4c727708e5a440
4
- data.tar.gz: 7db78180133b7b7d3e62dff82588036c73dabc80c1957d892ffbff96fd83e657
3
+ metadata.gz: 0f3064a982a38257ff4ef606d6de52925a377e2138a3bacc7cb60033a6ff1ac1
4
+ data.tar.gz: f24f28f6daac8df45542854f099c071d5b17f52deff99ae7f3bd5d009d6d7c0d
5
5
  SHA512:
6
- metadata.gz: 601948e2be2303a5c82573728118fe4fdb6bd123ce983f6f92776373e3215e96c1b29ab02217356353a8978335af54233093ede1aeb9aa8665a57f1f189a9525
7
- data.tar.gz: ac68a261028b8a92a948bb0f93caed9997e5e3d13c885962d1857104c65f16d2da2eba38996aac90fb0a17da57d9fa8b7e1c806956e22d65d36765ebcf9f84c7
6
+ metadata.gz: 7e08082742ca10c5156773d5d279c1e5c7fe6d035cbe06678e2c68509862d89880c1a7f3e40d4e7a69b433e2407546d3735846a7d53a3c139819fa271001b852
7
+ data.tar.gz: 8d8551cf4cd26ae177b36e5aa67f217323853535ffaed26e4825f537e4384e998629b6084240a2dd82eaad276396dd51b22ab84a4d65f6f9f98475965ca6096e
data/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Fixed
11
+ - The convenience API (`compress_file`, `compress_directory`,
12
+ `extract_archive`, `list_archive`, `read_from_archive`,
13
+ `add_to_archive`, `remove_from_archive`) now routes archive
14
+ formats by extension: `.tar` writes/reads real TAR (previously a
15
+ mislabeled ZIP), `.7z` writes/reads real 7z via a new
16
+ `ArchiveHandlers::SevenZipHandler` (previously a mislabeled ZIP;
17
+ archives verify with `7zz`), and read-only formats (`.rar`,
18
+ `.iso`, `.cpio`) raise `UnsupportedFormatError` instead of
19
+ silently writing a ZIP under a foreign name. Extensionless
20
+ outputs keep the ZIP default; an explicit `format:` still wins.
21
+
22
+ ## [0.3.32] - 2026-08-27
23
+
10
24
  ### Fixed
11
25
  - The `omnizip` executable crashed on every invocation
12
26
  (`uninitialized constant Omnizip::Cli`): the `Cli` autoload was
@@ -69,6 +69,7 @@ module Omnizip
69
69
  LAZY_LOAD_TRIGGERS = {
70
70
  zip: -> { Omnizip::ArchiveHandlers::ZipHandler },
71
71
  tar: -> { Omnizip::ArchiveHandlers::TarHandler },
72
+ seven_zip: -> { Omnizip::ArchiveHandlers::SevenZipHandler },
72
73
  }.freeze
73
74
  private_constant :LAZY_LOAD_TRIGGERS
74
75
  end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module ArchiveHandlers
5
+ # Adapter that exposes the canonical +create+/+extract_to+/+list+
6
+ # interface for the 7z format. Wraps +Omnizip::Formats::SevenZip+.
7
+ class SevenZipHandler
8
+ # Creates a .7z archive. The yielded proxy only supports
9
+ # +add(name, source_path)+ for files — directory entries are not
10
+ # part of the single-file convenience flow.
11
+ def create(path, &block)
12
+ Omnizip::Formats::SevenZip.create(path) do |writer|
13
+ block&.call(FileProxy.new(writer))
14
+ end
15
+ end
16
+
17
+ def extract_to(path, output_dir, **options)
18
+ Omnizip::Formats::SevenZip.open(path, options) do |reader|
19
+ reader.extract_all(output_dir)
20
+ end
21
+ end
22
+
23
+ def list(path, details: false, **options)
24
+ Omnizip::Formats::SevenZip.open(path, options) do |reader|
25
+ files = reader.list_files
26
+ return details ? files.map { |f| { name: f } } : files
27
+ end
28
+ end
29
+
30
+ def read_entry(_path, _entry_name)
31
+ raise NotImplementedError,
32
+ "read_from_archive for .7z is not wired; use " \
33
+ "Formats::SevenZip.open"
34
+ end
35
+
36
+ # Translates the generic +add(name, source_path)+ interface to
37
+ # the 7z writer's +add_file(file_path, archive_path)+.
38
+ class FileProxy
39
+ def initialize(writer)
40
+ @writer = writer
41
+ end
42
+
43
+ def add(name, source_path = nil)
44
+ if source_path.nil?
45
+ raise ArgumentError,
46
+ "directory entries are not supported in .7z " \
47
+ "convenience compression"
48
+ end
49
+
50
+ @writer.add_file(source_path, name)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ Omnizip::ArchiveHandler.register(:seven_zip,
58
+ Omnizip::ArchiveHandlers::SevenZipHandler.new)
@@ -7,5 +7,6 @@ module Omnizip
7
7
  module ArchiveHandlers
8
8
  autoload :ZipHandler, "omnizip/archive_handlers/zip_handler"
9
9
  autoload :TarHandler, "omnizip/archive_handlers/tar_handler"
10
+ autoload :SevenZipHandler, "omnizip/archive_handlers/seven_zip_handler"
10
11
  end
11
12
  end
@@ -40,7 +40,7 @@ module Omnizip
40
40
  return output_path
41
41
  end
42
42
 
43
- Omnizip::ArchiveHandler.for(format).create(output_path) do |archive|
43
+ Omnizip::ArchiveHandler.for(resolve_archive_format(output_path, format)).create(output_path) do |archive|
44
44
  archive.add(::File.basename(input_path), input_path)
45
45
  end
46
46
 
@@ -69,7 +69,7 @@ module Omnizip
69
69
  apply_profile(first_file, options)
70
70
  end
71
71
 
72
- Omnizip::ArchiveHandler.for(format).create(output_path) do |archive|
72
+ Omnizip::ArchiveHandler.for(resolve_archive_format(output_path, format)).create(output_path) do |archive|
73
73
  add_directory_contents(archive, input_dir, "", recursive: recursive)
74
74
  end
75
75
 
@@ -87,7 +87,7 @@ module Omnizip
87
87
  def extract_archive(archive_path, output_dir, format: DEFAULT_FORMAT,
88
88
  overwrite: false, **options)
89
89
  require_archive!(archive_path)
90
- Omnizip::ArchiveHandler.for(format)
90
+ Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format))
91
91
  .extract_to(archive_path, output_dir,
92
92
  overwrite: overwrite, **options)
93
93
  end
@@ -102,7 +102,7 @@ module Omnizip
102
102
  def list_archive(archive_path, format: DEFAULT_FORMAT, details: false,
103
103
  **options)
104
104
  require_archive!(archive_path)
105
- Omnizip::ArchiveHandler.for(format)
105
+ Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format))
106
106
  .list(archive_path, details: details, **options)
107
107
  end
108
108
 
@@ -114,7 +114,7 @@ module Omnizip
114
114
  # @return [String] Entry contents
115
115
  def read_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT)
116
116
  require_archive!(archive_path)
117
- Omnizip::ArchiveHandler.for(format).read_entry(archive_path, entry_name)
117
+ Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format)).read_entry(archive_path, entry_name)
118
118
  end
119
119
 
120
120
  # Add a file to an existing archive.
@@ -131,7 +131,7 @@ module Omnizip
131
131
  raise Errno::ENOENT, "Source file not found: #{source_path}"
132
132
  end
133
133
 
134
- handler = Omnizip::ArchiveHandler.for(format)
134
+ handler = Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format))
135
135
  # allowed: handler is a registered duck; missing add_entry raises below
136
136
  if handler.respond_to?(:add_entry)
137
137
  handler.add_entry(archive_path, entry_name, source_path)
@@ -151,7 +151,7 @@ module Omnizip
151
151
  # @return [String] +archive_path+
152
152
  def remove_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT)
153
153
  require_archive!(archive_path)
154
- handler = Omnizip::ArchiveHandler.for(format)
154
+ handler = Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format))
155
155
  # allowed: handler is a registered duck; missing remove_entry raises below
156
156
  unless handler.respond_to?(:remove_entry)
157
157
  raise Omnizip::UnsupportedFormatError,
@@ -172,6 +172,20 @@ module Omnizip
172
172
  # Extension -> single-file compressor map. Each lambda takes
173
173
  # (input_path, output_path, options). These formats are streams,
174
174
  # not archives, so they bypass ArchiveHandler.
175
+ # Extensions naming archive formats with a registered handler;
176
+ # routed when the caller did not pass an explicit +format:+.
177
+ ARCHIVE_FORMAT_EXTENSIONS = {
178
+ ".zip" => :zip,
179
+ ".tar" => :tar,
180
+ ".7z" => :seven_zip,
181
+ }.freeze
182
+
183
+ # Extensions naming real formats this gem can READ but not write
184
+ # through the convenience API. Writing them a ZIP under a foreign
185
+ # name was silent corruption; failing truthfully is the only
186
+ # honest behavior.
187
+ READ_ONLY_FORMAT_EXTENSIONS = [".rar", ".iso", ".cpio"].freeze
188
+
175
189
  SINGLE_FILE_COMPRESSORS = {
176
190
  ".gz" => lambda do |input, output, options|
177
191
  Omnizip::Formats::Gzip.compress(input, output, options)
@@ -206,6 +220,26 @@ module Omnizip
206
220
  SINGLE_FILE_COMPRESSORS[ext]
207
221
  end
208
222
 
223
+ # Archive format for a path: an explicit +format+ wins unless it
224
+ # is the default; otherwise the extension routes. Known-but-
225
+ # unwritable extensions raise instead of receiving a mislabeled
226
+ # ZIP.
227
+ def resolve_archive_format(path, format)
228
+ return format unless format == DEFAULT_FORMAT
229
+
230
+ ext = ::File.extname(path).downcase
231
+ routed = ARCHIVE_FORMAT_EXTENSIONS[ext]
232
+ return routed if routed
233
+
234
+ if READ_ONLY_FORMAT_EXTENSIONS.include?(ext)
235
+ raise Omnizip::UnsupportedFormatError,
236
+ "#{ext} archives cannot be written by the convenience " \
237
+ "API (read-only support); use the format-specific reader"
238
+ end
239
+
240
+ DEFAULT_FORMAT
241
+ end
242
+
209
243
  private
210
244
 
211
245
  def require_archive!(archive_path)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Omnizip
4
- VERSION = "0.3.32"
4
+ VERSION = "0.3.33"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omnizip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.32
4
+ version: 0.3.33
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -321,6 +321,7 @@ files:
321
321
  - lib/omnizip/algorithms/zstandard/xxhash.rb
322
322
  - lib/omnizip/archive_handler.rb
323
323
  - lib/omnizip/archive_handlers.rb
324
+ - lib/omnizip/archive_handlers/seven_zip_handler.rb
324
325
  - lib/omnizip/archive_handlers/tar_handler.rb
325
326
  - lib/omnizip/archive_handlers/zip_handler.rb
326
327
  - lib/omnizip/buffer.rb