Class: Gem::Package::Old

Inherits:
Gem::Package show all
Defined in:
lib/rubygems/package/old.rb

Overview

The format class knows the guts of the ancient .gem file format and provides the capability to read such ancient gems.

Please pretend this doesn’t exist.

Instance Attribute Summary

Attributes inherited from Gem::Package

#build_time, #checksums, #files, #security_policy

Instance Method Summary collapse

Methods inherited from Gem::Package

#add_checksums, #add_contents, #add_files, #add_metadata, build, #build, #digest, #extract_tar_gz, #gzip_to, #install_location, #load_spec, new, #open_tar_gz, #read_checksums, #setup_signer, #verify_checksums, #verify_files, #verify_gz

Methods included from UserInteraction

#alert, #alert_error, #alert_warning, #ask, #ask_for_password, #ask_yes_no, #choose_from_list, #say, #terminate_interaction

Methods included from DefaultUserInteraction

ui, #ui, ui=, #ui=, use_ui, #use_ui

Constructor Details

#initialize(gem) ⇒ Old

Creates a new old-format package reader for gem. Old-format packages cannot be written.



21
22
23
24
25
26
27
28
29
# File 'lib/rubygems/package/old.rb', line 21

def initialize gem
  require 'fileutils'
  require 'zlib'
  Gem.load_yaml

  @gem      = gem
  @contents = nil
  @spec     = nil
end

Instance Method Details

#contentsObject

A list of file names contained in this gem



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rubygems/package/old.rb', line 34

def contents
  verify

  return @contents if @contents

  open @gem, 'rb' do |io|
    read_until_dashes io # spec
    header = file_list io

    @contents = header.map { |file| file['path'] }
  end
end

#extract_files(destination_dir) ⇒ Object

Extracts the files in this package into destination_dir



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/rubygems/package/old.rb', line 50

def extract_files destination_dir
  verify

  errstr = "Error reading files from gem"

  open @gem, 'rb' do |io|
    read_until_dashes io # spec
    header = file_list io
    raise Gem::Exception, errstr unless header

    header.each do |entry|
      full_name = entry['path']

      destination = install_location full_name, destination_dir

      file_data = ''

      read_until_dashes io do |line|
        file_data << line
      end

      file_data = file_data.strip.unpack("m")[0]
      file_data = Zlib::Inflate.inflate file_data

      raise Gem::Package::FormatError, "#{full_name} in #{@gem} is corrupt" if
        file_data.length != entry['size'].to_i

      FileUtils.rm_rf destination

      FileUtils.mkdir_p File.dirname destination

      open destination, 'wb', entry['mode'] do |out|
        out.write file_data
      end

      say destination if Gem.configuration.really_verbose
    end
  end
rescue Zlib::DataError
  raise Gem::Exception, errstr
end

#file_list(io) ⇒ Object

Reads the file list section from the old-format gem io



95
96
97
98
99
100
101
102
103
# File 'lib/rubygems/package/old.rb', line 95

def file_list io # :nodoc:
  header = ''

  read_until_dashes io do |line|
    header << line
  end

  YAML.load header
end

#read_until_dashes(io) ⇒ Object

Reads lines until a “—” separator is found



108
109
110
111
112
# File 'lib/rubygems/package/old.rb', line 108

def read_until_dashes io # :nodoc:
  while (line = io.gets) && line.chomp.strip != "---" do
    yield line if block_given?
  end
end

#skip_ruby(io) ⇒ Object

Skips the Ruby self-install header in io.

Raises:



117
118
119
120
121
122
123
124
125
126
# File 'lib/rubygems/package/old.rb', line 117

def skip_ruby io # :nodoc:
  loop do
    line = io.gets

    return if line.chomp == '__END__'
    break unless line
  end

  raise Gem::Exception, "Failed to find end of ruby script while reading gem"
end

#specObject

The specification for this gem



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/rubygems/package/old.rb', line 131

def spec
  verify

  return @spec if @spec

  yaml = ''

  open @gem, 'rb' do |io|
    skip_ruby io
    read_until_dashes io do |line|
      yaml << line
    end
  end

  yaml_error = if RUBY_VERSION < '1.8' then
                 YAML::ParseError
               elsif YAML::ENGINE.yamler == 'syck' then
                 YAML::ParseError
               else
                 YAML::SyntaxError
               end

  begin
    @spec = Gem::Specification.from_yaml yaml
  rescue yaml_error => e
    raise Gem::Exception, "Failed to parse gem specification out of gem file"
  end
rescue ArgumentError => e
  raise Gem::Exception, "Failed to parse gem specification out of gem file"
end

#verifyObject

Raises an exception if a security policy that verifies data is active. Old format gems cannot be verified as signed.



166
167
168
169
170
171
172
173
174
# File 'lib/rubygems/package/old.rb', line 166

def verify
  return true unless @security_policy

  raise Gem::Security::Exception,
        'old format gems do not contain signatures and cannot be verified' if
    @security_policy.verify_data

  true
end