solve 0.8.2 → 1.0.0.rc1

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: 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)