plain-merge 7.1.1 → 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: 5da79765d212fbd8c3734697f1bf0879be015dfee2c126b2784356b75badf72f
4
- data.tar.gz: '0218ac56ff565a835d03b85cd48095a463ac415eabb1ffcf9a88ca2600fba806'
3
+ metadata.gz: eb21dc58d45117871ad2b96d9adaff4775cfdc8e5267e5742a3cf71d09b1ea2c
4
+ data.tar.gz: 896051c7f24220265b0086912e9d91f77ab28e94914720b1b4e795016029d981
5
5
  SHA512:
6
- metadata.gz: 84e346b9c77e9c93eb93e38a10d0e38bf2fee19efcab787f261f321f7efecf67f2cb918f46a75bcf060ee5e5cb3ac1027476c442397fd988b61696f725e68df7
7
- data.tar.gz: 426d63fd97bbc694cd05b8c3e9a2264389a9b8516db32377ea946569616adb3b95409621b995d371ae84a94fb39b2658393420d316ba2b5f26ef87161e5cee73
6
+ metadata.gz: bb3a96716022df3e9ce9ed6a63638a1c913ec0de744bc74b3c70625a2774a57cac56d17fd9fb766be3528512fa5eed7082f0640561b083718155c722b420eb05
7
+ data.tar.gz: a06b47194805436a93962350698b6f898a9f66cab476fb8929c2c7eedef2a6d1b0d3b4da3142f3cb25bc8424159041fd54fbceddcaf3c410343753e80c0a9fdf
checksums.yaml.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -51,7 +51,7 @@ callers can enter plain text analysis through
51
51
 
52
52
  ### Compatibility
53
53
 
54
- Compatible with MRI Ruby 4.0.0+, and concordant releases of JRuby, and TruffleRuby.
54
+ Compatible with MRI Ruby 4.0.0+, JRuby, and TruffleRuby.
55
55
  CI workflows and Appraisals are generated for MRI Ruby 4.0.0+.
56
56
  This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
57
57
  may be higher than the gem's runtime compatibility floor when legacy Rubies are
@@ -118,20 +118,12 @@ See [SECURITY.md][🔐security].
118
118
  ## 🤝 Contributing
119
119
 
120
120
  If you need some ideas of where to help, you could work on adding more code coverage,
121
- or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues] or [PRs][🤝gh-pulls],
122
- or use the gem and think about how it could be better.
121
+ check [issues][🤝gh-issues] or [PRs][🤝gh-pulls], or use the gem and think about how it could be better.
123
122
 
124
123
  We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
125
124
 
126
125
  See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
127
126
 
128
- ### Code Coverage
129
-
130
- <details markdown="1">
131
- <summary>Coverage service badges</summary>
132
-
133
- </details>
134
-
135
127
  ## 📌 Versioning
136
128
 
