bash-merge 7.1.3 → 7.1.4

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: 63912e4ed1e5c589b747fe8c4bff43704efb8011c051c738c140a3a9b8372610
4
- data.tar.gz: c37449f1e387c5beeb1f4bcd062a5c748ec2cbeae76c1b3dd8e1559c8f3f8404
3
+ metadata.gz: 3e3f73ff82048635caccf19c960791ce05565f83e3c393b6dc175d4d2d16b417
4
+ data.tar.gz: 96404acb74336004facfe0222183882909c23bc1de2c5ec827769c769de4b6f8
5
5
  SHA512:
6
- metadata.gz: 05c63cd77818e9091f81afdc9f33212c0c66f40b266f4d9a57f7426ca4ef9c39b4a07da65d599f06f8bd8987ac12695cfbf05158d26dec7bf500243ade3a9e5b
7
- data.tar.gz: ca5966709c53a0ebac627228ebf76b3bdc1541efef4cc6f40399cef04c71870b0f5fd3c0d8a325fc46a428388851d78c52e1cd919c7c82b6f49d0f25d42b0221
6
+ metadata.gz: 1abeafbfc3c7485a49ca9f4f45853f888f95040dd895b7df7fea1f6584fb08565711abeb41dbd4e4abae9d0b13b6166fb2f973fd6ca531838d6e9865bc1b63d9
7
+ data.tar.gz: 2eab528d0568ae00321490ad534bf41ac3bcbd2aab46355be98b034f6238a869648a03f9c89f5d81990706acec19c12fe3f15cacd29a57bb6292058f60144e18
checksums.yaml.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -403,7 +403,7 @@ If none of the available licenses suit your use case, please [contact us](mailto
403
403
  [📌gitmoji]: https://gitmoji.dev
404
404
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
405
405
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
406
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.810-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
406
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-1.305-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
407
407
  [🔐security]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/SECURITY.md
408
408
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
409
409
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -5,6 +5,7 @@ require 'json'
5
5
  require 'ast/merge/source_render'
6
6
  require_relative 'node_wrapper'
7
7
  require_relative 'file_analysis'
8
+ require_relative 'test_harness_identity'
8
9
 
9
10
  module Bash
10
11
  # Registration and source-preserving workflow implementation for Bash.
@@ -22,8 +23,9 @@ module Bash
22
23
  end
23
24
 
24
25
  # Base-aware, source-preserving provider for native top-level Bash owners.
25
- # Functions and assignments have stable AST identities. Every other
26
- # top-level form must remain identical across all revisions in a composite.
26
+ # Functions, assignments, and literal-title test_expect_success calls have
27
+ # stable AST identities. Every other top-level form must remain identical
28
+ # across all revisions in a composite.
27
29
  # rubocop:disable Metrics/AbcSize, Metrics/ClassLength, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/ParameterLists, Metrics/PerceivedComplexity -- provider decisions, source plans, and verification form one boundary
28
30
  class Provider
29
31
  DEFAULT_PROFILE = :source_preserving
@@ -42,7 +44,7 @@ module Bash
42
44
  backends: [TREE_SITTER_BACKEND.id.to_sym],
43
45
  profiles: [DEFAULT_PROFILE],
44
46
  role: :workflow,
45
- ast_ownership: :stable_functions_and_assignments,
47
+ ast_ownership: :stable_functions_assignments_and_literal_test_titles,
46
48
  source_preservation: %i[exact_source declaration_fragments line_provenance reparse semantic_verification]
47
49
  }.freeze
48
50
  end
@@ -103,6 +105,9 @@ module Bash
103
105
  ownership_failure = unstable_ownership_failure(request, documents)
104
106
  return ownership_failure if ownership_failure
105
107
 
108
+ ownership_failure = test_harness_ownership_failure(request, documents)
109
+ return ownership_failure if ownership_failure
110
+
106
111
  decision = decide(documents, include_unmanaged_conflict: true)
107
112
  return render_conflicts(request, documents, decision) unless decision.conflicts.empty?
108
113
 
@@ -212,6 +217,8 @@ module Bash
212
217
  elsif wrapper.variable_assignment?
213
218
  name = wrapper.variable_name
214
219
  name && [:variable_assignment, name]
220
+ elsif (identity = TestHarnessIdentity.for(wrapper))
221
+ [:test_harness_call, *identity]
215
222
  else
216
223
  wrapper.signature
217
224
  end
@@ -396,7 +403,57 @@ module Bash
396
403
  end
397
404
 
398
405
  def stable_signature?(signature)
