versionomy 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,6 +1,20 @@
1
+ === 0.2.0 / 2009-11-05
2
+
3
+ * API CHANGE: Slight change to value comparison semantics. Value#eql? returns true only if the schemas are the same, whereas Value#== and the greater than and less than comparisons attempt to compare the semantic value, and thus may perform automatic schema conversion on the RHS.
4
+ * API CHANGE: Merged Formats namespace into Format. Versionomy::Formats is now a (deprecated) alias for Versionomy::Format.
5
+ * API CHANGE: The delimiter parsing algorithm now defaults :extra_characters to :error instead of :ignore.
6
+ * Added a mechanism for converting from one format/schema to another.
7
+ * Added Rubygems format, along with conversions to and from the standard format.
8
+ * Values now include Comparable.
9
+ * Values can now be serialized using Marshal and YAML.
10
+ * Schemas can now add custom methods to value objects. Added "prerelease?" and "release" methods to rubygems and standard format values.
11
+ * Added default field settings to schema DSL.
12
+ * Implemented #=== for schemas and formats.
13
+ * Many minor bug fixes and documentation updates.
14
+
1
15
  === 0.1.3 / 2009-10-29
2
16
 
3
- * Fixed an issue with parsing the "-p" patchlevel delimiter (e.g. "1.9.1-p243").
17
+ * Fixed an issue with parsing the "-p" patchlevel delimiter, e.g. "1.9.1-p243". (Reported by Luis Lavena.)
4
18
 
5
19
  === 0.1.2 / 2009-10-28
6
20
 
data/README.rdoc CHANGED
@@ -4,15 +4,46 @@ Versionomy is a generalized version number library.
4
4
  It provides tools to represent, manipulate, parse, and compare version
5
5
  numbers in the wide variety of versioning schemes in use.
6
6
 
7
+ === Version numbers done right?
8
+
9
+ Let's be honest. Version numbers are not easy to deal with, and very
10
+ seldom seem to be done right.
11
+ Imagine the common case of testing the Ruby version. Most of us, if we
12
+ need to worry about Ruby VM compatibility, will do something like:
13
+
14
+ do_something if RUBY_VERSION >= "1.8.7"
15
+
16
+ Treating the version number as a string works well enough, until it
17
+ 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
+
20
+ There are a few version number classes out there that do better than
21
+ treating version numbers as plain strings. One well-known class is
22
+ Gem::Version, part of rubygems. This class separates the version into
23
+ fields and lets you manipulate and compare version numbers more robustly.
24
+ It provides limited support for "prerelease" versions through using
25
+ string-valued fields as a bit of a hack. However, it's still a little
26
+ clumsy. A prerelease version has to be represented like this: "1.9.2.b.1"
27
+ or "1.9.2.preview.2". Wouldn't it be nice to be able to parse more typical
28
+ version number formats such as "1.9.2b1" and "1.9.2 preview-2"? Wouldn't
29
+ it be nice for a version like "1.9.2b1" to _understand_ that it's a "beta"
30
+ version and behave accordingly?
31
+
32
+ With Versionomy, you can!
33
+
7
34
  === Some examples
8
35
 
9
36
  require 'versionomy'
10
37
 
11
- v1 = Versionomy.parse('1.3.2')
38
+ # Create version numbers that understand their own semantics
39
+ v1 = Versionomy.create(:major => 1, :minor => 3, :tiny => 2)
12
40
  v1.major # => 1
13
41
  v1.minor # => 3
14
42
  v1.tiny # => 2
43
+ v1.release_type # => :final
44
+ v1.patchlevel # => 0
15
45
 
46
+ # Parse version numbers, including common prerelease syntax
16
47
  v2 = Versionomy.parse('1.4a3')
17
48
  v2.major # => 1
18
49
  v2.minor # => 4
@@ -20,7 +51,9 @@ numbers in the wide variety of versioning schemes in use.
20
51
  v2.release_type # => :alpha
21
52
  v2.alpha_version # => 3
22
53
  v2 > v1 # => true
54
+ v2.to_s # => '1.4a3'
23
55
 
56
+ # Another parsing example.
24
57
  v3 = Versionomy.parse('1.4.0b2')
