# # File:: %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_zip.rb # Description:: ZIP builder for convert system. # # Author:: David Muir # Date:: 18 January 2011 # Date:: 24 June 2011 (rubyzip2 update) # # Content convert specifics for ZIP file assets. This class should not be # used directly - use the ConvertSystem class instead. # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'pipeline/config/projects' require 'pipeline/content/content_core' require 'pipeline/os/path' require 'pipeline/projectutil/data_zip' require 'pipeline/resourcing/common' require 'pipeline/resourcing/converter' require 'pipeline/resourcing/path' require 'pipeline/util/environment' include Pipeline #----------------------------------------------------------------------------- # Implementation #----------------------------------------------------------------------------- module Pipeline module Resourcing module Converters # # == Description # Builds any valid ZIP content node. # class ZipConverter < ConverterBase # Setup the converter for a project and branch. def initialize( project, branch ) super( project, branch ) @r = Pipeline::RageUtils.new( @project, @branch.name ) @zip_files = [] end # Return whether this converter can convert the specified content node. def can_convert?( content ) ( content.is_a?( Content::Zip ) and ( content.target.is_a?( IndependentTarget ) ) ) end # Builds the ZIP file with all the added content. This method can raise # a BuildError exception which indicates a fatal error in producing the # ZIP file. def build( &block ) ZipConverter.log.info( 'No ZIP files to build.' ) \ unless ( @zip_files.size > 0 ) env = Environment.new() @branch.fill_env( env ) result = true @zip_files.each do |zipfile| zip_filename = zipfile.content.filename # Ensure our ZIP file is writable. if ( ::File::exists?( zip_filename ) and !::File::writable?( zip_filename ) ) then message = "File #{zip_filename} is not writable. Zip failed." ZipConverter::log().error( message ) throw BuildError.new( zipfile.content, message ) end # Loop through our pack item content nodes. zip_dir = OS::Path::get_directory( zip_filename ) FileUtils::mkdir_p( zip_dir ) unless ( File::directory?( zip_dir ) ) file_list = [] zipfile.items.each do |zip_item| if ( ::File::exists?( zip_item.src ) ) then entry = {} entry[:src] = env.subst( zip_item.src ) entry[:dst] = zip_item.dst file_list << entry yield( zip_item.content, true ) if ( block_given? ) else ZipConverter::log().warn( "Cannot add #{zip_item.src} to ZIP file. File does not exist on disk." ) yield( zip_item.content, false ) if ( block_given? ) end end success = ProjectUtil::data_zip_create( zip_filename, file_list, zipfile.content.compress ) yield( zipfile.content, success ) if ( block_given? ) result = false unless ( success ) end { :success => result } end # Clear the content from the build list. def clear( ) @zip_files.clear( ) end # Add content to be put into this ZIP file. def add_content( content ) path_stack = [] if ( content.is_a?( Pipeline::Content::Zip ) ) then zip = ZipFile.new( content ) if ( content.methods.include?( 'inputs' ) ) then content.inputs.each do |child| add_content_recursive( child, path_stack, zip ) end end @zip_files << zip @zip_files.uniq! true else ZipConverter.log().error( "couldn't convert #{content}" ) false end end # Zip converter's log object. def ZipConverter::log( ) @@log = Log.new( 'convert_zip' ) if ( @@log.nil? ) @@log end #-------------------------------------------------------------------- # Private #-------------------------------------------------------------------- private @@log = nil # Internal class to represent a single ZIP file. class ZipFile attr_reader :content # RPF content node attr_reader :items # Array of PackItem objects def initialize( content ) @content = content @items = [] end end # Internal class to represent a single file being added to an ZIP file. # We store the source and destination paths and the content node the # file came from. class ZipFileItem attr_reader :content attr_reader :src attr_reader :dst def initialize( content, src, dst ) @content = content @src = src @dst = dst end end # Add content to be put into this RPF file. def add_content_recursive( content, path_stack, zipfile ) if ( content.is_a?( Pipeline::Content::File ) ) then pre_handle_file_node( content, path_stack, zipfile ) elsif ( content.is_a?( Pipeline::Content::Group ) ) then pre_handle_group_node( content, path_stack, zipfile ) end content.inputs.each do |child| add_content_recursive( child, path_stack, zipfile ) end if ( content.methods.include?( 'children' ) ) then content.children.each do |child| add_content_recursive( child, path_stack, zipfile ) end end if ( content.is_a?( Pipeline::Content::Group ) ) then post_handle_group_node( content, path_stack, zipfile ) end end # def pre_handle_file_node( content, path_stack, zipfile ) src = "" dst = "" @branch.in_env() do | e | src = e.subst( content.filename ) dst = e.subst( "#{OS::Path.combine( OS::Path.combine(*path_stack), OS::Path::get_filename( content.filename ) )}" ) end zipfile.items << ZipFileItem.new( content, src, dst ) end # def pre_handle_group_node( content, path_stack, zipfile ) if ( nil != content.path and '' != content.path ) then path_stack.push( content.path ) end end # def post_handle_group_node( content, path_stack, zipfile ) if ( nil != content.path and '' != content.path ) then path_stack.pop() end end end # ZipConverter class end # Converters module end # Resourcing module end # Pipeline module # %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_zip.rb