399
- %i[function variable_assignment].include?(signature.first)
406
+ %i[function variable_assignment test_harness_call].include?(signature.first)
407
+ end
408
+
409
+ def test_harness_ownership_failure(request, documents)
410
+ sequences = documents.transform_values do |document|
411
+ document.owners.filter_map do |owner|
412
+ owner.id if owner.signature.first == :test_harness_call
413
+ end
414
+ end
415
+ base = sequences.fetch(:base)
416
+ invalid_role = %i[ours theirs].find do |role|
417
+ sequence = sequences.fetch(role)
418
+ sequence.length < base.length || sequence.first(base.length) != base
419
+ end
420
+ changed_role = %i[ours theirs].find { |role| sequences.fetch(role) != base }
421
+ return unless invalid_role || changed_role
422
+
423
+ reason = if invalid_role
424
+ :non_append_only_test_harness_change
425
+ else
426
+ :test_harness_addition_requires_ordered_rendering
427
+ end
428
+ source_role = invalid_role || changed_role
429
+
430
+ signature_digest = Digest::SHA256.hexdigest(JSON.generate(Ast::Merge.json_ready(sequences)))
431
+ conflict = {
432
+ conflict_id: "bash-test-ownership-#{signature_digest[0, 16]}",
433
+ category: :unproven_ast_ownership,
434
+ path: '<test_expect_success-sequence>',
435
+ owner_id: nil,
436
+ source_role: source_role,
437
+ identities: sequences,
438
+ reason: reason
439
+ }.freeze
440
+ decision = Decision.new(changes: [], conflicts: [conflict], choices: {})
441
+ rendered = render_plan(request, [whole_document_conflict(request, decision)])
442
+ failure(
443
+ :merge3,
444
+ request,
445
+ category: :unproven_ast_ownership,
446
+ message: 'Literal-title test_expect_success membership changes require ordered insertion rendering.',
447
+ conflicts: [conflict],
448
+ conflicted_output: rendered.content,
449
+ render_report: render_report(rendered, :full_file_conflict),
450
+ verification: { base_participated: true },
451
+ fallbacks: [{
452
+ from: :test_harness_ast_ownership,
453
+ to: :full_file_conflict,
454
+ reason: reason
455
+ }]
456
+ )
400
457
  end
401
458
 
402
459
  def side_change(base, side)
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bash
4
+ module Merge
5
+ # Extracts bounded AST identities for Git-style shell test harness calls.
6
+ class TestHarnessIdentity
7
+ class << self
8
+ def for(wrapper)
9
+ return unless wrapper.command? && wrapper.command_name == 'test_expect_success'
10
+
11
+ identity = literal_identity(wrapper)
12
+ [:test_expect_success, *identity] if identity
13
+ end
14
+
15
+ private
16
+
17
+ def literal_identity(wrapper)
18
+ arguments = command_argument_nodes(wrapper.node)
19
+ return [source_for(wrapper, arguments.first)] if simple_literal_title?(arguments)
20
+ return unless qualified_literal_title?(arguments)
21
+
22
+ arguments.first(2).map { |argument| source_for(wrapper, argument) }
23
+ end
24
+
25
+ def command_argument_nodes(node)
26
+ children = node.children.select(&:named?)
27
+ command_index = children.index { |child| %w[word command_name].include?(child.type.to_s) }
28
+ return [] unless command_index
29
+
30
+ arguments = children.drop(command_index + 1)
31
+ arguments.any? { |child| child.type.to_s.include?('redirect') } ? [] : arguments
32
+ end
33
+
34
+ def simple_literal_title?(arguments)
35
+ arguments.length == 2 && literal_title?(arguments.first)
36
+ end
37
+
38
+ def qualified_literal_title?(arguments)
39
+ arguments.length == 3 &&
40
+ literal_prerequisite?(arguments[0]) &&
41
+ literal_title?(arguments[1])
42
+ end
43
+
44
+ def literal_prerequisite?(argument)
45
+ argument.type.to_s == 'word' && argument.children.none?(&:named?)
46
+ end
47
+
48
+ def literal_title?(argument)
49
+ return true if argument.type.to_s == 'raw_string'
50
+ return false unless argument.type.to_s == 'string'
51
+
52
+ argument.children.select(&:named?).all? { |child| child.type.to_s == 'string_content' }
53
+ end
54
+
55
+ def source_for(wrapper, node)
56
+ start_offset = node.start_byte - wrapper.start_byte
57
+ end_offset = node.end_byte - wrapper.start_byte
58
+ wrapper.source_text.byteslice(start_offset...end_offset).to_s
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -5,7 +5,7 @@ module Bash
5
5
  # Version namespace for this gem.
6
6
  module Version
7
7
  # Current gem version.