25
58
  v3.major # => 1
26
59
  v3.minor # => 4
@@ -31,29 +64,44 @@ numbers in the wide variety of versioning schemes in use.
31
64
  v3 > v2 # => true
32
65
  v3.to_s # => '1.4.0b2'
33
66
 
34
- v4 = v3.bump(:beta_version)
67
+ # You can bump any field
68
+ v4 = Versionomy.parse('1.4.0b2').bump(:beta_version)
35
69
  v4.to_s # => '1.4.0b3'
70
+ v5 = v4.bump(:tiny)
71
+ v5.to_s # => '1.4.1'
36
72
 
37
- v5 = v4.bump(:release_type)
38
- v5.to_s # => '1.4.0rc1'
39
-
40
- v6 = v5.bump(:release_type)
41
- v6.to_s # => '1.4.0'
42
-
43
- v7 = v3.bump(:tiny)
44
- v7.to_s # => '1.4.1'
73
+ # Bumping the release type works as you would expect
74
+ v6 = Versionomy.parse('1.4.0b2').bump(:release_type)
75
+ v6.release_type # => :release_candidate
76
+ v6.to_s # => '1.4.0rc1'
77
+ v7 = v6.bump(:release_type)
78
+ v7.release_type # => :final
79
+ v7.to_s # => '1.4.0'
45
80
 
46
- v8 = v3.bump(:major)
81
+ # If a version has trailing zeros, it remembers how many fields to
82
+ # unparse; however, you can also change this.
83
+ v8 = Versionomy.parse('1.4.0b2').bump(:major)
47
84
  v8.to_s # => '2.0.0'
48
85
  v8.unparse(:optional_fields => [:tiny]) # => '2.0'
86
+ v8.unparse(:required_fields => [:tiny2]) # => '2.0.0.0'
49
87
 
88
+ # Comparisons are semantic, so will behave as expected even if the
89
+ # formatting is set up differently.
50
90
  v9 = Versionomy.parse('2.0.0.0')
51
91
  v9.to_s # => '2.0.0.0'
52
- v9 == v8 # => true
92
+ v9 == Versionomy.parse('2') # => true
53
93
 
54
- v10 = v8.bump(:patchlevel)
94
+ # Patchlevels are supported when the release type is :final
95
+ v10 = Versionomy.parse('2.0.0').bump(:patchlevel)
96
+ v10.patchlevel # => 1
55
97
  v10.to_s # => '2.0.0-1'
98
+ v11 = Versionomy.parse('2.0p1')
99
+ v11.patchlevel # => 1
100
+ v11.to_s # => '2.0p1'
101
+ v11 == v10 # => true
56
102
 
103
+ # You can create your own format from scratch or by modifying an
104
+ # existing format
57
105
  microsoft_format = Versionomy.default_format.modified_copy do
58
106
  field(:minor) do
59
107
  recognize_number(:default_value_optional => true,
@@ -61,12 +109,12 @@ numbers in the wide variety of versioning schemes in use.
61
109
  :default_delimiter => ' SP')
62
110
  end
63
111
  end
64
- v11 = microsoft_format.parse('2008 SP2')
65
- v11.major # => 2008
66
- v11.minor # => 2
67
- v11.tiny # => 0
68
- v11.to_s # => '2008 SP2'
69
- v11 == Versionomy.parse('2008.2') # => true
112
+ v12 = microsoft_format.parse('2008 SP2')
113
+ v12.major # => 2008
114
+ v12.minor # => 2
115
+ v12.tiny # => 0
116
+ v12.to_s # => '2008 SP2'
117
+ v12 == Versionomy.parse('2008.2') # => true
70
118
 
71
119
  === Feature list
72
120
 
@@ -82,12 +130,15 @@ custom formats.
82
130
 
83
131
  Finally, Versionomy also lets you to create alternate versioning "schemas".
84
132
  You can define any number of version number fields, and provide your own
85
- semantics for comparing, parsing, and modifying version numbers.
133
+ semantics for comparing, parsing, and modifying version numbers. You can
134
+ provide conversions from one schema to another. As an example, Versionomy
135
+ provides a schema and formatter/parser matching Gem::Version.
86
136
 
87
137
  === Requirements
