Imported File#ftype spec from rubyspecs.
[rbx.git] / lib / rubygems / package / tar_output.rb
blobb22f7dd86bb55c9cc784f2171fef138af93fac83
1 #++
2 # Copyright (C) 2004 Mauricio Julio Fernández Pradier
3 # See LICENSE.txt for additional licensing information.
4 #--
6 require 'rubygems/package'
8 ##
9 # TarOutput is a wrapper to TarWriter that builds gem-format tar file.
11 # Gem-format tar files contain the following files:
12 # [data.tar.gz] A gzipped tar file containing the files that compose the gem
13 #               which will be extracted into the gem/ dir on installation.
14 # [metadata.gz] A YAML format Gem::Specification.
15 # [data.tar.gz.sig] A signature for the gem's data.tar.gz.
16 # [metadata.gz.sig] A signature for the gem's metadata.gz.
18 # See TarOutput::open for usage details.
20 class Gem::Package::TarOutput
22   ##
23   # Creates a new TarOutput which will yield a TarWriter object for the
24   # data.tar.gz portion of a gem-format tar file.
25   #
26   # See #initialize for details on +io+ and +signer+.
27   #
28   # See #add_gem_contents for details on adding metadata to the tar file.
30   def self.open(io, signer = nil, &block) # :yield: data_tar_writer
31     tar_outputter = new io, signer
32     tar_outputter.add_gem_contents(&block)
33     tar_outputter.add_metadata
34     tar_outputter.add_signatures
36   ensure
37     tar_outputter.close
38   end
40   ##
41   # Creates a new TarOutput that will write a gem-format tar file to +io+.  If
42   # +signer+ is given, the data.tar.gz and metadata.gz will be signed and
43   # the signatures will be added to the tar file.
45   def initialize(io, signer)
46     @io = io
47     @signer = signer
49     @tar_writer = Gem::Package::TarWriter.new @io
51     @metadata = nil
53     @data_signature = nil
54     @meta_signature = nil
55   end
57   ##
58   # Yields a TarWriter for the data.tar.gz inside a gem-format tar file.
59   # The yielded TarWriter has been extended with a #metadata= method for
60   # attaching a YAML format Gem::Specification which will be written by
61   # add_metadata.
63   def add_gem_contents
64     @tar_writer.add_file "data.tar.gz", 0644 do |inner|
65       sio = @signer ? StringIO.new : nil
66       Zlib::GzipWriter.wrap(sio || inner) do |os|
68         Gem::Package::TarWriter.new os do |data_tar_writer|
69           def data_tar_writer.metadata() @metadata end
70           def data_tar_writer.metadata=(metadata) @metadata = metadata end
72           yield data_tar_writer
74           @metadata = data_tar_writer.metadata
75         end
76       end
78       # if we have a signing key, then sign the data
79       # digest and return the signature
80       if @signer then
81         digest = Gem::Security::OPT[:dgst_algo].digest sio.string
82         @data_signature = @signer.sign digest
83         inner.write sio.string
84       end
85     end
87     self
88   end
90   ##
91   # Adds metadata.gz to the gem-format tar file which was saved from a
92   # previous #add_gem_contents call.
94   def add_metadata
95     return if @metadata.nil?
97     @tar_writer.add_file "metadata.gz", 0644 do |io|
98       begin
99         sio = @signer ? StringIO.new : nil
100         gzos = Zlib::GzipWriter.new(sio || io)
101         gzos.write @metadata
102       ensure
103         gzos.flush
104         gzos.finish
106         # if we have a signing key, then sign the metadata digest and return
107         # the signature
108         if @signer then
109           digest = Gem::Security::OPT[:dgst_algo].digest sio.string
110           @meta_signature = @signer.sign digest
111           io.write sio.string
112         end
113       end
114     end
115   end
117   ##
118   # Adds data.tar.gz.sig and metadata.gz.sig to the gem-format tar files if
119   # a Gem::Security::Signer was sent to initialize.
121   def add_signatures
122     if @data_signature then
123       @tar_writer.add_file 'data.tar.gz.sig', 0644 do |io|
124         io.write @data_signature
125       end
126     end
128     if @meta_signature then
129       @tar_writer.add_file 'metadata.gz.sig', 0644 do |io|
130         io.write @meta_signature
131       end
132     end
133   end
135   ##
136   # Closes the TarOutput.
138   def close
139     @tar_writer.close
140   end