PageRenderTime 116ms CodeModel.GetById 95ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/tools/Ruby/lib/ruby/site_ruby/1.8/rubygems/old_format.rb

http://github.com/agross/netopenspace
Ruby | 153 lines | 78 code | 27 blank | 48 comment | 9 complexity | 3a09372146a1a0eaa91369bc64f83fe3 MD5 | raw file
  1#--
  2# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
  3# All rights reserved.
  4# See LICENSE.txt for permissions.
  5#++
  6
  7require 'rubygems'
  8
  9##
 10# The format class knows the guts of the RubyGem .gem file format and provides
 11# the capability to read gem files
 12
 13class Gem::OldFormat
 14
 15  attr_accessor :spec, :file_entries, :gem_path
 16
 17  ##
 18  # Constructs an instance of a Format object, representing the gem's data
 19  # structure.
 20  #
 21  # gem:: [String] The file name of the gem
 22
 23  def initialize(gem_path)
 24    require 'fileutils'
 25    require 'zlib'
 26    Gem.load_yaml
 27
 28    @gem_path = gem_path
 29  end
 30
 31  ##
 32  # Reads the named gem file and returns a Format object, representing the
 33  # data from the gem file
 34  #
 35  # file_path:: [String] Path to the gem file
 36
 37  def self.from_file_by_path(file_path)
 38    unless File.exist?(file_path)
 39      raise Gem::Exception, "Cannot load gem file [#{file_path}]"
 40    end
 41
 42    File.open(file_path, 'rb') do |file|
 43      from_io(file, file_path)
 44    end
 45  end
 46
 47  ##
 48  # Reads a gem from an io stream and returns a Format object, representing
 49  # the data from the gem file
 50  #
 51  # io:: [IO] Stream from which to read the gem
 52
 53  def self.from_io(io, gem_path="(io)")
 54    format = self.new(gem_path)
 55    skip_ruby(io)
 56    format.spec = read_spec(io)
 57    format.file_entries = []
 58    read_files_from_gem(io) do |entry, file_data|
 59      format.file_entries << [entry, file_data]
 60    end
 61    format
 62  end
 63
 64  private
 65
 66  ##
 67  # Skips the Ruby self-install header.  After calling this method, the
 68  # IO index will be set after the Ruby code.
 69  #
 70  # file:: [IO] The IO to process (skip the Ruby code)
 71
 72  def self.skip_ruby(file)
 73    end_seen = false
 74    loop {
 75      line = file.gets
 76      if(line == nil || line.chomp == "__END__") then
 77        end_seen = true
 78        break
 79      end
 80    }
 81
 82    if end_seen == false then
 83      raise Gem::Exception.new("Failed to find end of ruby script while reading gem")
 84    end
 85  end
 86
 87  ##
 88  # Reads the specification YAML from the supplied IO and constructs
 89  # a Gem::Specification from it.  After calling this method, the
 90  # IO index will be set after the specification header.
 91  #
 92  # file:: [IO] The IO to process
 93
 94  def self.read_spec(file)
 95    yaml = ''
 96
 97    read_until_dashes file do |line|
 98      yaml << line
 99    end
100
101    Gem::Specification.from_yaml yaml
102  rescue YAML::Error => e
103    raise Gem::Exception, "Failed to parse gem specification out of gem file"
104  rescue ArgumentError => e
105    raise Gem::Exception, "Failed to parse gem specification out of gem file"
106  end
107
108  ##
109  # Reads lines from the supplied IO until a end-of-yaml (---) is
110  # reached
111  #
112  # file:: [IO] The IO to process
113  # block:: [String] The read line
114
115  def self.read_until_dashes(file)
116    while((line = file.gets) && line.chomp.strip != "---") do
117      yield line
118    end
119  end
120
121  ##
122  # Reads the embedded file data from a gem file, yielding an entry
123  # containing metadata about the file and the file contents themselves
124  # for each file that's archived in the gem.
125  # NOTE: Many of these methods should be extracted into some kind of
126  # Gem file read/writer
127  #
128  # gem_file:: [IO] The IO to process
129
130  def self.read_files_from_gem(gem_file)
131    errstr = "Error reading files from gem"
132    header_yaml = ''
133    begin
134      self.read_until_dashes(gem_file) do |line|
135        header_yaml << line
136      end
137      header = YAML.load(header_yaml)
138      raise Gem::Exception, errstr unless header
139
140      header.each do |entry|
141        file_data = ''
142        self.read_until_dashes(gem_file) do |line|
143          file_data << line
144        end
145        yield [entry, Zlib::Inflate.inflate(file_data.strip.unpack("m")[0])]
146      end
147    rescue Zlib::DataError
148      raise Gem::Exception, errstr
149    end
150  end
151
152end
153