Files
2025-09-29 00:52:08 +02:00

257 lines
7.5 KiB
Ruby
Executable File

#
# File:: %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_pack.rb
# Description:: RPF builder for convert system.
#
# Author:: Luke Openshaw <luke.openshaw@rockstarnorth.com>
# Author:: David Muir <david.muir@rockstarnorth.com>
# Date:: 14 July 2008
#
# Content convert specifics for RPF 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_rpf'
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 RPF content node.
#
class PackConverter < ConverterBase
#
# Setup the converter for a project and branch.
#
def initialize( project, branch )
super( project, branch )
@r = Pipeline::RageUtils.new( @project, @branch.name )
@rpf_files = []
end
# Return whether this converter can convert the specified content node.
def can_convert?( content )
( content.is_a?( Content::RPF ) and ( content.target.is_a?( IndependentTarget ) ) )
end
#
# Builds the RPF file with all the added content. This method can raise
# a BuildError exception which indicates a fatal error in producing the
# RPF file.
#
def build( &block )
PackConverter.log.info( 'No RPF files to build.' ) \
unless ( @rpf_files.size > 0 )
env = Environment.new()
@branch.fill_env( env )
result = true
@rpf_files.each do |rpffile|
rpf_filename = rpffile.content.filename
# Ensure our RPF file is writable.
if ( ::File::exists?( rpf_filename ) and !::File::writable?( rpf_filename ) ) then
message = "File #{rpf_filename} is not writable. Pack failed."
PackConverter::log().error( message )
throw BuildError.new( rpffile.content, message )
end
# Loop through our pack item content nodes.
rpf_dir = OS::Path::get_directory( rpf_filename )
FileUtils::mkdir_p( rpf_dir ) unless ( File::directory?( rpf_dir ) )
file_list = []
rpffile.items.each do |pack_item|
entry = {}
entry[:src] = env.subst( pack_item.src )
entry[:dst] = pack_item.dst
if ( ::File::exists?( pack_item.src ) ) then
file_list << entry
yield( pack_item.content, true ) if ( block_given? )
else
PackConverter::log().warn( "Cannot add #{pack_item.src} to RPF file. File does not exist on disk." )
yield( pack_item.content, false ) if ( block_given? )
end
end
success = ProjectUtil::data_create_rpf( rpf_filename, file_list, rpffile.content.compress )
yield( rpffile.content, success ) if ( block_given? )
result = false unless ( success )
end
{ :success => result }
end
# Clear the content from the build list.
def clear( )
@rpf_files.clear( )
end
# Add content to be put into this RPF file.
def add_content( content )
path_stack = []
if ( content.is_a?( Pipeline::Content::RPF ) ) then
rpf = PackFile.new( content )
if ( content.methods.include?( 'inputs' ) ) then
content.inputs.each do |child|
add_content_recursive( child, path_stack, rpf )
end
end
@rpf_files << rpf
true
else
PackConverter.log().warn("couldn't convert #{content}")
false
end
end
# RPF converter's log object.
def PackConverter::log( )
@@log = Log.new( 'convert_pack' ) if ( @@log.nil? )
@@log
end
#--------------------------------------------------------------------
# Private
#--------------------------------------------------------------------
private
@@log = nil
#
# Internal class to represent a single RPF file.
#
class PackFile
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 RPF file.
# We store the source and destination paths and the content node the
# file came from.
#
class PackItem
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, rpffile )
# Handle content type pre-recursion
if ( content.is_a?( Pipeline::Content::RPF ) ) then
pre_handle_rpf_node( content, path_stack, rpffile )
elsif ( content.is_a?( Pipeline::Content::File ) ) then
pre_handle_file_node( content, path_stack, rpffile )
elsif ( content.is_a?( Pipeline::Content::Group ) ) then
pre_handle_group_node( content, path_stack, rpffile )
end
content.inputs.each do |child|
add_content_recursive( child, path_stack, rpffile )
end
if ( content.methods.include?( 'children' ) ) then
content.children.each do |child|
add_content_recursive( child, path_stack, rpffile )
end
end
if ( content.is_a?( Pipeline::Content::Group ) ) then
post_handle_group_node( content, path_stack, rpffile )
end
end
#---------------------------------------------------------------------
# Content-node Specific Handling Methods
# "pre_" - handlers pre-recurse
# "post_" - handlers post-recuse
#---------------------------------------------------------------------
#
def pre_handle_rpf_node( content, path_stack, rpffile )
src = ""
dst = ""
@branch.in_env() do | e |
src = e.subst( content.filename )
if ( rpffile.content.stack_path ) then
dst = e.subst( "#{OS::Path.combine( OS::Path.combine(*path_stack), OS::Path::get_filename( content.filename ) )}" )
else
dst = e.subst( OS::Path::get_filename( content.filename ) )
end
end
rpffile.items << PackItem.new( content, src, dst )
end
#
def pre_handle_file_node( content, path_stack, rpffile )
src = ""
dst = ""
@branch.in_env() do | e |
src = e.subst( content.filename )
if ( rpffile.content.stack_path ) then
dst = e.subst( "#{OS::Path.combine( OS::Path.combine(*path_stack), OS::Path::get_filename( content.filename ) )}" )
else
dst = e.subst( OS::Path::get_filename( content.filename ) )
end
end
rpffile.items << PackItem.new( content, src, dst )
end
#
def pre_handle_group_node( content, path_stack, rpffile )
if ( nil != content.path and '' != content.path ) then
path_stack.push( content.path )
end
end
#
def post_handle_group_node( content, path_stack, rpffile )
if ( nil != content.path and '' != content.path ) then
path_stack.pop()
end
end
end # PackConverter class
end # Converters module
end # Resourcing module
end # Pipeline module
# %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_pack.rb