librarianp 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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