8
- VERSION = '7.1.3'
8
+ VERSION = '7.1.4'
9
9
  end
10
10
  # Current gem version exposed at the traditional constant location.
11
11
  VERSION = Version::VERSION # Traditional Constant Location
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bash-merge
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.3
4
+ version: 7.1.4
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.3
46
+ version: 7.1.4
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.3
53
+ version: 7.1.4
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.3
60
+ version: 7.1.4
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.3
67
+ version: 7.1.4
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: version_gem
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -94,7 +94,7 @@ dependencies:
94
94
  version: '3.0'
95
95
  - - ">="
96
96
  - !ruby/object:Gem::Version
97
- version: 3.0.0
97
+ version: 3.0.7
98
98
  type: :development
99
99
  prerelease: false
100
100
  version_requirements: !ruby/object:Gem::Requirement
@@ -104,7 +104,7 @@ dependencies:
104
104
  version: '3.0'
105
105
  - - ">="
106
106
  - !ruby/object:Gem::Version
107
- version: 3.0.0
107
+ version: 3.0.7
108
108
  - !ruby/object:Gem::Dependency
109
109
  name: bundler-audit
110
110
  requirement: !ruby/object:Gem::Requirement
@@ -202,7 +202,7 @@ dependencies:
202
202
  version: '2.0'
203
203
  - - ">="
204
204
  - !ruby/object:Gem::Version
205
- version: 2.0.19
205
+ version: 2.0.20
206
206
  type: :development
207
207
  prerelease: false
208
208
  version_requirements: !ruby/object:Gem::Requirement
@@ -212,7 +212,7 @@ dependencies:
212
212
  version: '2.0'
213
213
  - - ">="
214
214
  - !ruby/object:Gem::Version
215
- version: 2.0.19
215
+ version: 2.0.20
216
216
  - !ruby/object:Gem::Dependency
217
217
  name: turbo_tests2
218
218
  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.5
225
+ version: 3.2.6
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.5
235
+ version: 3.2.6
236
236
  - !ruby/object:Gem::Dependency
237
237
  name: ruby-progressbar
238
238
  requirement: !ruby/object:Gem::Requirement
@@ -276,7 +276,7 @@ dependencies:
276
276
  version: '2.0'
277
277
  - - ">="
278
278
  - !ruby/object:Gem::Version
279
- version: 2.0.11
279
+ version: 2.0.12
280
280
  type: :development
281
281
  prerelease: false
282
282
  version_requirements: !ruby/object:Gem::Requirement
@@ -286,7 +286,7 @@ dependencies:
286
286
  version: '2.0'
287
287
  - - ">="
288
288
  - !ruby/object:Gem::Version
289
- version: 2.0.11
289
+ version: 2.0.12
290
290
  description: "☯️ Bash statement, comment, freeze-block, and template merge behavior
291
291
  for Structured Merge."
292
292
  email:
@@ -308,6 +308,7 @@ files:
308
308
  - lib/bash/merge/node_wrapper.rb
309
309
  - lib/bash/merge/provider.rb
310
310
  - lib/bash/merge/smart_merger.rb
311
+ - lib/bash/merge/test_harness_identity.rb
311
312
  - lib/bash/merge/version.rb
312
313
  - sig/bash/merge.rbs
313
314
  homepage: https://github.com/structuredmerge/structuredmerge-ruby
@@ -316,10 +317,10 @@ licenses:
316
317
  - PolyForm-Small-Business-1.0.0
317
318
  metadata:
318
319
  homepage_uri: https://structuredmerge.org
319
- source_code_uri: https://github.com/structuredmerge/structuredmerge-ruby/tree/v7.1.3
320
- changelog_uri: https://github.com/structuredmerge/structuredmerge-ruby/blob/v7.1.3/CHANGELOG.md
320
+ source_code_uri: https://github.com/structuredmerge/structuredmerge-ruby/tree/v7.1.4
321
+ changelog_uri: https://github.com/structuredmerge/structuredmerge-ruby/blob/v7.1.4/CHANGELOG.md
321
322
  bug_tracker_uri: https://github.com/structuredmerge/structuredmerge-ruby/issues
322
- documentation_uri: https://www.rubydoc.info/gems/bash-merge/7.1.3
323
+ documentation_uri: https://www.rubydoc.info/gems/bash-merge/7.1.4
323
324
  funding_uri: https://github.com/sponsors/pboling
324
325
  wiki_uri: https://github.com/structuredmerge/structuredmerge-ruby/wiki
325
326
  news_uri: https://www.railsbling.com/tags/bash-merge
metadata.gz.sig CHANGED
Binary file