molinillo 0.5.4 → 0.5.5

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
  SHA1:
3
- metadata.gz: f53e46c97a53227bf496401139787e902f29c31c
4
- data.tar.gz: 4c702b61c8eb41ddbcb899579e226588ca6ea8c1
3
+ metadata.gz: a3f407e98934857813a1d4e17fbf807171bfbd02
4
+ data.tar.gz: 5ca9cff1741fb50a1c8767a7fb6aadc6465d1b70
5
5
  SHA512:
6
- metadata.gz: 531ffbe26a13d5c3d9883b4de8b0f5d01d3df2aeba3b6f6bfe5ebbbed06187f0594aab1532268894ad8e7f12bef790cc68ebc8e1ef0ebd2e86eac8f74c3a0941
7
- data.tar.gz: 1323d5f6cad31427e8bf44e07237de6ee8f9c1f272ec3a2ad803cd33684f634f4d0f6d86013fc49c84c981bddf856638eab1dda7906a397712e9fb8854660a31
6
+ metadata.gz: 0a683263d7bf6566b74e88d948c20a6b2ec18cbbf26ae68e335ec27ab61708c25b9565329b6295e90bad515322196792d94df6f1d651997d84f32066253b6d85
7
+ data.tar.gz: d529667799bbb115b1fadd3fffa107fadca0ec456b0c00a97af9404713b45d1ec6a4ae54a8f2309acd68ea068018f7cf63c494b91effcbbf80fc112390340bbb
@@ -119,6 +119,7 @@ module Molinillo
119
119
  # {Vertex#successors}
120
120
  def ==(other)
121
121
  return false unless other
122
+ return true if equal?(other)
122
123
  vertices.each do |name, vertex|
123
124
  other_vertex = other.vertex_named(name)
124
125
  return false unless other_vertex
@@ -134,6 +135,7 @@ module Molinillo
134
135
  def add_child_vertex(name, payload, parent_names, requirement)
135
136
  root = !parent_names.delete(nil) { true }
136
137
  vertex = add_vertex(name, payload, root)
138
+ vertex.explicit_requirements << requirement if root
137
139
  parent_names.each do |parent_name|
138
140
  parent_node = vertex_named(parent_name)
139
141
  add_edge(parent_node, vertex, requirement)
@@ -152,7 +154,7 @@ module Molinillo
152
154
  # Detaches the {#vertex_named} `name` {Vertex} from the graph, recursively
153
155
  # removing any non-root vertices that were orphaned in the process
154
156
  # @param [String] name
155
- # @return [void]
157
+ # @return [Array<Vertex>] the vertices which have been detached
156
158
  def detach_vertex_named(name)
157
159
  log.detach_vertex_named(self, name)
158
160
  end
@@ -14,16 +14,23 @@ module Molinillo
14
14
 
15
15
  # (see Action#up)
16
16
  def up(graph)
17
- return unless @vertex = graph.vertices.delete(name)
17
+ return [] unless @vertex = graph.vertices.delete(name)
18
+
19
+ removed_vertices = [@vertex]
18
20
  @vertex.outgoing_edges.each do |e|
19
21
  v = e.destination
20
22
  v.incoming_edges.delete(e)
21
- graph.detach_vertex_named(v.name) unless v.root? || v.predecessors.any?
23
+ if !v.root? && v.incoming_edges.empty?
24
+ removed_vertices.concat graph.detach_vertex_named(v.name)
25
+ end
22
26
  end
27
+
23
28
  @vertex.incoming_edges.each do |e|
24
29
  v = e.origin
25
30
  v.outgoing_edges.delete(e)
26
31
  end
32
+
33
+ removed_vertices
27
34
  end
28
35
 
29
36
  # (see Action#down)
@@ -81,6 +81,7 @@ module Molinillo
81
81
  # @return [Boolean] whether the two vertices are equal, determined
82
82
  # by a recursive traversal of each {Vertex#successors}
83
83
  def ==(other)
