ast-merge-git 7.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6527f8c9a9e11a701a0650d6b6eb473c2182368ca1bef5338392ad332461911a
4
+ data.tar.gz: d8b813c4d98258a2ed46b016a943e350271b13a5f17d31f13733dea638fccc6f
5
+ SHA512:
6
+ metadata.gz: 8bc8b1aea1fbc0d857a6ce20280b28e634717a1ada45db509a1443ad6465776cb04be45d0c33b5d893a61ff8701dbab48196d67038c46ec4edee41d887329474
7
+ data.tar.gz: db7093c64f37155685bdac5ae5b8fdc5120d51a5b1f154bef1bf05badb5a00c721a8bcef9205fed399dae76fc2bcbeb707d749c9c3a67ad122a3d06d724bd9c8
checksums.yaml.gz.sig ADDED
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,294 @@
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
+ # ☯️ Ast::Merge::Git
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
+ `ast-merge-git` adapts StructuredMerge contracts to Git merge-driver workflows. It translates Git driver inputs into family-aware merge requests and reports structured diagnostics that can be surfaced by repository tooling.
25
+
26
+ ### Key Features
27
+
28
+ - Git-oriented request and response shaping for three-way merge driver integrations.
29
+ - Family detection from path, extension, and configured merge behavior.
30
+ - JSON-compatible reports that can be logged, inspected, or replayed by higher-level tooling.
31
+ - Fallback-friendly behavior for unsupported families or unsafe parser results.
32
+
33
+ ## 💡 Info you can shake a stick at
34
+
35
+ | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
36
+ |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
37
+ | Works with MRI Ruby 4 | [![Ruby current Compat][💎ruby-c-i]][🚎11-c-wf]|
38
+ | 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] |
39
+ | 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] |
40
+ | 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] |
41
+ | 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] |
42
+ | 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] |
43
+ | 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] |
44
+ | `...` 💖 | [![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] |
45
+
46
+ ### Compatibility
47
+
48
+ Compatible with MRI Ruby 4.0.0+, and concordant releases of JRuby, and TruffleRuby.
49
+ CI workflows and Appraisals are generated for MRI Ruby 4.0.0+.
50
+ This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
51
+ may be higher than the gem's runtime compatibility floor when legacy Rubies are
52
+ not practical for the current toolchain.
53
+
54
+ <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>
55
+
56
+ The _amazing_ test matrix is powered by the kettle-dev stack.
57
+
58
+ <details markdown="1">
59
+ <summary>How kettle-dev manages complexity in tests</summary>
60
+
61
+ | Gem | Source | Role | Total downloads |
62
+ |-----|--------|------|---------------------|
63
+ | [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) |
64
+ | [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) |
65
+ | [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) |
66
+ | [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) |
67
+ | [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) |
68
+ | [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) |
69
+ | [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) |
70
+ | [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) |
71
+
72
+ </details>
73
+
74
+ ## ✨ Installation
75
+
76
+ Install the gem and add to the application's Gemfile by executing:
77
+
78
+ ```console
79
+ bundle add ast-merge-git
80
+ ```
81
+
82
+ If bundler is not being used to manage dependencies, install the gem by executing:
83
+
84
+ ```console
85
+ gem install ast-merge-git
86
+ ```
87
+
88
+ ## ⚙️ Configuration
89
+
90
+ Configure `ast-merge-git` through the repository's Git attributes and StructuredMerge family settings. The gem expects callers to provide the ancestor, current, and incoming file contents that Git passes to a custom merge driver.
91
+
92
+ Keep family-specific parser configuration in the corresponding merge gem. For example, Markdown backend choices belong to `markdown-merge` or its provider gems, while Ruby source backend choices belong to `ruby-merge` or `prism-merge`.
93
+
94
+ ## 🔧 Basic Usage
95
+
96
+ ```ruby
97
+ require "ast/merge/git"
98
+
99
+ result = Ast::Merge::Git.merge3(
100
+ language: "json",
101
+ dialect: "json",
102
+ base_source: File.binread("%O"),
103
+ ours_source: File.binread("%A"),
104
+ theirs_source: File.binread("%B"),
105
+ )
106
+
107
+ if result.fetch(:ok)
108
+ File.binwrite("%A", result.fetch(:merged_source))
109
+ else
110
+ File.binwrite("%A", result.fetch(:conflicted_source)) if result[:conflicted_source]
111
+ abort result.fetch(:diagnostics).inspect
112
+ end
113
+ ```
114
+
115
+ ## 🔐 Security
116
+
117
+ See [SECURITY.md][🔐security].
118
+
119
+ ## 🤝 Contributing
120
+
121
+ If you need some ideas of where to help, you could work on adding more code coverage,
122
+ or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues] or [PRs][🤝gh-pulls],
123
+ or use the gem and think about how it could be better.
124
+
125
+ We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
126
+
127
+ See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
128
+
129
+ ### Code Coverage
130
+
131
+ <details markdown="1">
132
+ <summary>Coverage service badges</summary>
133
+
134
+ </details>
135
+
136
+ ## 📌 Versioning
137
+
138
+ This library follows [![Semantic Versioning 2.0.0][📌semver-img]][📌semver] for its public API where practical.
139
+ For most applications, prefer the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
140
+
141
+ For example:
142
+
143
+ ```ruby
144
+ spec.add_dependency("ast-merge-git", "~> 7.0")
145
+ ```
146
+
147
+ <details markdown="1">
148
+ <summary>📌 Is "Platform Support" part of the public API? More details inside.</summary>
149
+
150
+ Dropping support for a platform can be a breaking change for affected users.
151
+ If a release changes supported platforms, it should be called out clearly in the changelog and versioned with that impact in mind.
152
+
153
+ To get a better understanding of how SemVer is intended to work over a project's lifetime,
154
+ read this article from the creator of SemVer:
155
+
156
+ - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
157
+
158
+ </details>
159
+
160
+ See [CHANGELOG.md][📌changelog] for a list of releases.
161
+
162
+ ## 📄 License
163
+
164
+ 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).
165
+ See [LICENSE.md][📄license] for details.
166
+
167
+ If none of the available licenses suit your use case, please [contact us](mailto:floss@galtzo.com) to discuss a custom commercial license.
168
+
169
+ [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat
170
+ [⛳liberapay-bottom-img]: https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611
171
+ [⛳liberapay]: https://liberapay.com/pboling/donate
172
+ [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
173
+ [🖇sponsor-bottom-img]: https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github
174
+ [🖇sponsor]: https://github.com/sponsors/pboling
175
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
176
+ [🖇kofi]: https://ko-fi.com/pboling
177
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
178
+ [🖇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
179
+ [🖇buyme]: https://www.buymeacoffee.com/pboling
180
+ [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
181
+ [🖇paypal-bottom-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A
182
+ [🖇paypal]: https://www.paypal.com/paypalme/peterboling
183
+ [🖇floss-funding.dev]: https://floss-funding.dev
184
+ [🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding
185
+ [✉️discord-invite]: https://discord.gg/3qme4XHNKN
186
+ [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord
187
+ [✉️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
188
+ [✉️ruby-friends]: https://app.daily.dev/squads/rubyfriends
189
+ [✉️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
190
+ [✉️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
191
+ [✉️ruby-forum]: https://www.rubyforum.org/tag/structuredmerge
192
+ [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
193
+ [⛳️gem-namespace]: https://github.com/structuredmerge/structuredmerge-ruby/tree/main/gems/ast-merge-git
194
+ [⛳️namespace-img]: https://img.shields.io/badge/namespace-Ast::Merge::Git-3C2D2D.svg?style=square&logo=ruby&logoColor=white
195
+ [⛳️gem-name]: https://clickgems.clickhouse.com/dashboard/ast-merge-git
196
+ [⛳️name-img]: https://img.shields.io/badge/name-ast--merge--git-3C2D2D.svg?style=square&logo=rubygems&logoColor=red
197
+ [⛳️tag-img]: https://img.shields.io/github/tag/structuredmerge/structuredmerge-ruby.svg
198
+ [⛳️tag]: https://github.com/structuredmerge/structuredmerge-ruby/releases
199
+ [🚂maint-blog]: http://www.railsbling.com/tags/ast-merge-git
200
+ [🚂maint-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange
201
+ [🚂maint-contact]: http://www.railsbling.com/contact
202
+ [🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red
203
+ [💖🖇linkedin]: http://www.linkedin.com/in/peterboling
204
+ [💖🖇linkedin-img]: https://img.shields.io/badge/LinkedIn-Profile-0B66C2?style=flat&logo=newjapanprowrestling
205
+ [💖✌️wellfound]: https://wellfound.com/u/peter-boling
206
+ [💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound
207
+ [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
208
+ [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase
209
+ [💖🐘ruby-mast]: https://ruby.social/@galtzo
210
+ [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https://ruby.social&style=flat&logo=mastodon&label=Ruby%20@galtzo
211
+ [💖🦋bluesky]: https://bsky.app/profile/galtzo.com
212
+ [💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white
213
+ [💖🌳linktree]: https://linktr.ee/galtzo
214
+ [💖🌳linktree-img]: https://img.shields.io/badge/galtzo-purple?style=flat&logo=linktree
215
+ [💖💁🏼‍♂️devto]: https://dev.to/galtzo
216
+ [💖💁🏼‍♂️devto-img]: https://img.shields.io/badge/dev.to-0A0A0A?style=flat&logo=devdotto&logoColor=white
217
+ [💖💁🏼‍♂️aboutme]: https://about.me/peter.boling
218
+ [💖💁🏼‍♂️aboutme-img]: https://img.shields.io/badge/about.me-0A0A0A?style=flat&logo=aboutme&logoColor=white
219
+ [💖🧊berg]: https://codeberg.org/pboling
220
+ [💖🐙hub]: https://github.org/pboling
221
+ [💖🛖hut]: https://sr.ht/~galtzo/
222
+ [💖🧪lab]: https://gitlab.com/pboling
223
+ [👨🏼‍🏫expsup-upwork]: https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share
224
+ [👨🏼‍🏫expsup-upwork-img]: https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white
225
+ [👨🏼‍🏫expsup-codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github
226
+ [👨🏼‍🏫expsup-codementor-img]: https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white
227
+ [🏙️entsup-tidelift]: https://tidelift.com/subscription/pkg/rubygems-ast-merge-git?utm_source=rubygems-ast-merge-git&utm_medium=referral&utm_campaign=readme
228
+ [🏙️entsup-tidelift-img]: https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white
229
+ [🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar
230
+ [💁🏼‍♂️peterboling]: http://www.peterboling.com
231
+ [🚂railsbling]: http://www.railsbling.com
232
+ [📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange
233
+ [📜src-gl]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/tree/main/gems/ast-merge-git
234
+ [📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue
235
+ [📜src-cb]: https://codeberg.org/structuredmerge/structuredmerge-ruby/src/branch/main/gems/ast-merge-git
236
+ [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=GitHub&logoColor=green
237
+ [📜src-gh]: https://github.com/structuredmerge/structuredmerge-ruby/tree/main/gems/ast-merge-git
238
+ [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
239
+ [📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
240
+ [📜gl-wiki]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/wikis/home
241
+ [📜gh-wiki]: https://github.com/structuredmerge/structuredmerge-ruby/wiki
242
+ [📜gl-wiki-img]: https://img.shields.io/badge/wiki-gitlab-943CD2.svg?style=for-the-badge&logo=gitlab&logoColor=white
243
+ [📜gh-wiki-img]: https://img.shields.io/badge/wiki-github-943CD2.svg?style=for-the-badge&logo=github&logoColor=white
244
+ [👽dl-rank]: https://clickgems.clickhouse.com/dashboard/ast-merge-git
245
+ [👽dl-ranki]: https://img.shields.io/gem/dt/ast-merge-git.svg
246
+ [👽version]: https://clickgems.clickhouse.com/dashboard/ast-merge-git
247
+ [👽versioni]: https://img.shields.io/gem/v/ast-merge-git.svg
248
+ [🚎11-c-wf]: https://github.com/structuredmerge/structuredmerge-ruby/actions/workflows/current.yml
249
+ [🚎11-c-wfi]: https://github.com/structuredmerge/structuredmerge-ruby/actions/workflows/current.yml/badge.svg
250
+ [💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green
251
+ [🤝gh-issues]: https://github.com/structuredmerge/structuredmerge-ruby/issues
252
+ [🤝gh-pulls]: https://github.com/structuredmerge/structuredmerge-ruby/pulls
253
+ [🤝gl-issues]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/issues
254
+ [🤝gl-pulls]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/merge_requests
255
+ [🤝cb-issues]: https://codeberg.org/structuredmerge/structuredmerge-ruby/issues
256
+ [🤝cb-pulls]: https://codeberg.org/structuredmerge/structuredmerge-ruby/pulls
257
+ [🤝cb-donate]: https://donate.codeberg.org/
258
+ [🤝contributing]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/CONTRIBUTING.md
259
+ [🖐contrib-rocks]: https://contrib.rocks
260
+ [🖐contributors]: https://github.com/structuredmerge/structuredmerge-ruby/graphs/contributors
261
+ [🖐contributors-img]: https://contrib.rocks/image?repo=structuredmerge/structuredmerge-ruby
262
+ [🪇conduct]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/CODE_OF_CONDUCT.md
263
+ [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg
264
+ [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
265
+ [📌semver]: https://semver.org/spec/v2.0.0.html
266
+ [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat
267
+ [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139
268
+ [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
269
+ [📌changelog]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/CHANGELOG.md
270
+ [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
271
+ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
272
+ [📌gitmoji]: https://gitmoji.dev
273
+ [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
274
+ [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
275
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.163-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
276
+ [🔐security]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/SECURITY.md
277
+ [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
278
+ [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
279
+ [📄license]: LICENSE.md
280
+ [📄license-ref]: LICENSE.md
281
+ [📄license-img]: https://img.shields.io/badge/License-AGPL--3.0--only_OR_PolyForm--Small--Business--1.0.0-259D6C.svg
282
+ [📄license-compat]: https://www.apache.org/legal/resolved.html#category-x
283
+ [📄license-compat-img]: https://img.shields.io/badge/Apache_Incompatible:_Category_X-%E2%9C%97-C0392B.svg?style=flat&logo=Apache
284
+ [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm
285
+ [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat
286
+ [🚎yard-current]: http://rubydoc.info/gems/ast-merge-git
287
+ [🚎yard-head]: https://ast-merge-git.galtzo.com
288
+ [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums
289
+ [💎SHA_checksums]: https://gitlab.com/structuredmerge/structuredmerge-ruby/-/tree/main/checksums
290
+ [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
291
+ [💎rlts-img]: https://img.shields.io/badge/code_style_&_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
292
+ [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
293
+ [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
294
+ [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ast
4
+ module Merge
5
+ module Git
6
+ # Version namespace for this gem.
7
+ module Version
8
+ # Current gem version.
9
+ VERSION = '7.1.1'
10
+ end
11
+ # Current gem version exposed at the traditional constant location.
12
+ VERSION = Version::VERSION # Traditional Constant Location
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,412 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ast/merge'
4
+ require 'json'
5
+ require 'json/merge'
6
+
7
+ module Ast
8
+ module Merge
9
+ module Git
10
+ PACKAGE_NAME = 'ast-merge-git'
11
+ MERGE_CONFLICT_CATEGORY = 'merge_conflict'
12
+ MISSING = Object.new.freeze
13
+
14
+ module_function
15
+
16
+ def merge3(request)
17
+ normalized = normalize_request(request)
18
+ case normalize_language(normalized)
19
+ when 'json'
20
+ merge3_json(normalized)
21
+ else
22
+ response(
23
+ ok: false,
24
+ request: normalized,
25
+ diagnostics: [{
26
+ severity: 'error',
27
+ category: 'unsupported_feature',
28
+ message: 'ast-merge-git currently supports only json merge3.'
29
+ }]
30
+ )
31
+ end
32
+ end
33
+
34
+ def merge3_json(request)
35
+ parsed = parse_json_merge3_inputs(request)
36
+ return parsed unless parsed.is_a?(Hash) && parsed[:ok]
37
+
38
+ merge = merge_json_values(
39
+ parsed.fetch(:base),
40
+ parsed.fetch(:ours),
41
+ parsed.fetch(:theirs),
42
+ path: ''
43
+ )
44
+
45
+ if merge.fetch(:conflicts).empty?
46
+ merged_source = "#{JSON.pretty_generate(merge.fetch(:value))}\n"
47
+ return response(
48
+ ok: true,
49
+ request: request,
50
+ merged_source: merged_source,
51
+ change_classifications: merge.fetch(:change_classifications),
52
+ reparse_after_render: reparse_json_source(merged_source),
53
+ formatting_preservation: {
54
+ line_diff_score: 1.0,
55
+ character_diff_score: 1.0
56
+ }
57
+ )
58
+ end
59
+
60
+ render_conflicted_json(request, merge)
61
+ end
62
+
63
+ def parse_json_merge3_inputs(request)
64
+ dialect = request[:dialect].to_s.empty? ? 'json' : request[:dialect].to_s
65
+ {
66
+ ok: true,
67
+ base: Json::Merge.json_value_for_source(request.fetch(:base_source), dialect: dialect),
68
+ ours: Json::Merge.json_value_for_source(request.fetch(:ours_source), dialect: dialect),
69
+ theirs: Json::Merge.json_value_for_source(request.fetch(:theirs_source), dialect: dialect)
70
+ }
71
+ rescue Json::Merge::ParseError => e
72
+ source_role = parse_error_role(request, dialect)
73
+ response(
74
+ ok: false,
75
+ request: request,
76
+ diagnostics: [{
77
+ severity: 'error',
78
+ category: 'parse_error',
79
+ message: "#{source_role} parse error: #{e.message}"
80
+ }]
81
+ )
82
+ end
83
+
84
+ def parse_error_role(request, dialect)
85
+ %i[base ours theirs].find do |role|
86
+ Json::Merge.json_value_for_source(request.fetch(:"#{role}_source"), dialect: dialect)
87
+ false
88
+ rescue Json::Merge::ParseError
89
+ true
90
+ end || :unknown
91
+ end
92
+
93
+ def merge_json_values(base, ours, theirs, path:)
94
+ if ours == theirs
95
+ return merge_success(ours)
96
+ elsif base == ours
97
+ return merge_success(theirs, change: classify_json_change(path, base, ours, theirs))
98
+ elsif base == theirs
99
+ return merge_success(ours, change: classify_json_change(path, base, ours, theirs))
100
+ end
101
+
102
+ if base.is_a?(Hash) && ours.is_a?(Hash) && theirs.is_a?(Hash)
103
+ return merge_json_objects(base, ours, theirs, path: path)
104
+ end
105
+
106
+ conflict = json_conflict(path, base, ours, theirs)
107
+ {
108
+ value: ours.equal?(MISSING) ? theirs : ours,
109
+ conflicts: [conflict],
110
+ change_classifications: [conflict.fetch(:change_classification)]
111
+ }
112
+ end
113
+
114
+ def merge_json_objects(base, ours, theirs, path:)
115
+ merged = {}
116
+ conflicts = []
117
+ change_classifications = []
118
+ ordered_keys(base, ours, theirs).each do |key|
119
+ child_path = "#{path}/#{key}"
120
+ child = merge_json_values(
121
+ base.fetch(key, MISSING),
122
+ ours.fetch(key, MISSING),
123
+ theirs.fetch(key, MISSING),
124
+ path: child_path
125
+ )
126
+ merged[key] = child.fetch(:value) unless child.fetch(:value).equal?(MISSING)
127
+ conflicts.concat(child.fetch(:conflicts))
128
+ change_classifications.concat(child.fetch(:change_classifications))
129
+ end
130
+
131
+ {
132
+ value: merged,
133
+ conflicts: conflicts,
134
+ change_classifications: change_classifications
135
+ }
136
+ end
137
+
138
+ def ordered_keys(*objects)
139
+ objects.each_with_object([]) do |object, keys|
140
+ next unless object.is_a?(Hash)
141
+
142
+ object.each_key { |key| keys << key unless keys.include?(key) }
143
+ end
144
+ end
145
+
146
+ def merge_success(value, change: nil)
147
+ {
148
+ value: value,
149
+ conflicts: [],
150
+ change_classifications: change ? [change] : []
151
+ }
152
+ end
153
+
154
+ def classify_json_change(path, base, ours, theirs)
155
+ {
156
+ path: path,
157
+ ours: json_change_state(base, ours),
158
+ theirs: json_change_state(base, theirs)
159
+ }
160
+ end
161
+
162
+ def json_change_state(base, value)
163
+ return 'unchanged' if base == value
164
+ return 'added' if base.equal?(MISSING)
165
+ return 'deleted' if value.equal?(MISSING)
166
+
167
+ 'edited'
168
+ end
169
+
170
+ def json_conflict(path, base, ours, theirs)
171
+ category =
172
+ if ours.equal?(MISSING) || theirs.equal?(MISSING)
173
+ 'delete_edit'
174
+ else
175
+ 'edit_edit'
176
+ end
177
+ {
178
+ conflict_id: "json-conflict-#{path.delete_prefix('/').tr('/', '-')}",
179
+ category: category,
180
+ path: path,
181
+ message: "JSON value changed incompatibly at #{path}",
182
+ base: base,
183
+ ours: ours,
184
+ theirs: theirs,
185
+ change_classification: classify_json_change(path, base, ours, theirs)
186
+ }
187
+ end
188
+
189
+ def render_conflicted_json(request, merge)
190
+ conflicts = merge.fetch(:conflicts)
191
+ full_file = conflicts.any? { |conflict| conflict.fetch(:category) == 'delete_edit' }
192
+ conflicted_source = if full_file
193
+ render_conflict_source(request, conflicts)
194
+ else
195
+ render_owned_json_conflict_source(request, conflicts.first)
196
+ end
197
+ response(
198
+ ok: false,
199
+ request: request,
200
+ conflicted_source: conflicted_source,
201
+ conflicts: conflicts.map { |conflict| conflict.slice(:conflict_id, :category, :path, :message) },
202
+ change_classifications: merge.fetch(:change_classifications),
203
+ diagnostics: [{
204
+ severity: 'error',
205
+ category: MERGE_CONFLICT_CATEGORY,
206
+ message: "#{conflicts.length} unresolved JSON merge conflict(s)."
207
+ }],
208
+ owned_regions: full_file ? [] : [owned_json_region(conflicts.first)],
209
+ reparse_after_render: nil,
210
+ render_strategy: full_file ? 'full_file_conflict_markers' : 'owned_region_conflict_markers'
211
+ )
212
+ end
213
+
214
+ def render_owned_json_conflict_source(request, conflict)
215
+ marker_size = request[:conflict_marker_size].to_i
216
+ marker_size = 7 unless marker_size.positive?
217
+ key = conflict.fetch(:path).split('/').last
218
+ [
219
+ '{',
220
+ "#{'<' * marker_size} ours",
221
+ "#{JSON.generate(key)}:#{JSON.generate(conflict.fetch(:ours))}",
222
+ "#{'|' * marker_size} base",
223
+ "#{JSON.generate(key)}:#{JSON.generate(conflict.fetch(:base))}",
224
+ '=' * marker_size,
225
+ "#{JSON.generate(key)}:#{JSON.generate(conflict.fetch(:theirs))}",
226
+ "#{'>' * marker_size} theirs",
227
+ '}',
228
+ ''
229
+ ].join("\n")
230
+ end
231
+
232
+ def owned_json_region(conflict)
233
+ {
234
+ owner_path: conflict.fetch(:path),
235
+ node_id: "json:key:#{conflict.fetch(:path).split('/').last}",
236
+ region_kind: 'node',
237
+ line_range: { start: 1, end: 1 },
238
+ attached_spans: [],
239
+ backend_id: 'tree-haver',
240
+ parser_identity: 'tree_sitter_language_pack',
241
+ can_replace: true,
242
+ can_line_merge: false,
243
+ requires_reparse: true
244
+ }
245
+ end
246
+
247
+ def reparse_json_source(source)
248
+ Json::Merge.json_value_for_source(source)
249
+ true
250
+ rescue Json::Merge::ParseError
251
+ false
252
+ end
253
+
254
+ def normalize_request(request)
255
+ request.transform_keys(&:to_sym)
256
+ end
257
+
258
+ def merge_comment_delta(base_comment:, ours_comment:, theirs_comment:, owner_path: '/')
259
+ conflicts = []
260
+ merged_comment =
261
+ if ours_comment == theirs_comment
262
+ ours_comment
263
+ elsif base_comment == ours_comment
264
+ theirs_comment
265
+ elsif base_comment == theirs_comment
266
+ ours_comment
267
+ elsif ours_comment.nil?
268
+ conflicts << comment_conflict('delete_edit', owner_path, 'ours deleted a comment that theirs edited')
269
+ theirs_comment
270
+ elsif theirs_comment.nil?
271
+ conflicts << comment_conflict('delete_edit', owner_path, 'theirs deleted a comment that ours edited')
272
+ ours_comment
273
+ else
274
+ conflicts << comment_conflict('edit_edit', owner_path, 'comment changed differently in ours and theirs')
275
+ ours_comment
276
+ end
277
+
278
+ {
279
+ ok: conflicts.empty?,
280
+ merged_comment: conflicts.empty? ? merged_comment : nil,
281
+ conflicts: conflicts
282
+ }
283
+ end
284
+
285
+ def response(ok:, request:, merged_source: nil, conflicted_source: nil, conflicts: [],
286
+ change_classifications: [], diagnostics: [], fallbacks: [], owned_regions: [], reparse_after_render: nil, formatting_preservation: {}, secondary_formatting_metrics: nil, render_strategy: nil)
287
+ {
288
+ ok: ok,
289
+ merged_source: merged_source,
290
+ conflicted_source: conflicted_source,
291
+ conflicts: conflicts,
292
+ change_classifications: change_classifications,
293
+ diagnostics: diagnostics,
294
+ fallbacks: fallbacks,
295
+ owned_regions: owned_regions,
296
+ profile: {
297
+ profile_id: request[:profile_id].to_s,
298
+ language: normalize_language(request),
299
+ dialect: request[:dialect].to_s
300
+ },
301
+ render_report: {
302
+ strategy: render_strategy || (request[:render_policy].to_s.empty? ? 'canonical' : request[:render_policy].to_s),
303
+ **render_identity(request)
304
+ },
305
+ formatting_preservation: {
306
+ line_diff_score: 0.0,
307
+ character_diff_score: 0.0
308
+ }.merge(formatting_preservation),
309
+ secondary_formatting_metrics: secondary_formatting_metrics || secondary_formatting_metrics_for(ok && merged_source),
310
+ default_driver_evaluation: default_driver_evaluation(
311
+ formatting_preservation: {
312
+ line_diff_score: 0.0,
313
+ character_diff_score: 0.0
314
+ }.merge(formatting_preservation),
315
+ reparse_after_render: reparse_after_render,
316
+ render_strategy: render_strategy || (request[:render_policy].to_s.empty? ? 'canonical' : request[:render_policy].to_s)
317
+ ),
318
+ reparse_after_render: reparse_after_render
319
+ }
320
+ end
321
+
322
+ def default_driver_evaluation(formatting_preservation:, reparse_after_render:, render_strategy:)
323
+ threshold = 0.95
324
+ score = (formatting_preservation.fetch(:line_diff_score) + formatting_preservation.fetch(:character_diff_score)) / 2.0
325
+ reparse_passed = reparse_after_render == true
326
+ no_full_file_rewrite = render_strategy != 'full_file_conflict_markers'
327
+ coherent_conflict_markers = render_strategy != 'full_file_conflict_markers'
328
+ blocking_reasons = []
329
+ blocking_reasons << 'rendered output did not reparse' unless reparse_passed
330
+ blocking_reasons << 'formatting score is below threshold' if score < threshold
331
+ blocking_reasons << 'full-file rewrite or conflict markers were used' unless no_full_file_rewrite
332
+ blocking_reasons << 'conflict marker placement is not syntactically coherent' unless coherent_conflict_markers
333
+
334
+ {
335
+ status: blocking_reasons.empty? ? 'recommended' : 'not_recommended',
336
+ formatting_threshold: threshold,
337
+ formatting_score: score,
338
+ hard_gates: [
339
+ { name: 'reparse_after_render', passed: reparse_passed, weighted: false },
340
+ { name: 'no_full_file_rewrite', passed: no_full_file_rewrite, weighted: false },
341
+ { name: 'coherent_conflict_marker_placement', passed: coherent_conflict_markers, weighted: false }
342
+ ],
343
+ blocking_reasons: blocking_reasons,
344
+ diagnostics: ['default-driver evaluation is advisory unless explicitly required']
345
+ }
346
+ end
347
+
348
+ def secondary_formatting_metrics_for(merged)
349
+ if merged
350
+ {
351
+ unchanged_line_churn: 0,
352
+ output_diff_size: 0,
353
+ source_fragment_retention: 1.0,
354
+ weighted: false,
355
+ diagnostics: ['canonical JSON has no trivia-preserving source fragments yet']
356
+ }
357
+ else
358
+ {
359
+ unchanged_line_churn: 0,
360
+ output_diff_size: 0,
361
+ source_fragment_retention: 0.0,
362
+ weighted: false,
363
+ diagnostics: ['unresolved conflict did not produce a merged source-fragment retention measurement']
364
+ }
365
+ end
366
+ end
367
+
368
+ def render_identity(request)
369
+ case normalize_language(request)
370
+ when 'json'
371
+ { backend_id: 'tree-haver', parser_identity: 'tree_sitter_language_pack' }
372
+ else
373
+ {}
374
+ end
375
+ end
376
+
377
+ def render_conflict_source(request, conflicts)
378
+ marker_size = request[:conflict_marker_size].to_i
379
+ marker_size = 7 unless marker_size.positive?
380
+ header = "/* smorg structured conflicts: #{conflicts.length} unresolved */"
381
+ [
382
+ header,
383
+ "#{'<' * marker_size} ours",
384
+ request.fetch(:ours_source),
385
+ "#{'|' * marker_size} base",
386
+ request.fetch(:base_source),
387
+ '=' * marker_size,
388
+ request.fetch(:theirs_source),
389
+ "#{'>' * marker_size} theirs",
390
+ ''
391
+ ].join("\n")
392
+ end
393
+
394
+ def comment_conflict(category, path, message)
395
+ {
396
+ conflict_id: 'comment-conflict-1',
397
+ category: category,
398
+ path: path.to_s.empty? ? '/' : path,
399
+ message: message
400
+ }
401
+ end
402
+
403
+ def normalize_language(request)
404
+ language = request[:language].to_s.strip.downcase
405
+ return 'json' if language == 'json'
406
+ return 'json' if request[:path_name].to_s.downcase.end_with?('.json')
407
+
408
+ language
409
+ end
410
+ end
411
+ end
412
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ast/merge/git'
4
+ require 'version_gem'
5
+ require_relative 'ast/merge/git/version'
6
+
7
+ Ast::Merge::Git::Version.class_eval do
8
+ extend VersionGem::Basic
9
+ end
@@ -0,0 +1,10 @@
1
+ module Ast
2
+ module Merge
3
+ module Git
4
+ module Version
5
+ VERSION: String
6
+ end
7
+ VERSION: String
8
+ end
9
+ end
10
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,346 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ast-merge-git
3
+ version: !ruby/object:Gem::Version
4
+ version: 7.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Peter H. Boling
8
+ bindir: exe
9
+ cert_chain:
10
+ - |
11
+ -----BEGIN CERTIFICATE-----
12
+ MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
13
+ ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
14
+ A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM
15
+ DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
16
+ LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA
17
+ uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61
18
+ LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5
19
+ mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN
20
+ coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV
21
+ FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj
22
+ yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1
23
+ to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD
24
+ qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj
25
+ fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ
26
+ HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
27
+ A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
28
+ ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9
29
+ wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR
30
+ L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm
31
+ GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k
32
+ kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq
33
+ QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA
34
+ 0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p
35
+ DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
36
+ L9nRqA==
37
+ -----END CERTIFICATE-----
38
+ date: 1980-01-02 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: ast-merge
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '='
45
+ - !ruby/object:Gem::Version
46
+ version: 7.1.1
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '='
52
+ - !ruby/object:Gem::Version
53
+ version: 7.1.1
54
+ - !ruby/object:Gem::Dependency
55
+ name: json-merge
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '='
59
+ - !ruby/object:Gem::Version
60
+ version: 7.1.1
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '='
66
+ - !ruby/object:Gem::Version
67
+ version: 7.1.1
68
+ - !ruby/object:Gem::Dependency
69
+ name: version_gem
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.1'
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 1.1.15
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '1.1'
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: 1.1.15
88
+ - !ruby/object:Gem::Dependency
89
+ name: kettle-dev
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '2.5'
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 2.5.17
98
+ type: :development
99
+ prerelease: false
100
+ version_requirements: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '2.5'
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: 2.5.17
108
+ - !ruby/object:Gem::Dependency
109
+ name: bundler-audit
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: 0.9.3
115
+ type: :development
116
+ prerelease: false
117
+ version_requirements: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: 0.9.3
122
+ - !ruby/object:Gem::Dependency
123
+ name: rake
124
+ requirement: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - "~>"
127
+ - !ruby/object:Gem::Version
128
+ version: '13.0'
129
+ type: :development
130
+ prerelease: false
131
+ version_requirements: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: '13.0'
136
+ - !ruby/object:Gem::Dependency
137
+ name: require_bench
138
+ requirement: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: '1.0'
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: 1.0.4
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '1.0'
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: 1.0.4
156
+ - !ruby/object:Gem::Dependency
157
+ name: anonymous_loader
158
+ requirement: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - "~>"
161
+ - !ruby/object:Gem::Version
162
+ version: '0.1'
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: 0.1.3
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '0.1'
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: 0.1.3
176
+ - !ruby/object:Gem::Dependency
177
+ name: appraisal2
178
+ requirement: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - "~>"
181
+ - !ruby/object:Gem::Version
182
+ version: '3.2'
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: 3.2.0
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - "~>"
191
+ - !ruby/object:Gem::Version
192
+ version: '3.2'
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: 3.2.0
196
+ - !ruby/object:Gem::Dependency
197
+ name: kettle-test
198
+ requirement: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - "~>"
201
+ - !ruby/object:Gem::Version
202
+ version: '2.0'
203
+ - - ">="
204
+ - !ruby/object:Gem::Version
205
+ version: 2.0.19
206
+ type: :development
207
+ prerelease: false
208
+ version_requirements: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - "~>"
211
+ - !ruby/object:Gem::Version
212
+ version: '2.0'
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: 2.0.19
216
+ - !ruby/object:Gem::Dependency
217
+ name: turbo_tests2
218
+ requirement: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '3.2'
223
+ - - ">="
224
+ - !ruby/object:Gem::Version
225
+ version: 3.2.4
226
+ type: :development
227
+ prerelease: false
228
+ version_requirements: !ruby/object:Gem::Requirement
229
+ requirements:
230
+ - - "~>"
231
+ - !ruby/object:Gem::Version
232
+ version: '3.2'
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: 3.2.4
236
+ - !ruby/object:Gem::Dependency
237
+ name: ruby-progressbar
238
+ requirement: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - "~>"
241
+ - !ruby/object:Gem::Version
242
+ version: '1.13'
243
+ type: :development
244
+ prerelease: false
245
+ version_requirements: !ruby/object:Gem::Requirement
246
+ requirements:
247
+ - - "~>"
248
+ - !ruby/object:Gem::Version
249
+ version: '1.13'
250
+ - !ruby/object:Gem::Dependency
251
+ name: stone_checksums
252
+ requirement: !ruby/object:Gem::Requirement
253
+ requirements:
254
+ - - "~>"
255
+ - !ruby/object:Gem::Version
256
+ version: '1.0'
257
+ - - ">="
258
+ - !ruby/object:Gem::Version
259
+ version: 1.0.8
260
+ type: :development
261
+ prerelease: false
262
+ version_requirements: !ruby/object:Gem::Requirement
263
+ requirements:
264
+ - - "~>"
265
+ - !ruby/object:Gem::Version
266
+ version: '1.0'
267
+ - - ">="
268
+ - !ruby/object:Gem::Version
269
+ version: 1.0.8
270
+ - !ruby/object:Gem::Dependency
271
+ name: gitmoji-regex
272
+ requirement: !ruby/object:Gem::Requirement
273
+ requirements:
274
+ - - "~>"
275
+ - !ruby/object:Gem::Version
276
+ version: '2.0'
277
+ - - ">="
278
+ - !ruby/object:Gem::Version
279
+ version: 2.0.11
280
+ type: :development
281
+ prerelease: false
282
+ version_requirements: !ruby/object:Gem::Requirement
283
+ requirements:
284
+ - - "~>"
285
+ - !ruby/object:Gem::Version
286
+ version: '2.0'
287
+ - - ">="
288
+ - !ruby/object:Gem::Version
289
+ version: 2.0.11
290
+ description: "☯️ Git-specific merge3 contracts and conflict classification over ast-merge
291
+ primitives."
292
+ email:
293
+ - floss@galtzo.com
294
+ executables: []
295
+ extensions: []
296
+ extra_rdoc_files: []
297
+ files:
298
+ - LICENSE.md
299
+ - README.md
300
+ - lib/ast-merge-git.rb
301
+ - lib/ast/merge/git.rb
302
+ - lib/ast/merge/git/version.rb
303
+ - sig/ast/merge/git.rbs
304
+ homepage: https://github.com/structuredmerge/structuredmerge-ruby
305
+ licenses:
306
+ - AGPL-3.0-only
307
+ - PolyForm-Small-Business-1.0.0
308
+ metadata:
309
+ homepage_uri: https://structuredmerge.org
310
+ source_code_uri: https://github.com/structuredmerge/structuredmerge-ruby/tree/v7.1.1
311
+ changelog_uri: https://github.com/structuredmerge/structuredmerge-ruby/blob/v7.1.1/CHANGELOG.md
312
+ bug_tracker_uri: https://github.com/structuredmerge/structuredmerge-ruby/issues
313
+ documentation_uri: https://www.rubydoc.info/gems/ast-merge-git/7.1.1
314
+ funding_uri: https://github.com/sponsors/pboling
315
+ wiki_uri: https://github.com/structuredmerge/structuredmerge-ruby/wiki
316
+ news_uri: https://www.railsbling.com/tags/ast-merge-git
317
+ discord_uri: https://discord.gg/3qme4XHNKN
318
+ mailing_list_uri: https://www.rubyforum.org/tag/structuredmerge
319
+ rubygems_mfa_required: 'true'
320
+ rdoc_options:
321
+ - "--title"
322
+ - ast-merge-git - ☯️ Three-way git merge semantics for StructuredMerge
323
+ - "--main"
324
+ - README.md
325
+ - "--exclude"
326
+ - "^sig/"
327
+ - "--line-numbers"
328
+ - "--inline-source"
329
+ - "--quiet"
330
+ require_paths:
331
+ - lib
332
+ required_ruby_version: !ruby/object:Gem::Requirement
333
+ requirements:
334
+ - - ">="
335
+ - !ruby/object:Gem::Version
336
+ version: 4.0.0
337
+ required_rubygems_version: !ruby/object:Gem::Requirement
338
+ requirements:
339
+ - - ">="
340
+ - !ruby/object:Gem::Version
341
+ version: '0'
342
+ requirements: []
343
+ rubygems_version: 4.0.17
344
+ specification_version: 4
345
+ summary: "☯️ Three-way git merge semantics for StructuredMerge"
346
+ test_files: []
metadata.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ Z�˴�
2
+ ���"�t�d�4/�F�Ek�e#4�05�*����t8�ۍ����� ʢ��������K �!2R�k�i�}�vH��@���hCKX\ !��'��Ԫ~�9�<<B��Snb�Y��G�B�rȒ*�-�ެ�-�)gܧ�n�d����B��|}�SMw��Jg�d�ܽ��� �(�u��:�)���z&�b4��H��;>�B��,�Å1,�\��A��{���,4��"�)֐����U���p�hP������g��XvQ���r��1%RU��Rx���6Y<oB� �m-�Y�nK��vDg~^�l�R�{���T5�������[����'�|�乸��s���&�,Ѹ2��aaOn3�_����'(T��3