1#!./miniruby
2
3begin
4  load "./rbconfig.rb"
5rescue LoadError
6  CONFIG = Hash.new {""}
7else
8  include RbConfig
9  $".unshift File.expand_path("./rbconfig.rb")
10end
11
12srcdir = File.expand_path('../..', __FILE__)
13unless defined?(CROSS_COMPILING) and CROSS_COMPILING
14  $:.replace([srcdir+"/lib", Dir.pwd])
15end
16require 'fileutils'
17require 'shellwords'
18require 'optparse'
19require 'optparse/shellwords'
20require 'ostruct'
21require_relative 'vcs'
22
23STDOUT.sync = true
24File.umask(0)
25
26begin
27  $vcs = VCS.detect(File.expand_path('../..', __FILE__))
28rescue VCS::NotFoundError
29  $vcs = nil
30end
31
32def parse_args(argv = ARGV)
33  $mantype = 'doc'
34  $destdir = nil
35  $extout = nil
36  $make = 'make'
37  $mflags = []
38  $install = []
39  $installed_list = nil
40  $dryrun = false
41  $rdocdir = nil
42  $data_mode = 0644
43  $prog_mode = 0755
44  $dir_mode = nil
45  $script_mode = nil
46  $strip = false
47  $cmdtype = (if File::ALT_SEPARATOR == '\\'
48                File.exist?("rubystub.exe") ? 'exe' : 'bat'
49              end)
50  mflags = []
51  opt = OptionParser.new
52  opt.on('-n', '--dry-run') {$dryrun = true}
53  opt.on('--dest-dir=DIR') {|dir| $destdir = dir}
54  opt.on('--extout=DIR') {|dir| $extout = (dir unless dir.empty?)}
55  opt.on('--make=COMMAND') {|make| $make = make}
56  opt.on('--mantype=MAN') {|man| $mantype = man}
57  opt.on('--make-flags=FLAGS', '--mflags', Shellwords) do |v|
58    if arg = v.first
59      arg.insert(0, '-') if /\A[^-][^=]*\Z/ =~ arg
60    end
61    $mflags.concat(v)
62  end
63  opt.on('-i', '--install=TYPE', $install_procs.keys) do |ins|
64    $install << ins
65  end
66  opt.on('--data-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode|
67    $data_mode = mode
68  end
69  opt.on('--prog-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode|
70    $prog_mode = mode
71  end
72  opt.on('--dir-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode|
73    $dir_mode = mode
74  end
75  opt.on('--script-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode|
76    $script_mode = mode
77  end
78  opt.on('--installed-list [FILENAME]') {|name| $installed_list = name}
79  opt.on('--rdoc-output [DIR]') {|dir| $rdocdir = dir}
80  opt.on('--cmd-type=TYPE', %w[bat cmd plain]) {|cmd| $cmdtype = (cmd unless cmd == 'plain')}
81  opt.on('--[no-]strip') {|strip| $strip = strip}
82
83  opt.order!(argv) do |v|
84    case v
85    when /\AINSTALL[-_]([-\w]+)=(.*)/
86      argv.unshift("--#{$1.tr('_', '-')}=#{$2}")
87    when /\A\w[-\w+]*=\z/
88      mflags << v
89    when /\A\w[-\w+]*\z/
90      $install << v.intern
91    else
92      raise OptionParser::InvalidArgument, v
93    end
94  end rescue abort "#{$!.message}\n#{opt.help}"
95
96  unless defined?(RbConfig)
97    puts opt.help
98    exit
99  end
100
101  $make, *rest = Shellwords.shellwords($make)
102  $mflags.unshift(*rest) unless rest.empty?
103  $mflags.unshift(*mflags)
104
105  def $mflags.set?(flag)
106    grep(/\A-(?!-).*#{flag.chr}/i) { return true }
107    false
108  end
109  def $mflags.defined?(var)
110    grep(/\A#{var}=(.*)/) {return block_given? ? yield($1) : $1}
111    false
112  end
113
114  if $mflags.set?(?n)
115    $dryrun = true
116  else
117    $mflags << '-n' if $dryrun
118  end
119
120  $destdir ||= $mflags.defined?("DESTDIR")
121  if $extout ||= $mflags.defined?("EXTOUT")
122    RbConfig.expand($extout)
123  end
124
125  $continue = $mflags.set?(?k)
126
127  if $installed_list ||= $mflags.defined?('INSTALLED_LIST')
128    RbConfig.expand($installed_list, RbConfig::CONFIG)
129    $installed_list = open($installed_list, "ab")
130    $installed_list.sync = true
131  end
132
133  $rdocdir ||= $mflags.defined?('RDOCOUT')
134
135  $dir_mode ||= $prog_mode | 0700
136  $script_mode ||= $prog_mode
137end
138
139$install_procs = Hash.new {[]}
140def install?(*types, &block)
141  $install_procs[:all] <<= block
142  types.each do |type|
143    $install_procs[type] <<= block
144  end
145end
146
147def strip_file(files)
148  if !defined?($strip_command) and (cmd = CONFIG["STRIP"])
149    case cmd
150    when "", "true", ":" then return
151    else $strip_command = Shellwords.shellwords(cmd)
152    end
153  elsif !$strip_command
154    return
155  end
156  system(*($strip_command + [files].flatten))
157end
158
159def install(src, dest, options = {})
160  options = options.clone
161  strip = options.delete(:strip)
162  options[:preserve] = true
163  d = with_destdir(dest)
164  super(src, d, options)
165  srcs = Array(src)
166  if strip
167    d = srcs.map {|src| File.join(d, File.basename(src))} if $made_dirs[dest]
168    strip_file(d)
169  end
170  if $installed_list
171    dest = srcs.map {|src| File.join(dest, File.basename(src))} if $made_dirs[dest]
172    $installed_list.puts dest
173  end
174end
175
176def ln_sf(src, dest)
177  super(src, with_destdir(dest))
178  $installed_list.puts dest if $installed_list
179end
180
181$made_dirs = {}
182def makedirs(dirs)
183  dirs = fu_list(dirs)
184  dirs.collect! do |dir|
185    realdir = with_destdir(dir)
186    realdir unless $made_dirs.fetch(dir) do
187      $made_dirs[dir] = true
188      $installed_list.puts(File.join(dir, "")) if $installed_list
189      File.directory?(realdir)
190    end
191  end.compact!
192  super(dirs, :mode => $dir_mode) unless dirs.empty?
193end
194
195FalseProc = proc {false}
196def path_matcher(pat)
197  if pat and !pat.empty?
198    proc {|f| pat.any? {|n| File.fnmatch?(n, f)}}
199  else
200    FalseProc
201  end
202end
203
204def install_recursive(srcdir, dest, options = {})
205  opts = options.clone
206  noinst = opts.delete(:no_install)
207  glob = opts.delete(:glob) || "*"
208  subpath = (srcdir.size+1)..-1
209  prune = []
210  skip = []
211  if noinst
212    if Array === noinst
213      prune = noinst.grep(/#{File::SEPARATOR}/o).map!{|f| f.chomp(File::SEPARATOR)}
214      skip = noinst.grep(/\A[^#{File::SEPARATOR}]*\z/o)
215    else
216      if noinst.index(File::SEPARATOR)
217        prune = [noinst]
218      else
219        skip = [noinst]
220      end
221    end
222  end
223  skip |= %w"#*# *~ *.old *.bak *.orig *.rej *.diff *.patch *.core"
224  prune = path_matcher(prune)
225  skip = path_matcher(skip)
226  File.directory?(srcdir) or return rescue return
227  paths = [[srcdir, dest, true]]
228  found = []
229  while file = paths.shift
230    found << file
231    file, d, dir = *file
232    if dir
233      files = []
234      Dir.foreach(file) do |f|
235        src = File.join(file, f)
236        d = File.join(dest, dir = src[subpath])
237        stat = File.lstat(src) rescue next
238        if stat.directory?
239          files << [src, d, true] if /\A\./ !~ f and !prune[dir]
240        elsif stat.symlink?
241          # skip
242        else
243          files << [src, d, false] if File.fnmatch?(glob, f) and !skip[f]
244        end
245      end
246      paths.insert(0, *files)
247    end
248  end
249  for src, d, dir in found
250    if dir
251      makedirs(d)
252    else
253      makedirs(d[/.*(?=\/)/m])
254      if block_given?
255        yield src, d, opts
256      else
257        install src, d, opts
258      end
259    end
260  end
261end
262
263def open_for_install(path, mode)
264  data = open(realpath = with_destdir(path), "rb") {|f| f.read} rescue nil
265  newdata = yield
266  unless $dryrun
267    unless newdata == data
268      open(realpath, "wb", mode) {|f| f.write newdata}
269    end
270    File.chmod(mode, realpath)
271  end
272  $installed_list.puts path if $installed_list
273end
274
275def with_destdir(dir)
276  return dir if !$destdir or $destdir.empty?
277  dir = dir.sub(/\A\w:/, '') if File::PATH_SEPARATOR == ';'
278  $destdir + dir
279end
280
281def prepare(mesg, basedir, subdirs=nil)
282  return unless basedir
283  case
284  when !subdirs
285    dirs = basedir
286  when subdirs.size == 0
287    subdirs = nil
288  when subdirs.size == 1
289    dirs = [basedir = File.join(basedir, subdirs)]
290    subdirs = nil
291  else
292    dirs = [basedir, *subdirs.collect {|dir| File.join(basedir, dir)}]
293  end
294  printf("installing %-18s %s%s\n", "#{mesg}:", basedir,
295         (subdirs ? " (#{subdirs.join(', ')})" : ""))
296  makedirs(dirs)
297end
298
299def CONFIG.[](name, mandatory = false)
300  value = super(name)
301  if mandatory
302    raise "CONFIG['#{name}'] must be set" if !value or value.empty?
303  end
304  value
305end
306
307exeext = CONFIG["EXEEXT"]
308
309ruby_install_name = CONFIG["ruby_install_name", true]
310rubyw_install_name = CONFIG["rubyw_install_name"]
311goruby_install_name = "go" + ruby_install_name
312
313bindir = CONFIG["bindir", true]
314libdir = CONFIG["libdir", true]
315rubyhdrdir = CONFIG["rubyhdrdir", true]
316archhdrdir = CONFIG["rubyarchhdrdir"] || (rubyhdrdir + "/" + CONFIG['arch'])
317rubylibdir = CONFIG["rubylibdir", true]
318archlibdir = CONFIG["rubyarchdir", true]
319sitelibdir = CONFIG["sitelibdir"]
320sitearchlibdir = CONFIG["sitearchdir"]
321vendorlibdir = CONFIG["vendorlibdir"]
322vendorarchlibdir = CONFIG["vendorarchdir"]
323mandir = CONFIG["mandir", true]
324docdir = CONFIG["docdir", true]
325configure_args = Shellwords.shellwords(CONFIG["configure_args"])
326enable_shared = CONFIG["ENABLE_SHARED"] == 'yes'
327dll = CONFIG["LIBRUBY_SO", enable_shared]
328lib = CONFIG["LIBRUBY", true]
329arc = CONFIG["LIBRUBY_A", true]
330major = CONFIG["MAJOR", true]
331minor = CONFIG["MINOR", true]
332load_relative = configure_args.include?("--enable-load-relative")
333
334install?(:local, :arch, :bin, :'bin-arch') do
335  prepare "binary commands", bindir
336
337  install ruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip
338  if rubyw_install_name and !rubyw_install_name.empty?
339    install rubyw_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip
340  end
341  if File.exist? goruby_install_name+exeext
342    install goruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip
343  end
344  if enable_shared and dll != lib
345    install dll, bindir, :mode => $prog_mode, :strip => $strip
346  end
347end
348
349install?(:local, :arch, :lib) do
350  prepare "base libraries", libdir
351
352  install lib, libdir, :mode => $prog_mode, :strip => $strip unless lib == arc
353  install arc, libdir, :mode => $data_mode
354  if dll == lib and dll != arc
355    for link in CONFIG["LIBRUBY_ALIASES"].split
356      ln_sf(dll, File.join(libdir, link))
357    end
358  end
359
360  prepare "arch files", archlibdir
361  install "rbconfig.rb", archlibdir, :mode => $data_mode
362  if CONFIG["ARCHFILE"]
363    for file in CONFIG["ARCHFILE"].split
364      install file, archlibdir, :mode => $data_mode
365    end
366  end
367end
368
369install?(:local, :arch, :data) do
370  pc = CONFIG["ruby_pc"]
371  if pc and File.file?(pc) and File.size?(pc)
372    prepare "pkgconfig data", pkgconfigdir = File.join(libdir, "pkgconfig")
373    install pc, pkgconfigdir, :mode => $data_mode
374  end
375end
376
377install?(:ext, :arch, :'ext-arch') do
378  prepare "extension objects", archlibdir
379  noinst = %w[-* -*/] | (CONFIG["no_install_files"] || "").split
380  install_recursive("#{$extout}/#{CONFIG['arch']}", archlibdir, :no_install => noinst, :mode => $prog_mode, :strip => $strip)
381  prepare "extension objects", sitearchlibdir
382  prepare "extension objects", vendorarchlibdir
383end
384install?(:ext, :arch, :'ext-arch') do
385  prepare "extension headers", archhdrdir
386  install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "*.h", :mode => $data_mode)
387end
388install?(:ext, :comm, :'ext-comm') do
389  prepare "extension scripts", rubylibdir
390  install_recursive("#{$extout}/common", rubylibdir, :mode => $data_mode)
391  prepare "extension scripts", sitelibdir
392  prepare "extension scripts", vendorlibdir
393end
394install?(:ext, :comm, :'ext-comm') do
395  hdrdir = rubyhdrdir + "/ruby"
396  prepare "extension headers", hdrdir
397  install_recursive("#{$extout}/include/ruby", hdrdir, :glob => "*.h", :mode => $data_mode)
398end
399
400install?(:doc, :rdoc) do
401  if $rdocdir
402    ridatadir = File.join(CONFIG['ridir'], CONFIG['ruby_version'], "system")
403    prepare "rdoc", ridatadir
404    install_recursive($rdocdir, ridatadir, :mode => $data_mode)
405  end
406end
407install?(:doc, :capi) do
408  prepare "capi-docs", docdir
409  install_recursive "doc/capi", docdir+"/capi", :mode => $data_mode
410end
411
412if load_relative
413  PROLOG_SCRIPT = <<EOS
414#!/bin/sh\n# -*- ruby -*-
415bindir=`#{CONFIG["CHDIR"]} "${0%/*}" 2>/dev/null; pwd`
416EOS
417  if CONFIG["LIBRUBY_RELATIVE"] != 'yes' and libpathenv = CONFIG["LIBPATHENV"]
418    pathsep = File::PATH_SEPARATOR
419    PROLOG_SCRIPT << <<EOS
420prefix="${bindir%/bin}"
421export #{libpathenv}="$prefix/lib${#{libpathenv}#{pathsep}+#{pathsep}$#{libpathenv}}"
422EOS
423  end
424  PROLOG_SCRIPT << %Q[exec "$bindir/#{ruby_install_name}" -x "$0" "$@"\n]
425else
426  PROLOG_SCRIPT = nil
427end
428
429install?(:local, :comm, :bin, :'bin-comm') do
430  prepare "command scripts", bindir
431
432  ruby_shebang = File.join(bindir, ruby_install_name)
433  if File::ALT_SEPARATOR
434    ruby_bin = ruby_shebang.tr(File::SEPARATOR, File::ALT_SEPARATOR)
435    if $cmdtype == 'exe'
436      stub = File.open("rubystub.exe", "rb") {|f| f.read} << "\n" rescue nil
437    end
438  end
439  if trans = CONFIG["program_transform_name"]
440    exp = []
441    trans.gsub!(/\$\$/, '$')
442    trans.scan(%r[\G[\s;]*(/(?:\\.|[^/])*/)?([sy])(\\?\W)((?:(?!\3)(?:\\.|.))*)\3((?:(?!\3)(?:\\.|.))*)\3([gi]*)]) do
443      |addr, cmd, sep, pat, rep, opt|
444      addr &&= Regexp.new(addr[/\A\/(.*)\/\z/, 1])
445      case cmd
446      when 's'
447        next if pat == '^' and rep.empty?
448        exp << [addr, (opt.include?('g') ? :gsub! : :sub!),
449                Regexp.new(pat, opt.include?('i')), rep.gsub(/&/){'\&'}]
450      when 'y'
451        exp << [addr, :tr!, Regexp.quote(pat), rep]
452      end
453    end
454    trans = proc do |base|
455      exp.each {|addr, opt, pat, rep| base.__send__(opt, pat, rep) if !addr or addr =~ base}
456      base
457    end
458  elsif /ruby/ =~ ruby_install_name
459    trans = proc {|base| ruby_install_name.sub(/ruby/, base)}
460  else
461    trans = proc {|base| base}
462  end
463  install_recursive(File.join(srcdir, "bin"), bindir) do |src, cmd|
464    cmd = cmd.sub(/[^\/]*\z/m) {|n| RbConfig.expand(trans[n])}
465
466    shebang = ''
467    body = ''
468    open(src, "rb") do |f|
469      shebang = f.gets
470      body = f.read
471    end
472    if PROLOG_SCRIPT
473      shebang.sub!(/\A(\#!.*?ruby\b)?/) {PROLOG_SCRIPT + ($1 || "#!ruby\n")}
474    else
475      shebang.sub!(/\A\#!.*?ruby\b/) {"#!" + ruby_shebang}
476    end
477    shebang.sub!(/\r$/, '')
478    body.gsub!(/\r$/, '')
479
480    cmd << ".#{$cmdtype}" if $cmdtype
481    open_for_install(cmd, $script_mode) do
482      case $cmdtype
483      when "exe"
484        stub + shebang + body
485      when "bat"
486        [<<-"EOH".gsub(/^\s+/, ''), shebang, body, "__END__\n:endofruby\n"].join.gsub(/$/, "\r")
487          @echo off
488          @if not "%~d0" == "~d0" goto WinNT
489          #{ruby_bin} -x "#{cmd}" %1 %2 %3 %4 %5 %6 %7 %8 %9
490          @goto endofruby
491          :WinNT
492          "%~dp0#{ruby_install_name}" -x "%~f0" %*
493          @goto endofruby
494        EOH
495      when "cmd"
496        <<"/EOH" << shebang << body
497@"%~dp0#{ruby_install_name}" -x "%~f0" %*
498@exit /b %ERRORLEVEL%
499/EOH
500      else
501        shebang + body
502      end
503    end
504  end
505end
506
507install?(:local, :comm, :lib) do
508  prepare "library scripts", rubylibdir
509  noinst = %w[README* *.txt *.rdoc *.gemspec]
510  install_recursive(File.join(srcdir, "lib"), rubylibdir, :no_install => noinst, :mode => $data_mode)
511end
512
513install?(:local, :arch, :lib) do
514  prepare "common headers", rubyhdrdir
515
516  noinst = []
517  unless RUBY_PLATFORM =~ /mswin|mingw|bccwin/
518    noinst << "win32.h"
519  end
520  noinst = nil if noinst.empty?
521  install_recursive(File.join(srcdir, "include"), rubyhdrdir, :no_install => noinst, :glob => "*.h", :mode => $data_mode)
522end
523
524install?(:local, :comm, :man) do
525  mdocs = Dir["#{srcdir}/man/*.[1-9]"]
526  prepare "manpages", mandir, ([] | mdocs.collect {|mdoc| mdoc[/\d+$/]}).sort.collect {|sec| "man#{sec}"}
527
528  mandir = File.join(mandir, "man")
529  has_goruby = File.exist?(goruby_install_name+exeext)
530  require File.join(srcdir, "tool/mdoc2man.rb") if $mantype != "doc"
531  mdocs.each do |mdoc|
532    next unless File.file?(mdoc) and open(mdoc){|fh| fh.read(1) == '.'}
533    base = File.basename(mdoc)
534    if base == "goruby.1"
535      next unless has_goruby
536    end
537
538    destdir = mandir + (section = mdoc[/\d+$/])
539    destname = ruby_install_name.sub(/ruby/, base.chomp(".#{section}"))
540    destfile = File.join(destdir, "#{destname}.#{section}")
541
542    if $mantype == "doc"
543      install mdoc, destfile, :mode => $data_mode
544    else
545      class << (w = [])
546        alias print push
547      end
548      open(mdoc) {|r| Mdoc2Man.mdoc2man(r, w)}
549      open_for_install(destfile, $data_mode) {w.join("")}
550    end
551  end
552end
553
554# :stopdoc:
555module Gem
556  if defined?(Specification)
557    remove_const(:Specification)
558  end
559
560  class Specification < OpenStruct
561    def initialize(*)
562      super
563      yield(self) if defined?(yield)
564      self.executables ||= []
565    end
566
567    def self.load(path)
568      src = File.open(path, "rb") {|f| f.read}
569      src.sub!(/\A#.*/, '')
570      spec = eval(src, nil, path)
571      spec.date ||= last_date(path) || RUBY_RELEASE_DATE
572      spec
573    end
574
575    def self.last_date(path)
576      return unless $vcs
577      return unless time = $vcs.get_revisions(path)[2]
578      time.strftime("%Y-%m-%d")
579    end
580
581    def to_ruby
582        <<-GEMSPEC
583Gem::Specification.new do |s|
584  s.name = #{name.dump}
585  s.version = #{version.dump}
586  s.date = #{date.dump}
587  s.summary = #{summary.dump}
588  s.description = #{description.dump}
589  s.homepage = #{homepage.dump}
590  s.authors = #{authors.inspect}
591  s.email = #{email.inspect}
592  s.files = #{files.inspect}
593end
594        GEMSPEC
595    end
596  end
597end
598
599module RbInstall
600  module Specs
601    class FileCollector
602      def initialize(base_dir)
603        @base_dir = base_dir
604      end
605
606      def collect
607        (ruby_libraries + built_libraries).sort
608      end
609
610      private
611      def type
612        /\/(ext|lib)?\/.*?\z/ =~ @base_dir
613        $1
614      end
615
616      def ruby_libraries
617        case type
618        when "ext"
619          prefix = "#{$extout}/common/"
620          base = "#{prefix}#{relative_base}"
621        when "lib"
622          base = @base_dir
623          prefix = base.sub(/lib\/.*?\z/, "") + "lib/"
624        end
625
626        Dir.glob("#{base}{.rb,/**/*.rb}").collect do |ruby_source|
627          remove_prefix(prefix, ruby_source)
628        end
629      end
630
631      def built_libraries
632        case type
633        when "ext"
634          prefix = "#{$extout}/#{CONFIG['arch']}/"
635          base = "#{prefix}#{relative_base}"
636          Dir.glob("#{base}{.so,/**/*.so}").collect do |built_library|
637            remove_prefix(prefix, built_library)
638          end
639        when "lib"
640          []
641        end
642      end
643
644      def relative_base
645        /\/#{Regexp.escape(type)}\/(.*?)\z/ =~ @base_dir
646        $1
647      end
648
649      def remove_prefix(prefix, string)
650        string.sub(/\A#{Regexp.escape(prefix)}/, "")
651      end
652    end
653
654    class Reader < Struct.new(:src)
655      def gemspec
656        @gemspec ||= begin
657          spec = Gem::Specification.load(src) || raise("invalid spec in #{src}")
658          file_collector = FileCollector.new(File.dirname(src))
659          spec.files = file_collector.collect
660          spec
661        end
662      end
663
664      def spec_source
665        @gemspec.to_ruby
666      end
667    end
668
669    class Generator < Struct.new(:name, :base_dir, :src, :execs)
670      def gemspec
671        @gemspec ||= eval spec_source
672      end
673
674      def spec_source
675        <<-GEMSPEC
676Gem::Specification.new do |s|
677  s.name = #{name.dump}
678  s.version = #{version.dump}
679  s.summary = "This #{name} is bundled with Ruby"
680  s.executables = #{execs.inspect}
681  s.files = #{files.inspect}
682end
683        GEMSPEC
684      end
685
686      private
687      def version
688        version = open(src) { |f|
689          f.find { |s| /^\s*\w*VERSION\s*=(?!=)/ =~ s }
690        } or return
691        version.split(%r"=\s*", 2)[1].strip[/\A([\'\"])(.*?)\1/, 2]
692      end
693
694      def files
695        file_collector = FileCollector.new(base_dir)
696        file_collector.collect
697      end
698    end
699  end
700end
701# :startdoc:
702
703install?(:ext, :comm, :gem) do
704  $:.unshift(File.join(srcdir, "lib"))
705  require("rubygems.rb")
706  gem_dir = Gem.default_dir
707  # Gem.ensure_gem_subdirectories makes subdirectories group-writable.
708  directories = Gem::REPOSITORY_SUBDIRECTORIES
709  prepare "default gems", gem_dir, directories
710
711  spec_dir = File.join(gem_dir, directories.grep(/^spec/)[0])
712  default_spec_dir = "#{spec_dir}/default"
713  makedirs(default_spec_dir)
714
715  gems = {}
716  File.foreach(File.join(srcdir, "defs/default_gems")) do |line|
717    line.chomp!
718    line.sub!(/\s*#.*/, '')
719    next if line.empty?
720    words = []
721    line.scan(/\G\s*([^\[\]\s]+|\[([^\[\]]*)\])/) do
722      words << ($2 ? $2.split : $1)
723    end
724    name, base_dir, src, execs = *words
725    next unless name and base_dir and src
726
727    src       = File.join(srcdir, src)
728    base_dir  = File.join(srcdir, base_dir)
729    specgen   = RbInstall::Specs::Generator.new(name, base_dir, src, execs || [])
730    gems[name] ||= specgen
731  end
732
733  Dir.glob(srcdir+"/{lib,ext}/**/*.gemspec").each do |src|
734    specgen   = RbInstall::Specs::Reader.new(src)
735    gems[specgen.gemspec.name] ||= specgen
736  end
737
738  gems.sort.each do |name, specgen|
739    gemspec   = specgen.gemspec
740    base_dir  = specgen.src.sub(/\A#{Regexp.escape(srcdir)}\//, "")
741    full_name = "#{gemspec.name}-#{gemspec.version}"
742
743    puts "#{" "*30}#{gemspec.name} #{gemspec.version}"
744    gemspec_path = File.join(default_spec_dir, "#{full_name}.gemspec")
745    open_for_install(gemspec_path, $data_mode) do
746      specgen.spec_source
747    end
748
749    unless gemspec.executables.empty? then
750      bin_dir = File.join(gem_dir, 'gems', full_name, 'bin')
751      makedirs(bin_dir)
752
753      execs = gemspec.executables.map {|exec| File.join(srcdir, 'bin', exec)}
754      install(execs, bin_dir, :mode => $prog_mode)
755    end
756  end
757end
758
759parse_args()
760
761include FileUtils
762include FileUtils::NoWrite if $dryrun
763@fileutils_output = STDOUT
764@fileutils_label = ''
765
766$install << :local << :ext if $install.empty?
767$install.each do |inst|
768  if !(procs = $install_procs[inst]) || procs.empty?
769    next warn("unknown install target - #{inst}")
770  end
771  procs.each do |block|
772    dir = Dir.pwd
773    begin
774      block.call
775    ensure
776      Dir.chdir(dir)
777    end
778  end
779end
780
781# vi:set sw=2:
782