84
+ return true if equal?(other)
84
85
  shallow_eql?(other) &&
85
86
  successors.to_set == other.successors.to_set
86
87
  end
@@ -89,6 +90,7 @@ module Molinillo
89
90
  # @return [Boolean] whether the two vertices are equal, determined
90
91
  # solely by {#name} and {#payload} equality
91
92
  def shallow_eql?(other)
93
+ return true if equal?(other)
92
94
  other &&
93
95
  name == other.name &&
94
96
  payload == other.payload
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module Molinillo
3
3
  # The version of Molinillo.
4
- VERSION = '0.5.4'.freeze
4
+ VERSION = '0.5.5'.freeze
5
5
  end
@@ -366,13 +366,12 @@ module Molinillo
366
366
  if matching_deps.empty? && !succ.root? && succ.predecessors.to_a == [vertex]
367
367
  debug(depth) { "Removing orphaned spec #{succ.name} after swapping #{name}" }
368
368
  succ.requirements.each { |r| @parent_of.delete(r) }
369
- activated.detach_vertex_named(succ.name)
370
369
 
371
- all_successor_names = succ.recursive_successors.map(&:name)
372
-
373
- requirements.delete_if do |requirement|
374
- requirement_name = name_for(requirement)
375
- (requirement_name == succ.name) || all_successor_names.include?(requirement_name)
370
+ removed_names = activated.detach_vertex_named(succ.name).map(&:name)
371
+ requirements.delete_if do |r|
372
+ # the only removed vertices are those with no other requirements,
373
+ # so it's safe to delete only based upon name here
374
+ removed_names.include?(name_for(r))
376
375
  end
377
376
  elsif !matching_deps.include?(outgoing_edge.requirement)
378
377
  activated.delete_edge(outgoing_edge)
@@ -57,7 +57,7 @@ module Molinillo
57
57
  @graph.detach_vertex_named(root.name)
58
58
  expect(@graph.vertex_named(root.name)).to be_nil
59
59
  expect(@graph.vertex_named(child.name)).to eq(child)
60
- expect(child.predecessors).to eq([root2])
60
+ expect(child.predecessors).to contain_exactly(root2)
61
61
  expect(@graph.vertices.count).to eq(2)
62
62
  end
63
63
 
data/spec/fuzz_spec.rb ADDED
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+ require 'spec_helper/naive_resolver'
4
+
5
+ describe 'fuzzing' do
6
+ CONSTRAINTS = %w(<= ~> > < >= =).freeze
7
+ let(:dependencies) do
8
+ index.specs.keys.sample(Random.rand(5)).
9
+ map do |d|
10
+ VersionKit::Dependency.new(
11
+ d,
12
+ "#{CONSTRAINTS.sample} #{Random.rand(2)}.#{Random.rand(2)}"
13
+ )
14
+ end
15
+ end
16
+ let(:index) { Molinillo::TestIndex.from_fixture('fuzz') }
17
+ let(:ui) { Molinillo::TestUI.new }
18
+ let(:resolver) { Molinillo::Resolver.new(index, ui) }
19
+
20
+ subject { resolver.resolve(dependencies) }
21
+
22
+ def validate_dependency_graph_from(graph, dependency)
23
+ vertex = graph.vertex_named(dependency.name)
24
+ spec = vertex.payload
25
+ expect(dependency).to be_satisfied_by(spec.version)
26
+ expect(spec.dependencies).to match_array(vertex.outgoing_edges.map(&:requirement))
27
+ spec.dependencies.each do |d|
28
+ validate_dependency_graph_from(graph, d)
29
+ end
30
+ end
31
+
32
+ def validate_dependency_graph(graph)
33
+ dependencies.each do |d|
34
+ validate_dependency_graph_from(graph, d)
35
+ end
36
+ end
37
+
38
+ def all_possible_graphs
39
+ dependencies.reduce([]) { |d| strings(graphs, d) }
40
+ end
41
+
42
+ let(:naive) { Molinillo::NaiveResolver.resolve(index, dependencies) }
43
+
44
+ def validate_unresolvable(error)
45
+ expect(naive).to be_nil,
46
+ 'Got an error resolving but the naive resolver found ' \
47
+ "#{naive && naive.map(&:payload).map(&:to_s)}:\n#{error}"
48
+ end
49
+
50
+ def self.fuzz!(seeds = [])
51
+ seeds.each do |seed|
52
+ it "fuzzes with seed #{seed}" do
53
+ Random.srand seed
54
+ graph, error = begin
55
+ subject
56
+ [subject, nil]
57
+ rescue => e
58
+ [nil, e]
59
+ end
60
+ validate_dependency_graph(graph) if graph
61
+ validate_unresolvable(error) if error
62
+ expect(graph).to eq(naive),
63
+ "#{graph && graph.map(&:payload).map(&:to_s)} vs #{naive && naive.map(&:payload).map(&:to_s)}"
64
+ end
65
+ end
66
+ end
67
+
68
+ fuzz! [
69
+ 8,
70
+ 9,
71
+ 125,
72
+ 188,
73
+ 666,
74
+ 7_898_789,
75
+ 0.35096144504316984,
76
+ 3.14159,
77
+ ].concat(Array.new(ENV.fetch('MOLINILLO_FUZZER', '0').to_i) { Random.rand })
78
+ end if RUBY_VERSION >= '1.9'
@@ -1,25 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
  require File.expand_path('../spec_helper', __FILE__)
