devdaily home | apple | java | perl | unix | directory | blog

What this is

This file is included in the DevDaily.com "Ruby Source Code Warehouse" project. The intent of this project is to help you "Learn Ruby by Example" TM.

Other links

The source code

#
# This file is automatically generated. DO NOT MODIFY!
#
# install.rb
#
#   Copyright (c) 2000-2002 Minero Aoki 
#
#   This program is free software.
#   You can distribute/modify this program under the terms of
#   the GNU Lesser General Public License version 2.
#

### begin compat.rb

unless Enumerable.instance_methods.include? 'inject' then
module Enumerable
  def inject( result )
    each do |i|
      result = yield(result, i)
    end
    result
  end
end
end

def File.read_all( fname )
  File.open(fname, 'rb') {|f| return f.read }
end

def File.write( fname, str )
  File.open(fname, 'wb') {|f| f.write str }
end

### end compat.rb
### begin config.rb

if i = ARGV.index(/\A--rbconfig=/) then
  file = $'
  ARGV.delete_at(i)
  require file
else
  require 'rbconfig'
end


class ConfigTable

  c = ::Config::CONFIG

  rubypath = c['bindir'] + '/' + c['ruby_install_name']

  major = c['MAJOR'].to_i
  minor = c['MINOR'].to_i
  teeny = c['TEENY'].to_i
  version = "#{major}.#{minor}"

  # ruby ver. >= 1.4.4?
  newpath_p = ((major >= 2) or
               ((major == 1) and
                ((minor >= 5) or
                 ((minor == 4) and (teeny >= 4)))))
  
  re = Regexp.new('\A' + Regexp.quote(c['prefix']))
  subprefix = lambda {|path|
      re === path and path.sub(re, '$prefix')
  }

  if c['rubylibdir'] then
    # 1.6.3 < V
    stdruby    = subprefix.call(c['rubylibdir'])
    siteruby   = subprefix.call(c['sitedir'])
    versite    = subprefix.call(c['sitelibdir'])
    sodir      = subprefix.call(c['sitearchdir'])
  elsif newpath_p then
    # 1.4.4 <= V <= 1.6.3
    stdruby    = "$prefix/lib/ruby/#{version}"
    siteruby   = subprefix.call(c['sitedir'])
    versite    = siteruby + '/' + version
    sodir      = "$site-ruby/#{c['arch']}"
  else
    # V < 1.4.4
    stdruby    = "$prefix/lib/ruby/#{version}"
    siteruby   = "$prefix/lib/ruby/#{version}/site_ruby"
    versite    = siteruby
    sodir      = "$site-ruby/#{c['arch']}"
  end

  DESCRIPTER = [
    [ 'prefix',    [ c['prefix'],
                     'path',
                     'path prefix of target environment' ] ],
    [ 'std-ruby',  [ stdruby,
                     'path',
                     'the directory for standard ruby libraries' ] ],
    [ 'site-ruby-common', [ siteruby,
                     'path',
                     'the directory for version-independent non-standard ruby libraries' ] ],
    [ 'site-ruby', [ versite,
                     'path',
                     'the directory for non-standard ruby libraries' ] ],
    [ 'bin-dir',   [ '$prefix/bin',
                     'path',
                     'the directory for commands' ] ],
    [ 'rb-dir',    [ '$site-ruby',
                     'path',
                     'the directory for ruby scripts' ] ],
    [ 'so-dir',    [ sodir,
                     'path',
                     'the directory for ruby extentions' ] ],
    [ 'data-dir',  [ '$prefix/share',
                     'path',
                     'the directory for shared data' ] ],
    [ 'ruby-path', [ rubypath,
                     'path',
                     'path to set to #! line' ] ],
    [ 'ruby-prog', [ rubypath,
                     'name',
                     'the ruby program using for installation' ] ],
    [ 'make-prog', [ 'make',
                     'name',
                     'the make program to compile ruby extentions' ] ],
    [ 'without-ext', [ 'no',
                       'yes/no',
                       'does not compile/install ruby extentions' ] ]
  ]

  SAVE_FILE = 'config.save'

  def ConfigTable.each_name( &block )
    keys().each( &block )
  end

  def ConfigTable.keys
    DESCRIPTER.collect {|k,*dummy| k }
  end

  def ConfigTable.each_definition( &block )
    DESCRIPTER.each( &block )
  end

  def ConfigTable.get_entry( name )
    name, ent = DESCRIPTER.assoc(name)
    ent
  end

  def ConfigTable.get_entry!( name )
    get_entry(name) or raise ArgumentError, "no such config: #{name}"
  end

  def ConfigTable.add_entry( name, vals )
    ConfigTable::DESCRIPTER.push [name,vals]
  end

  def ConfigTable.remove_entry( name )
    get_entry name or raise ArgumentError, "no such config: #{name}"
    DESCRIPTER.delete_if {|n,arr| n == name }
  end

  def ConfigTable.config_key?( name )
    get_entry(name) ? true : false
  end

  def ConfigTable.bool_config?( name )
    ent = get_entry(name) or return false
    ent[1] == 'yes/no'
  end

  def ConfigTable.value_config?( name )
    ent = get_entry(name) or return false
    ent[1] != 'yes/no'
  end

  def ConfigTable.path_config?( name )
    ent = get_entry(name) or return false
    ent[1] == 'path'
  end


  class << self

    alias newobj new

    def new
      c = newobj()
      c.__send__ :init
      c
    end

    def load
      c = newobj()
      File.file? SAVE_FILE or
              raise InstallError, "#{File.basename $0} config first"
      File.foreach( SAVE_FILE ) do |line|
        k, v = line.split( '=', 2 )
        c.instance_eval {
            @table[k] = v.strip
        }
      end
      c
    end
  
  end

  def initialize
    @table = {}
  end

  def init
    DESCRIPTER.each do |k, (default, vname, desc, default2)|
      @table[k] = default
    end
  end
  private :init

  def save
    File.open( SAVE_FILE, 'w' ) {|f|
        @table.each do |k, v|
          f.printf "%s=%s\n", k, v if v
        end
    }
  end

  def []=( k, v )
    ConfigTable.config_key? k or raise InstallError, "unknown config option #{k}"
    if ConfigTable.path_config? k then
      @table[k] = (v[0,1] != '$') ? File.expand_path(v) : v
    else
      @table[k] = v
    end
  end
    
  def []( key )
    @table[key] or return nil
    @table[key].gsub( %r<\$([^/]+)> ) { self[$1] }
  end

  def set_raw( key, val )
    @table[key] = val
  end

  def get_raw( key )
    @table[key]
  end

