In Files

  • rubygems/package.rb
  • rubygems/package/digest_io.rb
  • rubygems/package/old.rb
  • rubygems/package/tar_header.rb
  • rubygems/package/tar_reader.rb
  • rubygems/package/tar_reader/entry.rb
  • rubygems/package/tar_test_case.rb
  • rubygems/package/tar_writer.rb

Class/Module Index [+]

Quicksearch

Gem::Package

Attributes

checksums[R]

Checksums for the contents of the package

files[R]

The files in this package. This is not the contents of the gem, just the files in the top-level container.

security_policy[RW]

The security policy used for verifying the contents of this package.

spec[W]

Sets the Gem::Specification to use to build this package.

Public Class Methods

build(spec, skip_validation=false) click to toggle source
 
               # 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
            
new(gem) click to toggle source

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
            

Public Instance Methods

add_checksums(tar) click to toggle source

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
            
build(skip_validation = false) click to toggle source

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
            
contents() click to toggle source

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
            
extract_files(destination_dir, pattern = "*") click to toggle source

Extracts the files in this package into destination_dir

If pattern is specified, only entries matching that glob will be extracted.

 
               # File rubygems/package.rb, line 309
def extract_files destination_dir, pattern = "*"
  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, pattern

      return # ignore further entries
    end
  end
end
            
gzip_to(io) click to toggle source

Gzips content written to gz_io to io.

 
               # File rubygems/package.rb, line 373
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
            
read_checksums(gem) click to toggle source

Reads and loads checksums.yaml.gz from the tar file gem

 
               # File rubygems/package.rb, line 438
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
            
setup_signer() click to toggle source

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 452
def setup_signer
  passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE']
  if @spec.signing_key then
    @signer = Gem::Security::Signer.new @spec.signing_key, @spec.cert_chain, passphrase
    @spec.signing_key = nil
    @spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_s }
  else
    @signer = Gem::Security::Signer.new nil, nil, passphrase
    @spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_pem } if
      @signer.cert_chain
  end
end
            
spec() click to toggle source

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 472
def spec
  verify unless @spec

  @spec
end
            
verify() click to toggle source

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 488
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
            
verify_entry(entry) click to toggle source

Verifies entry in a .gem file.

 
               # File rubygems/package.rb, line 538
def verify_entry entry
  file_name = entry.full_name
  @files << file_name

  case file_name
  when /\.sig$/ then
    @signatures[$`] = entry.read if @security_policy
    return
  else
    digest entry
  end

  case file_name
  when /^metadata(.gz)?$/ then
    load_spec entry
  when 'data.tar.gz' then
    verify_gz entry
  end
rescue => e
  message = "package is corrupt, exception while verifying: " +
            "#{e.message} (#{e.class})"
  raise Gem::Package::FormatError.new message, @gem
end
            
verify_files(gem) click to toggle source

Verifies the files of the gem

 
               # File rubygems/package.rb, line 565
def verify_files gem
  gem.each do |entry|
    verify_entry entry
  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
            

Protected Instance Methods

initialize(gem) click to toggle source

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 visit Documenting-ruby.org.

blog comments powered by Disqus