ast-merge-git 7.1.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6527f8c9a9e11a701a0650d6b6eb473c2182368ca1bef5338392ad332461911a
4
- data.tar.gz: d8b813c4d98258a2ed46b016a943e350271b13a5f17d31f13733dea638fccc6f
3
+ metadata.gz: be709f99d89a6dc5a6245b53d676a1d6136b64574724cfedada249935de9557b
4
+ data.tar.gz: dff9b5168e5dd8cac4af0c4a7510726db3038d389f2c0212df27a4954d67fcb1
5
5
  SHA512:
6
- metadata.gz: 8bc8b1aea1fbc0d857a6ce20280b28e634717a1ada45db509a1443ad6465776cb04be45d0c33b5d893a61ff8701dbab48196d67038c46ec4edee41d887329474
7
- data.tar.gz: db7093c64f37155685bdac5ae5b8fdc5120d51a5b1f154bef1bf05badb5a00c721a8bcef9205fed399dae76fc2bcbeb707d749c9c3a67ad122a3d06d724bd9c8
6
+ metadata.gz: dd3ccddce030b00948006e96a5c6029fda6d6ee7dab5f9af91bc24a4e361149a5e476ddaa5d45277bb981b593995e8d1135ce70c4d5b672cd5c799cd12078225
7
+ data.tar.gz: 431a3ab1a6fa2eb04521bbd5a3b99e7b4a786dc5d121de937aa0c5448bd882906c6cfcf013e520ce105bce587144c84dfbebab9475abd8e9d293eafde840329a
checksums.yaml.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -26,7 +26,7 @@ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-ta
26
26
  ### Key Features
27
27
 
28
28
  - Git-oriented request and response shaping for three-way merge driver integrations.
29
- - Family detection from path, extension, and configured merge behavior.
29
+ - Provider selection from explicit family/provider, dialect, backend, and profile selectors.
30
30
  - JSON-compatible reports that can be logged, inspected, or replayed by higher-level tooling.
31
31
  - Fallback-friendly behavior for unsupported families or unsafe parser results.
32
32
 
@@ -45,7 +45,7 @@ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-ta
45
45
 
46
46
  ### Compatibility
47
47
 
48
- Compatible with MRI Ruby 4.0.0+, and concordant releases of JRuby, and TruffleRuby.
48
+ Compatible with MRI Ruby 4.0.0+, JRuby, and TruffleRuby.
49
49
  CI workflows and Appraisals are generated for MRI Ruby 4.0.0+.
50
50
  This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
51
51
  may be higher than the gem's runtime compatibility floor when legacy Rubies are
@@ -87,17 +87,29 @@ gem install ast-merge-git
87
87
 
88
88
  ## ⚙️ Configuration
89
89
 
90
- Configure `ast-merge-git` through the repository's Git attributes and StructuredMerge family settings. The gem expects callers to provide the ancestor, current, and incoming file contents that Git passes to a custom merge driver.
90
+ Configure `ast-merge-git` through the repository's Git attributes and StructuredMerge provider settings. The gem expects callers to provide the ancestor, current, and incoming file contents that Git passes to a custom merge driver.
91
91
 
92
92
  Keep family-specific parser configuration in the corresponding merge gem. For example, Markdown backend choices belong to `markdown-merge` or its provider gems, while Ruby source backend choices belong to `ruby-merge` or `prism-merge`.
93
93
 
94
+ The executable does not infer or require family implementations. Configure
95
+ `AST_MERGE_REQUIRE` with comma-separated provider require paths and select a
96
+ provider with `AST_MERGE_FAMILY` or `AST_MERGE_PROVIDER`. Optional selectors are
97
+ `AST_MERGE_DIALECT`, `AST_MERGE_BACKEND`, and `AST_MERGE_PROFILE`.
98
+
99
+ ```ini
100
+ [merge "structured-json"]
101
+ name = StructuredMerge JSON-family driver
102
+ driver = AST_MERGE_REQUIRE=json/merge AST_MERGE_FAMILY=json AST_MERGE_DIALECT=json ast-merge-git %O %A %B %P %L
103
+ ```
104
+
94
105
  ## 🔧 Basic Usage
