versionomy 0.2.1 → 0.2.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 +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
|