# File rubygems/package.rb, line 105
def self.build spec, skip_validation=false
gem_file = spec.file_name
package = new gem_file
package.spec = spec
package.build skip_validation
gem_file
end
Creates a new Gem::Package for the file at
gem.
If gem is an existing file in the old format a Gem::Package::Old will be returned.
# File rubygems/package.rb, line 121
def self.new gem
return super unless Gem::Package == self
return super unless File.exist? gem
start = File.read gem, 20
return super unless start
return super unless start.include? 'MD5SUM ='
Gem::Package::Old.new gem
end
Adds a checksum for each entry in the gem to checksums.yaml.gz.
# File rubygems/package.rb, line 153
def add_checksums tar
Gem.load_yaml
checksums_by_algorithm = Hash.new { |h, algorithm| h[algorithm] = {} }
@checksums.each do |name, digests|
digests.each do |algorithm, digest|
checksums_by_algorithm[algorithm][name] = digest.hexdigest
end
end
tar.add_file_signed 'checksums.yaml.gz', 0444, @signer do |io|
gzip_to io do |gz_io|
YAML.dump checksums_by_algorithm, gz_io
end
end
end
Builds this package based on the specification set by spec=
# File rubygems/package.rb, line 220
def build skip_validation = false
Gem.load_yaml
require 'rubygems/security'
@spec.mark_version
@spec.validate unless skip_validation
setup_signer
open @gem, 'wb' do |gem_io|
Gem::Package::TarWriter.new gem_io do |gem|
add_metadata gem
add_contents gem
add_checksums gem
end
end
say <<-EOM
Successfully built RubyGem
Name: #{@spec.name}
Version: #{@spec.version}
File: #{File.basename @spec.cache_file}
EOM
ensure
@signer = nil
end
A list of file names contained in this gem
# File rubygems/package.rb, line 250
def contents
return @contents if @contents
verify unless @spec
@contents = []
open @gem, 'rb' do |io|
gem_tar = Gem::Package::TarReader.new io
gem_tar.each do |entry|
next unless entry.full_name == 'data.tar.gz'
open_tar_gz entry do |pkg_tar|
pkg_tar.each do |contents_entry|
@contents << contents_entry.full_name
end
end
return @contents
end
end
end
Extracts the files in this package into destination_dir
# File rubygems/package.rb, line 301
def extract_files destination_dir
verify unless @spec
FileUtils.mkdir_p destination_dir
open @gem, 'rb' do |io|
reader = Gem::Package::TarReader.new io
reader.each do |entry|
next unless entry.full_name == 'data.tar.gz'
extract_tar_gz entry, destination_dir
return # ignore further entries
end
end
end
Gzips content written to gz_io to io.
# File rubygems/package.rb, line 352
def gzip_to io # :yields: gz_io
gz_io = Zlib::GzipWriter.new io, Zlib::BEST_COMPRESSION
gz_io.mtime = @build_time
yield gz_io
ensure
gz_io.close
end
Reads and loads checksums.yaml.gz from the tar file gem
# File rubygems/package.rb, line 416
def read_checksums gem
Gem.load_yaml
@checksums = gem.seek 'checksums.yaml.gz' do |entry|
Zlib::GzipReader.wrap entry do |gz_io|
YAML.load gz_io.read
end
end
end
Prepares the gem for signing and checksum generation. If a signing certificate and key are not present only checksum generation is set up.
# File rubygems/package.rb, line 430
def setup_signer
if @spec.signing_key then
@signer = Gem::Security::Signer.new @spec.signing_key, @spec.cert_chain
@spec.signing_key = nil
@spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_s }
else
@signer = Gem::Security::Signer.new nil, nil
@spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_pem } if
@signer.cert_chain
end
end
The spec for this gem.
If this is a package for a built gem the spec is loaded from the gem and returned. If this is a package for a gem being built the provided spec is returned.
# File rubygems/package.rb, line 449
def spec
verify unless @spec
@spec
end
Verifies that this gem:
Contains a valid gem specification
Contains a contents archive
The contents archive is not corrupt
After verification the gem specification from the gem is available from spec
# File rubygems/package.rb, line 465
def verify
@files = []
@spec = nil
open @gem, 'rb' do |io|
Gem::Package::TarReader.new io do |reader|
read_checksums reader
verify_files reader
end
end
verify_checksums @digests, @checksums
@security_policy.verify_signatures @spec, @digests, @signatures if
@security_policy
true
rescue Gem::Security::Exception
@spec = nil
@files = []
raise
rescue Errno::ENOENT => e
raise Gem::Package::FormatError.new e.message
rescue Gem::Package::TarInvalidError => e
raise Gem::Package::FormatError.new e.message, @gem
end
Verifies the files of the gem
# File rubygems/package.rb, line 515
def verify_files gem
gem.each do |entry|
file_name = entry.full_name
@files << file_name
case file_name
when /\.sig$/ then
@signatures[$`] = entry.read if @security_policy
next
else
digest entry
end
case file_name
when /^metadata(.gz)?$/ then
load_spec entry
when 'data.tar.gz' then
verify_gz entry
end
end
unless @spec then
raise Gem::Package::FormatError.new 'package metadata is missing', @gem
end
unless @files.include? 'data.tar.gz' then
raise Gem::Package::FormatError.new 'package content (data.tar.gz) is missing', @gem
end
end
Creates a new package that will read or write to the file gem.
# File rubygems/package.rb, line 136
def initialize gem # :notnew:
@gem = gem
@build_time = Time.now
@checksums = {}
@contents = nil
@digests = Hash.new { |h, algorithm| h[algorithm] = {} }
@files = nil
@security_policy = nil
@signatures = {}
@signer = nil
@spec = nil
end
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please see Improve the docs, or visit Documenting-ruby.org.