ast-merge 4.0.0 → 4.0.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +43 -1
- data/lib/ast/merge/ast_node.rb +15 -19
- data/lib/ast/merge/diff_mapper_base.rb +1 -1
- data/lib/ast/merge/rspec/dependency_tags.rb +41 -182
- data/lib/ast/merge/rspec/merge_gem_registry.rb +382 -0
- data/lib/ast/merge/version.rb +1 -1
- data/lib/ast/merge.rb +3 -0
- data.tar.gz.sig +0 -0
- metadata +7 -6
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e6af6467980a8e2076bd454a35bea42e18064fed0651704754f459353a85087a
|
|
4
|
+
data.tar.gz: 1d89bad2aa237d11aafd957f68391d8ca83248cc0f7946bad54e788cc1fa05c2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a45b949a5b6b835ba26d0422eb855daa9a62e513131bf06627abe8b68dba2daae28dd835f51fce43758c36f652fb44851885adcec3f82a64519bc2baed6f77f9
|
|
7
|
+
data.tar.gz: c2a7c05cedc23b3552f5eaef980cc890cf034060efe82f51f0c7acc98cba5b5df3bc2441a96bcde188c48391baebe5474dd76f735e5a2dbda053ff85b07a6748
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,46 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [4.0.1] - 2026-01-11
|
|
34
|
+
|
|
35
|
+
- TAG: [v4.0.1][4.0.1t]
|
|
36
|
+
- COVERAGE: 96.45% -- 2553/2647 lines in 51 files
|
|
37
|
+
- BRANCH COVERAGE: 87.41% -- 812/929 branches in 51 files
|
|
38
|
+
- 98.80% documented
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- **`Ast::Merge::RSpec::MergeGemRegistry`** - Fully dynamic merge gem registration for RSpec dependency tags
|
|
43
|
+
- `register(tag_name, require_path:, merger_class:, test_source:, category:)` - Register a merge gem
|
|
44
|
+
- `available?(tag_name)` - Check if a merge gem is available and functional
|
|
45
|
+
- `registered_gems` - Get all registered gem tag names
|
|
46
|
+
- `gems_by_category(category)` - Filter gems by category (:markdown, :data, :code, :config, :other)
|
|
47
|
+
- `summary` - Get availability status of all registered gems
|
|
48
|
+
- Automatically defines `*_available?` methods on `DependencyTags` at registration time
|
|
49
|
+
- External merge gems can now get full RSpec tag support without modifying ast-merge
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- Upgrade to [tree_haver v5.0.1](https://github.com/kettle-rb/tree_haver/releases/tag/v5.0.1)
|
|
54
|
+
- **`Ast::Merge::AstNode` now inherits from `TreeHaver::Base::Node`**
|
|
55
|
+
- Ensures synthetic nodes stay in sync with the canonical Node API
|
|
56
|
+
- Inherits `Comparable`, `Enumerable` from base class
|
|
57
|
+
- Retains all existing methods and behavior (Point, Location, signature, etc.)
|
|
58
|
+
- Constructor calls `super(self, source: source)` to properly initialize base class
|
|
59
|
+
- **RSpec Dependency Tags refactored to use MergeGemRegistry**
|
|
60
|
+
- Removed hardcoded merge gem availability checks
|
|
61
|
+
- Removed `MERGE_GEM_TEST_SOURCES` constant
|
|
62
|
+
- `*_available?` methods are now defined dynamically when gems register
|
|
63
|
+
- `any_markdown_merge_available?` now queries registry by category
|
|
64
|
+
- RSpec exclusion filters are configured dynamically from registry
|
|
65
|
+
- `Ast::Merge::Testing::TestableNode` now delegates to `TreeHaver::RSpec::TestableNode`
|
|
66
|
+
- The TestableNode implementation has been moved to tree_haver for sharing across all merge gems
|
|
67
|
+
- `spec/support/testable_node.rb` now requires and re-exports the tree_haver version
|
|
68
|
+
- Backward compatible: existing tests continue to work unchanged
|
|
69
|
+
- `spec/ast/merge/node_wrapper_base_spec.rb` refactored to use `TestableNode` instead of mocks
|
|
70
|
+
- Real TreeHaver::Node behavior for most tests
|
|
71
|
+
- Mocks only retained for edge case testing (e.g., invalid end_line before start_line)
|
|
72
|
+
|
|
33
73
|
## [4.0.0] - 2026-01-11
|
|
34
74
|
|
|
35
75
|
- TAG: [v4.0.0][4.0.0t]
|
|
@@ -597,7 +637,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
597
637
|
|
|
598
638
|
- Initial release
|
|
599
639
|
|
|
600
|
-
[Unreleased]: https://github.com/kettle-rb/ast-merge/compare/v4.0.
|
|
640
|
+
[Unreleased]: https://github.com/kettle-rb/ast-merge/compare/v4.0.1...HEAD
|
|
641
|
+
[4.0.1]: https://github.com/kettle-rb/ast-merge/compare/v4.0.0...v4.0.1
|
|
642
|
+
[4.0.1t]: https://github.com/kettle-rb/ast-merge/releases/tag/v4.0.1
|
|
601
643
|
[4.0.0]: https://github.com/kettle-rb/ast-merge/compare/v3.1.0...v4.0.0
|
|
602
644
|
[4.0.0t]: https://github.com/kettle-rb/ast-merge/releases/tag/v4.0.0
|
|
603
645
|
[3.1.0]: https://github.com/kettle-rb/ast-merge/compare/v3.0.0...v3.1.0
|
data/lib/ast/merge/ast_node.rb
CHANGED
|
@@ -8,9 +8,9 @@ module Ast
|
|
|
8
8
|
# created by ast-merge for representing content that doesn't have a native
|
|
9
9
|
# AST (comments, text lines, env file entries, etc.).
|
|
10
10
|
#
|
|
11
|
-
# This class
|
|
12
|
-
# with
|
|
13
|
-
#
|
|
11
|
+
# This class inherits from TreeHaver::Base::Node, ensuring it stays in sync
|
|
12
|
+
# with the canonical Node API. This allows synthetic nodes to be used
|
|
13
|
+
# interchangeably with parser-backed nodes in merge operations.
|
|
14
14
|
#
|
|
15
15
|
# Implements the TreeHaver::Node protocol:
|
|
16
16
|
# - type → String node type
|
|
@@ -36,12 +36,10 @@ module Ast
|
|
|
36
36
|
# end
|
|
37
37
|
# end
|
|
38
38
|
#
|
|
39
|
-
# @see TreeHaver::Node The
|
|
39
|
+
# @see TreeHaver::Base::Node The base class defining the canonical Node API
|
|
40
40
|
# @see Comment::Line Example synthetic node for comments
|
|
41
41
|
# @see Text::LineNode Example synthetic node for text lines
|
|
42
|
-
class AstNode
|
|
43
|
-
include Comparable
|
|
44
|
-
|
|
42
|
+
class AstNode < TreeHaver::Base::Node
|
|
45
43
|
# Point class compatible with TreeHaver::Point
|
|
46
44
|
# Provides both method and hash-style access to row/column
|
|
47
45
|
Point = Struct.new(:row, :column, keyword_init: true) do
|
|
@@ -83,9 +81,6 @@ module Ast
|
|
|
83
81
|
# @return [String] The source text for this node
|
|
84
82
|
attr_reader :slice
|
|
85
83
|
|
|
86
|
-
# @return [String, nil] The full source text (for text extraction)
|
|
87
|
-
attr_reader :source
|
|
88
|
-
|
|
89
84
|
# Initialize a new AstNode.
|
|
90
85
|
#
|
|
91
86
|
# @param slice [String] The source text for this node
|
|
@@ -94,15 +89,14 @@ module Ast
|
|
|
94
89
|
def initialize(slice:, location:, source: nil)
|
|
95
90
|
@slice = slice
|
|
96
91
|
@location = location
|
|
97
|
-
|
|
92
|
+
# Call parent constructor with self as inner_node
|
|
93
|
+
super(self, source: source)
|
|
98
94
|
end
|
|
99
95
|
|
|
100
|
-
#
|
|
101
|
-
#
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def inner_node
|
|
105
|
-
self
|
|
96
|
+
# Override source to return stored value (not parent's)
|
|
97
|
+
# @return [String, nil] The full source text (for text extraction)
|
|
98
|
+
def source
|
|
99
|
+
@source || super
|
|
106
100
|
end
|
|
107
101
|
|
|
108
102
|
# TreeHaver::Node protocol: type
|
|
@@ -132,10 +126,11 @@ module Ast
|
|
|
132
126
|
#
|
|
133
127
|
# @return [Integer] Starting byte offset
|
|
134
128
|
def start_byte
|
|
135
|
-
|
|
129
|
+
src = source
|
|
130
|
+
return 0 unless src && location
|
|
136
131
|
|
|
137
132
|
# Calculate byte offset from line/column
|
|
138
|
-
lines =
|
|
133
|
+
lines = src.lines
|
|
139
134
|
byte_offset = 0
|
|
140
135
|
(0...(location.start_line - 1)).each do |i|
|
|
141
136
|
byte_offset += lines[i]&.bytesize || 0
|
|
@@ -249,6 +244,7 @@ module Ast
|
|
|
249
244
|
end
|
|
250
245
|
|
|
251
246
|
# Comparable: compare nodes by position
|
|
247
|
+
# Note: Inherits Comparable from TreeHaver::Base::Node
|
|
252
248
|
#
|
|
253
249
|
# @param other [AstNode] node to compare with
|
|
254
250
|
# @return [Integer, nil] -1, 0, 1, or nil if not comparable
|
|
@@ -227,7 +227,7 @@ module Ast
|
|
|
227
227
|
next unless node.respond_to?(:start_line) && node.respond_to?(:end_line)
|
|
228
228
|
next unless node.start_line && node.end_line
|
|
229
229
|
|
|
230
|
-
line_num
|
|
230
|
+
line_num.between?(node.start_line, node.end_line)
|
|
231
231
|
end
|
|
232
232
|
end
|
|
233
233
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "merge_gem_registry"
|
|
4
|
+
|
|
3
5
|
# Ast::Merge RSpec Dependency Tags
|
|
4
6
|
#
|
|
5
7
|
# This module provides dependency detection helpers for conditional test execution
|
|
6
|
-
# in the ast-merge gem family. It
|
|
7
|
-
# merge-gem-specific checks.
|
|
8
|
+
# in the ast-merge gem family. It uses MergeGemRegistry for dynamic merge gem detection.
|
|
8
9
|
#
|
|
9
10
|
# @example Loading in spec_helper.rb
|
|
10
11
|
# require "ast/merge/rspec/dependency_tags"
|
|
@@ -18,50 +19,26 @@
|
|
|
18
19
|
# # This test only runs when prism-merge is available
|
|
19
20
|
# end
|
|
20
21
|
#
|
|
21
|
-
# ==
|
|
22
|
-
#
|
|
23
|
-
# === Merge Gem Tags (run when dependency IS available)
|
|
24
|
-
#
|
|
25
|
-
# [:markly_merge]
|
|
26
|
-
# markly-merge gem is available and functional.
|
|
27
|
-
#
|
|
28
|
-
# [:commonmarker_merge]
|
|
29
|
-
# commonmarker-merge gem is available and functional.
|
|
30
|
-
#
|
|
31
|
-
# [:markdown_merge]
|
|
32
|
-
# markdown-merge gem is available and functional.
|
|
33
|
-
#
|
|
34
|
-
# [:prism_merge]
|
|
35
|
-
# prism-merge gem is available and functional.
|
|
36
|
-
#
|
|
37
|
-
# [:json_merge]
|
|
38
|
-
# json-merge gem is available and functional.
|
|
22
|
+
# == Dynamic Tag Registration
|
|
39
23
|
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
24
|
+
# Merge gems register themselves with MergeGemRegistry, which automatically:
|
|
25
|
+
# - Defines `*_available?` methods on DependencyTags
|
|
26
|
+
# - Configures RSpec exclusion filters for the tag
|
|
27
|
+
# - Supports negated tags (`:not_*`)
|
|
42
28
|
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
29
|
+
# @example How merge gems register (in their lib file)
|
|
30
|
+
# Ast::Merge::RSpec::MergeGemRegistry.register(
|
|
31
|
+
# :markly_merge,
|
|
32
|
+
# require_path: "markly/merge",
|
|
33
|
+
# merger_class: "Markly::Merge::SmartMerger",
|
|
34
|
+
# test_source: "# Test\n\nParagraph",
|
|
35
|
+
# category: :markdown
|
|
36
|
+
# )
|
|
45
37
|
#
|
|
46
|
-
#
|
|
47
|
-
# bash-merge gem is available and functional.
|
|
48
|
-
#
|
|
49
|
-
# [:psych_merge]
|
|
50
|
-
# psych-merge gem is available and functional.
|
|
51
|
-
#
|
|
52
|
-
# [:rbs_merge]
|
|
53
|
-
# rbs-merge gem is available and functional.
|
|
38
|
+
# == Built-in Composite Tags
|
|
54
39
|
#
|
|
55
40
|
# [:any_markdown_merge]
|
|
56
|
-
# At least one markdown merge gem (
|
|
57
|
-
#
|
|
58
|
-
# === Negated Tags (run when dependency is NOT available)
|
|
59
|
-
#
|
|
60
|
-
# All positive tags have negated versions prefixed with `not_`:
|
|
61
|
-
# - :not_markly_merge, :not_commonmarker_merge, :not_markdown_merge
|
|
62
|
-
# - :not_prism_merge, :not_json_merge, :not_jsonc_merge
|
|
63
|
-
# - :not_toml_merge, :not_bash_merge, :not_psych_merge, :not_rbs_merge
|
|
64
|
-
# - :not_any_markdown_merge
|
|
41
|
+
# At least one markdown merge gem is available (category: :markdown).
|
|
65
42
|
|
|
66
43
|
module Ast
|
|
67
44
|
module Merge
|
|
@@ -70,96 +47,16 @@ module Ast
|
|
|
70
47
|
module DependencyTags
|
|
71
48
|
class << self
|
|
72
49
|
# ============================================================
|
|
73
|
-
#
|
|
50
|
+
# Composite Availability Checks
|
|
74
51
|
# ============================================================
|
|
75
52
|
|
|
76
|
-
# rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
77
|
-
# Check if markly-merge is available and functional
|
|
78
|
-
#
|
|
79
|
-
# @return [Boolean] true if markly-merge works
|
|
80
|
-
def markly_merge_available?
|
|
81
|
-
return @markly_merge_available if defined?(@markly_merge_available)
|
|
82
|
-
@markly_merge_available = merge_gem_works?("markly/merge", "Markly::Merge::SmartMerger", "# Test\n\nParagraph")
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Check if commonmarker-merge is available and functional
|
|
86
|
-
#
|
|
87
|
-
# @return [Boolean] true if commonmarker-merge works
|
|
88
|
-
def commonmarker_merge_available?
|
|
89
|
-
return @commonmarker_merge_available if defined?(@commonmarker_merge_available)
|
|
90
|
-
@commonmarker_merge_available = merge_gem_works?("commonmarker/merge", "Commonmarker::Merge::SmartMerger", "# Test\n\nParagraph")
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Check if markdown-merge is available and functional
|
|
94
|
-
#
|
|
95
|
-
# @return [Boolean] true if markdown-merge works
|
|
96
|
-
def markdown_merge_available?
|
|
97
|
-
return @markdown_merge_available if defined?(@markdown_merge_available)
|
|
98
|
-
@markdown_merge_available = merge_gem_works?("markdown/merge", "Markdown::Merge::SmartMerger", "# Test\n\nParagraph")
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# Check if prism-merge is available and functional
|
|
102
|
-
#
|
|
103
|
-
# @return [Boolean] true if prism-merge works
|
|
104
|
-
def prism_merge_available?
|
|
105
|
-
return @prism_merge_available if defined?(@prism_merge_available)
|
|
106
|
-
@prism_merge_available = merge_gem_works?("prism/merge", "Prism::Merge::SmartMerger", "puts 1")
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Check if json-merge is available and functional
|
|
110
|
-
#
|
|
111
|
-
# @return [Boolean] true if json-merge works
|
|
112
|
-
def json_merge_available?
|
|
113
|
-
return @json_merge_available if defined?(@json_merge_available)
|
|
114
|
-
@json_merge_available = merge_gem_works?("json/merge", "Json::Merge::SmartMerger", '{"key": "value"}')
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# Check if jsonc-merge is available and functional
|
|
118
|
-
#
|
|
119
|
-
# @return [Boolean] true if jsonc-merge works
|
|
120
|
-
def jsonc_merge_available?
|
|
121
|
-
return @jsonc_merge_available if defined?(@jsonc_merge_available)
|
|
122
|
-
@jsonc_merge_available = merge_gem_works?("jsonc/merge", "Jsonc::Merge::SmartMerger", '{"key": "value" /* comment */}')
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
# Check if toml-merge is available and functional
|
|
126
|
-
#
|
|
127
|
-
# @return [Boolean] true if toml-merge works
|
|
128
|
-
def toml_merge_available?
|
|
129
|
-
return @toml_merge_available if defined?(@toml_merge_available)
|
|
130
|
-
@toml_merge_available = merge_gem_works?("toml/merge", "Toml::Merge::SmartMerger", 'key = "value"')
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# Check if bash-merge is available and functional
|
|
134
|
-
#
|
|
135
|
-
# @return [Boolean] true if bash-merge works
|
|
136
|
-
def bash_merge_available?
|
|
137
|
-
return @bash_merge_available if defined?(@bash_merge_available)
|
|
138
|
-
@bash_merge_available = merge_gem_works?("bash/merge", "Bash::Merge::SmartMerger", "echo hello")
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# Check if psych-merge is available and functional
|
|
142
|
-
#
|
|
143
|
-
# @return [Boolean] true if psych-merge works
|
|
144
|
-
def psych_merge_available?
|
|
145
|
-
return @psych_merge_available if defined?(@psych_merge_available)
|
|
146
|
-
@psych_merge_available = merge_gem_works?("psych/merge", "Psych::Merge::SmartMerger", "key: value")
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
# Check if rbs-merge is available and functional
|
|
150
|
-
#
|
|
151
|
-
# @return [Boolean] true if rbs-merge works
|
|
152
|
-
def rbs_merge_available?
|
|
153
|
-
return @rbs_merge_available if defined?(@rbs_merge_available)
|
|
154
|
-
@rbs_merge_available = merge_gem_works?("rbs/merge", "Rbs::Merge::SmartMerger", "class Foo end")
|
|
155
|
-
end
|
|
156
|
-
# rubocop:enable ThreadSafety/ClassInstanceVariable
|
|
157
|
-
|
|
158
53
|
# Check if at least one markdown merge gem is available
|
|
159
54
|
#
|
|
160
55
|
# @return [Boolean] true if any markdown merge gem works
|
|
161
56
|
def any_markdown_merge_available?
|
|
162
|
-
|
|
57
|
+
MergeGemRegistry.gems_by_category(:markdown).any? do |tag|
|
|
58
|
+
MergeGemRegistry.available?(tag)
|
|
59
|
+
end
|
|
163
60
|
end
|
|
164
61
|
|
|
165
62
|
# ============================================================
|
|
@@ -170,45 +67,16 @@ module Ast
|
|
|
170
67
|
#
|
|
171
68
|
# @return [Hash{Symbol => Boolean}] map of dependency name to availability
|
|
172
69
|
def summary
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
markdown_merge: markdown_merge_available?,
|
|
177
|
-
prism_merge: prism_merge_available?,
|
|
178
|
-
json_merge: json_merge_available?,
|
|
179
|
-
jsonc_merge: jsonc_merge_available?,
|
|
180
|
-
toml_merge: toml_merge_available?,
|
|
181
|
-
bash_merge: bash_merge_available?,
|
|
182
|
-
psych_merge: psych_merge_available?,
|
|
183
|
-
rbs_merge: rbs_merge_available?,
|
|
184
|
-
any_markdown_merge: any_markdown_merge_available?,
|
|
185
|
-
}
|
|
70
|
+
result = MergeGemRegistry.summary
|
|
71
|
+
result[:any_markdown_merge] = any_markdown_merge_available?
|
|
72
|
+
result
|
|
186
73
|
end
|
|
187
74
|
|
|
188
75
|
# Reset all memoized availability checks
|
|
189
76
|
#
|
|
190
77
|
# @return [void]
|
|
191
78
|
def reset!
|
|
192
|
-
|
|
193
|
-
remove_instance_variable(ivar) if ivar.to_s.end_with?("_available")
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
private
|
|
198
|
-
|
|
199
|
-
# Generic helper to check if a merge gem is available and functional
|
|
200
|
-
#
|
|
201
|
-
# @param require_path [String] the require path for the gem
|
|
202
|
-
# @param merger_class [String] the full class name of the SmartMerger
|
|
203
|
-
# @param test_source [String] sample source code to test merging
|
|
204
|
-
# @return [Boolean] true if the merger can be instantiated
|
|
205
|
-
def merge_gem_works?(require_path, merger_class, test_source)
|
|
206
|
-
require require_path
|
|
207
|
-
klass = Object.const_get(merger_class)
|
|
208
|
-
klass.new(test_source, test_source)
|
|
209
|
-
true
|
|
210
|
-
rescue LoadError, StandardError
|
|
211
|
-
false
|
|
79
|
+
MergeGemRegistry.reset_availability!
|
|
212
80
|
end
|
|
213
81
|
end
|
|
214
82
|
end
|
|
@@ -219,10 +87,11 @@ end
|
|
|
219
87
|
# Configure RSpec with dependency-based exclusion filters
|
|
220
88
|
RSpec.configure do |config|
|
|
221
89
|
deps = Ast::Merge::RSpec::DependencyTags
|
|
90
|
+
registry = Ast::Merge::RSpec::MergeGemRegistry
|
|
222
91
|
|
|
223
92
|
config.before(:suite) do
|
|
224
93
|
# Print dependency summary if AST_MERGE_DEBUG is set
|
|
225
|
-
|
|
94
|
+
unless ENV.fetch("AST_MERGE_DEBUG", "false").casecmp?("false")
|
|
226
95
|
puts "\n=== Ast::Merge Test Dependencies ==="
|
|
227
96
|
deps.summary.each do |dep, available|
|
|
228
97
|
status = available ? "✓ available" : "✗ not available"
|
|
@@ -233,34 +102,24 @@ RSpec.configure do |config|
|
|
|
233
102
|
end
|
|
234
103
|
|
|
235
104
|
# ============================================================
|
|
236
|
-
# Merge Gem Tags
|
|
105
|
+
# Dynamic Merge Gem Tags
|
|
237
106
|
# ============================================================
|
|
107
|
+
# Tags are configured dynamically based on what's registered in MergeGemRegistry.
|
|
108
|
+
# Each merge gem registers itself, and exclusion filters are set up automatically.
|
|
238
109
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
config.filter_run_excluding(psych_merge: true) unless deps.psych_merge_available?
|
|
248
|
-
config.filter_run_excluding(rbs_merge: true) unless deps.rbs_merge_available?
|
|
249
|
-
config.filter_run_excluding(any_markdown_merge: true) unless deps.any_markdown_merge_available?
|
|
110
|
+
registry.registered_gems.each do |tag|
|
|
111
|
+
# Positive tag: run when gem IS available
|
|
112
|
+
config.filter_run_excluding(tag => true) unless registry.available?(tag)
|
|
113
|
+
|
|
114
|
+
# Negated tag: run when gem is NOT available
|
|
115
|
+
negated_tag = :"not_#{tag}"
|
|
116
|
+
config.filter_run_excluding(negated_tag => true) if registry.available?(tag)
|
|
117
|
+
end
|
|
250
118
|
|
|
251
119
|
# ============================================================
|
|
252
|
-
#
|
|
120
|
+
# Composite Tags
|
|
253
121
|
# ============================================================
|
|
254
122
|
|
|
255
|
-
config.filter_run_excluding(
|
|
256
|
-
config.filter_run_excluding(not_commonmarker_merge: true) if deps.commonmarker_merge_available?
|
|
257
|
-
config.filter_run_excluding(not_markdown_merge: true) if deps.markdown_merge_available?
|
|
258
|
-
config.filter_run_excluding(not_prism_merge: true) if deps.prism_merge_available?
|
|
259
|
-
config.filter_run_excluding(not_json_merge: true) if deps.json_merge_available?
|
|
260
|
-
config.filter_run_excluding(not_jsonc_merge: true) if deps.jsonc_merge_available?
|
|
261
|
-
config.filter_run_excluding(not_toml_merge: true) if deps.toml_merge_available?
|
|
262
|
-
config.filter_run_excluding(not_bash_merge: true) if deps.bash_merge_available?
|
|
263
|
-
config.filter_run_excluding(not_psych_merge: true) if deps.psych_merge_available?
|
|
264
|
-
config.filter_run_excluding(not_rbs_merge: true) if deps.rbs_merge_available?
|
|
123
|
+
config.filter_run_excluding(any_markdown_merge: true) unless deps.any_markdown_merge_available?
|
|
265
124
|
config.filter_run_excluding(not_any_markdown_merge: true) if deps.any_markdown_merge_available?
|
|
266
125
|
end
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ast
|
|
4
|
+
module Merge
|
|
5
|
+
module RSpec
|
|
6
|
+
# Registry for merge gem dependency tag availability checkers
|
|
7
|
+
#
|
|
8
|
+
# This module allows merge gems (like markly-merge, prism-merge, json-merge)
|
|
9
|
+
# to register their availability checker for RSpec dependency tags without
|
|
10
|
+
# ast-merge needing to know about them directly.
|
|
11
|
+
#
|
|
12
|
+
# == Purpose
|
|
13
|
+
#
|
|
14
|
+
# When running RSpec tests with dependency tags (e.g., `:markly_merge`),
|
|
15
|
+
# ast-merge needs to know if each merge gem is available. The MergeGemRegistry
|
|
16
|
+
# provides a way for gems to register their availability checkers, and also
|
|
17
|
+
# pre-configures known merge gems so they can be checked before being loaded.
|
|
18
|
+
#
|
|
19
|
+
# == Pre-configured Gems
|
|
20
|
+
#
|
|
21
|
+
# The following merge gems are pre-configured so that their availability can
|
|
22
|
+
# be checked before they are loaded (e.g., during RSpec setup):
|
|
23
|
+
# - :markly_merge, :commonmarker_merge, :markdown_merge (markdown)
|
|
24
|
+
# - :prism_merge, :bash_merge, :rbs_merge (code)
|
|
25
|
+
# - :json_merge, :jsonc_merge (data)
|
|
26
|
+
# - :toml_merge, :psych_merge, :dotenv_merge (config)
|
|
27
|
+
#
|
|
28
|
+
# External merge gems can also register themselves by calling {register}
|
|
29
|
+
# when loaded.
|
|
30
|
+
#
|
|
31
|
+
# == Registration
|
|
32
|
+
#
|
|
33
|
+
# Each merge gem registers itself when loaded using {register}:
|
|
34
|
+
# - Tag name (e.g., :markly_merge)
|
|
35
|
+
# - Require path (e.g., "markly/merge")
|
|
36
|
+
# - Merger class name (e.g., "Markly::Merge::SmartMerger")
|
|
37
|
+
# - Test source code to verify the merger works
|
|
38
|
+
# - Optional category for grouping (e.g., :markdown, :data, :code)
|
|
39
|
+
#
|
|
40
|
+
# When a tag is registered, an availability method is automatically defined
|
|
41
|
+
# on `Ast::Merge::RSpec::DependencyTags`.
|
|
42
|
+
#
|
|
43
|
+
# == Thread Safety
|
|
44
|
+
#
|
|
45
|
+
# All operations are thread-safe using a Mutex for synchronization.
|
|
46
|
+
# Results are cached after first check for performance.
|
|
47
|
+
#
|
|
48
|
+
# @example Registering a merge gem (in your gem's lib file)
|
|
49
|
+
# # In markly-merge/lib/markly/merge.rb
|
|
50
|
+
# if defined?(Ast::Merge::RSpec::MergeGemRegistry)
|
|
51
|
+
# Ast::Merge::RSpec::MergeGemRegistry.register(
|
|
52
|
+
# :markly_merge,
|
|
53
|
+
# require_path: "markly/merge",
|
|
54
|
+
# merger_class: "Markly::Merge::SmartMerger",
|
|
55
|
+
# test_source: "# Test\n\nParagraph",
|
|
56
|
+
# category: :markdown
|
|
57
|
+
# )
|
|
58
|
+
# end
|
|
59
|
+
#
|
|
60
|
+
# @example Checking availability
|
|
61
|
+
# Ast::Merge::RSpec::MergeGemRegistry.available?(:markly_merge) # => true/false
|
|
62
|
+
#
|
|
63
|
+
# @example Getting all registered gems
|
|
64
|
+
# Ast::Merge::RSpec::MergeGemRegistry.registered_gems # => [:markly_merge, :prism_merge, ...]
|
|
65
|
+
#
|
|
66
|
+
# @see Ast::Merge::RSpec::DependencyTags Uses MergeGemRegistry for dynamic gem detection
|
|
67
|
+
# @api public
|
|
68
|
+
module MergeGemRegistry
|
|
69
|
+
@mutex = Mutex.new
|
|
70
|
+
@registry = {} # rubocop:disable ThreadSafety/MutableClassInstanceVariable
|
|
71
|
+
@availability_cache = {} # rubocop:disable ThreadSafety/MutableClassInstanceVariable
|
|
72
|
+
|
|
73
|
+
# Valid categories for merge gems
|
|
74
|
+
CATEGORIES = %i[markdown data code config other].freeze
|
|
75
|
+
|
|
76
|
+
# Pre-configured known merge gems
|
|
77
|
+
# These can be checked before the gems are actually loaded
|
|
78
|
+
KNOWN_GEMS = {
|
|
79
|
+
# Markdown gems
|
|
80
|
+
markly_merge: {
|
|
81
|
+
require_path: "markly/merge",
|
|
82
|
+
merger_class: "Markly::Merge::SmartMerger",
|
|
83
|
+
test_source: "# Test\n\nParagraph",
|
|
84
|
+
category: :markdown,
|
|
85
|
+
skip_instantiation: false,
|
|
86
|
+
},
|
|
87
|
+
commonmarker_merge: {
|
|
88
|
+
require_path: "commonmarker/merge",
|
|
89
|
+
merger_class: "Commonmarker::Merge::SmartMerger",
|
|
90
|
+
test_source: "# Test\n\nParagraph",
|
|
91
|
+
category: :markdown,
|
|
92
|
+
skip_instantiation: false,
|
|
93
|
+
},
|
|
94
|
+
markdown_merge: {
|
|
95
|
+
require_path: "markdown/merge",
|
|
96
|
+
merger_class: "Markdown::Merge::SmartMerger",
|
|
97
|
+
test_source: "# Test\n\nParagraph",
|
|
98
|
+
category: :markdown,
|
|
99
|
+
skip_instantiation: true, # Requires backend
|
|
100
|
+
},
|
|
101
|
+
# Code gems
|
|
102
|
+
prism_merge: {
|
|
103
|
+
require_path: "prism/merge",
|
|
104
|
+
merger_class: "Prism::Merge::SmartMerger",
|
|
105
|
+
test_source: "def foo; end",
|
|
106
|
+
category: :code,
|
|
107
|
+
skip_instantiation: false,
|
|
108
|
+
},
|
|
109
|
+
bash_merge: {
|
|
110
|
+
require_path: "bash/merge",
|
|
111
|
+
merger_class: "Bash::Merge::SmartMerger",
|
|
112
|
+
test_source: "#!/bin/bash\necho hello",
|
|
113
|
+
category: :code,
|
|
114
|
+
skip_instantiation: false,
|
|
115
|
+
},
|
|
116
|
+
rbs_merge: {
|
|
117
|
+
require_path: "rbs/merge",
|
|
118
|
+
merger_class: "Rbs::Merge::SmartMerger",
|
|
119
|
+
test_source: "class Foo\nend",
|
|
120
|
+
category: :code,
|
|
121
|
+
skip_instantiation: false,
|
|
122
|
+
},
|
|
123
|
+
# Data gems
|
|
124
|
+
json_merge: {
|
|
125
|
+
require_path: "json/merge",
|
|
126
|
+
merger_class: "Json::Merge::SmartMerger",
|
|
127
|
+
test_source: '{"key": "value"}',
|
|
128
|
+
category: :data,
|
|
129
|
+
skip_instantiation: false,
|
|
130
|
+
},
|
|
131
|
+
jsonc_merge: {
|
|
132
|
+
require_path: "jsonc/merge",
|
|
133
|
+
merger_class: "Jsonc::Merge::SmartMerger",
|
|
134
|
+
test_source: "// comment\n{\"key\": \"value\"}",
|
|
135
|
+
category: :data,
|
|
136
|
+
skip_instantiation: false,
|
|
137
|
+
},
|
|
138
|
+
# Config gems
|
|
139
|
+
toml_merge: {
|
|
140
|
+
require_path: "toml/merge",
|
|
141
|
+
merger_class: "Toml::Merge::SmartMerger",
|
|
142
|
+
test_source: "[section]\nkey = \"value\"",
|
|
143
|
+
category: :config,
|
|
144
|
+
skip_instantiation: false,
|
|
145
|
+
},
|
|
146
|
+
psych_merge: {
|
|
147
|
+
require_path: "psych/merge",
|
|
148
|
+
merger_class: "Psych::Merge::SmartMerger",
|
|
149
|
+
test_source: "key: value",
|
|
150
|
+
category: :config,
|
|
151
|
+
skip_instantiation: false,
|
|
152
|
+
},
|
|
153
|
+
dotenv_merge: {
|
|
154
|
+
require_path: "dotenv/merge",
|
|
155
|
+
merger_class: "Dotenv::Merge::SmartMerger",
|
|
156
|
+
test_source: "KEY=value",
|
|
157
|
+
category: :config,
|
|
158
|
+
skip_instantiation: false,
|
|
159
|
+
},
|
|
160
|
+
}.freeze
|
|
161
|
+
|
|
162
|
+
module_function
|
|
163
|
+
|
|
164
|
+
# Register a merge gem for dependency tag support
|
|
165
|
+
#
|
|
166
|
+
# When a gem is registered, this also dynamically defines a `*_available?` method
|
|
167
|
+
# on `Ast::Merge::RSpec::DependencyTags` if it doesn't already exist.
|
|
168
|
+
#
|
|
169
|
+
# @param tag_name [Symbol] the RSpec tag name (e.g., :markly_merge)
|
|
170
|
+
# @param require_path [String] the require path for the gem (e.g., "markly/merge")
|
|
171
|
+
# @param merger_class [String] the full class name of the SmartMerger
|
|
172
|
+
# @param test_source [String] sample source code to test merging
|
|
173
|
+
# @param category [Symbol] category for grouping (:markdown, :data, :code, :config, :other)
|
|
174
|
+
# @param skip_instantiation [Boolean] if true, only check class exists (for gems requiring backends)
|
|
175
|
+
# @return [void]
|
|
176
|
+
#
|
|
177
|
+
# @example Register a merge gem
|
|
178
|
+
# Ast::Merge::RSpec::MergeGemRegistry.register(
|
|
179
|
+
# :markly_merge,
|
|
180
|
+
# require_path: "markly/merge",
|
|
181
|
+
# merger_class: "Markly::Merge::SmartMerger",
|
|
182
|
+
# test_source: "# Test\n\nParagraph",
|
|
183
|
+
# category: :markdown
|
|
184
|
+
# )
|
|
185
|
+
def register(tag_name, require_path:, merger_class:, test_source:, category: :other, skip_instantiation: false)
|
|
186
|
+
raise ArgumentError, "Invalid category: #{category}" unless CATEGORIES.include?(category)
|
|
187
|
+
|
|
188
|
+
tag_sym = tag_name.to_sym
|
|
189
|
+
|
|
190
|
+
@mutex.synchronize do
|
|
191
|
+
@registry[tag_sym] = {
|
|
192
|
+
require_path: require_path,
|
|
193
|
+
merger_class: merger_class,
|
|
194
|
+
test_source: test_source,
|
|
195
|
+
category: category,
|
|
196
|
+
skip_instantiation: skip_instantiation,
|
|
197
|
+
}
|
|
198
|
+
# Clear cache when re-registering
|
|
199
|
+
@availability_cache.delete(tag_sym)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Define availability method on DependencyTags
|
|
203
|
+
define_availability_method(tag_sym)
|
|
204
|
+
|
|
205
|
+
nil
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Check if a merge gem is available and functional
|
|
209
|
+
#
|
|
210
|
+
# This method will try to load the gem if it's not yet registered but
|
|
211
|
+
# is known (in KNOWN_GEMS). This allows availability checking before
|
|
212
|
+
# the gem is explicitly loaded.
|
|
213
|
+
#
|
|
214
|
+
# @param tag_name [Symbol] the tag name to check
|
|
215
|
+
# @return [Boolean] true if the merge gem is available and works
|
|
216
|
+
def available?(tag_name)
|
|
217
|
+
tag_sym = tag_name.to_sym
|
|
218
|
+
|
|
219
|
+
# Check cache first
|
|
220
|
+
@mutex.synchronize do
|
|
221
|
+
return @availability_cache[tag_sym] if @availability_cache.key?(tag_sym)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Get registration info (from registry or known gems)
|
|
225
|
+
info = @mutex.synchronize { @registry[tag_sym] }
|
|
226
|
+
info ||= KNOWN_GEMS[tag_sym]
|
|
227
|
+
|
|
228
|
+
return false unless info
|
|
229
|
+
|
|
230
|
+
# Check if gem works
|
|
231
|
+
result = gem_works?(
|
|
232
|
+
info[:require_path],
|
|
233
|
+
info[:merger_class],
|
|
234
|
+
info[:test_source],
|
|
235
|
+
info[:skip_instantiation],
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# Cache result
|
|
239
|
+
@mutex.synchronize do
|
|
240
|
+
@availability_cache[tag_sym] = result
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
result
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Check if a tag is registered
|
|
247
|
+
#
|
|
248
|
+
# @param tag_name [Symbol] the tag name
|
|
249
|
+
# @return [Boolean] true if the tag is registered
|
|
250
|
+
def registered?(tag_name)
|
|
251
|
+
@mutex.synchronize do
|
|
252
|
+
@registry.key?(tag_name.to_sym)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Get all registered gem tag names (including pre-configured known gems)
|
|
257
|
+
#
|
|
258
|
+
# @return [Array<Symbol>] list of registered tag names
|
|
259
|
+
def registered_gems
|
|
260
|
+
@mutex.synchronize do
|
|
261
|
+
(KNOWN_GEMS.keys + @registry.keys).uniq
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Get gems filtered by category
|
|
266
|
+
#
|
|
267
|
+
# @param category [Symbol] one of :markdown, :data, :code, :config, :other
|
|
268
|
+
# @return [Array<Symbol>] list of tag names in that category
|
|
269
|
+
def gems_by_category(category)
|
|
270
|
+
@mutex.synchronize do
|
|
271
|
+
known = KNOWN_GEMS.select { |_, info| info[:category] == category }.keys
|
|
272
|
+
registered = @registry.select { |_, info| info[:category] == category }.keys
|
|
273
|
+
(known + registered).uniq
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# Get registration info for a gem
|
|
278
|
+
#
|
|
279
|
+
# @param tag_name [Symbol] the tag name
|
|
280
|
+
# @return [Hash, nil] registration info or nil if not registered/known
|
|
281
|
+
def info(tag_name)
|
|
282
|
+
tag_sym = tag_name.to_sym
|
|
283
|
+
@mutex.synchronize do
|
|
284
|
+
@registry[tag_sym]&.dup || KNOWN_GEMS[tag_sym]&.dup
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Get a summary of all registered gems and their availability
|
|
289
|
+
#
|
|
290
|
+
# @return [Hash{Symbol => Boolean}] map of tag name to availability
|
|
291
|
+
def summary
|
|
292
|
+
registered_gems.each_with_object({}) do |tag, result|
|
|
293
|
+
result[tag] = available?(tag)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Clear the availability cache
|
|
298
|
+
#
|
|
299
|
+
# @return [void]
|
|
300
|
+
def clear_cache!
|
|
301
|
+
@mutex.synchronize do
|
|
302
|
+
@availability_cache.clear
|
|
303
|
+
end
|
|
304
|
+
nil
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Clear all registrations and cache
|
|
308
|
+
#
|
|
309
|
+
# @return [void]
|
|
310
|
+
def clear!
|
|
311
|
+
@mutex.synchronize do
|
|
312
|
+
@registry.clear
|
|
313
|
+
@availability_cache.clear
|
|
314
|
+
end
|
|
315
|
+
nil
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Reset memoized availability on DependencyTags
|
|
319
|
+
#
|
|
320
|
+
# @return [void]
|
|
321
|
+
def reset_availability!
|
|
322
|
+
clear_cache!
|
|
323
|
+
return unless defined?(DependencyTags)
|
|
324
|
+
|
|
325
|
+
registered_gems.each do |tag|
|
|
326
|
+
ivar = :"@#{tag}_available"
|
|
327
|
+
DependencyTags.remove_instance_variable(ivar) if DependencyTags.instance_variable_defined?(ivar)
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# ============================================================
|
|
332
|
+
# Private Helpers
|
|
333
|
+
# ============================================================
|
|
334
|
+
|
|
335
|
+
# Check if a merge gem is available and functional
|
|
336
|
+
#
|
|
337
|
+
# @param require_path [String] the require path for the gem
|
|
338
|
+
# @param merger_class [String] the full class name of the SmartMerger
|
|
339
|
+
# @param test_source [String] sample source code to test merging
|
|
340
|
+
# @param skip_instantiation [Boolean] if true, only check class exists
|
|
341
|
+
# @return [Boolean] true if the merger can be loaded/instantiated
|
|
342
|
+
# @api private
|
|
343
|
+
def gem_works?(require_path, merger_class, test_source, skip_instantiation)
|
|
344
|
+
require require_path
|
|
345
|
+
klass = Object.const_get(merger_class)
|
|
346
|
+
|
|
347
|
+
if skip_instantiation
|
|
348
|
+
# Just check that the class exists and looks like a SmartMerger
|
|
349
|
+
klass.is_a?(Class) && klass.ancestors.any? { |a| a.name&.include?("SmartMergerBase") }
|
|
350
|
+
else
|
|
351
|
+
klass.new(test_source, test_source)
|
|
352
|
+
true
|
|
353
|
+
end
|
|
354
|
+
rescue LoadError, StandardError
|
|
355
|
+
false
|
|
356
|
+
end
|
|
357
|
+
private_class_method :gem_works?
|
|
358
|
+
|
|
359
|
+
# Dynamically define an availability method on DependencyTags
|
|
360
|
+
#
|
|
361
|
+
# @param tag_name [Symbol] the tag name (e.g., :markly_merge)
|
|
362
|
+
# @return [void]
|
|
363
|
+
# @api private
|
|
364
|
+
def define_availability_method(tag_name)
|
|
365
|
+
method_name = :"#{tag_name}_available?"
|
|
366
|
+
|
|
367
|
+
# Only define if DependencyTags is loaded
|
|
368
|
+
return unless defined?(DependencyTags)
|
|
369
|
+
|
|
370
|
+
# Don't override existing methods
|
|
371
|
+
return if DependencyTags.respond_to?(method_name)
|
|
372
|
+
|
|
373
|
+
# Define the method dynamically - MergeGemRegistry.available? handles caching
|
|
374
|
+
DependencyTags.define_singleton_method(method_name) do
|
|
375
|
+
MergeGemRegistry.available?(tag_name)
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
private_class_method :define_availability_method
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
end
|
data/lib/ast/merge/version.rb
CHANGED
data/lib/ast/merge.rb
CHANGED
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ast-merge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.0.
|
|
4
|
+
version: 4.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -66,7 +66,7 @@ dependencies:
|
|
|
66
66
|
version: '5.0'
|
|
67
67
|
- - ">="
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: 5.0.
|
|
69
|
+
version: 5.0.1
|
|
70
70
|
type: :runtime
|
|
71
71
|
prerelease: false
|
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -76,7 +76,7 @@ dependencies:
|
|
|
76
76
|
version: '5.0'
|
|
77
77
|
- - ">="
|
|
78
78
|
- !ruby/object:Gem::Version
|
|
79
|
-
version: 5.0.
|
|
79
|
+
version: 5.0.1
|
|
80
80
|
- !ruby/object:Gem::Dependency
|
|
81
81
|
name: kettle-dev
|
|
82
82
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -355,6 +355,7 @@ files:
|
|
|
355
355
|
- lib/ast/merge/recipe/script_loader.rb
|
|
356
356
|
- lib/ast/merge/rspec.rb
|
|
357
357
|
- lib/ast/merge/rspec/dependency_tags.rb
|
|
358
|
+
- lib/ast/merge/rspec/merge_gem_registry.rb
|
|
358
359
|
- lib/ast/merge/rspec/shared_examples.rb
|
|
359
360
|
- lib/ast/merge/rspec/shared_examples/conflict_resolver_base.rb
|
|
360
361
|
- lib/ast/merge/rspec/shared_examples/debug_logger.rb
|
|
@@ -381,10 +382,10 @@ licenses:
|
|
|
381
382
|
- MIT
|
|
382
383
|
metadata:
|
|
383
384
|
homepage_uri: https://ast-merge.galtzo.com/
|
|
384
|
-
source_code_uri: https://github.com/kettle-rb/ast-merge/tree/v4.0.
|
|
385
|
-
changelog_uri: https://github.com/kettle-rb/ast-merge/blob/v4.0.
|
|
385
|
+
source_code_uri: https://github.com/kettle-rb/ast-merge/tree/v4.0.1
|
|
386
|
+
changelog_uri: https://github.com/kettle-rb/ast-merge/blob/v4.0.1/CHANGELOG.md
|
|
386
387
|
bug_tracker_uri: https://github.com/kettle-rb/ast-merge/issues
|
|
387
|
-
documentation_uri: https://www.rubydoc.info/gems/ast-merge/4.0.
|
|
388
|
+
documentation_uri: https://www.rubydoc.info/gems/ast-merge/4.0.1
|
|
388
389
|
funding_uri: https://github.com/sponsors/pboling
|
|
389
390
|
wiki_uri: https://github.com/kettle-rb/ast-merge/wiki
|
|
390
391
|
news_uri: https://www.railsbling.com/tags/ast-merge
|
metadata.gz.sig
CHANGED
|
Binary file
|