137
129
  This library follows [![Semantic Versioning 2.0.0][📌semver-img]][📌semver] for its public API where practical.
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plain
4
+ module Merge
5
+ # Coarse whole-document provider for unstructured plain text.
6
+ # rubocop:disable Metrics/ClassLength, Metrics/MethodLength, Metrics/ParameterLists -- provider operations and envelopes form one cohesive boundary
7
+ class Provider
8
+ def provider_id = 'ruby.text'
9
+ def family = 'text'
10
+
11
+ def capabilities
12
+ {
13
+ operations: Ast::Merge::ProviderContract::OPERATIONS,
14
+ dialects: %i[text],
15
+ backends: [Plain::Merge::BACKEND_REFERENCE.id.to_sym],
16
+ profiles: %i[coarse_document],
17
+ role: :workflow,
18
+ source_preservation: %i[exact_source whole_document_conflict]
19
+ }.freeze
20
+ end
21
+
22
+ def analyze(request)
23
+ result(:analyze, request, analysis: Plain::Merge.analyze_text(request.fetch(:source)))
24
+ end
25
+
26
+ def diff2(request)
27
+ before = request.fetch(:before_source)
28
+ after = request.fetch(:after_source)
29
+ changes = before == after ? [] : [classification(before, before, after)]
30
+ result(:diff2, request, changes: changes, diff: { before: before, after: after, changes: changes })
31
+ end
32
+
33
+ def merge2(request)
34
+ merged = Plain::Merge.merge_text(request.fetch(:incoming_source), request.fetch(:current_source))
35
+ result(
36
+ :merge2,
37
+ request,
38
+ output: merged.fetch(:output),
39
+ render_report: { strategy: :normalized_block_merge },
40
+ verification: { output_rendered: true }
41
+ )
42
+ end
43
+
44
+ def merge3(request)
45
+ base = request.fetch(:base_source)
46
+ ours = request.fetch(:ours_source)
47
+ theirs = request.fetch(:theirs_source)
48
+ return exact_merge3(request, :ours, ours, base, ours, theirs) if ours == theirs || base == theirs
49
+ return exact_merge3(request, :theirs, theirs, base, ours, theirs) if base == ours
50
+
51
+ conflicted_merge3(request, base, ours, theirs)
52
+ end
53
+
54
+ private
55
+
56
+ def exact_merge3(request, role, output, base, ours, theirs)
57
+ rendered = render(request, [source_fragment(role, output)])
58
+ result(
59
+ :merge3,
60
+ request,
61
+ output: rendered.content,
62
+ changes: [classification(base, ours, theirs)],
63
+ render_report: render_report(rendered, :exact_revision),
64
+ verification: { base_participated: true, output_reparsed: true, semantic_match: rendered.content == output }
65
+ )
66
+ end
67
+
68
+ def conflicted_merge3(request, base, ours, theirs)
69
+ conflict = {
70
+ conflict_id: 'text-conflict-root',
71
+ category: :edit_edit,
72
+ path: '',
73
+ change_classification: classification(base, ours, theirs)
74
+ }
75
+ rendered = render(
76
+ request,
77
+ [
78
+ Ast::Merge::SourceRender::ConflictFragment.new(
79
+ conflict_id: conflict.fetch(:conflict_id),
80
+ base: [conflict_side(:base, base)],
81
+ ours: [conflict_side(:ours, ours)],
82
+ theirs: [conflict_side(:theirs, theirs)],
83
+ labels: request.fetch(:labels, {}),
84
+ marker_size: request.fetch(:conflict_marker_size, 7),
85
+ metadata: { path: '', category: :edit_edit }
86
+ )
87
+ ]
88
+ )
89
+ failure(
90
+ :merge3,
91
+ request,
92
+ category: :merge_conflict,
93
+ message: 'Plain text changed independently on both sides.',
94
+ changes: [conflict.fetch(:change_classification)],
95
+ conflicts: [conflict],
96
+ conflicted_output: rendered.content,
97
+ render_report: render_report(rendered, :whole_document_conflict),
98
+ verification: { base_participated: true }
99
+ )
100
+ end
101
+
102
+ def classification(base, ours, theirs)
103
+ {
104
+ path: '',
105
+ ours: base == ours ? :unchanged : :edited,
106
+ theirs: base == theirs ? :unchanged : :edited
107
+ }.freeze
108
+ end
109
+
110
+ def render(request, fragments)
111
+ Ast::Merge::SourceRender::Renderer.new.render(
112
+ Ast::Merge::SourceRender::Plan.new(
113
+ sources: {
114
+ base: request[:base_source].to_s,
115
+ ours: request[:ours_source].to_s,
116
+ theirs: request[:theirs_source].to_s
117
+ },
118
+ fragments: fragments,
119
+ metadata: { provider_id: provider_id }
120
+ )
121
+ )
122
+ end
123
+
124
+ def source_fragment(role, source)
125
+ if source.empty?
126
+ return Ast::Merge::SourceRender::SynthesizedFragment.new(
127
+ content: '',
128
+ reason: :exact_empty_source,
129
+ producer: provider_id,
130
+ metadata: { source_role: role }
131
+ )
132
+ end
133
+
134
+ Ast::Merge::SourceRender::SourceFragment.new(
135
+ revision: role,
136
+ start_line: 1,
137
+ end_line: [source.lines.length, 1].max,
138
+ metadata: { source_role: role }
139
+ )
140
+ end
141
+
142
+ def conflict_side(role, source)
143
+ return source_fragment(role, source) if !source.empty? && source.end_with?("\n")
144
+
145
+ Ast::Merge::SourceRender::SynthesizedFragment.new(
146
+ content: source.empty? ? '' : "#{source}\n",
147
+ reason: :conflict_line_boundary,
148
+ producer: provider_id,
149
+ metadata: { source_role: role, copied_source: true }
150
+ )
151
+ end
152
+
153
+ def render_report(rendered, strategy)
154
+ {
155
+ strategy: strategy,
156
+ line_records: rendered.line_records,
157
+ synthesized_fragments: rendered.synthesized_fragments,
158
+ conflicts: rendered.conflicts,
159
+ verification_input: rendered.verification_input
160
+ }
161
+ end
162
+
163
+ def result(operation, request, changes: [], render_report: {}, verification: {}, **payload)
164
+ Ast::Merge::ProviderResult.build(
165
+ operation: operation,
166
+ success: true,
167
+ envelope: envelope(request, changes: changes, render_report: render_report, verification: verification),
168
+ **payload
169
+ )
170
+ end
171
+
172
+ def failure(operation, request, category:, message:, changes: [], conflicts: [], render_report: {},
173
+ verification: {}, **payload)
174
+ Ast::Merge::ProviderResult.build(
175
+ operation: operation,
176
+ success: false,
177
+ envelope: envelope(
178
+ request,
179
+ changes: changes,
180
+ conflicts: conflicts,
181
+ diagnostics: [{ category: category, severity: :error, message: message, blocking: true }],
182
+ render_report: render_report,
183
+ verification: verification
184
+ ),
185
+ **payload
186
+ )
187
+ end
188
+
189
+ def envelope(request, **fields)
190
+ {
191
+ provider: {
192
+ provider_id: provider_id,
193
+ family: family,
194
+ dialect: request[:dialect] || :text,
195
+ backend: request[:backend],
196
+ package: Plain::Merge::PACKAGE_NAME,
197
+ package_version: Plain::Merge::Version::VERSION
198
+ },
199
+ profile: { profile_id: request[:profile_id] || :coarse_document }
200
+ }.merge(fields)
201
+ end
202
+ end
203
+ # rubocop:enable Metrics/ClassLength, Metrics/MethodLength, Metrics/ParameterLists
204
+ end
205
+ end
@@ -5,7 +5,7 @@ module Plain
5
5
  # Version namespace for this gem.