3
- require 'json'
4
- require 'pathname'
5
3
 
6
4
  module Molinillo
7
- FIXTURE_DIR = Pathname.new('spec/resolver_integration_specs')
8
- FIXTURE_INDEX_DIR = FIXTURE_DIR + 'index'
9
5
  FIXTURE_CASE_DIR = FIXTURE_DIR + 'case'
10
6
 
11
7
  class TestCase
12
- require File.expand_path('../spec_helper/index', __FILE__)
13
- require File.expand_path('../spec_helper/specification', __FILE__)
14
- require File.expand_path('../spec_helper/ui', __FILE__)
15
-
16
8
  attr_accessor :name, :requested, :base, :conflicts, :resolver, :result, :index
17
9
 
18
10
  def initialize(fixture_path)
19
11
  File.open(fixture_path) do |fixture|
20
12
  JSON.load(fixture).tap do |test_case|
21
13
  self.name = test_case['name']
22
- self.index = TestIndex.new(test_case['index'] || 'awesome')
14
+ self.index = TestIndex.from_fixture(test_case['index'] || 'awesome')
23
15
  self.requested = test_case['requested'].map do |(name, reqs)|
24
16
  VersionKit::Dependency.new name, reqs.split(',').map(&:chomp)
25
17
  end
@@ -90,7 +82,7 @@ module Molinillo
90
82
 
91
83
  describe 'in general' do
92
84
  before do
93
- @resolver = described_class.new(TestIndex.new('awesome'), TestUI.new)
85
+ @resolver = described_class.new(TestIndex.from_fixture('awesome'), TestUI.new)
94
86
  end
95
87
 
96
88
  it 'can resolve a list of 0 requirements' do
@@ -122,7 +114,7 @@ module Molinillo
122
114
  end
123
115
 
124
116
  it 'can resolve when two specs have the same dependencies' do
125
- index = BundlerIndex.new('rubygems-2016-09-11')
117
+ index = BundlerIndex.from_fixture('rubygems-2016-09-11')
126
118
  @resolver = described_class.new(index, TestUI.new)
