[27541] users/pipping/merge.rb
source_changes at macosforge.org
source_changes at macosforge.org
Tue Aug 7 03:12:53 PDT 2007
Revision: 27541
http://trac.macosforge.org/projects/macports/changeset/27541
Author: pipping at macports.org
Date: 2007-08-07 03:12:53 -0700 (Tue, 07 Aug 2007)
Log Message:
-----------
please do have a look at this repository for details:
http://elias.svn.binera.de
r66: minor changes
r67: add comment, minor changes
r68: trivial changes
r69: new structure: Merge class, FileHandler subclass, Helpers module | simplification of multiple functions' interfaces | partial rewrite of multiple functions, including copy, create_directory | new function special_copy for the time being | major code cleanup, including all kinds of formatting changes
r70: rewrite function true_for_all?
r71: formatting change
r72: rename check_consistency to consistent?, reorganize it and make it into a predicate | restructure | unify comments
r73: use/define String#start_with? and String#end_with? from Ruby 1.9
r74: use String#start_with?
Modified Paths:
--------------
users/pipping/merge.rb
Modified: users/pipping/merge.rb
===================================================================
--- users/pipping/merge.rb 2007-08-07 09:46:01 UTC (rev 27540)
+++ users/pipping/merge.rb 2007-08-07 10:12:53 UTC (rev 27541)
@@ -20,380 +20,425 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-require 'fileutils'
-require 'find'
-require 'logger'
-require 'optparse'
-require 'ostruct'
-require 'pathname'
-require 'set'
-require 'tempfile'
-require 'zlib'
+libs = %w{ fileutils find logger optparse ostruct pathname set tempfile zlib }
-###
-# we need GNU File with Apple's patches applied, otherwise we will not be
-# able to recognize x86_64 mach-o files
-FILE = '/usr/bin/file'
+libs.each {|lib| require lib}
-class MergeArguments
- def self.parse( args )
+module Helpers
+ def true_for_all?( filePath, includeFirst )
+ # checks if a predicate is true for all (but the first) architecture
+ iterand = includeFirst ? @args : @args[1..-1]
+ iterand.all? {|arch| yield( @options.input + arch + filePath, arch )}
+ end
+end
- # set up defaults
- options = OpenStruct.new
- options.dryrun = false
+# these ruby 1.9 extensions come in handy. in case we are running ruby 1.8 we
+# just define them ourselves
+class String
+ unless self.method_defined?( :start_with? )
+ def start_with?( string )
+ self.slice( 0...string.length ) == string
+ end
+ end
+ unless self.method_defined?( :end_with? )
+ def end_with?( string )
+ self.slice( -string.length..-1 ) == string
+ end
+ end
+end
+class Merge
- options.level = Logger::INFO
- options.log = 'STDOUT'
+ private
- options.exclude = %w{.svn CVS}
+ include Helpers
- options.input = Pathname.pwd
- options.output = Pathname.pwd + 'out'
+ class MergeArguments
+ def self.parse( arguments )
- opts = OptionParser.new {|opts|
- opts.banner = 'Usage: %s [options] arch arch [arch [arch ...]]' % $0
+ # set up defaults
+ options = OpenStruct.new
+ options.dryrun = false
- opts.on( '-i', '--input DIRECTORY',
- 'Change input directory', %{Defaults to '.'.} ) {|i|
- options.input = Pathname.new( i ).expand_path || options.input
- }
+ options.level = Logger::INFO
+ options.log = 'STDOUT'
- opts.on( '-o', '--output DIRECTORY',
- 'Change output directory', %{Defaults to './out'.} ) {|o|
- options.output = Pathname.new( o ).expand_path || options.output
- }
+ options.exclude = %w{ .svn CVS }
- opts.on( '-v', '--verbosity LEVEL', 'Change level of verbosity',
- %{Valid arguments are 'debug', 'info',},
- %{'warn', 'error', and 'fatal'.}, %{Defaults to 'info'.} ) {|v|
- case v
- when 'debug'
- options.level = Logger::DEBUG
- when 'info'
- options.level = Logger::INFO
- when 'warn'
- options.level = Logger::WARN
- when 'error'
- options.level = Logger::ERROR
- when 'fatal'
- options.level = Logger::FATAL
- end
- }
+ options.input = Pathname.pwd
+ options.output = Pathname.pwd + 'out'
- opts.on( '-l', '--log TARGET', 'Change target to log to',
- %{Valid arguments are 'STDOUT', 'STDERR',},
- %{and '/path/to/file'.}, %{Defaults to 'STDOUT'.} ) {|l|
- options.log = l
- }
+ opts = OptionParser.new {|opts|
+ opts.banner = 'Usage: %s [options] arch arch [arch [arch ...]]' % $0
- opts.on( '-e', '--exclude PATTERN1,PATTERN2', Array,
- 'Exclude files/directories (glob-style)') {|e|
- options.exclude = e
- }
+ opts.on( '-i', '--input DIRECTORY',
+ 'Change input directory', %q{Defaults to '.'} ) {|i|
+ options.input = Pathname.new( i ).expand_path || options.input
+ }
- opts.on( '-d', '--[no-]dry-run', 'Perform a dry run' ) {|d|
- options.dryrun = d
- }
+ opts.on( '-o', '--output DIRECTORY',
+ 'Change output directory', %q{Defaults to './out'} ) {|o|
+ options.output = Pathname.new( o ).expand_path || options.output
+ }
- opts.on_tail( '-h', '--help', 'Show this message' ) {
- puts opts
- exit
- }
- }
- opts.parse!( args )
- options
- end
-end
+ opts.on( '-v', '--verbosity LEVEL', 'Change level of verbosity',
+ %q{Valid arguments are 'debug', 'info',},
+ %q{'warn', 'error', and 'fatal'.}, %q{Defaults to 'info'} ) {|v|
+ case v
+ when 'debug', 'info', 'warn', 'error', 'fatal'
+ options.level = Logger.const_get( v.upcase )
+ end
+ }
-options = MergeArguments.parse( ARGV )
+ opts.on( '-l', '--log TARGET', 'Change target to log to',
+ %q{Valid arguments are 'STDOUT', 'STDERR',},
+ %q{and '/path/to/file'.}, %q{Defaults to 'STDOUT'} ) {|l|
+ options.log = l
+ }
-# ignore duplicates and trailing slashes
-ARGS = ARGV.collect {|arg| arg.chomp( '/' )}.uniq
+ opts.on( '-e', '--exclude PATTERN1,PATTERN2', Array,
+ 'Exclude files/directories (glob-style)') {|e|
+ options.exclude = e
+ }
-def true_for_all? ( filePath, includeFirst, opts )
-# checks if a predicate is true for all (but the first) architecture
- result = true
- iterable = includeFirst ? ARGS : ARGS[1..-1]
- iterable.each {|arch|
- unless yield( opts.input + arch + filePath, arch )
- result = false
- break
+ opts.on( '-d', '--[no-]dry-run', 'Perform a dry run' ) {|d|
+ options.dryrun = d
+ }
+
+ opts.on_tail( '-h', '--help', 'Show this message' ) {
+ puts opts
+ exit
+ }
+ }
+ opts.parse!( arguments )
+ options
end
- }
- return result
-end
-
-def create_directory ( dir, logPath, opts )
-# creates a directory
- unless dir.exist?
- dir.mkpath unless opts.dryrun
- $log.debug( 'created : %s' % logPath )
- else
- $log.debug( 'exists : %s' % logPath )
end
-end
-def copy ( origin, target, logPath, opts )
-# copies files
- unless target.exist?
- FileUtils.cp( origin, target,
- :noop => opts.dryrun
- )
- $log.debug( 'copied : %s' % logPath )
- else
- $log.debug( 'exists : %s' % logPath )
- end
-end
+ class FileHandler
-def check_consistency( path, regex, opts )
-# checks if a file has the correct type and architecture across all trees
- type_matches = true_for_all?( path, true, opts ) {|filePath, arch|
- fileCallOutput = %x{#{ FILE } -b "#{ filePath }"}.chomp
- fileCallOutput =~ regex
- }
- arch_matches = true_for_all?( path, true, opts ) {|filePath, arch|
- lipoCallOutput = %x{lipo -info "#{ filePath }"}.chomp
- lipoCallOutput =~ %r{is architecture: #{ arch }$}
- }
- unless type_matches and arch_matches
- $log.error( 'type or architecture mismatch' )
- raise( 'an error occurred. see the log for details.' )
- end
-end
+ include Helpers
-def lipo ( filePath, opts )
-# glues single-architecture files together using lipo(1)
- lipoArgs = Array.new
- ARGS.each {|arch|
- lipoArgs << sprintf( '-arch %s %s', arch, opts.input + arch + filePath )
- }
- lipoTarget = opts.output + filePath
- lipoCommand = sprintf(
- 'lipo %s -create -o %s', lipoArgs.join( ' ' ), lipoTarget
- )
- unless lipoTarget.exist?
- system lipoCommand unless opts.dryrun
- $log.debug( 'merged : %s' % filePath )
- else
- $log.debug( 'exists : %s' % filePath )
- end
-end
+ private
-def make_wrapper ( filePath, first, opts )
-# creates a wrapper for config scripts that differ across trees
- wrapperTarget = opts.output + filePath
- unless wrapperTarget.exist?
- wrapperTarget.open( 'w' ) {|wrapper|
- wrapper.puts '#! /bin/sh'
- wrapper.puts 'DIR="/%s"' % filePath.dirname
- wrapper.puts 'args=$@'
- wrapper.puts 'if [ "${args/-arch/}" != "$args" ]; then'
- wrapper.puts ' arch=`echo "$args" | ' +
- %q{sed 's!.*-arch *\([^ ][^ ]*\).*!\1!'`;}
- wrapper.puts 'else'
- wrapper.puts ' arch=`uname -p`'
- wrapper.puts 'fi'
- wrapper.puts 'args=`echo $@ | sed "s!-arch *${arch}!!"`'
- wrapper.puts 'exec $DIR/${arch}/%s ${args}' % filePath.basename
- }
- wrapperTarget.chmod( first.stat.mode )
- end
-end
+ def initialize( options, log, args )
+ @options, @log, @args = options, log, args
+ end
+ def create_directory( prefix, dir )
+ # creates a directory
+ prefixed = prefix + dir
+ unless prefixed.exist?
+ prefixed.mkpath unless @options.dryrun
+ @log.debug( 'created : %s' % dir )
+ else
+ @log.debug( 'exists : %s' % dir )
+ end
+ end
-ORIGIN = Pathname.pwd
-processed = Set.new
+ def copy( filePath )
+ # copies a file
+ origin = @options.input + @args[0] + filePath
+ target = @options.output + filePath
+ unless target.exist?
+ FileUtils.cp( origin, target, :noop => @options.dryrun )
+ @log.debug( 'copied : %s' % filePath )
+ else
+ @log.debug( 'exists : %s' % filePath )
+ end
+ end
-case options.log
-when 'STDERR'
- $log = Logger.new( STDERR )
-when 'STDOUT'
- $log = Logger.new( STDOUT )
-else
- logTarget = Pathname.new( options.log ).expand_path
- if logTarget.writable?
- $log = Logger.new( logTarget )
- elsif !logTarget.exist? and logTarget.dirname.writable?
- $log = Logger.new( logTarget )
- else
- $log = Logger.new( STDOUT )
- $log.error( 'cannot create log file' )
- raise( 'an error occurred.' )
- end
-end
-$log.level = options.level
-$log.info( 'starting up' )
+ def consistent?( path, string )
+ # checks if a file has the correct type and architecture across all trees
+ type_matches = true_for_all?( path, true ) {|filePath, arch|
+ fileCallOutput = %x{ #{ $FILE } -b "#{ filePath }" }.chomp
+ fileCallOutput.start_with?( string )
+ }
+ arch_matches = true_for_all?( path, true ) {|filePath, arch|
+ lipoCallOutput = %x{ lipo -info "#{ filePath }" }.chomp
+ lipoCallOutput.end_with?( 'is architecture: %s' % arch )
+ }
+ type_matches and arch_matches
+ end
-# make sure we're given a valid root directory
-unless options.input.directory?
- $log.fatal( 'invalid input directory: %s' % options.input )
- raise( 'an error occurred. see the log for details.' )
-end
+ def lipo( filePath )
+ # glues single-architecture files together using lipo(1)
+ lipoArgs = Array.new
+ @args.each {|arch|
+ lipoArgs << '-arch %s %s' % [ arch, @options.input + arch + filePath ]
+ }
+ lipoTarget = @options.output + filePath
+ lipoCommand = 'lipo %s -create -o %s' % [ lipoArgs.join( ' ' ), lipoTarget ]
+ unless lipoTarget.exist?
+ system lipoCommand unless @options.dryrun
+ @log.debug( 'merged : %s' % filePath )
+ else
+ @log.debug( 'exists : %s' % filePath )
+ end
+ end
-# make sure the requested architectures have corresponding subdirectories
-# in the the given input directory
-unless true_for_all?( '.', true, options) {|filePath, arch|
- filePath.directory?
-}
- $log.fatal( 'architecture missing from input directory' )
- raise( 'an error occurred. see the log for details.' )
-end
+ def make_wrapper( filePath, first )
+ # creates a wrapper for config scripts that differ across trees
+ wrapperTarget = @options.output + filePath
+ unless wrapperTarget.exist?
+ wrapperTarget.open( 'w' ) {|wrapper|
+ wrapper.puts(
+ '#! /bin/sh',
+ 'DIR="/%s"' % filePath.dirname,
+ 'args=$@',
+ 'if [ "${args/-arch/}" != "$args" ]; then',
+ %q{ arch=`echo "$args" | sed 's!.*-arch *\([^ ][^ ]*\).*!\1!'`;},
+ 'else',
+ ' arch=`uname -p`',
+ 'fi',
+ 'args=`echo $@ | sed "s!-arch *${arch}!!"`',
+ 'exec $DIR/${arch}/%s ${args}' % filePath.basename
+ )
+ }
+ wrapperTarget.chmod( first.stat.mode )
+ end
+ end
-ARGS.each {|architecture|
- FileUtils.cd options.input + architecture
- Pathname.new( '.' ).find {|subPath|
- options.exclude.each {|excludedPattern|
- if subPath.basename.fnmatch? excludedPattern
- Find.prune
- break
+ def special_copy( origin, target, logPath )
+ # copies files
+ unless target.exist?
+ FileUtils.cp( origin, target, :noop => @options.dryrun )
+ @log.debug( 'forked : %s' % logPath )
+ else
+ @log.debug( 'exists : %s' % logPath )
end
- }
- unless processed.include? subPath
- processed << subPath
- firstPath = options.input + ARGS[0] + subPath
- unless true_for_all?( subPath, false, options ) {|filePath, arch|
+ end
+
+ public
+
+ def handle_file( subPath )
+ # firstPath is used so we have something we can compare other
+ # architecture's versions of the file we are processing with.
+ firstPath = @options.input + @args[0] + subPath
+ unless true_for_all?( subPath, false ) {|filePath, arch|
begin
filePath.ftype == firstPath.ftype
rescue Errno::ENOENT
false
end
}
- $log.warn( 'skipped: %s' % subPath )
- next
- end
-
- case firstPath.ftype
- # handle file type: directory
- when 'directory'
- create_directory( options.output + subPath, subPath, options )
- # handle file type: symlinks
- when 'link'
- linkTarget = firstPath.readlink
- if true_for_all?( subPath, false, options ) {|filePath, arch|
- pathToSymlink = options.input + arch + subPath
- pathToSymlink.readlink == linkTarget
- }
- linkDestination = options.output + subPath
- unless linkDestination.symlink? or linkDestination.exist?
- FileUtils.copy_entry(
- firstPath,
- linkDestination
- )
- end
- else
- # DEBUG: link targets differ
- end
- when 'file'
- if true_for_all?( subPath, false, options ) {|filePath, arch|
- FileUtils.identical?( filePath, firstPath )
- }
- copy( firstPath, options.output + subPath, subPath, options )
- next
- end
-
- case subPath.extname
- # handle file type: header files
- when '.h', '.hpp'
- unless ( options.output + subPath ).exist?
- open( options.output + subPath, 'w' ) {|headerTarget|
- ARGS.each {|arch|
- headerInput = options.input + arch + subPath
- headerTarget.puts '#ifdef __%s__' % arch
- headerTarget.puts headerInput.open( 'r' ).read
- headerTarget.puts '#endif'
- }
- }
- $log.debug( 'merged: %s' % subPath )
+ # A file is either missing from at least on of the single-architecture
+ # directories or not all versions of the file have the same type.
+ @log.warn( 'skipped: %s' % subPath )
+ else
+ case firstPath.ftype
+ # Handle file type: directory
+ when 'directory'
+ create_directory( @options.output, subPath )
+ # Handle file type: symlink
+ when 'link'
+ firstLinkTarget = firstPath.readlink
+ if true_for_all?( subPath, false ) {|filePath, arch|
+ linkTarget = @options.input + arch + subPath
+ linkTarget.readlink == firstLinkTarget
+ }
+ linkDestination = @options.output + subPath
+ unless linkDestination.symlink? or linkDestination.exist?
+ FileUtils.copy_entry( firstPath, linkDestination )
+ @log.debug( 'copied : %s' % subPath )
+ else
+ @log.debug( 'exists : %s' % subPath )
+ end
else
- $log.debug( 'exists: %s' % subPath )
+ # The links point at different targets
+ @log.warn( 'skipped: %s' % subPath )
end
- # handle file type: pkg-config files
- when '.pc'
- ARGS.each {|arch|
- subArch = subPath.dirname + arch + subPath.basename
- copyTarget = options.output + subArch
- create_directory( copyTarget.dirname, subArch.dirname, options )
- copy( options.input + arch + subPath, copyTarget, subArch, options )
+ when 'file'
+ if true_for_all?( subPath, false ) {|filePath, arch|
+ FileUtils.identical?( filePath, firstPath )
}
- $log.debug( 'spread : %s' % subPath )
- # handle file type: gzip-compressed man pages
- when '.gz'
- temporaryFiles = Hash.new
- ARGS.each {|arch|
- compressed = options.input + arch + subPath
- uncompressed = Tempfile.new( compressed.basename )
- uncompressed.write( Zlib::GzipReader.open( compressed ).read )
- uncompressed.close
- temporaryFiles[arch] = uncompressed.path
- }
- if true_for_all?( subPath, false, options ) {|filePath, arch|
- FileUtils.identical?( temporaryFiles[arch], temporaryFiles[ARGS[0]] )
- }
- copy( firstPath, options.output + subPath, subPath, options )
+ copy( subPath )
else
- $log.warn( 'skipped: %s' % subPath )
- end
- # handle file type: other files
- else
- fileOutput = %x{ #{ FILE } -b "#{ firstPath }" }.chomp
- case fileOutput
- # handle file type: ar archives
- when %r{^current ar archive}
- check_consistency( subPath, %r{^current ar archive}, options )
- lipo( subPath, options )
- # handle file type: mach-o files
- when %r{^Mach-O}
- check_consistency( subPath, %r{^Mach-O}, options )
- links = Hash.new
- ARGS.each {|arch|
- links[arch] = %x{
- #{
- arch[-2..-1] == '64' ? 'otool64' : 'otool'
- } -arch #{ arch } -LX #{
- options.input + arch + subPath
+ case subPath.extname
+ # Handle file type: header file
+ when '.h', '.hpp'
+ unless ( @options.output + subPath ).exist?
+ open( @options.output + subPath, 'w' ) {|headerTarget|
+ @args.each {|arch|
+ headerInput = @options.input + arch + subPath
+ headerTarget.puts(
+ '#ifdef __%s__' % arch,
+ headerInput.open( 'r' ).read,
+ '#endif'
+ )
+ }
}
- }.entries.collect {|dependencyLine|
- dependencyLine.strip.gsub(
- Regexp.new(
- ' \(compatibility version \d+(\.\d+){2}, ' +
- 'current version \d+(\.\d+){2}\)'
- ), ''
+ @log.debug( 'merged: %s' % subPath )
+ else
+ @log.debug( 'exists: %s' % subPath )
+ end
+ # Handle file type: pkg-config file
+ when '.pc'
+ @args.each {|arch|
+ subArch = subPath.dirname + arch + subPath.basename
+ create_directory( @options.output, subArch.dirname )
+ special_copy(
+ @options.input + arch + subPath,
+ @options.output + subArch, subArch
)
- }.reject {|dep|
- dep[0..7] == '/usr/lib'
- }.to_set
- }
- unless true_for_all?( subPath, false, options ) {|filePath, arch|
- links[arch] == links[ARGS[0]]
- }
- $log.warn( 'skipped: %s' % subPath )
- next
+ }
+ # Handle file type: gzip-compressed man page
+ when '.gz'
+ temporaryFiles = Hash.new
+ @args.each {|arch|
+ compressed = @options.input + arch + subPath
+ uncompressed = Tempfile.new( compressed.basename )
+ uncompressed.write( Zlib::GzipReader.open( compressed ).read )
+ uncompressed.close
+ temporaryFiles[arch] = uncompressed.path
+ }
+ if true_for_all?( subPath, false ) {|filePath, arch|
+ FileUtils.identical?(
+ temporaryFiles[arch], temporaryFiles[@args[0]]
+ )
+ }
+ copy( subPath )
+ else
+ # The content of the compressed files differs
+ @log.warn( 'skipped: %s' % subPath )
+ end
+ else
+ fileOutput = %x{ #{ $FILE } -b "#{ firstPath }" }.chomp
+ case fileOutput
+ # Handle file type: ar archive
+ when %r{^current ar archive}
+ if consistent?( subPath, 'current ar archive' )
+ lipo( subPath )
+ else
+ @log.warn( 'skipped: %s' % subPath )
+ end
+ # Handle file type: mach-o binary
+ when %r{^Mach-O}
+ if consistent?( subPath, 'Mach-O' )
+ links = Hash.new
+ # Obtain the output of `otool -L`, get rid of everything we do
+ # not need and stuff it into a set for later comparison
+ @args.each {|arch|
+ links[arch] = %x{
+ #{
+ arch.end_with?( '64' ) ? 'otool64' : 'otool'
+ } -arch #{ arch } -LX #{
+ @options.input + arch + subPath
+ }
+ }.entries.collect {|library|
+ library.strip.gsub( %r{ \(compatibility version.+\)}, '' )
+ }.reject {|line|
+ line.start_with?( '/usr/lib' )
+ }.to_set
+ }
+ unless true_for_all?( subPath, false ) {|filePath, arch|
+ links[arch] == links[@args[0]]
+ }
+ # At least one single-architecture file was linked against a
+ # library not all of the others were.
+ @log.warn( 'skipped: %s' % subPath )
+ else
+ lipo( subPath )
+ end
+ else
+ @log.warn( 'skipped: %s' % subPath )
+ end
+ when 'Bourne shell script text executable'
+ if subPath.basename.to_s.end_with?( '-config' )
+ # Handle file type: config script
+ @args.each {|arch|
+ subArch = subPath.dirname + arch + subPath.basename
+ create_directory( @options.output, subArch.dirname )
+ special_copy(
+ @options.input + arch + subPath,
+ @options.output + subArch, subArch
+ )
+ }
+ make_wrapper( subPath, firstPath )
+ @log.debug( 'wrapped : %s' % subPath )
+ end
+ else
+ # The file is a Bourne shell script, but we do not know how to
+ # merge it.
+ @log.warn( 'skipped: %s' % subPath )
+ end
end
- lipo( subPath, options )
- when 'Bourne shell script text executable'
- # DEBUG: no way to handle a shell script in general
- next unless subPath.basename.to_s[-7..-1] == '-config'
- # handle file type: config script
- ARGS.each {|arch|
- subArch = subPath.dirname + arch + subPath.basename
- copyTarget = options.output + subArch
- create_directory( copyTarget.dirname, subArch.dirname, options )
- copy(
- options.input + arch + subPath, copyTarget, subArch, options
- )
- }
- make_wrapper( subPath, firstPath, options )
- $log.debug( 'wrapped : %s' % subPath )
- else
- # DEBUG: unable to determine file type
- $log.warn( 'skipped: %s' % subPath )
end
end
end
end
- }
-}
+ end
-FileUtils.cd ORIGIN
-$log.info( 'shutting down' )
+
+ def initialize
+ @options = MergeArguments.parse( ARGV )
+
+ # ignore duplicates and trailing slashes
+ @args = ARGV.collect {|arg| arg.chomp( '/' )}.uniq
+
+ @ORIGIN = Pathname.pwd
+ processed = Set.new
+
+ # We need File with Apple's patches applied, otherwise we will not be able
+ # to recognize x86_64 Mach-O files
+ $FILE = '/usr/bin/file'
+
+ # Start logging
+ case @options.log
+ when 'STDERR'
+ @log = Logger.new( STDERR )
+ when 'STDOUT'
+ @log = Logger.new( STDOUT )
+ else
+ logTarget = Pathname.new( @options.log ).expand_path
+ if logTarget.writable?
+ @log = Logger.new( logTarget )
+ elsif !logTarget.exist? and logTarget.dirname.writable?
+ @log = Logger.new( logTarget )
+ else
+ @log = Logger.new( STDOUT )
+ @log.error( 'cannot create log file' )
+ raise( 'an error occurred.' )
+ end
+ end
+ @log.level = @options.level
+ @log.info( 'starting up' )
+
+ # Make sure we are given a valid root directory
+ unless @options.input.directory?
+ @log.fatal( 'invalid input directory: %s' % @options.input )
+ raise( 'an error occurred. see the log for details.' )
+ end
+
+ # Make sure the requested architectures have corresponding subdirectories
+ # in the the given input directory
+ unless true_for_all?( '.', true ) {|filePath, arch|
+ filePath.directory?
+ }
+ @log.fatal( 'architecture missing from input directory' )
+ raise( 'an error occurred. see the log for details.' )
+ end
+
+ # Walk the trees
+ @args.each {|architecture|
+ FileUtils.cd @options.input + architecture
+ Pathname.new( '.' ).find {|subPath|
+ @options.exclude.each {|excludedPattern|
+ if subPath.basename.fnmatch? excludedPattern
+ Find.prune
+ break
+ end
+ }
+ unless processed.include? subPath
+ processed << subPath
+ FileHandler.new( @options, @log, @args).handle_file( subPath )
+ end
+ }
+ }
+
+ FileUtils.cd @ORIGIN
+ @log.info( 'shutting down' )
+ end
+end
+
+Merge.new
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20070807/f9cfb201/attachment.html
More information about the macports-changes
mailing list