6
6
  module Version
7
7
  # Current gem version.
8
- VERSION = '7.1.1'
8
+ VERSION = '7.1.3'
9
9
  end
10
10
  # Current gem version exposed at the traditional constant location.
11
11
  VERSION = Version::VERSION # Traditional Constant Location
data/lib/plain/merge.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'ast/merge'
3
4
  require 'tree_haver'
4
5
  require_relative 'merge/version'
5
6
 
@@ -13,6 +14,8 @@ module Plain
13
14
  position: 0.15
14
15
  }.freeze
15
16
 
17
+ autoload :Provider, 'plain/merge/provider'
18
+
16
19
  module_function
17
20
 
18
21
  def text_feature_profile
@@ -23,6 +26,14 @@ module Plain
23
26
  }
24
27
  end
25
28
 
29
+ def merge_provider
30
+ @merge_provider ||= Provider.new
31
+ end
32
+
33
+ def register_provider!(replace: false)
34
+ Ast::Merge.register_provider(merge_provider, replace: replace)
35
+ end
36
+
26
37
  def text_parse_request(source)
27
38
  TreeHaver::ParserRequest.new(source: source, language: 'text')
28
39
  end
@@ -263,3 +274,4 @@ end
263
274
 
264
275
  require_relative 'merge/backend'
265
276
  Plain::Merge.register_backend!
277
+ Plain::Merge.register_provider!
data/sig/plain/merge.rbs CHANGED
@@ -1,5 +1,18 @@
1
1
  module Plain
2
2
  module Merge
3
+ class Provider
4
+ def provider_id: () -> String
5
+ def family: () -> String
6
+ def capabilities: () -> Ast::Merge::provider_capabilities
7
+ def analyze: (Ast::Merge::provider_request request) -> Ast::Merge::provider_result
8
+ def diff2: (Ast::Merge::provider_request request) -> Ast::Merge::provider_result
9
+ def merge2: (Ast::Merge::provider_request request) -> Ast::Merge::provider_result
10
+ def merge3: (Ast::Merge::provider_request request) -> Ast::Merge::provider_result
11
+ end
12
+
13
+ def self.merge_provider: () -> Provider
14
+ def self.register_provider!: (?replace: bool) -> Ast::Merge::_MergeProvider
15
+
3
16
  module Version
4
17
  VERSION: String
5
18
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plain-merge
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.1
4
+ version: 7.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -43,28 +43,28 @@ dependencies:
43
43
  requirements:
44
44
  - - '='
45
45
  - !ruby/object:Gem::Version
46
- version: 7.1.1
46
+ version: 7.1.3
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - '='
52
52
  - !ruby/object:Gem::Version
