rubygems-update 0.8.3

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.

Potentially problematic release.


This version of rubygems-update might be problematic. Click here for more details.

Files changed (96) hide show
  1. data/ChangeLog +2335 -0
  2. data/README +54 -0
  3. data/Rakefile +293 -0
  4. data/Releases +98 -0
  5. data/TODO +7 -0
  6. data/bin/gem +11 -0
  7. data/bin/gem_server +111 -0
  8. data/bin/generate_yaml_index.rb +58 -0
  9. data/bin/update_rubygems +18 -0
  10. data/doc/doc.css +73 -0
  11. data/doc/makedoc.rb +4 -0
  12. data/examples/application/an-app.gemspec +26 -0
  13. data/examples/application/bin/myapp +3 -0
  14. data/examples/application/lib/somefunctionality.rb +3 -0
  15. data/gemspecs/README +4 -0
  16. data/gemspecs/cgikit-1.1.0.gemspec +18 -0
  17. data/gemspecs/jabber4r.gemspec +26 -0
  18. data/gemspecs/linguistics.gemspec +22 -0
  19. data/gemspecs/ook.gemspec +21 -0
  20. data/gemspecs/progressbar.gemspec +22 -0
  21. data/gemspecs/redcloth.gemspec +22 -0
  22. data/gemspecs/rublog.gemspec +23 -0
  23. data/gemspecs/ruby-doom.gemspec +21 -0
  24. data/gemspecs/rubyjdwp.gemspec +21 -0
  25. data/gemspecs/statistics.gemspec +21 -0
  26. data/lib/rubygems.rb +353 -0
  27. data/lib/rubygems/builder.rb +54 -0
  28. data/lib/rubygems/cmd_manager.rb +127 -0
  29. data/lib/rubygems/command.rb +191 -0
  30. data/lib/rubygems/config_file.rb +57 -0
  31. data/lib/rubygems/doc_manager.rb +94 -0
  32. data/lib/rubygems/format.rb +65 -0
  33. data/lib/rubygems/gem_commands.rb +925 -0
  34. data/lib/rubygems/gem_runner.rb +23 -0
  35. data/lib/rubygems/installer.rb +621 -0
  36. data/lib/rubygems/loadpath_manager.rb +108 -0
  37. data/lib/rubygems/old_format.rb +150 -0
  38. data/lib/rubygems/open-uri.rb +604 -0
  39. data/lib/rubygems/package.rb +740 -0
  40. data/lib/rubygems/remote_installer.rb +499 -0
  41. data/lib/rubygems/rubygems_version.rb +6 -0
  42. data/lib/rubygems/source_index.rb +130 -0
  43. data/lib/rubygems/specification.rb +613 -0
  44. data/lib/rubygems/user_interaction.rb +176 -0
  45. data/lib/rubygems/validator.rb +148 -0
  46. data/lib/rubygems/version.rb +279 -0
  47. data/lib/ubygems.rb +4 -0
  48. data/pkgs/sources/lib/sources.rb +6 -0
  49. data/pkgs/sources/sources.gemspec +14 -0
  50. data/post-install.rb +75 -0
  51. data/redist/session.gem +433 -0
  52. data/scripts/buildtests.rb +25 -0
  53. data/scripts/gemdoc.rb +62 -0
  54. data/scripts/runtest.rb +17 -0
  55. data/scripts/specdoc.rb +164 -0
  56. data/setup.rb +1360 -0
  57. data/test/bogussources.rb +5 -0
  58. data/test/data/legacy/keyedlist-0.4.0.ruby +11 -0
  59. data/test/data/legacy/keyedlist-0.4.0.yaml +16 -0
  60. data/test/data/lib/code.rb +1 -0
  61. data/test/data/one/README.one +1 -0
  62. data/test/data/one/lib/one.rb +3 -0
  63. data/test/data/one/one.gemspec +17 -0
  64. data/test/data/one/one.yaml +40 -0
  65. data/test/functional.rb +145 -0
  66. data/test/gemenvironment.rb +45 -0
  67. data/test/gemutilities.rb +18 -0
  68. data/test/insure_session.rb +46 -0
  69. data/test/mock/gems/gems/sources-0.0.1/lib/sources.rb +5 -0
  70. data/test/mock/gems/specifications/sources-0.0.1.gemspec +8 -0
  71. data/test/mockgemui.rb +45 -0
  72. data/test/onegem.rb +23 -0
  73. data/test/simple_gem.rb +66 -0
  74. data/test/test_builder.rb +13 -0
  75. data/test/test_cached_fetcher.rb +60 -0
  76. data/test/test_check_command.rb +28 -0
  77. data/test/test_command.rb +130 -0
  78. data/test/test_configfile.rb +36 -0
  79. data/test/test_format.rb +70 -0
  80. data/test/test_gemloadpaths.rb +45 -0
  81. data/test/test_gempaths.rb +115 -0
  82. data/test/test_loadmanager.rb +40 -0
  83. data/test/test_local_cache.rb +157 -0
  84. data/test/test_package.rb +600 -0
  85. data/test/test_parse_commands.rb +179 -0
  86. data/test/test_process_commands.rb +21 -0
  87. data/test/test_remote_fetcher.rb +162 -0
  88. data/test/test_remote_installer.rb +154 -0
  89. data/test/test_source_index.rb +58 -0
  90. data/test/test_specification.rb +286 -0
  91. data/test/test_validator.rb +53 -0
  92. data/test/test_version_comparison.rb +204 -0
  93. data/test/testgem.rc +6 -0
  94. data/test/user_capture.rb +1 -0
  95. data/test/yaml_data.rb +59 -0
  96. metadata +151 -0
