versionomy 0.1.3 → 0.2.0
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.
- data/History.rdoc +15 -1
- data/README.rdoc +73 -22
- data/Rakefile +1 -1
- data/lib/versionomy/{formats.rb → conversion/base.rb} +36 -37
- data/lib/versionomy/conversion/parsing.rb +173 -0
- data/lib/versionomy/conversion/rubygems.rb +138 -0
- data/lib/versionomy/conversion.rb +145 -0
- data/lib/versionomy/errors.rb +22 -2
- data/lib/versionomy/format/base.rb +53 -5
- data/lib/versionomy/format/delimiter.rb +39 -27
- data/lib/versionomy/format/rubygems.rb +234 -0
- data/lib/versionomy/format/standard.rb +382 -0
- data/lib/versionomy/format.rb +73 -4
- data/lib/versionomy/interface.rb +22 -14
- data/lib/versionomy/schema/field.rb +14 -5
- data/lib/versionomy/schema/wrapper.rb +84 -10
- data/lib/versionomy/schema.rb +9 -6
- data/lib/versionomy/value.rb +191 -53
- data/lib/versionomy/version.rb +1 -1
- data/lib/versionomy.rb +6 -2
- data/tests/tc_custom_format.rb +4 -4
- data/tests/tc_readme_examples.rb +9 -9
- data/tests/tc_rubygems_basic.rb +210 -0
- data/tests/tc_rubygems_conversions.rb +178 -0
- data/tests/tc_standard_basic.rb +10 -10
- data/tests/tc_standard_bump.rb +10 -10
- data/tests/tc_standard_change.rb +5 -5
- data/tests/tc_standard_comparison.rb +29 -16
- data/tests/tc_standard_misc.rb +95 -0
- data/tests/tc_standard_parse.rb +43 -23
- metadata +15 -5
- data/lib/versionomy/formats/standard.rb +0 -346
@@ -46,7 +46,7 @@ module Versionomy
|
|
46
46
|
# fields. If you provide a block, you must use the methods in
|
47
47
|
# Versionomy::Schema::Builder in the block to create the root field.
|
48
48
|
|
49
|
-
def self.create(field_=nil, &block_)
|
49
|
+
def self.create(field_=nil, opts_={}, &block_)
|
50
50
|
if field_ && block_
|
51
51
|
raise ::ArgumentError, 'You may provide either a root field or block but not both'
|
52
52
|
end
|
@@ -54,8 +54,11 @@ module Versionomy
|
|
54
54
|
builder_ = Schema::Builder.new
|
55
55
|
::Blockenspiel.invoke(block_, builder_)
|
56
56
|
field_ = builder_._get_field
|
57
|
+
modules_ = builder_._get_modules
|
58
|
+
else
|
59
|
+
modules_ = opts_[:modules] || []
|
57
60
|
end
|
58
|
-
Schema::Wrapper.new(field_)
|
61
|
+
Schema::Wrapper.new(field_, modules_)
|
59
62
|
end
|
60
63
|
|
61
64
|
|
@@ -68,33 +71,59 @@ module Versionomy
|
|
68
71
|
# This is a low-level method. Usually you should call
|
69
72
|
# Versionomy::Schema#create instead.
|
70
73
|
|
71
|
-
def initialize(field_)
|
74
|
+
def initialize(field_, modules_=[])
|
72
75
|
@root_field = field_
|
73
76
|
@names = @root_field._descendants_by_name
|
77
|
+
@modules = modules_
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def inspect # :nodoc:
|
82
|
+
"#<#{self.class}:0x#{object_id.to_s(16)} root=#{@root_field.inspect}>"
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_s # :nodoc:
|
86
|
+
inspect
|
74
87
|
end
|
75
88
|
|
76
89
|
|
77
90
|
# Returns true if this schema is equivalent to the other schema.
|
78
91
|
# Two schemas are equivalent if their root fields are the same--
|
79
|
-
# which means that the entire field tree is the same
|
92
|
+
# which means that the entire field tree is the same-- and they
|
93
|
+
# include the same value modules.
|
94
|
+
# Note that this is different from the definition of <tt>==</tt>.
|
80
95
|
|
81
96
|
def eql?(obj_)
|
82
97
|
return false unless obj_.kind_of?(Schema::Wrapper)
|
83
|
-
return @root_field == obj_.root_field
|
98
|
+
return @root_field == obj_.root_field && @modules == obj_.modules
|
84
99
|
end
|
85
100
|
|
86
101
|
|
87
|
-
# Returns true if this schema is
|
88
|
-
# Two schemas are
|
89
|
-
# which means that the entire field tree is the same.
|
102
|
+
# Returns true if this schema is compatible with the other schema.
|
103
|
+
# Two schemas are compatible if their root fields are the same--
|
104
|
+
# which means that the entire field tree is the same. They may,
|
105
|
+
# however, include different value modules.
|
106
|
+
# Note that this is different from the definition of <tt>eql?</tt>.
|
90
107
|
|
91
108
|
def ==(obj_)
|
92
109
|
eql?(obj_)
|
93
110
|
end
|
94
111
|
|
95
112
|
|
113
|
+
# If the RHS is a schema, returns true if the schemas are equivalent.
|
114
|
+
# If the RHS is a value, returns true if the value uses this schema.
|
115
|
+
|
116
|
+
def ===(obj_)
|
117
|
+
if obj_.kind_of?(Value)
|
118
|
+
obj_.schema == self
|
119
|
+
else
|
120
|
+
obj_ == self
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
|
96
125
|
def hash # :nodoc:
|
97
|
-
@hash ||= @root_field.hash
|
126
|
+
@hash ||= @root_field.hash ^ @modules.hash
|
98
127
|
end
|
99
128
|
|
100
129
|
|
@@ -121,6 +150,14 @@ module Versionomy
|
|
121
150
|
end
|
122
151
|
|
123
152
|
|
153
|
+
# Returns an array of modules that should be included in values that
|
154
|
+
# use this schema.
|
155
|
+
|
156
|
+
def modules
|
157
|
+
@modules.dup
|
158
|
+
end
|
159
|
+
|
160
|
+
|
124
161
|
end
|
125
162
|
|
126
163
|
|
@@ -133,6 +170,8 @@ module Versionomy
|
|
133
170
|
|
134
171
|
def initialize() # :nodoc:
|
135
172
|
@field = nil
|
173
|
+
@modules = []
|
174
|
+
@defaults = { :integer => {}, :string => {}, :symbol => {} }
|
136
175
|
end
|
137
176
|
|
138
177
|
|
@@ -161,7 +200,34 @@ module Versionomy
|
|
161
200
|
if @field
|
162
201
|
raise Errors::RangeOverlapError, "Root field already defined"
|
163
202
|
end
|
164
|
-
@field = Schema::Field.new(name_, opts_, &block_)
|
203
|
+
@field = Schema::Field.new(name_, opts_.merge(:master_builder => self), &block_)
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
# Add a module to values that use this schema.
|
208
|
+
|
209
|
+
def add_module(mod_)
|
210
|
+
@modules << mod_
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
def to_bump_type(type_, &block_)
|
215
|
+
@defaults[type_][:bump] = block_
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
def to_compare_type(type_, &block_)
|
220
|
+
@defaults[type_][:compare] = block_
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
def to_canonicalize_type(type_, &block_)
|
225
|
+
@defaults[type_][:canonicalize] = block_
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
def default_value_for_type(type_, value_)
|
230
|
+
@defaults[type_][:value] = value_
|
165
231
|
end
|
166
232
|
|
167
233
|
|
@@ -169,6 +235,14 @@ module Versionomy
|
|
169
235
|
@field
|
170
236
|
end
|
171
237
|
|
238
|
+
def _get_modules # :nodoc:
|
239
|
+
@modules
|
240
|
+
end
|
241
|
+
|
242
|
+
def _get_default_setting(type_, setting_) # :nodoc:
|
243
|
+
@defaults[type_][setting_]
|
244
|
+
end
|
245
|
+
|
172
246
|
end
|
173
247
|
|
174
248
|
|
data/lib/versionomy/schema.rb
CHANGED
@@ -43,17 +43,20 @@ module Versionomy
|
|
43
43
|
# The schema controls what fields are present in the version, how
|
44
44
|
# version numbers are compared, what the default values are, and how
|
45
45
|
# values can change. Version numbers with the same schema can be
|
46
|
-
# compared with one another, and version numbers can be converted
|
47
|
-
# formats that share the same schema
|
46
|
+
# compared with one another, and version numbers can be converted
|
47
|
+
# trivially to formats that share the same schema, without requiring a
|
48
|
+
# Conversion implementation.
|
48
49
|
#
|
49
50
|
# At its simplest, a version number is defined as a sequence of fields,
|
50
51
|
# each with a name and data type. These fields may be integer-valued,
|
51
52
|
# string-valued, or symbolic, though most will probably be integers.
|
52
|
-
# Symbolic fields are useful, for example, if
|
53
|
-
# the type of prerelease (e.g. "alpha",
|
53
|
+
# Symbolic fields are enumerated types that are useful, for example, if
|
54
|
+
# you want a field to specify the type of prerelease (e.g. "alpha",
|
55
|
+
# "beta", or "release candidate").
|
54
56
|
#
|
55
|
-
# As a simple example, you could construct a schema for
|
56
|
-
# of the form "major.minor.tiny" like this
|
57
|
+
# As a simple conceptual example, you could construct a schema for
|
58
|
+
# version numbers of the form "major.minor.tiny" like this. (This is a
|
59
|
+
# conceptual diagram, not actual syntax.)
|
57
60
|
#
|
58
61
|
# ("major": integer), ("minor": integer), ("tiny": integer)
|
59
62
|
#
|
data/lib/versionomy/value.rb
CHANGED
@@ -34,6 +34,9 @@
|
|
34
34
|
;
|
35
35
|
|
36
36
|
|
37
|
+
require 'yaml'
|
38
|
+
|
39
|
+
|
37
40
|
module Versionomy
|
38
41
|
|
39
42
|
|
@@ -64,18 +67,21 @@ module Versionomy
|
|
64
67
|
unless values_.kind_of?(::Hash) || values_.kind_of?(::Array)
|
65
68
|
raise ::ArgumentError, "Expected hash or array but got #{values_.class}"
|
66
69
|
end
|
67
|
-
@
|
68
|
-
@
|
69
|
-
@
|
70
|
-
@
|
71
|
-
|
70
|
+
@_format = format_
|
71
|
+
@_unparse_params = unparse_params_
|
72
|
+
@_field_path = []
|
73
|
+
@_values = {}
|
74
|
+
schema_ = @_format.schema
|
75
|
+
field_ = schema_.root_field
|
72
76
|
while field_
|
73
|
-
value_ = values_.kind_of?(Hash) ? values_[field_.name] : values_.shift
|
77
|
+
value_ = values_.kind_of?(::Hash) ? values_[field_.name] : values_.shift
|
74
78
|
value_ = value_ ? field_.canonicalize_value(value_) : field_.default_value
|
75
|
-
@
|
76
|
-
@
|
79
|
+
@_field_path << field_
|
80
|
+
@_values[field_.name] = value_
|
77
81
|
field_ = field_.child(value_)
|
78
82
|
end
|
83
|
+
modules_ = schema_.modules
|
84
|
+
extend(*modules_) if modules_.size > 0
|
79
85
|
end
|
80
86
|
|
81
87
|
|
@@ -90,7 +96,7 @@ module Versionomy
|
|
90
96
|
|
91
97
|
def _inspect # :nodoc:
|
92
98
|
"#<#{self.class}:0x#{object_id.to_s(16)} " +
|
93
|
-
@
|
99
|
+
@_field_path.map{ |field_| "#{field_.name}=#{@_values[field_.name].inspect}" }.join(' ')
|
94
100
|
end
|
95
101
|
|
96
102
|
|
@@ -107,26 +113,103 @@ module Versionomy
|
|
107
113
|
end
|
108
114
|
|
109
115
|
|
110
|
-
#
|
116
|
+
# Marshal this version number.
|
117
|
+
|
118
|
+
def marshal_dump # :nodoc:
|
119
|
+
format_name_ = Format.canonical_name_for(@_format, true)
|
120
|
+
unparsed_data_ = nil
|
121
|
+
if @_format.respond_to?(:unparse_for_serialization)
|
122
|
+
unparsed_data_ = @_format.unparse_for_serialization(self) rescue nil
|
123
|
+
end
|
124
|
+
unparsed_data_ ||= @_format.unparse(self) rescue nil
|
125
|
+
data_ = [format_name_]
|
126
|
+
case unparsed_data_
|
127
|
+
when ::Array
|
128
|
+
data_ << unparsed_data_[0]
|
129
|
+
data_ << unparsed_data_[1] if unparsed_data_[1]
|
130
|
+
when ::String
|
131
|
+
data_ << unparsed_data_
|
132
|
+
else
|
133
|
+
data_ << values_array
|
134
|
+
data_ << @_unparse_params if @_unparse_params
|
135
|
+
end
|
136
|
+
data_
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# Unmarshal this version number.
|
141
|
+
|
142
|
+
def marshal_load(data_) # :nodoc:
|
143
|
+
format_ = Format.get(data_[0], true)
|
144
|
+
if data_[1].kind_of?(::String)
|
145
|
+
val_ = format_.parse(data_[1], data_[2])
|
146
|
+
initialize(val_.values_array, format_, val_.unparse_params)
|
147
|
+
else
|
148
|
+
initialize(data_[1], format_, data_[2])
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
yaml_as "tag:danielazuma.com,2009:version"
|
154
|
+
|
155
|
+
|
156
|
+
# Deserialize a version number from YAML
|
157
|
+
|
158
|
+
def self.yaml_new(klass_, tag_, data_) # :nodoc:
|
159
|
+
unless data_.kind_of?(::Hash)
|
160
|
+
raise ::YAML::TypeError, "Invalid version format: #{val_.inspect}"
|
161
|
+
end
|
162
|
+
format_ = Format.get(data_['format'], true)
|
163
|
+
value_ = data_['value']
|
164
|
+
if value_
|
165
|
+
format_.parse(value_, data_['parse_params'])
|
166
|
+
else
|
167
|
+
Value.new(format_, data_['fields'], data_['unparse_params'])
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
# Serialize this version number to YAML format.
|
173
|
+
|
174
|
+
def to_yaml(opts_={})
|
175
|
+
data_ = marshal_dump
|
176
|
+
::YAML::quick_emit(nil, opts_) do |out_|
|
177
|
+
out_.map(taguri, to_yaml_style) do |map_|
|
178
|
+
map_.add('format', data_[0])
|
179
|
+
if data_[1].kind_of?(::String)
|
180
|
+
map_.add('value', data_[1])
|
181
|
+
map_.add('parse_params', data_[2]) if data_[2]
|
182
|
+
else
|
183
|
+
map_.add('fields', data_[1])
|
184
|
+
map_.add('unparse_params', data_[2]) if data_[2]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
# Unparse this version number and return a string.
|
111
192
|
#
|
112
193
|
# Raises Versionomy::Errors::UnparseError if unparsing failed.
|
113
194
|
|
114
195
|
def unparse(params_=nil)
|
115
|
-
@
|
196
|
+
@_format.unparse(self, params_)
|
116
197
|
end
|
117
198
|
|
118
199
|
|
119
|
-
# Return the schema defining the
|
200
|
+
# Return the schema defining the structure and semantics of this
|
201
|
+
# version number.
|
120
202
|
|
121
203
|
def schema
|
122
|
-
@
|
204
|
+
@_format.schema
|
123
205
|
end
|
124
206
|
|
125
207
|
|
126
|
-
# Return the format defining the
|
208
|
+
# Return the format defining the schema and formatting/parsing of
|
209
|
+
# this version number.
|
127
210
|
|
128
211
|
def format
|
129
|
-
@
|
212
|
+
@_format
|
130
213
|
end
|
131
214
|
|
132
215
|
|
@@ -134,15 +217,15 @@ module Versionomy
|
|
134
217
|
# Returns nil if this value was not created using a parser.
|
135
218
|
|
136
219
|
def unparse_params
|
137
|
-
@
|
220
|
+
@_unparse_params ? @_unparse_params.dup : nil
|
138
221
|
end
|
139
222
|
|
140
223
|
|
141
224
|
# Iterates over each field, in field order, yielding the field name and value.
|
142
225
|
|
143
226
|
def each_field
|
144
|
-
@
|
145
|
-
yield(field_, @
|
227
|
+
@_field_path.each do |field_|
|
228
|
+
yield(field_, @_values[field_.name])
|
146
229
|
end
|
147
230
|
end
|
148
231
|
|
@@ -151,16 +234,18 @@ module Versionomy
|
|
151
234
|
# Versionomy::Schema::Field object and value.
|
152
235
|
|
153
236
|
def each_field_object # :nodoc:
|
154
|
-
@
|
155
|
-
yield(field_, @
|
237
|
+
@_field_path.each do |field_|
|
238
|
+
yield(field_, @_values[field_.name])
|
156
239
|
end
|
157
240
|
end
|
158
241
|
|
159
242
|
|
160
243
|
# Returns an array of recognized field names for this value, in field order.
|
244
|
+
# This is the order of the fields actually present in this value, in
|
245
|
+
# order from most to least significant.
|
161
246
|
|
162
247
|
def field_names
|
163
|
-
@
|
248
|
+
@_field_path.map{ |field_| field_.name }
|
164
249
|
end
|
165
250
|
|
166
251
|
|
@@ -170,11 +255,11 @@ module Versionomy
|
|
170
255
|
def has_field?(field_)
|
171
256
|
case field_
|
172
257
|
when Schema::Field
|
173
|
-
@
|
258
|
+
@_field_path.include?(field_)
|
174
259
|
when ::Integer
|
175
|
-
@
|
260
|
+
@_field_path.size > field_ && field_ >= 0
|
176
261
|
when ::String, ::Symbol
|
177
|
-
@
|
262
|
+
@_values.has_key?(field_.to_sym)
|
178
263
|
else
|
179
264
|
raise ::ArgumentError
|
180
265
|
end
|
@@ -186,45 +271,47 @@ module Versionomy
|
|
186
271
|
# or field index.
|
187
272
|
|
188
273
|
def [](field_)
|
189
|
-
field_ = @
|
274
|
+
field_ = @_field_path[field_] if field_.kind_of?(::Integer)
|
190
275
|
field_ = field_.name if field_.kind_of?(Schema::Field)
|
191
|
-
field_ ? @
|
276
|
+
field_ ? @_values[field_.to_sym] : nil
|
192
277
|
end
|
193
278
|
|
194
279
|
|
195
280
|
# Returns the value as an array of field values, in field order.
|
281
|
+
# This is the order of the fields actually present in this value, in
|
282
|
+
# order from most to least significant.
|
196
283
|
|
197
284
|
def values_array
|
198
|
-
@
|
285
|
+
@_field_path.map{ |field_| @_values[field_.name] }
|
199
286
|
end
|
200
287
|
|
201
288
|
|
202
289
|
# Returns the value as a hash of values keyed by field name.
|
203
290
|
|
204
291
|
def values_hash
|
205
|
-
@
|
292
|
+
@_values.dup
|
206
293
|
end
|
207
294
|
|
208
295
|
|
209
296
|
# Returns a new version number created by bumping the given field. The
|
210
297
|
# field may be specified as a field object, field name, or field index.
|
211
|
-
# Returns self if
|
212
|
-
#
|
298
|
+
# Returns self unchanged if the field was not recognized or could not
|
299
|
+
# be modified.
|
213
300
|
|
214
301
|
def bump(name_)
|
215
|
-
name_ = @
|
302
|
+
name_ = @_field_path[name_] if name_.kind_of?(::Integer)
|
216
303
|
name_ = name_.name if name_.kind_of?(Schema::Field)
|
217
|
-
return
|
304
|
+
return self unless name_
|
218
305
|
name_ = name_.to_sym
|
219
|
-
return
|
306
|
+
return self unless @_values.include?(name_)
|
220
307
|
values_ = []
|
221
|
-
@
|
222
|
-
oldval_ = @
|
308
|
+
@_field_path.each do |field_|
|
309
|
+
oldval_ = @_values[field_.name]
|
223
310
|
if field_.name == name_
|
224
311
|
newval_ = field_.bump_value(oldval_)
|
225
312
|
return self if newval_ == oldval_
|
226
313
|
values_ << newval_
|
227
|
-
return Value.new(values_, @
|
314
|
+
return Value.new(values_, @_format, @_unparse_params)
|
228
315
|
else
|
229
316
|
values_ << oldval_
|
230
317
|
end
|
@@ -233,63 +320,109 @@ module Versionomy
|
|
233
320
|
end
|
234
321
|
|
235
322
|
|
236
|
-
# Returns a new version number created by
|
323
|
+
# Returns a new version number created by cloning this version number
|
324
|
+
# and changing the given field values.
|
325
|
+
#
|
326
|
+
# You should pass in a hash of field names to values. These are the
|
327
|
+
# fields to modify; any other fields will be left alone, unless they
|
328
|
+
# are implicitly changed by the modifications you are making.
|
329
|
+
# For example, changing the :release_type on a value using the standard
|
330
|
+
# format, may change which fields are present in the resulting value.
|
331
|
+
#
|
332
|
+
# You may also pass a delta hash to modify the unparse params stored in
|
333
|
+
# the value.
|
237
334
|
|
238
335
|
def change(values_={}, unparse_params_={})
|
239
|
-
unparse_params_ = @
|
240
|
-
Value.new(@
|
336
|
+
unparse_params_ = @_unparse_params.merge(unparse_params_) if @_unparse_params
|
337
|
+
Value.new(@_values.merge(values_), @_format, unparse_params_)
|
338
|
+
end
|
339
|
+
|
340
|
+
|
341
|
+
# Attempts to convert this value to the given format, and returns the
|
342
|
+
# resulting value.
|
343
|
+
#
|
344
|
+
# Raises Versionomy::Errors::ConversionError if the value could not
|
345
|
+
# be converted.
|
346
|
+
|
347
|
+
def convert(format_, convert_params_=nil)
|
348
|
+
if format_.kind_of?(::String) || format_.kind_of?(::Symbol)
|
349
|
+
format_ = Format.get(format_)
|
350
|
+
end
|
351
|
+
return self if @_format == format_
|
352
|
+
from_schema_ = @_format.schema
|
353
|
+
to_schema_ = format_.schema
|
354
|
+
if from_schema_ == to_schema_
|
355
|
+
return Value.new(@_values, format_, convert_params_)
|
356
|
+
end
|
357
|
+
conversion_ = Conversion.get(from_schema_, to_schema_, true)
|
358
|
+
conversion_.convert_value(self, format_, convert_params_)
|
241
359
|
end
|
242
360
|
|
243
361
|
|
244
362
|
def hash # :nodoc:
|
245
|
-
@
|
363
|
+
@_hash ||= @_values.hash
|
246
364
|
end
|
247
365
|
|
248
366
|
|
249
|
-
# Returns true if this version number is
|
250
|
-
#
|
367
|
+
# Returns true if this version number is equivalent to the given number.
|
368
|
+
# This type of equality means their schemas are compatible and their
|
369
|
+
# field values are equal.
|
370
|
+
# Note that this is different from the definition of <tt>==</tt>.
|
251
371
|
|
252
372
|
def eql?(obj_)
|
253
373
|
if obj_.kind_of?(::String)
|
254
|
-
obj_ = @
|
374
|
+
obj_ = @_format.parse(obj_) rescue nil
|
255
375
|
end
|
256
376
|
return false unless obj_.kind_of?(Value)
|
257
377
|
index_ = 0
|
258
378
|
obj_.each_field_object do |field_, value_|
|
259
|
-
return false if field_ != @
|
379
|
+
return false if field_ != @_field_path[index_] || value_ != @_values[field_.name]
|
260
380
|
index_ += 1
|
261
381
|
end
|
262
382
|
true
|
263
383
|
end
|
264
384
|
|
265
385
|
|
266
|
-
# Returns true if this version number is equal to the given
|
267
|
-
#
|
386
|
+
# Returns true if this version number is value-equal to the given number.
|
387
|
+
# This type of equality means that they are equivalent, or that it is
|
388
|
+
# possible to convert the RHS to the LHS's format, and that they would
|
389
|
+
# be equivalent after such a conversion has taken place.
|
390
|
+
# Note that this is different from the definition of <tt>eql?</tt>.
|
268
391
|
|
269
392
|
def ==(obj_)
|
270
|
-
|
393
|
+
(self <=> obj_) == 0
|
271
394
|
end
|
272
395
|
|
273
396
|
|
274
|
-
# Compare this version number with the given version number
|
397
|
+
# Compare this version number with the given version number,
|
398
|
+
# returning 0 if the two are value-equal, a negative number if the RHS
|
399
|
+
# is greater, or a positive number if the LHS is greater.
|
400
|
+
# The comparison may succeed even if the two have different schemas,
|
401
|
+
# if the RHS can be converted to the LHS's format.
|
275
402
|
|
276
403
|
def <=>(obj_)
|
277
404
|
if obj_.kind_of?(::String)
|
278
|
-
obj_ = @
|
405
|
+
obj_ = @_format.parse(obj_)
|
279
406
|
end
|
280
407
|
return nil unless obj_.kind_of?(Value)
|
281
|
-
|
408
|
+
if obj_.schema != @_format.schema
|
409
|
+
begin
|
410
|
+
obj_ = obj_.convert(@_format)
|
411
|
+
rescue
|
412
|
+
return nil
|
413
|
+
end
|
414
|
+
end
|
282
415
|
obj_.each_field_object do |field_, value_|
|
283
|
-
|
284
|
-
val_ = field_.compare_values(@values[field_.name], value_)
|
416
|
+
val_ = field_.compare_values(@_values[field_.name], value_)
|
285
417
|
return val_ if val_ != 0
|
286
|
-
index_ += 1
|
287
418
|
end
|
288
419
|
0
|
289
420
|
end
|
290
421
|
|
291
422
|
|
292
423
|
# Compare this version number with the given version number.
|
424
|
+
# The comparison may succeed even if the two have different schemas,
|
425
|
+
# if the RHS can be converted to the LHS's format.
|
293
426
|
|
294
427
|
def <(obj_)
|
295
428
|
val_ = (self <=> obj_)
|
@@ -301,6 +434,8 @@ module Versionomy
|
|
301
434
|
|
302
435
|
|
303
436
|
# Compare this version number with the given version number.
|
437
|
+
# The comparison may succeed even if the two have different schemas,
|
438
|
+
# if the RHS can be converted to the LHS's format.
|
304
439
|
|
305
440
|
def >(obj_)
|
306
441
|
val_ = (self <=> obj_)
|
@@ -311,6 +446,9 @@ module Versionomy
|
|
311
446
|
end
|
312
447
|
|
313
448
|
|
449
|
+
include ::Comparable
|
450
|
+
|
451
|
+
|
314
452
|
# Field values may be retrieved by calling them as methods.
|
315
453
|
|
316
454
|
def method_missing(symbol_)
|
data/lib/versionomy/version.rb
CHANGED
data/lib/versionomy.rb
CHANGED
@@ -52,9 +52,13 @@ includes_ = [
|
|
52
52
|
'format',
|
53
53
|
'format/base',
|
54
54
|
'format/delimiter',
|
55
|
-
'
|
56
|
-
'
|
55
|
+
'format/standard',
|
56
|
+
'format/rubygems',
|
57
57
|
'value',
|
58
|
+
'conversion',
|
59
|
+
'conversion/base',
|
60
|
+
'conversion/parsing',
|
61
|
+
'conversion/rubygems',
|
58
62
|
'interface',
|
59
63
|
'version',
|
60
64
|
]
|
data/tests/tc_custom_format.rb
CHANGED
@@ -36,24 +36,24 @@
|
|
36
36
|
|
37
37
|
|
38
38
|
require 'test/unit'
|
39
|
-
require File.expand_path("#{File.dirname(__FILE__)}/../lib/versionomy.rb")
|
39
|
+
require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/versionomy.rb")
|
40
40
|
|
41
41
|
|
42
42
|
module Versionomy
|
43
43
|
module Tests # :nodoc:
|
44
44
|
|
45
|
-
class TestCustomFormat < Test::Unit::TestCase # :nodoc:
|
45
|
+
class TestCustomFormat < ::Test::Unit::TestCase # :nodoc:
|
46
46
|
|
47
47
|
|
48
48
|
# Test parsing with custom format for patchlevel
|
49
49
|
|
50
50
|
def test_parsing_custom_patchlevel_format
|
51
|
-
format_ = Versionomy.default_format.modified_copy do
|
51
|
+
format_ = ::Versionomy.default_format.modified_copy do
|
52
52
|
field(:patchlevel, :requires_previous_field => false) do
|
53
53
|
recognize_number(:delimiter_regexp => '\s?sp', :default_delimiter => ' SP')
|
54
54
|
end
|
55
55
|
end
|
56
|
-
value1_ = Versionomy.parse('2008 SP2', format_)
|
56
|
+
value1_ = ::Versionomy.parse('2008 SP2', format_)
|
57
57
|
assert_equal(2, value1_.patchlevel)
|
58
58
|
value2_ = value1_.format.parse('2008 sp3')
|
59
59
|
assert_equal(3, value2_.patchlevel)
|