Class: Gem::Package::TarReader

Inherits:
Object
  • Object
show all
Includes:
Gem::Package
Defined in:
lib/rubygems/package/tar_reader.rb

Overview

TarReader reads tar files and allows iteration over their items

Defined Under Namespace

Classes: Entry, UnexpectedEOF

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Gem::Package

open, pack

Constructor Details

#initialize(io) ⇒ TarReader

Creates a new tar file reader on io which needs to respond to #pos, #eof?, #read, #getc and #pos=



40
41
42
43
# File 'lib/rubygems/package/tar_reader.rb', line 40

def initialize(io)
  @io = io
  @init_pos = io.pos
end

Class Method Details

.new(io) ⇒ Object

Creates a new TarReader on io and yields it to the block, if given.



22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/rubygems/package/tar_reader.rb', line 22

def self.new(io)
  reader = super

  return reader unless block_given?

  begin
    yield reader
  ensure
    reader.close
  end

  nil
end

Instance Method Details

#closeObject

Close the tar file



48
49
# File 'lib/rubygems/package/tar_reader.rb', line 48

def close
end

#eachObject Also known as: each_entry

Iterates over files in the tarball yielding each entry



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
# File 'lib/rubygems/package/tar_reader.rb', line 54

def each
  loop do
    return if @io.eof?

    header = Gem::Package::TarHeader.from @io
    return if header.empty?

    entry = Gem::Package::TarReader::Entry.new header, @io
    size = entry.header.size

    yield entry

    skip = (512 - (size % 512)) % 512
    pending = size - entry.bytes_read

    begin
      # avoid reading...
      @io.seek pending, IO::SEEK_CUR
      pending = 0
    rescue Errno::EINVAL, NameError
      while pending > 0 do
        bytes_read = @io.read([pending, 4096].min).size
        raise UnexpectedEOF if @io.eof?
        pending -= bytes_read
      end
    end

    @io.read skip # discard trailing zeros

    # make sure nobody can use #read, #getc or #rewind anymore
    entry.close
  end
end

#rewindObject

NOTE: Do not call #rewind during #each



93
94
95
96
97
98
99
100
101
# File 'lib/rubygems/package/tar_reader.rb', line 93

def rewind
  if @init_pos == 0 then
    raise Gem::Package::NonSeekableIO unless @io.respond_to? :rewind
    @io.rewind
  else
    raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos=
    @io.pos = @init_pos
  end
end