ast-merge-git 7.1.3 → 7.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +1 -1
- data/exe/ast-merge-git +32 -1
- data/lib/ast/merge/git/local_benchmark.rb +350 -15
- data/lib/ast/merge/git/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +14 -294
- 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: be709f99d89a6dc5a6245b53d676a1d6136b64574724cfedada249935de9557b
|
|
4
|
+
data.tar.gz: dff9b5168e5dd8cac4af0c4a7510726db3038d389f2c0212df27a4954d67fcb1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd3ccddce030b00948006e96a5c6029fda6d6ee7dab5f9af91bc24a4e361149a5e476ddaa5d45277bb981b593995e8d1135ce70c4d5b672cd5c799cd12078225
|
|
7
|
+
data.tar.gz: 431a3ab1a6fa2eb04521bbd5a3b99e7b4a786dc5d121de937aa0c5448bd882906c6cfcf013e520ce105bce587144c84dfbebab9475abd8e9d293eafde840329a
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/README.md
CHANGED
|
@@ -282,7 +282,7 @@ If none of the available licenses suit your use case, please [contact us](mailto
|
|
|
282
282
|
[📌gitmoji]: https://gitmoji.dev
|
|
283
283
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
284
284
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
285
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-
|
|
285
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-1.022-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
286
286
|
[🔐security]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/SECURITY.md
|
|
287
287
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
288
288
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/exe/ast-merge-git
CHANGED
|
@@ -3,6 +3,35 @@
|
|
|
3
3
|
|
|
4
4
|
require 'ast/merge/git'
|
|
5
5
|
|
|
6
|
+
if ARGV.first == 'benchmark-provider-diff'
|
|
7
|
+
require 'json'
|
|
8
|
+
|
|
9
|
+
begin
|
|
10
|
+
before_path, after_path, path_name = ARGV.drop(1)
|
|
11
|
+
raise ArgumentError, 'before, after, and path name are required' unless before_path && after_path && path_name
|
|
12
|
+
|
|
13
|
+
require ENV.fetch('AST_MERGE_REQUIRE')
|
|
14
|
+
result = Ast::Merge.dispatch_provider(
|
|
15
|
+
:diff2,
|
|
16
|
+
{
|
|
17
|
+
provider_id: ENV.fetch('AST_MERGE_PROVIDER'),
|
|
18
|
+
family: ENV.fetch('AST_MERGE_FAMILY'),
|
|
19
|
+
dialect: ENV.fetch('AST_MERGE_DIALECT'),
|
|
20
|
+
backend: ENV.fetch('AST_MERGE_BACKEND'),
|
|
21
|
+
profile_id: ENV.fetch('AST_MERGE_PROFILE'),
|
|
22
|
+
before_source: File.binread(before_path),
|
|
23
|
+
after_source: File.binread(after_path),
|
|
24
|
+
path_name: path_name
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
puts JSON.generate(Ast::Merge.json_ready(result))
|
|
28
|
+
exit(result[:ok] == true ? 0 : 2)
|
|
29
|
+
rescue ArgumentError, Ast::Merge::Error, KeyError, LoadError, SystemCallError => e
|
|
30
|
+
warn "ast-merge-git benchmark-provider-diff: #{e.message}"
|
|
31
|
+
exit 2
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
6
35
|
if ARGV.first == 'benchmark'
|
|
7
36
|
require 'json'
|
|
8
37
|
require 'optparse'
|
|
@@ -20,6 +49,7 @@ if ARGV.first == 'benchmark'
|
|
|
20
49
|
opts.on('--profile PROFILE') { |value| options[:profile] = value }
|
|
21
50
|
opts.on('--changed-path PATH') { |value| options[:changed_paths] << value }
|
|
22
51
|
opts.on('--driver PATH') { |value| options[:driver] = value }
|
|
52
|
+
opts.on('--mergiraf PATH') { |value| options[:mergiraf] = value }
|
|
23
53
|
opts.on('--tmp-root PATH') { |value| options[:tmp_root] = value }
|
|
24
54
|
opts.on('--timeout SECONDS', Integer) { |value| options[:timeout] = value }
|
|
25
55
|
end
|
|
@@ -41,7 +71,8 @@ if ARGV.first == 'benchmark'
|
|
|
41
71
|
benchmark: benchmark,
|
|
42
72
|
driver_path: driver,
|
|
43
73
|
tmp_root: options[:tmp_root],
|
|
44
|
-
timeout: options[:timeout]
|
|
74
|
+
timeout: options[:timeout],
|
|
75
|
+
competitor_paths: options[:mergiraf] ? { 'mergiraf' => options[:mergiraf] } : {}
|
|
45
76
|
).run(profile: options[:profile], changed_paths: options[:changed_paths])
|
|
46
77
|
command == 'report' ? Ast::Merge::Git::LocalBenchmarkReport.build(run) : run
|
|
47
78
|
else
|
|
@@ -16,6 +16,7 @@ module Ast
|
|
|
16
16
|
SCHEMA = 'structuredmerge.benchmark.corpus/v1'
|
|
17
17
|
CASE_SCHEMA = 'structuredmerge.benchmark/v1'
|
|
18
18
|
OPERATIONS = %w[merge3 metamorphic diff].freeze
|
|
19
|
+
EXECUTABLE_OPERATIONS = %w[merge3 metamorphic].freeze
|
|
19
20
|
PARTITIONS = %w[sentinel gold metamorphic].freeze
|
|
20
21
|
EXPECTATIONS = %w[clean conflict error excluded_ambiguous].freeze
|
|
21
22
|
SEVERITIES = %w[none low high critical].freeze
|
|
@@ -24,6 +25,9 @@ module Ast
|
|
|
24
25
|
rename move reorder formatting comment independent_edit delete_modify duplicate_key_identity
|
|
25
26
|
schema_aware_mutation
|
|
26
27
|
].freeze
|
|
28
|
+
METAMORPHIC_INVARIANTS = %w[
|
|
29
|
+
comment-retained no-semantic-edit same-json-value same-jsonc-value
|
|
30
|
+
].freeze
|
|
27
31
|
ID_PATTERN = /\A[a-z0-9]+(?:[.-][a-z0-9]+)*\z/
|
|
28
32
|
PROVENANCE_FIELDS = %w[
|
|
29
33
|
origin_uri revision spdx_license license_evidence_uri authorship author_review reviewer derivation
|
|
@@ -54,7 +58,7 @@ module Ast
|
|
|
54
58
|
|
|
55
59
|
def validate!
|
|
56
60
|
require_keys(document, %w[schema_version kind id version extends provenance profiles capability_map
|
|
57
|
-
selection cases expected_summary], 'corpus')
|
|
61
|
+
selection competitors cases expected_summary], 'corpus')
|
|
58
62
|
error!('unsupported corpus schema') unless document['schema_version'] == SCHEMA
|
|
59
63
|
error!('corpus must extend Slice 1022 v1') unless document['extends'] == CASE_SCHEMA
|
|
60
64
|
error!('network must be denied') unless document['network_policy'] == 'denied'
|
|
@@ -62,6 +66,7 @@ module Ast
|
|
|
62
66
|
validate_provenance!(document['provenance'], 'corpus')
|
|
63
67
|
validate_profiles!
|
|
64
68
|
validate_capability_map!
|
|
69
|
+
validate_competitors!
|
|
65
70
|
validate_cases!
|
|
66
71
|
validate_summary!
|
|
67
72
|
true
|
|
@@ -109,7 +114,9 @@ module Ast
|
|
|
109
114
|
'seed' => document.dig('selection', 'seed'),
|
|
110
115
|
'selected_case_ids' => neighbors
|
|
111
116
|
},
|
|
112
|
-
'unsupported_selected_cases' => selected.reject
|
|
117
|
+
'unsupported_selected_cases' => selected.reject do |id|
|
|
118
|
+
EXECUTABLE_OPERATIONS.include?(case_by_id(id)['operation'])
|
|
119
|
+
end,
|
|
113
120
|
'budgets' => definition.fetch('budgets'),
|
|
114
121
|
'explanation' => explanation(
|
|
115
122
|
profile,
|
|
@@ -148,6 +155,25 @@ module Ast
|
|
|
148
155
|
end
|
|
149
156
|
end
|
|
150
157
|
|
|
158
|
+
def validate_competitors!
|
|
159
|
+
document.fetch('competitors').each do |id, competitor|
|
|
160
|
+
require_keys(
|
|
161
|
+
competitor,
|
|
162
|
+
%w[adapter_id source_url source_revision version spdx_license reuse_posture toolchain
|
|
163
|
+
build_command operations dialects],
|
|
164
|
+
"competitor #{id}"
|
|
165
|
+
)
|
|
166
|
+
error!("competitor #{id}: adapter ID differs") unless competitor['adapter_id'] == id
|
|
167
|
+
unless /\A[0-9a-f]{40}\z/.match?(competitor['source_revision'])
|
|
168
|
+
error!("competitor #{id}: source revision must be a full SHA")
|
|
169
|
+
end
|
|
170
|
+
error!("competitor #{id}: only merge3 is admitted") unless competitor['operations'] == ['merge3']
|
|
171
|
+
next if competitor['dialects'] == competitor['dialects'].sort
|
|
172
|
+
|
|
173
|
+
error!("competitor #{id}: dialects must be sorted")
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
151
177
|
def validate_cases!
|
|
152
178
|
records = document['cases']
|
|
153
179
|
error!('cases must not be empty') unless records.is_a?(Array) && records.any?
|
|
@@ -260,6 +286,8 @@ module Ast
|
|
|
260
286
|
digest = item.dig('generator', 'sha256')
|
|
261
287
|
error!("#{id}: generator SHA-256 is malformed") unless /\A[0-9a-f]{64}\z/.match?(digest)
|
|
262
288
|
error!("#{id}: expected invariants must not be empty") if item['expected_invariants'].empty?
|
|
289
|
+
unknown_invariants = item['expected_invariants'] - METAMORPHIC_INVARIANTS
|
|
290
|
+
error!("#{id}: unsupported expected invariants: #{unknown_invariants.join(', ')}") if unknown_invariants.any?
|
|
263
291
|
item['transformations'].each do |transformation|
|
|
264
292
|
require_keys(transformation, %w[id type parameters], "#{id} transformation")
|
|
265
293
|
error!("#{id}: unknown transformation") unless TRANSFORMATIONS.include?(transformation['type'])
|
|
@@ -348,12 +376,23 @@ module Ast
|
|
|
348
376
|
# Executes the same authored merge bytes through Git and the installed driver.
|
|
349
377
|
class LocalBenchmarkRunner
|
|
350
378
|
DEFAULT_TIMEOUT = 30
|
|
379
|
+
MERGIRAF_EXTENSIONS = {
|
|
380
|
+
'bash' => 'sh',
|
|
381
|
+
'html' => 'html',
|
|
382
|
+
'json' => 'json',
|
|
383
|
+
'markdown' => 'md',
|
|
384
|
+
'ruby' => 'rb',
|
|
385
|
+
'toml' => 'toml',
|
|
386
|
+
'typescript' => 'ts',
|
|
387
|
+
'yaml' => 'yaml'
|
|
388
|
+
}.freeze
|
|
351
389
|
|
|
352
|
-
def initialize(benchmark:, driver_path:, tmp_root:, timeout: DEFAULT_TIMEOUT)
|
|
390
|
+
def initialize(benchmark:, driver_path:, tmp_root:, timeout: DEFAULT_TIMEOUT, competitor_paths: {})
|
|
353
391
|
@benchmark = benchmark
|
|
354
392
|
@driver_path = Pathname(driver_path).expand_path
|
|
355
393
|
@tmp_root = Pathname(tmp_root).expand_path
|
|
356
394
|
@timeout = Integer(timeout)
|
|
395
|
+
@competitor_paths = competitor_paths.transform_values { |path| Pathname(path).expand_path }
|
|
357
396
|
end
|
|
358
397
|
|
|
359
398
|
def run(profile:, changed_paths: [])
|
|
@@ -361,7 +400,8 @@ module Ast
|
|
|
361
400
|
selection = @benchmark.select(profile: profile, changed_paths: changed_paths)
|
|
362
401
|
original_cwd = Dir.pwd
|
|
363
402
|
results = selection['selected_case_ids'].flat_map do |id|
|
|
364
|
-
|
|
403
|
+
item = @benchmark.case_by_id(id)
|
|
404
|
+
execute_case(item) + execute_competitors(item)
|
|
365
405
|
end
|
|
366
406
|
raise LocalBenchmark::Error, 'runner changed its working directory' unless Dir.pwd == original_cwd
|
|
367
407
|
|
|
@@ -372,6 +412,7 @@ module Ast
|
|
|
372
412
|
'corpus_digest' => @benchmark.corpus_digest,
|
|
373
413
|
'selection' => selection,
|
|
374
414
|
'cache_identity' => cache_identity(selection),
|
|
415
|
+
'competitors' => competitor_provenance,
|
|
375
416
|
'results' => results
|
|
376
417
|
}
|
|
377
418
|
ensure
|
|
@@ -382,14 +423,67 @@ module Ast
|
|
|
382
423
|
|
|
383
424
|
def verify_environment!
|
|
384
425
|
error!("missing installed driver: #{@driver_path}") unless @driver_path.file? && @driver_path.executable?
|
|
426
|
+
@competitor_paths.each do |id, path|
|
|
427
|
+
error!("unknown competitor: #{id}") unless @benchmark.document.fetch('competitors').key?(id)
|
|
428
|
+
error!("missing competitor executable: #{path}") unless path.file? && path.executable?
|
|
429
|
+
end
|
|
385
430
|
root = Pathname(__dir__).join('..', '..', '..', '..').realpath
|
|
386
431
|
resolved = @tmp_root.exist? ? @tmp_root.realpath : @tmp_root.dirname.realpath.join(@tmp_root.basename)
|
|
387
432
|
error!('tmp_root must be inside the ast-merge-git repository') unless resolved.to_s.start_with?("#{root}/")
|
|
388
433
|
end
|
|
389
434
|
|
|
390
435
|
def execute_case(item)
|
|
391
|
-
return
|
|
436
|
+
return execute_merge3_case(item) if item['operation'] == 'merge3'
|
|
437
|
+
return execute_metamorphic_case(item) if item['operation'] == 'metamorphic'
|
|
438
|
+
|
|
439
|
+
unsupported_pair(item)
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
def execute_competitors(item)
|
|
443
|
+
@competitor_paths.map do |id, path|
|
|
444
|
+
metadata = @benchmark.document.dig('competitors', id)
|
|
445
|
+
unless metadata['operations'].include?(item['operation']) && metadata['dialects'].include?(item['dialect'])
|
|
446
|
+
next raw_result(
|
|
447
|
+
item,
|
|
448
|
+
id,
|
|
449
|
+
nil,
|
|
450
|
+
outcome: 'unsupported',
|
|
451
|
+
unsupported_reason: "#{id} does not support #{item['operation']}/#{item['dialect']}"
|
|
452
|
+
)
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
execute_mergiraf(item, path)
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def execute_mergiraf(item, path)
|
|
460
|
+
workspace = @tmp_root.join("#{safe_id(item['id'])}-mergiraf-#{Process.pid}")
|
|
461
|
+
FileUtils.rm_rf(workspace)
|
|
462
|
+
FileUtils.mkdir_p(workspace)
|
|
463
|
+
write_roles(item, workspace)
|
|
464
|
+
output = workspace.join('output')
|
|
465
|
+
capture = timed_capture(
|
|
466
|
+
oracle_free_env,
|
|
467
|
+
path.to_s,
|
|
468
|
+
'merge',
|
|
469
|
+
'base',
|
|
470
|
+
'ours',
|
|
471
|
+
'theirs',
|
|
472
|
+
'--output',
|
|
473
|
+
output.to_s,
|
|
474
|
+
'--path-name',
|
|
475
|
+
"#{item['id']}.#{MERGIRAF_EXTENSIONS.fetch(item['dialect'])}",
|
|
476
|
+
'--conflict-marker-size',
|
|
477
|
+
'7',
|
|
478
|
+
chdir: workspace
|
|
479
|
+
)
|
|
480
|
+
capture[:output] = output.file? ? output.binread : ''
|
|
481
|
+
raw_result(item, 'mergiraf', capture)
|
|
482
|
+
ensure
|
|
483
|
+
FileUtils.rm_rf(workspace) if workspace
|
|
484
|
+
end
|
|
392
485
|
|
|
486
|
+
def execute_merge3_case(item)
|
|
393
487
|
workspace = @tmp_root.join("#{safe_id(item['id'])}-#{Process.pid}")
|
|
394
488
|
FileUtils.rm_rf(workspace)
|
|
395
489
|
FileUtils.mkdir_p(workspace)
|
|
@@ -402,8 +496,22 @@ module Ast
|
|
|
402
496
|
FileUtils.rm_rf(workspace) if workspace
|
|
403
497
|
end
|
|
404
498
|
|
|
499
|
+
def execute_metamorphic_case(item)
|
|
500
|
+
workspace = @tmp_root.join("#{safe_id(item['id'])}-#{Process.pid}")
|
|
501
|
+
FileUtils.rm_rf(workspace)
|
|
502
|
+
FileUtils.mkdir_p(workspace)
|
|
503
|
+
write_metamorphic_roles(item, workspace)
|
|
504
|
+
baseline = execute_metamorphic_baseline(item, workspace)
|
|
505
|
+
candidate = execute_metamorphic_candidate(item, workspace)
|
|
506
|
+
rerun = execute_metamorphic_candidate(item, workspace)
|
|
507
|
+
candidate['deterministic_correctness_rerun'] = correctness_record(candidate) == correctness_record(rerun)
|
|
508
|
+
[baseline, candidate]
|
|
509
|
+
ensure
|
|
510
|
+
FileUtils.rm_rf(workspace) if workspace
|
|
511
|
+
end
|
|
512
|
+
|
|
405
513
|
def unsupported_pair(item)
|
|
406
|
-
%w[git.
|
|
514
|
+
%w[git.unsupported structuredmerge.unsupported].map do |adapter|
|
|
407
515
|
raw_result(item, adapter, nil, outcome: 'unsupported',
|
|
408
516
|
unsupported_reason: "no installed #{item['operation']} adapter")
|
|
409
517
|
end
|
|
@@ -434,6 +542,62 @@ module Ast
|
|
|
434
542
|
end
|
|
435
543
|
end
|
|
436
544
|
|
|
545
|
+
def write_metamorphic_roles(item, workspace)
|
|
546
|
+
%w[source transformed].each do |role|
|
|
547
|
+
workspace.join(role).binwrite(item.dig('inputs', role, 'bytes'))
|
|
548
|
+
end
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
def execute_metamorphic_baseline(item, workspace)
|
|
552
|
+
capture = timed_capture(
|
|
553
|
+
{},
|
|
554
|
+
'git', 'diff', '--no-index', '--no-color', '--no-ext-diff', '--', 'source', 'transformed',
|
|
555
|
+
chdir: workspace
|
|
556
|
+
)
|
|
557
|
+
capture[:output] = capture[:stdout]
|
|
558
|
+
metamorphic_result(
|
|
559
|
+
item,
|
|
560
|
+
'git.diff',
|
|
561
|
+
'baseline',
|
|
562
|
+
capture,
|
|
563
|
+
edit_signal: capture[:status] == 1
|
|
564
|
+
)
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
def execute_metamorphic_candidate(item, workspace)
|
|
568
|
+
capture, changes = capture_provider_diff(item, workspace)
|
|
569
|
+
metamorphic_result(
|
|
570
|
+
item,
|
|
571
|
+
'ast-merge-provider.diff2',
|
|
572
|
+
'candidate',
|
|
573
|
+
capture,
|
|
574
|
+
edit_signal: changes.any?
|
|
575
|
+
)
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
def capture_provider_diff(item, workspace)
|
|
579
|
+
selector = item.fetch('selector')
|
|
580
|
+
capture = timed_capture(
|
|
581
|
+
candidate_env(selector),
|
|
582
|
+
@driver_path.to_s,
|
|
583
|
+
'benchmark-provider-diff',
|
|
584
|
+
'source',
|
|
585
|
+
'transformed',
|
|
586
|
+
"#{item['id']}.#{item['dialect']}",
|
|
587
|
+
chdir: workspace
|
|
588
|
+
)
|
|
589
|
+
result = capture[:stdout].empty? ? {} : JSON.parse(capture[:stdout])
|
|
590
|
+
changes = capture[:status].zero? ? result.fetch('changes') : []
|
|
591
|
+
capture[:output] = JSON.generate(changes)
|
|
592
|
+
[capture, changes]
|
|
593
|
+
rescue JSON::ParserError, KeyError => e
|
|
594
|
+
capture ||= { stdout: '', stderr: '', status: 2, duration_ns: 0 }
|
|
595
|
+
capture[:stderr] = [capture[:stderr], e.message].reject(&:empty?).join("\n")
|
|
596
|
+
capture[:status] = 2
|
|
597
|
+
capture[:output] = ''
|
|
598
|
+
[capture, []]
|
|
599
|
+
end
|
|
600
|
+
|
|
437
601
|
def timed_capture(env, *command, chdir:)
|
|
438
602
|
started = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
|
|
439
603
|
stdin, stdout_io, stderr_io, process = Open3.popen3(env, *command, chdir: chdir.to_s)
|
|
@@ -475,6 +639,7 @@ module Ast
|
|
|
475
639
|
'id' => "result.#{safe_id(item['id'])}.#{safe_id(adapter)}",
|
|
476
640
|
'case_id' => item['id'],
|
|
477
641
|
'adapter_id' => adapter,
|
|
642
|
+
'adapter_role' => adapter_role(adapter),
|
|
478
643
|
'case_tags' => item.slice(
|
|
479
644
|
'operation', 'partition', 'family', 'provider', 'dialect',
|
|
480
645
|
'capabilities', 'false_auto_merge_severity'
|
|
@@ -498,6 +663,135 @@ module Ast
|
|
|
498
663
|
}
|
|
499
664
|
end
|
|
500
665
|
|
|
666
|
+
def adapter_role(adapter)
|
|
667
|
+
return 'baseline' if adapter.start_with?('git.')
|
|
668
|
+
return 'candidate' if %w[ast-merge-git ast-merge-provider.diff2 structuredmerge.unsupported].include?(adapter)
|
|
669
|
+
|
|
670
|
+
'competitor'
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
def metamorphic_result(item, adapter, adapter_role, capture, edit_signal:)
|
|
674
|
+
checks = metamorphic_checks(item, edit_signal)
|
|
675
|
+
classified = if capture[:status].nil? || capture[:status] >= 2
|
|
676
|
+
'error'
|
|
677
|
+
elsif checks['acceptable']
|
|
678
|
+
'correct_clean'
|
|
679
|
+
else
|
|
680
|
+
'false_conflict'
|
|
681
|
+
end
|
|
682
|
+
eligible = item.dig('oracle', 'score_eligible') && classified != 'error'
|
|
683
|
+
{
|
|
684
|
+
'schema_version' => 'structuredmerge.benchmark.result/v1',
|
|
685
|
+
'id' => "result.#{safe_id(item['id'])}.#{safe_id(adapter)}",
|
|
686
|
+
'case_id' => item['id'],
|
|
687
|
+
'adapter_id' => adapter,
|
|
688
|
+
'adapter_role' => adapter_role,
|
|
689
|
+
'case_tags' => item.slice(
|
|
690
|
+
'operation', 'partition', 'family', 'provider', 'dialect',
|
|
691
|
+
'capabilities', 'false_auto_merge_severity'
|
|
692
|
+
),
|
|
693
|
+
'outcome' => classified,
|
|
694
|
+
'score_eligible' => eligible,
|
|
695
|
+
'provenance' => item['provenance'],
|
|
696
|
+
'process' => {
|
|
697
|
+
'status' => capture[:status],
|
|
698
|
+
'exit_classification' => metamorphic_exit_class(adapter_role, capture[:status])
|
|
699
|
+
},
|
|
700
|
+
'raw' => {
|
|
701
|
+
'stdout' => raw_record(capture[:stdout]),
|
|
702
|
+
'stderr' => raw_record(capture[:stderr]),
|
|
703
|
+
'output' => raw_record(capture[:output])
|
|
704
|
+
},
|
|
705
|
+
'diagnostics' => diagnostics(capture[:stderr], nil),
|
|
706
|
+
'conflict_regions' => region_evidence(item, []),
|
|
707
|
+
'checks' => checks,
|
|
708
|
+
'independent_edit_evidence' => {},
|
|
709
|
+
'dimensions' => dimensions(item, classified, checks),
|
|
710
|
+
'runtime' => { 'duration_ns' => capture[:duration_ns], 'comparable' => true }
|
|
711
|
+
}
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
def metamorphic_checks(item, edit_signal)
|
|
715
|
+
evaluations = item.fetch('expected_invariants').map do |invariant|
|
|
716
|
+
matched, evidence = evaluate_metamorphic_invariant(item, invariant, edit_signal)
|
|
717
|
+
{ 'id' => invariant, 'matched' => matched, 'evidence' => evidence }
|
|
718
|
+
end
|
|
719
|
+
accepted = evaluations.all? { |evaluation| evaluation['matched'] }
|
|
720
|
+
{
|
|
721
|
+
'declared_invariants' => evaluations,
|
|
722
|
+
'accepted_equivalence' => accepted ? 'declared_invariants' : nil,
|
|
723
|
+
'acceptable_equivalence_evaluations' => [{
|
|
724
|
+
'class' => 'declared_invariants',
|
|
725
|
+
'matched' => accepted
|
|
726
|
+
}],
|
|
727
|
+
'parse_validity_only_accepted' => false,
|
|
728
|
+
'generator_replay' => {
|
|
729
|
+
'generator_id' => item.dig('generator', 'id'),
|
|
730
|
+
'generator_version' => item.dig('generator', 'version'),
|
|
731
|
+
'seed' => item.dig('generator', 'seed'),
|
|
732
|
+
'transformation_ids' => item.fetch('transformations').map { |transformation| transformation['id'] },
|
|
733
|
+
'authored_bytes_digest_verified' => true
|
|
734
|
+
},
|
|
735
|
+
'preservation_violations' => [],
|
|
736
|
+
'acceptable' => accepted
|
|
737
|
+
}
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
def evaluate_metamorphic_invariant(item, invariant, edit_signal)
|
|
741
|
+
case invariant
|
|
742
|
+
when 'same-json-value', 'same-jsonc-value'
|
|
743
|
+
[json_values_equal?(item), 'JSON-family values parsed from source and transformed bytes']
|
|
744
|
+
when 'no-semantic-edit'
|
|
745
|
+
[!edit_signal, 'adapter emitted no edit units']
|
|
746
|
+
when 'comment-retained'
|
|
747
|
+
[json_comments_retained?(item), 'JSONC AST comment content retained']
|
|
748
|
+
else
|
|
749
|
+
[false, 'unsupported invariant']
|
|
750
|
+
end
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
def json_values_equal?(item)
|
|
754
|
+
require 'json/merge'
|
|
755
|
+
selector = item.fetch('selector')
|
|
756
|
+
source = Json::Merge.json_value_for_source(
|
|
757
|
+
item.dig('inputs', 'source', 'bytes'),
|
|
758
|
+
dialect: selector.fetch('dialect').to_sym,
|
|
759
|
+
backend: selector.fetch('backend')
|
|
760
|
+
)
|
|
761
|
+
transformed = Json::Merge.json_value_for_source(
|
|
762
|
+
item.dig('inputs', 'transformed', 'bytes'),
|
|
763
|
+
dialect: selector.fetch('dialect').to_sym,
|
|
764
|
+
backend: selector.fetch('backend')
|
|
765
|
+
)
|
|
766
|
+
source == transformed
|
|
767
|
+
rescue Json::Merge::ParseError, LoadError
|
|
768
|
+
false
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
def json_comments_retained?(item)
|
|
772
|
+
require 'json/merge'
|
|
773
|
+
selector = item.fetch('selector')
|
|
774
|
+
source = Json::Merge::FileAnalysis.new(
|
|
775
|
+
item.dig('inputs', 'source', 'bytes'),
|
|
776
|
+
dialect: selector.fetch('dialect').to_sym
|
|
777
|
+
)
|
|
778
|
+
transformed = Json::Merge::FileAnalysis.new(
|
|
779
|
+
item.dig('inputs', 'transformed', 'bytes'),
|
|
780
|
+
dialect: selector.fetch('dialect').to_sym
|
|
781
|
+
)
|
|
782
|
+
source.valid? && transformed.valid? &&
|
|
783
|
+
source.comment_nodes.map(&:normalized_content) == transformed.comment_nodes.map(&:normalized_content)
|
|
784
|
+
rescue TreeHaver::Error, LoadError
|
|
785
|
+
false
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
def metamorphic_exit_class(adapter_role, status)
|
|
789
|
+
return 'error' if status.nil? || status >= 2
|
|
790
|
+
return status == 1 ? 'differences' : 'no_differences' if adapter_role == 'baseline'
|
|
791
|
+
|
|
792
|
+
'analyzed'
|
|
793
|
+
end
|
|
794
|
+
|
|
501
795
|
def classify(item, status, checks)
|
|
502
796
|
expected = item.dig('expected', 'outcome')
|
|
503
797
|
return 'excluded_ambiguous' if expected == 'excluded_ambiguous'
|
|
@@ -677,8 +971,11 @@ module Ast
|
|
|
677
971
|
end
|
|
678
972
|
|
|
679
973
|
def candidate_env(selector)
|
|
680
|
-
|
|
681
|
-
|
|
974
|
+
oracle_free_env.merge(selector_env(selector))
|
|
975
|
+
end
|
|
976
|
+
|
|
977
|
+
def oracle_free_env
|
|
978
|
+
ENV.keys.grep(/(?:ORACLE|EXPECTED)/i).to_h { |name| [name, nil] }
|
|
682
979
|
end
|
|
683
980
|
|
|
684
981
|
def cache_identity(selection)
|
|
@@ -693,10 +990,12 @@ module Ast
|
|
|
693
990
|
configuration = selection['selected_case_ids'].map do |id|
|
|
694
991
|
@benchmark.case_by_id(id).slice('id', 'selector')
|
|
695
992
|
end
|
|
993
|
+
competitors = competitor_provenance
|
|
696
994
|
identity = {
|
|
697
995
|
'adapter_source_sha' => source_sha.strip,
|
|
698
996
|
'adapter_artifact_sha256' => Digest::SHA256.file(@driver_path).hexdigest,
|
|
699
997
|
'configuration_sha256' => Digest::SHA256.hexdigest(JSON.generate(configuration)),
|
|
998
|
+
'competitors' => competitors,
|
|
700
999
|
'corpus_sha256' => @benchmark.corpus_digest,
|
|
701
1000
|
'environment' => environment,
|
|
702
1001
|
'profile' => selection['profile'],
|
|
@@ -710,6 +1009,22 @@ module Ast
|
|
|
710
1009
|
identity.merge('sha256' => Digest::SHA256.hexdigest(JSON.generate(identity)))
|
|
711
1010
|
end
|
|
712
1011
|
|
|
1012
|
+
def competitor_provenance
|
|
1013
|
+
@competitor_provenance ||= @competitor_paths.to_h do |id, path|
|
|
1014
|
+
metadata = @benchmark.document.fetch('competitors').fetch(id)
|
|
1015
|
+
capture = timed_capture(oracle_free_env, path.to_s, '--version', chdir: path.dirname)
|
|
1016
|
+
error!("#{id} version probe failed: #{capture[:stderr].strip}") unless capture[:status].zero?
|
|
1017
|
+
expected = "#{metadata.fetch('adapter_id')} #{metadata.fetch('version')}"
|
|
1018
|
+
error!("#{id} version differs: #{capture[:stdout].strip}") unless capture[:stdout].strip == expected
|
|
1019
|
+
|
|
1020
|
+
[id, metadata.merge(
|
|
1021
|
+
'binary_path' => path.to_s,
|
|
1022
|
+
'binary_sha256' => Digest::SHA256.file(path).hexdigest,
|
|
1023
|
+
'reported_version' => capture[:stdout].strip
|
|
1024
|
+
)]
|
|
1025
|
+
end
|
|
1026
|
+
end
|
|
1027
|
+
|
|
713
1028
|
def deep_sort(value)
|
|
714
1029
|
case value
|
|
715
1030
|
when Hash then value.keys.sort.to_h { |key| [key, deep_sort(value.fetch(key))] }
|
|
@@ -750,7 +1065,7 @@ module Ast
|
|
|
750
1065
|
|
|
751
1066
|
def build
|
|
752
1067
|
pairs = @results.group_by { |result| result['case_id'] }.values.map { |items| transition(items) }
|
|
753
|
-
false_auto_merges =
|
|
1068
|
+
false_auto_merges = candidate_eligible.select { |item| item['outcome'] == 'false_auto_merge' }
|
|
754
1069
|
{
|
|
755
1070
|
'schema_version' => 'structuredmerge.benchmark.report/v1',
|
|
756
1071
|
'kind' => 'paired_aggregate_report',
|
|
@@ -760,7 +1075,7 @@ module Ast
|
|
|
760
1075
|
'cache_identity' => @run['cache_identity'],
|
|
761
1076
|
'dimensions' => {
|
|
762
1077
|
'safety' => {
|
|
763
|
-
'eligible' =>
|
|
1078
|
+
'eligible' => candidate_eligible.length,
|
|
764
1079
|
'false_auto_merge_result_ids' => false_auto_merges.map { |item| item['id'] },
|
|
765
1080
|
'gate' => false_auto_merges.empty? ? 'pass' : 'fail',
|
|
766
1081
|
'non_compensable' => true
|
|
@@ -776,7 +1091,8 @@ module Ast
|
|
|
776
1091
|
'reliability' => { 'error_result_ids' => @results.filter_map do |item|
|
|
777
1092
|
item['id'] if item['outcome'] == 'error'
|
|
778
1093
|
end },
|
|
779
|
-
'coverage' => coverage
|
|
1094
|
+
'coverage' => coverage,
|
|
1095
|
+
'competitive' => competitive
|
|
780
1096
|
},
|
|
781
1097
|
'strata' => strata,
|
|
782
1098
|
'transitions' => pairs,
|
|
@@ -794,6 +1110,10 @@ module Ast
|
|
|
794
1110
|
@eligible ||= @results.select { |item| item['score_eligible'] }
|
|
795
1111
|
end
|
|
796
1112
|
|
|
1113
|
+
def candidate_eligible
|
|
1114
|
+
eligible.select { |item| item['adapter_role'] == 'candidate' }
|
|
1115
|
+
end
|
|
1116
|
+
|
|
797
1117
|
def outcome_counts
|
|
798
1118
|
%w[correct_clean false_conflict true_conflict false_auto_merge error unsupported
|
|
799
1119
|
excluded_ambiguous].to_h do |outcome|
|
|
@@ -802,8 +1122,8 @@ module Ast
|
|
|
802
1122
|
end
|
|
803
1123
|
|
|
804
1124
|
def transition(items)
|
|
805
|
-
baseline = items.find { |item| item['
|
|
806
|
-
candidate = items.find { |item| item['
|
|
1125
|
+
baseline = items.find { |item| item['adapter_role'] == 'baseline' }
|
|
1126
|
+
candidate = items.find { |item| item['adapter_role'] == 'candidate' }
|
|
807
1127
|
{
|
|
808
1128
|
'case_id' => items.first['case_id'],
|
|
809
1129
|
'baseline_result_id' => baseline['id'],
|
|
@@ -831,15 +1151,30 @@ module Ast
|
|
|
831
1151
|
def coverage
|
|
832
1152
|
selected = @run.dig('selection', 'selected_case_ids').length
|
|
833
1153
|
unsupported = @results.select do |item|
|
|
834
|
-
item['
|
|
1154
|
+
item['adapter_role'] == 'candidate' && item['outcome'] == 'unsupported'
|
|
835
1155
|
end
|
|
836
1156
|
{ 'selected_cases' => selected, 'executed_candidate_cases' => selected - unsupported.length,
|
|
837
1157
|
'unsupported_case_ids' => unsupported.map { |item| item['case_id'] },
|
|
838
1158
|
'unsupported_is_quality_failure' => false }
|
|
839
1159
|
end
|
|
840
1160
|
|
|
1161
|
+
def competitive
|
|
1162
|
+
results = @results.select { |item| item['adapter_role'] == 'competitor' }
|
|
1163
|
+
{
|
|
1164
|
+
'configured' => @run.fetch('competitors'),
|
|
1165
|
+
'outcomes' => results.group_by { |item| item['outcome'] }.transform_values(&:length),
|
|
1166
|
+
'unsupported_case_ids' => results.filter_map do |item|
|
|
1167
|
+
item['case_id'] if item['outcome'] == 'unsupported'
|
|
1168
|
+
end,
|
|
1169
|
+
'false_auto_merge_result_ids' => results.filter_map do |item|
|
|
1170
|
+
item['id'] if item['outcome'] == 'false_auto_merge'
|
|
1171
|
+
end,
|
|
1172
|
+
'affects_candidate_safety_gate' => false
|
|
1173
|
+
}
|
|
1174
|
+
end
|
|
1175
|
+
|
|
841
1176
|
def strata
|
|
842
|
-
case_results = @results.select { |item| item['
|
|
1177
|
+
case_results = @results.select { |item| item['adapter_role'] == 'candidate' }
|
|
843
1178
|
tag_fields = %w[operation partition family provider dialect false_auto_merge_severity]
|
|
844
1179
|
tag_strata = tag_fields.to_h do |field|
|
|
845
1180
|
[field, case_results.group_by { |item| item.dig('case_tags', field) }.transform_values(&:length)]
|
|
@@ -6,7 +6,7 @@ module Ast
|
|
|
6
6
|
# Version namespace for this gem.
|
|
7
7
|
module Version
|
|
8
8
|
# Current gem version.
|
|
9
|
-
VERSION = '7.1.
|
|
9
|
+
VERSION = '7.1.4'
|
|
10
10
|
end
|
|
11
11
|
# Current gem version exposed at the traditional constant location.
|
|
12
12
|
VERSION = Version::VERSION # Traditional Constant Location
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ast-merge-git
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 7.1.
|
|
4
|
+
version: 7.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -43,14 +43,14 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - '='
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 7.1.
|
|
46
|
+
version: 7.1.4
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - '='
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 7.1.
|
|
53
|
+
version: 7.1.4
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: version_gem
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,7 +80,7 @@ dependencies:
|
|
|
80
80
|
version: '3.0'
|
|
81
81
|
- - ">="
|
|
82
82
|
- !ruby/object:Gem::Version
|
|
83
|
-
version: 3.0.
|
|
83
|
+
version: 3.0.7
|
|
84
84
|
type: :development
|
|
85
85
|
prerelease: false
|
|
86
86
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -90,7 +90,7 @@ dependencies:
|
|
|
90
90
|
version: '3.0'
|
|
91
91
|
- - ">="
|
|
92
92
|
- !ruby/object:Gem::Version
|
|
93
|
-
version: 3.0.
|
|
93
|
+
version: 3.0.7
|
|
94
94
|
- !ruby/object:Gem::Dependency
|
|
95
95
|
name: bundler-audit
|
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -188,7 +188,7 @@ dependencies:
|
|
|
188
188
|
version: '2.0'
|
|
189
189
|
- - ">="
|
|
190
190
|
- !ruby/object:Gem::Version
|
|
191
|
-
version: 2.0.
|
|
191
|
+
version: 2.0.20
|
|
192
192
|
type: :development
|
|
193
193
|
prerelease: false
|
|
194
194
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -198,7 +198,7 @@ dependencies:
|
|
|
198
198
|
version: '2.0'
|
|
199
199
|
- - ">="
|
|
200
200
|
- !ruby/object:Gem::Version
|
|
201
|
-
version: 2.0.
|
|
201
|
+
version: 2.0.20
|
|
202
202
|
- !ruby/object:Gem::Dependency
|
|
203
203
|
name: turbo_tests2
|
|
204
204
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -208,7 +208,7 @@ dependencies:
|
|
|
208
208
|
version: '3.2'
|
|
209
209
|
- - ">="
|
|
210
210
|
- !ruby/object:Gem::Version
|
|
211
|
-
version: 3.2.
|
|
211
|
+
version: 3.2.6
|
|
212
212
|
type: :development
|
|
213
213
|
prerelease: false
|
|
214
214
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -218,287 +218,7 @@ dependencies:
|
|
|
218
218
|
version: '3.2'
|
|
219
219
|
- - ">="
|
|
220
220
|
- !ruby/object:Gem::Version
|
|
221
|
-
version: 3.2.
|
|
222
|
-
- !ruby/object:Gem::Dependency
|
|
223
|
-
name: bash-merge
|
|
224
|
-
requirement: !ruby/object:Gem::Requirement
|
|
225
|
-
requirements:
|
|
226
|
-
- - '='
|
|
227
|
-
- !ruby/object:Gem::Version
|
|
228
|
-
version: 7.1.3
|
|
229
|
-
type: :development
|
|
230
|
-
prerelease: false
|
|
231
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
232
|
-
requirements:
|
|
233
|
-
- - '='
|
|
234
|
-
- !ruby/object:Gem::Version
|
|
235
|
-
version: 7.1.3
|
|
236
|
-
- !ruby/object:Gem::Dependency
|
|
237
|
-
name: citrus-toml-merge
|
|
238
|
-
requirement: !ruby/object:Gem::Requirement
|
|
239
|
-
requirements:
|
|
240
|
-
- - '='
|
|
241
|
-
- !ruby/object:Gem::Version
|
|
242
|
-
version: 7.1.3
|
|
243
|
-
type: :development
|
|
244
|
-
prerelease: false
|
|
245
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
246
|
-
requirements:
|
|
247
|
-
- - '='
|
|
248
|
-
- !ruby/object:Gem::Version
|
|
249
|
-
version: 7.1.3
|
|
250
|
-
- !ruby/object:Gem::Dependency
|
|
251
|
-
name: commonmarker-merge
|
|
252
|
-
requirement: !ruby/object:Gem::Requirement
|
|
253
|
-
requirements:
|
|
254
|
-
- - '='
|
|
255
|
-
- !ruby/object:Gem::Version
|
|
256
|
-
version: 7.1.3
|
|
257
|
-
type: :development
|
|
258
|
-
prerelease: false
|
|
259
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
260
|
-
requirements:
|
|
261
|
-
- - '='
|
|
262
|
-
- !ruby/object:Gem::Version
|
|
263
|
-
version: 7.1.3
|
|
264
|
-
- !ruby/object:Gem::Dependency
|
|
265
|
-
name: dotenv-merge
|
|
266
|
-
requirement: !ruby/object:Gem::Requirement
|
|
267
|
-
requirements:
|
|
268
|
-
- - '='
|
|
269
|
-
- !ruby/object:Gem::Version
|
|
270
|
-
version: 7.1.3
|
|
271
|
-
type: :development
|
|
272
|
-
prerelease: false
|
|
273
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
274
|
-
requirements:
|
|
275
|
-
- - '='
|
|
276
|
-
- !ruby/object:Gem::Version
|
|
277
|
-
version: 7.1.3
|
|
278
|
-
- !ruby/object:Gem::Dependency
|
|
279
|
-
name: go-merge
|
|
280
|
-
requirement: !ruby/object:Gem::Requirement
|
|
281
|
-
requirements:
|
|
282
|
-
- - '='
|
|
283
|
-
- !ruby/object:Gem::Version
|
|
284
|
-
version: 7.1.3
|
|
285
|
-
type: :development
|
|
286
|
-
prerelease: false
|
|
287
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
288
|
-
requirements:
|
|
289
|
-
- - '='
|
|
290
|
-
- !ruby/object:Gem::Version
|
|
291
|
-
version: 7.1.3
|
|
292
|
-
- !ruby/object:Gem::Dependency
|
|
293
|
-
name: html-merge
|
|
294
|
-
requirement: !ruby/object:Gem::Requirement
|
|
295
|
-
requirements:
|
|
296
|
-
- - '='
|
|
297
|
-
- !ruby/object:Gem::Version
|
|
298
|
-
version: 7.1.3
|
|
299
|
-
type: :development
|
|
300
|
-
prerelease: false
|
|
301
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
302
|
-
requirements:
|
|
303
|
-
- - '='
|
|
304
|
-
- !ruby/object:Gem::Version
|
|
305
|
-
version: 7.1.3
|
|
306
|
-
- !ruby/object:Gem::Dependency
|
|
307
|
-
name: json-merge
|
|
308
|
-
requirement: !ruby/object:Gem::Requirement
|
|
309
|
-
requirements:
|
|
310
|
-
- - '='
|
|
311
|
-
- !ruby/object:Gem::Version
|
|
312
|
-
version: 7.1.3
|
|
313
|
-
type: :development
|
|
314
|
-
prerelease: false
|
|
315
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
316
|
-
requirements:
|
|
317
|
-
- - '='
|
|
318
|
-
- !ruby/object:Gem::Version
|
|
319
|
-
version: 7.1.3
|
|
320
|
-
- !ruby/object:Gem::Dependency
|
|
321
|
-
name: kramdown-merge
|
|
322
|
-
requirement: !ruby/object:Gem::Requirement
|
|
323
|
-
requirements:
|
|
324
|
-
- - '='
|
|
325
|
-
- !ruby/object:Gem::Version
|
|
326
|
-
version: 7.1.3
|
|
327
|
-
type: :development
|
|
328
|
-
prerelease: false
|
|
329
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
330
|
-
requirements:
|
|
331
|
-
- - '='
|
|
332
|
-
- !ruby/object:Gem::Version
|
|
333
|
-
version: 7.1.3
|
|
334
|
-
- !ruby/object:Gem::Dependency
|
|
335
|
-
name: markdown-merge
|
|
336
|
-
requirement: !ruby/object:Gem::Requirement
|
|
337
|
-
requirements:
|
|
338
|
-
- - '='
|
|
339
|
-
- !ruby/object:Gem::Version
|
|
340
|
-
version: 7.1.3
|
|
341
|
-
type: :development
|
|
342
|
-
prerelease: false
|
|
343
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
344
|
-
requirements:
|
|
345
|
-
- - '='
|
|
346
|
-
- !ruby/object:Gem::Version
|
|
347
|
-
version: 7.1.3
|
|
348
|
-
- !ruby/object:Gem::Dependency
|
|
349
|
-
name: markly-merge
|
|
350
|
-
requirement: !ruby/object:Gem::Requirement
|
|
351
|
-
requirements:
|
|
352
|
-
- - '='
|
|
353
|
-
- !ruby/object:Gem::Version
|
|
354
|
-
version: 7.1.3
|
|
355
|
-
type: :development
|
|
356
|
-
prerelease: false
|
|
357
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
358
|
-
requirements:
|
|
359
|
-
- - '='
|
|
360
|
-
- !ruby/object:Gem::Version
|
|
361
|
-
version: 7.1.3
|
|
362
|
-
- !ruby/object:Gem::Dependency
|
|
363
|
-
name: parslet-toml-merge
|
|
364
|
-
requirement: !ruby/object:Gem::Requirement
|
|
365
|
-
requirements:
|
|
366
|
-
- - '='
|
|
367
|
-
- !ruby/object:Gem::Version
|
|
368
|
-
version: 7.1.3
|
|
369
|
-
type: :development
|
|
370
|
-
prerelease: false
|
|
371
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
372
|
-
requirements:
|
|
373
|
-
- - '='
|
|
374
|
-
- !ruby/object:Gem::Version
|
|
375
|
-
version: 7.1.3
|
|
376
|
-
- !ruby/object:Gem::Dependency
|
|
377
|
-
name: plain-merge
|
|
378
|
-
requirement: !ruby/object:Gem::Requirement
|
|
379
|
-
requirements:
|
|
380
|
-
- - '='
|
|
381
|
-
- !ruby/object:Gem::Version
|
|
382
|
-
version: 7.1.3
|
|
383
|
-
type: :development
|
|
384
|
-
prerelease: false
|
|
385
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
386
|
-
requirements:
|
|
387
|
-
- - '='
|
|
388
|
-
- !ruby/object:Gem::Version
|
|
389
|
-
version: 7.1.3
|
|
390
|
-
- !ruby/object:Gem::Dependency
|
|
391
|
-
name: psych-merge
|
|
392
|
-
requirement: !ruby/object:Gem::Requirement
|
|
393
|
-
requirements:
|
|
394
|
-
- - '='
|
|
395
|
-
- !ruby/object:Gem::Version
|
|
396
|
-
version: 7.1.3
|
|
397
|
-
type: :development
|
|
398
|
-
prerelease: false
|
|
399
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
400
|
-
requirements:
|
|
401
|
-
- - '='
|
|
402
|
-
- !ruby/object:Gem::Version
|
|
403
|
-
version: 7.1.3
|
|
404
|
-
- !ruby/object:Gem::Dependency
|
|
405
|
-
name: rbs-merge
|
|
406
|
-
requirement: !ruby/object:Gem::Requirement
|
|
407
|
-
requirements:
|
|
408
|
-
- - '='
|
|
409
|
-
- !ruby/object:Gem::Version
|
|
410
|
-
version: 7.1.3
|
|
411
|
-
type: :development
|
|
412
|
-
prerelease: false
|
|
413
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
414
|
-
requirements:
|
|
415
|
-
- - '='
|
|
416
|
-
- !ruby/object:Gem::Version
|
|
417
|
-
version: 7.1.3
|
|
418
|
-
- !ruby/object:Gem::Dependency
|
|
419
|
-
name: ruby-merge
|
|
420
|
-
requirement: !ruby/object:Gem::Requirement
|
|
421
|
-
requirements:
|
|
422
|
-
- - '='
|
|
423
|
-
- !ruby/object:Gem::Version
|
|
424
|
-
version: 7.1.3
|
|
425
|
-
type: :development
|
|
426
|
-
prerelease: false
|
|
427
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
428
|
-
requirements:
|
|
429
|
-
- - '='
|
|
430
|
-
- !ruby/object:Gem::Version
|
|
431
|
-
version: 7.1.3
|
|
432
|
-
- !ruby/object:Gem::Dependency
|
|
433
|
-
name: rust-merge
|
|
434
|
-
requirement: !ruby/object:Gem::Requirement
|
|
435
|
-
requirements:
|
|
436
|
-
- - '='
|
|
437
|
-
- !ruby/object:Gem::Version
|
|
438
|
-
version: 7.1.3
|
|
439
|
-
type: :development
|
|
440
|
-
prerelease: false
|
|
441
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
442
|
-
requirements:
|
|
443
|
-
- - '='
|
|
444
|
-
- !ruby/object:Gem::Version
|
|
445
|
-
version: 7.1.3
|
|
446
|
-
- !ruby/object:Gem::Dependency
|
|
447
|
-
name: toml-merge
|
|
448
|
-
requirement: !ruby/object:Gem::Requirement
|
|
449
|
-
requirements:
|
|
450
|
-
- - '='
|
|
451
|
-
- !ruby/object:Gem::Version
|
|
452
|
-
version: 7.1.3
|
|
453
|
-
type: :development
|
|
454
|
-
prerelease: false
|
|
455
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
456
|
-
requirements:
|
|
457
|
-
- - '='
|
|
458
|
-
- !ruby/object:Gem::Version
|
|
459
|
-
version: 7.1.3
|
|
460
|
-
- !ruby/object:Gem::Dependency
|
|
461
|
-
name: typescript-merge
|
|
462
|
-
requirement: !ruby/object:Gem::Requirement
|
|
463
|
-
requirements:
|
|
464
|
-
- - '='
|
|
465
|
-
- !ruby/object:Gem::Version
|
|
466
|
-
version: 7.1.3
|
|
467
|
-
type: :development
|
|
468
|
-
prerelease: false
|
|
469
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
470
|
-
requirements:
|
|
471
|
-
- - '='
|
|
472
|
-
- !ruby/object:Gem::Version
|
|
473
|
-
version: 7.1.3
|
|
474
|
-
- !ruby/object:Gem::Dependency
|
|
475
|
-
name: yaml-merge
|
|
476
|
-
requirement: !ruby/object:Gem::Requirement
|
|
477
|
-
requirements:
|
|
478
|
-
- - '='
|
|
479
|
-
- !ruby/object:Gem::Version
|
|
480
|
-
version: 7.1.3
|
|
481
|
-
type: :development
|
|
482
|
-
prerelease: false
|
|
483
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
484
|
-
requirements:
|
|
485
|
-
- - '='
|
|
486
|
-
- !ruby/object:Gem::Version
|
|
487
|
-
version: 7.1.3
|
|
488
|
-
- !ruby/object:Gem::Dependency
|
|
489
|
-
name: zip-merge
|
|
490
|
-
requirement: !ruby/object:Gem::Requirement
|
|
491
|
-
requirements:
|
|
492
|
-
- - '='
|
|
493
|
-
- !ruby/object:Gem::Version
|
|
494
|
-
version: 7.1.3
|
|
495
|
-
type: :development
|
|
496
|
-
prerelease: false
|
|
497
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
498
|
-
requirements:
|
|
499
|
-
- - '='
|
|
500
|
-
- !ruby/object:Gem::Version
|
|
501
|
-
version: 7.1.3
|
|
221
|
+
version: 3.2.6
|
|
502
222
|
- !ruby/object:Gem::Dependency
|
|
503
223
|
name: ruby-progressbar
|
|
504
224
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -542,7 +262,7 @@ dependencies:
|
|
|
542
262
|
version: '2.0'
|
|
543
263
|
- - ">="
|
|
544
264
|
- !ruby/object:Gem::Version
|
|
545
|
-
version: 2.0.
|
|
265
|
+
version: 2.0.12
|
|
546
266
|
type: :development
|
|
547
267
|
prerelease: false
|
|
548
268
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -552,7 +272,7 @@ dependencies:
|
|
|
552
272
|
version: '2.0'
|
|
553
273
|
- - ">="
|
|
554
274
|
- !ruby/object:Gem::Version
|
|
555
|
-
version: 2.0.
|
|
275
|
+
version: 2.0.12
|
|
556
276
|
description: "☯️ Git protocol adaptation and provider dispatch over ast-merge primitives."
|
|
557
277
|
email:
|
|
558
278
|
- floss@galtzo.com
|
|
@@ -576,10 +296,10 @@ licenses:
|
|
|
576
296
|
- PolyForm-Small-Business-1.0.0
|
|
577
297
|
metadata:
|
|
578
298
|
homepage_uri: https://structuredmerge.org
|
|
579
|
-
source_code_uri: https://github.com/structuredmerge/structuredmerge-ruby/tree/v7.1.
|
|
580
|
-
changelog_uri: https://github.com/structuredmerge/structuredmerge-ruby/blob/v7.1.
|
|
299
|
+
source_code_uri: https://github.com/structuredmerge/structuredmerge-ruby/tree/v7.1.4
|
|
300
|
+
changelog_uri: https://github.com/structuredmerge/structuredmerge-ruby/blob/v7.1.4/CHANGELOG.md
|
|
581
301
|
bug_tracker_uri: https://github.com/structuredmerge/structuredmerge-ruby/issues
|
|
582
|
-
documentation_uri: https://www.rubydoc.info/gems/ast-merge-git/7.1.
|
|
302
|
+
documentation_uri: https://www.rubydoc.info/gems/ast-merge-git/7.1.4
|
|
583
303
|
funding_uri: https://github.com/sponsors/pboling
|
|
584
304
|
wiki_uri: https://github.com/structuredmerge/structuredmerge-ruby/wiki
|
|
585
305
|
news_uri: https://www.railsbling.com/tags/ast-merge-git
|
metadata.gz.sig
CHANGED
|
Binary file
|