tt-git-merge-structure-sql 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 91d83d55965d7e603c91b10f00b2544aeb5d2f98bb86996244ee3d1e6a4a6733
4
+ data.tar.gz: 1d75aa3a864ace209f4683a792f7188297cf471d41b0e579a292e271e56062a7
5
+ SHA512:
6
+ metadata.gz: e4c9dcb07bd4524152ece0c62f051d7586a2c86a356113cde6f4a74af9e846ab7d80942b75e677af49805f378e31f4cf77b28a9c6a640f1ff0ba42b565c5bf82
7
+ data.tar.gz: bb83102634f7f0fd920fa56f55c48931b7af13a52b69655147295b1ba30ca12b00e524e5b28f2624b4fd53be3ea77e52d290f24b803074677aa679da39982977
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ Gemfile.lock
2
+
3
+ /.bundle/
4
+ /.yardoc
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.5.1
7
+ before_install: gem install bundler -v 1.16.6
data/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Change Log
2
+
3
+ ## 1.0.0 (2018-11-29)
4
+
5
+ - Initial release
6
+
7
+ ## 1.1.0 (2018-11-30)
8
+
9
+ - Add support for the latest MySQL dump format
10
+ - Mention support for the SQLite3 dump format
11
+
12
+ ## 1.1.1 (2021-04-28)
13
+
14
+ - Fix installation when the attribute file does not exist yet
15
+
16
+ ## 1.1.2 (2021-04-30)
17
+
18
+ - Implemnt local installation with --install=local
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in tt-git-merge-structure-sql.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2018-2021 Akinori MUSHA
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
+ SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # tt-git-merge-structure-sql
2
+
3
+ This is a merge driver for Git that resolves typical merge conflicts
4
+ in a `db/structure.sql` file of Rails.
5
+
6
+ When your project is configured with
7
+ `config.active_record.schema_format = :sql`, the database schema is
8
+ kept in `db/structure.sql` instead of `db/schema.rb` in the native
9
+ dump format of the underlying database engine, which is not suitable
10
+ for the default merge driver of Git to deal with. As a result, when
11
+ you try to merge two branches you always have to resolve trivial
12
+ conflicts manually if new schema migrations take place in both
13
+ branches. This custom driver takes away such a pain.
14
+
15
+ Currently only PostgreSQL, MySQL and SQLite3 dump formats are
16
+ supported.
17
+
18
+ ## Installation
19
+
20
+ Run this:
21
+
22
+ $ gem install tt-git-merge-structure-sql
23
+
24
+ And enable it yourself in your Git configuration, or let it do that
25
+ for you by this command:
26
+
27
+ $ tt-git-merge-structure-sql --install
28
+
29
+ This adds necessary settings to your `~/.gitconfig` or
30
+ `$XDG_CONFIG_HOME/git/config` and the default gitattributes(5) file to
31
+ enable the merge driver for structure.sql files.
32
+
33
+ If you want to enable this driver only in the current git directory,
34
+ run this:
35
+
36
+ $ tt-git-merge-structure-sql --install=local
37
+
38
+ ## Usage
39
+
40
+ Once enabled, Git should call this driver as necessary when it needs
41
+ to merge changes made in structure.sql.
42
+
43
+ ## History
44
+
45
+ See `CHANGELOG.md` for the version history.
46
+
47
+ ## Author
48
+
49
+ Copyright (c) 2018-2021 Akinori MUSHA.
50
+
51
+ Licensed under the 2-clause BSD license. See `LICENSE.txt` for
52
+ details.
53
+
54
+ Visit the [GitHub Repository](https://github.com/knu/sidetiq-timezone)
55
+ for the latest information.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tt-git-merge-structure-sql"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tt-git-merge-structure-sql"
4
+
5
+ StructureSqlMergeDriver.new.main(*ARGV)
@@ -0,0 +1,293 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # tt-git-merge-structure-sql - git merge driver for db/structure.sql in a Rails project
5
+ #
6
+ # How to use:
7
+ # $ tt-git-merge-structure-sql --install
8
+ #
9
+ # Copyright (c) 2018-2021 Akinori MUSHA
10
+ #
11
+ # All rights reserved.
12
+ #
13
+ # Redistribution and use in source and binary forms, with or without
14
+ # modification, are permitted provided that the following conditions
15
+ # are met:
16
+ # 1. Redistributions of source code must retain the above copyright
17
+ # notice, this list of conditions and the following disclaimer.
18
+ # 2. Redistributions in binary form must reproduce the above copyright
19
+ # notice, this list of conditions and the following disclaimer in the
20
+ # documentation and/or other materials provided with the distribution.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
+ # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
+ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
+ # SUCH DAMAGE.
33
+ #
34
+
35
+ class StructureSqlMergeDriver
36
+ VERSION = '1.1.2'
37
+ VARIANTS = []
38
+
39
+ module Default # This covers PostgreSQL, SQLite and newer MySQL formats.
40
+ RE_VERSION = /^\('(\d+)'\)[,;]\n/
41
+ RE_VERSIONS = /^INSERT INTO (?<q>["`])schema_migrations\k<q> \(version\) VALUES\n\K#{RE_VERSION}+/
42
+
43
+ class << self
44
+ def match?(content)
45
+ RE_VERSIONS === content
46
+ end
47
+
48
+ def merge!(*contents)
49
+ merge_versions!(*contents)
50
+ end
51
+
52
+ private
53
+
54
+ def merge_versions!(*contents)
55
+ replacement = format_versions(
56
+ contents.inject([]) { |versions, content|
57
+ versions | content[RE_VERSIONS].scan(RE_VERSION).flatten
58
+ }.sort
59
+ )
60
+
61
+ contents.each { |content|
62
+ content.sub!(RE_VERSIONS, replacement)
63
+ }
64
+ end
65
+
66
+ def format_versions(versions)
67
+ versions.map { |version| "('%s')" % version }.join(",\n") << ";\n"
68
+ end
69
+ end
70
+
71
+ VARIANTS.unshift self
72
+ end
73
+
74
+ module Postgresql # This covers PostgreSQL with leading commas
75
+ RE_VERSION = /^[, ]\('(\d+)'\)\n/
76
+ RE_VERSIONS = /^INSERT INTO (?<q>["`])schema_migrations\k<q> \(version\) VALUES\n\K#{RE_VERSION}+;/
77
+
78
+ class << self
79
+ def match?(content)
80
+ RE_VERSIONS === content
81
+ end
82
+
83
+ def merge!(*contents)
84
+ merge_versions!(*contents)
85
+ end
86
+
87
+ private
88
+
89
+ def merge_versions!(*contents)
90
+ replacement = format_versions(
91
+ contents.inject([]) { |versions, content|
92
+ versions | content[RE_VERSIONS].scan(RE_VERSION).flatten
93
+ }.sort
94
+ )
95
+
96
+ contents.each { |content|
97
+ content.sub!(RE_VERSIONS, replacement)
98
+ }
99
+ end
100
+
101
+ def format_versions(versions)
102
+ " " + versions.map { |version| "('%s')" % version }.join("\n,") << "\n;"
103
+ end
104
+ end
105
+
106
+ VARIANTS.unshift self
107
+ end
108
+
109
+ module MySQL
110
+ class << self
111
+ RE_DUMP_TIMESTAMP = /^-- Dump completed on \K.+$/
112
+ RE_AUTO_INCREMENT_VALUE = /^\)(?= ).*\K AUTO_INCREMENT=\d+(?=.*;$)/
113
+ RE_VERSION = /^INSERT INTO schema_migrations \(version\) VALUES \('(\d+)'\);\s+/
114
+ RE_VERSIONS = /#{RE_VERSION}+/
115
+
116
+ def match?(content)
117
+ /^-- MySQL dump / === content
118
+ end
119
+
120
+ def merge!(*contents)
121
+ merge_dump_timestamps!(*contents)
122
+ scrub_auto_increment_values!(*contents)
123
+ merge_versions!(*contents)
124
+ end
125
+
126
+ private
127
+
128
+ def merge_dump_timestamps!(*contents)
129
+ replacement = contents.inject('') { |timestamp, content|
130
+ [timestamp, *content.scan(RE_DUMP_TIMESTAMP)].max rescue ''
131
+ }
132
+
133
+ unless replacement.empty?
134
+ contents.each { |content|
135
+ content.gsub!(RE_DUMP_TIMESTAMP, replacement)
136
+ }
137
+ end
138
+ end
139
+
140
+ def scrub_auto_increment_values!(*contents)
141
+ contents.each { |content|
142
+ content.gsub!(RE_AUTO_INCREMENT_VALUE, '')
143
+ }
144
+ end
145
+
146
+ def merge_versions!(*contents)
147
+ replacement = format_versions(
148
+ contents.inject([]) { |versions, content|
149
+ versions | content.scan(RE_VERSION).flatten
150
+ }.sort
151
+ )
152
+
153
+ contents.each { |content|
154
+ content.sub!(RE_VERSIONS, replacement)
155
+ }
156
+ end
157
+
158
+ def format_versions(versions)
159
+ versions.map { |version| "INSERT INTO schema_migrations (version) VALUES ('%s');\n\n" % version }.join
160
+ end
161
+ end
162
+
163
+ VARIANTS.unshift self
164
+ end
165
+
166
+ def system!(*args)
167
+ system(*args) or exit $?.exitstatus
168
+ end
169
+
170
+ def main(*argv)
171
+ require 'optparse'
172
+ require 'shellwords'
173
+
174
+ myname = File.basename($0)
175
+ driver_name = 'merge-structure-sql'
176
+
177
+ banner = <<~EOF
178
+ #{myname} - git merge driver for db/structure.sql in a Rails project #{VERSION}
179
+
180
+ usage: #{myname} <current-file> <base-file> <other-file>
181
+ #{myname} --install
182
+
183
+ EOF
184
+
185
+ install = false
186
+
187
+ opts = OptionParser.new(banner) { |opts|
188
+ opts.version = VERSION
189
+ opts.summary_indent = ''
190
+ opts.summary_width = 24
191
+
192
+ opts.on('--install[={global|local}]',
193
+ "Enable this merge driver in Git (default: global)") { |val|
194
+ case install = val&.to_sym || :global
195
+ when :global, :local
196
+ # ok
197
+ else
198
+ raise OptionParser::InvalidArgument, "--install=#{val}: unknown argument"
199
+ end
200
+ }
201
+ }
202
+
203
+ files = opts.order(argv)
204
+
205
+ if install
206
+ global = install == :global
207
+
208
+ git_config = ["git", "config", *("--global" if global)]
209
+
210
+ config_file = `GIT_EDITOR=echo #{git_config.shelljoin} -e 2>/dev/null`.chomp
211
+
212
+ puts "#{config_file}: Adding the \"#{driver_name}\" driver definition"
213
+
214
+ system!(
215
+ *git_config,
216
+ "merge.#{driver_name}.name",
217
+ "Rails structure.sql merge driver"
218
+ )
219
+ system!(
220
+ *git_config,
221
+ "merge.#{driver_name}.driver",
222
+ "#{myname.shellescape} %A %O %B"
223
+ )
224
+
225
+ attributes_file =
226
+ if global
227
+ filename = `git config --global core.attributesfile`.chomp
228
+
229
+ if $?.success?
230
+ File.expand_path(filename)
231
+ else
232
+ [
233
+ [File.join(ENV['XDG_CONFIG_HOME'] || '~/.config', 'git'), 'attributes'],
234
+ ['~', '.gitattributes']
235
+ ].find { |dir, file|
236
+ if File.directory?(File.expand_path(dir))
237
+ system!(*%W[
238
+ git config --global core.attributesfile #{File.join(dir, file)}
239
+ ])
240
+ break File.expand_path(file, dir)
241
+ end
242
+ } or raise "don't you have home?"
243
+ end
244
+ else
245
+ git_dir = `git rev-parse --git-dir`.chomp
246
+
247
+ if $?.success?
248
+ File.expand_path(File.join('info', 'attributes'), git_dir)
249
+ else
250
+ raise "not in a git directory"
251
+ end
252
+ end
253
+
254
+ File.open(attributes_file, 'a+') { |f|
255
+ pattern = /^\s*structure.sql\s+(?:\S+\s+)*merge=#{Regexp.quote(driver_name)}(?:\s|$)/
256
+ break if f.any? { |line| pattern === line }
257
+
258
+ puts "#{attributes_file}: Registering the \"#{driver_name}\" driver for structure.sql"
259
+ f.puts if f.pos > 0
260
+ f.puts "structure.sql merge=#{driver_name}"
261
+ }
262
+
263
+ exit
264
+ end
265
+
266
+ unless files.size == 3
267
+ STDERR.print opts.help
268
+ exit 64
269
+ end
270
+
271
+ contents = files.map { |file| File.read(file) }
272
+
273
+ sample = contents[0]
274
+ if variant = VARIANTS.find { |v| v.match?(sample) }
275
+ variant.merge!(*contents)
276
+
277
+ files.zip(contents) do |file, content|
278
+ File.write(file, content)
279
+ end
280
+ else
281
+ STDERR.puts "#{myname}: Unsupported format; falling back to git-merge-file(1)"
282
+ end
283
+
284
+ exec(*%W[git merge-file -q], *files)
285
+ rescue => e
286
+ STDERR.puts "#{myname}: #{e.message}"
287
+ exit 1
288
+ end
289
+ end
290
+
291
+ if $0 == __FILE__
292
+ StructureSqlMergeDriver.new.main(*ARGV)
293
+ end
@@ -0,0 +1,34 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "tt-git-merge-structure-sql"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tt-git-merge-structure-sql"
8
+ spec.version = StructureSqlMergeDriver::VERSION
9
+ spec.authors = ["Akinori MUSHA", "Jonas Brusman"]
10
+ spec.email = ["knu@idaemons.org"]
11
+ spec.license = "BSD-2-Clause"
12
+
13
+ spec.summary = %q{git merge driver for db/structure.sql in a Rails project}
14
+ spec.homepage = "https://github.com/teamtailor/git-merge-structure-sql"
15
+
16
+ if spec.respond_to?(:metadata)
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = "https://github.com/teamtailor/git-merge-structure-sql/blob/master/CHANGELOG.md"
20
+ end
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ end
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.add_development_dependency "bundler", "~> 2.2"
32
+ spec.add_development_dependency "rake", "~> 13.0"
33
+ spec.add_development_dependency "rspec", "~> 3.0"
34
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tt-git-merge-structure-sql
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Akinori MUSHA
8
+ - Jonas Brusman
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2024-07-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '2.2'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '2.2'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '13.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '13.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.0'
56
+ description:
57
+ email:
58
+ - knu@idaemons.org
59
+ executables:
60
+ - tt-git-merge-structure-sql
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - ".rspec"
66
+ - ".travis.yml"
67
+ - CHANGELOG.md
68
+ - Gemfile
69
+ - LICENSE.txt
70
+ - README.md
71
+ - Rakefile
72
+ - bin/console
73
+ - bin/setup
74
+ - exe/tt-git-merge-structure-sql
75
+ - lib/tt-git-merge-structure-sql.rb
76
+ - tt-git-merge-structure-sql.gemspec
77
+ homepage: https://github.com/teamtailor/git-merge-structure-sql
78
+ licenses:
79
+ - BSD-2-Clause
80
+ metadata:
81
+ homepage_uri: https://github.com/teamtailor/git-merge-structure-sql
82
+ source_code_uri: https://github.com/teamtailor/git-merge-structure-sql
83
+ changelog_uri: https://github.com/teamtailor/git-merge-structure-sql/blob/master/CHANGELOG.md
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubygems_version: 3.4.10
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: git merge driver for db/structure.sql in a Rails project
103
+ test_files: []