molinillo 0.4.0 → 0.4.1
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 +4 -4
- data/lib/molinillo.rb +4 -0
- data/lib/molinillo/dependency_graph.rb +9 -0
- data/lib/molinillo/errors.rb +5 -0
- data/lib/molinillo/gem_metadata.rb +2 -1
- data/lib/molinillo/resolution.rb +1 -0
- data/lib/molinillo/resolver.rb +2 -1
- data/lib/molinillo/state.rb +7 -7
- data/spec/dependency_graph_spec.rb +16 -30
- data/spec/resolver_spec.rb +25 -30
- data/spec/spec_helper.rb +2 -5
- data/spec/state_spec.rb +5 -9
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ea85c0037f78e6763d19bf7d8144c33eccb1a28
|
4
|
+
data.tar.gz: da1f09939f213f0e93bc644a8ba021000c79db9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a84d8bde06c58dcf77fe69d9128c964a35077226a8cb5b9f9af6d4aa78592426491b35e62371565d2654f035302a7797deda05584c778e6d58e4575291bc5c5e
|
7
|
+
data.tar.gz: 40f4b4b9282474acee27715541f6d2f3c5153b1e333c1ed84f42d04aa09f8aeb4e024f6010abae83d958c41baa7c596002a2457c69ec008573efccac9824cf93
|
data/lib/molinillo.rb
CHANGED
@@ -14,8 +14,10 @@ module Molinillo
|
|
14
14
|
|
15
15
|
include TSort
|
16
16
|
|
17
|
+
# @visibility private
|
17
18
|
alias_method :tsort_each_node, :each
|
18
19
|
|
20
|
+
# @visibility private
|
19
21
|
def tsort_each_child(vertex, &block)
|
20
22
|
vertex.successors.each(&block)
|
21
23
|
end
|
@@ -41,12 +43,14 @@ module Molinillo
|
|
41
43
|
# by {Vertex#name}
|
42
44
|
attr_reader :vertices
|
43
45
|
|
46
|
+
# Initializes an empty dependency graph
|
44
47
|
def initialize
|
45
48
|
@vertices = {}
|
46
49
|
end
|
47
50
|
|
48
51
|
# Initializes a copy of a {DependencyGraph}, ensuring that all {#vertices}
|
49
52
|
# are properly copied.
|
53
|
+
# @param [DependencyGraph] other the graph to copy.
|
50
54
|
def initialize_copy(other)
|
51
55
|
super
|
52
56
|
@vertices = {}
|
@@ -100,6 +104,7 @@ module Molinillo
|
|
100
104
|
vertex
|
101
105
|
end
|
102
106
|
|
107
|
+
# Adds a vertex with the given name, or updates the existing one.
|
103
108
|
# @param [String] name
|
104
109
|
# @param [Object] payload
|
105
110
|
# @return [Vertex] the vertex that was added to `self`
|
@@ -150,6 +155,8 @@ module Molinillo
|
|
150
155
|
|
151
156
|
private
|
152
157
|
|
158
|
+
# Adds a new {Edge} to the dependency graph without checking for
|
159
|
+
# circularity.
|
153
160
|
def add_edge_no_circular(origin, destination, requirement)
|
154
161
|
edge = Edge.new(origin, destination, requirement)
|
155
162
|
origin.outgoing_edges << edge
|
@@ -174,6 +181,7 @@ module Molinillo
|
|
174
181
|
attr_accessor :root
|
175
182
|
alias_method :root?, :root
|
176
183
|
|
184
|
+
# Initializes a vertex with the given name and payload.
|
177
185
|
# @param [String] name see {#name}
|
178
186
|
# @param [Object] payload see {#payload}
|
179
187
|
def initialize(name, payload)
|
@@ -240,6 +248,7 @@ module Molinillo
|
|
240
248
|
successors.to_set == other.successors.to_set
|
241
249
|
end
|
242
250
|
|
251
|
+
# @param [Vertex] other the other vertex to compare to
|
243
252
|
# @return [Boolean] whether the two vertices are equal, determined
|
244
253
|
# solely by {#name} and {#payload} equality
|
245
254
|
def shallow_eql?(other)
|
data/lib/molinillo/errors.rb
CHANGED
@@ -11,6 +11,7 @@ module Molinillo
|
|
11
11
|
# @return [Array<Object>] the specifications that depended upon {#dependency}
|
12
12
|
attr_accessor :required_by
|
13
13
|
|
14
|
+
# Initializes a new error with the given missing dependency.
|
14
15
|
# @param [Object] dependency @see {#dependency}
|
15
16
|
# @param [Array<Object>] required_by @see {#required_by}
|
16
17
|
def initialize(dependency, required_by = [])
|
@@ -19,6 +20,8 @@ module Molinillo
|
|
19
20
|
super()
|
20
21
|
end
|
21
22
|
|
23
|
+
# The error message for the missing dependency, including the specifications
|
24
|
+
# that had this dependency.
|
22
25
|
def message
|
23
26
|
sources = required_by.map { |r| "`#{r}`" }.join(' and ')
|
24
27
|
message = "Unable to find a specification for `#{dependency}`"
|
@@ -36,6 +39,7 @@ module Molinillo
|
|
36
39
|
# [Set<Object>] the dependencies responsible for causing the error
|
37
40
|
attr_reader :dependencies
|
38
41
|
|
42
|
+
# Initializes a new error with the given circular vertices.
|
39
43
|
# @param [Array<DependencyGraph::Vertex>] nodes the nodes in the dependency
|
40
44
|
# that caused the error
|
41
45
|
def initialize(nodes)
|
@@ -50,6 +54,7 @@ module Molinillo
|
|
50
54
|
# resolution to fail
|
51
55
|
attr_reader :conflicts
|
52
56
|
|
57
|
+
# Initializes a new error with the given version conflicts.
|
53
58
|
# @param [{String => Resolution::Conflict}] conflicts see {#conflicts}
|
54
59
|
def initialize(conflicts)
|
55
60
|
pairs = []
|
data/lib/molinillo/resolution.rb
CHANGED
@@ -38,6 +38,7 @@ module Molinillo
|
|
38
38
|
# @return [Array] the dependencies that were explicitly required
|
39
39
|
attr_reader :original_requested
|
40
40
|
|
41
|
+
# Initializes a new resolution.
|
41
42
|
# @param [SpecificationProvider] specification_provider
|
42
43
|
# see {#specification_provider}
|
43
44
|
# @param [UI] resolver_ui see {#resolver_ui}
|
data/lib/molinillo/resolver.rb
CHANGED
@@ -3,7 +3,7 @@ require 'molinillo/dependency_graph'
|
|
3
3
|
module Molinillo
|
4
4
|
# This class encapsulates a dependency resolver.
|
5
5
|
# The resolver is responsible for determining which set of dependencies to
|
6
|
-
# activate, with feedback from the
|
6
|
+
# activate, with feedback from the {#specification_provider}
|
7
7
|
#
|
8
8
|
#
|
9
9
|
class Resolver
|
@@ -17,6 +17,7 @@ module Molinillo
|
|
17
17
|
# during the resolution process
|
18
18
|
attr_reader :resolver_ui
|
19
19
|
|
20
|
+
# Initializes a new resolver.
|
20
21
|
# @param [SpecificationProvider] specification_provider
|
21
22
|
# see {#specification_provider}
|
22
23
|
# @param [UI] resolver_ui
|
data/lib/molinillo/state.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module Molinillo
|
2
2
|
# A state that a {Resolution} can be in
|
3
|
-
# @attr [String] name
|
4
|
-
# @attr [Array<Object>] requirements
|
5
|
-
# @attr [DependencyGraph] activated
|
6
|
-
# @attr [Object] requirement
|
7
|
-
# @attr [Object]
|
8
|
-
# @attr [Integer] depth
|
9
|
-
# @attr [Set<Object>] conflicts
|
3
|
+
# @attr [String] name the name of the current requirement
|
4
|
+
# @attr [Array<Object>] requirements currently unsatisfied requirements
|
5
|
+
# @attr [DependencyGraph] activated the graph of activated dependencies
|
6
|
+
# @attr [Object] requirement the current requirement
|
7
|
+
# @attr [Object] possibilities the possibilities to satisfy the current requirement
|
8
|
+
# @attr [Integer] depth the depth of the resolution
|
9
|
+
# @attr [Set<Object>] conflicts unresolved conflicts
|
10
10
|
ResolutionState = Struct.new(
|
11
11
|
:name,
|
12
12
|
:requirements,
|
@@ -4,59 +4,49 @@ module Molinillo
|
|
4
4
|
describe DependencyGraph do
|
5
5
|
describe 'in general' do
|
6
6
|
before do
|
7
|
-
@graph =
|
7
|
+
@graph = described_class.new
|
8
8
|
@root = @graph.add_vertex('Root', 'Root', true)
|
9
9
|
@root2 = @graph.add_vertex('Root2', 'Root2', true)
|
10
10
|
@child = @graph.add_child_vertex('Child', 'Child', %w(Root), 'Child')
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'returns root vertices by name' do
|
14
|
-
@graph.root_vertex_named('Root').
|
15
|
-
should.equal @root
|
14
|
+
expect(@graph.root_vertex_named('Root')).to eq(@root)
|
16
15
|
end
|
17
16
|
|
18
17
|
it 'returns vertices by name' do
|
19
|
-
@graph.vertex_named('Root').
|
20
|
-
|
21
|
-
@graph.vertex_named('Child').
|
22
|
-
should.equal @child
|
18
|
+
expect(@graph.vertex_named('Root')).to eq(@root)
|
19
|
+
expect(@graph.vertex_named('Child')).to eq(@child)
|
23
20
|
end
|
24
21
|
|
25
22
|
it 'returns nil for non-existant root vertices' do
|
26
|
-
@graph.root_vertex_named('missing').
|
27
|
-
should.equal nil
|
23
|
+
expect(@graph.root_vertex_named('missing')).to be_nil
|
28
24
|
end
|
29
25
|
|
30
26
|
it 'returns nil for non-existant vertices' do
|
31
|
-
@graph.vertex_named('missing').
|
32
|
-
should.equal nil
|
27
|
+
expect(@graph.vertex_named('missing')).to be_nil
|
33
28
|
end
|
34
29
|
end
|
35
30
|
|
36
31
|
describe 'detaching a node' do
|
37
32
|
before do
|
38
|
-
@graph =
|
33
|
+
@graph = described_class.new
|
39
34
|
end
|
40
35
|
|
41
36
|
it 'detaches a root vertex without successors' do
|
42
37
|
root = @graph.add_vertex('root', 'root', true)
|
43
38
|
@graph.detach_vertex_named(root.name)
|
44
|
-
@graph.vertex_named(root.name).
|
45
|
-
|
46
|
-
@graph.vertices.count.
|
47
|
-
should.equal 0
|
39
|
+
expect(@graph.vertex_named(root.name)).to be_nil
|
40
|
+
expect(@graph.vertices).to be_empty
|
48
41
|
end
|
49
42
|
|
50
43
|
it 'detaches a root vertex with successors' do
|
51
44
|
root = @graph.add_vertex('root', 'root', true)
|
52
45
|
child = @graph.add_child_vertex('child', 'child', %w(root), 'child')
|
53
46
|
@graph.detach_vertex_named(root.name)
|
54
|
-
@graph.vertex_named(root.name).
|
55
|
-
|
56
|
-
@graph.
|
57
|
-
should.equal nil
|
58
|
-
@graph.vertices.count.
|
59
|
-
should.equal 0
|
47
|
+
expect(@graph.vertex_named(root.name)).to be_nil
|
48
|
+
expect(@graph.vertex_named(child.name)).to be_nil
|
49
|
+
expect(@graph.vertices).to be_empty
|
60
50
|
end
|
61
51
|
|
62
52
|
it 'detaches a root vertex with successors with other parents' do
|
@@ -64,14 +54,10 @@ module Molinillo
|
|
64
54
|
root2 = @graph.add_vertex('root2', 'root2', true)
|
65
55
|
child = @graph.add_child_vertex('child', 'child', %w(root root2), 'child')
|
66
56
|
@graph.detach_vertex_named(root.name)
|
67
|
-
@graph.vertex_named(root.name).
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
child.predecessors.
|
72
|
-
should.equal [root2]
|
73
|
-
@graph.vertices.count.
|
74
|
-
should.equal 2
|
57
|
+
expect(@graph.vertex_named(root.name)).to be_nil
|
58
|
+
expect(@graph.vertex_named(child.name)).to eq(child)
|
59
|
+
expect(child.predecessors).to eq([root2])
|
60
|
+
expect(@graph.vertices.count).to eq(2)
|
75
61
|
end
|
76
62
|
end
|
77
63
|
end
|
data/spec/resolver_spec.rb
CHANGED
@@ -14,7 +14,6 @@ module Molinillo
|
|
14
14
|
|
15
15
|
attr_accessor :name, :requested, :base, :conflicts, :resolver, :result, :index
|
16
16
|
|
17
|
-
# rubocop:disable Metrics/MethodLength
|
18
17
|
def initialize(fixture_path)
|
19
18
|
File.open(fixture_path) do |fixture|
|
20
19
|
JSON.load(fixture).tap do |test_case|
|
@@ -54,7 +53,6 @@ module Molinillo
|
|
54
53
|
|
55
54
|
self.resolver = Resolver.new(index, TestUI.new)
|
56
55
|
end
|
57
|
-
# rubocop:enable Metrics/MethodLength
|
58
56
|
end
|
59
57
|
|
60
58
|
describe Resolver do
|
@@ -65,27 +63,25 @@ module Molinillo
|
|
65
63
|
resolve = lambda { test_case.resolver.resolve(test_case.requested, test_case.base) }
|
66
64
|
|
67
65
|
if test_case.conflicts.any?
|
68
|
-
|
69
|
-
|
66
|
+
expect { resolve.call }.to raise_error do |error|
|
67
|
+
expect(error).to be_a(ResolverError)
|
68
|
+
names = case error
|
69
|
+
when CircularDependencyError
|
70
|
+
error.dependencies.map(&:name)
|
71
|
+
when VersionConflict
|
72
|
+
error.conflicts.keys
|
73
|
+
end.to_set
|
74
|
+
expect(names).to eq(test_case.conflicts)
|
70
75
|
end
|
71
|
-
|
72
|
-
names = case error
|
73
|
-
when CircularDependencyError
|
74
|
-
error.dependencies.map(&:name)
|
75
|
-
when VersionConflict
|
76
|
-
error.conflicts.keys
|
77
|
-
end.to_set
|
78
|
-
names.should.equal test_case.conflicts
|
79
76
|
else
|
80
77
|
result = resolve.call
|
81
78
|
|
82
79
|
pretty_dependencies = lambda do |dg|
|
83
80
|
dg.vertices.values.map { |v| "#{v.payload.name} (#{v.payload.version})" }.sort
|
84
81
|
end
|
85
|
-
pretty_dependencies.call(result).
|
86
|
-
equal pretty_dependencies.call(test_case.result)
|
82
|
+
expect(pretty_dependencies.call(result)).to eq(pretty_dependencies.call(test_case.result))
|
87
83
|
|
88
|
-
result.
|
84
|
+
expect(result).to eq(test_case.result)
|
89
85
|
end
|
90
86
|
end
|
91
87
|
end
|
@@ -93,36 +89,35 @@ module Molinillo
|
|
93
89
|
|
94
90
|
describe 'in general' do
|
95
91
|
before do
|
96
|
-
@resolver =
|
92
|
+
@resolver = described_class.new(TestIndex.new('awesome'), TestUI.new)
|
97
93
|
end
|
98
94
|
|
99
95
|
it 'can resolve a list of 0 requirements' do
|
100
|
-
@resolver.resolve([], DependencyGraph.new).
|
101
|
-
should.equal DependencyGraph.new
|
96
|
+
expect(@resolver.resolve([], DependencyGraph.new)).to eq(DependencyGraph.new)
|
102
97
|
end
|
103
98
|
|
104
99
|
it 'includes the source of a user-specified unsatisfied dependency' do
|
105
|
-
|
100
|
+
expect do
|
106
101
|
@resolver.resolve([VersionKit::Dependency.new('missing', '3.0')], DependencyGraph.new)
|
107
|
-
end.
|
102
|
+
end.to raise_error(VersionConflict, /required by `user-specified dependency`/)
|
108
103
|
end
|
109
104
|
|
110
105
|
it 'can handle when allow_missing? returns true for the only requirement' do
|
111
106
|
dep = VersionKit::Dependency.new('missing', '3.0')
|
112
|
-
@resolver.specification_provider.
|
113
|
-
@resolver.resolve([dep], DependencyGraph.new).to_a.
|
107
|
+
allow(@resolver.specification_provider).to receive(:allow_missing?).with(dep).and_return(true)
|
108
|
+
expect(@resolver.resolve([dep], DependencyGraph.new).to_a).to be_empty
|
114
109
|
end
|
115
110
|
|
116
111
|
it 'can handle when allow_missing? returns true for a nested requirement' do
|
117
|
-
index = TestIndex.new('awesome')
|
118
112
|
dep = VersionKit::Dependency.new('actionpack', '1.2.3')
|
119
|
-
@resolver.specification_provider.
|
120
|
-
with
|
121
|
-
@resolver.specification_provider.
|
122
|
-
with
|
123
|
-
@resolver.specification_provider.
|
124
|
-
with
|
125
|
-
@resolver.resolve([dep], DependencyGraph.new)
|
113
|
+
allow(@resolver.specification_provider).to receive(:allow_missing?).
|
114
|
+
with(have_attributes(:name => 'activesupport')).and_return(true)
|
115
|
+
allow(@resolver.specification_provider).to receive(:search_for).
|
116
|
+
with(have_attributes(:name => 'activesupport')).and_return([])
|
117
|
+
allow(@resolver.specification_provider).to receive(:search_for).
|
118
|
+
with(have_attributes(:name => 'actionpack')).and_call_original
|
119
|
+
resolved = @resolver.resolve([dep], DependencyGraph.new)
|
120
|
+
expect(resolved.map(&:payload).map(&:to_s)).to eq(['actionpack (1.2.3)'])
|
126
121
|
end
|
127
122
|
end
|
128
123
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
require 'bundler/setup'
|
1
2
|
|
2
3
|
# Set up coverage analysis
|
3
4
|
#-----------------------------------------------------------------------------#
|
4
5
|
|
5
|
-
if (ENV['CI'] || ENV['GENERATE_COVERAGE']) && RUBY_VERSION >= '2.0.0'
|
6
|
+
if (ENV['CI'] || ENV['GENERATE_COVERAGE']) && RUBY_VERSION >= '2.0.0' && Bundler.current_ruby.mri?
|
6
7
|
require 'simplecov'
|
7
8
|
require 'codeclimate-test-reporter'
|
8
9
|
|
@@ -26,9 +27,5 @@ ROOT = Pathname.new(File.expand_path('../../', __FILE__))
|
|
26
27
|
$LOAD_PATH.unshift((ROOT + 'lib').to_s)
|
27
28
|
$LOAD_PATH.unshift((ROOT + 'spec').to_s)
|
28
29
|
|
29
|
-
require 'bundler/setup'
|
30
|
-
require 'bacon'
|
31
|
-
require 'mocha-on-bacon'
|
32
|
-
require 'pretty_bacon'
|
33
30
|
require 'version_kit'
|
34
31
|
require 'molinillo'
|
data/spec/state_spec.rb
CHANGED
@@ -4,7 +4,7 @@ module Molinillo
|
|
4
4
|
describe ResolutionState do
|
5
5
|
describe DependencyState do
|
6
6
|
before do
|
7
|
-
@state =
|
7
|
+
@state = described_class.new(
|
8
8
|
'name',
|
9
9
|
%w(requirement1 requirement2 requirement3),
|
10
10
|
DependencyGraph.new,
|
@@ -18,15 +18,11 @@ module Molinillo
|
|
18
18
|
it 'pops a possibility state' do
|
19
19
|
possibility_state = @state.pop_possibility_state
|
20
20
|
%w(name requirements activated requirement conflicts).each do |attr|
|
21
|
-
possibility_state.send(attr).
|
22
|
-
should.equal @state.send(attr)
|
21
|
+
expect(possibility_state.send(attr)).to eq(@state.send(attr))
|
23
22
|
end
|
24
|
-
possibility_state.
|
25
|
-
|
26
|
-
possibility_state.
|
27
|
-
should.equal @state.depth + 1
|
28
|
-
possibility_state.possibilities.
|
29
|
-
should.equal %w(possibility)
|
23
|
+
expect(possibility_state).to be_a(PossibilityState)
|
24
|
+
expect(possibility_state.depth).to eq(@state.depth + 1)
|
25
|
+
expect(possibility_state.possibilities).to eq(%w(possibility))
|
30
26
|
end
|
31
27
|
end
|
32
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: molinillo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
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: 2015-
|
11
|
+
date: 2015-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -84,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
84
|
version: '0'
|
85
85
|
requirements: []
|
86
86
|
rubyforge_project:
|
87
|
-
rubygems_version: 2.
|
87
|
+
rubygems_version: 2.5.1
|
88
88
|
signing_key:
|
89
89
|
specification_version: 4
|
90
90
|
summary: Provides support for dependency resolution
|
@@ -97,3 +97,4 @@ test_files:
|
|
97
97
|
- spec/spec_helper/ui.rb
|
98
98
|
- spec/spec_helper.rb
|
99
99
|
- spec/state_spec.rb
|
100
|
+
has_rdoc:
|