end


class MetaConfigEnvironment

  def self.eval_file( file )
    return unless File.file? file
    new.instance_eval File.read_all(file), file, 1
  end

  private

  def config_names
    ConfigTable.keys
  end

  def config?( name )
    ConfigTable.config_key? name
  end

  def bool_config?( name )
    ConfigTable.bool_config? name
  end

  def value_config?( name )
    ConfigTable.value_config? name
  end

  def path_config?( name )
    ConfigTable.path_config? name
  end

  def add_config( name, argname, default, desc )
    ConfigTable.add_entry name,[default,argname,desc]
  end

  def add_path_config( name, default, desc )
    add_config name, 'path', default, desc
  end

  def add_bool_config( name, default, desc )
    add_config name, 'yes/no', default ? 'yes' : 'no', desc
  end

  def set_config_default( name, default )
    if bool_config? name then
      ConfigTable.get_entry!(name)[0] = default ? 'yes' : 'no'
    else
      ConfigTable.get_entry!(name)[0] = default
    end
  end

  def remove_config( name )
    ent = ConfigTable.get_entry(name)
    ConfigTable.remove_entry name
    ent
  end

end

### end config.rb
### begin fileop.rb

module FileOperations

  def mkdir_p( dname, prefix = nil )
    dname = prefix + dname if prefix
    $stderr.puts "mkdir -p #{dname}" if verbose?
    return if no_harm?

    # does not check '/'... it's too abnormal case
    dirs = dname.split(%r_(?=/)_)
    if /\A[a-z]:\z/i === dirs[0] then
      disk = dirs.shift
      dirs[0] = disk + dirs[0]
    end
    dirs.each_index do |idx|
      path = dirs[0..idx].join('')
      Dir.mkdir path unless dir? path
    end
  end

  def rm_f( fname )
    $stderr.puts "rm -f #{fname}" if verbose?
    return if no_harm?

    if File.exist? fname or File.symlink? fname then
      File.chmod 0777, fname
      File.unlink fname
    end
  end

  def rm_rf( dn )
    $stderr.puts "rm -rf #{dn}" if verbose?
    return if no_harm?

    Dir.chdir dn
    Dir.foreach('.') do |fn|
      next if fn == '.'
      next if fn == '..'
      if dir? fn then
        verbose_off {
            rm_rf fn
        }
      else
        verbose_off {
            rm_f fn
        }
      end
    end
    Dir.chdir '..'
    Dir.rmdir dn
  end

  def mv( src, dest )
    rm_f dest
    begin
      File.link src, dest
    rescue
      File.write dest, File.read_all(src)
      File.chmod File.stat(src).mode, dest
    end
    rm_f src
  end

  def install( from, dest, mode, prefix = nil )
    $stderr.puts "install #{from} #{dest}" if verbose?
    return if no_harm?

    realdest = prefix + dest if prefix
    if dir? realdest then
      realdest += '/' + File.basename(from)
    end
    str = File.read_all(from)
    if diff? str, realdest then
      verbose_off {
          rm_f realdest if File.exist? realdest
      }
      File.write realdest, str
      File.chmod mode, realdest

      File.open( objdir + '/InstalledFiles', 'a' ) {|f| f.puts realdest }
    end
  end

  def diff?( orig, targ )
    return true unless File.exist? targ
    orig != File.read_all(targ)
  end

  def command( str )
    $stderr.puts str if verbose?
    system str or raise RuntimeError, "'system #{str}' failed"
  end

  def ruby( str )
    command config('ruby-prog') + ' ' + str
  end

  def dir?( dname )
    # for corrupted windows stat()
    File.directory?( (dname[-1,1] == '/') ? dname : dname + '/' )
  end

  def all_files( dname )
    Dir.open( dname ) {|d|
        return d.find_all {|n| File.file? "#{dname}/#{n}" }
    }
  end

  def all_dirs( dname )
    Dir.open( dname ) {|d|
        return d.find_all {|n| dir? "#{dname}/#{n}" } - %w(. ..)
    }
  end

