versionable 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/versionable/version_number.rb +11 -11
- data/lib/versionable/versions.rb +38 -27
- data/spec/versionable/version_number_spec.rb +0 -6
- data/versionable.gemspec +2 -2
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
@@ -8,15 +8,19 @@ module Versionable
|
|
8
8
|
# If the to_s'd argument does not match VERSION_NUMBER_REGEX, an ArgumentError is raised.
|
9
9
|
def initialize(v)
|
10
10
|
v = v.to_s
|
11
|
-
|
11
|
+
unless v =~ VERSION_NUMBER_REGEX
|
12
|
+
raise ArgumentError.new "#{v.inspect} is not a dotted sequence of positive integers"
|
13
|
+
end
|
12
14
|
super v
|
13
15
|
end
|
14
16
|
|
15
17
|
# Compare version numbers as lists of integers.
|
16
18
|
#
|
17
|
-
# If one version number has more segments than the other, the shorter one is right-extended
|
19
|
+
# If one version number has more segments than the other, the shorter one is right-extended
|
20
|
+
# with zeros.
|
18
21
|
#
|
19
|
-
# For example, when comparing 0.2 to 0.10.1, the 0.2 is extended to 0.2.0. The left two 0s
|
22
|
+
# For example, when comparing 0.2 to 0.10.1, the 0.2 is extended to 0.2.0. The left two 0s
|
23
|
+
# are equal, so comparison shifts to 2 and 10: 0.10.1 is the greater version.
|
20
24
|
def <=>(other)
|
21
25
|
my_segments, their_segments = to_s.split('.'), other.to_s.split('.')
|
22
26
|
size_difference = my_segments.size - their_segments.size
|
@@ -27,7 +31,10 @@ module Versionable
|
|
27
31
|
my_segments.concat(['0'] * -size_difference)
|
28
32
|
end
|
29
33
|
|
30
|
-
partwise = my_segments.zip(their_segments).collect
|
34
|
+
partwise = my_segments.zip(their_segments).collect do |mine, theirs|
|
35
|
+
mine.to_i <=> theirs.to_i
|
36
|
+
end
|
37
|
+
|
31
38
|
partwise.detect { |cmp| cmp != 0 } || 0
|
32
39
|
end
|
33
40
|
|
@@ -38,13 +45,6 @@ module Versionable
|
|
38
45
|
(self <=> other) == 0
|
39
46
|
end
|
40
47
|
|
41
|
-
# Bump to the next most-significant version number.
|
42
|
-
#
|
43
|
-
# VersionNumber.new("2.1").next.to_s # => "3"
|
44
|
-
def next
|
45
|
-
self.class.new(split('.', 2).first.to_i + 1)
|
46
|
-
end
|
47
|
-
|
48
48
|
# Hash the version number string after stripping any trailing zeroes.
|
49
49
|
#
|
50
50
|
# This preserves the hash/equality contract: 2 == 2.0, so they both hash the same as well.
|
data/lib/versionable/versions.rb
CHANGED
@@ -2,25 +2,32 @@ module Versionable
|
|
2
2
|
# A container for all versions of a given module.
|
3
3
|
class Versions
|
4
4
|
COMPARISON_REGEX = /^(<|<=|=|>=|>)\s+((?:0|[1-9]\d*)(?:\.(?:0|[1-9]\d*))*)$/
|
5
|
-
|
5
|
+
|
6
6
|
# Construct a Versions recording versions of the passed module.
|
7
7
|
def initialize(versioned_module)
|
8
8
|
@latest_version = versioned_module
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
# Build and store a new version with the given number.
|
12
|
-
#
|
13
|
-
# Versions must be built in increasing order: if version_number is not greater than the
|
14
|
-
# The initial version number is always 0.
|
15
|
-
#
|
12
|
+
#
|
13
|
+
# Versions must be built in increasing order: if version_number is not greater than the
|
14
|
+
# previous version, an ArgumentError is raised. The initial version number is always 0.
|
15
|
+
#
|
16
16
|
# If a block parameter is passed, it is included in the created version.
|
17
|
-
# If this is the first time a block is passed, then record the _previous_ version as the
|
18
|
-
# Once build is called with a block, subsequent versions must also pass a block
|
17
|
+
# If this is the first time a block is passed, then record the _previous_ version as the
|
18
|
+
# default one. Once build is called with a block, subsequent versions must also pass a block
|
19
|
+
# or a VersioningError will be raised.
|
19
20
|
def build(version_number, &block)
|
20
21
|
version_number = VersionNumber.new(version_number)
|
21
22
|
|
22
|
-
|
23
|
-
|
23
|
+
unless latest_version_number < version_number
|
24
|
+
raise ArgumentError.new "Can't bump to #{version_number} from #{latest_version_number}"
|
25
|
+
end
|
26
|
+
|
27
|
+
if default_version and not block
|
28
|
+
raise VersioningError.new(
|
29
|
+
"Once version is called with a block, all subsequent calls must pass a block.")
|
30
|
+
end
|
24
31
|
|
25
32
|
if block and default_version.nil?
|
26
33
|
self.default_version = latest_version
|
@@ -30,32 +37,36 @@ module Versionable
|
|
30
37
|
else
|
31
38
|
versions[latest_version_number] = latest_version.dup
|
32
39
|
end
|
33
|
-
|
40
|
+
|
34
41
|
self.latest_version_number = version_number
|
35
42
|
latest_version.module_eval &block if block
|
36
43
|
end
|
37
|
-
|
44
|
+
|
38
45
|
# Find the maximal version satisifying the given requirement.
|
39
|
-
#
|
40
|
-
# The requirement may be a version string such as "1.0.7", or a comparator followed by a
|
41
|
-
#
|
46
|
+
#
|
47
|
+
# The requirement may be a version string such as "1.0.7", or a comparator followed by a
|
48
|
+
# version such as "< 3.0".
|
49
|
+
#
|
42
50
|
# Returns the matching module if found, nil otherwise.
|
43
51
|
def find(version_requirement)
|
44
52
|
if version_requirement =~ VersionNumber::VERSION_NUMBER_REGEX
|
45
|
-
versions[VersionNumber.new(version_requirement)]
|
46
|
-
elsif version_requirement =~ Versions::COMPARISON_REGEX
|
47
|
-
comparator, version_requirement = $1, VersionNumber.new($2)
|
48
|
-
comparator = '==' if comparator == '=' # stick that in your pipe and smoke it.
|
49
|
-
comparator = comparator.to_sym
|
50
|
-
|
51
|
-
match = (versions.keys + [latest_version_number]).select { |v| v.send comparator, version_requirement }.max
|
52
|
-
|
53
|
-
versions[match]
|
54
|
-
else
|
55
|
-
nil
|
53
|
+
return versions[VersionNumber.new(version_requirement)]
|
56
54
|
end
|
55
|
+
|
56
|
+
return nil unless version_requirement =~ Versions::COMPARISON_REGEX
|
57
|
+
|
58
|
+
# Break the comparator (relational operator) out from the version requrement
|
59
|
+
comparator, version_requirement = $1, VersionNumber.new($2)
|
60
|
+
comparator = '==' if comparator == '=' # stick that in your pipe and smoke it.
|
61
|
+
comparator = comparator.to_sym
|
62
|
+
|
63
|
+
match = (versions.keys + [latest_version_number]).select do |v|
|
64
|
+
v.send comparator, version_requirement
|
65
|
+
end.max
|
66
|
+
|
67
|
+
versions[match]
|
57
68
|
end
|
58
|
-
|
69
|
+
|
59
70
|
private
|
60
71
|
|
61
72
|
attr_accessor :latest_version # :nodoc:
|
@@ -28,12 +28,6 @@ describe Versionable::VersionNumber do
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
describe "#next" do
|
32
|
-
it "bumps most significant segment by 1 and drops remainder" do
|
33
|
-
v("1.0").next.should == v("2")
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
31
|
describe "#hash" do
|
38
32
|
it "is the string hash after stripping trailing zero segments" do
|
39
33
|
v("1").hash.should == v("1.0.0.0.0").hash
|
data/versionable.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{versionable}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Phil Smith"]
|
12
|
-
s.date = %q{2010-04-
|
12
|
+
s.date = %q{2010-04-26}
|
13
13
|
s.description = %q{Versionable lets a ruby module or class declare multiple numbered versions of itself, and provides a way to select one based on a gem-like requirement.}
|
14
14
|
s.email = %q{phil.h.smith@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Phil Smith
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-26 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|