diff options
Diffstat (limited to 'trunk/lib/rubygems/package/tar_output.rb')
-rw-r--r-- | trunk/lib/rubygems/package/tar_output.rb | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/trunk/lib/rubygems/package/tar_output.rb b/trunk/lib/rubygems/package/tar_output.rb new file mode 100644 index 0000000000..b22f7dd86b --- /dev/null +++ b/trunk/lib/rubygems/package/tar_output.rb @@ -0,0 +1,143 @@ +#++ +# Copyright (C) 2004 Mauricio Julio Fernández Pradier +# See LICENSE.txt for additional licensing information. +#-- + +require 'rubygems/package' + +## +# TarOutput is a wrapper to TarWriter that builds gem-format tar file. +# +# Gem-format tar files contain the following files: +# [data.tar.gz] A gzipped tar file containing the files that compose the gem +# which will be extracted into the gem/ dir on installation. +# [metadata.gz] A YAML format Gem::Specification. +# [data.tar.gz.sig] A signature for the gem's data.tar.gz. +# [metadata.gz.sig] A signature for the gem's metadata.gz. +# +# See TarOutput::open for usage details. + +class Gem::Package::TarOutput + + ## + # Creates a new TarOutput which will yield a TarWriter object for the + # data.tar.gz portion of a gem-format tar file. + # + # See #initialize for details on +io+ and +signer+. + # + # See #add_gem_contents for details on adding metadata to the tar file. + + def self.open(io, signer = nil, &block) # :yield: data_tar_writer + tar_outputter = new io, signer + tar_outputter.add_gem_contents(&block) + tar_outputter.add_metadata + tar_outputter.add_signatures + + ensure + tar_outputter.close + end + + ## + # Creates a new TarOutput that will write a gem-format tar file to +io+. If + # +signer+ is given, the data.tar.gz and metadata.gz will be signed and + # the signatures will be added to the tar file. + + def initialize(io, signer) + @io = io + @signer = signer + + @tar_writer = Gem::Package::TarWriter.new @io + + @metadata = nil + + @data_signature = nil + @meta_signature = nil + end + + ## + # Yields a TarWriter for the data.tar.gz inside a gem-format tar file. + # The yielded TarWriter has been extended with a #metadata= method for + # attaching a YAML format Gem::Specification which will be written by + # add_metadata. + + def add_gem_contents + @tar_writer.add_file "data.tar.gz", 0644 do |inner| + sio = @signer ? StringIO.new : nil + Zlib::GzipWriter.wrap(sio || inner) do |os| + + Gem::Package::TarWriter.new os do |data_tar_writer| + def data_tar_writer.metadata() @metadata end + def data_tar_writer.metadata=(metadata) @metadata = metadata end + + yield data_tar_writer + + @metadata = data_tar_writer.metadata + end + end + + # if we have a signing key, then sign the data + # digest and return the signature + if @signer then + digest = Gem::Security::OPT[:dgst_algo].digest sio.string + @data_signature = @signer.sign digest + inner.write sio.string + end + end + + self + end + + ## + # Adds metadata.gz to the gem-format tar file which was saved from a + # previous #add_gem_contents call. + + def add_metadata + return if @metadata.nil? + + @tar_writer.add_file "metadata.gz", 0644 do |io| + begin + sio = @signer ? StringIO.new : nil + gzos = Zlib::GzipWriter.new(sio || io) + gzos.write @metadata + ensure + gzos.flush + gzos.finish + + # if we have a signing key, then sign the metadata digest and return + # the signature + if @signer then + digest = Gem::Security::OPT[:dgst_algo].digest sio.string + @meta_signature = @signer.sign digest + io.write sio.string + end + end + end + end + + ## + # Adds data.tar.gz.sig and metadata.gz.sig to the gem-format tar files if + # a Gem::Security::Signer was sent to initialize. + + def add_signatures + if @data_signature then + @tar_writer.add_file 'data.tar.gz.sig', 0644 do |io| + io.write @data_signature + end + end + + if @meta_signature then + @tar_writer.add_file 'metadata.gz.sig', 0644 do |io| + io.write @meta_signature + end + end + end + + ## + # Closes the TarOutput. + + def close + @tar_writer.close + end + +end + |