[26793] users/pipping/merge.rb
source_changes at macosforge.org
source_changes at macosforge.org
Sun Jul 8 05:38:57 PDT 2007
Revision: 26793
http://trac.macosforge.org/projects/macports/changeset/26793
Author: pipping at macports.org
Date: 2007-07-08 05:38:56 -0700 (Sun, 08 Jul 2007)
Log Message:
-----------
r50: rewrite 'wrapper_target' ( takes another argument now, looks nicer, cares about permissions )
r51: rewrite option parsing
Modified Paths:
--------------
users/pipping/merge.rb
Modified: users/pipping/merge.rb
===================================================================
--- users/pipping/merge.rb 2007-07-08 07:40:39 UTC (rev 26792)
+++ users/pipping/merge.rb 2007-07-08 12:38:56 UTC (rev 26793)
@@ -23,6 +23,7 @@
require 'fileutils'
require 'find'
require 'optparse'
+require 'ostruct'
require 'pathname'
require 'set'
@@ -31,153 +32,130 @@
# able to recognize x86_64 mach-o files
FILE = '/usr/bin/file'
-class MergeArguments < Hash
- def initialize( args )
- super( )
+class MergeArguments
+ def self.parse( args )
# set up defaults
- self[:dry_run] = false
- self[:force] = false
- self[:verbose] = false
+ options = OpenStruct.new
+ options.dryrun = false
+ options.force = false
+ options.verbose = false
- self[:exclude] = Set.new << '.svn' << 'CVS'
- self[:output] = Pathname.pwd + 'out'
- self[:input] = Pathname.pwd
+ options.exclude = %w{.svn CVS}
+ options.input = Pathname.pwd
+ options.output = Pathname.pwd + 'out'
+
opts = OptionParser.new {|opts|
- opts.banner = "Usage: #$0 [options] <arch> <arch> [<arch> ...]"
+ opts.banner = 'Usage: %s [options] arch arch [arch [arch ...]]' % $0
- opts.on(
- '-i', '--input DIRECTORY',
- 'specify input directory'
- ) {|input|
- self[:input] = Pathname.new( input ).expand_path || Pathname.pwd
+ opts.on( '-i', '--input DIRECTORY',
+ 'Change input directory', 'Defaults to \'.\'') {|i|
+ options.input = Pathname.new( i ).expand_path || options.input
}
- opts.on(
- '-o', '--output DIRECTORY',
- 'specify output directory'
- ) {|output|
- self[:output] = Pathname.new( output ).expand_path || Pathname.pwd
+ opts.on( '-o', '--output DIRECTORY',
+ 'Change output directory', 'Defaults to \'./out\'') {|o|
+ options.output = Pathname.new( o ).expand_path || options.output
}
- opts.on(
- '-e', '--exclude NAMES',
- 'specify names of files/directories to exclude'
- ) {|exclude|
- self[:exclude] = Set.new
- exclude.split.each {|item|
- self[:exclude] << item
- }
+ opts.on( '-e', '--exclude PATTERN1,PATTERN2', Array,
+ 'Exclude files/directories (glob-style)') {|e|
+ options.exclude = e
}
- opts.on(
- '-d', '--dry-run',
- 'perform a dry run'
- ) {
- self[:dry_run] = true
+ opts.on( '-d', '--[no-]dry-run', 'Perform a dry run' ) {|d|
+ options.dryrun = d
}
- opts.on(
- '-f', '--force',
- 'force writing, ignoring collisions'
- ) {
- self[:force] = true
+ opts.on( '-f', '--[no-]force', 'Ignore collisions' ) {|f|
+ options.force = f
}
- opts.on(
- '-v', '--verbose',
- 'enable verbose output'
- ) {
- self[:verbose] = true
+ opts.on( '-v', '--[no-]verbose', 'Run verbosely' ) {|v|
+ options.verbose = v
}
- opts.on_tail(
- '-h', '--help',
- 'display this help and exit'
- ) {
+ opts.on_tail( '-h', '--help', 'Show this message' ) {
puts opts
exit
}
}
opts.parse!( args )
+ options
end
end
-arguments = MergeArguments.new( ARGV )
+options = MergeArguments.parse( ARGV )
# ignore duplicates and trailing slashes
ARGS = ARGV.collect {|arg| arg.chomp( '/' )}.uniq
-def true_for_all? ( path, args, first_too, &block )
+def true_for_all? ( path, opts, first_too, &block )
# checks if a predicate is true for all (but the first) architecture
result = true
iter_over = first_too ? ARGS : ARGS[1..-1]
iter_over.each {|arch|
- result = false unless yield( args[:input] + arch + path, arch )
+ result = false unless yield( opts.input + arch + path, arch )
}
return result
end
-def copy ( origin, target, args )
+def copy ( origin, target, opts )
# copies files
- unless target.exist? and !args[:force]
+ unless target.exist? and !opts.force
FileUtils.cp( origin, target,
- :noop => args[:dry_run],
- :verbose => args[:verbose]
+ :noop => opts.dryrun,
+ :verbose => opts.verbose
)
end
end
-def check_singlearch( my_path, args, regex )
+def check_singlearch( my_path, opts, regex )
# checks if a file has the correct type and architecture across all trees
- type_matches = true_for_all?( my_path, args, true ) {|filepath, arch|
+ type_matches = true_for_all?( my_path, opts, true ) {|filepath, arch|
filecall_out = %x{#{ FILE } -b "#{ filepath }"}.chomp
filecall_out =~ regex
}
- arch_matches = true_for_all?( my_path, args, true ) {|filepath, arch|
+ arch_matches = true_for_all?( my_path, opts, true ) {|filepath, arch|
lipocall_out = %x{lipo -info "#{ filepath }"}.chomp
lipocall_out =~ %r{is architecture: #{ arch }$}
}
raise 'type or architecture mismatch' unless type_matches and arch_matches
end
-def lipo ( filepath, architectures, args )
+def lipo ( filepath, architectures, opts )
# glues single-architecture files together using lipo(1)
lipoargs = Array.new
architectures.each {|arch|
- lipoargs << sprintf( '-arch %s %s', arch, args[:input] + arch + filepath )
+ lipoargs << sprintf( '-arch %s %s', arch, opts.input + arch + filepath )
}
- lipotarget = args[:output] + filepath
+ lipotarget = opts.output + filepath
lipocmd = sprintf( 'lipo %s -create -o %s', lipoargs.join( ' ' ), lipotarget )
- unless lipotarget.exist? and !args[:force]
- puts lipocmd if args[:verbose]
- system lipocmd unless args[:dry_run]
+ unless lipotarget.exist? and !opts.force
+ puts lipocmd if opts.verbose
+ system lipocmd unless opts.dryrun
end
end
-def make_wrapper ( filepath, args )
+def make_wrapper ( filepath, first, opts )
# creates a wrapper for config scripts that differ across trees
- unless ( args[:output] + filepath ).exist? and !args[:force]
- open( args[:output] + filepath, 'w' ) {|my_file|
- my_file.puts <<EOF
-#! /bin/sh
-
-DIR="#{filepath.dirname}"
-
-args=$@
-
-if [ "${args/-arch/}" != "$args" ]; then
- arch=`echo "$args" | sed 's!.*-arch *\\([^ ][^ ]*\\).*!\\1!'`;
-else
- arch=`uname -p`
-fi
-
-args=`echo $@ | sed "s!-arch *${arch}!!"`
-
-exec $DIR/${arch}/#{filepath.basename} ${args}
-EOF
+ wrapper_target = opts.output + filepath
+ unless wrapper_target.exist? and !opts.force
+ wrapper_target.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" | ' +
+ '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
}
+ wrapper_target.chmod( first.stat.mode )
end
end
@@ -186,52 +164,52 @@
processed = Set.new
# make sure we're given a valid root directory
-unless arguments[:input].directory?
- raise 'invalid input directory: %s' % arguments[:input]
+unless options.input.directory?
+ raise 'invalid input directory: %s' % options.input
end
# make sure the requested architectures have corresponding subdirectories
# in the the given input directory
-unless true_for_all?( '.', arguments, true) {|filepath, arch|
+unless true_for_all?( '.', options, true) {|filepath, arch|
filepath.directory?
}
raise 'architecture missing from input directory'
end
ARGS.each {|architecture|
- FileUtils.cd arguments[:input] + architecture
+ FileUtils.cd options.input + architecture
Pathname.new( '.' ).find {|path|
- arguments[:exclude].each {|exclude_me|
+ options.exclude.each {|exclude_me|
Find.prune if path.basename.fnmatch? exclude_me
}
Find.prune if processed.include? path
- first_path = arguments[:input] + ARGS[0] + path
- unless true_for_all?( path, arguments, false ) {|filepath, arch|
+ first_path = options.input + ARGS[0] + path
+ unless true_for_all?( path, options, false ) {|filepath, arch|
begin
filepath.ftype == first_path.ftype
- # file does not exist
rescue Errno::ENOENT
+ # DEBUG: file does not exist
false
end
}
- printf "DEBUG: skipping %s\n", path
+ puts 'DEBUG: skipping %s' % path
Find.prune
end
case first_path.ftype
# handle file type: directory
when 'directory'
- my_dir = arguments[:output] + path
- my_dir.mkpath unless arguments[:dry_run]
+ my_dir = options.output + path
+ my_dir.mkpath unless options.dryrun
# handle file type: symlinks
when 'link'
link_target = first_path.readlink
- if true_for_all?( path, arguments, false ) {|filepath, arch|
- my_symlink = arguments[:input] + arch + path
+ if true_for_all?( path, options, false ) {|filepath, arch|
+ my_symlink = options.input + arch + path
my_symlink.readlink == link_target
}
- link_output = arguments[:output] + path
+ link_output = options.output + path
unless link_output.symlink? or link_output.exist?
FileUtils.copy_entry(
first_path,
@@ -242,21 +220,21 @@
# DEBUG: link targets differ
end
when 'file'
- if true_for_all?( path, arguments, false ) {|filepath, arch|
+ if true_for_all?( path, options, false ) {|filepath, arch|
FileUtils.identical?( filepath, first_path )
}
- copy( first_path, arguments[:output] + path, arguments )
+ copy( first_path, options.output + path, options )
Find.prune
end
case path.extname
# handle file type: header files
when '.h', '.hpp'
- unless ( arguments[:output] + path ).exist? and !arguments[:force]
- open( arguments[:output] + path, 'w' ) {|my_file|
+ unless ( options.output + path ).exist? and !options.force
+ open( options.output + path, 'w' ) {|my_file|
ARGS.each {|arch|
- my_file.printf "#ifdef __%s__\n", arch
- my_file.puts open( arguments[:input] + arch + path, 'r' ).read
+ my_file.puts '#ifdef __%s__' % arch
+ my_file.puts open( options.input + arch + path, 'r' ).read
my_file.puts '#endif'
}
}
@@ -264,9 +242,9 @@
# handle file type: pkg-config files
when '.pc'
ARGS.each {|arch|
- copy_target = arguments[:output] + path.dirname + arch + path.basename
- copy_target.dirname.mkpath unless arguments[:dry_run]
- copy( arguments[:input] + arch + path, copy_target, arguments )
+ copy_target = options.output + path.dirname + arch + path.basename
+ copy_target.dirname.mkpath unless options.dryrun
+ copy( options.input + arch + path, copy_target, options )
}
# handle file type: other files
else
@@ -274,18 +252,18 @@
case file_output
# handle file type: ar archives
when %r{^current ar archive}
- check_singlearch( path, arguments, %r{^current ar archive} )
- lipo( path, ARGS, arguments )
+ check_singlearch( path, options, %r{^current ar archive} )
+ lipo( path, ARGS, options )
# handle file type: mach-o files
when %r{^Mach-O}
- check_singlearch( path, arguments, %r{^Mach-O} )
+ check_singlearch( path, options, %r{^Mach-O} )
links = Hash.new
ARGS.each {|my_arch|
links[my_arch] = %x{
#{
my_arch[-2..-1] == '64' ? 'otool64' : 'otool'
} -arch #{ my_arch } -LX #{
- arguments[:input] + my_arch + path
+ options.input + my_arch + path
}
}.split( "\n" ).collect {|dep_line|
dep_line.lstrip.gsub(
@@ -304,18 +282,19 @@
end
end
}
- lipo( path, ARGS, arguments )
+ lipo( path, ARGS, options )
when 'Bourne shell script text executable'
unless path.basename.to_s[-7..-1] == '-config'
Find.prune
- # ERROR: no way to handle a shell script in general
+ # DEBUG: no way to handle a shell script in general
end
+ # handle file type: config script
ARGS.each {|arch|
- copy_target=arguments[:output] + path.dirname + arch + path.basename
- copy_target.dirname.mkpath unless arguments[:dry_run]
- copy( arguments[:input] + arch + path, copy_target, arguments )
+ copy_target=options.output + path.dirname + arch + path.basename
+ copy_target.dirname.mkpath unless options.dryrun
+ copy( options.input + arch + path, copy_target, options )
}
- make_wrapper( path, arguments )
+ make_wrapper( path, first_path, options )
else
# DEBUG: unable to determine file type
end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20070708/f60b8334/attachment.html
More information about the macports-changes
mailing list