88
138
 
89
- * Ruby 1.8.6 or later (1.8.7 recommended), Ruby 1.9.1 or later, or JRuby 1.4 or later.
90
- * blockenspiel gem.
139
+ * Ruby 1.8.6 or later (1.8.7 recommended), Ruby 1.9.1 or later, or JRuby
140
+ 1.4 or later.
141
+ * blockenspiel 0.3 or later.
91
142
 
92
143
  === Installation
93
144
 
data/Rakefile CHANGED
@@ -89,7 +89,7 @@ gemspec_ = Gem::Specification.new do |s_|
89
89
  s_.has_rdoc = true
90
90
  s_.test_files = FileList['tests/tc_*.rb']
91
91
  s_.platform = Gem::Platform::RUBY
92
- s_.add_dependency('blockenspiel', '>= 0.2.2')
92
+ s_.add_dependency('blockenspiel', '>= 0.3.0')
93
93
  end
94
94
  Rake::GemPackageTask.new(gemspec_) do |task_|
95
95
  task_.need_zip = false
@@ -1,6 +1,6 @@
1
1
  # -----------------------------------------------------------------------------
2
2
  #
3
- # Versionomy format registry
3
+ # Versionomy conversion base class
4
4
  #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2008-2009 Daniel Azuma
@@ -37,51 +37,50 @@
37
37
  module Versionomy
38
38
 
39
39
 
40
- # === Version number format regsitry.
41
- #
42
- # Use the methods of this module to register formats with a name. This
43
- # allows version numbers to be serialized with their format.
44
- #
45
- # You may also access predefined formats such as the standard format from
46
- # this module. It also contains the implementations of these formats as
47
- # examples.
48
-
49
- module Formats
50
-
51
-
52
- @names = ::Hash.new
40
+ module Conversion
53
41
 
54
42
 
55
- # Get the format with the given name.
43
+ # The base conversion class.
56
44
  #
57
- # If the given name has not been defined, and strict is set to true,
58
- # raises Versionomy::Errors::UnknownFormatError. If strict is set to
59
- # false, returns nil if the given name has not been defined.
45
+ # This base class defines the API for a conversion. All conversions must
46
+ # define the method <tt>convert_value</tt> documented here. Conversions
47
+ # need not actually extend this base class, as long as they duck-type
48
+ # this method. However, this base class does provide a few convenience
49
+ # methods such as a sane implementation of inspect.
60
50
 
61
- def self.get(name_, strict_=false)
62
- format_ = @names[name_.to_s]
63
- if format_.nil? && strict_
64
- raise Errors::UnknownFormatError, name_
51
+ class Base
52
+
53
+
54
+ # Convert the given value to the given format and return the converted
55
+ # value.
56
+ #
57
+ # The convert_params may be interpreted however the particular
58
+ # conversion wishes.
59
+ #
60
+ # Raises Versionomy::Errors::ConversionError if the conversion failed.
61
+
62
+ def convert_value(value_, format_, convert_params_=nil)
63
+ raise Errors::ConversionError, "Conversion not implemented"
65
64
  end
66
- format_
67
- end
68
-
69
-
70
- # Register the given format under the given name.
71
- #
72
- # Raises Versionomy::Errors::FormatRedefinedError if the name has
73
- # already been defined.
74
-
75
- def self.register(name_, format_)
76
- name_ = name_.to_s
77
- if @names.include?(name_)
78
- raise Errors::FormatRedefinedError, name_
65
+
66
+
67
+ # Inspect this conversion.
68
+
69
+ def inspect
70
+ "#<#{self.class}:0x#{object_id.to_s(16)}>"
79
71
  end
80
- @names[name_] = format_
72
+
73
+
74
+ # The default to_s implementation just calls inspect.
75
+
76
+ def to_s
77
+ inspect
78
+ end
79
+
80
+
81
81
  end
82
82
 
83
83
 
84
84
  end
85
85
 
86
-
87
86
  end
