zip-merge 7.0.0 → 7.1.3

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: a859c92350627feaf0b728b47e735675f19c339d50c6bf709a5c516e6fd252ec
4
- data.tar.gz: 54d03cd74d3ec83b9050bdcad173320f5a9c00dd49a657a04f736f92c3ce53bc
3
+ metadata.gz: ab8707f72ab19bcb5d7fa6ac1dff9e120b6359913377a27a0068fa25c7811550
4
+ data.tar.gz: ec42f4edba8322a35f933367b172b414a18aaa32af0af976b962214122c6dfb4
5
5
  SHA512:
6
- metadata.gz: 96e218946eb50b84c11e3d1fff6354626fd44f50d1672e32275aa3eb18e960821566845a0a4fd6adcd1a68a7c2be9d2de6255c2933da91b266105309e3369b20
7
- data.tar.gz: 882dadf7d82282213faf7d43691eee6f4382a14eb261c5b4aeb7659db609c9532b1c86a688a5bdd2f0c034a1c1eaf37c8db98f31536f726c65f490488763e4d5
6
+ metadata.gz: eb36f6b3bfd9e0a1c338c33a9772a57f8bd16f7e90eca6b27c1c339c6a88ece6508f6528af4e5a74d801e21bb9c0b2f85275e4bf03665ec495109984798be7c6
7
+ data.tar.gz: 275ba874d435f03ab9619940f2d8add76aac49c1ae9cb29278955b00c11c19b40d78c12353ec3e3f1aa57acc71d22332693899abe524adbf0d6d67726315df08
checksums.yaml.gz.sig CHANGED
Binary file
data/LICENSE.md ADDED
@@ -0,0 +1,13 @@
1
+ # License
2
+
3
+ This project is made available under the following licenses.
4
+ Choose the option that best fits your use case:
5
+
6
+ - [AGPL-3.0-only](https://github.com/structuredmerge/structuredmerge-ruby/blob/main/AGPL-3.0-only.md)
7
+ - [PolyForm-Small-Business-1.0.0](https://github.com/structuredmerge/structuredmerge-ruby/blob/main/PolyForm-Small-Business-1.0.0.md)
8
+
9
+ If none of the above licenses fit your use case, please [contact us](mailto:floss@galtzo.com) to discuss a custom commercial license.
10
+
11
+ ## Copyright Notice
12
+
13
+ - Required Notice: Copyright (c) 2026 Peter H. Boling
data/README.md ADDED
@@ -0,0 +1,299 @@
1
+ <a href="https://github.com/structuredmerge"><img alt="structuredmerge Logo by GitHub" src="https://github.com/structuredmerge.png?size=192" width="14%" align="right"/></a>
2
+
3
+ # ☯️ Zip::Merge
4
+
5
+ [![Version][👽versioni]][👽version] [![Ruby Users Forum][✉️ruby-forum-top-img]][✉️ruby-forum] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: AGPL-3.0-only OR PolyForm-Small-Business-1.0.0][📄license-img]][📄license] [![Total downloads][👽dl-ranki]][👽dl-rank] [![CI Current][🚎11-c-wfi]][🚎11-c-wf]
6
+
7
+ `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know on Discord][✉️discord-invite] or [RubyForum][✉️ruby-forum], as I may have missed the notification.
8
+
9
+ ---
10
+
11
+ `if ci_badges.map(&:color).all? { it == "green"}` 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job.
12
+
13
+ [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate at ko-fi.com][🖇kofi-img]][🖇kofi]
14
+
15
+ <details markdown="1">
16
+ <summary>👣 How will this project approach the September 2025 hostile takeover of RubyGems? 🚑️</summary>
17
+
18
+ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo).
19
+
20
+ </details>
21
+
22
+ ## 🌻 Synopsis <a href="https://discord.gg/3qme4XHNKN"><img alt="Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/galtzo-floss/avatar-128px.svg" width="8%" align="right"/></a> <a href="https://ruby-toolbox.com"><img alt="ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5" src="https://logos.galtzo.com/assets/images/ruby-lang/avatar-128px.svg" width="8%" align="right"/></a>
23
+
24
+ `Zip::Merge` plans ZIP archive merges by member path and raw byte ranges. It is
25
+ a Kaitai-family binary AST integration in the StructuredMerge stack: ZIP
26
+ inventories are represented with TreeHaver ZIP report nodes, and analysis enters
27
+ through a `parser_for(:zip)` Kaitai path. It depends on `binary-merge` for the
28
+ shared binary-family substrate: preservation reports, unsafe diagnostics,
29
+ byte-range ownership, and renderer planning vocabulary.
30
+ It identifies safe preservation cases, unsafe entries, members that need
31
+ structured nested merges, and archive metadata that must be rewritten by a
32
+ renderer.
33
+
34
+ ### Key Features
35
+
36
+ - Central directory and local header inventory parsing.
37
+ - Kaitai-family binary AST reporting through TreeHaver ZIP structures.
38
+ - Shared binary-family report and diagnostic helpers from `binary-merge`.
39
+ - Member decisions for preserve, add, delete, rewrite, delegate, and reject operations.
40
+ - Nested family dispatch for structured archive members.
41
+ - Raw-preserving renderer for safe unchanged members.
42
+ - Checksum and central-directory update reporting.
43
+
44
+ ## 💡 Info you can shake a stick at
45
+
46
+ | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
47
+ |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
48
+ | Works with MRI Ruby 4 | [![Ruby current Compat][💎ruby-c-i]][🚎11-c-wf]|
49
+ | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Get help from RubyForum][✉️ruby-forum-img]][✉️ruby-forum] [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
50
+ | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on GitHub.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] |
51
+ | Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![GitLab Wiki][📜gl-wiki-img]][📜gl-wiki] [![GitHub Wiki][📜gh-wiki-img]][📜gh-wiki] |
52
+ | Compliance | [![License: AGPL-3.0-only OR PolyForm-Small-Business-1.0.0][📄license-img]][📄license] [![Apache license compatibility: Category X][📄license-compat-img]][📄license-compat] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] |
53
+ | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] |
54
+ | Maintainer 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
55
+ | `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] |
56
+
57
+ ### Compatibility
58
+
59
+ Compatible with MRI Ruby 4.0.0+, JRuby, and TruffleRuby.
60
+ CI workflows and Appraisals are generated for MRI Ruby 4.0.0+.
61
+ This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
62
+ may be higher than the gem's runtime compatibility floor when legacy Rubies are
63
+ not practical for the current toolchain.
64
+
65
+ <a href="https://github.com/kettle-dev"><img alt="kettle-dev Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/kettle-dev/avatar-128px.svg" width="14%" align="right"/></a>
66
+
67
+ The _amazing_ test matrix is powered by the kettle-dev stack.
68
+
69
+ <details markdown="1">
70
+ <summary>How kettle-dev manages complexity in tests</summary>
71
+
72
+ | Gem | Source | Role | Total downloads |
73
+ |-----|--------|------|---------------------|
74
+ | [appraisal2](https://clickgems.clickhouse.com/dashboard/appraisal2) | [GitHub](https://github.com/appraisal-rb/appraisal2) | multi-dependency Appraisal matrix generation | [![Total downloads for appraisal2](https://img.shields.io/gem/dt/appraisal2.svg?style=flat-square)](https://clickgems.clickhouse.com/dashboard/appraisal2) |
75
+ | [appraisal2-rubocop](https://clickgems.clickhouse.com/dashboard/appraisal2-rubocop) | [GitHub](https://github.com/appraisal-rb/appraisal2-rubocop) | RuboCop Appraisal generator integration | [![Total downloads for appraisal2-rubocop](https://img.shields.io/gem/dt/appraisal2-rubocop.svg?style=flat-square)](https://clickgems.clickhouse.com/dashboard/appraisal2-rubocop) |
76
+ | [kettle-dev](https://clickgems.clickhouse.com/dashboard/kettle-dev) | [GitHub](https://github.com/kettle-dev/kettle-dev) | development, release, and CI workflow tooling | [![Total downloads for kettle-dev](https://img.shields.io/gem/dt/kettle-dev.svg?style=flat-square)](https://clickgems.clickhouse.com/dashboard/kettle-dev) |
77
+ | [kettle-jem](https://clickgems.clickhouse.com/dashboard/kettle-jem) | [GitHub](https://github.com/kettle-dev/kettle-jem) | Appraisals & CI workflow templates | [![Total downloads for kettle-jem](https://img.shields.io/gem/dt/kettle-jem.svg?style=flat-square)](https://clickgems.clickhouse.com/dashboard/kettle-jem) |
78
+ | [kettle-soup-cover](https://clickgems.clickhouse.com/dashboard/kettle-soup-cover) | [GitHub](https://github.com/kettle-dev/kettle-soup-cover) | SimpleCov coverage policy and reporting | [![Total downloads for kettle-soup-cover](https://img.shields.io/gem/dt/kettle-soup-cover.svg?style=flat-square)](https://clickgems.clickhouse.com/dashboard/kettle-soup-cover) |
79
+ | [kettle-test](https://clickgems.clickhouse.com/dashboard/kettle-test) | [GitHub](https://github.com/kettle-dev/kettle-test) | standard test runner and coverage harness | [![Total downloads for kettle-test](https://img.shields.io/gem/dt/kettle-test.svg?style=flat-square)](https://clickgems.clickhouse.com/dashboard/kettle-test) |
80
+ | [rubocop-lts](https://clickgems.clickhouse.com/dashboard/rubocop-lts) | [GitHub](https://github.com/rubocop-lts/rubocop-lts) | Ruby-version-aware linting | [![Total downloads for rubocop-lts](https://img.shields.io/gem/dt/rubocop-lts.svg?style=flat-square)](https://clickgems.clickhouse.com/dashboard/rubocop-lts) |
81
+ | [turbo_tests2](https://clickgems.clickhouse.com/dashboard/turbo_tests2) | [GitHub](https://github.com/galtzo-floss/turbo_tests2) | parallel test execution | [![Total downloads for turbo_tests2](https://img.shields.io/gem/dt/turbo_tests2.svg?style=flat-square)](https://clickgems.clickhouse.com/dashboard/turbo_tests2) |
82
+
83
+ </details>
84
+
85
+ ## ✨ Installation
86
+
87
+ Install the gem and add to the application's Gemfile by executing:
88
+
89
+ ```console
90
+ bundle add zip-merge
91
+ ```
92
+
93
+ If bundler is not being used to manage dependencies, install the gem by executing:
94
+
95
+ ```console
96
+ gem install zip-merge
97
+ ```
98
+
99
+ ## ⚙️ Configuration
100
+
101
+ `Zip::Merge` works from parsed inventories rather than global settings.
102
+
103
+ ```ruby
104
+ ancestor = Zip::Merge.parse_zip_inventory(ancestor_bytes)
105
+ current = Zip::Merge.parse_zip_inventory(current_bytes)
106
+ incoming = Zip::Merge.parse_zip_inventory(incoming_bytes)
107
+ plan = Zip::Merge.plan_zip_merge(ancestor, current, incoming)
108
+ ```
109
+
110
+ Rendering requires caller-supplied member bytes for added, rewritten, or delegated members.
111
+
112
+ ## 🔧 Basic Usage
113
+
114
+ ```ruby
115
+ require "zip/merge"
116
+
117
+ zip_parser = TreeHaver.parser_for(:zip, backend_type: :kaitai)
118
+ ancestor = zip_parser.parse(File.binread("base.zip"))
119
+ current = zip_parser.parse(File.binread("ours.zip"))
120
+ incoming = zip_parser.parse(File.binread("theirs.zip"))
121
+
122
+ plan = Zip::Merge.plan_zip_merge(ancestor, current, incoming)
123
+ plan.member_decisions.each do |decision|
124
+ puts "#{decision.operation}: #{decision.normalized_path}"
125
+ end
126
+ ```
127
+
128
+ ## 🔐 Security
129
+
130
+ See [SECURITY.md][🔐security].
131
+
132
+ ## 🤝 Contributing
133
+
134
+ If you need some ideas of where to help, you could work on adding more code coverage,
135
+ check [issues][🤝gh-issues] or [PRs][🤝gh-pulls], or use the gem and think about how it could be better.
136
+
137
+ We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
138
+
139
+ See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
140
+
141
+ ## 📌 Versioning
142
+
143
+ This library follows [![Semantic Versioning 2.0.0][📌semver-img]][📌semver] for its public API where practical.
144
+ For most applications, prefer the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
145
+
146
+ For example:
147
+
148
+ ```ruby
149
+ spec.add_dependency("zip-merge", "~> 7.0")
150
+ ```
151
+
152
+ <details markdown="1">
153
+ <summary>📌 Is "Platform Support" part of the public API? More details inside.</summary>
154
+
155
+ Dropping support for a platform can be a breaking change for affected users.
156
+ If a release changes supported platforms, it should be called out clearly in the changelog and versioned with that impact in mind.
157
+
158
+ To get a better understanding of how SemVer is intended to work over a project's lifetime,
159
+ read this article from the creator of SemVer:
160
+
161
+ - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
162
+
163
+ </details>
164
+
165
+ See [CHANGELOG.md][📌changelog] for a list of releases.
166
+
167
+ ## 📄 License
168
+
169
+ The gem is available under the following licenses: [AGPL-3.0-only](https://github.com/structuredmerge/structuredmerge-ruby/blob/main/AGPL-3.0-only.md), [PolyForm-Small-Business-1.0.0](https://github.com/structuredmerge/structuredmerge-ruby/blob/main/PolyForm-Small-Business-1.0.0.md).
170
+ See [LICENSE.md][📄license] for details.
171
+
172
+ If none of the available licenses suit your use case, please [contact us](mailto:floss@galtzo.com) to discuss a custom commercial license.
173
+
174
+ [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat
175
+ [⛳liberapay-bottom-img]: https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611
176
+ [⛳liberapay]: https://liberapay.com/pboling/donate
177
+ [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
178
+ [🖇sponsor-bottom-img]: https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github
179
+ [🖇sponsor]: https://github.com/sponsors/pboling
180
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
181
+ [🖇kofi]: https://ko-fi.com/pboling
182
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
183
+ [🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff
184
+ [🖇buyme]: https://www.buymeacoffee.com/pboling
185
+ [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
186
+ [🖇paypal-bottom-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A
187
+ [🖇paypal]: https://www.paypal.com/paypalme/peterboling
188
+ [🖇floss-funding.dev]: https://floss-funding.dev
189
+ [🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding
190
+ [✉️discord-invite]: https://discord.gg/3qme4XHNKN
191
+ [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord
192
+ [✉️ruby-friends-img]: https://img.shields.io/badge/daily.dev-%F0%9F%92%8E_Ruby_Friends-0A0A0A?style=for-the-badge&logo=dailydotdev&logoColor=white
193
+ [✉️ruby-friends]: https://app.daily.dev/squads/rubyfriends
194
+ [✉️ruby-forum-top-img]: https://img.shields.io/discourse/topics?server=https%3A%2F%2Fwww.rubyforum.org&style=flat&logo=discourse&label=Ruby%20Users%20Forum
195
+ [✉️ruby-forum-img]: https://img.shields.io/discourse/topics?server=https%3A%2F%2Fwww.rubyforum.org&style=for-the-badge&logo=discourse&label=Ruby%20Users%20Forum
196
+ [✉️ruby-forum]: https://www.rubyforum.org/tag/structuredmerge
197
+ [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
198
+ [⛳️gem-namespace]: https://github.com/structuredmerge/structuredmerge-ruby/tree/main/gems/zip-merge
199
+ [⛳️namespace-img]: https://img.shields.io/badge/namespace-Zip::Merge-3C2D2D.svg?style=square&logo=ruby&logoColor=white
200
+ [⛳️gem-name]: https://clickgems.clickhouse.com/dashboard/zip-merge
201
+ [⛳️name-img]: https://img.shields.io/badge/name-zip--merge-3C2D2D.svg?style=square&logo=rubygems&logoColor=red
202
+ [⛳️tag-img]: https://img.shields.io/github/tag/structuredmerge/structuredmerge-ruby.svg
203
+ [⛳️tag]: https://github.com/structuredmerge/structuredmerge-ruby/releases
204
+ [🚂maint-blog]: http://www.railsbling.com/tags/zip-merge
205
+ [🚂maint-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange
206
+ [🚂maint-contact]: http://www.railsbling.com/contact
207
+ [🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red
208
+ [💖🖇linkedin]: http://www.linkedin.com/in/peterboling
209
+ [💖🖇linkedin-img]: https://img.shields.io/badge/LinkedIn-Profile-0B66C2?style=flat&logo=newjapanprowrestling
210
+ [💖✌️wellfound]: https://wellfound.com/u/peter-boling
211
+ [💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound
212
+ [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
213
+ [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase
214
+ [💖🐘ruby-mast]: https://ruby.social/@galtzo
215
+ [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https://ruby.social&style=flat&logo=mastodon&label=Ruby%20@galtzo
216
+ [💖🦋bluesky]: https://bsky.app/profile/galtzo.com
217
+ [💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white
218
+ [💖🌳linktree]: https://linktr.ee/galtzo
219
+ [💖🌳linktree-img]: https://img.shields.io/badge/galtzo-purple?style=flat&logo=linktree
220
+ [💖💁🏼‍♂️devto]: https://dev.to/galtzo
221
+ [💖💁🏼‍♂️devto-img]: https://img.shields.io/badge/dev.to-0A0A0A?style=flat&logo=devdotto&logoColor=white
222
+ [💖💁🏼‍♂️aboutme]: https://about.me/peter.boling
223
+ [💖💁🏼‍♂️aboutme-img]: https://img.shields.io/badge/about.me-0A0A0A?style=flat&logo=aboutme&logoColor=white
224
+ [💖🧊berg]: https://codeberg.org/pboling
225
+ [💖🐙hub]: https://github.org/pboling
226
+ [💖🛖hut]: https://sr.ht/~galtzo/
227
+ [💖🧪lab]: https://gitlab.com/pboling
228
+ [👨🏼‍🏫expsup-upwork]: https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share
229
+ [👨🏼‍🏫expsup-upwork-img]: https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white
230
+ [👨🏼‍🏫expsup-codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github
231
+ [👨🏼‍🏫expsup-codementor-img]: https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white
232
+ [🏙️entsup-tidelift]: https://tidelift.com/subscription/pkg/rubygems-zip-merge?utm_source=rubygems-zip-merge&utm_medium=referral&utm_campaign=readme
233
+ [🏙️entsup-tidelift-img]: https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white
234
+ [🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar
235
+ [💁🏼‍♂️peterboling]: http://www.peterboling.com
236
+ [🚂railsbling]: http://www.railsbling.com
237
+ [📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange
238
+ [📜src-gl]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/tree/main/gems/zip-merge
239
+ [📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue
240
+ [📜src-cb]: https://codeberg.org/structuredmerge/structuredmerge-ruby/src/branch/main/gems/zip-merge
241
+ [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=GitHub&logoColor=green
242
+ [📜src-gh]: https://github.com/structuredmerge/structuredmerge-ruby/tree/main/gems/zip-merge
243
+ [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
244
+ [📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
245
+ [📜gl-wiki]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/wikis/home
246
+ [📜gh-wiki]: https://github.com/structuredmerge/structuredmerge-ruby/wiki
247
+ [📜gl-wiki-img]: https://img.shields.io/badge/wiki-gitlab-943CD2.svg?style=for-the-badge&logo=gitlab&logoColor=white
248
+ [📜gh-wiki-img]: https://img.shields.io/badge/wiki-github-943CD2.svg?style=for-the-badge&logo=github&logoColor=white
249
+ [👽dl-rank]: https://clickgems.clickhouse.com/dashboard/zip-merge
250
+ [👽dl-ranki]: https://img.shields.io/gem/dt/zip-merge.svg
251
+ [👽version]: https://clickgems.clickhouse.com/dashboard/zip-merge
252
+ [👽versioni]: https://img.shields.io/gem/v/zip-merge.svg
253
+ [🚎11-c-wf]: https://github.com/structuredmerge/structuredmerge-ruby/actions/workflows/current.yml
254
+ [🚎11-c-wfi]: https://github.com/structuredmerge/structuredmerge-ruby/actions/workflows/current.yml/badge.svg
255
+ [💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green
256
+ [🤝gh-issues]: https://github.com/structuredmerge/structuredmerge-ruby/issues
257
+ [🤝gh-pulls]: https://github.com/structuredmerge/structuredmerge-ruby/pulls
258
+ [🤝gl-issues]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/issues
259
+ [🤝gl-pulls]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/merge_requests
260
+ [🤝cb-issues]: https://codeberg.org/structuredmerge/structuredmerge-ruby/issues
261
+ [🤝cb-pulls]: https://codeberg.org/structuredmerge/structuredmerge-ruby/pulls
262
+ [🤝cb-donate]: https://donate.codeberg.org/
263
+ [🤝contributing]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/CONTRIBUTING.md
264
+ [🖐contrib-rocks]: https://contrib.rocks
265
+ [🖐contributors]: https://github.com/structuredmerge/structuredmerge-ruby/graphs/contributors
266
+ [🖐contributors-img]: https://contrib.rocks/image?repo=structuredmerge/structuredmerge-ruby
267
+ [🪇conduct]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/CODE_OF_CONDUCT.md
268
+ [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg
269
+ [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
270
+ [📌semver]: https://semver.org/spec/v2.0.0.html
271
+ [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat
272
+ [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139
273
+ [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
274
+ [📌changelog]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/CHANGELOG.md
275
+ [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
276
+ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
277
+ [📌gitmoji]: https://gitmoji.dev
278
+ [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
279
+ [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
280
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.247-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
281
+ [🔐security]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/SECURITY.md
282
+ [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
283
+ [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
284
+ [📄license]: LICENSE.md
285
+ [📄license-ref]: LICENSE.md
286
+ [📄license-img]: https://img.shields.io/badge/License-AGPL--3.0--only_OR_PolyForm--Small--Business--1.0.0-259D6C.svg
287
+ [📄license-compat]: https://www.apache.org/legal/resolved.html#category-x
288
+ [📄license-compat-img]: https://img.shields.io/badge/Apache_Incompatible:_Category_X-%E2%9C%97-C0392B.svg?style=flat&logo=Apache
289
+ [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm
290
+ [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat
291
+ [🚎yard-current]: http://rubydoc.info/gems/zip-merge
292
+ [🚎yard-head]: https://zip-merge.galtzo.com
293
+ [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums
294
+ [💎SHA_checksums]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/tree/main/checksums
295
+ [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
296
+ [💎rlts-img]: https://img.shields.io/badge/code_style_&_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
297
+ [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
298
+ [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
299
+ [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zip
4
+ # StructuredMerge ZIP archive merge planning and rendering helpers.
5
+ module Merge
6
+ BACKEND_REFERENCE = TreeHaver::KAITAI_STRUCT_BACKEND
7
+
8
+ module Backend
9
+ # TreeHaver language wrapper for ZIP archives parsed through Kaitai-style
10
+ # binary AST inventory.
11
+ class Language < TreeHaver::Base::Language
12
+ def initialize(name = :zip)
13
+ super(name, backend: :kaitai, options: {})
14
+ end
15
+
16
+ def self.zip
17
+ new(:zip)
18
+ end
19
+ end
20
+
21
+ # Parser adapter that exposes the ZIP inventory as the TreeHaver
22
+ # `parser_for(:zip)` Kaitai backend surface.
23
+ class Parser < TreeHaver::Base::Parser
24
+ def parse(source)
25
+ raise 'Language not set' unless language
26
+
27
+ Zip::Merge.parse_zip_inventory(source)
28
+ end
29
+
30
+ def parse_string(_old_tree, source)
31
+ parse(source)
32
+ end
33
+ end
34
+ end
35
+
36
+ def self.register_backend!
37
+ TreeHaver::BackendRegistry.register(BACKEND_REFERENCE)
38
+ TreeHaver.register_language(
39
+ :zip,
40
+ backend_module: Backend,
41
+ backend_type: :kaitai,
42
+ gem_name: 'zip-merge',
43
+ contract: :kaitai
44
+ )
45
+ nil
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zip
4
+ module Merge
5
+ # Validates ZIP inputs while applying the safety-first opaque binary policy.
6
+ # rubocop:disable Metrics/MethodLength -- provider envelope is one public result contract
7
+ class Provider < Binary::Merge::Provider
8
+ PARSE_ERRORS = [RuntimeError, NoMethodError, TypeError, KeyError].freeze
9
+
10
+ def provider_id = 'ruby.zip'
11
+ def family = 'zip'
12
+
13
+ def capabilities
14
+ {
15
+ operations: Ast::Merge::ProviderContract::OPERATIONS,
16
+ dialects: %i[zip],
17
+ backends: [Zip::Merge::BACKEND_REFERENCE.id.to_sym],
18
+ profiles: %i[opaque_archive],
19
+ role: :workflow,
20
+ source_preservation: %i[exact_source opaque_conflict_retains_ours]
21
+ }.freeze
22
+ end
23
+
24
+ def analyze(request)
25
+ inventory = parse(request.fetch(:source), :source, :analyze, request)
26
+ return inventory if provider_result?(inventory)
27
+
28
+ result(:analyze, request, analysis: inventory)
29
+ end
30
+
31
+ def diff2(request)
32
+ failure = validate_sources(request, :diff2, before_source: :before, after_source: :after)
33
+ failure || super
34
+ end
35
+
36
+ def merge2(request)
37
+ failure = validate_sources(request, :merge2, current_source: :current, incoming_source: :incoming)
38
+ failure || super
39
+ end
40
+
41
+ def merge3(request)
42
+ failure = validate_sources(
43
+ request,
44
+ :merge3,
45
+ base_source: :base,
46
+ ours_source: :ours,
47
+ theirs_source: :theirs
48
+ )
49
+ failure || super
50
+ end
51
+
52
+ private
53
+
54
+ def validate_sources(request, operation, roles)
55
+ roles.each do |request_key, source_role|
56
+ parsed = parse(request.fetch(request_key), source_role, operation, request)
57
+ return parsed if provider_result?(parsed)
58
+ end
59
+ nil
60
+ end
61
+
62
+ def parse(source, source_role, operation, request)
63
+ Zip::Merge.parse_zip_inventory(source)
64
+ rescue *PARSE_ERRORS => e
65
+ failure(
66
+ operation,
67
+ request,
68
+ category: :parse_error,
69
+ message: "Invalid ZIP #{source_role} source: #{e.message}",
70
+ source_role: source_role
71
+ )
72
+ end
73
+
74
+ def provider_result?(value)
75
+ value.is_a?(Hash) && value[:schema] == Ast::Merge::ProviderContract::RESULT_SCHEMA
76
+ end
77
+
78
+ def envelope(request, **fields)
79
+ {
80
+ provider: {
81
+ provider_id: provider_id,
82
+ family: family,
83
+ dialect: request[:dialect] || :zip,
84
+ backend: request[:backend],
85
+ package: 'zip-merge',
86
+ package_version: Zip::Merge::Version::VERSION
87
+ },
88
+ profile: { profile_id: request[:profile_id] || :opaque_archive }
89
+ }.merge(fields)
90
+ end
91
+ end
92
+ # rubocop:enable Metrics/MethodLength
93
+ end
94
+ end
95
+
96
+ # Provider registration entry point.
97
+ module Zip
98
+ # ZIP provider registration.
99
+ module Merge
100
+ module_function
101
+
102
+ def merge_provider
103
+ @merge_provider ||= Provider.new
104
+ end
105
+
106
+ def register_provider!
107
+ Ast::Merge.register_provider(merge_provider, replace: true)
108
+ end
109
+ end
110
+ end
@@ -2,10 +2,12 @@
2
2
 
3
3
  module Zip
4
4
  module Merge
5
+ # Version namespace for this gem.
5
6
  module Version
6
- VERSION = "7.0.0"
7
+ # Current gem version.
8
+ VERSION = '7.1.3'
7
9
  end
8
-
9
- VERSION = Version::VERSION
10
+ # Current gem version exposed at the traditional constant location.
11
+ VERSION = Version::VERSION # Traditional Constant Location
10
12
  end
11
13
  end