@@ -0,0 +1,176 @@
1
+ module Gem
2
+
3
+ ##
4
+ # Module that defines the default UserInteraction. Any class
5
+ # including this module will have access to the +ui+ method that
6
+ # returns the default UI.
7
+ module DefaultUserInteraction
8
+
9
+ # Return the default UI.
10
+ def ui
11
+ DefaultUserInteraction.ui
12
+ end
13
+
14
+ # Set the default UI. If the default UI is never explicity set, a
15
+ # simple console based UserInteraction will be used automatically.
16
+ def ui=(new_ui)
17
+ DefaultUserInteraction.ui = new_ui
18
+ end
19
+
20
+ def use_ui(new_ui, &block)
21
+ DefaultUserInteraction.use_ui(new_ui, &block)
22
+ end
23
+
24
+ # The default UI is a class variable of the singleton class for
25
+ # this module.
26
+ class << self
27
+ def ui
28
+ @ui ||= Gem::ConsoleUI.new
29
+ end
30
+ def ui=(new_ui)
31
+ @ui = new_ui
32
+ end
33
+ def use_ui(new_ui)
34
+ old_ui = @ui
35
+ @ui = new_ui
36
+ yield
37
+ ensure
38
+ @ui = old_ui
39
+ end
40
+ end
41
+ end
42
+
43
+ ##
44
+ # Make the default UI accessable without the "ui." prefix. Classes
45
+ # including this module may use the interaction methods on the
46
+ # default UI directly. Classes may also reference the +ui+ and
47
+ # <tt>ui=</tt> methods.
48
+ #
49
+ # Example:
50
+ #
51
+ # class X
52
+ # include Gem::UserInteraction
53
+ #
54
+ # def get_answer
55
+ # n = ask("What is the meaning of life?")
56
+ # end
57
+ # end
58
+ module UserInteraction
59
+ include DefaultUserInteraction
60
+ [
61
+ :choose_from_list, :ask, :ask_yes_no, :say, :alert, :alert_warning,
62
+ :alert_error, :terminate_interaction!, :terminate_interaction
63
+ ].each do |methname|
64
+ class_eval %{
65
+ def #{methname}(*args)
66
+ ui.#{methname}(*args)
67
+ end
68
+ }
69
+ end
70
+ end
71
+
72
+ ##
73
+ # StreamUI implements a simple stream based user interface.
74
+ class StreamUI
75
+ def initialize(in_stream, out_stream, err_stream=STDERR)
76
+ @ins = in_stream
77
+ @outs = out_stream
78
+ @errs = err_stream
79
+ end
80
+
81
+ # Choose from a list of options. +question+ is a prompt displayed
82
+ # above the list. +list+ is a list of option strings. Returns
83
+ # the pair [option_name, option_index].
84
+ def choose_from_list(question, list)
85
+ @outs.puts question
86
+ list.each_with_index do |item, index|
87
+ @outs.puts " #{index+1}. #{item}"
88
+ end
89
+ @outs.print "> "
90
+ @outs.flush
91
+ result = @ins.gets.strip.to_i - 1
92
+ return list[result], result
93
+ end
94
+
95
+ # Ask a question. Returns a true for yes, false for no.
96
+ def ask_yes_no(question, default=nil)
97
+ qstr = case default
98
+ when nil
99
+ 'yn'
100
+ when true
101
+ 'Yn'
102
+ else
103
+ 'yN'
104
+ end
105
+ result = nil
106
+ while result.nil?
107
+ result = ask("#{question} [#{qstr}]")
108
+ result = case result
109
+ when /^[Yy].*/
110
+ true
111
+ when /^[Nn].*/
112
+ false
113
+ else
114
+ default
115
+ end
116
+ end
117
+ return result
118
+ end
119
+
120
+ # Ask a question. Returns an answer.
121
+ def ask(question)
122
+ @outs.print(question + " ")
123
+ @outs.flush
124
+ result = @ins.gets
125
+ result.chomp! if result
126
+ result
127
+ end
128
+
129
+ # Display a statement.
130
+ def say(statement="")
131
+ @outs.puts statement
132
+ end
133
+
134
+ # Display an informational alert.
135
+ def alert(statement, question=nil)
136
+ @outs.puts "INFO: #{statement}"
137
+ return ask(question) if question
138
+ end
139
+
140
+ # Display a warning in a location expected to get error messages.
141
+ def alert_warning(statement, question=nil)
142
+ @errs.puts "WARNING: #{statement}"
143
+ ask(question) if question
144
+ end
145
+
146
+ # Display an error message in a location expected to get error
147
+ # messages.
148
+ def alert_error(statement, question=nil)
149
+ @errs.puts "ERROR: #{statement}"
150
+ ask(question) if question
151
+ end
152
+
153
+ # Terminate the application immediately without running any exit
154
+ # handlers.
155
+ def terminate_interaction!(status=-1)
156
+ exit!(status)
157
+ end
158
+
159
+ # Terminate the appliation normally, running any exit handlers
160
+ # that might have been defined.
161
+ def terminate_interaction(status=0)
162
+ exit(status)
163
+ end
164
+ end
165
+
166
+
167
+ ##
168
+ # Subclass of StreamUI that instantiates the user interaction using
169
+ # standard in, out and error.
170
+ class ConsoleUI < StreamUI
171
+ def initialize
172
+ super(STDIN, STDOUT, STDERR)
173
+ end
174
+ end
175
+ end
176
+
@@ -0,0 +1,148 @@
1
+ module Gem
2
+
3
+ class VerificationError < Gem::Exception; end
4
+
5
+ ##
6
+ # Validator performs various gem file and gem database validation
7
+ class Validator
8
+ include UserInteraction
9
+
10
+ ##
11
+ # Given a gem file's contents, validates against its own MD5 checksum
12
+ # gem_data:: [String] Contents of the gem file
13
+ def verify_gem(gem_data)
14
+ if(gem_data.size == 0) then
15
+ raise VerificationError.new("Empty Gem file")
16
+ end
17
+ require 'md5'
18
+ unless(gem_data =~ /MD5SUM/m)
19
+ return # Don't worry about it...this sucks. Need to fix MD5 stuff for
20
+ # new format
21
+ # FIXME
22
+ end
23
+ unless (MD5.md5(gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/, "MD5SUM = \"" + ("F" * 32) + "\"")) == $1.to_s)
24
+ raise VerificationError.new("Invalid checksum for Gem file")
25
+ end
26
+ end
27
+
28
+ ##
29
+ # Given the path to a gem file, validates against its own MD5 checksum
30
+ #
31
+ # gem_path:: [String] Path to gem file
32
+ def verify_gem_file(gem_path)
33
+ begin
34
+ File.open(gem_path, 'rb') do |file|
35
+ gem_data = file.read
36
+ verify_gem(gem_data)
37
+ end
38
+ rescue Errno::ENOENT
39
+ raise Gem::VerificationError.new("Missing gem file #{gem_path}")
40
+ end
41
+ end
42
+
43
+ private
44
+ def find_files_for_gem(gem_directory)
45
+ installed_files = []
46
+ Find.find(gem_directory) {|file_name|
47
+ fn = file_name.slice((gem_directory.size)..(file_name.size-1)).sub(/^\//, "")
48
+ if(!(fn =~ /CVS/ || File.directory?(fn) || fn == "")) then
49
+ installed_files << fn
50
+ end
51
+
52
+ }
53
+ installed_files
54
+ end
55
+
56
+
57
+ public
58
+ ErrorData = Struct.new(:path, :problem)
59
+
60
+ ##
61
+ # Checks the gem directory for the following potential
62
+ # inconsistencies/problems:
63
+ # * Checksum gem itself
64
+ # * For each file in each gem, check consistency of installed versions
65
+ # * Check for files that aren't part of the gem but are in the gems directory
66
+ # * 1 cache - 1 spec - 1 directory.
67
+ #
68
+ # returns a hash of ErrorData objects, keyed on the problem gem's name.
69
+ def alien
70
+ require 'rubygems/installer'
71
+ require 'find'
72
+ require 'md5'
73
+ errors = {}
74
+ Gem::SourceIndex.from_installed_gems.each do |gem_name, gem_spec|
75
+ errors[gem_name] ||= []
76
+ gem_path = File.join(Gem.dir, "cache", gem_spec.full_name) + ".gem"
77
+ spec_path = File.join(Gem.dir, "specifications", gem_spec.full_name) + ".gemspec"
78
+ gem_directory = File.join(Gem.dir, "gems", gem_spec.full_name)
79
+ installed_files = find_files_for_gem(gem_directory)
80
+
81
+ if(!File.exist?(spec_path)) then
82
+ errors[gem_name] << ErrorData.new(spec_path, "Spec file doesn't exist for installed gem")
83
+ end
84
+
85
+ begin
86
+ require 'rubygems/format.rb'
87
+ verify_gem_file(gem_path)
88
+ File.open(gem_path) do |file|
89
+ format = Gem::Format.from_file_by_path(gem_path)
90
+ format.file_entries.each do |entry, data|
91
+ # Found this file. Delete it from list
92
+ installed_files.delete remove_leading_dot_dir(entry['path'])
93
+ File.open(File.join(gem_directory, entry['path']), 'rb') do |f|
94
+ unless MD5.md5(f.read).to_s == MD5.md5(data).to_s
95
+ errors[gem_name] << ErrorData.new(entry['path'], "installed file doesn't match original from gem")
96
+ end
97
+ end
98
+ end
99
+ end
100
+ rescue VerificationError => e
101
+ errors[gem_name] << ErrorData.new(gem_path, e.message)
102
+ end
103
+ # Clean out directories that weren't explicitly included in the gemspec
104
+ # FIXME: This still allows arbitrary incorrect directories.
105
+ installed_files.delete_if {|potential_directory|
106
+ File.directory?(File.join(gem_directory, potential_directory))
107
+ }
108
+ if(installed_files.size > 0) then
109
+ errors[gem_name] << ErrorData.new(gem_path, "Unmanaged files in gem: #{installed_files.inspect}")
110
+ end
111
+ end
112
+ errors
113
+ end
114
+
115
+ ##
116
+ # Runs unit tests for a given gem specification
117
+ def unit_test(gem_spec)
118
+ start_dir = Dir.pwd
119
+ Dir.chdir(gem_spec.full_gem_path)
120
+ $: << File.join(Gem.dir, "gems", gem_spec.full_name)
121
+ # XXX: why do we need this gem_spec when we've already got 'spec'?
122
+ test_files = gem_spec.test_files
123
+ if test_files.empty?
124
+ say "There are no unit tests to run for #{gem_spec.name}-#{gem_spec.version}"
125
+ return
126
+ end
127
+ require_gem gem_spec.name, "= #{gem_spec.version.version}"
128
+ test_files.each do |f| require f end
129
+ require 'test/unit/ui/console/testrunner'
130
+ suite = Test::Unit::TestSuite.new("#{gem_spec.name}-#{gem_spec.version}")
131
+ ObjectSpace.each_object(Class) do |klass|
132
+ suite << klass.suite if (klass < Test::Unit::TestCase)
133
+ end
134
+ result = Test::Unit::UI::Console::TestRunner.run(suite, Test::Unit::UI::SILENT)
135
+ unless result.passed?
136
+ alert_error(result.to_s)
137
+ #unless ask_yes_no(result.to_s + "...keep Gem?", true) then
138
+ #Gem::Uninstaller.new(gem_spec.name, gem_spec.version.version).uninstall
139
+ #end
140
+ end
141
+ Dir.chdir(start_dir)
142
+ end
143
+
144
+ def remove_leading_dot_dir(path)
145
+ path.sub(/^\.\//, "")
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,279 @@
1
+ module Gem
2
+
3
+ ##
4
+ # The Dependency class holds a Gem name and Version::Requirement
5
+ #
6
+ class Dependency
7
+ attr_accessor :name, :version_requirements
8
+
9
+ ##
10
+ # Constructs the dependency
11
+ #
12
+ # name:: [String] name of the Gem
13
+ # version_requirements:: [String Array] version requirement (e.g. ["> 1.2"])
14
+ #
15
+ def initialize(name, version_requirements)
16
+ @name = name
17
+ @version_requirements = Version::Requirement.new(version_requirements)
18
+ @version_requirement = nil # Avoid warnings.
19
+ end
20
+
21
+ undef version_requirements
22
+ def version_requirements
23
+ normalize if @version_requirement
24
+ @version_requirements
25
+ end
26
+
27
+ def requirement_list
28
+ version_requirements.as_list
29
+ end
30
+
31
+ alias requirements_list requirement_list
32
+
33
+ def normalize
34
+ ver = @version_requirement.instance_eval { @version }
35
+ @version_requirements = Version::Requirement.new([ver])
36
+ @version_requirement = nil
37
+ end
38
+
39
+ def to_s
40
+ "#{name} (#{version_requirements})"
41
+ end
42
+
43
+ def ==(other)
44
+ self.name = other.name and
45
+ self.version_requirements == other.version_requirements
46
+ end
47
+ end
48
+
49
+ ##
50
+ # The Version class processes string versions into comparable values
51
+ #
52
+ class Version
53
+ include Comparable
54
+
55
+ attr_accessor :version
56
+
57
+ NUM_RE = /\s*(\d+(\.\d+)*)*\s*/
58
+
59
+ ##
60
+ # Checks if version string is valid format
61
+ #
62
+ # str:: [String] the version string
63
+ # return:: [Boolean] true if the string format is correct, otherwise false
64
+ #
65
+ def self.correct?(str)
66
+ /^#{NUM_RE}$/.match(str)
67
+ end
68
+
69
+ ##
70
+ # Factory method to create a Version object. Input may be a Version or a
71
+ # String. Intended to simplify client code.
72
+ #
73
+ # ver1 = Version.create('1.3.17') # -> (Version object)
74
+ # ver2 = Version.create(ver1) # -> (ver1)
75
+ # ver3 = Version.create(nil) # -> nil
76
+ #
77
+ def self.create(input)
78
+ if input.respond_to? :version
79
+ return input
80
+ elsif input.nil?
81
+ return nil
82
+ else
83
+ return Version.new(input)
84
+ end
85
+ end
86
+
87
+ ##
88
+ # Constructs a version from the supplied string
89
+ #
90
+ # version:: [String] The version string. Format is digit.digit...
91
+ #
92
+ def initialize(version)
93
+ raise ArgumentError,
94
+ "Malformed version number string #{version}" unless Version.correct?(version)
95
+ @version = version
96
+ end
97
+
98
+ ##
99
+ # Returns the text representation of the version
100
+ #
101
+ # return:: [String] version as string
102
+ #
103
+ def to_s
104
+ @version
105
+ end
106
+
107
+ ##
108
+ # Convert version to integer array
109
+ #
110
+ # return:: [Array] list of integers
111
+ #
112
+ def to_ints
113
+ @version.scan(/\d+/).map {|s| s.to_i}
114
+ end
115
+
116
+ ##
117
+ # Compares two versions
118
+ #
119
+ # other:: [Version or .to_ints] other version to compare to
120
+ # return:: [Fixnum] -1, 0, 1
121
+ #
122
+ def <=>(other)
123
+ return 1 unless other
124
+ rnums, vnums = to_ints, other.to_ints
125
+ [rnums.size, vnums.size].max.times {|i|
126
+ rnums[i] ||= 0
127
+ vnums[i] ||= 0
128
+ }
129
+
130
+ begin
131
+ r,v = rnums.shift, vnums.shift
132
+ end until (r != v || rnums.empty?)
133
+
134
+ return r <=> v
135
+ end
136
+
137
+ # Return a new version object where the next to the last revision
138
+ # number is one greater. (e.g. 5.3.1 => 5.4)
139
+ def bump
140
+ ints = to_ints
141
+ ints.pop if ints.size > 1
142
+ ints[-1] += 1
143
+ self.class.new(ints.join("."))
144
+ end
145
+
146
+ ##
147
+ # Requirement version includes a prefaced comparator in addition
148
+ # to a version number.
149
+ #
150
+ # A Requirement object can actually contain multiple, er, requirements, as
151
+ # in (> 1.2, < 2.0).
152
+ #
153
+ class Requirement
154
+ include Comparable
155
+
156
+ OPS = {
157
+ "=" => lambda { |v, r| v == r },
158
+ "!=" => lambda { |v, r| v != r },
159
+ ">" => lambda { |v, r| v > r },
160
+ "<" => lambda { |v, r| v < r },
161
+ ">=" => lambda { |v, r| v >= r },
162
+ "<=" => lambda { |v, r| v <= r },
163
+ "~>" => lambda { |v, r| v >= r && v < r.bump }
164
+ }
165
+
166
+ OP_RE = Regexp.new(OPS.keys.collect{|k| Regexp.quote(k)}.join("|"))
167
+ REQ_RE = /\s*(#{OP_RE})\s*/
168
+
169
+ ##
170
+ # Factory method to create a Version::Requirement object. Input may be a
171
+ # Version, a String, or nil. Intended to simplify client code.
172
+ #
173
+ # If the input is "weird", the default version requirement is returned.
174
+ #
175
+ def self.create(input)
176
+ if input.kind_of?(Requirement)
177
+ return input
178
+ elsif input.kind_of?(Array)
179
+ return self.new(input)
180
+ elsif input.respond_to? :to_str
181
+ return self.new([input.to_str])
182
+ else
183
+ return self.default
184
+ end
185
+ end
186
+
187
+ ##
188
+ # A default "version requirement" can surely _only_ be '> 0'.
189
+ #
190
+ def self.default
191
+ self.new(['> 0.0.0'])
192
+ end
193
+
194
+ ##
195
+ # Constructs a version requirement instance
196
+ #
197
+ # str:: [String Array] the version requirement string (e.g. ["> 1.23"])
198
+ #
199
+ def initialize(reqs)
200
+ @requirements = reqs.collect do |rq|
201
+ op, version_string = parse(rq)
202
+ [op, Version.new(version_string)]
203
+ end
204
+ @version = nil # Avoid warnings.
205
+ end
206
+
207
+ ##
208
+ # Overrides to check for comparator
209
+ #
210
+ # str:: [String] the version requirement string
211
+ # return:: [Boolean] true if the string format is correct, otherwise false
212
+ #
213
+ def correct?(str)
214
+ /^#{REQ_RE}#{NUM_RE}$/.match(str)
215
+ end
216
+
217
+ def to_s
218
+ as_list.join(", ")
219
+ end
220
+
221
+ def as_list
222
+ normalize
223
+ @requirements.collect { |req|
224
+ "#{req[0]} #{req[1]}"
225
+ }
226
+ end
227
+
228
+ def normalize
229
+ return if @version.nil?
230
+ @requirements = [parse(@version)]
231
+ @nums = nil
232
+ @version = nil
233
+ @op = nil
234
+ end
235
+
236
+ ##
237
+ # Is the requirement satifised by +version+.
238
+ #
239
+ # version:: [Gem::Version] the version to compare against
240
+ # return:: [Boolean] true if this requirement is satisfied by
241
+ # the version, otherwise false
242
+ #
243
+ def satisfied_by?(version)
244
+ normalize
245
+ @requirements.all? { |op, rv| satisfy?(op, version, rv) }
246
+ end
247
+
248
+ private
249
+
250
+ ##
251
+ # Is "version op required_version" satisfied?
252
+ #
253
+ def satisfy?(op, version, required_version)
254
+ OPS[op].call(version, required_version)
255
+ end
256
+
257
+ ##
258
+ # Parse the version requirement string. Return the operator and
259
+ # version strings.
260
+ #
261
+ def parse(str)
262
+ if md = /^\s*(#{OP_RE})\s*([0-9.]+)\s*$/.match(str)
263
+ [md[1], md[2]]
264
+ elsif md = /^\s*([0-9.]+)\s*$/.match(str)
265
+ ["=", md[1]]
266
+ elsif md = /^\s*(#{OP_RE})\s*$/.match(str)
267
+ [md[1], "0"]
268
+ else
269
+ fail ArgumentError, "Illformed requirement [#{str}]"
270
+ end
271
+ end
272
+
273
+ def <=>(other)
274
+ to_s <=> other.to_s
275
+ end
276
+
277
+ end
278
+ end
279
+ end