@@ -0,0 +1,173 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Versionomy conversion base class
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2008-2009 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ module Versionomy
38
+
39
+
40
+ module Conversion
41
+
42
+
43
+ # A conversion strategy that relies on parsing.
44
+ # Essentially, it unparses the value and then attempts to parse it with
45
+ # the new format.
46
+
47
+ class Parsing < Base
48
+
49
+
50
+ # Create a parsing conversion.
51
+ #
52
+ # By default, this just unparses and reparses using the default
53
+ # parse settings. In some cases, this may be enough, but you may
54
+ # wish to improve the reliability of the conversion by tweaking the
55
+ # parsing settings. To do so, pass a block to the new method, and
56
+ # call methods of Versionomy::Conversion::Parsing::Builder in that
57
+ # block.
58
+
59
+ def initialize(&block_)
60
+ if block_
61
+ builder_ = Builder.new
62
+ ::Blockenspiel.invoke(block_, builder_)
63
+ @string_modifier = builder_._get_string_modifier
64
+ @unparse_params_modifier = builder_._get_unparse_params_modifier
65
+ @parse_params_generator ||= builder_._get_parse_params_generator
66
+ end
67
+ end
68
+
69
+
70
+ # Returns a value equivalent to the given value in the given format.
71
+ #
72
+ # The convert_params are passed to this conversion's customization
73
+ # blocks (if any).
74
+ #
75
+ # Raises Versionomy::Errors::ConversionError if the conversion failed.
76
+ # Typically, this is due to a failure of the parsing or unparsing.
77
+
78
+ def convert_value(value_, format_, convert_params_=nil)
79
+ begin
80
+ unparse_params_ = value_.unparse_params
81
+ if @unparse_params_modifier
82
+ unparse_params_ = @unparse_params_modifier.call(unparse_params_, convert_params_)
83
+ end
84
+ string_ = value_.unparse(unparse_params_)
85
+ if @string_modifier
86
+ string_ = @string_modifier.call(string_, convert_params_)
87
+ end
88
+ if @parse_params_generator
89
+ parse_params_ = @parse_params_generator.call(convert_params_)
90
+ else
91
+ parse_params_ = nil
92
+ end
93
+ new_value_ = format_.parse(string_, parse_params_)
94
+ return new_value_
95
+ rescue Errors::UnparseError => ex_
96
+ raise Errors::ConversionError, "Unparsing failed: #{ex_.inspect}"
97
+ rescue Errors::ParseError => ex_
98
+ raise Errors::ConversionError, "Parsing failed: #{ex_.inspect}"
99
+ end
100
+ end
101
+
102
+
103
+ # Call methods of this class in the block passed to
104
+ # Versionomy::Conversion::Parsing#new to fine-tune the behavior of
105
+ # the converter.
106
+
107
+ class Builder
108
+
109
+ include ::Blockenspiel::DSL
110
+
111
+
112
+ def initialize # :nodoc:
113
+ @string_modifier = nil
114
+ @parse_params_generator = nil
115
+ @unparse_params_modifier = nil
116
+ end
117
+
118
+
119
+ # Provide a block that generates the params used to parse the new
120
+ # value. The block should take one parameter, the convert_params
121
+ # passed to convert_value (which may be nil). It should return the
122
+ # parse params that should be used.
123
+
124
+ def to_generate_parse_params(&block_)
125
+ @parse_params_generator = block_
126
+ end
127
+
128
+
129
+ # Provide a block that can modify the params used to unparse the
130
+ # old value. The block should take two parameters: first, the
131
+ # original unparse params from the old value (which may be nil),
132
+ # and second, the convert_params passed to convert_value (which
133
+ # may also be nil). It should return the unparse params that
134
+ # should actually be used.
135
+
136
+ def to_modify_unparse_params(&block_)
137
+ @unparse_params_modifier = block_
138
+ end
139
+
140
+
141
+ # Provide a block that can modify the unparsed string prior to
142
+ # it being passed to the parser. The block should take two
143
+ # parameters: first, the string resulting from unparsing the old
144
+ # value, and second, the convert_params passed to convert_value
145
+ # (which may be nil). It should return the string to be parsed to
146
+ # get the new value.
147
+
148
+ def to_modify_string(&block_)
149
+ @string_modifier = block_
150
+ end
151
+
152
+
153
+ def _get_string_modifier # :nodoc:
154
+ @string_modifier
155
+ end
156
+
157
+ def _get_unparse_params_modifier # :nodoc:
158
+ @unparse_params_modifier
159
+ end
160
+
161
+ def _get_parse_params_generator # :nodoc:
162
+ @parse_params_generator
163
+ end
164
+
165
+ end
166
+
167
+
168
+ end
169
+
170
+
171
+ end
172
+
173
+ end
@@ -0,0 +1,138 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Versionomy standard format implementation
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2008-2009 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ module Versionomy
38
+
39
+ module Conversion
40
+
41
+
42
+ # This is a namespace for the implementation of the conversion between
43
+ # the rubygems and standard formats.
44
+
45
+ module Rubygems
46
+
47
+
48
+ # Create the conversion from standard to rubygems format.
49
+ # This method is called internally when Versionomy initializes itself,
50
+ # and you should not need to call it again. It is documented, however,
51
+ # so that you can inspect its source code from RDoc, since the source
52
+ # contains useful examples of how to use the conversion DSLs.
53
+
54
+ def self.create_standard_to_rubygems
55
+
56
+ # We'll use a parsing conversion.
57
+ Conversion::Parsing.new do
58
+
59
+ # We're going to modify how the standard format version is
60
+ # unparsed, so the rubygems format will have a better chance
61
+ # of parsing it.
62
+ to_modify_unparse_params do |params_, convert_params_|
63
+
64
+ params_ ||= {}
65
+
66
+ # If the standard format version has a prerelease notation,
67
+ # make sure it is set off using a delimiter that the rubygems
68
+ # format can recognized. So instead of "1.0b2", we force the
69
+ # unparsing to generate "1.0.b.2".
70
+ params_[:release_type_delim] = '.'
71
+ params_[:release_type_postdelim] = '.'
72
+
73
+ # If the standard format version has a patchlevel notation,
74
+ # force it to use the default number rather than letter style.
75
+ # So instead of "1.2c", we force the unparsing to generate
76
+ # "1.2-3".
77
+ params_[:patchlevel_style] = nil
78
+
79
+ # If the standard format version has a patchlevel notation,
80
+ # force it to use the default delimiter of "-" so the rubygems
81
+ # format will recognize it. So instead of "1.9.1p243", we force
82
+ # the unparsing to generate "1.9.1-243".
83
+ params_[:patchlevel_delim] = nil
84
+
85
+ params_
86
+ end
87
+
88
+ # Standard formats sometimes allow hyphens and spaces in field
89
+ # delimiters, but the rubygems format requires periods. So modify
90
+ # the unparsed string to conform to rubygems's expectations.
91
+ to_modify_string do |str_, convert_params_|
92
+ str_.gsub(/[\.\s-]+/, '.')
93
+ end
94
+
95
+ end
96
+
97
+ end
98
+
99
+
100
+ # Create the conversion from rubygems to standard format.
101
+ # This method is called internally when Versionomy initializes itself,
102
+ # and you should not need to call it again. It is documented, however,
103
+ # so that you can inspect its source code from RDoc, since the source
104
+ # contains useful examples of how to use the conversion DSLs.
105
+
106
+ def self.create_rubygems_to_standard
107
+
108
+ # We'll use a parsing conversion.
109
+ Conversion::Parsing.new do
110
+
111
+ # Handle the case where the rubygems version ends with a string
112
+ # field, e.g. "1.0.b". We want to treat this like "1.0b0" rather
113
+ # than "1.0-2" since the rubygems semantic states that this is a
114
+ # prerelease version. So we add 0 to the end of the parsed string
115
+ # if it ends in a letter.
116
+ to_modify_string do |str_, convert_params_|
117
+ str_.gsub(/([[:alpha:]])\z/, '\10')
118
+ end
119
+
120
+ end
121
+
122
+ end
123
+
124
+
125
+ unless Conversion.get(:standard, :rubygems)
126
+ Conversion.register(:standard, :rubygems, create_standard_to_rubygems)
127
+ end
128
+ unless Conversion.get(:rubygems, :standard)
129
+ Conversion.register(:rubygems, :standard, create_rubygems_to_standard)
130
+ end
131
+
132
+
133
+ end
134
+
135
+
136
+ end
137
+
138
+ end