end

### end fileop.rb
### begin base.rb

class InstallError < StandardError; end


class Installer

  Version   = '3.1.2'
  Copyright = 'Copyright (c) 2000-2002 Minero Aoki'


  @toplevel = nil

  def self.declear_toplevel_installer( inst )
    @toplevel and
        raise ArgumentError, 'more than one toplevel installer decleared'
    @toplevel = inst
  end

  def self.toplevel_installer
    @toplevel
  end


  FILETYPES = %w( bin lib ext data )

  include FileOperations

  def initialize( config, opt, srcroot, objroot )
    @config = config
    @options = opt
    @srcdir = File.expand_path(srcroot)
    @objdir = File.expand_path(objroot)
    @currdir = '.'
  end

  def inspect
    "#<#{type} #{__id__}>"
  end

  #
  # configs/options
  #

  def get_config( key )
    @config[key]
  end

  alias config get_config

  def set_config( key, val )
    @config[key] = val
  end

  def no_harm?
    @options['no-harm']
  end

  def verbose?
    @options['verbose']
  end

  def verbose_off
    save, @options['verbose'] = @options['verbose'], false
    yield
    @options['verbose'] = save
  end

  #
  # srcdir/objdir
  #

  attr_reader :srcdir
  alias srcdir_root srcdir
  alias package_root srcdir

  def curr_srcdir
    "#{@srcdir}/#{@currdir}"
  end

  attr_reader :objdir
  alias objdir_root objdir

  def curr_objdir
    "#{@objdir}/#{@currdir}"
  end

  def srcfile( path )
    curr_srcdir + '/' + path
  end

  def srcexist?( path )
    File.exist? srcfile(path)
  end

  def srcdirectory?( path )
    dir? srcfile(path)
  end
  
  def srcfile?( path )
    File.file? srcfile(path)
  end

  def srcentries( path = '.' )
    Dir.open( curr_srcdir + '/' + path ) {|d|
        return d.to_a - %w(. ..) - hookfilenames
    }
  end

  def srcfiles( path = '.' )
    srcentries(path).find_all {|fname|
        File.file? File.join(curr_srcdir, path, fname)
    }
  end

  def srcdirectories( path = '.' )
    srcentries(path).find_all {|fname|
        dir? File.join(curr_srcdir, path, fname)
    }
  end

  def dive_into( rel )
    return unless dir? "#{@srcdir}/#{rel}"

    dir = File.basename(rel)
    Dir.mkdir dir unless dir? dir
    save = Dir.pwd
    Dir.chdir dir
    $stderr.puts '---> ' + rel if verbose?
    @currdir = rel
    yield
    Dir.chdir save
    $stderr.puts '<--- ' + rel if verbose?
    @currdir = File.dirname(rel)
  end

  #
  # config
  #

  def exec_config
    exec_task_traverse 'config'
  end

  def config_dir_bin( rel )
  end

  def config_dir_lib( rel )
  end

  def config_dir_ext( rel )
    extconf if extdir? curr_srcdir
  end

  def extconf
    opt = @options['config-opt'].join(' ')
    command "#{config('ruby-prog')} #{curr_srcdir}/extconf.rb #{opt}"
  end

  def config_dir_data( rel )
  end

  #
  # setup
  #

  def exec_setup
    exec_task_traverse 'setup'
  end

  def setup_dir_bin( relpath )
    all_files( curr_srcdir ).each do |fname|
      add_rubypath "#{curr_srcdir}/#{fname}"
    end
  end

  SHEBANG_RE = /\A\#!\s*\S*ruby\S*/

  def add_rubypath( path )
    $stderr.puts %Q if verbose?
    return if no_harm?

    tmpfile = File.basename(path) + '.tmp'
    begin
      File.open( path ) {|r|
      File.open( tmpfile, 'w' ) {|w|
          first = r.gets
          return unless SHEBANG_RE === first   # reject '/usr/bin/env ruby'

          w.print first.sub( SHEBANG_RE, '#!' + config('ruby-path') )
          w.write r.read
      } }
      mv tmpfile, File.basename(path)
    ensure
      rm_f tmpfile if File.exist? tmpfile
    end
  end

  def setup_dir_lib( relpath )
  end

  def setup_dir_ext( relpath )
    if extdir? curr_srcdir then
      make
    end
  end

  def make
    command config('make-prog')
  end

  def setup_dir_data( relpath )
  end

  #
  # install
  #

  def exec_install
    exec_task_traverse 'install'
  end

  def install_dir_bin( rel )
    install_files targfiles, config('bin-dir') + '/' + rel, 0755
  end

  def install_dir_lib( rel )
    install_files targfiles, config('rb-dir') + '/' + rel, 0644
  end

  def install_dir_ext( rel )
    if extdir? curr_srcdir then
      install_dir_ext_main File.dirname(rel)
    end
  end

  def install_dir_ext_main( rel )
    install_files allext('.'), config('so-dir') + '/' + rel, 0555
  end

  def install_dir_data( rel )
    install_files targfiles, config('data-dir') + '/' + rel, 0644
  end

  def install_files( list, dest, mode )
    mkdir_p dest, @options['install-prefix']
    list.each do |fname|
      install fname, dest, mode, @options['install-prefix']
    end
  end
  
  def targfiles
    (targfilenames() - hookfilenames()).collect {|fname|
        File.exist?(fname) ? fname : File.join(curr_srcdir(), fname)
    }
  end

  def targfilenames
    [ curr_srcdir(), '.' ].inject([]) {|ret, dir|
        ret | all_files(dir)
    }
  end

  def hookfilenames
    %w( pre-%s post-%s pre-%s.rb post-%s.rb ).collect {|fmt|
        %w( config setup install clean ).collect {|t| sprintf fmt, t }
    }.flatten
  end

  def allext( dir )
    _allext(dir) or raise InstallError,
        "no extention exists: Have you done 'ruby #{$0} setup' ?"
  end

  DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/

  def _allext( dir )
    Dir.open( dir ) {|d|
        return d.find_all {|fname| DLEXT === fname }
    }
  end

  #
  # clean
  #

  def exec_clean
    exec_task_traverse 'clean'
    rm_f 'config.save'
    rm_f 'InstalledFiles'
  end

  def clean_dir_bin( rel )
  end

  def clean_dir_lib( rel )
  end

  def clean_dir_ext( rel )
    clean
  end
  
  def clean
    command config('make-prog') + ' clean' if File.file? 'Makefile'
  end

  def clean_dir_data( rel )
  end

  #
  # lib
  #

  def exec_task_traverse( task )
    run_hook 'pre-' + task
    FILETYPES.each do |type|
      if config('without-ext') == 'yes' and type == 'ext' then
        $stderr.puts 'skipping ext/* by user option' if verbose?
        next
      end
      traverse task, type, task + '_dir_' + type
    end
    run_hook 'post-' + task
  end

  def traverse( task, rel, mid )
    dive_into( rel ) {
        run_hook 'pre-' + task
        __send__ mid, rel.sub( %r_\A.*?(?:/|\z)_, '' )
        all_dirs( curr_srcdir ).each do |d|
          traverse task, rel + '/' + d, mid
        end
        run_hook 'post-' + task
    }
  end

  def run_hook( name )
    try_run_hook curr_srcdir + '/' + name           or
    try_run_hook curr_srcdir + '/' + name + '.rb'
  end

  def try_run_hook( fname )
    return false unless File.file? fname

    env = self.dup
    begin
      env.instance_eval File.read_all(fname), fname, 1
    rescue
      raise InstallError, "hook #{fname} failed:\n" + $!.message
    end
    true
  end

  def extdir?( dir )
    File.exist? dir + '/MANIFEST'
  end

