librarianp 0.1.2

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.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +10 -0
  5. data/CHANGELOG.md +255 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +235 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +55 -0
  10. data/Rakefile +28 -0
  11. data/VERSION +1 -0
  12. data/lib/librarian/action/base.rb +24 -0
  13. data/lib/librarian/action/clean.rb +44 -0
  14. data/lib/librarian/action/ensure.rb +24 -0
  15. data/lib/librarian/action/install.rb +95 -0
  16. data/lib/librarian/action/persist_resolution_mixin.rb +51 -0
  17. data/lib/librarian/action/resolve.rb +46 -0
  18. data/lib/librarian/action/update.rb +44 -0
  19. data/lib/librarian/action.rb +5 -0
  20. data/lib/librarian/algorithms.rb +133 -0
  21. data/lib/librarian/cli/manifest_presenter.rb +89 -0
  22. data/lib/librarian/cli.rb +225 -0
  23. data/lib/librarian/config/database.rb +205 -0
  24. data/lib/librarian/config/file_source.rb +47 -0
  25. data/lib/librarian/config/hash_source.rb +33 -0
  26. data/lib/librarian/config/source.rb +149 -0
  27. data/lib/librarian/config.rb +7 -0
  28. data/lib/librarian/dependency.rb +153 -0
  29. data/lib/librarian/dsl/receiver.rb +42 -0
  30. data/lib/librarian/dsl/target.rb +171 -0
  31. data/lib/librarian/dsl.rb +102 -0
  32. data/lib/librarian/environment/runtime_cache.rb +101 -0
  33. data/lib/librarian/environment.rb +230 -0
  34. data/lib/librarian/error.rb +4 -0
  35. data/lib/librarian/helpers.rb +29 -0
  36. data/lib/librarian/linter/source_linter.rb +55 -0
  37. data/lib/librarian/lockfile/compiler.rb +66 -0
  38. data/lib/librarian/lockfile/parser.rb +123 -0
  39. data/lib/librarian/lockfile.rb +29 -0
  40. data/lib/librarian/logger.rb +46 -0
  41. data/lib/librarian/manifest.rb +146 -0
  42. data/lib/librarian/manifest_set.rb +150 -0
  43. data/lib/librarian/mock/cli.rb +19 -0
  44. data/lib/librarian/mock/dsl.rb +15 -0
  45. data/lib/librarian/mock/environment.rb +21 -0
  46. data/lib/librarian/mock/extension.rb +9 -0
  47. data/lib/librarian/mock/source/mock/registry.rb +83 -0
  48. data/lib/librarian/mock/source/mock.rb +80 -0
  49. data/lib/librarian/mock/source.rb +1 -0
  50. data/lib/librarian/mock/version.rb +5 -0
  51. data/lib/librarian/mock.rb +1 -0
  52. data/lib/librarian/posix.rb +129 -0
  53. data/lib/librarian/resolution.rb +46 -0
  54. data/lib/librarian/resolver/implementation.rb +238 -0
  55. data/lib/librarian/resolver.rb +94 -0
  56. data/lib/librarian/rspec/support/cli_macro.rb +120 -0
  57. data/lib/librarian/source/basic_api.rb +45 -0
  58. data/lib/librarian/source/git/repository.rb +193 -0
  59. data/lib/librarian/source/git.rb +172 -0
  60. data/lib/librarian/source/local.rb +54 -0
  61. data/lib/librarian/source/path.rb +56 -0
  62. data/lib/librarian/source.rb +2 -0
  63. data/lib/librarian/spec.rb +13 -0
  64. data/lib/librarian/spec_change_set.rb +173 -0
  65. data/lib/librarian/specfile.rb +19 -0
  66. data/lib/librarian/support/abstract_method.rb +21 -0
  67. data/lib/librarian/ui.rb +64 -0
  68. data/lib/librarian/version.rb +3 -0
  69. data/lib/librarian.rb +11 -0
  70. data/librarian.gemspec +47 -0
  71. data/spec/functional/cli_spec.rb +27 -0
  72. data/spec/functional/posix_spec.rb +32 -0
  73. data/spec/functional/source/git/repository_spec.rb +199 -0
  74. data/spec/functional/source/git_spec.rb +174 -0
  75. data/spec/support/fakefs.rb +37 -0
  76. data/spec/support/method_patch_macro.rb +30 -0
  77. data/spec/support/project_path_macro.rb +14 -0
  78. data/spec/support/with_env_macro.rb +22 -0
  79. data/spec/unit/action/base_spec.rb +18 -0
  80. data/spec/unit/action/clean_spec.rb +102 -0
  81. data/spec/unit/action/ensure_spec.rb +37 -0
  82. data/spec/unit/action/install_spec.rb +111 -0
  83. data/spec/unit/algorithms_spec.rb +131 -0
  84. data/spec/unit/config/database_spec.rb +320 -0
  85. data/spec/unit/dependency/requirement_spec.rb +12 -0
  86. data/spec/unit/dependency_spec.rb +212 -0
  87. data/spec/unit/dsl_spec.rb +173 -0
  88. data/spec/unit/environment/runtime_cache_spec.rb +73 -0
  89. data/spec/unit/environment_spec.rb +209 -0
  90. data/spec/unit/lockfile/parser_spec.rb +162 -0
  91. data/spec/unit/lockfile_spec.rb +65 -0
  92. data/spec/unit/manifest/version_spec.rb +11 -0
  93. data/spec/unit/manifest_set_spec.rb +202 -0
  94. data/spec/unit/manifest_spec.rb +36 -0
  95. data/spec/unit/mock/environment_spec.rb +25 -0
  96. data/spec/unit/mock/source/mock_spec.rb +22 -0
  97. data/spec/unit/resolver_spec.rb +299 -0
  98. data/spec/unit/source/git_spec.rb +29 -0
  99. data/spec/unit/spec_change_set_spec.rb +169 -0
  100. metadata +257 -0
