bash-merge 1.0.0 → 1.0.2
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 +36 -1
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/lib/bash/merge/file_analysis.rb +3 -1
- data/lib/bash/merge/node_wrapper.rb +14 -115
- data/lib/bash/merge/version.rb +1 -1
- data/lib/bash/merge.rb +8 -19
- data.tar.gz.sig +0 -0
- metadata +8 -8
- 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: bf2cbd8a4823b24975b63a2366d700f7cbc61a72584bf08d4c90e998713df3bf
|
|
4
|
+
data.tar.gz: 172b697453ad5c0b647914036906f3068b49a4d18475c183471f2dd649081f21
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4bd8c9ff57b18df22ca30d2a7fd55868fbf101d1159f76b987bb39b92c592e044ab96856bbaf73dea137af9da4089f4eae9a43fd240694488e45f20608a79dfc
|
|
7
|
+
data.tar.gz: 87b6db769a1a8680a77380f6e1b0d0b6f842430687b314fbd5fa36c4097c87e984b7b974d2aea0d85fd2e2f9c10292d034a997257e601cbe92e1f65406f8aa20
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,37 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [1.0.2] - 2026-01-02
|
|
34
|
+
|
|
35
|
+
- TAG: [v1.0.2][1.0.2t]
|
|
36
|
+
- COVERAGE: 100.00% -- 109/109 lines in 2 files
|
|
37
|
+
- BRANCH COVERAGE: 100.00% -- 28/28 branches in 2 files
|
|
38
|
+
- 96.46% documented
|
|
39
|
+
|
|
40
|
+
### Removed
|
|
41
|
+
|
|
42
|
+
- **Load-time grammar registration** - TreeHaver's `parser_for` now handles grammar discovery
|
|
43
|
+
and registration automatically. Removed manual `GrammarFinder` calls and warnings from
|
|
44
|
+
`lib/bash/merge.rb`.
|
|
45
|
+
|
|
46
|
+
## [1.0.1] - 2026-01-01
|
|
47
|
+
|
|
48
|
+
- TAG: [v1.0.1][1.0.1t]
|
|
49
|
+
- COVERAGE: 100.00% -- 109/109 lines in 2 files
|
|
50
|
+
- BRANCH COVERAGE: 100.00% -- 28/28 branches in 2 files
|
|
51
|
+
- 96.46% documented
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- **NodeWrapper**: Now inherits from `Ast::Merge::NodeWrapperBase`
|
|
56
|
+
- Removes ~100 lines of duplicated code (initialization, line extraction, basic methods)
|
|
57
|
+
- Keeps only Bash-specific type predicates and signature computation
|
|
58
|
+
- Adds `#node_wrapper?` method for distinguishing from `NodeTyping::Wrapper`
|
|
59
|
+
- **FileAnalysis error handling**: Now rescues `TreeHaver::Error` instead of `TreeHaver::NotAvailable`
|
|
60
|
+
- `TreeHaver::Error` inherits from `Exception`, not `StandardError`
|
|
61
|
+
- `TreeHaver::NotAvailable` is a subclass of `TreeHaver::Error`, so it's also caught
|
|
62
|
+
- Fixes parse error handling on alternative Ruby engines
|
|
63
|
+
|
|
33
64
|
## [1.0.0] - 2026-01-01
|
|
34
65
|
|
|
35
66
|
- TAG: [v1.0.0][1.0.0t]
|
|
@@ -43,6 +74,10 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
43
74
|
|
|
44
75
|
### Security
|
|
45
76
|
|
|
46
|
-
[Unreleased]: https://github.com/kettle-rb/bash-merge/compare/v1.0.
|
|
77
|
+
[Unreleased]: https://github.com/kettle-rb/bash-merge/compare/v1.0.2...HEAD
|
|
78
|
+
[1.0.2]: https://github.com/kettle-rb/bash-merge/compare/v1.0.1...v1.0.2
|
|
79
|
+
[1.0.2t]: https://github.com/kettle-rb/bash-merge/releases/tag/v1.0.2
|
|
80
|
+
[1.0.1]: https://github.com/kettle-rb/bash-merge/compare/v1.0.0...v1.0.1
|
|
81
|
+
[1.0.1t]: https://github.com/kettle-rb/bash-merge/releases/tag/v1.0.1
|
|
47
82
|
[1.0.0]: https://github.com/kettle-rb/bash-merge/compare/db525d5aedd0c895422a067629118f3fa9c3c22d...v1.0.0
|
|
48
83
|
[1.0.0t]: https://github.com/kettle-rb/bash-merge/tags/v1.0.0
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -685,7 +685,7 @@ See [LICENSE.txt](LICENSE.txt) for the official [Copyright Notice](https://opens
|
|
|
685
685
|
|
|
686
686
|
<ul>
|
|
687
687
|
<li>
|
|
688
|
-
Copyright (c) 2025 Peter H. Boling, of
|
|
688
|
+
Copyright (c) 2025-2026 Peter H. Boling, of
|
|
689
689
|
<a href="https://discord.gg/3qme4XHNKN">
|
|
690
690
|
Galtzo.com
|
|
691
691
|
<picture>
|
|
@@ -144,7 +144,9 @@ module Bash
|
|
|
144
144
|
if @ast&.root_node&.has_error?
|
|
145
145
|
collect_parse_errors(@ast.root_node)
|
|
146
146
|
end
|
|
147
|
-
rescue TreeHaver::
|
|
147
|
+
rescue TreeHaver::Error => e
|
|
148
|
+
# TreeHaver::Error inherits from Exception, not StandardError.
|
|
149
|
+
# This also catches TreeHaver::NotAvailable (subclass of Error).
|
|
148
150
|
@errors << e.message
|
|
149
151
|
@ast = nil
|
|
150
152
|
rescue StandardError => e
|
|
@@ -5,87 +5,20 @@ module Bash
|
|
|
5
5
|
# Wraps TreeHaver nodes with comment associations, line information, and signatures.
|
|
6
6
|
# This provides a unified interface for working with Bash AST nodes during merging.
|
|
7
7
|
#
|
|
8
|
+
# Inherits common functionality from Ast::Merge::NodeWrapperBase:
|
|
9
|
+
# - Source context (lines, source, comments)
|
|
10
|
+
# - Line info extraction
|
|
11
|
+
# - Basic methods: #type, #type?, #text, #content, #signature
|
|
12
|
+
#
|
|
8
13
|
# @example Basic usage
|
|
9
14
|
# parser = TreeHaver::Parser.new
|
|
10
15
|
# parser.language = TreeHaver::Language.bash
|
|
11
16
|
# tree = parser.parse(source)
|
|
12
17
|
# wrapper = NodeWrapper.new(tree.root_node, lines: source.lines, source: source)
|
|
13
18
|
# wrapper.signature # => [:program, ...]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# @return [Array<Hash>] Leading comments associated with this node
|
|
19
|
-
attr_reader :leading_comments
|
|
20
|
-
|
|
21
|
-
# @return [Hash, nil] Inline/trailing comment on the same line
|
|
22
|
-
attr_reader :inline_comment
|
|
23
|
-
|
|
24
|
-
# @return [Integer] Start line (1-based)
|
|
25
|
-
attr_reader :start_line
|
|
26
|
-
|
|
27
|
-
# @return [Integer] End line (1-based)
|
|
28
|
-
attr_reader :end_line
|
|
29
|
-
|
|
30
|
-
# @return [Array<String>] Source lines
|
|
31
|
-
attr_reader :lines
|
|
32
|
-
|
|
33
|
-
# @return [String] The original source string
|
|
34
|
-
attr_reader :source
|
|
35
|
-
|
|
36
|
-
# @param node [TreeHaver::Node] tree-haver node to wrap
|
|
37
|
-
# @param lines [Array<String>] Source lines for content extraction
|
|
38
|
-
# @param source [String] Original source string for byte-based text extraction
|
|
39
|
-
# @param leading_comments [Array<Hash>] Comments before this node
|
|
40
|
-
# @param inline_comment [Hash, nil] Inline comment on the node's line
|
|
41
|
-
def initialize(node, lines:, source: nil, leading_comments: [], inline_comment: nil)
|
|
42
|
-
@node = node
|
|
43
|
-
@lines = lines
|
|
44
|
-
@source = source || lines.join("\n")
|
|
45
|
-
@leading_comments = leading_comments
|
|
46
|
-
@inline_comment = inline_comment
|
|
47
|
-
|
|
48
|
-
# Extract line information from the tree-haver node (0-indexed to 1-indexed)
|
|
49
|
-
if node.respond_to?(:start_point)
|
|
50
|
-
point = node.start_point
|
|
51
|
-
@start_line = (point.respond_to?(:row) ? point.row : point[:row]) + 1
|
|
52
|
-
end
|
|
53
|
-
if node.respond_to?(:end_point)
|
|
54
|
-
point = node.end_point
|
|
55
|
-
@end_line = (point.respond_to?(:row) ? point.row : point[:row]) + 1
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Handle edge case where end_line might be before start_line
|
|
59
|
-
@end_line = @start_line if @start_line && @end_line && @end_line < @start_line
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Generate a signature for this node for matching purposes.
|
|
63
|
-
# Signatures are used to identify corresponding nodes between template and destination.
|
|
64
|
-
#
|
|
65
|
-
# @return [Array, nil] Signature array or nil if not signaturable
|
|
66
|
-
def signature
|
|
67
|
-
compute_signature(@node)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# Check if this is a freeze node
|
|
71
|
-
# @return [Boolean]
|
|
72
|
-
def freeze_node?
|
|
73
|
-
false
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Get the node type as a symbol
|
|
77
|
-
# @return [Symbol]
|
|
78
|
-
def type
|
|
79
|
-
@node.type.to_sym
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Check if this node has a specific type
|
|
83
|
-
# @param type_name [Symbol, String] Type to check
|
|
84
|
-
# @return [Boolean]
|
|
85
|
-
def type?(type_name)
|
|
86
|
-
@node.type.to_s == type_name.to_s
|
|
87
|
-
end
|
|
88
|
-
|
|
19
|
+
#
|
|
20
|
+
# @see Ast::Merge::NodeWrapperBase
|
|
21
|
+
class NodeWrapper < Ast::Merge::NodeWrapperBase
|
|
89
22
|
# Check if this is a function definition
|
|
90
23
|
# @return [Boolean]
|
|
91
24
|
def function_definition?
|
|
@@ -174,18 +107,6 @@ module Bash
|
|
|
174
107
|
nil
|
|
175
108
|
end
|
|
176
109
|
|
|
177
|
-
# Get children wrapped as NodeWrappers
|
|
178
|
-
# @return [Array<NodeWrapper>]
|
|
179
|
-
def children
|
|
180
|
-
return [] unless @node.respond_to?(:each)
|
|
181
|
-
|
|
182
|
-
result = []
|
|
183
|
-
@node.each do |child|
|
|
184
|
-
result << NodeWrapper.new(child, lines: @lines, source: @source)
|
|
185
|
-
end
|
|
186
|
-
result
|
|
187
|
-
end
|
|
188
|
-
|
|
189
110
|
# Find a child by field name
|
|
190
111
|
# @param field_name [String] Field name to look for
|
|
191
112
|
# @return [TreeSitter::Node, nil]
|
|
@@ -207,37 +128,13 @@ module Bash
|
|
|
207
128
|
nil
|
|
208
129
|
end
|
|
209
130
|
|
|
210
|
-
|
|
211
|
-
# @return [String]
|
|
212
|
-
def text
|
|
213
|
-
node_text(@node)
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
# Extract text from a tree-sitter node using byte positions
|
|
217
|
-
# @param ts_node [TreeSitter::Node] The tree-sitter node
|
|
218
|
-
# @return [String]
|
|
219
|
-
def node_text(ts_node)
|
|
220
|
-
return "" unless ts_node.respond_to?(:start_byte) && ts_node.respond_to?(:end_byte)
|
|
221
|
-
|
|
222
|
-
@source[ts_node.start_byte...ts_node.end_byte] || ""
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
# Get the content for this node from source lines
|
|
226
|
-
# @return [String]
|
|
227
|
-
def content
|
|
228
|
-
return "" unless @start_line && @end_line
|
|
229
|
-
|
|
230
|
-
(@start_line..@end_line).map { |ln| @lines[ln - 1] }.compact.join("\n")
|
|
231
|
-
end
|
|
131
|
+
protected
|
|
232
132
|
|
|
233
|
-
#
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
"#<#{self.class.name} type=#{@node.type} lines=#{@start_line}..#{@end_line}>"
|
|
133
|
+
# Override wrap_child to use Bash::Merge::NodeWrapper
|
|
134
|
+
def wrap_child(child)
|
|
135
|
+
NodeWrapper.new(child, lines: @lines, source: @source)
|
|
237
136
|
end
|
|
238
137
|
|
|
239
|
-
private
|
|
240
|
-
|
|
241
138
|
def compute_signature(node)
|
|
242
139
|
node_type = node.type.to_s
|
|
243
140
|
|
|
@@ -289,6 +186,8 @@ module Bash
|
|
|
289
186
|
end
|
|
290
187
|
end
|
|
291
188
|
|
|
189
|
+
private
|
|
190
|
+
|
|
292
191
|
def extract_command_signature_context(node)
|
|
293
192
|
# Extract additional context like redirections
|
|
294
193
|
redirections = []
|
data/lib/bash/merge/version.rb
CHANGED
data/lib/bash/merge.rb
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
require "tree_haver"
|
|
3
|
+
# std libs
|
|
4
|
+
require "set"
|
|
6
5
|
|
|
6
|
+
# External gems
|
|
7
|
+
# TreeHaver provides a unified cross-Ruby interface to tree-sitter.
|
|
8
|
+
# It handles grammar discovery and backend selection automatically
|
|
9
|
+
# via parser_for(:bash). No manual registration needed.
|
|
10
|
+
#
|
|
7
11
|
# BACKEND COMPATIBILITY for Bash:
|
|
8
12
|
# - FFI: Most portable and reliable with bash grammar (recommended)
|
|
9
13
|
# - MRI: Has ABI incompatibility with bash grammar
|
|
@@ -12,24 +16,9 @@ require "tree_haver"
|
|
|
12
16
|
# Set TREE_HAVER_BACKEND=ffi (or mri/rust) to control backend selection.
|
|
13
17
|
# When MRI loads a grammar first, FFI gets incompatible pointers (symbol conflict).
|
|
14
18
|
# MRI statically links tree-sitter, FFI dynamically links libtree-sitter.so.
|
|
15
|
-
|
|
16
|
-
# Register tree-sitter bash grammar
|
|
17
|
-
bash_finder = TreeHaver::GrammarFinder.new(:bash)
|
|
18
|
-
bash_available = bash_finder.available?
|
|
19
|
-
bash_finder.register! if bash_available
|
|
20
|
-
|
|
21
|
-
# Only warn if the grammar file is actually missing (not just runtime unavailable)
|
|
22
|
-
# When the runtime isn't available, tree-sitter backends just won't be used,
|
|
23
|
-
# which is expected behavior - no need to warn the user.
|
|
24
|
-
unless bash_available
|
|
25
|
-
grammar_path = bash_finder.find_library_path
|
|
26
|
-
unless grammar_path
|
|
27
|
-
warn "WARNING: Bash grammar not available. #{bash_finder.not_found_message}"
|
|
28
|
-
end
|
|
29
|
-
end
|
|
19
|
+
require "tree_haver"
|
|
30
20
|
|
|
31
21
|
require "version_gem"
|
|
32
|
-
require "set"
|
|
33
22
|
|
|
34
23
|
# Shared merge infrastructure
|
|
35
24
|
require "ast/merge"
|
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: 1.0.
|
|
4
|
+
version: 1.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -46,7 +46,7 @@ dependencies:
|
|
|
46
46
|
version: '3.2'
|
|
47
47
|
- - ">="
|
|
48
48
|
- !ruby/object:Gem::Version
|
|
49
|
-
version: 3.2.
|
|
49
|
+
version: 3.2.3
|
|
50
50
|
type: :runtime
|
|
51
51
|
prerelease: false
|
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -56,7 +56,7 @@ dependencies:
|
|
|
56
56
|
version: '3.2'
|
|
57
57
|
- - ">="
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: 3.2.
|
|
59
|
+
version: 3.2.3
|
|
60
60
|
- !ruby/object:Gem::Dependency
|
|
61
61
|
name: ast-merge
|
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -66,7 +66,7 @@ dependencies:
|
|
|
66
66
|
version: '2.0'
|
|
67
67
|
- - ">="
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: 2.0.
|
|
69
|
+
version: 2.0.9
|
|
70
70
|
type: :runtime
|
|
71
71
|
prerelease: false
|
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -76,7 +76,7 @@ dependencies:
|
|
|
76
76
|
version: '2.0'
|
|
77
77
|
- - ">="
|
|
78
78
|
- !ruby/object:Gem::Version
|
|
79
|
-
version: 2.0.
|
|
79
|
+
version: 2.0.9
|
|
80
80
|
- !ruby/object:Gem::Dependency
|
|
81
81
|
name: version_gem
|
|
82
82
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -315,10 +315,10 @@ licenses:
|
|
|
315
315
|
- MIT
|
|
316
316
|
metadata:
|
|
317
317
|
homepage_uri: https://bash-merge.galtzo.com/
|
|
318
|
-
source_code_uri: https://github.com/kettle-rb/bash-merge/tree/v1.0.
|
|
319
|
-
changelog_uri: https://github.com/kettle-rb/bash-merge/blob/v1.0.
|
|
318
|
+
source_code_uri: https://github.com/kettle-rb/bash-merge/tree/v1.0.2
|
|
319
|
+
changelog_uri: https://github.com/kettle-rb/bash-merge/blob/v1.0.2/CHANGELOG.md
|
|
320
320
|
bug_tracker_uri: https://github.com/kettle-rb/bash-merge/issues
|
|
321
|
-
documentation_uri: https://www.rubydoc.info/gems/bash-merge/1.0.
|
|
321
|
+
documentation_uri: https://www.rubydoc.info/gems/bash-merge/1.0.2
|
|
322
322
|
funding_uri: https://github.com/sponsors/pboling
|
|
323
323
|
wiki_uri: https://github.com/kettle-rb/bash-merge/wiki
|
|
324
324
|
news_uri: https://www.railsbling.com/tags/bash-merge
|
metadata.gz.sig
CHANGED
|
Binary file
|