versionomy 0.4.1 → 0.4.2
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 +4 -0
- data/Version +1 -1
- data/lib/versionomy.rb +19 -25
- data/lib/versionomy/conversion.rb +41 -41
- data/lib/versionomy/conversion/base.rb +31 -31
- data/lib/versionomy/conversion/parsing.rb +49 -49
- data/lib/versionomy/errors.rb +63 -63
- data/lib/versionomy/format.rb +51 -51
- data/lib/versionomy/format/base.rb +44 -44
- data/lib/versionomy/format/delimiter.rb +205 -205
- data/lib/versionomy/format_definitions/rubygems.rb +85 -85
- data/lib/versionomy/format_definitions/semver.rb +78 -78
- data/lib/versionomy/format_definitions/standard.rb +68 -68
- data/lib/versionomy/interface.rb +46 -46
- data/lib/versionomy/schema.rb +21 -21
- data/lib/versionomy/schema/field.rb +112 -112
- data/lib/versionomy/schema/wrapper.rb +91 -91
- data/lib/versionomy/value.rb +224 -180
- data/lib/versionomy/version.rb +9 -9
- data/test/tc_custom_format.rb +14 -14
- data/test/tc_readme_examples.rb +24 -24
- data/test/tc_rubygems_basic.rb +68 -68
- data/test/tc_rubygems_conversions.rb +46 -46
- data/test/tc_semver_basic.rb +62 -62
- data/test/tc_semver_conversions.rb +52 -52
- data/test/tc_standard_basic.rb +35 -35
- data/test/tc_standard_bump.rb +35 -35
- data/test/tc_standard_change.rb +20 -20
- data/test/tc_standard_comparison.rb +38 -38
- data/test/tc_standard_misc.rb +23 -23
- data/test/tc_standard_parse.rb +77 -77
- data/test/tc_standard_reset.rb +29 -29
- data/test/tc_version_of.rb +15 -15
- metadata +30 -34
@@ -1,15 +1,15 @@
|
|
1
1
|
# -----------------------------------------------------------------------------
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Versionomy schema wrapper class
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
# Copyright 2008-2009 Daniel Azuma
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# All rights reserved.
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# Redistribution and use in source and binary forms, with or without
|
11
11
|
# modification, are permitted provided that the following conditions are met:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# * Redistributions of source code must retain the above copyright notice,
|
14
14
|
# this list of conditions and the following disclaimer.
|
15
15
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
@@ -18,7 +18,7 @@
|
|
18
18
|
# * Neither the name of the copyright holder, nor the names of any other
|
19
19
|
# contributors to this software, may be used to endorse or promote products
|
20
20
|
# derived from this software without specific prior written permission.
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
23
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
24
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
@@ -35,17 +35,17 @@
|
|
35
35
|
|
36
36
|
|
37
37
|
module Versionomy
|
38
|
-
|
38
|
+
|
39
39
|
module Schema
|
40
|
-
|
41
|
-
|
40
|
+
|
41
|
+
|
42
42
|
# Creates a schema.
|
43
43
|
# Returns an object of type Versionomy::Schema::Wrapper.
|
44
|
-
#
|
44
|
+
#
|
45
45
|
# You may either pass a root field, or provide a block to use to build
|
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
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'
|
@@ -61,17 +61,17 @@ module Versionomy
|
|
61
61
|
end
|
62
62
|
Schema::Wrapper.new(field_, modules_, aliases_)
|
63
63
|
end
|
64
|
-
|
65
|
-
|
64
|
+
|
65
|
+
|
66
66
|
# Schemas are generally referenced through an object of this class.
|
67
|
-
|
67
|
+
|
68
68
|
class Wrapper
|
69
|
-
|
70
|
-
|
69
|
+
|
70
|
+
|
71
71
|
# Create a new schema wrapper object given a root field.
|
72
72
|
# This is a low-level method. Usually you should call
|
73
73
|
# Versionomy::Schema#create instead.
|
74
|
-
|
74
|
+
|
75
75
|
def initialize(field_, modules_=[], aliases_={})
|
76
76
|
@root_field = field_
|
77
77
|
@names = @root_field._descendants_by_name
|
@@ -85,43 +85,43 @@ module Versionomy
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
88
|
-
|
89
|
-
|
88
|
+
|
89
|
+
|
90
90
|
def inspect # :nodoc:
|
91
91
|
"#<#{self.class}:0x#{object_id.to_s(16)} root=#{@root_field.inspect}>"
|
92
92
|
end
|
93
|
-
|
93
|
+
|
94
94
|
def to_s # :nodoc:
|
95
95
|
inspect
|
96
96
|
end
|
97
|
-
|
98
|
-
|
97
|
+
|
98
|
+
|
99
99
|
# Returns true if this schema is equivalent to the other schema.
|
100
100
|
# Two schemas are equivalent if their root fields are the same--
|
101
101
|
# which means that the entire field tree is the same-- and they
|
102
102
|
# include the same value modules.
|
103
103
|
# Note that this is different from the definition of <tt>==</tt>.
|
104
|
-
|
104
|
+
|
105
105
|
def eql?(obj_)
|
106
106
|
return false unless obj_.kind_of?(Schema::Wrapper)
|
107
107
|
return @root_field == obj_.root_field && @modules == obj_.modules && @aliases == obj_.aliases
|
108
108
|
end
|
109
|
-
|
110
|
-
|
109
|
+
|
110
|
+
|
111
111
|
# Returns true if this schema is compatible with the other schema.
|
112
112
|
# Two schemas are compatible if their root fields are the same--
|
113
113
|
# which means that the entire field tree is the same. They may,
|
114
114
|
# however, include different value modules.
|
115
115
|
# Note that this is different from the definition of <tt>eql?</tt>.
|
116
|
-
|
116
|
+
|
117
117
|
def ==(obj_)
|
118
118
|
eql?(obj_)
|
119
119
|
end
|
120
|
-
|
121
|
-
|
120
|
+
|
121
|
+
|
122
122
|
# If the RHS is a schema, returns true if the schemas are equivalent.
|
123
123
|
# If the RHS is a value, returns true if the value uses this schema.
|
124
|
-
|
124
|
+
|
125
125
|
def ===(obj_)
|
126
126
|
if obj_.kind_of?(Value)
|
127
127
|
obj_.schema == self
|
@@ -129,86 +129,86 @@ module Versionomy
|
|
129
129
|
obj_ == self
|
130
130
|
end
|
131
131
|
end
|
132
|
-
|
133
|
-
|
132
|
+
|
133
|
+
|
134
134
|
def hash # :nodoc:
|
135
135
|
@hash ||= @root_field.hash ^ @modules.hash
|
136
136
|
end
|
137
|
-
|
138
|
-
|
137
|
+
|
138
|
+
|
139
139
|
# Returns the root (most significant) field in this schema.
|
140
|
-
|
140
|
+
|
141
141
|
def root_field
|
142
142
|
@root_field
|
143
143
|
end
|
144
|
-
|
145
|
-
|
144
|
+
|
145
|
+
|
146
146
|
# Return the canonical field name given a name, or nil if the name
|
147
147
|
# is not recognized.
|
148
|
-
|
148
|
+
|
149
149
|
def canonical_name(name_)
|
150
150
|
name_ = name_.to_sym
|
151
151
|
name_ = @aliases[name_] || name_
|
152
152
|
@names.include?(name_) ? name_ : nil
|
153
153
|
end
|
154
|
-
|
155
|
-
|
154
|
+
|
155
|
+
|
156
156
|
# Return the field with the given name, or nil if the given name
|
157
157
|
# is not found in this schema. If include_aliases_ is set to true,
|
158
158
|
# this also supports lookup by alias.
|
159
|
-
|
159
|
+
|
160
160
|
def field_named(name_, include_aliases_=false)
|
161
161
|
name_ = name_.to_sym
|
162
162
|
name_ = @aliases[name_] || name_ if include_aliases_
|
163
163
|
field_ = @names[name_]
|
164
164
|
end
|
165
|
-
|
166
|
-
|
165
|
+
|
166
|
+
|
167
167
|
# Returns an array of names present in this schema, in no particular
|
168
168
|
# order. Does not include aliases.
|
169
|
-
|
169
|
+
|
170
170
|
def names
|
171
171
|
@names.keys
|
172
172
|
end
|
173
|
-
|
174
|
-
|
173
|
+
|
174
|
+
|
175
175
|
# Returns an array of modules that should be included in values that
|
176
176
|
# use this schema.
|
177
|
-
|
177
|
+
|
178
178
|
def modules
|
179
179
|
@modules.dup
|
180
180
|
end
|
181
|
-
|
182
|
-
|
181
|
+
|
182
|
+
|
183
183
|
# Returns a hash of field name aliases.
|
184
|
-
|
184
|
+
|
185
185
|
def aliases
|
186
186
|
@aliases.dup
|
187
187
|
end
|
188
|
-
|
189
|
-
|
188
|
+
|
189
|
+
|
190
190
|
end
|
191
|
-
|
192
|
-
|
191
|
+
|
192
|
+
|
193
193
|
# These methods are available in a schema definition block given to
|
194
194
|
# Versionomy::Schema#create.
|
195
|
-
|
195
|
+
|
196
196
|
class Builder
|
197
|
-
|
197
|
+
|
198
198
|
include ::Blockenspiel::DSL
|
199
|
-
|
199
|
+
|
200
200
|
def initialize() # :nodoc:
|
201
201
|
@field = nil
|
202
202
|
@modules = []
|
203
203
|
@aliases = {}
|
204
204
|
@defaults = { :integer => {}, :string => {}, :symbol => {} }
|
205
205
|
end
|
206
|
-
|
207
|
-
|
206
|
+
|
207
|
+
|
208
208
|
# Create the root field.
|
209
|
-
#
|
209
|
+
#
|
210
210
|
# Recognized options include:
|
211
|
-
#
|
211
|
+
#
|
212
212
|
# <tt>:type</tt>::
|
213
213
|
# Type of field. This should be <tt>:integer</tt>, <tt>:string</tt>,
|
214
214
|
# or <tt>:symbol</tt>. Default is <tt>:integer</tt>.
|
@@ -216,51 +216,51 @@ module Versionomy
|
|
216
216
|
# Default value for the field if no value is explicitly set. Default
|
217
217
|
# is 0 for an integer field, the empty string for a string field, or
|
218
218
|
# the first symbol added for a symbol field.
|
219
|
-
#
|
219
|
+
#
|
220
220
|
# You may provide an optional block. Within the block, you may call
|
221
221
|
# methods of Versionomy::Schema::FieldBuilder to customize this field.
|
222
|
-
#
|
222
|
+
#
|
223
223
|
# Raises Versionomy::Errors::IllegalValueError if the given default
|
224
224
|
# value is not legal.
|
225
|
-
#
|
225
|
+
#
|
226
226
|
# Raises Versionomy::Errors::RangeOverlapError if a root field has
|
227
227
|
# already been created.
|
228
|
-
|
228
|
+
|
229
229
|
def field(name_, opts_={}, &block_)
|
230
230
|
if @field
|
231
231
|
raise Errors::RangeOverlapError, "Root field already defined"
|
232
232
|
end
|
233
233
|
@field = Schema::Field.new(name_, opts_.merge(:master_builder => self), &block_)
|
234
234
|
end
|
235
|
-
|
236
|
-
|
235
|
+
|
236
|
+
|
237
237
|
# Create a field alias.
|
238
|
-
|
238
|
+
|
239
239
|
def alias_field(alias_name_, field_name_)
|
240
240
|
@aliases[alias_name_.to_sym] = field_name_.to_sym
|
241
241
|
end
|
242
|
-
|
243
|
-
|
242
|
+
|
243
|
+
|
244
244
|
# Add a module to the schema. All values that use this schema will
|
245
245
|
# include this module. This provides a way to add schema-specific
|
246
246
|
# capabilities to version numbers.
|
247
|
-
|
247
|
+
|
248
248
|
def add_module(mod_)
|
249
249
|
@modules << mod_
|
250
250
|
end
|
251
|
-
|
252
|
-
|
251
|
+
|
252
|
+
|
253
253
|
# Provide a default bump procedure for the given type.
|
254
254
|
# The type should be <tt>:integer</tt>, <tt>:string</tt>, or
|
255
255
|
# <tt>:symbol</tt>. You must provide a block that takes a field value
|
256
256
|
# and returns the "bumped" value. This procedure will be used for
|
257
257
|
# all fields of this type, unless explicitly overridden by the field.
|
258
|
-
|
258
|
+
|
259
259
|
def to_bump_type(type_, &block_)
|
260
260
|
@defaults[type_][:bump] = block_
|
261
261
|
end
|
262
|
-
|
263
|
-
|
262
|
+
|
263
|
+
|
264
264
|
# Provide a default compare procedure for the given type.
|
265
265
|
# The type should be <tt>:integer</tt>, <tt>:string</tt>, or
|
266
266
|
# <tt>:symbol</tt>. You must provide a block that takes two values
|
@@ -269,53 +269,53 @@ module Versionomy
|
|
269
269
|
# positive integer if the first value is greater. This procedure will
|
270
270
|
# be used for all fields of this type, unless explicitly overridden
|
271
271
|
# by the field.
|
272
|
-
|
272
|
+
|
273
273
|
def to_compare_type(type_, &block_)
|
274
274
|
@defaults[type_][:compare] = block_
|
275
275
|
end
|
276
|
-
|
277
|
-
|
276
|
+
|
277
|
+
|
278
278
|
# Provide a default canonicalization procedure for the given type.
|
279
279
|
# The type should be <tt>:integer</tt>, <tt>:string</tt>, or
|
280
280
|
# <tt>:symbol</tt>. You must provide a block that takes a field value
|
281
281
|
# and returns the canonical value. This procedure will be used for
|
282
282
|
# all fields of this type, unless explicitly overridden by the field.
|
283
|
-
|
283
|
+
|
284
284
|
def to_canonicalize_type(type_, &block_)
|
285
285
|
@defaults[type_][:canonicalize] = block_
|
286
286
|
end
|
287
|
-
|
288
|
-
|
287
|
+
|
288
|
+
|
289
289
|
# Provide a default value for the given type.
|
290
290
|
# The type should be <tt>:integer</tt>, <tt>:string</tt>, or
|
291
291
|
# <tt>:symbol</tt>. You must provide a default value that will be
|
292
292
|
# used for all fields of this type, unless explicitly overridden by
|
293
293
|
# the field.
|
294
|
-
|
294
|
+
|
295
295
|
def default_value_for_type(type_, value_)
|
296
296
|
@defaults[type_][:value] = value_
|
297
297
|
end
|
298
|
-
|
299
|
-
|
298
|
+
|
299
|
+
|
300
300
|
def _get_field # :nodoc:
|
301
301
|
@field
|
302
302
|
end
|
303
|
-
|
303
|
+
|
304
304
|
def _get_modules # :nodoc:
|
305
305
|
@modules
|
306
306
|
end
|
307
|
-
|
307
|
+
|
308
308
|
def _get_aliases # :nodoc:
|
309
309
|
@aliases
|
310
310
|
end
|
311
|
-
|
311
|
+
|
312
312
|
def _get_default_setting(type_, setting_) # :nodoc:
|
313
313
|
@defaults[type_][setting_]
|
314
314
|
end
|
315
|
-
|
315
|
+
|
316
316
|
end
|
317
|
-
|
318
|
-
|
317
|
+
|
318
|
+
|
319
319
|
end
|
320
|
-
|
320
|
+
|
321
321
|
end
|
data/lib/versionomy/value.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# -----------------------------------------------------------------------------
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Versionomy value
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
# Copyright 2008-2009 Daniel Azuma
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# All rights reserved.
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# Redistribution and use in source and binary forms, with or without
|
11
11
|
# modification, are permitted provided that the following conditions are met:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# * Redistributions of source code must retain the above copyright notice,
|
14
14
|
# this list of conditions and the following disclaimer.
|
15
15
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
@@ -18,7 +18,7 @@
|
|
18
18
|
# * Neither the name of the copyright holder, nor the names of any other
|
19
19
|
# contributors to this software, may be used to endorse or promote products
|
20
20
|
# derived from this software without specific prior written permission.
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
23
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
24
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
@@ -34,35 +34,39 @@
|
|
34
34
|
;
|
35
35
|
|
36
36
|
|
37
|
-
|
37
|
+
begin
|
38
|
+
require 'psych'
|
39
|
+
rescue ::LoadError
|
40
|
+
require 'yaml'
|
41
|
+
end
|
38
42
|
|
39
43
|
|
40
44
|
module Versionomy
|
41
|
-
|
42
|
-
|
45
|
+
|
46
|
+
|
43
47
|
# === Version number value
|
44
|
-
#
|
48
|
+
#
|
45
49
|
# A version number value is an ordered list of values, corresponding to an
|
46
50
|
# ordered list of fields defined by a schema. For example, if the schema
|
47
51
|
# is a simple one of the form "major.minor.tiny", then the the version
|
48
52
|
# number "1.4.2" would have the values <tt>[1, 4, 2]</tt> in that order,
|
49
53
|
# corresponding to the fields <tt>[:major, :minor, :tiny]</tt>.
|
50
|
-
#
|
54
|
+
#
|
51
55
|
# Version number values are comparable with other values that have an
|
52
56
|
# equivalent schema.
|
53
|
-
|
57
|
+
|
54
58
|
class Value
|
55
|
-
|
56
|
-
|
59
|
+
|
60
|
+
|
57
61
|
# Create a value, given a hash or array of values, and a format. Both
|
58
62
|
# these parameters are required.
|
59
|
-
#
|
63
|
+
#
|
60
64
|
# The values should either be a hash of field names and values, or an
|
61
65
|
# array of values that will be interpreted in field order.
|
62
|
-
#
|
66
|
+
#
|
63
67
|
# You can also optionally provide default unparsing parameters for the
|
64
68
|
# value.
|
65
|
-
|
69
|
+
|
66
70
|
def initialize(values_, format_, unparse_params_=nil)
|
67
71
|
unless values_.kind_of?(::Hash) || values_.kind_of?(::Array)
|
68
72
|
raise ::ArgumentError, "Expected hash or array but got #{values_.class}"
|
@@ -83,8 +87,8 @@ module Versionomy
|
|
83
87
|
modules_ = @_format.schema.modules
|
84
88
|
extend(*modules_) if modules_.size > 0
|
85
89
|
end
|
86
|
-
|
87
|
-
|
90
|
+
|
91
|
+
|
88
92
|
def inspect # :nodoc:
|
89
93
|
begin
|
90
94
|
str_ = unparse
|
@@ -93,17 +97,17 @@ module Versionomy
|
|
93
97
|
_inspect
|
94
98
|
end
|
95
99
|
end
|
96
|
-
|
100
|
+
|
97
101
|
def _inspect # :nodoc:
|
98
102
|
"#<#{self.class}:0x#{object_id.to_s(16)} " +
|
99
103
|
@_field_path.map{ |field_| "#{field_.name}=#{@_values[field_.name].inspect}" }.join(' ')
|
100
104
|
end
|
101
|
-
|
102
|
-
|
105
|
+
|
106
|
+
|
103
107
|
# Returns a string representation generated by unparsing.
|
104
108
|
# If unparsing fails, does not raise Versionomy::Errors::UnparseError,
|
105
109
|
# but instead returns the string generated by +inspect+.
|
106
|
-
|
110
|
+
|
107
111
|
def to_s
|
108
112
|
begin
|
109
113
|
unparse
|
@@ -111,149 +115,72 @@ module Versionomy
|
|
111
115
|
_inspect
|
112
116
|
end
|
113
117
|
end
|
114
|
-
|
115
|
-
|
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 tags. The last one is the canonical one.
|
154
|
-
yaml_as "tag:danielazuma.com,2009:version"
|
155
|
-
yaml_as "tag:verse15.com,2009:version"
|
156
|
-
|
157
|
-
|
158
|
-
# Deserialize a version number from YAML
|
159
|
-
|
160
|
-
def self.yaml_new(klass_, tag_, data_) # :nodoc:
|
161
|
-
unless data_.kind_of?(::Hash)
|
162
|
-
raise ::YAML::TypeError, "Invalid version format: #{val_.inspect}"
|
163
|
-
end
|
164
|
-
format_ = Format.get(data_['format'], true)
|
165
|
-
value_ = data_['value']
|
166
|
-
if value_
|
167
|
-
format_.parse(value_, data_['parse_params'])
|
168
|
-
else
|
169
|
-
Value.new(format_, data_['fields'], data_['unparse_params'])
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
|
174
|
-
# Serialize this version number to YAML format.
|
175
|
-
|
176
|
-
def to_yaml(opts_={})
|
177
|
-
data_ = marshal_dump
|
178
|
-
::YAML::quick_emit(nil, opts_) do |out_|
|
179
|
-
out_.map(taguri, to_yaml_style) do |map_|
|
180
|
-
map_.add('format', data_[0])
|
181
|
-
if data_[1].kind_of?(::String)
|
182
|
-
map_.add('value', data_[1])
|
183
|
-
map_.add('parse_params', data_[2]) if data_[2]
|
184
|
-
else
|
185
|
-
map_.add('fields', data_[1])
|
186
|
-
map_.add('unparse_params', data_[2]) if data_[2]
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
|
118
|
+
|
119
|
+
|
193
120
|
# Unparse this version number and return a string.
|
194
|
-
#
|
121
|
+
#
|
195
122
|
# Raises Versionomy::Errors::UnparseError if unparsing failed.
|
196
|
-
|
123
|
+
|
197
124
|
def unparse(params_=nil)
|
198
125
|
@_format.unparse(self, params_)
|
199
126
|
end
|
200
|
-
|
201
|
-
|
127
|
+
|
128
|
+
|
202
129
|
# Return the schema defining the structure and semantics of this
|
203
130
|
# version number.
|
204
|
-
|
131
|
+
|
205
132
|
def schema
|
206
133
|
@_format.schema
|
207
134
|
end
|
208
|
-
|
209
|
-
|
135
|
+
|
136
|
+
|
210
137
|
# Return the format defining the schema and formatting/parsing of
|
211
138
|
# this version number.
|
212
|
-
|
139
|
+
|
213
140
|
def format
|
214
141
|
@_format
|
215
142
|
end
|
216
|
-
|
217
|
-
|
143
|
+
|
144
|
+
|
218
145
|
# Return the unparsing parameters for this value.
|
219
146
|
# Returns nil if this value was not created using a parser.
|
220
|
-
|
147
|
+
|
221
148
|
def unparse_params
|
222
149
|
@_unparse_params ? @_unparse_params.dup : nil
|
223
150
|
end
|
224
|
-
|
225
|
-
|
151
|
+
|
152
|
+
|
226
153
|
# Iterates over each field, in field order, yielding the field name and value.
|
227
|
-
|
154
|
+
|
228
155
|
def each_field
|
229
156
|
@_field_path.each do |field_|
|
230
157
|
yield(field_, @_values[field_.name])
|
231
158
|
end
|
232
159
|
end
|
233
|
-
|
234
|
-
|
160
|
+
|
161
|
+
|
235
162
|
# Iterates over each field, in field order, yielding the
|
236
163
|
# Versionomy::Schema::Field object and value.
|
237
|
-
|
164
|
+
|
238
165
|
def each_field_object # :nodoc:
|
239
166
|
@_field_path.each do |field_|
|
240
167
|
yield(field_, @_values[field_.name])
|
241
168
|
end
|
242
169
|
end
|
243
|
-
|
244
|
-
|
170
|
+
|
171
|
+
|
245
172
|
# Returns an array of recognized field names for this value, in field order.
|
246
173
|
# This is the order of the fields actually present in this value, in
|
247
174
|
# order from most to least significant.
|
248
|
-
|
175
|
+
|
249
176
|
def field_names
|
250
177
|
@_field_path.map{ |field_| field_.name }
|
251
178
|
end
|
252
|
-
|
253
|
-
|
179
|
+
|
180
|
+
|
254
181
|
# Returns true if this value contains the given field, which may be specified
|
255
182
|
# as a field object, name, or index.
|
256
|
-
|
183
|
+
|
257
184
|
def has_field?(field_)
|
258
185
|
case field_
|
259
186
|
when Schema::Field
|
@@ -266,38 +193,38 @@ module Versionomy
|
|
266
193
|
raise ::ArgumentError
|
267
194
|
end
|
268
195
|
end
|
269
|
-
|
270
|
-
|
196
|
+
|
197
|
+
|
271
198
|
# Returns the value of the given field, or nil if the field is not
|
272
199
|
# recognized. The field may be specified as a field object, field name,
|
273
200
|
# or field index.
|
274
|
-
|
201
|
+
|
275
202
|
def [](field_)
|
276
203
|
@_values[_interpret_field(field_)]
|
277
204
|
end
|
278
|
-
|
279
|
-
|
205
|
+
|
206
|
+
|
280
207
|
# Returns the value as an array of field values, in field order.
|
281
208
|
# This is the order of the fields actually present in this value, in
|
282
209
|
# order from most to least significant.
|
283
|
-
|
210
|
+
|
284
211
|
def values_array
|
285
212
|
@_field_path.map{ |field_| @_values[field_.name] }
|
286
213
|
end
|
287
|
-
|
288
|
-
|
214
|
+
|
215
|
+
|
289
216
|
# Returns the value as a hash of values keyed by field name.
|
290
|
-
|
217
|
+
|
291
218
|
def values_hash
|
292
219
|
@_values.dup
|
293
220
|
end
|
294
|
-
|
295
|
-
|
221
|
+
|
222
|
+
|
296
223
|
# Returns a new version number created by bumping the given field. The
|
297
224
|
# field may be specified as a field object, field name, or field index.
|
298
225
|
# Returns self unchanged if the field was not recognized or could not
|
299
226
|
# be modified.
|
300
|
-
|
227
|
+
|
301
228
|
def bump(field_)
|
302
229
|
name_ = _interpret_field(field_)
|
303
230
|
return self unless name_ && @_values.include?(name_)
|
@@ -315,13 +242,13 @@ module Versionomy
|
|
315
242
|
end
|
316
243
|
self
|
317
244
|
end
|
318
|
-
|
319
|
-
|
245
|
+
|
246
|
+
|
320
247
|
# Returns a new version number created by resetting the given field. The
|
321
248
|
# field may be specified as a field object, field name, or field index.
|
322
249
|
# Returns self unchanged if the field was not recognized or could not
|
323
250
|
# be modified.
|
324
|
-
|
251
|
+
|
325
252
|
def reset(field_)
|
326
253
|
name_ = _interpret_field(field_)
|
327
254
|
return self unless name_ && @_values.include?(name_)
|
@@ -337,33 +264,33 @@ module Versionomy
|
|
337
264
|
end
|
338
265
|
self
|
339
266
|
end
|
340
|
-
|
341
|
-
|
267
|
+
|
268
|
+
|
342
269
|
# Returns a new version number created by cloning this version number
|
343
270
|
# and changing the given field values.
|
344
|
-
#
|
271
|
+
#
|
345
272
|
# You should pass in a hash of field names to values. These are the
|
346
273
|
# fields to modify; any other fields will be left alone, unless they
|
347
274
|
# are implicitly changed by the modifications you are making.
|
348
275
|
# For example, changing the :release_type on a value using the standard
|
349
276
|
# format, may change which fields are present in the resulting value.
|
350
|
-
#
|
277
|
+
#
|
351
278
|
# You may also pass a delta hash to modify the unparse params stored in
|
352
279
|
# the value.
|
353
|
-
|
280
|
+
|
354
281
|
def change(values_={}, unparse_params_={})
|
355
282
|
unparse_params_ = @_unparse_params.merge(unparse_params_) if @_unparse_params
|
356
283
|
values_ = _canonicalize_values_hash(values_)
|
357
284
|
Value.new(@_values.merge(values_), @_format, unparse_params_)
|
358
285
|
end
|
359
|
-
|
360
|
-
|
286
|
+
|
287
|
+
|
361
288
|
# Attempts to convert this value to the given format, and returns the
|
362
289
|
# resulting value.
|
363
|
-
#
|
290
|
+
#
|
364
291
|
# Raises Versionomy::Errors::ConversionError if the value could not
|
365
292
|
# be converted.
|
366
|
-
|
293
|
+
|
367
294
|
def convert(format_, convert_params_=nil)
|
368
295
|
if format_.kind_of?(::String) || format_.kind_of?(::Symbol)
|
369
296
|
format_ = Format.get(format_)
|
@@ -389,18 +316,18 @@ module Versionomy
|
|
389
316
|
end
|
390
317
|
end
|
391
318
|
end
|
392
|
-
|
393
|
-
|
319
|
+
|
320
|
+
|
394
321
|
def hash # :nodoc:
|
395
322
|
@_hash ||= @_values.hash
|
396
323
|
end
|
397
|
-
|
398
|
-
|
324
|
+
|
325
|
+
|
399
326
|
# Returns true if this version number is equivalent to the given number.
|
400
327
|
# This type of equality means their schemas are compatible and their
|
401
328
|
# field values are equal.
|
402
329
|
# Note that this is different from the definition of <tt>==</tt>.
|
403
|
-
|
330
|
+
|
404
331
|
def eql?(obj_)
|
405
332
|
if obj_.kind_of?(::String)
|
406
333
|
obj_ = @_format.parse(obj_) rescue nil
|
@@ -413,25 +340,25 @@ module Versionomy
|
|
413
340
|
end
|
414
341
|
true
|
415
342
|
end
|
416
|
-
|
417
|
-
|
343
|
+
|
344
|
+
|
418
345
|
# Returns true if this version number is value-equal to the given number.
|
419
346
|
# This type of equality means that they are equivalent, or that it is
|
420
347
|
# possible to convert the RHS to the LHS's format, and that they would
|
421
348
|
# be equivalent after such a conversion has taken place.
|
422
349
|
# Note that this is different from the definition of <tt>eql?</tt>.
|
423
|
-
|
350
|
+
|
424
351
|
def ==(obj_)
|
425
352
|
(self <=> obj_) == 0
|
426
353
|
end
|
427
|
-
|
428
|
-
|
354
|
+
|
355
|
+
|
429
356
|
# Compare this version number with the given version number,
|
430
357
|
# returning 0 if the two are value-equal, a negative number if the RHS
|
431
358
|
# is greater, or a positive number if the LHS is greater.
|
432
359
|
# The comparison may succeed even if the two have different schemas,
|
433
360
|
# if the RHS can be converted to the LHS's format.
|
434
|
-
|
361
|
+
|
435
362
|
def <=>(obj_)
|
436
363
|
if obj_.kind_of?(::String)
|
437
364
|
obj_ = @_format.parse(obj_)
|
@@ -450,12 +377,12 @@ module Versionomy
|
|
450
377
|
end
|
451
378
|
0
|
452
379
|
end
|
453
|
-
|
454
|
-
|
380
|
+
|
381
|
+
|
455
382
|
# Compare this version number with the given version number.
|
456
383
|
# The comparison may succeed even if the two have different schemas,
|
457
384
|
# if the RHS can be converted to the LHS's format.
|
458
|
-
|
385
|
+
|
459
386
|
def <(obj_)
|
460
387
|
val_ = (self <=> obj_)
|
461
388
|
unless val_
|
@@ -463,12 +390,12 @@ module Versionomy
|
|
463
390
|
end
|
464
391
|
val_ < 0
|
465
392
|
end
|
466
|
-
|
467
|
-
|
393
|
+
|
394
|
+
|
468
395
|
# Compare this version number with the given version number.
|
469
396
|
# The comparison may succeed even if the two have different schemas,
|
470
397
|
# if the RHS can be converted to the LHS's format.
|
471
|
-
|
398
|
+
|
472
399
|
def >(obj_)
|
473
400
|
val_ = (self <=> obj_)
|
474
401
|
unless val_
|
@@ -476,20 +403,137 @@ module Versionomy
|
|
476
403
|
end
|
477
404
|
val_ > 0
|
478
405
|
end
|
479
|
-
|
480
|
-
|
406
|
+
|
407
|
+
|
481
408
|
include ::Comparable
|
482
|
-
|
483
|
-
|
409
|
+
|
410
|
+
|
484
411
|
# Field values may be retrieved by calling them as methods.
|
485
|
-
|
412
|
+
|
486
413
|
def method_missing(symbol_)
|
487
414
|
self[symbol_] || super
|
488
415
|
end
|
489
|
-
|
490
|
-
|
416
|
+
|
417
|
+
|
418
|
+
# :stopdoc:
|
419
|
+
|
420
|
+
|
421
|
+
# Marshal support
|
422
|
+
|
423
|
+
# Marshal this version number
|
424
|
+
def marshal_dump
|
425
|
+
format_name_ = Format.canonical_name_for(@_format, true)
|
426
|
+
unparsed_data_ = nil
|
427
|
+
if @_format.respond_to?(:unparse_for_serialization)
|
428
|
+
unparsed_data_ = @_format.unparse_for_serialization(self) rescue nil
|
429
|
+
end
|
430
|
+
unparsed_data_ ||= @_format.unparse(self) rescue nil
|
431
|
+
data_ = [format_name_]
|
432
|
+
case unparsed_data_
|
433
|
+
when ::Array
|
434
|
+
data_ << unparsed_data_[0]
|
435
|
+
data_ << unparsed_data_[1] if unparsed_data_[1]
|
436
|
+
when ::String
|
437
|
+
data_ << unparsed_data_
|
438
|
+
else
|
439
|
+
data_ << values_array
|
440
|
+
data_ << @_unparse_params if @_unparse_params
|
441
|
+
end
|
442
|
+
data_
|
443
|
+
end
|
444
|
+
|
445
|
+
# Unmarshal this version number.
|
446
|
+
def marshal_load(data_)
|
447
|
+
format_ = Format.get(data_[0], true)
|
448
|
+
if data_[1].kind_of?(::String)
|
449
|
+
val_ = format_.parse(data_[1], data_[2])
|
450
|
+
initialize(val_.values_array, format_, val_.unparse_params)
|
451
|
+
else
|
452
|
+
initialize(data_[1], format_, data_[2])
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
|
457
|
+
if defined?(::Psych)
|
458
|
+
|
459
|
+
# YAML support through psych
|
460
|
+
|
461
|
+
# YAML tags. The last one is the canonical one.
|
462
|
+
yaml_tag "tag:danielazuma.com,2009:version"
|
463
|
+
yaml_tag "tag:verse15.com,2009:version"
|
464
|
+
|
465
|
+
# Deserialize a version number from YAML
|
466
|
+
def init_with(coder_) # :nodoc:
|
467
|
+
format_ = Format.get(coder_['format'], true)
|
468
|
+
value_ = coder_['value']
|
469
|
+
if value_
|
470
|
+
value_ = format_.parse(value_, coder_['parse_params'])
|
471
|
+
initialize(value_.values_array, format_, value_.unparse_params)
|
472
|
+
else
|
473
|
+
initialize(coder_['fields'], format_, coder_['unparse_params'])
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
# Serialize this version number to YAML format.
|
478
|
+
def encode_with(coder_) # :nodoc:
|
479
|
+
data_ = marshal_dump
|
480
|
+
coder_['format'] = data_[0]
|
481
|
+
if data_[1].kind_of?(::String)
|
482
|
+
coder_['value'] = data_[1]
|
483
|
+
coder_['parse_params'] = data_[2] if data_[2]
|
484
|
+
else
|
485
|
+
coder_['fields'] = data_[1]
|
486
|
+
coder_['unparse_params'] = data_[2] if data_[2]
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
else
|
491
|
+
|
492
|
+
# YAML support through syck
|
493
|
+
|
494
|
+
# YAML tags. The last one is the canonical one.
|
495
|
+
yaml_as "tag:danielazuma.com,2009:version"
|
496
|
+
yaml_as "tag:verse15.com,2009:version"
|
497
|
+
|
498
|
+
# Deserialize a version number from YAML
|
499
|
+
def self.yaml_new(klass_, tag_, data_) # :nodoc:
|
500
|
+
unless data_.kind_of?(::Hash)
|
501
|
+
raise ::YAML::TypeError, "Invalid version format: #{data_.inspect}"
|
502
|
+
end
|
503
|
+
format_ = Format.get(data_['format'], true)
|
504
|
+
value_ = data_['value']
|
505
|
+
if value_
|
506
|
+
format_.parse(value_, data_['parse_params'])
|
507
|
+
else
|
508
|
+
Value.new(data_['fields'], format_, data_['unparse_params'])
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
# Serialize this version number to YAML format.
|
513
|
+
def to_yaml(opts_={})
|
514
|
+
data_ = marshal_dump
|
515
|
+
::YAML.quick_emit(nil, opts_) do |out_|
|
516
|
+
out_.map(taguri, to_yaml_style) do |map_|
|
517
|
+
map_.add('format', data_[0])
|
518
|
+
if data_[1].kind_of?(::String)
|
519
|
+
map_.add('value', data_[1])
|
520
|
+
map_.add('parse_params', data_[2]) if data_[2]
|
521
|
+
else
|
522
|
+
map_.add('fields', data_[1])
|
523
|
+
map_.add('unparse_params', data_[2]) if data_[2]
|
524
|
+
end
|
525
|
+
end
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
end
|
530
|
+
|
531
|
+
|
532
|
+
# :startdoc:
|
533
|
+
|
534
|
+
|
491
535
|
private
|
492
|
-
|
536
|
+
|
493
537
|
def _interpret_field(field_) # :nodoc:
|
494
538
|
case field_
|
495
539
|
when Schema::Field
|
@@ -501,8 +545,8 @@ module Versionomy
|
|
501
545
|
@_format.schema.canonical_name(field_)
|
502
546
|
end
|
503
547
|
end
|
504
|
-
|
505
|
-
|
548
|
+
|
549
|
+
|
506
550
|
def _canonicalize_values_hash(values_) # :nodoc:
|
507
551
|
schema_ = @_format.schema
|
508
552
|
new_values_ = {}
|
@@ -512,9 +556,9 @@ module Versionomy
|
|
512
556
|
end
|
513
557
|
new_values_
|
514
558
|
end
|
515
|
-
|
516
|
-
|
559
|
+
|
560
|
+
|
517
561
|
end
|
518
|
-
|
519
|
-
|
562
|
+
|
563
|
+
|
520
564
|
end
|