Files
gtav-src/tools_ng/lib/pipeline/resourcing/converters/converter_zip.rb
T
2025-09-29 00:52:08 +02:00

222 lines
6.4 KiB
Ruby
Executable File

#
# File:: %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_zip.rb
# Description:: ZIP builder for convert system.
#
# Author:: David Muir <david.muir@rockstarnorth.com>
# 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