solve 0.8.2 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0d32f1998f6ba4ceabff84d83a11c7505aa276b
4
- data.tar.gz: 0df2526224af83a576fe981eebb44554ce982817
3
+ metadata.gz: ae30420202e6609e3ee6c924b9bb0be3eff51195
4
+ data.tar.gz: 253757447932569a84b96aded37c0cba007e5847
5
5
  SHA512:
6
- metadata.gz: b2333d4f5015046efa4c2513c52ce05d9342430010bd361602797e22f10e2a790c6b69caafbdbab6022f429aeefe374e7d3e3059e7083f5a5619eeefea0fa2c5
7
- data.tar.gz: 6d17efaaa7bfec9b40cf6afab111bb93f66fe91479402736ef454c2b3066d10cd41fa07c74defe13c74dcfb562c513b1ec55f0f30dfee6228182e6d4a366398a
6
+ metadata.gz: d8c10b4a7b18fd20515cf99de348923104746f5297ac56bbd03f9ff56006d05f678d742a039047f065820cea39335dd73c41d0eab6508f8890a2673027abfa3b
7
+ data.tar.gz: e7fff54c7b0d5801e3ae8885db96cbcd12afd86c30bf84dbdedfa68c06189bf97fcf4964815a164a125ca07b6674aa7975a55dcf0dff578c183555150ecda237
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .ruby-version
19
+ .rspec
data/.travis.yml CHANGED
@@ -1,3 +1,7 @@
1
+ before_install:
2
+ - sudo apt-get update
3
+ - sudo apt-get install libgecode-dev
4
+
1
5
  script: "bundle exec thor spec"
2
6
  language: ruby
