kettle-dev 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.rubocop_rspec.yml +3 -0
- data/CHANGELOG.md +19 -1
- data/README.md +1 -1
- data/README.md.example +1 -1
- data/Rakefile.example +1 -1
- data/kettle-dev.gemspec.example +3 -3
- data/lib/kettle/dev/source_merger.rb +208 -44
- data/lib/kettle/dev/version.rb +1 -1
- 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: cad2d78d297d0e69cd016624ff87dba0c5fa4bd3af5399d7c97c4e8fcc2af82a
|
|
4
|
+
data.tar.gz: '08f58025922178025f79d3ef3004b35f9207e23764c490587ec3ed5dfc240ca5'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 12563697c8b719fc13ded6b096fcd92266dbb98f9f8c87a21aad756bebbe2065f7dc17e2be982d1a3765a15c8c3b8cbd0eec88642fc7fb90600e1be88c4db149
|
|
7
|
+
data.tar.gz: e3ce95406792e64d08da4db003a5771c45c975155c417176e10972e13ad0e012ed006aa9193b81b1fbecc96d59edb752cba80a26a538c60f824c52228e6110e9
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/.rubocop_rspec.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,22 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [1.2.3] - 2025-11-28
|
|
34
|
+
|
|
35
|
+
- TAG: [v1.2.3][1.2.3t]
|
|
36
|
+
- COVERAGE: 93.43% -- 4681/5010 lines in 31 files
|
|
37
|
+
- BRANCH COVERAGE: 76.63% -- 1912/2495 branches in 31 files
|
|
38
|
+
- 70.55% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Fixed Gemfile parsing to properly deduplicate comments across multiple template runs
|
|
43
|
+
- Implemented two-pass comment deduplication: sequences first, then individual lines
|
|
44
|
+
- Magic comments (frozen_string_literal, encoding, etc.) are now properly deduplicated by content, not line position
|
|
45
|
+
- File-level comments are deduplicated while preserving leading comments attached to statements
|
|
46
|
+
- Ensures idempotent behavior when running templating multiple times on the same file
|
|
47
|
+
- Prevents accumulation of duplicate frozen_string_literal comments and comment blocks
|
|
48
|
+
|
|
33
49
|
## [1.2.2] - 2025-11-27
|
|
34
50
|
|
|
35
51
|
- TAG: [v1.2.2][1.2.2t]
|
|
@@ -1491,7 +1507,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
1491
1507
|
- Selecting will run the selected workflow via `act`
|
|
1492
1508
|
- This may move to its own gem in the future.
|
|
1493
1509
|
|
|
1494
|
-
[Unreleased]: https://github.com/kettle-rb/kettle-dev/compare/v1.2.
|
|
1510
|
+
[Unreleased]: https://github.com/kettle-rb/kettle-dev/compare/v1.2.3...HEAD
|
|
1511
|
+
[1.2.3]: https://github.com/kettle-rb/kettle-dev/compare/v1.2.2...v1.2.3
|
|
1512
|
+
[1.2.3t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v1.2.3
|
|
1495
1513
|
[1.2.2]: https://github.com/kettle-rb/kettle-dev/compare/v1.2.1...v1.2.2
|
|
1496
1514
|
[1.2.2t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v1.2.2
|
|
1497
1515
|
[1.2.0]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.60...v1.2.0
|
data/README.md
CHANGED
|
@@ -1026,7 +1026,7 @@ Thanks for RTFM. ☺️
|
|
|
1026
1026
|
[📌gitmoji]: https://gitmoji.dev
|
|
1027
1027
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1028
1028
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1029
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-
|
|
1029
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-5.010-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1030
1030
|
[🔐security]: SECURITY.md
|
|
1031
1031
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1032
1032
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/README.md.example
CHANGED
|
@@ -548,7 +548,7 @@ Thanks for RTFM. ☺️
|
|
|
548
548
|
[📌gitmoji]: https://gitmoji.dev
|
|
549
549
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
550
550
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
551
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-
|
|
551
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-5.010-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
552
552
|
[🔐security]: SECURITY.md
|
|
553
553
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
554
554
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/Rakefile.example
CHANGED
data/kettle-dev.gemspec.example
CHANGED
|
@@ -114,10 +114,10 @@ Gem::Specification.new do |spec|
|
|
|
114
114
|
# and preferably a modular one (see gemfiles/modular/*.gemfile).
|
|
115
115
|
|
|
116
116
|
# Dev, Test, & Release Tasks
|
|
117
|
-
spec.add_development_dependency("{KETTLE|DEV|GEM}", "~> 1.
|
|
117
|
+
spec.add_development_dependency("{KETTLE|DEV|GEM}", "~> 1.2") # ruby >= 2.3.0
|
|
118
118
|
|
|
119
119
|
# Security
|
|
120
|
-
spec.add_development_dependency("bundler-audit", "~> 0.9.
|
|
120
|
+
spec.add_development_dependency("bundler-audit", "~> 0.9.3") # ruby >= 2.0.0
|
|
121
121
|
|
|
122
122
|
# Tasks
|
|
123
123
|
spec.add_development_dependency("rake", "~> 13.0") # ruby >= 2.2.0
|
|
@@ -131,7 +131,7 @@ Gem::Specification.new do |spec|
|
|
|
131
131
|
|
|
132
132
|
# Releasing
|
|
133
133
|
spec.add_development_dependency("ruby-progressbar", "~> 1.13") # ruby >= 0
|
|
134
|
-
spec.add_development_dependency("stone_checksums", "~> 1.0", ">= 1.0.
|
|
134
|
+
spec.add_development_dependency("stone_checksums", "~> 1.0", ">= 1.0.3") # ruby >= 2.2.0
|
|
135
135
|
|
|
136
136
|
# Git integration (optional)
|
|
137
137
|
# The 'git' gem is optional; kettle-dev falls back to shelling out to `git` if it is not present.
|
|
@@ -48,7 +48,7 @@ module Kettle
|
|
|
48
48
|
content =
|
|
49
49
|
case strategy
|
|
50
50
|
when :skip
|
|
51
|
-
src_with_reminder
|
|
51
|
+
normalize_source(src_with_reminder)
|
|
52
52
|
when :replace
|
|
53
53
|
normalize_source(src_with_reminder)
|
|
54
54
|
when :append
|
|
@@ -81,17 +81,22 @@ module Kettle
|
|
|
81
81
|
[before, snippet, after].join
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
# Normalize source code
|
|
84
|
+
# Normalize source code by parsing and rebuilding to deduplicate comments
|
|
85
85
|
#
|
|
86
86
|
# @param source [String] Ruby source code
|
|
87
|
-
# @return [String] Normalized source with trailing newline
|
|
87
|
+
# @return [String] Normalized source with trailing newline and deduplicated comments
|
|
88
88
|
# @api private
|
|
89
89
|
def normalize_source(source)
|
|
90
90
|
parse_result = PrismUtils.parse_with_comments(source)
|
|
91
91
|
return ensure_trailing_newline(source) unless parse_result.success?
|
|
92
92
|
|
|
93
|
-
#
|
|
94
|
-
|
|
93
|
+
# Extract and deduplicate comments
|
|
94
|
+
magic_comments = extract_magic_comments(parse_result)
|
|
95
|
+
file_leading_comments = extract_file_leading_comments(parse_result)
|
|
96
|
+
node_infos = extract_nodes_with_comments(parse_result)
|
|
97
|
+
|
|
98
|
+
# Rebuild source with deduplicated comments
|
|
99
|
+
build_source_from_nodes(node_infos, magic_comments: magic_comments, file_leading_comments: file_leading_comments)
|
|
95
100
|
end
|
|
96
101
|
|
|
97
102
|
def reminder_present?(content)
|
|
@@ -231,8 +236,8 @@ module Kettle
|
|
|
231
236
|
end
|
|
232
237
|
|
|
233
238
|
def prism_merge(src_content, dest_content)
|
|
234
|
-
src_result = PrismUtils.parse_with_comments(src_content)
|
|
235
|
-
dest_result = PrismUtils.parse_with_comments(dest_content)
|
|
239
|
+
src_result = Kettle::Dev::PrismUtils.parse_with_comments(src_content)
|
|
240
|
+
dest_result = Kettle::Dev::PrismUtils.parse_with_comments(dest_content)
|
|
236
241
|
|
|
237
242
|
# If src parsing failed, return src unchanged to avoid losing content
|
|
238
243
|
unless src_result.success?
|
|
@@ -245,11 +250,48 @@ module Kettle
|
|
|
245
250
|
|
|
246
251
|
merged_nodes = yield(src_nodes, dest_nodes, src_result, dest_result)
|
|
247
252
|
|
|
248
|
-
# Extract
|
|
249
|
-
|
|
253
|
+
# Extract and deduplicate comments from src and dest SEPARATELY
|
|
254
|
+
# This allows sequence detection to work within each source
|
|
255
|
+
src_tuples = create_comment_tuples(src_result)
|
|
256
|
+
src_deduplicated = deduplicate_comment_sequences(src_tuples)
|
|
257
|
+
|
|
258
|
+
dest_tuples = dest_result.success? ? create_comment_tuples(dest_result) : []
|
|
259
|
+
dest_deduplicated = deduplicate_comment_sequences(dest_tuples)
|
|
260
|
+
|
|
261
|
+
# Now merge the deduplicated tuples by hash+type only (ignore line numbers)
|
|
262
|
+
seen_hash_type = Set.new
|
|
263
|
+
final_tuples = []
|
|
264
|
+
|
|
265
|
+
# Add all deduplicated src tuples
|
|
266
|
+
src_deduplicated.each do |tuple|
|
|
267
|
+
hash_val = tuple[0]
|
|
268
|
+
type = tuple[1]
|
|
269
|
+
key = [hash_val, type]
|
|
270
|
+
unless seen_hash_type.include?(key)
|
|
271
|
+
final_tuples << tuple
|
|
272
|
+
seen_hash_type << key
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Add deduplicated dest tuples that don't duplicate src (by hash+type)
|
|
277
|
+
dest_deduplicated.each do |tuple|
|
|
278
|
+
hash_val = tuple[0]
|
|
279
|
+
type = tuple[1]
|
|
280
|
+
key = [hash_val, type]
|
|
281
|
+
unless seen_hash_type.include?(key)
|
|
282
|
+
final_tuples << tuple
|
|
283
|
+
seen_hash_type << key
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Extract magic and file-level comments from final merged tuples
|
|
288
|
+
magic_comments = final_tuples
|
|
289
|
+
.select { |tuple| tuple[1] == :magic }
|
|
290
|
+
.map { |tuple| tuple[2] }
|
|
250
291
|
|
|
251
|
-
|
|
252
|
-
|
|
292
|
+
file_leading_comments = final_tuples
|
|
293
|
+
.select { |tuple| tuple[1] == :file_level }
|
|
294
|
+
.map { |tuple| tuple[2] }
|
|
253
295
|
|
|
254
296
|
build_source_from_nodes(merged_nodes, magic_comments: magic_comments, file_leading_comments: file_leading_comments)
|
|
255
297
|
end
|
|
@@ -257,45 +299,155 @@ module Kettle
|
|
|
257
299
|
def extract_magic_comments(parse_result)
|
|
258
300
|
return [] unless parse_result.success?
|
|
259
301
|
|
|
260
|
-
|
|
261
|
-
|
|
302
|
+
tuples = create_comment_tuples(parse_result)
|
|
303
|
+
deduplicated = deduplicate_comment_sequences(tuples)
|
|
262
304
|
|
|
263
|
-
#
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
305
|
+
# Filter to only magic comments and return their text
|
|
306
|
+
deduplicated
|
|
307
|
+
.select { |tuple| tuple[1] == :magic }
|
|
308
|
+
.map { |tuple| tuple[2] }
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# Create a tuple for each comment: [hash, type, text, line_number]
|
|
312
|
+
# where type is one of: :magic, :file_level, :leading
|
|
313
|
+
# (inline comments are handled with their associated statements)
|
|
314
|
+
def create_comment_tuples(parse_result)
|
|
315
|
+
return [] unless parse_result.success?
|
|
316
|
+
|
|
317
|
+
statements = PrismUtils.extract_statements(parse_result.value.statements)
|
|
318
|
+
first_stmt_line = statements.any? ? statements.first.location.start_line : Float::INFINITY
|
|
319
|
+
|
|
320
|
+
tuples = []
|
|
321
|
+
|
|
322
|
+
parse_result.comments.each do |comment|
|
|
323
|
+
comment_line = comment.location.start_line
|
|
324
|
+
comment_text = comment.slice.strip
|
|
325
|
+
|
|
326
|
+
# Determine comment type - magic comments are identified by content, not line number
|
|
327
|
+
type = if is_magic_comment?(comment_text)
|
|
328
|
+
:magic
|
|
329
|
+
elsif comment_line < first_stmt_line
|
|
330
|
+
:file_level
|
|
331
|
+
else
|
|
332
|
+
# This will be handled as a leading or inline comment for a statement
|
|
333
|
+
:leading
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# Create hash from normalized comment text (ignoring trailing whitespace)
|
|
337
|
+
comment_hash = comment_text.hash
|
|
338
|
+
|
|
339
|
+
tuples << [comment_hash, type, comment.slice.rstrip, comment_line]
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
tuples
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def is_magic_comment?(text)
|
|
346
|
+
text.include?("frozen_string_literal:") ||
|
|
347
|
+
text.include?("encoding:") ||
|
|
348
|
+
text.include?("warn_indent:") ||
|
|
349
|
+
text.include?("shareable_constant_value:")
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Two-pass deduplication:
|
|
353
|
+
# Pass 1: Deduplicate multi-line sequences
|
|
354
|
+
# Pass 2: Deduplicate single-line duplicates
|
|
355
|
+
def deduplicate_comment_sequences(tuples)
|
|
356
|
+
return [] if tuples.empty?
|
|
357
|
+
|
|
358
|
+
# Group tuples by type
|
|
359
|
+
by_type = tuples.group_by { |tuple| tuple[1] }
|
|
360
|
+
|
|
361
|
+
result = []
|
|
362
|
+
|
|
363
|
+
[:magic, :file_level, :leading].each do |type|
|
|
364
|
+
type_tuples = by_type[type] || []
|
|
365
|
+
next if type_tuples.empty?
|
|
366
|
+
|
|
367
|
+
# Pass 1: Remove duplicate sequences
|
|
368
|
+
after_pass1 = deduplicate_sequences_pass1(type_tuples)
|
|
369
|
+
|
|
370
|
+
# Pass 2: Remove single-line duplicates
|
|
371
|
+
after_pass2 = deduplicate_singles_pass2(after_pass1)
|
|
372
|
+
|
|
373
|
+
result.concat(after_pass2)
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
result
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# Pass 1: Find and remove duplicate multi-line comment sequences
|
|
380
|
+
# A sequence is defined by consecutive comments (ignoring blank lines in between)
|
|
381
|
+
def deduplicate_sequences_pass1(tuples)
|
|
382
|
+
return tuples if tuples.length <= 1
|
|
383
|
+
|
|
384
|
+
# Group tuples into sequences (consecutive comments, allowing gaps for blank lines)
|
|
385
|
+
sequences = []
|
|
386
|
+
current_seq = []
|
|
387
|
+
prev_line = nil
|
|
388
|
+
|
|
389
|
+
tuples.each do |tuple|
|
|
390
|
+
line_num = tuple[3]
|
|
391
|
+
|
|
392
|
+
# If this is consecutive with previous (allowing reasonable gaps for blank lines)
|
|
393
|
+
if prev_line.nil? || (line_num - prev_line) <= 3
|
|
394
|
+
current_seq << tuple
|
|
395
|
+
else
|
|
396
|
+
# Start new sequence
|
|
397
|
+
sequences << current_seq if current_seq.any?
|
|
398
|
+
current_seq = [tuple]
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
prev_line = line_num
|
|
402
|
+
end
|
|
403
|
+
sequences << current_seq if current_seq.any?
|
|
404
|
+
|
|
405
|
+
# Find duplicate sequences by comparing hash signatures
|
|
406
|
+
seen_seq_signatures = Set.new
|
|
407
|
+
unique_tuples = []
|
|
408
|
+
|
|
409
|
+
sequences.each do |seq|
|
|
410
|
+
# Create signature from hashes and sequence length
|
|
411
|
+
seq_signature = seq.map { |t| t[0] }.join(",")
|
|
412
|
+
|
|
413
|
+
unless seen_seq_signatures.include?(seq_signature)
|
|
414
|
+
seen_seq_signatures << seq_signature
|
|
415
|
+
unique_tuples.concat(seq)
|
|
277
416
|
end
|
|
278
417
|
end
|
|
279
418
|
|
|
280
|
-
|
|
419
|
+
unique_tuples
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
# Pass 2: Remove single-line duplicates from already sequence-deduplicated tuples
|
|
423
|
+
def deduplicate_singles_pass2(tuples)
|
|
424
|
+
return tuples if tuples.length <= 1
|
|
425
|
+
|
|
426
|
+
seen_hashes = Set.new
|
|
427
|
+
unique_tuples = []
|
|
428
|
+
|
|
429
|
+
tuples.each do |tuple|
|
|
430
|
+
comment_hash = tuple[0]
|
|
431
|
+
|
|
432
|
+
unless seen_hashes.include?(comment_hash)
|
|
433
|
+
seen_hashes << comment_hash
|
|
434
|
+
unique_tuples << tuple
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
unique_tuples
|
|
281
439
|
end
|
|
282
440
|
|
|
283
441
|
def extract_file_leading_comments(parse_result)
|
|
284
442
|
return [] unless parse_result.success?
|
|
285
443
|
|
|
286
|
-
|
|
287
|
-
|
|
444
|
+
tuples = create_comment_tuples(parse_result)
|
|
445
|
+
deduplicated = deduplicate_comment_sequences(tuples)
|
|
288
446
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
# but before the first executable statement. These are typically documentation
|
|
294
|
-
# comments describing the file's purpose.
|
|
295
|
-
parse_result.comments.select do |comment|
|
|
296
|
-
comment.location.start_line > 2 &&
|
|
297
|
-
comment.location.start_line < first_stmt_line
|
|
298
|
-
end.map { |comment| comment.slice.rstrip }
|
|
447
|
+
# Filter to only file-level comments and return their text
|
|
448
|
+
deduplicated
|
|
449
|
+
.select { |tuple| tuple[1] == :file_level }
|
|
450
|
+
.map { |tuple| tuple[2] }
|
|
299
451
|
end
|
|
300
452
|
|
|
301
453
|
def extract_nodes_with_comments(parse_result)
|
|
@@ -358,8 +510,6 @@ module Kettle
|
|
|
358
510
|
end
|
|
359
511
|
|
|
360
512
|
def build_source_from_nodes(node_infos, magic_comments: [], file_leading_comments: [])
|
|
361
|
-
return "" if node_infos.empty?
|
|
362
|
-
|
|
363
513
|
lines = []
|
|
364
514
|
|
|
365
515
|
# Add magic comments at the top (frozen_string_literal, etc.)
|
|
@@ -371,9 +521,16 @@ module Kettle
|
|
|
371
521
|
# Add file-level leading comments (comments before first statement)
|
|
372
522
|
if file_leading_comments.any?
|
|
373
523
|
lines.concat(file_leading_comments)
|
|
374
|
-
|
|
524
|
+
# Only add blank line if there are statements following
|
|
525
|
+
lines << "" if node_infos.any?
|
|
375
526
|
end
|
|
376
527
|
|
|
528
|
+
# If there are no statements and no comments, return empty string
|
|
529
|
+
return "" if node_infos.empty? && lines.empty?
|
|
530
|
+
|
|
531
|
+
# If there are only comments and no statements, return the comments
|
|
532
|
+
return lines.join("\n") if node_infos.empty?
|
|
533
|
+
|
|
377
534
|
node_infos.each do |node_info|
|
|
378
535
|
# Add blank lines before this statement (for visual grouping)
|
|
379
536
|
blank_lines = node_info[:blank_lines_before] || 0
|
|
@@ -435,7 +592,14 @@ module Kettle
|
|
|
435
592
|
def restore_custom_leading_comments(dest_content, merged_content)
|
|
436
593
|
block = leading_comment_block(dest_content)
|
|
437
594
|
return merged_content if block.strip.empty?
|
|
438
|
-
|
|
595
|
+
|
|
596
|
+
# Check if the merged content already starts with this block
|
|
597
|
+
# Use normalized comparison to handle whitespace differences
|
|
598
|
+
merged_leading = leading_comment_block(merged_content)
|
|
599
|
+
|
|
600
|
+
# If merged already has the same or more comprehensive leading comments, don't add
|
|
601
|
+
return merged_content if merged_leading.strip == block.strip
|
|
602
|
+
return merged_content if merged_content.include?(block.strip)
|
|
439
603
|
|
|
440
604
|
# Insert after shebang / frozen string literal comments (same place reminder goes)
|
|
441
605
|
insertion_index = reminder_insertion_index(merged_content)
|
data/lib/kettle/dev/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: kettle-dev
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -57,14 +57,14 @@ dependencies:
|
|
|
57
57
|
requirements:
|
|
58
58
|
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: 0.9.
|
|
60
|
+
version: 0.9.3
|
|
61
61
|
type: :development
|
|
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: 0.9.
|
|
67
|
+
version: 0.9.3
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
69
|
name: require_bench
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -142,7 +142,7 @@ dependencies:
|
|
|
142
142
|
version: '1.0'
|
|
143
143
|
- - ">="
|
|
144
144
|
- !ruby/object:Gem::Version
|
|
145
|
-
version: 1.0.
|
|
145
|
+
version: 1.0.3
|
|
146
146
|
type: :development
|
|
147
147
|
prerelease: false
|
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -152,7 +152,7 @@ dependencies:
|
|
|
152
152
|
version: '1.0'
|
|
153
153
|
- - ">="
|
|
154
154
|
- !ruby/object:Gem::Version
|
|
155
|
-
version: 1.0.
|
|
155
|
+
version: 1.0.3
|
|
156
156
|
- !ruby/object:Gem::Dependency
|
|
157
157
|
name: gitmoji-regex
|
|
158
158
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -414,10 +414,10 @@ licenses:
|
|
|
414
414
|
- MIT
|
|
415
415
|
metadata:
|
|
416
416
|
homepage_uri: https://kettle-dev.galtzo.com/
|
|
417
|
-
source_code_uri: https://github.com/kettle-rb/kettle-dev/tree/v1.2.
|
|
418
|
-
changelog_uri: https://github.com/kettle-rb/kettle-dev/blob/v1.2.
|
|
417
|
+
source_code_uri: https://github.com/kettle-rb/kettle-dev/tree/v1.2.3
|
|
418
|
+
changelog_uri: https://github.com/kettle-rb/kettle-dev/blob/v1.2.3/CHANGELOG.md
|
|
419
419
|
bug_tracker_uri: https://github.com/kettle-rb/kettle-dev/issues
|
|
420
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/1.2.
|
|
420
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/1.2.3
|
|
421
421
|
funding_uri: https://github.com/sponsors/pboling
|
|
422
422
|
wiki_uri: https://github.com/kettle-rb/kettle-dev/wiki
|
|
423
423
|
news_uri: https://www.railsbling.com/tags/kettle-dev
|
metadata.gz.sig
CHANGED
|
Binary file
|