end

### end base.rb
### begin toplevel.rb

class ToplevelInstaller < Installer

  TASKS = [
    [ 'config',   'saves your configurations' ],
    [ 'show',     'shows current configuration' ],
    [ 'setup',    'compiles extention or else' ],
    [ 'install',  'installs files' ],
    [ 'clean',    "does `make clean' for each extention" ]
  ]


  def initialize( root )
    super nil, {'verbose' => true}, root, '.'
    Installer.declear_toplevel_installer self
  end


  def execute
    run_metaconfigs

    case task = parsearg_global()
    when 'config'
      @config = ConfigTable.new
    else
      @config = ConfigTable.load
    end
    parsearg_TASK task

    exectask task
  end


  def run_metaconfigs
    MetaConfigEnvironment.eval_file "#{srcdir_root}/#{metaconfig}"
  end

  def metaconfig
    'metaconfig'
  end


  def exectask( task )
    if task == 'show' then
      exec_show
    else
      try task
    end
  end

  def try( task )
    $stderr.printf "#{File.basename $0}: entering %s phase...\n", task if verbose?
    begin
      __send__ 'exec_' + task
    rescue
      $stderr.printf "%s failed\n", task
      raise
    end
    $stderr.printf "#{File.basename $0}: %s done.\n", task if verbose?
  end

  #
  # processing arguments
  #

  def parsearg_global
    task_re = /\A(?:#{TASKS.collect {|i| i[0] }.join '|'})\z/

    while arg = ARGV.shift do
      case arg
      when /\A\w+\z/
        task_re === arg or raise InstallError, "wrong task: #{arg}"
        return arg

      when '-q', '--quiet'
        @options['verbose'] = false

      when       '--verbose'
        @options['verbose'] = true

      when '-h', '--help'
        print_usage $stdout
        exit 0

      when '-v', '--version'
        puts "#{File.basename $0} version #{Version}"
        exit 0
      
      when '--copyright'
        puts Copyright
        exit 0

      else
        raise InstallError, "unknown global option '#{arg}'"
      end
    end

    raise InstallError, 'no task or global option given'
  end


  def parsearg_TASK( task )
    mid = "parsearg_#{task}"
    if respond_to? mid, true then
      __send__ mid
    else
      ARGV.empty? or
          raise InstallError, "#{task}:  unknown options: #{ARGV.join ' '}"
    end
  end

  def parsearg_config
    re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
    @options['config-opt'] = []

    while i = ARGV.shift do
      if /\A--?\z/ === i then
        @options['config-opt'] = ARGV.dup
        break
      end
      m = re.match(i) or raise InstallError, "config: unknown option #{i}"
      name, value = m.to_a[1,2]
      if value then
        if ConfigTable.bool_config?(name) then
          /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i === value or raise InstallError, "config: --#{name} allows only yes/no for argument"
          value = (/\Ay(es)?|\At(rue)/i === value) ? 'yes' : 'no'
        end
      else
        ConfigTable.bool_config?(name) or raise InstallError, "config: --#{name} requires argument"
        value = 'yes'
      end
      @config[name] = value
    end
  end

  def parsearg_install
    @options['no-harm'] = false
    @options['install-prefix'] = ''
    while a = ARGV.shift do
      case a
      when /\A--no-harm\z/
        @options['no-harm'] = true
      when /\A--prefix=(.*)\z/
        path = $1
        path = File.expand_path(path) unless path[0,1] == '/'
        @options['install-prefix'] = path
      else
        raise InstallError, "install: unknown option #{a}"
      end
    end
  end


  def print_usage( out )
    out.puts
    out.puts 'Usage:'
    out.puts "  ruby #{File.basename $0} "
    out.puts "  ruby #{File.basename $0} []  []"

    fmt = "  %-20s %s\n"
    out.puts
    out.puts 'Global options:'
    out.printf fmt, '-q,--quiet',   'suppress message outputs'
    out.printf fmt, '   --verbose', 'output messages verbosely'
    out.printf fmt, '-h,--help',    'print this message'
    out.printf fmt, '-v,--version', 'print version and quit'
    out.printf fmt, '--copyright',  'print copyright and quit'

    out.puts
    out.puts 'Tasks:'
    TASKS.each do |name, desc|
      out.printf "  %-10s  %s\n", name, desc
    end

    out.puts
    out.puts 'Options for config:'
    ConfigTable.each_definition do |name, (default, arg, desc, default2)|
      out.printf "  %-20s %s [%s]\n",
                 '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
                 desc,
                 default2 || default
    end
    out.printf "  %-20s %s [%s]\n",
        '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"

    out.puts
    out.puts 'Options for install:'
    out.printf "  %-20s %s [%s]\n",
        '--no-harm', 'only display what to do if given', 'off'

    out.puts
  end

  #
  # config
  #

  def exec_config
    super
    @config.save
  end

  #
  # show
  #

  def exec_show
    ConfigTable.each_name do |k|
      v = @config.get_raw(k)
      if not v or v.empty? then
        v = '(not specified)'
      end
      printf "%-10s %s\n", k, v
    end
  end

end

### end toplevel.rb

if $0 == __FILE__ then
  begin
    installer = ToplevelInstaller.new( File.dirname($0) )
    installer.execute
  rescue
    raise if $DEBUG
    $stderr.puts $!.message
    $stderr.puts "try 'ruby #{$0} --help' for usage"
    exit 1
  end
end




Copyright 1998-2008 Alvin Alexander
All Rights Reserved.
 
devdaily.com is based in louisville, kentucky, and this web site is hosted by godaddy.com