omnizip 0.3.32 → 0.3.34
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 +4 -4
- data/CHANGELOG.md +25 -0
- data/lib/omnizip/archive_handler.rb +1 -0
- data/lib/omnizip/archive_handlers/seven_zip_handler.rb +58 -0
- data/lib/omnizip/archive_handlers/tar_handler.rb +19 -1
- data/lib/omnizip/archive_handlers.rb +1 -0
- data/lib/omnizip/convenience.rb +41 -7
- data/lib/omnizip/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ad5f2e41132ed61e2e80173f7550d75f3f0c8711d264e36a605fbee28e4a322e
|
|
4
|
+
data.tar.gz: 6d2b1989b06bb359cf48f2a5d24e8eea4b697cde22404c144cfef72357fdfb2d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 38afce515d452d0dd4b1ace8b32608b59ff72e86d76d7d0ccfe3985f2d8cae6c24f4e657dc2e48d92b1b9194de2bca7e6d38eedb499255f1b8dcc3da5e2660db
|
|
7
|
+
data.tar.gz: dab546e8c4db730e7d257d29c89e903768e2112e858a87ef55daf3ac64305e584c715b3042a60e5caef7428357a8b12d4c2609e8ed2baa15612a5ada53ed3337
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Fixed
|
|
11
|
+
- `Omnizip.compress_directory` to `.7z` and `.tar` (both documented)
|
|
12
|
+
works now: the 7z handler treats directory entries as the no-op
|
|
13
|
+
they are in the format (7z derives the tree from file paths;
|
|
14
|
+
nested paths verified against `7zz`), and the Tar handler routes
|
|
15
|
+
bare directory entries to the writer's `add_directory` instead of
|
|
16
|
+
misreading them as CWD-relative paths. Both round-trip nested
|
|
17
|
+
subdirectories through `extract_archive`.
|
|
18
|
+
|
|
19
|
+
## [0.3.33] - 2026-08-27
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- The convenience API (`compress_file`, `compress_directory`,
|
|
23
|
+
`extract_archive`, `list_archive`, `read_from_archive`,
|
|
24
|
+
`add_to_archive`, `remove_from_archive`) now routes archive
|
|
25
|
+
formats by extension: `.tar` writes/reads real TAR (previously a
|
|
26
|
+
mislabeled ZIP), `.7z` writes/reads real 7z via a new
|
|
27
|
+
`ArchiveHandlers::SevenZipHandler` (previously a mislabeled ZIP;
|
|
28
|
+
archives verify with `7zz`), and read-only formats (`.rar`,
|
|
29
|
+
`.iso`, `.cpio`) raise `UnsupportedFormatError` instead of
|
|
30
|
+
silently writing a ZIP under a foreign name. Extensionless
|
|
31
|
+
outputs keep the ZIP default; an explicit `format:` still wins.
|
|
32
|
+
|
|
33
|
+
## [0.3.32] - 2026-08-27
|
|
34
|
+
|
|
10
35
|
### Fixed
|
|
11
36
|
- The `omnizip` executable crashed on every invocation
|
|
12
37
|
(`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
|
+
# Directory entries are a no-op: 7z archives derive the
|
|
44
|
+
# directory tree from the files' archive paths ("sub/f.txt"
|
|
45
|
+
# implies "sub/"), and the writer/reader handle slashed
|
|
46
|
+
# paths (verified against 7zz).
|
|
47
|
+
def add(name, source_path = nil)
|
|
48
|
+
return if source_path.nil?
|
|
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)
|
|
@@ -6,7 +6,9 @@ module Omnizip
|
|
|
6
6
|
# /+list+ interface for the TAR format. Wraps +Omnizip::Formats::Tar+.
|
|
7
7
|
class TarHandler
|
|
8
8
|
def create(path, &block)
|
|
9
|
-
Omnizip::Formats::Tar.create(path
|
|
9
|
+
Omnizip::Formats::Tar.create(path) do |writer|
|
|
10
|
+
block&.call(EntryProxy.new(writer))
|
|
11
|
+
end
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def open(path, &block)
|
|
@@ -34,6 +36,22 @@ module Omnizip
|
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
|
|
39
|
+
# Translates the generic +add(name, source_path)+ interface:
|
|
40
|
+
# a bare +add(name)+ is a directory ENTRY (no source on disk
|
|
41
|
+
# relative to the caller), which the Tar writer's own +add+
|
|
42
|
+
# would misread as a CWD-relative path.
|
|
43
|
+
class EntryProxy
|
|
44
|
+
def initialize(writer)
|
|
45
|
+
@writer = writer
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def add(name, source_path = nil)
|
|
49
|
+
return @writer.add_directory(name) if source_path.nil?
|
|
50
|
+
|
|
51
|
+
@writer.add(name, source_path)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
37
55
|
def read_entry(path, entry_name)
|
|
38
56
|
data = nil
|
|
39
57
|
Omnizip::Formats::Tar.open(path) do |reader|
|
data/lib/omnizip/convenience.rb
CHANGED
|
@@ -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)
|
data/lib/omnizip/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.3.34
|
|
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
|