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

247 lines
8.1 KiB
Ruby
Executable File

#
# File:: %RS_TOOLSLIB%/pipeline/projectutil/data_zip.rb
# Description:: Zip file functions.
#
# Author:: David Muir <david.muir@rockstarnorth.com>
# Date:: 24 June 2011
#
#-----------------------------------------------------------------------------
# Uses
#-----------------------------------------------------------------------------
require 'pipeline/log/log'
require 'pipeline/os/path'
include Pipeline
require 'time'
require 'zip/zip'
include Zip
require 'pipeline/util/rubyzip2_mtime_fix'
#-----------------------------------------------------------------------------
# Implementation
#-----------------------------------------------------------------------------
module Pipeline
module ProjectUtil
@@zip_log = Pipeline::Log::new( 'data_zip' )
#
# == Description
# Extract the content of a ZIP file to a destination directory. The
# optional block is executed for each file that is extracted specifying the
# full path of the extracted file.
#
# ZIP sub-directories are preserved in the destination directory.
#
# The filenames of the extracted files are return in an Array.
#
# == Example Usage
# See %RS_TOOLSLIB%/util/data_extract_zip.rb.
#
def ProjectUtil::data_zip_extract( filename, destination, overwrite = false, filter = '*.*', &block )
dest_files = []
FileUtils::mkdir_p( destination ) unless ( File::directory?( destination ) )
Dir::chdir( destination ) do
ZipFile::open( filename ) do |zf|
zf.each do |entry|
# Skip filenames that do not match filter.
next unless ::File::fnmatch( filter, entry.name, File::FNM_CASEFOLD )
dir = OS::Path::get_directory( entry.name )
FileUtils::mkdir_p( dir ) unless ( dir.nil? or 0 == dir.size or File::directory?( dir ) )
entry.extract do
overwrite
end
# Local time.
dest_file = OS::Path::combine( destination, entry.name )
mtime = ( entry.time )
File::utime( mtime, mtime, dest_file )
dest_files << dest_file
yield( dest_file ) if ( block_given? )
end
end
end
dest_files
end
#
# == Description
# Extract the contents of a ZIP file to a destination directory. The
# block is executed with each ZipEntry object as a parameter; if the block
# returns true then the file is extracted, otherwise the file is not extracted.
# If the 'overwrite' parameter is used, the block still needs to evaluate
# to true for the file to be written.
#
# ZIP sub-directories are preserved in the destination directory.
#
# The filenames of the extracted files are return in an Array.
#
# == Example Usage
# DHM TODO
#
def ProjectUtil::data_zip_extract2( filename, destination, overwrite = false, filter = '*.*', &block )
dest_files = []
FileUtils::mkdir_p( destination ) unless ( File::directory?( destination ) )
Dir::chdir( destination ) do
ZipFile::open( filename ) do |zf|
zf.each do |entry|
# Skip filenames that do not match filter.
next unless ::File::fnmatch( filter, entry.name, File::FNM_CASEFOLD )
dir = OS::Path::get_directory( entry.name )
FileUtils::mkdir_p( dir ) unless ( dir.nil? or 0 == dir.size or File::directory?( dir ) )
if ( block_given? and ( yield entry ) ) then
entry.extract do
overwrite
end
else
entry.extract do
overwrite
end
end
# Local time.
dest_file = OS::Path::combine( destination, entry.name )
mtime = ( entry.time )
File::utime( mtime, mtime, dest_file )
dest_files << dest_file
end
end
end
dest_files
end
#
# == Description
# Extract the contents of a ZIP file to a destination directory. Only
# files newer than the destination files are overwritten; this can be forced
# by setting 'overwrite' to true.
#
# ZIP sub-directories are preserved in the destination directory.
#
# The filenames of the extracted files are return in an Array.
#
# == Example Usage
# DHM TODO
#
def ProjectUtil::data_zip_extract3( filename, destination, overwrite = false, filter = '*.*', &block )
ProjectUtil::data_zip_extract2( filename, destination, overwrite, filter ) do |entry|
destination_file = OS::Path::combine( destination, entry.name )
if ( File::exists?( destination_file ) ) then
# Destination file exists; extract if its modified date is
# earlier than the modified date of the zip entry.
mtime = File::mtime( destination_file )
( ( mtime <=> entry.time ) < 0 )
else
# Destination file does not exist so we should extract.
true
end
end
end
#
# == Description
# Return Array of filenames within the zip file. Also yields each
# filename to the block, if given.
#
def ProjectUtil::data_zip_filelist( filename, &block )
dest_files = []
ZipFile::foreach( filename ) do |zf|
yield( zf.name ) if ( block_given? )
dest_files << zf.name
end
dest_files
end
#
# == Description
# Create a ZIP file; from the specific file list.
#
# file_list is an Array; of either file path Strings or Hash objects
# containing two keys, :src, :dst specifying source file and destination
# path in the zip file.
#
# User-block is yielded for each file added (with filename as parameter).
#
# == Example Usage
# See %RS_TOOLSLIB%/util/data_mk_generic_zip.rb
#
def ProjectUtil::data_zip_create( filename, file_list, compress = true, &block )
directory = OS::Path::get_directory( filename )
FileUtils::mkdir_p( directory ) if ( not File::directory?( directory ) )
# Delete the existing Zip file if it exists.
FileUtils::rm( filename ) if ( File::exists?( filename ) )
# Create the Zip file and write our entries.
ZipFile::open( filename, ZipFile::CREATE ) do |zf|
file_list.each do |path|
if ( path.is_a?( String ) and File::file?( path ) ) then
if ( not File::exists?( path ) ) then
@@zip_log.error( "File #{path} does not exist. Skipping." )
next
end
entry = zf.add( OS::Path::get_filename( path ), path ) do
true # continue on exists (overwrite)
end
entry.time = File::mtime( File::expand_path( path ) ).getlocal
entry.compression_method = ZipEntry::DEFLATED if ( compress )
entry.compression_method = ZipEntry::STORED unless ( compress )
yield( path ) if ( block_given? )
elsif ( path.is_a?( Hash ) and path.has_key?( :src ) and path.has_key?( :dst ) )
if ( not File::exists?( path[:src] ) ) then
@@zip_log.error( "File #{path} does not exist. Skipping." )
next
end
entry = zf.add( path[:dst], path[:src] ) do
true # continue on exists (overwrite)
end
entry.time = File::mtime( File::expand_path( path[:src] ) ).getlocal
entry.compression_method = ZipEntry::DEFLATED if ( compress )
entry.compression_method = ZipEntry::STORED unless ( compress )
yield( path ) if ( block_given? )
else
@@zip_log.error( "Misformed entry in file_list (#{path.class}, '#{path.to_s}')." )
end
end
zf.comment = "Created by #{__FILE__} on #{DateTime::now}"
@@zip_log.info( "Zip file #{filename} created (#{file_list.size} entries)." )
zf.close()
end
true
end
#
# == Description
# Read the contents of a file into memory and return its content as a
# String.
#
def ProjectUtil::data_zip_readfile( filename, contained_filename )
data = nil
ZipFile::open( filename ) do |zf|
data = zf.read( contained_filename )
end
end
end # ProjectUtil module
end # Pipeline module
# %RS_TOOLSLIB%/pipeline/projectutil/data_zip.rb