omnizip 0.3.30 → 0.3.31

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: 20b634d20f6abd7d5c44314d94b89e5008b1ad34e4c0efa14a01ef72a71c0723
4
- data.tar.gz: 58d5380b5f2a98f92361395a55738047313f66c90bb9e662a56a47ee20333f11
3
+ metadata.gz: eb1ed1142019a375dd71be87daa4c59bdd509640530a183e34b5db31841d9d1b
4
+ data.tar.gz: a203011eea4196ef77193b642794c1a1eb5b870be4d1e9f66a1a233895d7c4b1
5
5
  SHA512:
6
- metadata.gz: efcdcc1f1f3cf2774a6c955531f5a6747f4bad4464e0521f27e89d6b5c97b31bedcd1e3e2315f421bb7bea29a4aa73ca4f75dcee8eec702516e8c2b5349fb115
7
- data.tar.gz: 96d041e3847fa402dbf86cfa3f86b7ba7b9b12f754471e10a8c60de8e966decbb0cfeb3711f71cfb905bf7acfea62a30128a1fb573f4f52e8e8e29b37fecc00b
6
+ metadata.gz: 17955bf45c57c5a2a6d4117b66617590f9ae5c0527c3f268b79b9be8f353f10b38a51829b60b9bb77cfd374840f694b55b1f56e3777cb8bb629e04e4b3044e17
7
+ data.tar.gz: 6396d10e54bfd95dcddff3e3475884f8240a3da8c83850156396c2e515b8ad19059094241260adac8684c202e64b5bf41dcf2507a1deda87dc44009661ea3e9d
data/CHANGELOG.md CHANGED
@@ -7,7 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ## [0.3.31] - 2026-08-27
10
+ ### Fixed
11
+ - `Omnizip.compress_file` now routes single-file compression by
12
+ output extension: `.gz`, `.bz2`, `.xz`, `.lzma` and `.lz` produce
13
+ the matching format instead of silently writing a ZIP under a
14
+ foreign extension (the documented
15
+ `compress_file('input.txt', 'output.lzma', algorithm: :lzma)`
16
+ example previously emitted `PK`-magic data). Unknown extensions
17
+ and explicit archive formats keep the previous behavior.
18
+
19
+ ## [0.3.30] - 2026-08-27
11
20
 
12
21
  ### Changed
13
22
  - Re-enabled LZMA2 in the 7-Zip header-encryption and split-archive
@@ -32,7 +32,7 @@ as absolute rules:
32
32
  | 10 | `10-format-detector-ocp.md` | medium | **DONE** |
33
33
  | 11 | `11-convenience-decoupling.md` | medium | **DONE** (ArchiveHandler dispatcher + ZipHandler + TarHandler) |
34
34
  | 12 | `12-thread-safety.md` | covered by 01 | n/a |
35
- | 13 | `13-lutaml-model-migration.md` | medium | **PARTIAL** — CompressionOptions and AlgorithmMetadata migrated; ConversionOptions pending lutaml symbol-type support |
35
+ | 13 | `13-lutaml-model-migration.md` | medium | **DONE** — six models migrated; follow-ups 2+3 landed in 0.3.28; 1 and 4 decided (deferred rename / migration declined with reasons) |
36
36
  | 14 | `14-add-missing-specs.md` | high | **DONE** |
37
37
 
38
38
  ## Anti-pattern counts (lib/)
@@ -129,18 +129,30 @@ is the intended end state, not unfinished work.
129
129
 
130
130
  ## Follow-up work
131
131
 
