[26785] users/pipping/merge.rb

source_changes at macosforge.org source_changes at macosforge.org
Sat Jul 7 08:27:07 PDT 2007


Revision: 26785
          http://trac.macosforge.org/projects/macports/changeset/26785
Author:   pipping at macports.org
Date:     2007-07-07 08:27:05 -0700 (Sat, 07 Jul 2007)

Log Message:
-----------
r40
  add/clean up comments
r41
  if-to-case transition
  make full use of pathname library
r42
  replace symlink-creation with call to copy_entry, remove :preserve as it doesn't work with broken symlinks
r43
  minor changes (reformatting)
r44
  add comments that describe helper functions briefly
  allow --exclude to be passed glob-style arguments
r45
  get rid of unneccessary regex
r46
  make check_singlearch into a function

Modified Paths:
--------------
    users/pipping/merge.rb

Modified: users/pipping/merge.rb
===================================================================
--- users/pipping/merge.rb	2007-07-07 11:09:55 UTC (rev 26784)
+++ users/pipping/merge.rb	2007-07-07 15:27:05 UTC (rev 26785)
@@ -41,8 +41,8 @@
     self[:verbose] = false
 
     self[:exclude] = Set.new << '.svn' << 'CVS'
-    self[:output]  = File.join( Dir.pwd, 'out' )
-    self[:input]    = Dir.pwd
+    self[:output]  = Pathname.pwd + 'out'
+    self[:input]   = Pathname.pwd
 
     opts = OptionParser.new {|opts|
       opts.banner = "Usage: #$0 [options] <arch> <arch> [<arch> ...]"
@@ -51,14 +51,14 @@
         '-i', '--input DIRECTORY',
         'specify input directory'
       ) {|input|
-        self[:input] = File.expand_path( input ) || Dir.pwd
+        self[:input] = Pathname.new( input ).expand_path || Pathname.pwd
       }
 
       opts.on(
         '-o', '--output DIRECTORY',
         'specify output directory'
-      ) {|out|
-        self[:output] = File.expand_path( out ) || Dir.pwd
+      ) {|output|
+        self[:output] = Pathname.new( output ).expand_path || Pathname.pwd
       }
 
       opts.on(
@@ -110,244 +110,184 @@
 ARGS = ARGV.collect {|arg| arg.chomp( '/' )}.uniq
 
 def true_for_all? ( path, args, 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( File.join( args[:input], arch, path ), arch )
+    result = false unless yield( args[:input] + arch + path, arch )
   }
   return result
 end
 
 def copy ( origin, target, args )
-  if !File.exist?( target ) or args[:force]
-    FileUtils.cp(
-      origin,
-      target,
+# copies files
+  unless target.exist? and !args[:force]
+    FileUtils.cp( origin, target,
       :noop => args[:dry_run],
-      :preserve => true,
       :verbose => args[:verbose]
     )
   end
 end
 
+def check_singlearch( my_path, args, 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|
+    filecall_out = %x{#{ FILE } -b "#{ filepath }"}.chomp
+    filecall_out =~ regex
+  }
+  arch_matches = true_for_all?( my_path, args, 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 )
+# glues single-architecture files together using lipo(1)
   lipoargs = Array.new
   architectures.each {|arch|
-    lipoargs << sprintf(
-      '-arch %s %s',
-      arch, File.join(
-        args[:input], arch, filepath
-      )
-    )
+    lipoargs << sprintf( '-arch %s %s', arch, args[:input] + arch + filepath )
   }
-  lipotarget = File.join( args[:output], filepath )
-  lipocmd = sprintf(
-    'lipo %s -create -o %s',
-    lipoargs.join( ' ' ),
-    lipotarget
-  )
-  if !File.exist?( lipotarget ) or args[:force]
+  lipotarget = args[: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]
   end
 end
 
-ORIGINAL_DIR = Dir.pwd
+ORIGINAL_DIR = Pathname.pwd
 processed = Set.new
 
 # make sure we're given a valid root directory
-unless File.directory?( arguments[:input] )
-  raise sprintf(
-    'invalid input directory: %s',
-    arguments[:input]
-  )
+unless arguments[:input].directory?
+  raise sprintf( 'invalid input directory: %s', arguments[:input] )
 end
 
 # make sure the requested architectures have corresponding subdirectories
 # in the the given input directory
 unless true_for_all?( '.', arguments, true) {|filepath, arch|
-  File.directory? filepath
+  filepath.directory?
 }
   raise 'architecture missing from input directory'
 end
 
 ARGS.each {|architecture|
-  FileUtils.cd(
-    File.join( arguments[:input], architecture )
-  )
-  Find.find( '.' ) {|path|
+  FileUtils.cd arguments[:input] + architecture
+  Pathname.new( '.' ).find {|path|
     arguments[:exclude].each {|exclude_me|
-      Find.prune if File.basename( path ) == exclude_me
+      Find.prune if path.basename.fnmatch? exclude_me
     }
-    unless processed.include? path
-      my_dir = File.dirname( File.join( arguments[:output], path ) )
-      # TODO: maybe mkdir should only be called *after* we've decided what
-      #       needs to be done with the file
-      unless File.exist? my_dir
-        FileUtils.mkdir_p(
-          my_dir,
-          :noop => arguments[:dry_run],
-          :verbose => arguments[:verbose]
-        )
+    Find.prune if processed.include? path
+
+    first_path = arguments[:input] + ARGS[0] + path
+    unless true_for_all?( path, arguments, false ) {|filepath, arch|
+      begin
+        filepath.ftype == first_path.ftype
+      # file does not exist
+      rescue Errno::ENOENT
+        false
       end
-      first_path = File.join( arguments[:input], ARGS[0], path )
-      if true_for_all?( path, arguments, true ) {|filepath, arch|
-        !FileTest.symlink? filepath
+    }
+      printf "DEBUG: skipping %s\n", 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]
+    # 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
+        my_symlink.readlink == link_target
       }
-        if true_for_all?( path, arguments, true ) {|filepath, arch|
-          File.exist? filepath
+        link_output = arguments[:output] + path
+        unless link_output.symlink? or link_output.exist?
+          FileUtils.copy_entry(
+            first_path,
+            link_output
+          )
+        end
+      else
+        # DEBUG: link targets differ
+      end
+    when 'file'
+      if true_for_all?( path, arguments, false ) {|filepath, arch|
+        FileUtils.identical?( filepath, first_path )
+      }
+        copy( first_path, arguments[:output] + path, arguments )
+        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' ) {|file|
+            ARGS.each {|arch|
+              file.printf '#ifdef __%s__\n', arch
+              file.puts open( arguments[:input] + arch + path, 'r' ).read
+              file.puts '#endif'
+            }
+          }
+        end
+      # 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 )
         }
-          if true_for_all?( path, arguments, true ) {|filepath, arch|
-            !File.directory? filepath
+      # handle file type: other files
+      else
+        file_output = %x{ #{ FILE } -b "#{ first_path }" }.chomp
+        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 )
+        # handle file type: mach-o files
+        when %r{^Mach-O}
+          check_singlearch( path, arguments, %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
+              }
+            }.split( "\n" ).collect {|dep_line|
+              dep_line.lstrip.gsub(
+                %r{ \(compatibility version \d+(\.\d+)*, current version \d+(\.\d+)*\)}, ''
+              )
+            }.reject {|dep|
+              dep[0..7] == '/usr/lib'
+            }.to_set
           }
-            if true_for_all?( path, arguments, false ) {|filepath, arch|
-              FileUtils.identical?( filepath, first_path )
-            }
-              copy( first_path, File.join( arguments[:output], path ), arguments )
-            else
-              case File.basename path
-              when %r{\.h$}, %r{\.hpp$}
-                if arguments[:force] or !File.exists?(
-                  File.join( arguments[:output], path )
+          ARGS.each {|my_arch|
+            unless links[my_arch] == links[ARGS[0]]
+              missing_in  = links[my_arch]-links[ARGS[0]]
+              missing_out = links[ARGS[0]]-links[my_arch]
+              if missing_in.any? or missing_out.any?
+                raise sprintf(
+                  'difference in linking encountered: file %s',
+                  path
                 )
-                  open( File.join( arguments[:output], path ), 'w' ) {|file|
-                    ARGS.each {|arch|
-                      file.printf '#ifdef __%s__\n', arch
-                      file.puts open(
-                        File.join( arguments[:input], arch, path ), 'r'
-                      ).read
-                      file.puts '#endif'
-                    }
-                  }
-                end
-              when %r{\.pc$}
-                ARGS.each {|arch|
-                  copy_target = File.join(
-                    arguments[:output],
-                    File.dirname( path ),
-                    arch,
-                    File.basename( path )
-                  )
-                  unless File.exists? File.dirname( copy_target )
-                    FileUtils.mkdir_p(
-                      File.dirname( copy_target ),
-                      :verbose => arguments[:verbose],
-                      :noop => arguments[:dry_run]
-                    )
-                  end
-                  copy(
-                    File.join( arguments[:input], arch, path ),
-                    copy_target,
-                    arguments
-                  )
-                }
-              else
-                file_output = %x{ #{ FILE } -b "#{ first_path }" }.chomp
-                case file_output
-                when %r{^current ar archive}
-                  if true_for_all?( path, arguments, false ) {|filepath, arch|
-                    filecall_out = %x{#{ FILE } -b "#{ filepath }"}.chomp
-                    filecall_out =~ %r{^current ar archive}
-                  }
-                    if true_for_all?( path, arguments, true ) {|filepath, arch|
-                      lipocall_out = %x{lipo -info "#{ filepath }"}.chomp
-                      lipocall_out =~ %r{is architecture: #{ arch }$}
-                    }
-                      lipo( path, ARGS, arguments )
-                    else
-                      raise sprintf(
-                        'universal binary or wrong architecture: %s',
-                        path
-                      )
-                    end
-                  else
-                    # some files are archives, some are not
-                  end
-                when %r{^Mach-O}
-                  if true_for_all?( path, arguments, false ) {|filepath, arch|
-                    filecall_out = %x{#{ FILE } -b "#{ filepath }"}.chomp
-                    filecall_out =~ %r{^Mach-O}
-                  }
-                    if true_for_all?( path, arguments, true ) {|filepath, arch|
-                      lipocall_out = %x{lipo -info "#{ filepath }"}.chomp
-                      lipocall_out =~ %r{is architecture: #{arch}$}
-                    }
-                      links = Hash.new
-                      ARGS.each {|my_arch|
-                        links[my_arch] = %x{
-                          #{
-                            my_arch =~ %r{64$} ? 'otool64' : 'otool'
-                          } -arch #{ my_arch } -LX #{
-                            File.join( arguments[:input], my_arch, path )
-                          }
-                        }.split( "\n" ).collect {|dep_line|
-                          dep_line.lstrip.gsub(
-                            %r{ \(compatibility version \d+(\.\d+)*, current version \d+(\.\d+)*\)}, ''
-                          )
-                        }.reject {|dep|
-                          dep =~ %r{^\/usr\/lib\/}
-                        }.to_set
-                      }
-                      ARGS.each {|my_arch|
-                        unless links[my_arch] == links[ARGS[0]]
-                          missing_in  = links[my_arch]-links[ARGS[0]]
-                          missing_out = links[ARGS[0]]-links[my_arch]
-                          if missing_in.any? or missing_out.any?
-                            raise sprintf(
-                              'difference in linking encountered: file %s',
-                              path
-                            )
-                          end
-                        end
-                      }
-                      lipo( path, ARGS, arguments )
-                    else
-                      raise sprintf(
-                        'universal binary or wrong architecture: %s',
-                        path
-                      )
-                    end
-                  else
-                    # some files are mach-o, some are not
-                  end
-                else
-                  # unable to determine file type
-                end
               end
             end
-          end
+          }
+          lipo( path, ARGS, arguments )
         else
-          # a file is not present in all trees.
+          # DEBUG: unable to determine file type
         end
-      elsif true_for_all?( path, arguments, true ) {|filepath, arch|
-        FileTest.symlink? filepath
-      }
-        link_target = Pathname.new( first_path ).readlink
-        if true_for_all?( path, arguments, false ) {|filepath, arch|
-          my_link_target = Pathname.new(
-            File.join( arguments[:input], arch, path )
-          ).readlink
-          my_link_target == link_target
-        }
-          link_output = File.join( arguments[:output], path )
-          if !File.exists? link_output or arguments[:force]
-            FileUtils.symlink(
-              link_target,
-              link_output, 
-              :force => arguments[:force],
-              :verbose => arguments[:verbose],
-              :noop => arguments [:dry_run]
-            )
-          end
-        else
-          # link targets differ
-        end
-      else
-        # dealing with a mix of at least one symlink and items that are not
-        # symlinks
       end
-      processed << path
     end
+    processed << path
   }
 }
 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20070707/0058acf5/attachment.html


More information about the macports-changes mailing list