@@ -0,0 +1,320 @@
1
+ require "fileutils"
2
+ require "pathname"
3
+ require "tmpdir"
4
+ require "yaml"
5
+
6
+ require "support/fakefs"
7
+
8
+ require "librarian/config/database"
9
+
10
+ describe Librarian::Config::Database do
11
+ include ::Support::FakeFS
12
+
13
+ def write_yaml!(path, *yamlables)
14
+ path = Pathname(path)
15
+ path.dirname.mkpath unless path.dirname.directory?
16
+ File.open(path, "wb"){|f| yamlables.each{|y| YAML.dump(y, f)}}
17
+ end
18
+
19
+ let(:adapter_name) { "gem" }
20
+
21
+ let(:env) { { } }
22
+ let(:pwd) { Pathname(Dir.tmpdir) }
23
+ let(:home) { Pathname("~").expand_path }
24
+ let(:project_path) { nil }
25
+ let(:specfile_name) { nil }
26
+ let(:global) { home.join(".librarian/gem/config") }
27
+ let(:local) { pwd.join(".librarian/gem/config") }
28
+ let(:specfile) { pwd.join("Gemfile") }
29
+
30
+ before do
31
+ FileUtils.mkpath(pwd)
32
+ FileUtils.touch(specfile)
33
+ end
34
+
35
+ let(:database) do
36
+ described_class.new(adapter_name,
37
+ :env => env,
38
+ :pwd => pwd.to_s,
39
+ :home => home.to_s,
40
+ :project_path => project_path,
41
+ :specfile_name => specfile_name
42
+ )
43
+ end
44
+
45
+ context "when a key is given globally" do
46
+ let(:key) { "jam" }
47
+ let(:value) { "jelly" }
48
+ let(:raw_key) { "LIBRARIAN_GEM_JAM" }
49
+
50
+ before do
51
+ write_yaml! global, raw_key => value
52
+ end
53
+
54
+ it "should have the key globally" do
55
+ expect(database.global[key]).to eq value
56
+ end
57
+
58
+ it "should not have the key in the env" do
59
+ expect(database.env[key]).to be_nil
60
+ end
61
+
62
+ it "should not have the key locally" do
63
+ expect(database.local[key]).to be_nil
64
+ end
65
+
66
+ it "should have the key generally" do
67
+ expect(database[key]).to eq value
68
+ end
69
+ end
70
+
71
+ context "when a key is set globally" do
72
+ let(:key) { "jam" }
73
+ let(:value) { "jelly" }
74
+ let(:raw_key) { "LIBRARIAN_GEM_JAM" }
75
+
76
+ before do
77
+ database.global[key] = value
78
+ end
79
+
80
+ it "should have the key globally" do
81
+ expect(database.global[key]).to eq value
82
+ end
83
+
84
+ it "should not have the key in the env" do
85
+ expect(database.env[key]).to be_nil
86
+ end
87
+
88
+ it "should not have the key locally" do
89
+ expect(database.local[key]).to be_nil
90
+ end
91
+
92
+ it "should have the key generally" do
93
+ expect(database[key]).to eq value
94
+ end
95
+
96
+ it "should persist the key" do
97
+ data = YAML.load_file(global)
98
+
99
+ expect(data).to eq({raw_key => value})
100
+ end
101
+ end
102
+
103
+ context "when the key is set and unset globally" do
104
+ let(:key) { "jam" }
105
+ let(:value) { "jelly" }
106
+ let(:raw_key) { "LIBRARIAN_GEM_JAM" }
107
+
108
+ before do
109
+ database.global[key] = value
110
+ database.global[key] = nil
111
+ end
112
+
113
+ it "should not have the key globally" do
114
+ expect(database.global[key]).to be_nil
115
+ end
116
+
117
+ it "should not have the key in the env" do
118
+ expect(database.env[key]).to be_nil
119
+ end
120
+
121
+ it "should not have the key locally" do
122
+ expect(database.local[key]).to be_nil
123
+ end
124
+
125
+ it "should not have the key generally" do
126
+ expect(database[key]).to be_nil
127
+ end
128
+
129
+ it "should unpersist the key" do
130
+ expect(File).to_not exist global
131
+ end
132
+ end
133
+
134
+ context "when a key is given in the env" do
135
+ let(:key) { "jam" }
136
+ let(:value) { "jelly" }
137
+ let(:raw_key) { "LIBRARIAN_GEM_JAM" }
138
+
139
+ #override
140
+ let(:env) { {raw_key => value} }
141
+
142
+ it "should not have the key globally" do
143
+ expect(database.global[key]).to be_nil
144
+ end
145
+
146
+ it "should have the key in the env" do
147
+ expect(database.env[key]).to eq value
148
+ end
149
+
150
+ it "should not have the key locally" do
151
+ expect(database.local[key]).to be_nil
152
+ end
153
+
154
+ it "should have the key generally" do
155
+ expect(database[key]).to eq value
156
+ end
157
+ end
158
+
159
+ context "when a key is given locally" do
160
+ let(:key) { "jam" }
161
+ let(:value) { "jelly" }
162
+ let(:raw_key) { "LIBRARIAN_GEM_JAM" }
163
+
164
+ before do
165
+ write_yaml! local, raw_key => value
166
+ end
167
+
168
+ it "should not have the key globally" do
169
+ expect(database.global[key]).to be_nil
170
+ end
171
+
172
+ it "should not have the key in the env" do
173
+ expect(database.env[key]).to be_nil
174
+ end
175
+
176
+ it "should have the key locally" do
177
+ expect(database.local[key]).to eq value
178
+ end
179
+
180
+ it "should have the key generally" do
181
+ expect(database[key]).to eq value
182
+ end
183
+ end
184
+
185
+ context "when a key is set locally" do
186
+ let(:key) { "jam" }
187
+ let(:value) { "jelly" }
188
+ let(:raw_key) { "LIBRARIAN_GEM_JAM" }
189
+
190
+ before do
191
+ database.local[key] = value
192
+ end
193
+
194
+ it "should not have the key globally" do
195
+ expect(database.global[key]).to be_nil
196
+ end
197
+
198
+ it "should not have the key in the env" do
199
+ expect(database.env[key]).to be_nil
200
+ end
201
+
202
+ it "should have the key locally" do
203
+ expect(database.local[key]).to eq value
204
+ end
205
+
206
+ it "should have the key generally" do
207
+ expect(database[key]).to eq value
208
+ end
209
+
210
+ it "should persist the key" do
211
+ data = YAML.load_file(local)
212
+
213
+ expect(data).to eq({raw_key => value})
214
+ end
215
+ end
216
+
217
+ context "when the key is set and unset locally" do
218
+ let(:key) { "jam" }
219
+ let(:value) { "jelly" }
220
+ let(:raw_key) { "LIBRARIAN_GEM_JAM" }
221
+
222
+ before do
223
+ database.local[key] = value
224
+ database.local[key] = nil
225
+ end
226
+
227
+ it "should not have the key globally" do
228
+ expect(database.global[key]).to be_nil
229
+ end
230
+
231
+ it "should not have the key in the env" do
232
+ expect(database.env[key]).to be_nil
233
+ end
234
+
235
+ it "should not have the key locally" do
236
+ expect(database.local[key]).to be_nil
237
+ end
238
+
239
+ it "should not have the key generally" do
240
+ expect(database[key]).to be_nil
241
+ end
242
+
243
+ it "should unpersist the key" do
244
+ expect(File).to_not exist local
245
+ end
246
+ end
247
+
248
+ context "setting malformatted keys" do
249
+ it "should ban caps" do
250
+ expect { database.global["JAM"] = "jelly" }.
251
+ to raise_error Librarian::Error, %[key not permitted: "JAM"]
252
+ end
253
+
254
+ it "should ban double dots" do
255
+ expect { database.global["jam..jam"] = "jelly" }.
256
+ to raise_error Librarian::Error, %[key not permitted: "jam..jam"]
257
+ end
258
+ end
259
+
260
+ context "setting banned keys" do
261
+ it "should ban the specfile key" do
262
+ expect { database.global["gemfile"] = "jelly" }.
263
+ to raise_error Librarian::Error, %[key not permitted: "gemfile"]
264
+ end
265
+
266
+ it "should ban the global-config key" do
267
+ expect { database.global["config"] = "jelly" }.
268
+ to raise_error Librarian::Error, %[key not permitted: "config"]
269
+ end
270
+ end
271
+
272
+ context "project_path" do
273
+ context "by default" do
274
+ it "should give the default project path" do
275
+ expect(database.project_path).to eq Pathname("/tmp")
276
+ end
277
+ end
278
+
279
+ context "when the specfile is set in the env" do
280
+ let(:env) { {"LIBRARIAN_GEM_GEMFILE" => "/non/sense/path/to/Sillyfile"} }
281
+
282
+ it "should give the project path from the env-set specfile" do
283
+ expect(database.project_path).to eq Pathname("/non/sense/path/to")
284
+ end
285
+ end
286
+ end
287
+
288
+ context "specfile_path" do
289
+ context "by default" do
290
+ it "should give the default specfile path" do
291
+ expect(database.specfile_path).to eq specfile
292
+ end
293
+ end
294
+
295
+ context "when set in the env" do
296
+ let(:env) { {"LIBRARIAN_GEM_GEMFILE" => "/non/sense/path/to/Sillyfile"} }
297
+
298
+ it "should give the given specfile path" do
299
+ expect(database.specfile_path).to eq Pathname("/non/sense/path/to/Sillyfile")
300
+ end
301
+ end
302
+
303
+ context "when the project_path is assigned" do
304
+ let(:project_path) { "/non/sense/path/to" }
305
+
306
+ it "should give the assigned specfile path" do
307
+ expect(database.specfile_path).to eq Pathname("/non/sense/path/to/Gemfile")
308
+ end
309
+ end
310
+
311
+ context "when the specfile_name is assigned" do
312
+ let(:specfile_name) { "Sillyfile" }
313
+
314
+ it "should give the assigned specfile path" do
315
+ expect(database.specfile_path).to eq Pathname("/tmp/Sillyfile")
316
+ end
317
+ end
318
+ end
319
+
320
+ end
@@ -0,0 +1,12 @@
1
+ require "librarian/dependency"
2
+
3
+ describe Librarian::Dependency::Requirement do
4
+
5
+ describe "#inspect" do
6
+ subject(:requirement) { described_class.new(">= 3.2.1") }
7
+
8
+ specify { expect(requirement.inspect).
9
+ to eq "#<Librarian::Dependency::Requirement >= 3.2.1>" }
10
+ end
11
+
12
+ end
@@ -0,0 +1,212 @@
1
+ require "librarian/dependency"
2
+
3
+ describe Librarian::Dependency do
4
+
5
+ describe "validations" do
6
+
7
+ context "when the name is blank" do
8
+ it "raises" do
9
+ expect { described_class.new("", [], nil) }.
10
+ to raise_error(ArgumentError, %{name ("") must be sensible})
11
+ end
12
+ end
13
+
14
+ context "when the name has leading whitespace" do
15
+ it "raises" do
16
+ expect { described_class.new(" the-name", [], nil) }.
17
+ to raise_error(ArgumentError, %{name (" the-name") must be sensible})
18
+ end
19
+ end
20
+
21
+ context "when the name has trailing whitespace" do
22
+ it "raises" do
23
+ expect { described_class.new("the-name ", [], nil) }.
24
+ to raise_error(ArgumentError, %{name ("the-name ") must be sensible})
25
+ end
26
+ end
27
+
28
+ context "when the name is a single character" do
29
+ it "passes" do
30
+ described_class.new("R", [], nil)
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ describe "#consistent_with?" do
37
+ def req(s) described_class::Requirement.new(s) end
38
+ def self.assert_consistent(a, b)
39
+ /^(.+):(\d+):in `(.+)'$/ =~ caller.first
40
+ line = $2.to_i
41
+
42
+ title = "is consistent with #{a.inspect} and #{b.inspect}"
43
+ module_eval <<-CODE, __FILE__, line
44
+ it #{title.inspect} do
45
+ a, b = req(#{a.inspect}), req(#{b.inspect})
46
+ expect(a).to be_consistent_with(b)
47
+ expect(a).to_not be_inconsistent_with(b)
48
+ expect(b).to be_consistent_with(a)
49
+ expect(b).to_not be_inconsistent_with(a)
50
+ end
51
+ CODE
52
+ end
53
+ def self.refute_consistent(a, b)
54
+ /^(.+):(\d+):in `(.+)'$/ =~ caller.first
55
+ line = $2.to_i
56
+
57
+ title = "is inconsistent with #{a.inspect} and #{b.inspect}"
58
+ module_eval <<-CODE, __FILE__, line
59
+ it #{title.inspect} do
60
+ a, b = req(#{a.inspect}), req(#{b.inspect})
61
+ expect(a).to_not be_consistent_with(b)
62
+ expect(a).to be_inconsistent_with(b)
63
+ expect(b).to_not be_consistent_with(a)
64
+ expect(b).to be_inconsistent_with(a)
65
+ end
66
+ CODE
67
+ end
68
+
69
+ # = =
70
+ assert_consistent "3", "3"
71
+ refute_consistent "3", "4"
72
+ refute_consistent "3", "0"
73
+ refute_consistent "0", "3"
74
+
75
+ # = !=
76
+ assert_consistent "3", "!= 4"
77
+ assert_consistent "3", "!= 0"
78
+ refute_consistent "3", "!= 3"
79
+
80
+ # = >
81
+ assert_consistent "3", "> 2"
82
+ refute_consistent "3", "> 3"
83
+ refute_consistent "3", "> 4"
84
+
85
+ # = <
86
+ assert_consistent "3", "< 4"
87
+ refute_consistent "3", "< 3"
88
+ refute_consistent "3", "< 2"
89
+
90
+ # = >=
91
+ assert_consistent "3", ">= 2"
92
+ assert_consistent "3", ">= 3"
93
+ refute_consistent "3", ">= 4"
94
+
95
+ # = <=
96
+ assert_consistent "3", "<= 4"
97
+ assert_consistent "3", "<= 3"
98
+ refute_consistent "3", "<= 2"
99
+
100
+ # = ~>
101
+ assert_consistent "3.4.1", "~> 3.4.1"
102
+ assert_consistent "3.4.2", "~> 3.4.1"
103
+ refute_consistent "3.4", "~> 3.4.1"
104
+ refute_consistent "3.5", "~> 3.4.1"
105
+
106
+ # != !=
107
+ assert_consistent "!= 3", "!= 3"
108
+ assert_consistent "!= 3", "!= 4"
109
+
110
+ # != >
111
+ assert_consistent "!= 3", "> 2"
112
+ assert_consistent "!= 3", "> 3"
113
+ assert_consistent "!= 3", "> 4"
114
+
115
+ # != <
116
+ assert_consistent "!= 3", "< 2"
117
+ assert_consistent "!= 3", "< 3"
118
+ assert_consistent "!= 3", "< 4"
119
+
120
+ # != >=
121
+ assert_consistent "!= 3", ">= 2"
122
+ assert_consistent "!= 3", ">= 3"
123
+ assert_consistent "!= 3", ">= 4"
124
+
125
+ # != <=
126
+ assert_consistent "!= 3", "<= 2"
127
+ assert_consistent "!= 3", "<= 3"
128
+ assert_consistent "!= 3", "<= 4"
129
+
130
+ # != ~>
131
+ assert_consistent "!= 3.4.1", "~> 3.4.1"
132
+ assert_consistent "!= 3.4.2", "~> 3.4.1"
133
+ assert_consistent "!= 3.5", "~> 3.4.1"
134
+
135
+ # > >
136
+ assert_consistent "> 3", "> 2"
137
+ assert_consistent "> 3", "> 3"
138
+ assert_consistent "> 3", "> 4"
139
+
140
+ # > <
141
+ assert_consistent "> 3", "< 4"
142
+ refute_consistent "> 3", "< 3"
143
+ refute_consistent "> 3", "< 2"
144
+
145
+ # > >=
146
+ assert_consistent "> 3", ">= 2"
147
+ assert_consistent "> 3", ">= 3"
148
+ assert_consistent "> 3", ">= 4"
149
+
150
+ # > <=
151
+ assert_consistent "> 3", "<= 4"
152
+ refute_consistent "> 3", "<= 3"
153
+ refute_consistent "> 3", "<= 2"
154
+
155
+ # > ~>
156
+ assert_consistent "> 3.3", "~> 3.4.1"
157
+ assert_consistent "> 3.4.1", "~> 3.4.1"
158
+ assert_consistent "> 3.4.2", "~> 3.4.1"
159
+ refute_consistent "> 3.5", "~> 3.4.1"
160
+
161
+ # < <
162
+ assert_consistent "< 3", "< 2"
163
+ assert_consistent "< 3", "< 3"
164
+ assert_consistent "< 3", "< 4"
165
+
166
+ # < >=
167
+ assert_consistent "< 3", ">= 2"
168
+ refute_consistent "< 3", ">= 3"
169
+ refute_consistent "< 3", ">= 4"
170
+
171
+ # < <=
172
+ assert_consistent "< 3", "<= 2"
173
+ assert_consistent "< 3", "<= 3"
174
+ assert_consistent "< 3", "<= 4"
175
+
176
+ # >= >=
177
+ assert_consistent ">= 3", ">= 2"
178
+ assert_consistent ">= 3", ">= 3"
179
+ assert_consistent ">= 3", ">= 4"
180
+
181
+ # >= <=
182
+ assert_consistent ">= 3", "<= 4"
183
+ assert_consistent ">= 3", "<= 3"
184
+ refute_consistent ">= 3", "<= 2"
185
+
186
+ # >= ~>
187
+ assert_consistent ">= 3.3", "~> 3.4.1"
188
+ assert_consistent ">= 3.4.1", "~> 3.4.1"
189
+ assert_consistent ">= 3.4.2", "~> 3.4.1"
190
+ refute_consistent ">= 3.5", "~> 3.4.1"
191
+
192
+ # <= <=
193
+ assert_consistent "<= 3", "<= 2"
194
+ assert_consistent "<= 3", "<= 3"
195
+ assert_consistent "<= 3", "<= 4"
196
+
197
+ # <= ~>
198
+ assert_consistent "<= 3.5", "~> 3.4.1"
199
+ assert_consistent "<= 3.4.1", "~> 3.4.1"
200
+ assert_consistent "<= 3.4.2", "~> 3.4.1"
201
+ refute_consistent "<= 3.3", "~> 3.4.1"
202
+
203
+ # ~> ~>
204
+ assert_consistent "~> 3.4.1", "~> 3.4.1"
205
+ assert_consistent "~> 3.4.2", "~> 3.4.1"
206
+ assert_consistent "~> 3.3", "~> 3.4.1"
207
+ refute_consistent "~> 3.3.3", "~> 3.4.1"
208
+ refute_consistent "~> 3.5", "~> 3.4.1"
209
+ refute_consistent "~> 3.5.4", "~> 3.4.1"
210
+ end
211
+
212
+ end