ruby_core_source 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,28 @@
1
+ Retrieve ruby core source files.
2
+
3
+ This can be used by any C extension gem that needs Ruby core headers (*.h and *.inc)
4
+
5
+ Usage:
6
+
7
+ Ruby_core_source::create_makefile_with_core(hdr_check_proc, gem_name)
8
+ takes the place of
9
+ create_makefile(gem_name)
10
+ in your extconf.rb
11
+
12
+ This will:
13
+ If hdr_check_proc is true, call create_makefile(gem_name)
14
+ Else: if core headers already exist, and hdr_check_proc is true, call create_makefile(gem_name)
15
+ Else: fetch and extract the core headers, check hdr_check_proc, and call create_makefile(gem_name)
16
+ Else: return false
17
+
18
+ Note that for Ruby preview releases, the corresponding RUBY_REVISION needs to be maintained in
19
+ http://cloud.github.com/downloads/mark-moseley/ruby_core_source/preview_revision.yml
20
+
21
+ Example use in extconf.rb:
22
+
23
+ hdrs = proc { have_header("vm_core.h") and have_header("iseq.h") }
24
+ dir_config("ruby") # allow user to pass in non-standard core include directory
25
+ if !Ruby_core_source::create_makefile_with_core(hdrs, "foo")
26
+ # error
27
+ exit(1)
28
+ end
@@ -0,0 +1,237 @@
1
+ # = progressbar.rb
2
+ #
3
+ # == Copyright (C) 2001 Satoru Takabayashi
4
+ #
5
+ # Ruby License
6
+ #
7
+ # This module is free software. You may use, modify, and/or redistribute this
8
+ # software under the same terms as Ruby.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
+ # FOR A PARTICULAR PURPOSE.
13
+ #
14
+ # == Author(s)
15
+ #
16
+ # * Satoru Takabayashi
17
+
18
+ # Author:: Satoru Takabayashi
19
+ # Copyright:: Copyright (c) 2001 Satoru Takabayashi
20
+ # License:: Ruby License
21
+
22
+ # = Console Progress Bar
23
+ #
24
+ # Console::ProgressBar is a terminal-based progress bar library.
25
+ #
26
+ # == Usage
27
+ #
28
+ # pbar = ConsoleProgressBar.new( "Demo", 100 )
29
+ # 100.times { pbar.inc }
30
+ # pbar.finish
31
+ #
32
+
33
+ module Console; end
34
+
35
+ class Console::ProgressBar
36
+
37
+ def initialize(title, total, out = STDERR)
38
+ @title = title
39
+ @total = total
40
+ @out = out
41
+ @bar_length = 80
42
+ @bar_mark = "o"
43
+ @total_overflow = true
44
+ @current = 0
45
+ @previous = 0
46
+ @is_finished = false
47
+ @start_time = Time.now
48
+ @format = "%-14s %3d%% %s %s"
49
+ @format_arguments = [:title, :percentage, :bar, :stat]
50
+ show_progress
51
+ end
52
+
53
+ private
54
+ def convert_bytes (bytes)
55
+ if bytes < 1024
56
+ sprintf("%6dB", bytes)
57
+ elsif bytes < 1024 * 1000 # 1000kb
58
+ sprintf("%5.1fKB", bytes.to_f / 1024)
59
+ elsif bytes < 1024 * 1024 * 1000 # 1000mb
60
+ sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
61
+ else
62
+ sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
63
+ end
64
+ end
65
+
66
+ def transfer_rate
67
+ bytes_per_second = @current.to_f / (Time.now - @start_time)
68
+ sprintf("%s/s", convert_bytes(bytes_per_second))
69
+ end
70
+
71
+ def bytes
72
+ convert_bytes(@current)
73
+ end
74
+
75
+ def format_time (t)
76
+ t = t.to_i
77
+ sec = t % 60
78
+ min = (t / 60) % 60
79
+ hour = t / 3600
80
+ sprintf("%02d:%02d:%02d", hour, min, sec);
81
+ end
82
+
83
+ # ETA stands for Estimated Time of Arrival.
84
+ def eta
85
+ if @current == 0
86
+ "ETA: --:--:--"
87
+ else
88
+ elapsed = Time.now - @start_time
89
+ eta = elapsed * @total / @current - elapsed;
90
+ sprintf("ETA: %s", format_time(eta))
91
+ end
92
+ end
93
+
94
+ def elapsed
95
+ elapsed = Time.now - @start_time
96
+ sprintf("Time: %s", format_time(elapsed))
97
+ end
98
+
99
+ def stat
100
+ if @is_finished then elapsed else eta end
101
+ end
102
+
103
+ def stat_for_file_transfer
104
+ if @is_finished then
105
+ sprintf("%s %s %s", bytes, transfer_rate, elapsed)
106
+ else
107
+ sprintf("%s %s %s", bytes, transfer_rate, eta)
108
+ end
109
+ end
110
+
111
+ def eol
112
+ if @is_finished then "\n" else "\r" end
113
+ end
114
+
115
+ def bar
116
+ len = percentage * @bar_length / 100
117
+ sprintf("|%s%s|", @bar_mark * len, " " * (@bar_length - len))
118
+ end
119
+
120
+ def percentage
121
+ if @total.zero?
122
+ 100
123
+ else
124
+ @current * 100 / @total
125
+ end
126
+ end
127
+
128
+ def title
129
+ @title[0,13] + ":"
130
+ end
131
+
132
+ def get_width
133
+ # FIXME: I don't know how portable it is.
134
+ default_width = 80
135
+ begin
136
+ tiocgwinsz = 0x5413
137
+ data = [0, 0, 0, 0].pack("SSSS")
138
+ if @out.ioctl(tiocgwinsz, data) >= 0 then
139
+ rows, cols, xpixels, ypixels = data.unpack("SSSS")
140
+ if cols >= 0 then cols else default_width end
141
+ else
142
+ default_width
143
+ end
144
+ rescue Exception
145
+ default_width
146
+ end
147
+ end
148
+
149
+ def show
150
+ arguments = @format_arguments.map {|method| send(method) }
151
+ line = sprintf(@format, *arguments)
152
+
153
+ width = get_width
154
+ if line.length == width - 1
155
+ @out.print(line + eol)
156
+ elsif line.length >= width
157
+ @bar_length = [@bar_length - (line.length - width + 1), 0].max
158
+ if @bar_length == 0 then @out.print(line + eol) else show end
159
+ else #line.length < width - 1
160
+ @bar_length += width - line.length + 1
161
+ show
162
+ end
163
+ end
164
+
165
+ def show_progress
166
+ if @total.zero?
167
+ cur_percentage = 100
168
+ prev_percentage = 0
169
+ else
170
+ cur_percentage = (@current * 100 / @total).to_i
171
+ prev_percentage = (@previous * 100 / @total).to_i
172
+ end
173
+
174
+ if cur_percentage > prev_percentage || @is_finished
175
+ show
176
+ end
177
+ end
178
+
179
+ public
180
+ def file_transfer_mode
181
+ @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
182
+ end
183
+
184
+ def bar_mark= (mark)
185
+ @bar_mark = String(mark)[0..0]
186
+ end
187
+
188
+ def total_overflow= (boolv)
189
+ @total_overflow = boolv ? true : false
190
+ end
191
+
192
+ def format= (format)
193
+ @format = format
194
+ end
195
+
196
+ def format_arguments= (arguments)
197
+ @format_arguments = arguments
198
+ end
199
+
200
+ def finish
201
+ @current = @total
202
+ @is_finished = true
203
+ show_progress
204
+ end
205
+
206
+ def halt
207
+ @is_finished = true
208
+ show_progress
209
+ end
210
+
211
+ def set (count)
212
+ if count < 0
213
+ raise "invalid count less than zero: #{count}"
214
+ elsif count > @total
215
+ if @total_overflow
216
+ @total = count + 1
217
+ else
218
+ raise "invalid count greater than total: #{count}"
219
+ end
220
+ end
221
+ @current = count
222
+ show_progress
223
+ @previous = @current
224
+ end
225
+
226
+ def inc (step = 1)
227
+ @current += step
228
+ @current = @total if @current > @total
229
+ show_progress
230
+ @previous = @current
231
+ end
232
+
233
+ def inspect
234
+ "(ProgressBar: #{@current}/#{@total})"
235
+ end
236
+
237
+ end
@@ -0,0 +1,289 @@
1
+ #
2
+ # I've striped down dependencies on Net::SSH and Facets to
3
+ # stay as simple as possible.
4
+ #
5
+ # Original code from Assaf Arkin, released under Apache License
6
+ # (http://buildr.rubyforge.org/license.html)
7
+ #
8
+ require 'cgi'
9
+ require 'uri'
10
+ require 'net/http'
11
+ require 'net/https'
12
+ require 'tempfile'
13
+ require 'fileutils'
14
+
15
+ # show progress of download
16
+ require File.join(File.dirname(__FILE__), 'progressbar')
17
+
18
+ # Not quite open-uri, but similar. Provides read and write methods for the resource represented by the URI.
19
+ # Currently supports reads for URI::HTTP and writes for URI::SFTP. Also provides convenience methods for
20
+ # downloads and uploads.
21
+ module URI
22
+ # Raised when trying to read/download a resource that doesn't exist.
23
+ class NotFoundError < RuntimeError; end
24
+
25
+ class << self
26
+ # :call-seq:
27
+ # read(uri, options?) => content
28
+ # read(uri, options?) { |chunk| ... }
29
+ #
30
+ # Reads from the resource behind this URI. The first form returns the content of the resource,
31
+ # the second form yields to the block with each chunk of content (usually more than one).
32
+ #
33
+ # For example:
34
+ # File.open "image.jpg", "w" do |file|
35
+ # URI.read("http://example.com/image.jpg") { |chunk| file.write chunk }
36
+ # end
37
+ # Shorter version:
38
+ # File.open("image.jpg", "w") { |file| file.write URI.read("http://example.com/image.jpg") }
39
+ #
40
+ # Supported options:
41
+ # * :modified -- Only download if file modified since this timestamp. Returns nil if not modified.
42
+ # * :progress -- Show the progress bar while reading.
43
+ def read(uri, options = nil, &block)
44
+ uri = URI.parse(uri.to_s) unless URI === uri
45
+ uri.read(options, &block)
46
+ end
47
+
48
+ # :call-seq:
49
+ # download(uri, target, options?)
50
+ #
51
+ # Downloads the resource to the target.
52
+ #
53
+ # The target may be a file name (string or task), in which case the file is created from the resource.
54
+ # The target may also be any object that responds to +write+, e.g. File, StringIO, Pipe.
55
+ #
56
+ # Use the progress bar when running in verbose mode.
57
+ def download(uri, target, options = nil)
58
+ uri = URI.parse(uri.to_s) unless URI === uri
59
+ uri.download(target, options)
60
+ end
61
+
62
+ # :call-seq:
63
+ # write(uri, content, options?)
64
+ # write(uri, options?) { |bytes| .. }
65
+ #
66
+ # Writes to the resource behind the URI. The first form writes the content from a string or an object
67
+ # that responds to +read+ and optionally +size+. The second form writes the content by yielding to the
68
+ # block. Each yield should return up to the specified number of bytes, the last yield returns nil.
69
+ #
70
+ # For example:
71
+ # File.open "killer-app.jar", "rb" do |file|
72
+ # write("sftp://localhost/jars/killer-app.jar") { |chunk| file.read(chunk) }
73
+ # end
74
+ # Or:
75
+ # write "sftp://localhost/jars/killer-app.jar", File.read("killer-app.jar")
76
+ #
77
+ # Supported options:
78
+ # * :progress -- Show the progress bar while reading.
79
+ def write(uri, *args, &block)
80
+ uri = URI.parse(uri.to_s) unless URI === uri
81
+ uri.write(*args, &block)
82
+ end
83
+ end
84
+
85
+ class Generic
86
+
87
+ # :call-seq:
88
+ # read(options?) => content
89
+ # read(options?) { |chunk| ... }
90
+ #
91
+ # Reads from the resource behind this URI. The first form returns the content of the resource,
92
+ # the second form yields to the block with each chunk of content (usually more than one).
93
+ #
94
+ # For options, see URI::read.
95
+ def read(options = nil, &block)
96
+ fail "This protocol doesn't support reading (yet, how about helping by implementing it?)"
97
+ end
98
+
99
+ # :call-seq:
100
+ # download(target, options?)
101
+ #
102
+ # Downloads the resource to the target.
103
+ #
104
+ # The target may be a file name (string or task), in which case the file is created from the resource.
105
+ # The target may also be any object that responds to +write+, e.g. File, StringIO, Pipe.
106
+ #
107
+ # Use the progress bar when running in verbose mode.
108
+ def download(target, options = {})
109
+ case target
110
+ when String
111
+ # If download breaks we end up with a partial file which is
112
+ # worse than not having a file at all, so download to temporary
113
+ # file and then move over.
114
+ modified = File.stat(target).mtime if File.exist?(target)
115
+ temp = nil
116
+ Tempfile.open(File.basename(target)) do |tf|
117
+ tf.binmode
118
+ read(options.merge(:modified => modified)) { |chunk| tf.write chunk }
119
+ temp = tf
120
+ end
121
+ FileUtils.mkpath(File.dirname(target))
122
+ FileUtils.move(temp.path, target)
123
+ when File
124
+ read(options.merge(:modified => target.mtime)) { |chunk| target.write chunk }
125
+ target.flush
126
+ else
127
+ raise ArgumentError, "Expecting a target that is either a file name (string, task) or object that responds to write (file, pipe)." unless target.respond_to?(:write)
128
+ read(options) { |chunk| target.write chunk }
129
+ target.flush
130
+ end
131
+ end
132
+
133
+ # :call-seq:
134
+ # write(content, options?)
135
+ # write(options?) { |bytes| .. }
136
+ #
137
+ # Writes to the resource behind the URI. The first form writes the content from a string or an object
138
+ # that responds to +read+ and optionally +size+. The second form writes the content by yielding to the
139
+ # block. Each yield should return up to the specified number of bytes, the last yield returns nil.
140
+ #
141
+ # For options, see URI::write.
142
+ def write(*args, &block)
143
+ options = args.pop if Hash === args.last
144
+ options ||= {}
145
+ if String === args.first
146
+ ios = StringIO.new(args.first, "r")
147
+ write(options.merge(:size => args.first.size)) { |bytes| ios.read(bytes) }
148
+ elsif args.first.respond_to?(:read)
149
+ size = args.first.size rescue nil
150
+ write({ :size => size }.merge(options)) { |bytes| args.first.read(bytes) }
151
+ elsif args.empty? && block
152
+ write_internal(options, &block)
153
+ else
154
+ raise ArgumentError, "Either give me the content, or pass me a block, otherwise what would I upload?"
155
+ end
156
+ end
157
+
158
+ protected
159
+
160
+ # :call-seq:
161
+ # with_progress_bar(enable, file_name, size) { |progress| ... }
162
+ #
163
+ # Displays a progress bar while executing the block. The first argument must be true for the
164
+ # progress bar to show (TTY output also required), as a convenient for selectively using the
165
+ # progress bar from a single block.
166
+ #
167
+ # The second argument provides a filename to display, the third its size in bytes.
168
+ #
169
+ # The block is yielded with a progress object that implements a single method.
170
+ # Call << for each block of bytes down/uploaded.
171
+ def with_progress_bar(enable, file_name, size) #:nodoc:
172
+ if enable && $stdout.isatty
173
+ progress_bar = Console::ProgressBar.new(file_name, size)
174
+ # Extend the progress bar so we can display count/total.
175
+ class << progress_bar
176
+ def total()
177
+ convert_bytes(@total)
178
+ end
179
+ end
180
+ # Squeeze the filename into 30 characters.
181
+ if file_name.size > 30
182
+ base, ext = File.basename(file_name), File.extname(file_name)
183
+ truncated = "#{base[0..26-ext.to_s.size]}..#{ext}"
184
+ else
185
+ truncated = file_name
186
+ end
187
+ progress_bar.format = "#{CGI.unescape(truncated)}: %3d%% %s %s/%s %s"
188
+ progress_bar.format_arguments = [:percentage, :bar, :bytes, :total, :stat]
189
+ progress_bar.bar_mark = "o"
190
+
191
+ begin
192
+ class << progress_bar
193
+ def <<(bytes)
194
+ inc bytes.respond_to?(:size) ? bytes.size : bytes
195
+ end
196
+ end
197
+ yield progress_bar
198
+ ensure
199
+ progress_bar.finish
200
+ end
201
+ else
202
+ progress_bar = Object.new
203
+ class << progress_bar
204
+ def <<(bytes)
205
+ end
206
+ end
207
+ yield progress_bar
208
+ end
209
+ end
210
+
211
+ # :call-seq:
212
+ # proxy_uri() => URI?
213
+ #
214
+ # Returns the proxy server to use. Obtains the proxy from the relevant environment variable (e.g. HTTP_PROXY).
215
+ # Supports exclusions based on host name and port number from environment variable NO_PROXY.
216
+ def proxy_uri()
217
+ proxy = ENV["#{scheme.upcase}_PROXY"]
218
+ proxy = URI.parse(proxy) if String === proxy
219
+ excludes = (ENV["NO_PROXY"] || "").split(/\s*,\s*/).compact
220
+ excludes = excludes.map { |exclude| exclude =~ /:\d+$/ ? exclude : "#{exclude}:*" }
221
+ return proxy unless excludes.any? { |exclude| File.fnmatch(exclude, "#{host}:#{port}") }
222
+ end
223
+
224
+ def write_internal(options, &block) #:nodoc:
225
+ fail "This protocol doesn't support writing (yet, how about helping by implementing it?)"
226
+ end
227
+ end
228
+
229
+ class HTTP #:nodoc:
230
+
231
+ # See URI::Generic#read
232
+ def read(options = nil, &block)
233
+ options ||= {}
234
+ connect do |http|
235
+ puts "Requesting #{self}" #if verbose
236
+ headers = { 'If-Modified-Since' => CGI.rfc1123_date(options[:modified].utc) } if options[:modified]
237
+ request = Net::HTTP::Get.new(request_uri.empty? ? '/' : request_uri, headers)
238
+ request.basic_auth self.user, self.password if self.user
239
+ http.request request do |response|
240
+ case response
241
+ when Net::HTTPNotModified
242
+ # No modification, nothing to do.
243
+ puts 'Not modified since last download' #if verbose
244
+ return nil
245
+ when Net::HTTPRedirection
246
+ # Try to download from the new URI, handle relative redirects.
247
+ puts "Redirected to #{response['Location']}" #if verbose
248
+ return (self + URI.parse(response['location'])).read(options, &block)
249
+ when Net::HTTPOK
250
+ puts "Downloading #{self}" #if verbose
251
+ result = nil
252
+ with_progress_bar options[:progress], path.split('/').last, response.content_length do |progress|
253
+ if block
254
+ response.read_body do |chunk|
255
+ block.call chunk
256
+ progress << chunk
257
+ end
258
+ else
259
+ result = ''
260
+ response.read_body do |chunk|
261
+ result << chunk
262
+ progress << chunk
263
+ end
264
+ end
265
+ end
266
+ return result
267
+ when Net::HTTPNotFound
268
+ raise NotFoundError, "Looking for #{self} and all I got was a 404!"
269
+ else
270
+ raise RuntimeError, "Failed to download #{self}: #{response.message}"
271
+ end
272
+ end
273
+ end
274
+ end
275
+
276
+ private
277
+
278
+ def connect
279
+ if proxy = proxy_uri
280
+ proxy = URI.parse(proxy) if String === proxy
281
+ http = Net::HTTP.new(host, port, proxy.host, proxy.port, proxy.user, proxy.password)
282
+ else
283
+ http = Net::HTTP.new(host, port)
284
+ end
285
+ http.use_ssl = true if self.instance_of? URI::HTTPS
286
+ yield http
287
+ end
288
+ end
289
+ end
@@ -0,0 +1,78 @@
1
+
2
+ require 'rbconfig'
3
+ require 'tempfile'
4
+ require 'tmpdir'
5
+ require 'yaml'
6
+ require File.join(File.dirname(__FILE__), 'contrib', 'uri_ext')
7
+ require 'archive/tar/minitar'
8
+ require 'zlib'
9
+ require 'fileutils'
10
+
11
+ module Ruby_core_source
12
+
13
+ def create_makefile_with_core(hdrs, name)
14
+
15
+ #
16
+ # First, see if the gem already has the needed headers
17
+ #
18
+ if hdrs.call
19
+ create_makefile(name)
20
+ return true
21
+ end
22
+
23
+ ruby_dir = ""
24
+ if RUBY_PATCHLEVEL < 0
25
+ Tempfile.open("preview-revision") { |temp|
26
+ uri = URI.parse("http://cloud.github.com/downloads/mark-moseley/ruby_core_source/preview_revision.yml")
27
+ uri.download(temp)
28
+ revision_map = YAML::load(File.open(temp.path))
29
+ ruby_dir = revision_map[RUBY_REVISION]
30
+ return false if ruby_dir.nil?
31
+ }
32
+ else
33
+ ruby_dir = "ruby-" + RUBY_VERSION.to_s + "-p" + RUBY_PATCHLEVEL.to_s
34
+ end
35
+
36
+ #
37
+ # Check if core headers were already downloaded; if so, use them
38
+ #
39
+ dest_dir = Config::CONFIG["rubyhdrdir"] + "/" + ruby_dir
40
+ with_cppflags("-I" + dest_dir) {
41
+ if hdrs.call
42
+ create_makefile(name)
43
+ return true
44
+ end
45
+ }
46
+
47
+ #
48
+ # Download the headers
49
+ #
50
+ uri_path = "http://ftp.ruby-lang.org/pub/ruby/1.9/" + ruby_dir + ".tar.gz"
51
+ Tempfile.open("ruby-src") { |temp|
52
+
53
+ temp.binmode
54
+ uri = URI.parse(uri_path)
55
+ uri.download(temp)
56
+
57
+ tgz = Zlib::GzipReader.new(File.open(temp, "rb"))
58
+
59
+ FileUtils.mkdir_p(dest_dir)
60
+ Dir.mktmpdir { |dir|
61
+ inc_dir = dir + "/" + ruby_dir + "/*.inc"
62
+ hdr_dir = dir + "/" + ruby_dir + "/*.h"
63
+ Archive::Tar::Minitar.unpack(tgz, dir)
64
+ FileUtils.cp(Dir.glob([ inc_dir, hdr_dir ]), dest_dir)
65
+ }
66
+ }
67
+
68
+ with_cppflags("-I" + dest_dir) {
69
+ if hdrs.call
70
+ create_makefile(name)
71
+ return true
72
+ end
73
+ }
74
+ return false
75
+ end
76
+ module_function :create_makefile_with_core
77
+
78
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_core_source
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - Mark Moseley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-15 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: archive-tar-minitar
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.5.2
24
+ version:
25
+ description: Retrieve Ruby core source files
26
+ email: mark@fast-software.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ - lib/ruby_core_source.rb
34
+ files:
35
+ - README
36
+ - lib/ruby_core_source.rb
37
+ - lib/contrib/uri_ext.rb
38
+ - lib/contrib/progressbar.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/mark-moseley/ruby_core_source
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --charset=UTF-8
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.8.2
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.4
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Retrieve Ruby core source files
67
+ test_files: []
68
+