versionomy 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +8 -2
- data/README.rdoc +14 -13
- data/lib/versionomy/conversion/rubygems.rb +7 -3
- data/lib/versionomy/format/delimiter.rb +139 -73
- data/lib/versionomy/format/standard.rb +53 -38
- data/lib/versionomy/interface.rb +15 -0
- data/lib/versionomy/version.rb +1 -1
- data/tests/tc_standard_parse.rb +66 -4
- metadata +2 -2
data/History.rdoc
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
+
=== 0.2.2 / 2009-11-18
|
2
|
+
|
3
|
+
* Standard format now supports certain kinds of prereleases without a prerelease number. e.g. "1.9.2dev" is interpreted as the same number as "1.9.2dev0".
|
4
|
+
* Added Versionomy#ruby_version.
|
5
|
+
* A field can specify a default_value for parsing, distinct from the one specified by the schema.
|
6
|
+
* A field can specify requires_next_field to control whether the following field is required or optional.
|
7
|
+
|
1
8
|
=== 0.2.1 / 2009-11-08
|
2
9
|
|
3
10
|
* Added Versionomy#version_of.
|
4
|
-
* Now lets Blockenspiel set its own VERSION instead of reaching into
|
5
|
-
Blockenspiel's namespace.
|
11
|
+
* Now lets Blockenspiel set its own VERSION instead of reaching into Blockenspiel's namespace.
|
6
12
|
|
7
13
|
=== 0.2.0 / 2009-11-05
|
8
14
|
|
data/README.rdoc
CHANGED
@@ -8,6 +8,7 @@ numbers in the wide variety of versioning schemes in use.
|
|
8
8
|
|
9
9
|
Let's be honest. Version numbers are not easy to deal with, and very
|
10
10
|
seldom seem to be done right.
|
11
|
+
|
11
12
|
Imagine the common case of testing the Ruby version. Most of us, if we
|
12
13
|
need to worry about Ruby VM compatibility, will do something like:
|
13
14
|
|
@@ -15,21 +16,23 @@ need to worry about Ruby VM compatibility, will do something like:
|
|
15
16
|
|
16
17
|
Treating the version number as a string works well enough, until it
|
17
18
|
doesn't. The above code will do the right thing for Ruby 1.8.6, 1.8.7,
|
18
|
-
1.8.8, and 1.9.1. But it will fail if the version is "1.8.10".
|
19
|
+
1.8.8, and 1.9.1. But it will fail if the version is "1.8.10" or "1.10".
|
20
|
+
And properly interpreting "prerelease" version syntax such as
|
21
|
+
"1.9.2-preview1"? Forget it.
|
19
22
|
|
20
23
|
There are a few version number classes out there that do better than
|
21
|
-
treating version numbers as plain strings. One
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
version number formats such as "1.9.2b1" and "1.9.2
|
24
|
+
treating version numbers as plain strings. One example is Gem::Version,
|
25
|
+
part of the RubyGems package. This class separates the version into fields
|
26
|
+
and lets you manipulate and compare version numbers more robustly. It even
|
27
|
+
provides limited support for "prerelease" versions through using string-
|
28
|
+
valued fields-- although it's a hack, and a bit of a clumsy one at that. A
|
29
|
+
prerelease version has to be represented like this: "1.9.2.b.1" or
|
30
|
+
"1.9.2.preview.2". Wouldn't it be nice to be able to parse more typical
|
31
|
+
version number formats such as "1.9.2b1" and "1.9.2-preview2"? Wouldn't
|
29
32
|
it be nice for a version like "1.9.2b1" to _understand_ that it's a "beta"
|
30
33
|
version and behave accordingly?
|
31
34
|
|
32
|
-
With Versionomy, you can
|
35
|
+
With Versionomy, you can do all this and more.
|
33
36
|
|
34
37
|
=== Some examples
|
35
38
|
|
@@ -53,7 +56,7 @@ With Versionomy, you can!
|
|
53
56
|
v2 > v1 # => true
|
54
57
|
v2.to_s # => '1.4a3'
|
55
58
|
|
56
|
-
#
|
59
|
+
# Version numbers are semantically self-adjusting.
|
57
60
|
v3 = Versionomy.parse('1.4.0b2')
|
58
61
|
v3.major # => 1
|
59
62
|
v3.minor # => 4
|
@@ -149,8 +152,6 @@ provides a schema and formatter/parser matching Gem::Version.
|
|
149
152
|
* Test coverage is still a little skimpy. It is focused on the "standard"
|
150
153
|
version number format and schema, but doesn't fully exercise all the
|
151
154
|
capabilities of custom formats.
|
152
|
-
* The standard format parser requires that "prerelease" versions have a
|
153
|
-
prerelease number. e.g. it accepts "1.9.2dev1" but not "1.9.2dev".
|
154
155
|
|
155
156
|
=== Development and support
|
156
157
|
|
@@ -50,7 +50,7 @@ module Versionomy
|
|
50
50
|
# and you should not need to call it again. It is documented, however,
|
51
51
|
# so that you can inspect its source code from RDoc, since the source
|
52
52
|
# contains useful examples of how to use the conversion DSLs.
|
53
|
-
|
53
|
+
|
54
54
|
def self.create_standard_to_rubygems
|
55
55
|
|
56
56
|
# We'll use a parsing conversion.
|
@@ -65,10 +65,14 @@ module Versionomy
|
|
65
65
|
|
66
66
|
# If the standard format version has a prerelease notation,
|
67
67
|
# make sure it is set off using a delimiter that the rubygems
|
68
|
-
# format can
|
68
|
+
# format can recognize. So instead of "1.0b2", we force the
|
69
69
|
# unparsing to generate "1.0.b.2".
|
70
70
|
params_[:release_type_delim] = '.'
|
71
|
-
params_[:
|
71
|
+
params_[:development_version_delim] = '.'
|
72
|
+
params_[:alpha_version_delim] = '.'
|
73
|
+
params_[:beta_version_delim] = '.'
|
74
|
+
params_[:release_candidate_version_delim] = '.'
|
75
|
+
params_[:preview_version_delim] = '.'
|
72
76
|
|
73
77
|
# If the standard format version has a patchlevel notation,
|
74
78
|
# force it to use the default number rather than letter style.
|
@@ -137,30 +137,69 @@ module Versionomy
|
|
137
137
|
# uninterpreted characters.
|
138
138
|
|
139
139
|
def parse(string_, params_=nil)
|
140
|
-
values_ = {}
|
141
140
|
parse_params_ = default_parse_params
|
142
141
|
parse_params_.merge!(params_) if params_
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
142
|
+
parse_state_ = {
|
143
|
+
:backtrack => nil,
|
144
|
+
:string => string_,
|
145
|
+
:values => {},
|
146
|
+
:unparse_params => {},
|
147
|
+
:field => @schema.root_field,
|
148
|
+
:recognizer_index => 0,
|
149
|
+
:previous_field_missing => false
|
150
|
+
}
|
151
|
+
while (field_ = parse_state_[:field])
|
148
152
|
handler_ = @field_handlers[field_.name]
|
149
|
-
|
150
|
-
|
151
|
-
|
153
|
+
recognizer_ = handler_.get_recognizer(parse_state_[:recognizer_index])
|
154
|
+
parse_data_ = nil
|
155
|
+
if recognizer_
|
156
|
+
parse_state_[:recognizer_index] += 1
|
157
|
+
parse_data_ = recognizer_.parse(parse_state_, parse_params_)
|
158
|
+
if parse_data_
|
159
|
+
parse_state_[:previous_field_missing] = false
|
160
|
+
if recognizer_.requires_next_field
|
161
|
+
parse_state_[:next_field_required] = true
|
162
|
+
parse_state_ = {
|
163
|
+
:backtrack => parse_state_,
|
164
|
+
:string => parse_state_[:string],
|
165
|
+
:values => parse_state_[:values].dup,
|
166
|
+
:unparse_params => parse_state_[:unparse_params].dup,
|
167
|
+
:field => parse_state_[:field],
|
168
|
+
:recognizer_index => 0,
|
169
|
+
:previous_field_missing => false,
|
170
|
+
}
|
171
|
+
else
|
172
|
+
parse_state_[:next_field_required] = false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
elsif parse_state_[:next_field_required]
|
176
|
+
parse_state_ = parse_state_[:backtrack]
|
177
|
+
else
|
178
|
+
parse_data_ = [handler_.default_value, nil, nil, nil]
|
179
|
+
parse_state_[:previous_field_missing] = true
|
180
|
+
parse_state_[:next_field_required] = false
|
181
|
+
end
|
182
|
+
if parse_data_
|
183
|
+
parse_state_[:values][field_.name] = parse_data_[0]
|
184
|
+
parse_state_[:string] = parse_data_[2] if parse_data_[2]
|
185
|
+
parse_state_[:unparse_params].merge!(parse_data_[3]) if parse_data_[3]
|
186
|
+
parse_state_[:field] = field_.child(parse_data_[0])
|
187
|
+
parse_state_[:recognizer_index] = 0
|
188
|
+
handler_.set_style_unparse_param(parse_data_[1], parse_state_[:unparse_params])
|
189
|
+
end
|
152
190
|
end
|
153
|
-
|
191
|
+
unparse_params_ = parse_state_[:unparse_params]
|
192
|
+
if parse_state_[:string].length > 0
|
154
193
|
case parse_params_[:extra_characters]
|
155
194
|
when :ignore
|
156
195
|
# do nothing
|
157
196
|
when :suffix
|
158
|
-
unparse_params_[:suffix] =
|
197
|
+
unparse_params_[:suffix] = parse_state_[:string]
|
159
198
|
else
|
160
|
-
raise Errors::ParseError, "Extra characters: #{
|
199
|
+
raise Errors::ParseError, "Extra characters: #{parse_state_[:string].inspect}"
|
161
200
|
end
|
162
201
|
end
|
163
|
-
Value.new(
|
202
|
+
Value.new(parse_state_[:values], self, unparse_params_)
|
164
203
|
end
|
165
204
|
|
166
205
|
|
@@ -210,32 +249,32 @@ module Versionomy
|
|
210
249
|
unparse_params_.merge!(params_)
|
211
250
|
_interpret_field_lists(unparse_params_)
|
212
251
|
end
|
213
|
-
|
214
|
-
|
252
|
+
skipped_handler_list_ = nil
|
253
|
+
requires_next_field_ = false
|
215
254
|
string_ = ''
|
216
255
|
value_.each_field_object do |field_, val_|
|
217
256
|
handler_ = @field_handlers[field_.name]
|
218
|
-
|
219
|
-
if
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
list_.each do |pair_|
|
224
|
-
frag_ = pair_[0].unparse(pair_[1], unparse_params_)
|
257
|
+
unparse_data_ = handler_.unparse(val_, unparse_params_, requires_next_field_)
|
258
|
+
if unparse_data_
|
259
|
+
if skipped_handler_list_ && handler_.requires_previous_field
|
260
|
+
skipped_handler_list_.each do |pair_|
|
261
|
+
frag_ = pair_[0].unparse(pair_[1], unparse_params_, true)
|
225
262
|
unless frag_
|
226
263
|
raise Errors::UnparseError, "Field #{field_.name} empty although a prerequisite for a later field"
|
227
264
|
end
|
228
|
-
string_ << frag_
|
265
|
+
string_ << frag_[0]
|
229
266
|
end
|
230
|
-
unparse_params_[:required_for_later] = false
|
231
267
|
end
|
232
|
-
|
268
|
+
skipped_handler_list_ = nil
|
269
|
+
string_ << unparse_data_[0]
|
270
|
+
requires_next_field_ = unparse_data_[1]
|
233
271
|
else
|
234
272
|
if handler_.requires_previous_field
|
235
|
-
(
|
273
|
+
(skipped_handler_list_ ||= []) << [handler_, val_]
|
236
274
|
else
|
237
|
-
|
275
|
+
skipped_handler_list_ = [[handler_, val_]]
|
238
276
|
end
|
277
|
+
requires_next_field_ = false
|
239
278
|
end
|
240
279
|
end
|
241
280
|
string_ << (unparse_params_[:suffix] || '')
|
@@ -280,14 +319,14 @@ module Versionomy
|
|
280
319
|
def _interpret_field_lists(unparse_params_) # :nodoc:
|
281
320
|
fields_ = unparse_params_.delete(:required_fields)
|
282
321
|
if fields_
|
283
|
-
fields_ = [fields_] unless fields_.kind_of?(Array)
|
322
|
+
fields_ = [fields_] unless fields_.kind_of?(::Array)
|
284
323
|
fields_.each do |f_|
|
285
324
|
unparse_params_["#{f_}_required".to_sym] = true
|
286
325
|
end
|
287
326
|
end
|
288
327
|
fields_ = unparse_params_.delete(:optional_fields)
|
289
328
|
if fields_
|
290
|
-
fields_ = [fields_] unless fields_.kind_of?(Array)
|
329
|
+
fields_ = [fields_] unless fields_.kind_of?(::Array)
|
291
330
|
fields_.each do |f_|
|
292
331
|
unparse_params_["#{f_}_required".to_sym] = false
|
293
332
|
end
|
@@ -353,6 +392,10 @@ module Versionomy
|
|
353
392
|
# field is optional, but the first and second are required, so it
|
354
393
|
# will often be unparsed as "2.0".
|
355
394
|
# Default is false.
|
395
|
+
# <tt>:default_value</tt>::
|
396
|
+
# The actual value set for this field if it is omitted from the
|
397
|
+
# version string. Defaults to the field's schema default value,
|
398
|
+
# but that can be overridden here.
|
356
399
|
# <tt>:case_sensitive</tt>::
|
357
400
|
# If set to true, the regexps are case-sensitive. Default is false.
|
358
401
|
# <tt>:delimiter_regexp</tt>::
|
@@ -391,6 +434,15 @@ module Versionomy
|
|
391
434
|
# parameter set to true. The default is true, so you must specify
|
392
435
|
# <tt>:requires_previous_field => false</tt> explicitly if you want
|
393
436
|
# a field not to require the previous field.
|
437
|
+
# <tt>:requires_next_field</tt>::
|
438
|
+
# If set to true, this field's presence in a formatted version
|
439
|
+
# string requires the presence of the next field. For example, in
|
440
|
+
# the version "1.0a5", the release_type field requires the presence
|
441
|
+
# of the alpha_version field, because if the "5" was missing, the
|
442
|
+
# string "1.0a" looks like a patchlevel indicator. Often it is
|
443
|
+
# easier to set default_value_optional in the next field, but this
|
444
|
+
# option is also available if the behavior is dependent on the
|
445
|
+
# value of this previous field.
|
394
446
|
# <tt>:default_style</tt>::
|
395
447
|
# The default style for this field. This is the style used for
|
396
448
|
# unparsing if the value was not constructed by a parser or is
|
@@ -607,6 +659,7 @@ module Versionomy
|
|
607
659
|
@field = field_
|
608
660
|
@recognizers = []
|
609
661
|
@requires_previous_field = default_opts_.fetch(:requires_previous_field, true)
|
662
|
+
@default_value = default_opts_[:default_value] || field_.default_value
|
610
663
|
@default_style = default_opts_.fetch(:default_style, nil)
|
611
664
|
@style_unparse_param_key = "#{field_.name}_style".to_sym
|
612
665
|
if block_
|
@@ -631,37 +684,44 @@ module Versionomy
|
|
631
684
|
end
|
632
685
|
|
633
686
|
|
634
|
-
#
|
635
|
-
#
|
636
|
-
# It should also set the style in the unparse_params, if the style
|
637
|
-
# is determined not to be the default.
|
687
|
+
# Returns the default value set when this field is missing from a
|
688
|
+
# version string.
|
638
689
|
|
639
|
-
def
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
690
|
+
def default_value
|
691
|
+
@default_value
|
692
|
+
end
|
693
|
+
|
694
|
+
|
695
|
+
# Gets the given indexed recognizer. Returns nil if the index is out
|
696
|
+
# of range.
|
697
|
+
|
698
|
+
def get_recognizer(index_)
|
699
|
+
@recognizers[index_]
|
700
|
+
end
|
701
|
+
|
702
|
+
|
703
|
+
# Finishes up parsing by setting the appropriate style field in the
|
704
|
+
# unparse_params, if needed.
|
705
|
+
|
706
|
+
def set_style_unparse_param(style_, unparse_params_)
|
707
|
+
if style_ && style_ != @default_style
|
708
|
+
unparse_params_[@style_unparse_param_key] = style_
|
649
709
|
end
|
650
|
-
pair_[0]
|
651
710
|
end
|
652
711
|
|
653
712
|
|
654
713
|
# Unparse a string from this field value.
|
655
714
|
# This may return nil if this field is not required.
|
656
715
|
|
657
|
-
def unparse(value_, unparse_params_)
|
716
|
+
def unparse(value_, unparse_params_, required_for_later_)
|
658
717
|
style_ = unparse_params_[@style_unparse_param_key] || @default_style
|
659
718
|
@recognizers.each do |recog_|
|
660
719
|
if recog_.should_unparse?(value_, style_)
|
661
|
-
|
720
|
+
fragment_ = recog_.unparse(value_, style_, unparse_params_, required_for_later_)
|
721
|
+
return fragment_ ? [fragment_, recog_.requires_next_field] : nil
|
662
722
|
end
|
663
723
|
end
|
664
|
-
|
724
|
+
required_for_later_ ? ['', false] : nil
|
665
725
|
end
|
666
726
|
|
667
727
|
end
|
@@ -690,6 +750,7 @@ module Versionomy
|
|
690
750
|
def setup(field_, value_regexp_, opts_)
|
691
751
|
@style = opts_[:style]
|
692
752
|
@default_value_optional = opts_[:default_value_optional]
|
753
|
+
@default_value = opts_[:default_value] || field_.default_value
|
693
754
|
@regexp_options = opts_[:case_sensitive] ? nil : ::Regexp::IGNORECASE
|
694
755
|
@value_regexp = ::Regexp.new("\\A(#{value_regexp_})", @regexp_options)
|
695
756
|
regexp_ = opts_[:delimiter_regexp] || '\.'
|
@@ -703,8 +764,8 @@ module Versionomy
|
|
703
764
|
@default_delimiter = opts_[:default_delimiter] || '.'
|
704
765
|
@default_post_delimiter = opts_[:default_post_delimiter] || ''
|
705
766
|
@requires_previous_field = opts_.fetch(:requires_previous_field, true)
|
767
|
+
@requires_next_field = opts_.fetch(:requires_next_field, false)
|
706
768
|
name_ = field_.name
|
707
|
-
@default_field_value = field_.default_value
|
708
769
|
@delim_unparse_param_key = "#{name_}_delim".to_sym
|
709
770
|
@post_delim_unparse_param_key = "#{name_}_postdelim".to_sym
|
710
771
|
@required_unparse_param_key = "#{name_}_required".to_sym
|
@@ -716,9 +777,9 @@ module Versionomy
|
|
716
777
|
# Returns either nil, indicating that this recognizer doesn't match
|
717
778
|
# the given syntax, or a two element array of the value and style.
|
718
779
|
|
719
|
-
def parse(
|
720
|
-
return nil if @requires_previous_field &&
|
721
|
-
string_ =
|
780
|
+
def parse(parse_state_, parse_params_)
|
781
|
+
return nil if @requires_previous_field && parse_state_[:previous_field_missing]
|
782
|
+
string_ = parse_state_[:string]
|
722
783
|
if @delimiter_regexp
|
723
784
|
match_ = @delimiter_regexp.match(string_)
|
724
785
|
return nil unless match_
|
@@ -743,9 +804,9 @@ module Versionomy
|
|
743
804
|
match_ = @follower_regexp.match(string_)
|
744
805
|
return nil unless match_
|
745
806
|
end
|
746
|
-
|
747
|
-
return nil unless
|
748
|
-
|
807
|
+
parse_result_ = parsed_value(value_, parse_params_)
|
808
|
+
return nil unless parse_result_
|
809
|
+
unparse_params_ = parse_result_[1] || {}
|
749
810
|
if delim_ != @default_delimiter
|
750
811
|
unparse_params_[@delim_unparse_param_key] = delim_
|
751
812
|
end
|
@@ -753,7 +814,15 @@ module Versionomy
|
|
753
814
|
unparse_params_[@post_delim_unparse_param_key] = post_delim_
|
754
815
|
end
|
755
816
|
unparse_params_[@required_unparse_param_key] = true if @default_value_optional
|
756
|
-
[
|
817
|
+
[parse_result_[0], @style, string_, unparse_params_]
|
818
|
+
end
|
819
|
+
|
820
|
+
|
821
|
+
# Returns true if this field can appear in an unparsed string only
|
822
|
+
# if the next field also appears.
|
823
|
+
|
824
|
+
def requires_next_field
|
825
|
+
@requires_next_field
|
757
826
|
end
|
758
827
|
|
759
828
|
|
@@ -773,11 +842,10 @@ module Versionomy
|
|
773
842
|
# It is guaranteed that this will be called only if should_unparse?
|
774
843
|
# returns true.
|
775
844
|
|
776
|
-
def unparse(value_, style_, unparse_params_)
|
845
|
+
def unparse(value_, style_, unparse_params_, required_for_later_)
|
777
846
|
str_ = nil
|
778
|
-
if !@default_value_optional || value_ != @
|
779
|
-
unparse_params_[
|
780
|
-
unparse_params_[@required_unparse_param_key]
|
847
|
+
if !@default_value_optional || value_ != @default_value ||
|
848
|
+
required_for_later_ || unparse_params_[@required_unparse_param_key]
|
781
849
|
then
|
782
850
|
str_ = unparsed_value(value_, style_, unparse_params_)
|
783
851
|
if str_
|
@@ -816,8 +884,8 @@ module Versionomy
|
|
816
884
|
setup(field_, '\d+', opts_)
|
817
885
|
end
|
818
886
|
|
819
|
-
def parsed_value(value_, parse_params_
|
820
|
-
value_.to_i
|
887
|
+
def parsed_value(value_, parse_params_)
|
888
|
+
[value_.to_i, nil]
|
821
889
|
end
|
822
890
|
|
823
891
|
def unparsed_value(value_, style_, unparse_params_)
|
@@ -846,16 +914,14 @@ module Versionomy
|
|
846
914
|
setup(field_, value_regexp_, opts_)
|
847
915
|
end
|
848
916
|
|
849
|
-
def parsed_value(value_, parse_params_
|
917
|
+
def parsed_value(value_, parse_params_)
|
850
918
|
value_ = value_.unpack('c')[0] # Compatible with both 1.8 and 1.9
|
851
919
|
if value_ >= 97 && value_ <= 122
|
852
|
-
|
853
|
-
value_ - 96
|
920
|
+
[value_ - 96, {@case_unparse_param_key => :lower}]
|
854
921
|
elsif value_ >= 65 && value_ <= 90
|
855
|
-
|
856
|
-
value_ - 64
|
922
|
+
[value_ - 64, {@case_unparse_param_key => :upper}]
|
857
923
|
else
|
858
|
-
0
|
924
|
+
[0, nil]
|
859
925
|
end
|
860
926
|
end
|
861
927
|
|
@@ -883,8 +949,8 @@ module Versionomy
|
|
883
949
|
setup(field_, regexp_, opts_)
|
884
950
|
end
|
885
951
|
|
886
|
-
def parsed_value(value_, parse_params_
|
887
|
-
value_
|
952
|
+
def parsed_value(value_, parse_params_)
|
953
|
+
[value_, nil]
|
888
954
|
end
|
889
955
|
|
890
956
|
def unparsed_value(value_, style_, unparse_params_)
|
@@ -905,8 +971,8 @@ module Versionomy
|
|
905
971
|
@canonical = canonical_
|
906
972
|
end
|
907
973
|
|
908
|
-
def parsed_value(value_,
|
909
|
-
@value
|
974
|
+
def parsed_value(value_, parse_params_)
|
975
|
+
[@value, nil]
|
910
976
|
end
|
911
977
|
|
912
978
|
def unparsed_value(value_, style_, unparse_params_)
|
@@ -937,9 +1003,9 @@ module Versionomy
|
|
937
1003
|
end
|
938
1004
|
end
|
939
1005
|
|
940
|
-
def parsed_value(value_,
|
1006
|
+
def parsed_value(value_, parse_params_)
|
941
1007
|
@mappings_in_order.each do |map_|
|
942
|
-
return map_[2] if map_[0].match(value_)
|
1008
|
+
return [map_[2], nil] if map_[0].match(value_)
|
943
1009
|
end
|
944
1010
|
nil
|
945
1011
|
end
|
@@ -277,73 +277,87 @@ module Versionomy
|
|
277
277
|
# syntax looks like "1.0a5". Long syntax looks more like
|
278
278
|
# "1.0 Alpha 5". The parsed value retains knowledge of which style
|
279
279
|
# it came from so it can be reconstructed when the value is unparsed.
|
280
|
-
#
|
280
|
+
# Note that we turn requires_previous_field off because the release
|
281
281
|
# type syntax markers don't require any particular set of the core
|
282
282
|
# version number fields to be present. "1.0a5" and "1.0.0.0a5" are
|
283
283
|
# both valid version numbers.
|
284
284
|
field(:release_type, :requires_previous_field => false,
|
285
285
|
:default_style => :short) do
|
286
|
-
#
|
287
|
-
#
|
288
|
-
#
|
289
|
-
#
|
286
|
+
# Some markers require a prerelease version (e.g. the 5 in
|
287
|
+
# "1.0a5") while others don't (e.g. "1.9.2dev"). This is because
|
288
|
+
# the syntax "1.0a" looks like a patchlevel syntax. So some of
|
289
|
+
# the following recognizers set requires_next_field while others
|
290
|
+
# do not.
|
291
|
+
# Also note that we omit the value <tt>:final</tt>. This is
|
292
|
+
# because that value is signaled by the absence of any syntax in
|
293
|
+
# the version string, including the absence of any delimiters.
|
294
|
+
# So we just allow it to fall through to the default.
|
295
|
+
|
296
|
+
recognize_regexp_map(:style => :long, :default_delimiter => '',
|
297
|
+
:delimiter_regexp => '-|\.|\s?') do
|
298
|
+
map(:development, 'dev')
|
299
|
+
map(:alpha, 'alpha')
|
300
|
+
map(:beta, 'beta')
|
301
|
+
map(:preview, 'preview')
|
302
|
+
end
|
290
303
|
recognize_regexp_map(:style => :short, :default_delimiter => '',
|
291
|
-
:delimiter_regexp => '-|\.|\s?'
|
292
|
-
:post_delimiter_regexp => '-|\.|\s?',
|
293
|
-
:expected_follower_regexp => '\d') do
|
294
|
-
map(:development, 'd')
|
295
|
-
map(:alpha, 'a')
|
296
|
-
map(:beta, 'b')
|
304
|
+
:delimiter_regexp => '-|\.|\s?') do
|
297
305
|
map(:release_candidate, 'rc')
|
298
306
|
map(:preview, 'pre')
|
299
|
-
# Note that we omit the value <tt>:final</tt>. This is because
|
300
|
-
# that value is signaled by the absence of any syntax in the
|
301
|
-
# version string, including the absence of any delimiters. So we
|
302
|
-
# just allow it to fall through to the default.
|
303
307
|
end
|
304
|
-
# Check for "long form" syntax. Note again that we omit :final.
|
305
308
|
recognize_regexp_map(:style => :long, :default_delimiter => '',
|
306
|
-
:delimiter_regexp => '-|\.|\s?'
|
307
|
-
:post_delimiter_regexp => '-|\.|\s?',
|
308
|
-
:expected_follower_regexp => '\d') do
|
309
|
-
map(:development, 'dev')
|
310
|
-
map(:alpha, 'alpha')
|
311
|
-
map(:beta, 'beta')
|
309
|
+
:delimiter_regexp => '-|\.|\s?') do
|
312
310
|
map(:release_candidate, 'rc')
|
313
|
-
|
311
|
+
end
|
312
|
+
recognize_regexp_map(:style => :short, :default_delimiter => '',
|
313
|
+
:delimiter_regexp => '-|\.|\s?',
|
314
|
+
:requires_next_field => true) do
|
315
|
+
map(:development, 'd')
|
316
|
+
map(:alpha, 'a')
|
317
|
+
map(:beta, 'b')
|
314
318
|
end
|
315
319
|
end
|
316
320
|
|
317
|
-
# The
|
318
|
-
#
|
319
|
-
#
|
320
|
-
#
|
321
|
-
|
322
|
-
|
321
|
+
# The main prerelease version may sometimes be optional, so we
|
322
|
+
# mark it as optional here. If it is required, that will be
|
323
|
+
# signalled by requires_next_field on the release_type field.
|
324
|
+
# Minor prerelease versions are always optional.
|
325
|
+
# Note that we override the default_value (normally 1) and set
|
326
|
+
# it to 0 if a main prerelease version is not present. This is
|
327
|
+
# so schema-oriented operations like bumping will set the value
|
328
|
+
# to 1, while parsing a string will yield 0 when the field is
|
329
|
+
# missing (e.g. we want "1.9.2dev" to mean "1.9.2dev0".)
|
330
|
+
field(:development_version, :default_value => 0) do
|
331
|
+
recognize_number(:delimiter_regexp => '-|\.|\s?', :default_delimiter => '',
|
332
|
+
:default_value_optional => true)
|
323
333
|
end
|
324
334
|
field(:development_minor) do
|
325
335
|
recognize_number(:default_value_optional => true)
|
326
336
|
end
|
327
|
-
field(:alpha_version) do
|
328
|
-
recognize_number(:delimiter_regexp => '', :default_delimiter => ''
|
337
|
+
field(:alpha_version, :default_value => 0) do
|
338
|
+
recognize_number(:delimiter_regexp => '-|\.|\s?', :default_delimiter => '',
|
339
|
+
:default_value_optional => true)
|
329
340
|
end
|
330
341
|
field(:alpha_minor) do
|
331
342
|
recognize_number(:default_value_optional => true)
|
332
343
|
end
|
333
|
-
field(:beta_version) do
|
334
|
-
recognize_number(:delimiter_regexp => '', :default_delimiter => ''
|
344
|
+
field(:beta_version, :default_value => 0) do
|
345
|
+
recognize_number(:delimiter_regexp => '-|\.|\s?', :default_delimiter => '',
|
346
|
+
:default_value_optional => true)
|
335
347
|
end
|
336
348
|
field(:beta_minor) do
|
337
349
|
recognize_number(:default_value_optional => true)
|
338
350
|
end
|
339
|
-
field(:release_candidate_version) do
|
340
|
-
recognize_number(:delimiter_regexp => '', :default_delimiter => ''
|
351
|
+
field(:release_candidate_version, :default_value => 0) do
|
352
|
+
recognize_number(:delimiter_regexp => '-|\.|\s?', :default_delimiter => '',
|
353
|
+
:default_value_optional => true)
|
341
354
|
end
|
342
355
|
field(:release_candidate_minor) do
|
343
356
|
recognize_number(:default_value_optional => true)
|
344
357
|
end
|
345
|
-
field(:preview_version) do
|
346
|
-
recognize_number(:delimiter_regexp => '', :default_delimiter => ''
|
358
|
+
field(:preview_version, :default_value => 0) do
|
359
|
+
recognize_number(:delimiter_regexp => '-|\.|\s?', :default_delimiter => '',
|
360
|
+
:default_value_optional => true)
|
347
361
|
end
|
348
362
|
field(:preview_minor) do
|
349
363
|
recognize_number(:default_value_optional => true)
|
@@ -366,7 +380,8 @@ module Versionomy
|
|
366
380
|
|
367
381
|
# By default, we require that at least the major and minor fields
|
368
382
|
# appear in an unparsed version string.
|
369
|
-
default_unparse_params(:required_fields => [:minor
|
383
|
+
default_unparse_params(:required_fields => [:minor, :development_version, :alpha_version,
|
384
|
+
:beta_version, :release_candidate_version, :preview_version])
|
370
385
|
end
|
371
386
|
end
|
372
387
|
|
data/lib/versionomy/interface.rb
CHANGED
@@ -154,6 +154,21 @@ module Versionomy
|
|
154
154
|
end
|
155
155
|
|
156
156
|
|
157
|
+
# Get the ruby version as a Versionomy::Value, using the builtin
|
158
|
+
# constants RUBY_VERSION and RUBY_PATCHLEVEL.
|
159
|
+
|
160
|
+
def ruby_version
|
161
|
+
unless @ruby_version
|
162
|
+
@ruby_version = parse(::RUBY_VERSION, :standard)
|
163
|
+
if @ruby_version.release_type == :final
|
164
|
+
@ruby_version = @ruby_version.change({:patchlevel => ::RUBY_PATCHLEVEL},
|
165
|
+
:patchlevel_required => true, :patchlevel_delim => '-p')
|
166
|
+
end
|
167
|
+
end
|
168
|
+
@ruby_version
|
169
|
+
end
|
170
|
+
|
171
|
+
|
157
172
|
end
|
158
173
|
|
159
174
|
end
|
data/lib/versionomy/version.rb
CHANGED
data/tests/tc_standard_parse.rb
CHANGED
@@ -93,6 +93,21 @@ module Versionomy
|
|
93
93
|
end
|
94
94
|
|
95
95
|
|
96
|
+
# Test parsing major version only.
|
97
|
+
|
98
|
+
def test_parsing_major_only
|
99
|
+
value_ = ::Versionomy.parse('2')
|
100
|
+
assert_equal(2, value_.major)
|
101
|
+
assert_equal(0, value_.minor)
|
102
|
+
assert_equal(0, value_.tiny)
|
103
|
+
assert_equal(0, value_.tiny2)
|
104
|
+
assert_equal(:final, value_.release_type)
|
105
|
+
assert_equal(0, value_.patchlevel)
|
106
|
+
assert_equal(0, value_.patchlevel_minor)
|
107
|
+
assert_equal('2', value_.unparse)
|
108
|
+
end
|
109
|
+
|
110
|
+
|
96
111
|
# Test parsing preview.
|
97
112
|
|
98
113
|
def test_parsing_preview
|
@@ -151,6 +166,7 @@ module Versionomy
|
|
151
166
|
assert_equal(::Versionomy.parse('2.52.1BETA4'), '2.52.1b4')
|
152
167
|
assert_equal(::Versionomy.parse('2.52.1 Beta4'), '2.52.1b4')
|
153
168
|
assert_equal(::Versionomy.parse('2.52.1 eta4', :extra_characters => :ignore), '2.52.1')
|
169
|
+
assert_equal(::Versionomy.parse('2.52.1 Beta'), '2.52.1b0')
|
154
170
|
end
|
155
171
|
|
156
172
|
|
@@ -167,7 +183,53 @@ module Versionomy
|
|
167
183
|
assert_equal(0, value_.release_candidate_minor)
|
168
184
|
assert_equal('0.2rc0', value_.unparse)
|
169
185
|
assert_equal('0.2rc0.0', value_.unparse(:required_fields => [:release_candidate_minor]))
|
170
|
-
assert_equal('0.
|
186
|
+
assert_equal('0.2rc', value_.unparse(:optional_fields => [:release_candidate_version]))
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
# Test parsing release candidate changing to other prerelease.
|
191
|
+
# Ensures that :short style takes precedence over :long for parsing "rc".
|
192
|
+
|
193
|
+
def test_parsing_release_candidate_type_change
|
194
|
+
value_ = ::Versionomy.parse('0.2rc1')
|
195
|
+
assert_equal(:release_candidate, value_.release_type)
|
196
|
+
assert_equal(1, value_.release_candidate_version)
|
197
|
+
assert_equal('0.2rc1', value_.unparse)
|
198
|
+
value_ = value_.change(:release_type => :beta)
|
199
|
+
assert_equal(:beta, value_.release_type)
|
200
|
+
assert_equal(1, value_.beta_version)
|
201
|
+
assert_equal('0.2b1', value_.unparse)
|
202
|
+
value_ = value_.change({:release_type => :beta}, :release_type_style => :long)
|
203
|
+
assert_equal(:beta, value_.release_type)
|
204
|
+
assert_equal(1, value_.beta_version)
|
205
|
+
assert_equal('0.2beta1', value_.unparse)
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
# Test parsing forms without a prerelease version
|
210
|
+
|
211
|
+
def test_parsing_without_prerelease_version
|
212
|
+
value_ = ::Versionomy.parse('1.9.2dev')
|
213
|
+
assert_equal(value_.release_type, :development)
|
214
|
+
assert_equal(value_.development_version, 0)
|
215
|
+
assert_equal('1.9.2dev', value_.to_s)
|
216
|
+
value_ = value_.bump(:development_version)
|
217
|
+
assert_equal('1.9.2dev1', value_.to_s)
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
# Test parsing forms without a prerelease version.
|
222
|
+
# Ensures that :development_version prefers to be required.
|
223
|
+
|
224
|
+
def test_unparsing_prerelease_version_0
|
225
|
+
value_ = ::Versionomy.parse('1.9.2dev1')
|
226
|
+
assert_equal(value_.release_type, :development)
|
227
|
+
assert_equal(value_.development_version, 1)
|
228
|
+
assert_equal('1.9.2dev1', value_.to_s)
|
229
|
+
value2_ = value_.change(:development_version => 0)
|
230
|
+
assert_equal('1.9.2dev0', value2_.to_s)
|
231
|
+
value2_ = value_.change({:development_version => 0}, :optional_fields => [:development_version])
|
232
|
+
assert_equal('1.9.2dev', value2_.to_s)
|
171
233
|
end
|
172
234
|
|
173
235
|
|
@@ -212,10 +274,10 @@ module Versionomy
|
|
212
274
|
|
213
275
|
def test_unparse_with_custom_delimiters
|
214
276
|
value_ = ::Versionomy.parse('1.2b3')
|
215
|
-
assert_equal('1.2.b.3', value_.unparse(:release_type_delim => '.', :
|
216
|
-
assert_equal('1.2b3', value_.unparse(:release_type_delim => '=', :
|
277
|
+
assert_equal('1.2.b.3', value_.unparse(:release_type_delim => '.', :beta_version_delim => '.'))
|
278
|
+
assert_equal('1.2b3', value_.unparse(:release_type_delim => '=', :beta_version_delim => '*'))
|
217
279
|
value_ = ::Versionomy.parse('1.2-4')
|
218
|
-
assert_equal('1.2-4', value_.unparse(:release_type_delim => '.'
|
280
|
+
assert_equal('1.2-4', value_.unparse(:release_type_delim => '.'))
|
219
281
|
end
|
220
282
|
|
221
283
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: versionomy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-18 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|