Geminstaller C0 Coverage Information - RCov

spec/fixture/rubygems_dist/rubygems-trunk/lib/rubygems/package/tar_input.rb

Name Total Lines Lines of Code Total Coverage Code Coverage
spec/fixture/rubygems_dist/rubygems-trunk/lib/rubygems/package/tar_input.rb 219 149
53.88%
47.65%

Key

Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.

Coverage Details

1 # -*- coding: iso-8859-1 -*-
2 #++
3 # Copyright (C) 2004 Mauricio Julio Fernández Pradier
4 # See LICENSE.txt for additional licensing information.
5 #--
6 
7 class Gem::Package::TarInput
8 
9   include Gem::Package::FSyncDir
10   include Enumerable
11 
12   attr_reader :metadata
13 
14   private_class_method :new
15 
16   def self.open(io, security_policy = nil,  &block)
17     is = new io, security_policy
18 
19     yield is
20   ensure
21     is.close if is
22   end
23 
24   def initialize(io, security_policy = nil)
25     @io = io
26     @tarreader = Gem::Package::TarReader.new @io
27     has_meta = false
28 
29     data_sig, meta_sig, data_dgst, meta_dgst = nil, nil, nil, nil
30     dgst_algo = security_policy ? Gem::Security::OPT[:dgst_algo] : nil
31 
32     @tarreader.each do |entry|
33       case entry.full_name
34       when "metadata"
35         @metadata = load_gemspec entry.read
36         has_meta = true
37       when "metadata.gz"
38         begin
39           # if we have a security_policy, then pre-read the metadata file
40           # and calculate it's digest
41           sio = nil
42           if security_policy
43             Gem.ensure_ssl_available
44             sio = StringIO.new(entry.read)
45             meta_dgst = dgst_algo.digest(sio.string)
46             sio.rewind
47           end
48 
49           gzis = Zlib::GzipReader.new(sio || entry)
50           # YAML wants an instance of IO
51           @metadata = load_gemspec(gzis)
52           has_meta = true
53         ensure
54           gzis.close unless gzis.nil?
55         end
56       when 'metadata.gz.sig'
57         meta_sig = entry.read
58       when 'data.tar.gz.sig'
59         data_sig = entry.read
60       when 'data.tar.gz'
61         if security_policy
62           Gem.ensure_ssl_available
63           data_dgst = dgst_algo.digest(entry.read)
64         end
65       end
66     end
67 
68     if security_policy then
69       Gem.ensure_ssl_available
70 
71       # map trust policy from string to actual class (or a serialized YAML
72       # file, if that exists)
73       if String === security_policy then
74         if Gem::Security::Policies.key? security_policy then
75           # load one of the pre-defined security policies
76           security_policy = Gem::Security::Policies[security_policy]
77         elsif File.exist? security_policy then
78           # FIXME: this doesn't work yet
79           security_policy = YAML.load File.read(security_policy)
80         else
81           raise Gem::Exception, "Unknown trust policy '#{security_policy}'"
82         end
83       end
84 
85       if data_sig && data_dgst && meta_sig && meta_dgst then
86         # the user has a trust policy, and we have a signed gem
87         # file, so use the trust policy to verify the gem signature
88 
89         begin
90           security_policy.verify_gem(data_sig, data_dgst, @metadata.cert_chain)
91         rescue Exception => e
92           raise "Couldn't verify data signature: #{e}"
93         end
94 
95         begin
96           security_policy.verify_gem(meta_sig, meta_dgst, @metadata.cert_chain)
97         rescue Exception => e
98           raise "Couldn't verify metadata signature: #{e}"
99         end
100       elsif security_policy.only_signed
101         raise Gem::Exception, "Unsigned gem"
102       else
103         # FIXME: should display warning here (trust policy, but
104         # either unsigned or badly signed gem file)
105       end
106     end
107 
108     @tarreader.rewind
109     @fileops = Gem::FileOperations.new
110 
111     raise Gem::Package::FormatError, "No metadata found!" unless has_meta
112   end
113 
114   def close
115     @io.close
116     @tarreader.close
117   end
118 
119   def each(&block)
120     @tarreader.each do |entry|
121       next unless entry.full_name == "data.tar.gz"
122       is = zipped_stream entry
123 
124       begin
125         Gem::Package::TarReader.new is do |inner|
126           inner.each(&block)
127         end
128       ensure
129         is.close if is
130       end
131     end
132 
133     @tarreader.rewind
134   end
135 
136   def extract_entry(destdir, entry, expected_md5sum = nil)
137     if entry.directory? then
138       dest = File.join destdir, entry.full_name
139 
140       if File.directory? dest then
141         @fileops.chmod entry.header.mode, dest, :verbose => false
142       else
143         @fileops.mkdir_p dest, :mode => entry.header.mode, :verbose => false
144       end
145 
146       fsync_dir dest
147       fsync_dir File.join(dest, "..")
148 
149       return
150     end
151 
152     # it's a file
153     md5 = Digest::MD5.new if expected_md5sum
154     destdir = File.join destdir, File.dirname(entry.full_name)
155     @fileops.mkdir_p destdir, :mode => 0755, :verbose => false
156     destfile = File.join destdir, File.basename(entry.full_name)
157     @fileops.chmod 0600, destfile, :verbose => false rescue nil # Errno::ENOENT
158 
159     open destfile, "wb", entry.header.mode do |os|
160       loop do
161         data = entry.read 4096
162         break unless data
163         # HACK shouldn't we check the MD5 before writing to disk?
164         md5 << data if expected_md5sum
165         os.write(data)
166       end
167 
168       os.fsync
169     end
170 
171     @fileops.chmod entry.header.mode, destfile, :verbose => false
172     fsync_dir File.dirname(destfile)
173     fsync_dir File.join(File.dirname(destfile), "..")
174 
175     if expected_md5sum && expected_md5sum != md5.hexdigest then
176       raise Gem::Package::BadCheckSum
177     end
178   end
179 
180   # Attempt to YAML-load a gemspec from the given _io_ parameter.  Return
181   # nil if it fails.
182   def load_gemspec(io)
183     Gem::Specification.from_yaml io
184   rescue Gem::Exception
185     nil
186   end
187 
188   ##
189   # Return an IO stream for the zipped entry.
190   #
191   # NOTE:  Originally this method used two approaches, Return a GZipReader
192   # directly, or read the GZipReader into a string and return a StringIO on
193   # the string.  The string IO approach was used for versions of ZLib before
194   # 1.2.1 to avoid buffer errors on windows machines.  Then we found that
195   # errors happened with 1.2.1 as well, so we changed the condition.  Then
196   # we discovered errors occurred with versions as late as 1.2.3.  At this
197   # point (after some benchmarking to show we weren't seriously crippling
198   # the unpacking speed) we threw our hands in the air and declared that
199   # this method would use the String IO approach on all platforms at all
200   # times.  And that's the way it is.
201 
202   def zipped_stream(entry)
203     if defined? Rubinius or defined? Maglev then
204       # these implementations have working Zlib
205       zis = Zlib::GzipReader.new entry
206       dis = zis.read
207       is = StringIO.new(dis)
208     else
209       # This is Jamis Buck's Zlib workaround for some unknown issue
210       entry.read(10) # skip the gzip header
211       zis = Zlib::Inflate.new(-Zlib::MAX_WBITS)
212       is = StringIO.new(zis.inflate(entry.read))
213     end
214   ensure
215     zis.finish if zis
216   end
217 
218 end
219 

Generated on Mon May 10 23:40:28 -0700 2010 with rcov 0.9.8