95
106
 
96
107
  ```ruby
97
108
  require "ast/merge/git"
109
+ require "json/merge"
98
110
 
99
111
  result = Ast::Merge::Git.merge3(
100
- language: "json",
112
+ family: "json",
101
113
  dialect: "json",
102
114
  base_source: File.binread("%O"),
103
115
  ours_source: File.binread("%A"),
@@ -112,6 +124,12 @@ else
112
124
  end
113
125
  ```
114
126
 
127
+ For direct Git-driver execution, `ast-merge-git` writes clean provider output to
128
+ `%A` and exits `0`. Unresolved conflicts exit `1`; unsupported capabilities,
129
+ invalid provider output, configuration failures, and file errors exit `2`.
130
+ `AST_MERGE_CONFLICT_POLICY=leave_ours` prevents conflicted output from replacing
131
+ `%A`; the default `write` policy writes provider conflict output when available.
132
+
115
133
  ## 🔐 Security
116
134
 
117
135
  See [SECURITY.md][🔐security].
@@ -119,20 +137,12 @@ See [SECURITY.md][🔐security].
119
137
  ## 🤝 Contributing
120
138
 
121
139
  If you need some ideas of where to help, you could work on adding more code coverage,
122
- or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues] or [PRs][🤝gh-pulls],
123
- or use the gem and think about how it could be better.
140
+ check [issues][🤝gh-issues] or [PRs][🤝gh-pulls], or use the gem and think about how it could be better.
124
141
 
125
142
  We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
126
143
 
127
144
  See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
128
145
 
129
- ### Code Coverage
130
-
131
- <details markdown="1">
132
- <summary>Coverage service badges</summary>
133
-
134
- </details>
135
-
136
146
  ## 📌 Versioning
137
147
 
138
148
  This library follows [![Semantic Versioning 2.0.0][📌semver-img]][📌semver] for its public API where practical.