3
7
  bundler_args: --without development
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # Solve
2
- [![Gem Version](https://badge.fury.io/rb/solve.png)](http://badge.fury.io/rb/solve)
3
- [![Build Status](https://secure.travis-ci.org/berkshelf/solve.png?branch=master)](http://travis-ci.org/berkshelf/solve)
2
+ [![Gem Version](http://img.shields.io/gem/v/solve.svg)][gem]
3
+ [![Build Status](http://img.shields.io/travis/berkshelf/solve.svg)][travis]
4
+
5
+ [gem]: https://rubygems.org/gems/solve
6
+ [travis]: http://travis-ci.org/berkshelf/solve
4
7
 
5
8
  A Ruby versioning constraint solver implementing [Semantic Versioning 2.0.0](http://semver.org).
6
9
 
@@ -16,15 +19,15 @@ Create a new graph
16
19
 
17
20
  Add an artifact to the graph
18
21
 
19
- graph.artifacts("nginx", "1.0.0")
22
+ graph.artifact("nginx", "1.0.0")
20
23
 
21
24
  Now add another artifact that has a dependency
22
25
 
23
- graph.artifacts("mysql", "1.2.4-alpha.1").depends("openssl", "~> 1.0.0")
26
+ graph.artifact("mysql", "1.2.4-alpha.1").depends("openssl", "~> 1.0.0")
24
27
 
25
28
  Dependencies can be chained, too
26
29
 
27
- graph.artifacts("ntp", "1.0.0").depends("build-essential").depends("yum")
30
+ graph.artifact("ntp", "1.0.0").depends("build-essential").depends("yum")
28
31
 
29
32
  And now solve the graph with some demands
30
33
 
@@ -35,12 +38,6 @@ NOTE: This will raise Solve::Errors::UnsortableSolutionError if the solution con
35
38
 
36
39
  Solve.it!(graph, ['nginx', '>= 0.100.0'], sorted: true)
37
40
 
38
- ### Removing an artifact, or dependency from the graph
39
-
40
- graph.artifacts("nginx", "1.0.0").delete
41
-
42
- artifact.dependencies("nginx", "~> 1.0.0").delete
43
-
44
41
  ## Authors
45
42
 
46
43
  * [Jamie Winsor](https://github.com/reset) (<jamie@vialstudios.com>)
data/lib/solve.rb CHANGED
@@ -1,14 +1,13 @@
1
+ require 'semverse'
2
+
1
3
  module Solve
2
4
  require_relative 'solve/artifact'
3
- require_relative 'solve/constraint'
4
5
  require_relative 'solve/demand'
5
6
  require_relative 'solve/dependency'
6
7
  require_relative 'solve/gem_version'
7
8
  require_relative 'solve/errors'
8
9
  require_relative 'solve/graph'
9
10
  require_relative 'solve/solver'
10
- require_relative 'solve/version'
11
- require_relative 'solve/tracers'
12
11
 
13
12
  class << self
14
13
  # @return [Solve::Formatter]
@@ -24,10 +23,7 @@ module Solve
24
23
  # @param [Array<Solve::Demand>, Array<String, String>] demands
25
24
  #
26
25
  # @option options [#say] :ui (nil)
27
- # a ui object for output, this will be used to output from a Solve::Tracers::HumanReadable if
28
- # no other tracer is provided in options[:tracer]
29
- # @option options [AbstractTracer] :tracer (nil)
30
- # a Tracer object that is used to format and output tracing information
26
+ # a ui object for output
31
27
  # @option options [Boolean] :sorted (false)
32
28
  # should the output be a sorted list rather than a Hash
33
29
  #
@@ -35,7 +31,6 @@ module Solve
35
31
  #
36
32
  # @return [Hash]
37
33
  def it!(graph, demands, options = {})
38
- @tracer = options[:tracer] || Solve::Tracers.build(options[:ui])
39
34
  Solver.new(graph, demands, options[:ui]).resolve(options)
40
35
  end
41
36
  end
@@ -14,70 +14,72 @@ module Solve
14
14
 
15
15
  # The version of this artifact
16
16
  #
17
- # @return [Solve::Version]
17
+ # @return [Semverse::Version]
18
18
  attr_reader :version
19
19
 
20
20
  # @param [Solve::Graph] graph
21
21
  # @param [#to_s] name
22
- # @param [Solve::Version, #to_s] version
22
+ # @param [Semverse::Version, #to_s] version
23
23
  def initialize(graph, name, version)
24
- @graph = graph
25
- @name = name
26
- @version = Version.new(version)
27
- @dependencies = Hash.new
24
+ @graph = graph
25
+ @name = name
26
+ @version = Semverse::Version.new(version)
27
+ @dependencies = {}
28
28
  end
29
29
 
30
- # Return the Solve::Dependency from the collection of
31
- # dependencies with the given name and constraint.
30
+ # Check if the artifact has a dependency with the matching name and
31
+ # constraint
32
32
  #
33
33
  # @param [#to_s] name
34
- # @param [Solve::Constraint, #to_s] constraint
34
+ # @param [#to_s] constraint
35
35
  #
36
- # @example adding dependencies
37
- # artifact.depends("nginx") => <#Dependency: @name="nginx", @constraint=">= 0.0.0">
38
- # artifact.depends("ntp", "= 1.0.0") => <#Dependency: @name="ntp", @constraint="= 1.0.0">
36
+ # @return [Boolean]
37
+ def dependency?(name, constraint)
38
+ !dependency(name, constraint).nil?
39
+ end
40
+ alias_method :has_dependency?, :dependency?
41
+
42
+ # Retrieve the dependency from the artifact with the matching name and constraint
39
43
  #
40
- # @example chaining dependencies
41
- # artifact.depends("nginx").depends("ntp")
44
+ # @param [#to_s] name
45
+ # @param [#to_s] constraint
42
46
  #
43
- # @return [Solve::Artifact]
44
- def depends(name, constraint = ">= 0.0.0")
45
- if name.nil?
46
- raise ArgumentError, "A name must be specified. You gave: #{args}."
47
- end
48
-
49
- dependency = Dependency.new(self, name, constraint)
50
- add_dependency(dependency)
51
-
52
- self
47
+ # @return [Solve::Artifact, nil]
48
+ def dependency(name, constraint)
49
+ @dependencies["#{name}-#{constraint}"] = Dependency.new(self, name, constraint)
53
50
  end
54
51
 
55
52
  # Return the collection of dependencies on this instance of artifact
56
53
  #
57
54
  # @return [Array<Solve::Dependency>]
58
55
  def dependencies
59
- @dependencies.collect { |name, dependency| dependency }
56
+ @dependencies.values
60
57
  end
61
58
 
62
- # Retrieve the dependency from the artifact with the matching name and constraint
59
+ # Return the Solve::Dependency from the collection of
60
+ # dependencies with the given name and constraint.
63
61
  #
64
62
  # @param [#to_s] name
65
- # @param [#to_s] constraint
63
+ # @param [String] constraint
66
64
  #
67
- # @return [Solve::Artifact, nil]
68
- def get_dependency(name, constraint)
69
- @dependencies.fetch(Graph.dependency_key(name, constraint), nil)
70
- end
71
-
72
- # Remove this artifact from the graph it belongs to
65
+ # @example Adding dependencies
66
+ # artifact.depends('nginx')
67
+ # #=> #<Dependency nginx (>= 0.0.0)>
68
+ # artifact.depends('ntp', '= 1.0.0')
69
+ # #=> #<Dependency ntp (= 1.0.0)>
73
70
  #
74
- # @return [Solve::Artifact, nil]
75
- def delete
76
- unless graph.nil?
77
- result = graph.remove_artifact(self)
78
- @graph = nil
79
- result
71
+ # @example Chaining dependencies
72
+ # artifact
73
+ # .depends('nginx')
74
+ # .depends('ntp', '~> 1.3')
75
+ #
76
+ # @return [Solve::Artifact]
77
+ def depends(name, constraint = '>= 0.0.0')
78
+ unless dependency?(name, constraint)
79
+ @dependencies["#{name}-#{constraint}"] = Dependency.new(self, name, constraint)
80
80
  end
81
+
82
+ self
81
83
  end
82
84
 
83
85
  def to_s
@@ -89,54 +91,16 @@ module Solve
89
91
  # @return [Boolean]
90
92
  def ==(other)
91
93
  other.is_a?(self.class) &&
92
- self.name == other.name &&
93
- self.version == other.version
94
+ self.name == other.name &&
95
+ self.version == other.version
94
96
  end
95
97
  alias_method :eql?, :==
96
98
 
97
- # @param [Solve::Version] other
99
+ # @param [Semverse::Version] other
98
100
  #
99
101
  # @return [Integer]
100
102
  def <=>(other)
101
103
  self.version <=> other.version
102
104
  end
103
-
104
- private
105
-
106
- # Add a Solve::Dependency to the collection of dependencies
107
- # and return the added Solve::Dependency. No change will be
108
- # made if the dependency is already a member of the collection.
109
- #
110
- # @param [Solve::Dependency] dependency
111
- #
112
- # @return [Solve::Dependency]
113
- def add_dependency(dependency)
114
- unless has_dependency?(dependency.name, dependency.constraint)
115
- @dependencies[Graph.key_for(dependency)] = dependency
116
- end
117
-
118
- get_dependency(dependency.name, dependency.constraint)
119
- end
120
-
121
- # Remove the matching dependency from the artifact
122
- #
123
- # @param [Solve::Dependency] dependency
124
- #
125
- # @return [Solve::Dependency, nil]
126
- def remove_dependency(dependency)
127
- if has_dependency?(dependency)
128
- @dependencies.delete(Graph.key_for(dependency))
129
- end
130
- end
131
-
132
- # Check if the artifact has a dependency with the matching name and constraint
133
- #
134
- # @param [#to_s] name
135
- # @param [#to_s] constraint
136
- #
137
- # @return [Boolean]
138
- def has_dependency?(name, constraint)
139
- @dependencies.has_key?(Graph.dependency_key(name, constraint))
140
- end
141
105
  end
142
106
  end
@@ -1,6 +1,19 @@
1
1
  module Solve
2
2
  class Constraint
3
3
  class << self
4
+ # Coerce the object into a constraint.
5
+ #
6
+ # @param [Constraint, String]
7
+ #
8
+ # @return [Constraint]
9
+ def coerce(object)
10
+ if object.nil?
11
+ Semverse::DEFAULT_CONSTRAINT
12
+ else
13
+ object.is_a?(self) ? object : new(object)
14
+ end
15
+ end
16
+
4
17
  # Split a constraint string into an Array of two elements. The first
5
18
  # element being the operator and second being the version string.
6
19
  #
@@ -50,64 +63,64 @@ module Solve
50
63
  [ operator, split_version ].flatten
51
64
  end
52
65
 
53
- # @param [Solve::Constraint] constraint
54
- # @param [Solve::Version] target_version
66
+ # @param [Semverse::Constraint] constraint
67
+ # @param [Semverse::Version] target_version
55
68
  #
56
69
  # @return [Boolean]
57
70
  def compare_equal(constraint, target_version)
58
71
  target_version == constraint.version
59
72
  end
60
73
 
61
- # @param [Solve::Constraint] constraint
62
- # @param [Solve::Version] target_version
74
+ # @param [Semverse::Constraint] constraint
75
+ # @param [Semverse::Version] target_version
63
76
  #
64
77
  # @return [Boolean]
65
78
  def compare_gt(constraint, target_version)
66
79
  target_version > constraint.version
67
80
  end
68
81
 
69
- # @param [Solve::Constraint] constraint
70
- # @param [Solve::Version] target_version
82
+ # @param [Semverse::Constraint] constraint
83
+ # @param [Semverse::Version] target_version
71
84
  #
72
85
  # @return [Boolean]
73
86
  def compare_lt(constraint, target_version)
74
87
  target_version < constraint.version
75
88
  end
76
89
 
77
- # @param [Solve::Constraint] constraint
78
- # @param [Solve::Version] target_version
90
+ # @param [Semverse::Constraint] constraint
91
+ # @param [Semverse::Version] target_version
79
92
  #
80
93
  # @return [Boolean]
81
94
  def compare_gte(constraint, target_version)
82
95
  target_version >= constraint.version
83
96
  end
84
97
 
85
- # @param [Solve::Constraint] constraint
86
- # @param [Solve::Version] target_version
98
+ # @param [Semverse::Constraint] constraint
99
+ # @param [Semverse::Version] target_version
87
100
  #
88
101
  # @return [Boolean]
89
102
  def compare_lte(constraint, target_version)
90
103
  target_version <= constraint.version
91
104
  end
92
105
 
93
- # @param [Solve::Constraint] constraint
94
- # @param [Solve::Version] target_version
106
+ # @param [Semverse::Constraint] constraint
107
+ # @param [Semverse::Version] target_version
95
108
  #
96
109
  # @return [Boolean]
97
110
  def compare_approx(constraint, target_version)
98
111
  min = constraint.version
99
112
  max = if constraint.patch.nil?
100
- Version.new([min.major + 1, 0, 0, 0])
113
+ Semverse::Version.new([min.major + 1, 0, 0, 0])
101
114
  elsif constraint.build
102
115
  identifiers = constraint.version.identifiers(:build)
103
116
  replace = identifiers.last.to_i.to_s == identifiers.last.to_s ? "-" : nil
104
- Version.new([min.major, min.minor, min.patch, min.pre_release, identifiers.fill(replace, -1).join('.')])
117
+ Semverse::Version.new([min.major, min.minor, min.patch, min.pre_release, identifiers.fill(replace, -1).join('.')])
105
118
  elsif constraint.pre_release
106
119
  identifiers = constraint.version.identifiers(:pre_release)
107
120
  replace = identifiers.last.to_i.to_s == identifiers.last.to_s ? "-" : nil
108
- Version.new([min.major, min.minor, min.patch, identifiers.fill(replace, -1).join('.')])
121
+ Semverse::Version.new([min.major, min.minor, min.patch, identifiers.fill(replace, -1).join('.')])
109
122
  else
110
- Version.new([min.major, min.minor + 1, 0, 0])
123
+ Semverse::Version.new([min.major, min.minor + 1, 0, 0])
111
124
  end
112
125
  min <= target_version && target_version < max
113
126
  end
@@ -141,10 +154,17 @@ module Solve
141
154
  attr_reader :pre_release
142
155
  attr_reader :build
143
156
 
144
- # @param [#to_s] constraint (">= 0.0.0")
157
+ # Return the Semverse::Version representation of the major, minor, and patch
158
+ # attributes of this instance
159
+ #
160
+ # @return [Semverse::Version]
161
+ attr_reader :version
162
+
163
+ # @param [#to_s] constraint
145
164
  def initialize(constraint = nil)
165
+ constraint = constraint.to_s
146
166
  if constraint.nil? || constraint.empty?
147
- constraint = ">= 0.0.0"
167
+ constraint = '>= 0.0.0'
148
168
  end
149
169
 
150
170
  @operator, @major, @minor, @patch, @pre_release, @build = self.class.split(constraint)
@@ -153,22 +173,14 @@ module Solve
153
173
  @minor ||= 0
154
174
  @patch ||= 0
155
175
  end
156
- end
157
176
 
158
- # Return the Solve::Version representation of the major, minor, and patch
159
- # attributes of this instance
160
- #
161
- # @return [Solve::Version]
162
- def version
163
- @version ||= Version.new(
164
- [
165
- self.major,
166
- self.minor,
167
- self.patch,
168
- self.pre_release,
169
- self.build
170
- ]
171
- )
177
+ @version = Semverse::Version.new([
178
+ self.major,
179
+ self.minor,
180
+ self.patch,
181
+ self.pre_release,
182
+ self.build,
183
+ ])
172
184
  end
173
185
 
174
186
  # @return [Symbol]
@@ -183,17 +195,21 @@ module Solve
183
195
  # Returns true or false if the given version would be satisfied by
184
196
  # the version constraint.
185
197
  #
186
- # @param [#to_s] target_version
198
+ # @param [Version, #to_s] target
187
199
  #
188
200
  # @return [Boolean]
189
- def satisfies?(target_version)
190
- target_version = Version.new(target_version.to_s)
201
+ def satisfies?(target)
202
+ target = Version.coerce(target)
191
203
 
192
- return false if !version.zero? && greedy_match?(target_version)
204
+ return false if !version.zero? && greedy_match?(target)
193
205
 
194
- compare(target_version)
206
+ compare(target)
195
207
  end
196
208
 
209
+ # dep-selector uses include? to determine if a version matches the
210
+ # constriant.
211
+ alias_method :include?, :satisfies?
212
+
197
213
  # @param [Object] other
198
214
  #
199
215
  # @return [Boolean]
@@ -209,12 +225,12 @@ module Solve
209
225
  end
210
226
 
211
227
  def to_s
212
- str = "#{operator} #{major}"
213
- str += ".#{minor}" if minor
214
- str += ".#{patch}" if patch
215
- str += "-#{pre_release}" if pre_release
216
- str += "+#{build}" if build
217
- str
228
+ out = "#{operator} #{major}"
229
+ out << ".#{minor}" if minor
230
+ out << ".#{patch}" if patch
231
+ out << "-#{pre_release}" if pre_release
232
+ out << "+#{build}" if build
233
+ out
218
234
  end
219
235
 
220
236
  private
@@ -223,13 +239,13 @@ module Solve
223
239
  # does not include a pre-release and if the operator isn't < or <=.
224
240
  # This avoids greedy matches, e.g. 2.0.0.alpha won't satisfy >= 1.0.0.
225
241
  #
226
- # @param [Solve::Version] target_version
242
+ # @param [Semverse::Version] target_version
227
243
  #
228
244
  def greedy_match?(target_version)
229
245
  operator_type !~ /less/ && target_version.pre_release? && !version.pre_release?
230
246
  end
231
247
 
232
- # @param [Solve::Version] target
248
+ # @param [Semverse::Version] target
233
249
  #
234
250
  # @return [Boolean]
235
251
  def compare(target)