127
119
  demands = [
128
120
  VersionKit::Dependency.new('chef', '~> 12.1.2'),
@@ -182,7 +174,7 @@ module Molinillo
182
174
  end
183
175
 
184
176
  it 'can resolve when two specs have the same dependencies and swapping happens' do
185
- index = BundlerIndex.new('rubygems-2016-10-06')
177
+ index = BundlerIndex.from_fixture('rubygems-2016-10-06')
186
178
  @resolver = described_class.new(index, TestUI.new)
187
179
  demands = [
188
180
  VersionKit::Dependency.new('avro_turf', '0.6.2'),
@@ -243,7 +235,7 @@ module Molinillo
243
235
  end
244
236
 
245
237
  it 'can unwind when the conflict has a common parent' do
246
- index = BundlerIndex.new('rubygems-2016-11-05')
238
+ index = BundlerIndex.from_fixture('rubygems-2016-11-05')
247
239
  @resolver = described_class.new(index, TestUI.new)
248
240
  demands = [
249
241
  VersionKit::Dependency.new('github-pages', '>= 0'),
@@ -256,7 +248,7 @@ module Molinillo
256
248
  end
257
249
 
258
250
  it 'can resolve when swapping changes transitive dependencies' do
259
- index = TestIndex.new('restkit')
251
+ index = TestIndex.from_fixture('restkit')
260
252
  def index.sort_dependencies(dependencies, activated, conflicts)
261
253
  dependencies.sort_by do |d|
262
254
  [
@@ -315,11 +307,11 @@ module Molinillo
315
307
  end
316
308
 
317
309
  def versions_of(dependency_name)
318
- specs[dependency_name].count
310
+ Array(specs[dependency_name]).count
319
311
  end
320
312
  end
321
313
 
322
- index = swap_child_with_successors_index.new('swap_child_with_successors')
314
+ index = swap_child_with_successors_index.from_fixture('swap_child_with_successors')
323
315
  @resolver = described_class.new(index, TestUI.new)
324
316
  demands = [
325
317
  VersionKit::Dependency.new('build-essential', '>= 0.0.0'),
@@ -340,6 +332,50 @@ module Molinillo
340
332
 
341
333
  expect(resolved.map(&:payload).map(&:to_s)).to match_array(expected)
342
334
  end
335
+
336
+ it 'can resolve ur face' do
337
+ index = TestIndex.new(
338
+ 'a' => [
339
+ TestSpecification.new('name' => 'a', 'version' => '1.0.0', 'dependencies' => { 'z' => '= 2.0.0' }),
340
+ TestSpecification.new('name' => 'a', 'version' => '2.0.0', 'dependencies' => { 'z' => '= 1.0.0' }),
341
+ ],
342
+ 'b' => [
343
+ TestSpecification.new('name' => 'b', 'version' => '1.0.0', 'dependencies' => { 'a' => '< 2' }),
344
+ TestSpecification.new('name' => 'b', 'version' => '2.0.0', 'dependencies' => { 'a' => '< 2' }),
345
+ ],
346
+ 'c' => [
347
+ TestSpecification.new('name' => 'c', 'version' => '1.0.0'),
348
+ TestSpecification.new('name' => 'c', 'version' => '2.0.0', 'dependencies' => { 'b' => '< 2' }),
349
+ ],
350
+ 'z' => [
351
+ TestSpecification.new('name' => 'z', 'version' => '1.0.0'),
352
+ TestSpecification.new('name' => 'z', 'version' => '2.0.0'),
353
+ ]
354
+ )
355
+ def index.sort_dependencies(dependencies, _activated, _conflicts)
356
+ index = ['c (>= 1.0.0)', 'b (< 2.0.0)', 'a (< 2.0.0)', 'c (= 1.0.0)']
357
+ dependencies.sort_by do |dep|
358
+ [
359
+ index.index(dep.to_s) || 999,
360
+ ]
361
+ end
362
+ end
363
+ @resolver = described_class.new(index, TestUI.new)
364
+ demands = [
365
+ VersionKit::Dependency.new('c', '= 1.0.0'),
366
+ VersionKit::Dependency.new('c', '>= 1.0.0'),
367
+ VersionKit::Dependency.new('z', '>= 1.0.0'),
368
+ ]
369
+
370
+ resolved = @resolver.resolve(demands, DependencyGraph.new)
371
+
372
+ expected = [
373
+ 'c (1.0.0)',
374
+ 'z (2.0.0)',
375
+ ]
376
+
377
+ expect(resolved.map(&:payload).map(&:to_s)).to match_array(expected)
378
+ end
343
379
  end
344
380
  end
345
381
  end
data/spec/spec_helper.rb CHANGED
@@ -24,6 +24,7 @@ end
24
24
  #-----------------------------------------------------------------------------#
25
25
 
26
26
  require 'pathname'
27
+ require 'json'
27
28
  ROOT = Pathname.new(File.expand_path('../../', __FILE__))
28
29
  $LOAD_PATH.unshift((ROOT + 'lib').to_s)
29
30
  $LOAD_PATH.unshift((ROOT + 'spec').to_s)
@@ -31,6 +32,10 @@ $LOAD_PATH.unshift((ROOT + 'spec').to_s)
31
32
  require 'version_kit'
32
33
  require 'molinillo'
33
34
 
35
+ require 'spec_helper/index'
36
+ require 'spec_helper/specification'
37
+ require 'spec_helper/ui'
38
+
34
39
  RSpec.configure do |config|
35
40
  # Enable flags like --only-failures and --next-failure
36
41
  config.example_status_persistence_file_path = '.rspec_status'
@@ -1,19 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
  module Molinillo
3
+ FIXTURE_DIR = Pathname.new('spec/resolver_integration_specs')
4
+ FIXTURE_INDEX_DIR = FIXTURE_DIR + 'index'
5
+
3
6
  class TestIndex
4
7
  attr_accessor :specs
5
8
  include SpecificationProvider
6
9
 
7
- def initialize(fixture_name)
10
+ def self.from_fixture(fixture_name)
8
11
  File.open(FIXTURE_INDEX_DIR + (fixture_name + '.json'), 'r') do |fixture|
9
- self.specs = JSON.load(fixture).reduce(Hash.new([])) do |specs_by_name, (name, versions)|
12
+ sorted_specs = JSON.load(fixture).reduce(Hash.new([])) do |specs_by_name, (name, versions)|
10
13
  specs_by_name.tap do |specs|
11
14
  specs[name] = versions.map { |s| TestSpecification.new s }.sort_by(&:version)
12
15
  end
13
16
  end
17
+ return new(sorted_specs)
14
18
  end
15
19
  end
16
20
 
21
+ def initialize(specs_by_name)
22
+ self.specs = specs_by_name
23
+ end
24
+
17
25
  def requirement_satisfied_by?(requirement, _activated, spec)
18
26
  case requirement
19
27
  when TestSpecification
@@ -27,7 +35,7 @@ module Molinillo
27
35
  @search_for ||= {}
28
36
  @search_for[dependency] ||= begin
29
37
  pre_release = dependency_pre_release?(dependency)
30
- specs[dependency.name].select do |spec|
38
+ Array(specs[dependency.name]).select do |spec|
31
39
  (pre_release ? true : !spec.version.pre_release?) &&
32
40
  dependency.satisfied_by?(spec.version)
33
41
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/CyclomaticComplexity
4
+ # rubocop:disable Metrics/LineLength
5
+ # rubocop:disable Style/Semicolon
6
+
7
+ module Molinillo
8
+ class NaiveResolver
9
+ def self.resolve(index, dependencies)
10
+ activated = Molinillo::DependencyGraph.new
11
+ level = 0
12
+ dependencies.each { |d| activated.add_child_vertex(d.name, nil, [nil], d) }
13
+ activated.tag(level)
14
+ possibilities_by_level = {}
15
+ loop do
16
+ vertex = activated.find { |a| !a.requirements.empty? && a.payload.nil? }
17
+ break unless vertex
18
+ possibilities = possibilities_by_level[level] ||= index.search_for(VersionKit::Dependency.new(vertex.name, '>= 0.0.0-a'))
19
+ possibilities.select! do |spec|
20
+ vertex.requirements.all? { |r| r.satisfied_by?(spec.version) && (!spec.version.pre_release? || index.send(:dependency_pre_release?, r)) } &&
21
+ spec.dependencies.all? { |d| v = activated.vertex_named(d.name); !v || !v.payload || d.satisfied_by?(v.payload.version) }
22
+ end
23
+ warn "level = #{level} possibilities = #{possibilities.map(&:to_s)} requirements = #{vertex.requirements.map(&:to_s)}"
24
+ if spec = possibilities.pop
25
+ warn "trying #{spec}"
26
+ activated.set_payload(vertex.name, spec)
27
+ spec.dependencies.each do |d|
28
+ activated.add_child_vertex(d.name, nil, [spec.name], d)
29
+ end
30
+ level += 1
31
+ warn "tagging level #{level}"
32
+ activated.tag(level)
33
+ next
34
+ end
35
+ level = possibilities_by_level.reverse_each.find(proc { [-1, nil] }) { |_l, p| !p.empty? }.first
36
+ warn "going back to level #{level}"
37
+ possibilities_by_level.reject! { |l, _| l > level }
38
+ return nil if level < 0
39
+ activated.rewind_to(level)
40
+ activated.tag(level)
41
+ end
42
+
43
+ activated
44
+ end
45
+
46
+ def self.warn(*); end
47
+ end
48
+ end
@@ -5,8 +5,9 @@ module Molinillo
5
5
  def initialize(hash)
6
6
  self.name = hash['name']
7
7
  self.version = VersionKit::Version.new(hash['version'])
8
- self.dependencies = hash['dependencies'].map do |(name, requirement)|
9
- VersionKit::Dependency.new(name, requirement.split(',').map(&:chomp))
8
+ self.dependencies = hash.fetch('dependencies') { Hash.new }.map do |(name, requirement)|
9
+ requirements = requirement.split(',').map(&:chomp)
10
+ VersionKit::Dependency.new(name, requirements)
10
11
  end
11
12
  end
12
13
 
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: molinillo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel E. Giddins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-14 00:00:00.000000000 Z
11
+ date: 2017-01-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.5'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.5'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  description:
@@ -70,10 +70,12 @@ files:
70
70
  - spec/dependency_graph/log_spec.rb
71
71
  - spec/dependency_graph_spec.rb
72
72
  - spec/errors_spec.rb
73
+ - spec/fuzz_spec.rb
73
74
  - spec/resolver_integration_specs/index_from_rubygems.rb
74
75
  - spec/resolver_spec.rb
75
76
  - spec/spec_helper.rb
76
77
  - spec/spec_helper/index.rb
78
+ - spec/spec_helper/naive_resolver.rb
77
79
  - spec/spec_helper/specification.rb
78
80
  - spec/spec_helper/ui.rb
79
81
  - spec/state_spec.rb
@@ -87,12 +89,12 @@ require_paths:
87
89
  - lib
88
90
  required_ruby_version: !ruby/object:Gem::Requirement
89
91
  requirements:
90
- - - ">="
92
+ - - '>='
91
93
  - !ruby/object:Gem::Version
92
94
  version: '0'
93
95
  required_rubygems_version: !ruby/object:Gem::Requirement
94
96
  requirements:
95
- - - ">="
97
+ - - '>='
96
98
  - !ruby/object:Gem::Version
97
99
  version: '0'
98
100
  requirements: []
@@ -105,9 +107,11 @@ test_files:
105
107
  - spec/dependency_graph/log_spec.rb
106
108
  - spec/dependency_graph_spec.rb
107
109
  - spec/errors_spec.rb
110
+ - spec/fuzz_spec.rb
108
111
  - spec/resolver_integration_specs/index_from_rubygems.rb
109
112
  - spec/resolver_spec.rb
110
113
  - spec/spec_helper/index.rb
114
+ - spec/spec_helper/naive_resolver.rb
111
115
  - spec/spec_helper/specification.rb
112
116
  - spec/spec_helper/ui.rb
113
117
  - spec/spec_helper.rb