53
- version: 7.1.1
53
+ version: 7.1.3
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: tree_haver
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - '='
59
59
  - !ruby/object:Gem::Version
60
- version: 7.1.1
60
+ version: 7.1.3
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - '='
66
66
  - !ruby/object:Gem::Version
67
- version: 7.1.1
67
+ version: 7.1.3
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: version_gem
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -91,20 +91,20 @@ dependencies:
91
91
  requirements:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
- version: '2.5'
94
+ version: '3.0'
95
95
  - - ">="
96
96
  - !ruby/object:Gem::Version
97
- version: 2.5.17
97
+ version: 3.0.0
98
98
  type: :development
99
99
  prerelease: false
100
100
  version_requirements: !ruby/object:Gem::Requirement
101
101
  requirements:
102
102
  - - "~>"
103
103
  - !ruby/object:Gem::Version
104
- version: '2.5'
104
+ version: '3.0'
105
105
  - - ">="
106
106
  - !ruby/object:Gem::Version
107
- version: 2.5.17
107
+ version: 3.0.0
108
108
  - !ruby/object:Gem::Dependency
109
109
  name: bundler-audit
110
110
  requirement: !ruby/object:Gem::Requirement
@@ -182,7 +182,7 @@ dependencies:
182
182
  version: '3.2'
183
183
  - - ">="
184
184
  - !ruby/object:Gem::Version
185
- version: 3.2.0
185
+ version: 3.2.2
186
186
  type: :development
187
187
  prerelease: false
188
188
  version_requirements: !ruby/object:Gem::Requirement
@@ -192,7 +192,7 @@ dependencies:
192
192
  version: '3.2'
193
193
  - - ">="
194
194
  - !ruby/object:Gem::Version
195
- version: 3.2.0
195
+ version: 3.2.2
196
196
  - !ruby/object:Gem::Dependency
197
197
  name: kettle-test
198
198
  requirement: !ruby/object:Gem::Requirement
@@ -222,7 +222,7 @@ dependencies:
222
222
  version: '3.2'
223
223
  - - ">="
224
224
  - !ruby/object:Gem::Version
225
- version: 3.2.4
225
+ version: 3.2.5
226
226
  type: :development
227
227
  prerelease: false
228
228
  version_requirements: !ruby/object:Gem::Requirement
@@ -232,7 +232,7 @@ dependencies:
232
232
  version: '3.2'
233
233
  - - ">="
234
234
  - !ruby/object:Gem::Version
235
- version: 3.2.4
235
+ version: 3.2.5
236
236
  - !ruby/object:Gem::Dependency
237
237
  name: ruby-progressbar
238
238
  requirement: !ruby/object:Gem::Requirement
@@ -300,6 +300,7 @@ files:
300
300
  - lib/plain-merge.rb
301
301
  - lib/plain/merge.rb
302
302
  - lib/plain/merge/backend.rb
303
+ - lib/plain/merge/provider.rb
303
304
  - lib/plain/merge/version.rb
304
305
  - sig/plain/merge.rbs
305
306
  homepage: https://github.com/structuredmerge/structuredmerge-ruby
@@ -308,10 +309,10 @@ licenses:
308
309
  - PolyForm-Small-Business-1.0.0
309
310
  metadata:
310
311
  homepage_uri: https://structuredmerge.org
311
- source_code_uri: https://github.com/structuredmerge/structuredmerge-ruby/tree/v7.1.1
312
- changelog_uri: https://github.com/structuredmerge/structuredmerge-ruby/blob/v7.1.1/CHANGELOG.md
312
+ source_code_uri: https://github.com/structuredmerge/structuredmerge-ruby/tree/v7.1.3
313
+ changelog_uri: https://github.com/structuredmerge/structuredmerge-ruby/blob/v7.1.3/CHANGELOG.md
313
314
  bug_tracker_uri: https://github.com/structuredmerge/structuredmerge-ruby/issues
314
- documentation_uri: https://www.rubydoc.info/gems/plain-merge/7.1.1
315
+ documentation_uri: https://www.rubydoc.info/gems/plain-merge/7.1.3
315
316
  funding_uri: https://github.com/sponsors/pboling
316
317
  wiki_uri: https://github.com/structuredmerge/structuredmerge-ruby/wiki
317
318
  news_uri: https://www.railsbling.com/tags/plain-merge
metadata.gz.sig CHANGED
Binary file