@@ -272,7 +282,7 @@ If none of the available licenses suit your use case, please [contact us](mailto
272
282
  [📌gitmoji]: https://gitmoji.dev
273
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
274
284
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
275
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.163-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
285
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-1.022-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
276
286
  [🔐security]: https://github.com/structuredmerge/structuredmerge-ruby/blob/main/SECURITY.md
277
287
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
278
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 ADDED
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'ast/merge/git'
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
+
35
+ if ARGV.first == 'benchmark'
36
+ require 'json'
37
+ require 'optparse'
38
+
39
+ command = ARGV.fetch(1, 'help')
40
+ options = {
41
+ profile: 'micro',
42
+ changed_paths: [],
43
+ tmp_root: File.expand_path('../tmp/benchmark', __dir__),
44
+ timeout: 30
45
+ }
46
+ parser = OptionParser.new do |opts|
47
+ opts.banner = 'usage: ast-merge-git benchmark validate|select|run|report [options]'
48
+ opts.on('--corpus PATH') { |value| options[:corpus] = value }
49
+ opts.on('--profile PROFILE') { |value| options[:profile] = value }
50
+ opts.on('--changed-path PATH') { |value| options[:changed_paths] << value }
51
+ opts.on('--driver PATH') { |value| options[:driver] = value }
52
+ opts.on('--mergiraf PATH') { |value| options[:mergiraf] = value }
53
+ opts.on('--tmp-root PATH') { |value| options[:tmp_root] = value }
54
+ opts.on('--timeout SECONDS', Integer) { |value| options[:timeout] = value }
55
+ end
56
+
57
+ begin
58
+ parser.parse!(ARGV.drop(2))
59
+ raise Ast::Merge::Git::LocalBenchmark::Error, '--corpus is required' unless options[:corpus]
60
+
61
+ benchmark = Ast::Merge::Git::LocalBenchmark.load(options[:corpus])
62
+ output = case command
63
+ when 'validate'
64
+ { schema_version: 1, valid: benchmark.validate!, corpus_id: benchmark.document['id'],
65
+ corpus_digest: benchmark.corpus_digest, cases: benchmark.cases.length }
66
+ when 'select'
67
+ benchmark.select(profile: options[:profile], changed_paths: options[:changed_paths])
68
+ when 'run', 'report'
69
+ driver = options[:driver] || Gem.bin_path('ast-merge-git', 'ast-merge-git')
70
+ run = Ast::Merge::Git::LocalBenchmarkRunner.new(
71
+ benchmark: benchmark,
72
+ driver_path: driver,
73
+ tmp_root: options[:tmp_root],
74
+ timeout: options[:timeout],
75
+ competitor_paths: options[:mergiraf] ? { 'mergiraf' => options[:mergiraf] } : {}
76
+ ).run(profile: options[:profile], changed_paths: options[:changed_paths])
77
+ command == 'report' ? Ast::Merge::Git::LocalBenchmarkReport.build(run) : run
78
+ else
79
+ warn parser
80
+ exit 2
81
+ end
82
+ puts JSON.generate(output)
83
+ exit 1 if command == 'report' && output['hard_gate_failed']
84
+ rescue Ast::Merge::Git::LocalBenchmark::Error, OptionParser::ParseError => e
85
+ warn "ast-merge-git benchmark: #{e.message}"
86
+ exit 2
87
+ end
88
+ exit 0
89
+ end
90
+
91
+ if ARGV.first == 'corpus'
92
+ require 'json'
93
+ require 'optparse'
94
+
95
+ command = ARGV.fetch(1, 'help')
96
+ options = { tmp_root: File.expand_path('../tmp/corpus', __dir__), timeout: 30 }
97
+ parser = OptionParser.new do |opts|
98
+ opts.banner = 'usage: ast-merge-git corpus validate|run|acquire [options]'
99
+ opts.on('--manifest PATH') { |value| options[:manifest] = value }
100
+ opts.on('--repository PATH') { |value| options[:repository] = value }
101
+ opts.on('--driver PATH') { |value| options[:driver] = value }
102
+ opts.on('--tmp-root PATH') { |value| options[:tmp_root] = value }
103
+ opts.on('--case ID') { |value| options[:case_id] = value }
104
+ opts.on('--destination PATH') { |value| options[:destination] = value }
105
+ opts.on('--timeout SECONDS', Integer) { |value| options[:timeout] = value }
106
+ end
107
+
108
+ begin
109
+ parser.parse!(ARGV.drop(2))
110
+ raise Ast::Merge::Git::Corpus::Error, '--manifest is required' unless options[:manifest]
111
+
112
+ corpus = Ast::Merge::Git::Corpus.load(options[:manifest])
113
+ case command
114
+ when 'validate'
115
+ corpus.validate!
116
+ puts JSON.generate(schema_version: 1, valid: true, cases: corpus.manifest.fetch('cases').length)
117
+ when 'acquire'
118
+ raise Ast::Merge::Git::Corpus::Error, '--destination is required' unless options[:destination]
119
+
120
+ path = Ast::Merge::Git::CorpusAcquirer.acquire(
121
+ corpus: corpus,
122
+ destination: options[:destination],
123
+ tmp_root: options[:tmp_root]
124
+ )
125
+ puts JSON.generate(schema_version: 1, repository: path.to_s, revision: corpus.manifest.dig('source', 'revision'))
126
+ when 'run'
127
+ raise Ast::Merge::Git::Corpus::Error, '--repository is required' unless options[:repository]
128
+
129
+ driver = options[:driver] || Gem.bin_path('ast-merge-git', 'ast-merge-git')
130
+ runner = Ast::Merge::Git::CorpusRunner.new(
131
+ corpus: corpus,
132
+ repository: options[:repository],
133
+ driver_path: driver,
134
+ tmp_root: options[:tmp_root],
135
+ timeout: options[:timeout]
136
+ )
137
+ puts JSON.generate(schema_version: 1, results: runner.run(case_id: options[:case_id]))
138
+ else
139
+ warn parser
140
+ exit 2
141
+ end
142
+ rescue Ast::Merge::Git::Corpus::Error, OptionParser::ParseError => e
143
+ warn "ast-merge-git corpus: #{e.message}"
144
+ exit 2
145
+ end
146
+ exit 0
147
+ end
148
+
149
+ exit Ast::Merge::Git.run(ARGV)