132
- 1. **Rename the 17.** If they are reports and projections, `to_h` is
133
- the wrong name that is the real defect. Suggested groupings:
134
- `to_report` for the computed ones, `to_tag_map` / `to_attributes`
135
- for projections, `to_xml_attributes` / `to_fields` for wire-format
136
- builders. Each rename is itself a public-API break.
137
- 2. **Fix `apply` in `CompressionOptions` and `AlgorithmMetadata`.**
138
- Both iterate `self.class.attributes.each do |attr| ... attr.name`,
139
- but `attributes` is a Hash, so the block gets a two-element Array
140
- and `attr.name` raises `NoMethodError`. Neither has a caller or a
141
- spec today, which is why it went unnoticed. Fix is `each_key`, plus
142
- a spec per class.
143
- 3. **Extract the shared `apply` loop** once (2) has landed — three
144
- classes now carry a similar body.
145
- 4. **Consider `FilterConfig` and the profile classes** for a proper
146
- migration; both were judged too high-blast-radius to bundle here.
132
+ 1. **Rename the 17 DECIDED: deferred to a deliberate major/minor
133
+ release.** The names below remain the plan if that release
134
+ happens: `to_report` for the computed ones, `to_tag_map` /
135
+ `to_attributes` for projections, `to_xml_attributes` / `to_fields`
136
+ for wire-format builders. Each rename is a public-API break
137
+ (every one of the 17 is a public class method), so it cannot ship
138
+ silently in a patch; the 17 staying is the intended end state for
139
+ now, per "Why 17 stay" above.
140
+ 2. **DONE (0.3.28, PR #42).** `apply` fixed in both classes all
141
+ three options models now share the tested
142
+ `Models::AttributeApply` concern, which also delivers (3).
143
+ 3. **DONE (0.3.28, PR #42)** see (2).
144
+ 4. **Considered decided against, with reasons.**
145
+ - `FilterConfig` is a behavior-heavy domain object, not a
146
+ serialization model: `filter_instance` reaches into
147
+ `FilterRegistry`, `id_for_format`/`bcj?`/`delta?` are domain
148
+ queries, `properties` defaults to a binary String (lutaml's
149
+ `:string` is UTF-8-oriented, so the attribute would need a
150
+ custom type), and initialization accepts two alias keys
151
+ (`:name`/`:name_sym`). Its `to_h` is a projection with no
152
+ round-trip consumer. Migration would fight the framework to
153
+ achieve nothing the class needs.
154
+ - The profile classes are abstract domain objects: subclasses
155
+ override `suitable_for?`, `apply_to` mutates an options object,
156
+ five validators run at construction, and `to_h` coexists with
157
+ `to_s`/`inspect` as display projections. No wire format round
158
+ trips them. Same verdict.
@@ -31,6 +31,15 @@ module Omnizip
31
31
  return Omnizip::Chunked.compress_file(input_path, output_path, **options)
32
32
  end
33
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
+
34
43
  Omnizip::ArchiveHandler.for(format).create(output_path) do |archive|
35
44
  archive.add(::File.basename(input_path), input_path)
36
45
  end
@@ -160,6 +169,43 @@ module Omnizip
160
169
  Omnizip::Formats::Rar.create(archive_path, options, &block)
161
170
  end
162
171
 
172
+ # Extension -> single-file compressor map. Each lambda takes
173
+ # (input_path, output_path, options). These formats are streams,
174
+ # not archives, so they bypass ArchiveHandler.
175
+ SINGLE_FILE_COMPRESSORS = {
176
+ ".gz" => lambda do |input, output, options|
177
+ Omnizip::Formats::Gzip.compress(input, output, options)
178
+ end,
179
+ ".bz2" => lambda do |input, output, options|
180
+ Omnizip::Formats::Bzip2File.compress(input, output, options)
181
+ end,
182
+ ".xz" => lambda do |input, output, options|
183
+ Omnizip::Formats::Xz.create(::File.binread(input), output, options)
184
+ end,
185
+ ".lzma" => lambda do |input, output, options|
186
+ ::File.open(input, "rb") do |input_io|
187
+ ::File.open(output, "wb") do |output_io|
188
+ Omnizip::Formats::LzmaAlone.compress_stream(input_io, output_io,
189
+ options)
190
+ end
191
+ end
192
+ end,
193
+ ".lz" => lambda do |input, output, options|
194
+ ::File.open(input, "rb") do |input_io|
195
+ ::File.open(output, "wb") do |output_io|
196
+ Omnizip::Formats::Lzip.compress_stream(input_io, output_io,
197
+ options)
198
+ end
199
+ end
200
+ end,
201
+ }.freeze
202
+
203
+ # The single-file compressor matching the output extension, or nil.
204
+ def single_file_handler(output_path)
205
+ ext = ::File.extname(output_path).downcase
206
+ SINGLE_FILE_COMPRESSORS[ext]
207
+ end
208
+
163
209
  private
164
210
 
165
211
  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.30"
4
+ VERSION = "0.3.31"
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.30
4
+ version: 0.3.31
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.