bash-merge 2.0.0 → 2.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 +1 -3
- data/CHANGELOG.md +25 -1
- data/README.md +35 -9
- data/lib/bash/merge/conflict_resolver.rb +47 -42
- data/lib/bash/merge/emitter.rb +34 -74
- data/lib/bash/merge/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +12 -12
- 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: c67a335db3b9d46652ca59793d480c4087bd88d4233070f0a6b4036a2902f136
|
|
4
|
+
data.tar.gz: a685d8c63ead508e3583eab6373d9cff3277b39c423315a3ad6aad77a3b5c9d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b32ddf1683fa6fc4ac1e9cfeef550416b54cf7d552eea9707642dd6176be1d7cb2fa4c6c8074770beccc5debbb8c850f53d45c56c8bdaa1208649bae302be820
|
|
7
|
+
data.tar.gz: bde6435c6ace02b852880ff8c0517e2e79ff03417ce64ef0ee764f1a9c0395fe87b0bdf992e1bc6088971f42ffaf506d8448e98fbff84fb1bc204b17cce79949
|
checksums.yaml.gz.sig
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,28 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [2.0.1] - 2026-01-09
|
|
34
|
+
|
|
35
|
+
- TAG: [v2.0.1][2.0.1t]
|
|
36
|
+
- COVERAGE: 96.34% -- 500/519 lines in 11 files
|
|
37
|
+
- BRANCH COVERAGE: 76.54% -- 124/162 branches in 11 files
|
|
38
|
+
- 96.33% documented
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- FFI backend isolation for test suite
|
|
43
|
+
- Added `bin/rspec-ffi` script to run FFI specs in isolation (before MRI backend loads)
|
|
44
|
+
- Added `spec/spec_ffi_helper.rb` for FFI-specific test configuration
|
|
45
|
+
- Updated Rakefile with `ffi_specs` and `remaining_specs` tasks
|
|
46
|
+
- The `:test` task now runs FFI specs first, then remaining specs
|
|
47
|
+
- Emitter-based output
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- ast-merge v3.1.0, adds Ast::Merge::EmitterBase
|
|
52
|
+
- tree_haver v4.0.4, adds error handling for FFI backend
|
|
53
|
+
- major spec refactor
|
|
54
|
+
|
|
33
55
|
## [2.0.0] - 2026-01-06
|
|
34
56
|
|
|
35
57
|
- TAG: [v2.0.0][2.0.0t]
|
|
@@ -85,7 +107,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
85
107
|
|
|
86
108
|
### Security
|
|
87
109
|
|
|
88
|
-
[Unreleased]: https://github.com/kettle-rb/bash-merge/compare/v2.0.
|
|
110
|
+
[Unreleased]: https://github.com/kettle-rb/bash-merge/compare/v2.0.1...HEAD
|
|
111
|
+
[2.0.1]: https://github.com/kettle-rb/bash-merge/compare/v2.0.0...v2.0.1
|
|
112
|
+
[2.0.1t]: https://github.com/kettle-rb/bash-merge/releases/tag/v2.0.1
|
|
89
113
|
[2.0.0]: https://github.com/kettle-rb/bash-merge/compare/v1.0.2...v2.0.0
|
|
90
114
|
[2.0.0t]: https://github.com/kettle-rb/bash-merge/releases/tag/v2.0.0
|
|
91
115
|
[1.0.2]: https://github.com/kettle-rb/bash-merge/compare/v1.0.1...v1.0.2
|
data/README.md
CHANGED
|
@@ -118,12 +118,36 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
|
|
|
118
118
|
| [rbs-merge][rbs-merge] | RBS | [tree-sitter-bash][ts-rbs] (via tree_haver), [RBS][rbs] (`rbs` std lib gem) | Smart merge for Ruby type signatures |
|
|
119
119
|
| [toml-merge][toml-merge] | TOML | [Citrus + toml-rb][toml-rb] (default, via tree_haver), [tree-sitter-toml][ts-toml] (via tree_haver) | Smart merge for TOML files |
|
|
120
120
|
|
|
121
|
+
#### Backend Platform Compatibility
|
|
122
|
+
|
|
123
|
+
tree_haver supports multiple parsing backends, but not all backends work on all Ruby platforms:
|
|
124
|
+
|
|
125
|
+
| Platform 👉️<br> TreeHaver Backend 👇️ | MRI | JRuby | TruffleRuby | Notes |
|
|
126
|
+
|------------------------------------------------|:---:|:-----:|:-----------:|-----------------------------------------------------|
|
|
127
|
+
| **MRI** ([ruby_tree_sitter][ruby_tree_sitter]) | ✅ | ❌ | ❌ | C extension, MRI only |
|
|
128
|
+
| **Rust** ([tree_stump][tree_stump]) | ✅ | ❌ | ❌ | Rust extension via magnus/rb-sys, MRI only |
|
|
129
|
+
| **FFI** | ✅ | ✅ | ❌ | TruffleRuby's FFI doesn't support `STRUCT_BY_VALUE` |
|
|
130
|
+
| **Java** ([jtreesitter][jtreesitter]) | ❌ | ✅ | ❌ | JRuby only, requires grammar JARs |
|
|
131
|
+
| **Prism** | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
|
|
132
|
+
| **Psych** | ✅ | ✅ | ✅ | YAML parsing, stdlib |
|
|
133
|
+
| **Citrus** | ✅ | ✅ | ✅ | Pure Ruby, no native dependencies |
|
|
134
|
+
| **Commonmarker** | ✅ | ❌ | ❓ | Rust extension for Markdown |
|
|
135
|
+
| **Markly** | ✅ | ❌ | ❓ | C extension for Markdown |
|
|
136
|
+
|
|
137
|
+
**Legend**: ✅ = Works, ❌ = Does not work, ❓ = Untested
|
|
138
|
+
|
|
139
|
+
**Why some backends don't work on certain platforms**:
|
|
140
|
+
|
|
141
|
+
- **JRuby**: Runs on the JVM; cannot load native C/Rust extensions (`.so` files)
|
|
142
|
+
- **TruffleRuby**: Has C API emulation via Sulong/LLVM, but it doesn't expose all MRI internals that native extensions require (e.g., `RBasic.flags`, `rb_gc_writebarrier`)
|
|
143
|
+
- **FFI on TruffleRuby**: TruffleRuby's FFI implementation doesn't support returning structs by value, which tree-sitter's C API requires
|
|
144
|
+
|
|
121
145
|
**Example implementations** for the gem templating use case:
|
|
122
146
|
|
|
123
|
-
| Gem
|
|
124
|
-
|
|
125
|
-
| [kettle-dev]
|
|
126
|
-
| [kettle-jem]
|
|
147
|
+
| Gem | Purpose | Description |
|
|
148
|
+
|--------------------------|-----------------|-----------------------------------------------|
|
|
149
|
+
| [kettle-dev][kettle-dev] | Gem Development | Gem templating tool using `*-merge` gems |
|
|
150
|
+
| [kettle-jem][kettle-jem] | Gem Templating | Gem template library with smart merge support |
|
|
127
151
|
|
|
128
152
|
[tree_haver]: https://github.com/kettle-rb/tree_haver
|
|
129
153
|
[ast-merge]: https://github.com/kettle-rb/ast-merge
|
|
@@ -143,16 +167,18 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
|
|
|
143
167
|
[prism]: https://github.com/ruby/prism
|
|
144
168
|
[psych]: https://github.com/ruby/psych
|
|
145
169
|
[ts-json]: https://github.com/tree-sitter/tree-sitter-json
|
|
170
|
+
[ts-jsonc]: https://gitlab.com/WhyNotHugo/tree-sitter-jsonc
|
|
146
171
|
[ts-bash]: https://github.com/tree-sitter/tree-sitter-bash
|
|
172
|
+
[ts-rbs]: https://github.com/joker1007/tree-sitter-rbs
|
|
147
173
|
[ts-toml]: https://github.com/tree-sitter-grammars/tree-sitter-toml
|
|
174
|
+
[dotenv]: https://github.com/bkeepers/dotenv
|
|
148
175
|
[rbs]: https://github.com/ruby/rbs
|
|
149
176
|
[toml-rb]: https://github.com/emancu/toml-rb
|
|
150
177
|
[markly]: https://github.com/ioquatix/markly
|
|
151
178
|
[commonmarker]: https://github.com/gjtorikian/commonmarker
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
[
|
|
155
|
-
[dotenv]: https://github.com/bkeepers/dotenv
|
|
179
|
+
[ruby_tree_sitter]: https://github.com/Faveod/ruby-tree-sitter
|
|
180
|
+
[tree_stump]: https://github.com/joker1007/tree_stump
|
|
181
|
+
[jtreesitter]: https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter
|
|
156
182
|
|
|
157
183
|
## 💡 Info you can shake a stick at
|
|
158
184
|
|
|
@@ -877,7 +903,7 @@ Thanks for RTFM. ☺️
|
|
|
877
903
|
[📌gitmoji]: https://gitmoji.dev
|
|
878
904
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
879
905
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
880
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.
|
|
906
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.519-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
881
907
|
[🔐security]: SECURITY.md
|
|
882
908
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
883
909
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -9,9 +9,6 @@ module Bash
|
|
|
9
9
|
# resolver = ConflictResolver.new(template_analysis, dest_analysis)
|
|
10
10
|
# resolver.resolve(result)
|
|
11
11
|
class ConflictResolver < ::Ast::Merge::ConflictResolverBase
|
|
12
|
-
# Alias for backward compatibility with existing API
|
|
13
|
-
alias_method :preference, :preference
|
|
14
|
-
|
|
15
12
|
# Creates a new ConflictResolver
|
|
16
13
|
#
|
|
17
14
|
# @param template_analysis [FileAnalysis] Analyzed template file
|
|
@@ -33,6 +30,7 @@ module Bash
|
|
|
33
30
|
match_refiner: match_refiner,
|
|
34
31
|
**options
|
|
35
32
|
)
|
|
33
|
+
@emitter = Emitter.new
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
# Resolve conflicts and populate the result
|
|
@@ -43,6 +41,9 @@ module Bash
|
|
|
43
41
|
template_nodes = @template_analysis.nodes
|
|
44
42
|
dest_nodes = @dest_analysis.nodes
|
|
45
43
|
|
|
44
|
+
# Clear emitter for fresh merge
|
|
45
|
+
@emitter.clear
|
|
46
|
+
|
|
46
47
|
# Build signature maps
|
|
47
48
|
template_by_sig = build_signature_map(template_nodes, @template_analysis)
|
|
48
49
|
dest_by_sig = build_signature_map(dest_nodes, @dest_analysis)
|
|
@@ -51,17 +52,24 @@ module Bash
|
|
|
51
52
|
processed_template_sigs = ::Set.new
|
|
52
53
|
processed_dest_sigs = ::Set.new
|
|
53
54
|
|
|
54
|
-
# Process nodes
|
|
55
|
-
|
|
55
|
+
# Process nodes via emitter
|
|
56
|
+
merge_nodes_to_emitter(
|
|
56
57
|
template_nodes,
|
|
57
58
|
dest_nodes,
|
|
58
59
|
template_by_sig,
|
|
59
60
|
dest_by_sig,
|
|
60
61
|
processed_template_sigs,
|
|
61
62
|
processed_dest_sigs,
|
|
62
|
-
result,
|
|
63
63
|
)
|
|
64
64
|
|
|
65
|
+
# Transfer emitter output to result
|
|
66
|
+
emitted_content = @emitter.to_s
|
|
67
|
+
unless emitted_content.empty?
|
|
68
|
+
emitted_content.lines.each do |line|
|
|
69
|
+
result.add_line(line.chomp, decision: MergeResult::DECISION_MERGED, source: :merged)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
65
73
|
DebugLogger.debug("Conflict resolution complete", {
|
|
66
74
|
template_nodes: template_nodes.size,
|
|
67
75
|
dest_nodes: dest_nodes.size,
|
|
@@ -72,18 +80,14 @@ module Bash
|
|
|
72
80
|
|
|
73
81
|
private
|
|
74
82
|
|
|
75
|
-
def
|
|
76
|
-
# Determine the output order based on preference
|
|
77
|
-
# We'll iterate through destination nodes first (to preserve dest order for matches)
|
|
78
|
-
# then add any template-only nodes if configured
|
|
79
|
-
|
|
83
|
+
def merge_nodes_to_emitter(template_nodes, dest_nodes, template_by_sig, dest_by_sig, processed_template_sigs, processed_dest_sigs)
|
|
80
84
|
# First pass: Process destination nodes and find matches
|
|
81
85
|
dest_nodes.each do |dest_node|
|
|
82
86
|
dest_sig = @dest_analysis.generate_signature(dest_node)
|
|
83
87
|
|
|
84
88
|
# Freeze blocks from destination are always preserved
|
|
85
89
|
if freeze_node?(dest_node)
|
|
86
|
-
|
|
90
|
+
emit_freeze_block(dest_node)
|
|
87
91
|
processed_dest_sigs << dest_sig if dest_sig
|
|
88
92
|
next
|
|
89
93
|
end
|
|
@@ -93,18 +97,18 @@ module Bash
|
|
|
93
97
|
template_info = template_by_sig[dest_sig].first
|
|
94
98
|
template_node = template_info[:node]
|
|
95
99
|
|
|
96
|
-
# Decide which to
|
|
100
|
+
# Decide which to emit based on preference
|
|
97
101
|
if @preference == :destination
|
|
98
|
-
|
|
102
|
+
emit_node(dest_node, @dest_analysis)
|
|
99
103
|
else
|
|
100
|
-
|
|
104
|
+
emit_node(template_node, @template_analysis)
|
|
101
105
|
end
|
|
102
106
|
|
|
103
107
|
processed_dest_sigs << dest_sig
|
|
104
108
|
processed_template_sigs << dest_sig
|
|
105
109
|
else
|
|
106
110
|
# Destination-only node - always keep
|
|
107
|
-
|
|
111
|
+
emit_node(dest_node, @dest_analysis)
|
|
108
112
|
processed_dest_sigs << dest_sig if dest_sig
|
|
109
113
|
end
|
|
110
114
|
end
|
|
@@ -118,43 +122,44 @@ module Bash
|
|
|
118
122
|
# Skip if already processed (matched with dest)
|
|
119
123
|
next if template_sig && processed_template_sigs.include?(template_sig)
|
|
120
124
|
|
|
121
|
-
# Skip freeze blocks from template
|
|
125
|
+
# Skip freeze blocks from template
|
|
122
126
|
next if freeze_node?(template_node)
|
|
123
127
|
|
|
124
128
|
# Add template-only node
|
|
125
|
-
|
|
129
|
+
emit_node(template_node, @template_analysis)
|
|
126
130
|
processed_template_sigs << template_sig if template_sig
|
|
127
131
|
end
|
|
128
132
|
end
|
|
129
133
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
# Emit a single node to the emitter
|
|
135
|
+
# @param node [NodeWrapper] Node to emit
|
|
136
|
+
# @param analysis [FileAnalysis] Analysis for accessing source
|
|
137
|
+
def emit_node(node, analysis)
|
|
138
|
+
return if freeze_node?(node)
|
|
139
|
+
|
|
140
|
+
# Emit leading comments
|
|
141
|
+
if node.start_line
|
|
142
|
+
leading = analysis.comment_tracker.leading_comments_before(node.start_line)
|
|
143
|
+
leading.each do |comment|
|
|
144
|
+
@emitter.emit_tracked_comment(comment)
|
|
145
|
+
end
|
|
137
146
|
end
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def add_wrapper_to_result(wrapper, result, source, decision)
|
|
141
|
-
return unless wrapper.start_line && wrapper.end_line
|
|
142
147
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
# Emit the node content
|
|
149
|
+
if node.start_line && node.end_line
|
|
150
|
+
lines = []
|
|
151
|
+
(node.start_line..node.end_line).each do |line_num|
|
|
152
|
+
line = analysis.line_at(line_num)
|
|
153
|
+
lines << line if line
|
|
154
|
+
end
|
|
155
|
+
@emitter.emit_raw_lines(lines)
|
|
149
156
|
end
|
|
157
|
+
end
|
|
150
158
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
result.add_line(line.chomp, decision: decision, source: source, original_line: line_num)
|
|
157
|
-
end
|
|
159
|
+
# Emit a freeze block
|
|
160
|
+
# @param freeze_node [FreezeNode] Freeze block to emit
|
|
161
|
+
def emit_freeze_block(freeze_node)
|
|
162
|
+
@emitter.emit_raw_lines(freeze_node.lines)
|
|
158
163
|
end
|
|
159
164
|
end
|
|
160
165
|
end
|
data/lib/bash/merge/emitter.rb
CHANGED
|
@@ -6,27 +6,28 @@ module Bash
|
|
|
6
6
|
# This class provides utilities for emitting Bash while maintaining
|
|
7
7
|
# the original structure, comments, and style choices.
|
|
8
8
|
#
|
|
9
|
+
# Inherits common emitter functionality from Ast::Merge::EmitterBase.
|
|
10
|
+
#
|
|
9
11
|
# @example Basic usage
|
|
10
12
|
# emitter = Emitter.new
|
|
11
13
|
# emitter.emit_comment("This is a comment")
|
|
12
14
|
# emitter.emit_line("echo 'hello'")
|
|
13
|
-
class Emitter
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
attr_reader :indent_level
|
|
15
|
+
class Emitter < Ast::Merge::EmitterBase
|
|
16
|
+
# Initialize subclass-specific state
|
|
17
|
+
def initialize_subclass_state(**options)
|
|
18
|
+
# Bash doesn't need separator tracking like JSON
|
|
19
|
+
end
|
|
19
20
|
|
|
20
|
-
#
|
|
21
|
-
|
|
21
|
+
# Clear subclass-specific state
|
|
22
|
+
def clear_subclass_state
|
|
23
|
+
# Nothing to clear for Bash
|
|
24
|
+
end
|
|
22
25
|
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@lines
|
|
28
|
-
@indent_level = 0
|
|
29
|
-
@indent_size = indent_size
|
|
26
|
+
# Emit a tracked comment from CommentTracker
|
|
27
|
+
# @param comment [Hash] Comment with :text, :indent
|
|
28
|
+
def emit_tracked_comment(comment)
|
|
29
|
+
indent = " " * (comment[:indent] || 0)
|
|
30
|
+
@lines << "#{indent}# #{comment[:text]}"
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
# Emit a comment line
|
|
@@ -44,22 +45,6 @@ module Bash
|
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
|
|
47
|
-
# Emit leading comments
|
|
48
|
-
#
|
|
49
|
-
# @param comments [Array<Hash>] Comment hashes from CommentTracker
|
|
50
|
-
def emit_leading_comments(comments)
|
|
51
|
-
comments.each do |comment|
|
|
52
|
-
# Preserve original indentation from comment
|
|
53
|
-
indent = " " * (comment[:indent] || 0)
|
|
54
|
-
@lines << "#{indent}# #{comment[:text]}"
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Emit a blank line
|
|
59
|
-
def emit_blank_line
|
|
60
|
-
@lines << ""
|
|
61
|
-
end
|
|
62
|
-
|
|
63
48
|
# Emit a shebang line
|
|
64
49
|
#
|
|
65
50
|
# @param interpreter [String] Interpreter path (e.g., "/bin/bash")
|
|
@@ -85,12 +70,12 @@ module Bash
|
|
|
85
70
|
# @param name [String] Function name
|
|
86
71
|
def emit_function_start(name)
|
|
87
72
|
@lines << "#{current_indent}#{name}() {"
|
|
88
|
-
|
|
73
|
+
indent
|
|
89
74
|
end
|
|
90
75
|
|
|
91
76
|
# Emit a function definition end
|
|
92
77
|
def emit_function_end
|
|
93
|
-
|
|
78
|
+
dedent
|
|
94
79
|
@lines << "#{current_indent}}"
|
|
95
80
|
end
|
|
96
81
|
|
|
@@ -99,28 +84,28 @@ module Bash
|
|
|
99
84
|
# @param condition [String] Condition expression
|
|
100
85
|
def emit_if_start(condition)
|
|
101
86
|
@lines << "#{current_indent}if #{condition}; then"
|
|
102
|
-
|
|
87
|
+
indent
|
|
103
88
|
end
|
|
104
89
|
|
|
105
90
|
# Emit an elif clause
|
|
106
91
|
#
|
|
107
92
|
# @param condition [String] Condition expression
|
|
108
93
|
def emit_elif(condition)
|
|
109
|
-
|
|
94
|
+
dedent
|
|
110
95
|
@lines << "#{current_indent}elif #{condition}; then"
|
|
111
|
-
|
|
96
|
+
indent
|
|
112
97
|
end
|
|
113
98
|
|
|
114
99
|
# Emit an else clause
|
|
115
100
|
def emit_else
|
|
116
|
-
|
|
101
|
+
dedent
|
|
117
102
|
@lines << "#{current_indent}else"
|
|
118
|
-
|
|
103
|
+
indent
|
|
119
104
|
end
|
|
120
105
|
|
|
121
106
|
# Emit an if statement end
|
|
122
107
|
def emit_fi
|
|
123
|
-
|
|
108
|
+
dedent
|
|
124
109
|
@lines << "#{current_indent}fi"
|
|
125
110
|
end
|
|
126
111
|
|
|
@@ -130,12 +115,12 @@ module Bash
|
|
|
130
115
|
# @param items [String] Items to iterate over
|
|
131
116
|
def emit_for_start(var, items)
|
|
132
117
|
@lines << "#{current_indent}for #{var} in #{items}; do"
|
|
133
|
-
|
|
118
|
+
indent
|
|
134
119
|
end
|
|
135
120
|
|
|
136
|
-
# Emit a for loop end
|
|
121
|
+
# Emit a for/while loop end
|
|
137
122
|
def emit_done
|
|
138
|
-
|
|
123
|
+
dedent
|
|
139
124
|
@lines << "#{current_indent}done"
|
|
140
125
|
end
|
|
141
126
|
|
|
@@ -144,7 +129,7 @@ module Bash
|
|
|
144
129
|
# @param condition [String] Condition expression
|
|
145
130
|
def emit_while_start(condition)
|
|
146
131
|
@lines << "#{current_indent}while #{condition}; do"
|
|
147
|
-
|
|
132
|
+
indent
|
|
148
133
|
end
|
|
149
134
|
|
|
150
135
|
# Emit a case statement start
|
|
@@ -152,7 +137,7 @@ module Bash
|
|
|
152
137
|
# @param expression [String] Expression to match
|
|
153
138
|
def emit_case_start(expression)
|
|
154
139
|
@lines << "#{current_indent}case #{expression} in"
|
|
155
|
-
|
|
140
|
+
indent
|
|
156
141
|
end
|
|
157
142
|
|
|
158
143
|
# Emit a case pattern
|
|
@@ -160,18 +145,18 @@ module Bash
|
|
|
160
145
|
# @param pattern [String] Pattern to match
|
|
161
146
|
def emit_case_pattern(pattern)
|
|
162
147
|
@lines << "#{current_indent}#{pattern})"
|
|
163
|
-
|
|
148
|
+
indent
|
|
164
149
|
end
|
|
165
150
|
|
|
166
151
|
# Emit a case pattern terminator
|
|
167
152
|
def emit_case_pattern_end
|
|
168
|
-
|
|
153
|
+
dedent
|
|
169
154
|
@lines << "#{current_indent};;"
|
|
170
155
|
end
|
|
171
156
|
|
|
172
157
|
# Emit a case statement end
|
|
173
158
|
def emit_esac
|
|
174
|
-
|
|
159
|
+
dedent
|
|
175
160
|
@lines << "#{current_indent}esac"
|
|
176
161
|
end
|
|
177
162
|
|
|
@@ -182,36 +167,11 @@ module Bash
|
|
|
182
167
|
@lines << "#{current_indent}#{line}"
|
|
183
168
|
end
|
|
184
169
|
|
|
185
|
-
#
|
|
186
|
-
#
|
|
187
|
-
# @param raw_lines [Array<String>] Lines to emit as-is
|
|
188
|
-
def emit_raw_lines(raw_lines)
|
|
189
|
-
raw_lines.each { |line| @lines << line.chomp }
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
# Get the output as a single string
|
|
170
|
+
# Get the output as a Bash string
|
|
193
171
|
#
|
|
194
172
|
# @return [String]
|
|
195
173
|
def to_bash
|
|
196
|
-
|
|
197
|
-
content += "\n" unless content.empty? || content.end_with?("\n")
|
|
198
|
-
content
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
# Alias for consistency with other merge gems
|
|
202
|
-
# @return [String]
|
|
203
|
-
alias_method :to_s, :to_bash
|
|
204
|
-
|
|
205
|
-
# Clear the output
|
|
206
|
-
def clear
|
|
207
|
-
@lines = []
|
|
208
|
-
@indent_level = 0
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
private
|
|
212
|
-
|
|
213
|
-
def current_indent
|
|
214
|
-
" " * (@indent_level * @indent_size)
|
|
174
|
+
to_s
|
|
215
175
|
end
|
|
216
176
|
end
|
|
217
177
|
end
|
data/lib/bash/merge/version.rb
CHANGED
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: 2.0.
|
|
4
|
+
version: 2.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -43,40 +43,40 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '
|
|
46
|
+
version: '4.0'
|
|
47
47
|
- - ">="
|
|
48
48
|
- !ruby/object:Gem::Version
|
|
49
|
-
version:
|
|
49
|
+
version: 4.0.4
|
|
50
50
|
type: :runtime
|
|
51
51
|
prerelease: false
|
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
53
53
|
requirements:
|
|
54
54
|
- - "~>"
|
|
55
55
|
- !ruby/object:Gem::Version
|
|
56
|
-
version: '
|
|
56
|
+
version: '4.0'
|
|
57
57
|
- - ">="
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
|
-
version:
|
|
59
|
+
version: 4.0.4
|
|
60
60
|
- !ruby/object:Gem::Dependency
|
|
61
61
|
name: ast-merge
|
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
|
63
63
|
requirements:
|
|
64
64
|
- - "~>"
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: '3.
|
|
66
|
+
version: '3.1'
|
|
67
67
|
- - ">="
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: 3.
|
|
69
|
+
version: 3.1.0
|
|
70
70
|
type: :runtime
|
|
71
71
|
prerelease: false
|
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
|
73
73
|
requirements:
|
|
74
74
|
- - "~>"
|
|
75
75
|
- !ruby/object:Gem::Version
|
|
76
|
-
version: '3.
|
|
76
|
+
version: '3.1'
|
|
77
77
|
- - ">="
|
|
78
78
|
- !ruby/object:Gem::Version
|
|
79
|
-
version: 3.
|
|
79
|
+
version: 3.1.0
|
|
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/v2.0.
|
|
319
|
-
changelog_uri: https://github.com/kettle-rb/bash-merge/blob/v2.0.
|
|
318
|
+
source_code_uri: https://github.com/kettle-rb/bash-merge/tree/v2.0.1
|
|
319
|
+
changelog_uri: https://github.com/kettle-rb/bash-merge/blob/v2.0.1/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/2.0.
|
|
321
|
+
documentation_uri: https://www.rubydoc.info/gems/bash-merge/2.0.1
|
|
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
|