Created
June 4, 2013 14:05
-
-
Save headius/5706190 to your computer and use it in GitHub Desktop.
refactoring rbinstall.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit f59cc080876a339add92b31171040fe91da22eac | |
Author: Charles Oliver Nutter <headius@headius.com> | |
Date: Tue Jun 4 09:04:38 2013 -0500 | |
Refactor rbinstall into component libraries. #8488 | |
diff --git a/tool/rbinstall.rb b/tool/rbinstall.rb | |
index 1063fac..b43f596 100755 | |
--- a/tool/rbinstall.rb | |
+++ b/tool/rbinstall.rb | |
@@ -1,768 +1,7 @@ | |
#!./miniruby | |
-begin | |
- load "./rbconfig.rb" | |
-rescue LoadError | |
- CONFIG = Hash.new {""} | |
-else | |
- include RbConfig | |
- $".unshift File.expand_path("./rbconfig.rb") | |
-end | |
+require_relative 'rbinstall/rbinstall' | |
-srcdir = File.expand_path('../..', __FILE__) | |
-unless defined?(CROSS_COMPILING) and CROSS_COMPILING | |
- $:.replace([srcdir+"/lib", Dir.pwd]) | |
-end | |
-require 'fileutils' | |
-require 'shellwords' | |
-require 'optparse' | |
-require 'optparse/shellwords' | |
-require 'ostruct' | |
- | |
-STDOUT.sync = true | |
-File.umask(0) | |
- | |
-def parse_args(argv = ARGV) | |
- $mantype = 'doc' | |
- $destdir = nil | |
- $extout = nil | |
- $make = 'make' | |
- $mflags = [] | |
- $install = [] | |
- $installed_list = nil | |
- $dryrun = false | |
- $rdocdir = nil | |
- $data_mode = 0644 | |
- $prog_mode = 0755 | |
- $dir_mode = nil | |
- $script_mode = nil | |
- $strip = false | |
- $cmdtype = (if File::ALT_SEPARATOR == '\\' | |
- File.exist?("rubystub.exe") ? 'exe' : 'bat' | |
- end) | |
- mflags = [] | |
- opt = OptionParser.new | |
- opt.on('-n', '--dry-run') {$dryrun = true} | |
- opt.on('--dest-dir=DIR') {|dir| $destdir = dir} | |
- opt.on('--extout=DIR') {|dir| $extout = (dir unless dir.empty?)} | |
- opt.on('--make=COMMAND') {|make| $make = make} | |
- opt.on('--mantype=MAN') {|man| $mantype = man} | |
- opt.on('--make-flags=FLAGS', '--mflags', Shellwords) do |v| | |
- if arg = v.first | |
- arg.insert(0, '-') if /\A[^-][^=]*\Z/ =~ arg | |
- end | |
- $mflags.concat(v) | |
- end | |
- opt.on('-i', '--install=TYPE', $install_procs.keys) do |ins| | |
- $install << ins | |
- end | |
- opt.on('--data-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| | |
- $data_mode = mode | |
- end | |
- opt.on('--prog-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| | |
- $prog_mode = mode | |
- end | |
- opt.on('--dir-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| | |
- $dir_mode = mode | |
- end | |
- opt.on('--script-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| | |
- $script_mode = mode | |
- end | |
- opt.on('--installed-list [FILENAME]') {|name| $installed_list = name} | |
- opt.on('--rdoc-output [DIR]') {|dir| $rdocdir = dir} | |
- opt.on('--cmd-type=TYPE', %w[bat cmd plain]) {|cmd| $cmdtype = (cmd unless cmd == 'plain')} | |
- opt.on('--[no-]strip') {|strip| $strip = strip} | |
- | |
- opt.order!(argv) do |v| | |
- case v | |
- when /\AINSTALL[-_]([-\w]+)=(.*)/ | |
- argv.unshift("--#{$1.tr('_', '-')}=#{$2}") | |
- when /\A\w[-\w+]*=\z/ | |
- mflags << v | |
- when /\A\w[-\w+]*\z/ | |
- $install << v.intern | |
- else | |
- raise OptionParser::InvalidArgument, v | |
- end | |
- end rescue abort "#{$!.message}\n#{opt.help}" | |
- | |
- unless defined?(RbConfig) | |
- puts opt.help | |
- exit | |
- end | |
- | |
- $make, *rest = Shellwords.shellwords($make) | |
- $mflags.unshift(*rest) unless rest.empty? | |
- $mflags.unshift(*mflags) | |
- | |
- def $mflags.set?(flag) | |
- grep(/\A-(?!-).*#{flag.chr}/i) { return true } | |
- false | |
- end | |
- def $mflags.defined?(var) | |
- grep(/\A#{var}=(.*)/) {return block_given? ? yield($1) : $1} | |
- false | |
- end | |
- | |
- if $mflags.set?(?n) | |
- $dryrun = true | |
- else | |
- $mflags << '-n' if $dryrun | |
- end | |
- | |
- $destdir ||= $mflags.defined?("DESTDIR") | |
- if $extout ||= $mflags.defined?("EXTOUT") | |
- RbConfig.expand($extout) | |
- end | |
- | |
- $continue = $mflags.set?(?k) | |
- | |
- if $installed_list ||= $mflags.defined?('INSTALLED_LIST') | |
- RbConfig.expand($installed_list, RbConfig::CONFIG) | |
- $installed_list = open($installed_list, "ab") | |
- $installed_list.sync = true | |
- end | |
- | |
- $rdocdir ||= $mflags.defined?('RDOCOUT') | |
- | |
- $dir_mode ||= $prog_mode | 0700 | |
- $script_mode ||= $prog_mode | |
-end | |
- | |
-$install_procs = Hash.new {[]} | |
-def install?(*types, &block) | |
- $install_procs[:all] <<= block | |
- types.each do |type| | |
- $install_procs[type] <<= block | |
- end | |
-end | |
- | |
-def strip_file(files) | |
- if !defined?($strip_command) and (cmd = CONFIG["STRIP"]) | |
- case cmd | |
- when "", "true", ":" then return | |
- else $strip_command = Shellwords.shellwords(cmd) | |
- end | |
- elsif !$strip_command | |
- return | |
- end | |
- system(*($strip_command + [files].flatten)) | |
-end | |
- | |
-def install(src, dest, options = {}) | |
- options = options.clone | |
- strip = options.delete(:strip) | |
- options[:preserve] = true | |
- d = with_destdir(dest) | |
- super(src, d, options) | |
- srcs = Array(src) | |
- if strip | |
- d = srcs.map {|src| File.join(d, File.basename(src))} if $made_dirs[dest] | |
- strip_file(d) | |
- end | |
- if $installed_list | |
- dest = srcs.map {|src| File.join(dest, File.basename(src))} if $made_dirs[dest] | |
- $installed_list.puts dest | |
- end | |
-end | |
- | |
-def ln_sf(src, dest) | |
- super(src, with_destdir(dest)) | |
- $installed_list.puts dest if $installed_list | |
-end | |
- | |
-$made_dirs = {} | |
-def makedirs(dirs) | |
- dirs = fu_list(dirs) | |
- dirs.collect! do |dir| | |
- realdir = with_destdir(dir) | |
- realdir unless $made_dirs.fetch(dir) do | |
- $made_dirs[dir] = true | |
- $installed_list.puts(File.join(dir, "")) if $installed_list | |
- File.directory?(realdir) | |
- end | |
- end.compact! | |
- super(dirs, :mode => $dir_mode) unless dirs.empty? | |
-end | |
- | |
-FalseProc = proc {false} | |
-def path_matcher(pat) | |
- if pat and !pat.empty? | |
- proc {|f| pat.any? {|n| File.fnmatch?(n, f)}} | |
- else | |
- FalseProc | |
- end | |
-end | |
- | |
-def install_recursive(srcdir, dest, options = {}) | |
- opts = options.clone | |
- noinst = opts.delete(:no_install) | |
- glob = opts.delete(:glob) || "*" | |
- maxdepth = opts.delete(:maxdepth) | |
- subpath = (srcdir.size+1)..-1 | |
- prune = [] | |
- skip = [] | |
- if noinst | |
- if Array === noinst | |
- prune = noinst.grep(/#{File::SEPARATOR}/o).map!{|f| f.chomp(File::SEPARATOR)} | |
- skip = noinst.grep(/\A[^#{File::SEPARATOR}]*\z/o) | |
- else | |
- if noinst.index(File::SEPARATOR) | |
- prune = [noinst] | |
- else | |
- skip = [noinst] | |
- end | |
- end | |
- end | |
- skip |= %w"#*# *~ *.old *.bak *.orig *.rej *.diff *.patch *.core" | |
- prune = path_matcher(prune) | |
- skip = path_matcher(skip) | |
- File.directory?(srcdir) or return rescue return | |
- paths = [[srcdir, dest, 0]] | |
- found = [] | |
- while file = paths.shift | |
- found << file | |
- file, d, dir = *file | |
- if dir | |
- depth = dir + 1 | |
- next if maxdepth and maxdepth < depth | |
- files = [] | |
- Dir.foreach(file) do |f| | |
- src = File.join(file, f) | |
- d = File.join(dest, dir = src[subpath]) | |
- stat = File.lstat(src) rescue next | |
- if stat.directory? | |
- files << [src, d, depth] if maxdepth != depth and /\A\./ !~ f and !prune[dir] | |
- elsif stat.symlink? | |
- # skip | |
- else | |
- files << [src, d, false] if File.fnmatch?(glob, f) and !skip[f] | |
- end | |
- end | |
- paths.insert(0, *files) | |
- end | |
- end | |
- for src, d, dir in found | |
- if dir | |
- makedirs(d) | |
- else | |
- makedirs(d[/.*(?=\/)/m]) | |
- if block_given? | |
- yield src, d, opts | |
- else | |
- install src, d, opts | |
- end | |
- end | |
- end | |
-end | |
- | |
-def open_for_install(path, mode) | |
- data = open(realpath = with_destdir(path), "rb") {|f| f.read} rescue nil | |
- newdata = yield | |
- unless $dryrun | |
- unless newdata == data | |
- open(realpath, "wb", mode) {|f| f.write newdata} | |
- end | |
- File.chmod(mode, realpath) | |
- end | |
- $installed_list.puts path if $installed_list | |
-end | |
- | |
-def with_destdir(dir) | |
- return dir if !$destdir or $destdir.empty? | |
- dir = dir.sub(/\A\w:/, '') if File::PATH_SEPARATOR == ';' | |
- $destdir + dir | |
-end | |
- | |
-def prepare(mesg, basedir, subdirs=nil) | |
- return unless basedir | |
- case | |
- when !subdirs | |
- dirs = basedir | |
- when subdirs.size == 0 | |
- subdirs = nil | |
- when subdirs.size == 1 | |
- dirs = [basedir = File.join(basedir, subdirs)] | |
- subdirs = nil | |
- else | |
- dirs = [basedir, *subdirs.collect {|dir| File.join(basedir, dir)}] | |
- end | |
- printf("installing %-18s %s%s\n", "#{mesg}:", basedir, | |
- (subdirs ? " (#{subdirs.join(', ')})" : "")) | |
- makedirs(dirs) | |
-end | |
- | |
-def CONFIG.[](name, mandatory = false) | |
- value = super(name) | |
- if mandatory | |
- raise "CONFIG['#{name}'] must be set" if !value or value.empty? | |
- end | |
- value | |
-end | |
- | |
-exeext = CONFIG["EXEEXT"] | |
- | |
-ruby_install_name = CONFIG["ruby_install_name", true] | |
-rubyw_install_name = CONFIG["rubyw_install_name"] | |
-goruby_install_name = "go" + ruby_install_name | |
- | |
-bindir = CONFIG["bindir", true] | |
-libdir = CONFIG[CONFIG.fetch("libdirname", "libdir"), true] | |
-rubyhdrdir = CONFIG["rubyhdrdir", true] | |
-archhdrdir = CONFIG["rubyarchhdrdir"] || (rubyhdrdir + "/" + CONFIG['arch']) | |
-rubylibdir = CONFIG["rubylibdir", true] | |
-archlibdir = CONFIG["rubyarchdir", true] | |
-sitelibdir = CONFIG["sitelibdir"] | |
-sitearchlibdir = CONFIG["sitearchdir"] | |
-vendorlibdir = CONFIG["vendorlibdir"] | |
-vendorarchlibdir = CONFIG["vendorarchdir"] | |
-mandir = CONFIG["mandir", true] | |
-docdir = CONFIG["docdir", true] | |
-configure_args = Shellwords.shellwords(CONFIG["configure_args"]) | |
-enable_shared = CONFIG["ENABLE_SHARED"] == 'yes' | |
-dll = CONFIG["LIBRUBY_SO", enable_shared] | |
-lib = CONFIG["LIBRUBY", true] | |
-arc = CONFIG["LIBRUBY_A", true] | |
-major = CONFIG["MAJOR", true] | |
-minor = CONFIG["MINOR", true] | |
-load_relative = configure_args.include?("--enable-load-relative") | |
- | |
-install?(:local, :arch, :bin, :'bin-arch') do | |
- prepare "binary commands", bindir | |
- | |
- install ruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip | |
- if rubyw_install_name and !rubyw_install_name.empty? | |
- install rubyw_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip | |
- end | |
- if File.exist? goruby_install_name+exeext | |
- install goruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip | |
- end | |
- if enable_shared and dll != lib | |
- install dll, bindir, :mode => $prog_mode, :strip => $strip | |
- end | |
-end | |
- | |
-install?(:local, :arch, :lib) do | |
- prepare "base libraries", libdir | |
- | |
- install lib, libdir, :mode => $prog_mode, :strip => $strip unless lib == arc | |
- install arc, libdir, :mode => $data_mode | |
- if dll == lib and dll != arc | |
- for link in CONFIG["LIBRUBY_ALIASES"].split | |
- ln_sf(dll, File.join(libdir, link)) | |
- end | |
- end | |
- | |
- prepare "arch files", archlibdir | |
- install "rbconfig.rb", archlibdir, :mode => $data_mode | |
- if CONFIG["ARCHFILE"] | |
- for file in CONFIG["ARCHFILE"].split | |
- install file, archlibdir, :mode => $data_mode | |
- end | |
- end | |
-end | |
- | |
-install?(:local, :arch, :data) do | |
- pc = CONFIG["ruby_pc"] | |
- if pc and File.file?(pc) and File.size?(pc) | |
- prepare "pkgconfig data", pkgconfigdir = File.join(libdir, "pkgconfig") | |
- install pc, pkgconfigdir, :mode => $data_mode | |
- end | |
-end | |
- | |
-install?(:ext, :arch, :'ext-arch') do | |
- prepare "extension objects", archlibdir | |
- noinst = %w[-* -*/] | (CONFIG["no_install_files"] || "").split | |
- install_recursive("#{$extout}/#{CONFIG['arch']}", archlibdir, :no_install => noinst, :mode => $prog_mode, :strip => $strip) | |
- prepare "extension objects", sitearchlibdir | |
- prepare "extension objects", vendorarchlibdir | |
-end | |
-install?(:ext, :arch, :'ext-arch') do | |
- prepare "extension headers", archhdrdir | |
- install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "*.h", :mode => $data_mode) | |
-end | |
-install?(:ext, :comm, :'ext-comm') do | |
- prepare "extension scripts", rubylibdir | |
- install_recursive("#{$extout}/common", rubylibdir, :mode => $data_mode) | |
- prepare "extension scripts", sitelibdir | |
- prepare "extension scripts", vendorlibdir | |
-end | |
-install?(:ext, :comm, :'ext-comm') do | |
- hdrdir = rubyhdrdir + "/ruby" | |
- prepare "extension headers", hdrdir | |
- install_recursive("#{$extout}/include/ruby", hdrdir, :glob => "*.h", :mode => $data_mode) | |
-end | |
- | |
-install?(:doc, :rdoc) do | |
- if $rdocdir | |
- ridatadir = File.join(CONFIG['ridir'], CONFIG['ruby_version'], "system") | |
- prepare "rdoc", ridatadir | |
- install_recursive($rdocdir, ridatadir, :mode => $data_mode) | |
- end | |
-end | |
-install?(:doc, :capi) do | |
- prepare "capi-docs", docdir | |
- install_recursive "doc/capi", docdir+"/capi", :mode => $data_mode | |
-end | |
- | |
-if load_relative | |
- PROLOG_SCRIPT = <<EOS | |
-#!/bin/sh\n# -*- ruby -*- | |
-bindir=`#{CONFIG["CHDIR"]} "${0%/*}" 2>/dev/null; pwd` | |
-EOS | |
- if CONFIG["LIBRUBY_RELATIVE"] != 'yes' and libpathenv = CONFIG["LIBPATHENV"] | |
- pathsep = File::PATH_SEPARATOR | |
- PROLOG_SCRIPT << <<EOS | |
-prefix="${bindir%/bin}" | |
-export #{libpathenv}="$prefix/lib${#{libpathenv}#{pathsep}+#{pathsep}$#{libpathenv}}" | |
-EOS | |
- end | |
- PROLOG_SCRIPT << %Q[exec "$bindir/#{ruby_install_name}" -x "$0" "$@"\n] | |
-else | |
- PROLOG_SCRIPT = nil | |
-end | |
- | |
-install?(:local, :comm, :bin, :'bin-comm') do | |
- prepare "command scripts", bindir | |
- | |
- ruby_shebang = File.join(bindir, ruby_install_name) | |
- if File::ALT_SEPARATOR | |
- ruby_bin = ruby_shebang.tr(File::SEPARATOR, File::ALT_SEPARATOR) | |
- if $cmdtype == 'exe' | |
- stub = File.open("rubystub.exe", "rb") {|f| f.read} << "\n" rescue nil | |
- end | |
- end | |
- if trans = CONFIG["program_transform_name"] | |
- exp = [] | |
- trans.gsub!(/\$\$/, '$') | |
- trans.scan(%r[\G[\s;]*(/(?:\\.|[^/])*/)?([sy])(\\?\W)((?:(?!\3)(?:\\.|.))*)\3((?:(?!\3)(?:\\.|.))*)\3([gi]*)]) do | |
- |addr, cmd, sep, pat, rep, opt| | |
- addr &&= Regexp.new(addr[/\A\/(.*)\/\z/, 1]) | |
- case cmd | |
- when 's' | |
- next if pat == '^' and rep.empty? | |
- exp << [addr, (opt.include?('g') ? :gsub! : :sub!), | |
- Regexp.new(pat, opt.include?('i')), rep.gsub(/&/){'\&'}] | |
- when 'y' | |
- exp << [addr, :tr!, Regexp.quote(pat), rep] | |
- end | |
- end | |
- trans = proc do |base| | |
- exp.each {|addr, opt, pat, rep| base.__send__(opt, pat, rep) if !addr or addr =~ base} | |
- base | |
- end | |
- elsif /ruby/ =~ ruby_install_name | |
- trans = proc {|base| ruby_install_name.sub(/ruby/, base)} | |
- else | |
- trans = proc {|base| base} | |
- end | |
- install_recursive(File.join(srcdir, "bin"), bindir, :maxdepth => 1) do |src, cmd| | |
- cmd = cmd.sub(/[^\/]*\z/m) {|n| RbConfig.expand(trans[n])} | |
- | |
- shebang = '' | |
- body = '' | |
- open(src, "rb") do |f| | |
- shebang = f.gets | |
- body = f.read | |
- end | |
- shebang or raise "empty file - #{src}" | |
- if PROLOG_SCRIPT | |
- shebang.sub!(/\A(\#!.*?ruby\b)?/) {PROLOG_SCRIPT + ($1 || "#!ruby\n")} | |
- else | |
- shebang.sub!(/\A\#!.*?ruby\b/) {"#!" + ruby_shebang} | |
- end | |
- shebang.sub!(/\r$/, '') | |
- body.gsub!(/\r$/, '') | |
- | |
- cmd << ".#{$cmdtype}" if $cmdtype | |
- open_for_install(cmd, $script_mode) do | |
- case $cmdtype | |
- when "exe" | |
- stub + shebang + body | |
- when "bat" | |
- [<<-"EOH".gsub(/^\s+/, ''), shebang, body, "__END__\n:endofruby\n"].join.gsub(/$/, "\r") | |
- @echo off | |
- @if not "%~d0" == "~d0" goto WinNT | |
- #{ruby_bin} -x "#{cmd}" %1 %2 %3 %4 %5 %6 %7 %8 %9 | |
- @goto endofruby | |
- :WinNT | |
- "%~dp0#{ruby_install_name}" -x "%~f0" %* | |
- @goto endofruby | |
- EOH | |
- when "cmd" | |
- <<"/EOH" << shebang << body | |
-@"%~dp0#{ruby_install_name}" -x "%~f0" %* | |
-@exit /b %ERRORLEVEL% | |
-/EOH | |
- else | |
- shebang + body | |
- end | |
- end | |
- end | |
-end | |
- | |
-install?(:local, :comm, :lib) do | |
- prepare "library scripts", rubylibdir | |
- noinst = %w[README* *.txt *.rdoc *.gemspec] | |
- install_recursive(File.join(srcdir, "lib"), rubylibdir, :no_install => noinst, :mode => $data_mode) | |
-end | |
- | |
-install?(:local, :arch, :lib) do | |
- prepare "common headers", rubyhdrdir | |
- | |
- noinst = [] | |
- unless RUBY_PLATFORM =~ /mswin|mingw|bccwin/ | |
- noinst << "win32.h" | |
- end | |
- noinst = nil if noinst.empty? | |
- install_recursive(File.join(srcdir, "include"), rubyhdrdir, :no_install => noinst, :glob => "*.h", :mode => $data_mode) | |
-end | |
- | |
-install?(:local, :comm, :man) do | |
- mdocs = Dir["#{srcdir}/man/*.[1-9]"] | |
- prepare "manpages", mandir, ([] | mdocs.collect {|mdoc| mdoc[/\d+$/]}).sort.collect {|sec| "man#{sec}"} | |
- | |
- mandir = File.join(mandir, "man") | |
- has_goruby = File.exist?(goruby_install_name+exeext) | |
- require File.join(srcdir, "tool/mdoc2man.rb") if $mantype != "doc" | |
- mdocs.each do |mdoc| | |
- next unless File.file?(mdoc) and open(mdoc){|fh| fh.read(1) == '.'} | |
- base = File.basename(mdoc) | |
- if base == "goruby.1" | |
- next unless has_goruby | |
- end | |
- | |
- destdir = mandir + (section = mdoc[/\d+$/]) | |
- destname = ruby_install_name.sub(/ruby/, base.chomp(".#{section}")) | |
- destfile = File.join(destdir, "#{destname}.#{section}") | |
- | |
- if $mantype == "doc" | |
- install mdoc, destfile, :mode => $data_mode | |
- else | |
- class << (w = []) | |
- alias print push | |
- end | |
- open(mdoc) {|r| Mdoc2Man.mdoc2man(r, w)} | |
- open_for_install(destfile, $data_mode) {w.join("")} | |
- end | |
- end | |
-end | |
- | |
-# :stopdoc: | |
-module Gem | |
- if defined?(Specification) | |
- remove_const(:Specification) | |
- end | |
- | |
- class Specification < OpenStruct | |
- def initialize(*) | |
- super | |
- yield(self) if defined?(yield) | |
- self.executables ||= [] | |
- end | |
- | |
- def self.load(path) | |
- src = File.open(path, "rb") {|f| f.read} | |
- src.sub!(/\A#.*/, '') | |
- eval(src, nil, path) | |
- end | |
- | |
- def to_ruby | |
- <<-GEMSPEC | |
-Gem::Specification.new do |s| | |
- s.name = #{name.dump} | |
- s.version = #{version.dump} | |
- s.summary = #{summary.dump} | |
- s.description = #{description.dump} | |
- s.homepage = #{homepage.dump} | |
- s.authors = #{authors.inspect} | |
- s.email = #{email.inspect} | |
- s.files = #{files.inspect} | |
-end | |
- GEMSPEC | |
- end | |
- end | |
-end | |
- | |
-module RbInstall | |
- module Specs | |
- class FileCollector | |
- def initialize(base_dir) | |
- @base_dir = base_dir | |
- end | |
- | |
- def collect | |
- ruby_libraries + built_libraries | |
- end | |
- | |
- private | |
- def type | |
- /\/(ext|lib)?\/.*?\z/ =~ @base_dir | |
- $1 | |
- end | |
- | |
- def ruby_libraries | |
- case type | |
- when "ext" | |
- prefix = "#{$extout}/common/" | |
- base = "#{prefix}#{relative_base}" | |
- when "lib" | |
- base = @base_dir | |
- prefix = base.sub(/lib\/.*?\z/, "") + "lib/" | |
- end | |
- | |
- Dir.glob("#{base}{.rb,/**/*.rb}").collect do |ruby_source| | |
- remove_prefix(prefix, ruby_source) | |
- end | |
- end | |
- | |
- def built_libraries | |
- case type | |
- when "ext" | |
- prefix = "#{$extout}/#{CONFIG['arch']}/" | |
- base = "#{prefix}#{relative_base}" | |
- Dir.glob("#{base}{.so,/**/*.so}").collect do |built_library| | |
- remove_prefix(prefix, built_library) | |
- end | |
- when "lib" | |
- [] | |
- end | |
- end | |
- | |
- def relative_base | |
- /\/#{Regexp.escape(type)}\/(.*?)\z/ =~ @base_dir | |
- $1 | |
- end | |
- | |
- def remove_prefix(prefix, string) | |
- string.sub(/\A#{Regexp.escape(prefix)}/, "") | |
- end | |
- end | |
- | |
- class Reader < Struct.new(:src) | |
- def gemspec | |
- @gemspec ||= begin | |
- spec = Gem::Specification.load(src) || raise("invalid spec in #{src}") | |
- file_collector = FileCollector.new(File.dirname(src)) | |
- spec.files = file_collector.collect | |
- spec | |
- end | |
- end | |
- | |
- def spec_source | |
- @gemspec.to_ruby | |
- end | |
- end | |
- | |
- class Generator < Struct.new(:name, :base_dir, :src, :execs) | |
- def gemspec | |
- @gemspec ||= eval spec_source | |
- end | |
- | |
- def spec_source | |
- <<-GEMSPEC | |
-Gem::Specification.new do |s| | |
- s.name = #{name.dump} | |
- s.version = #{version.dump} | |
- s.summary = "This #{name} is bundled with Ruby" | |
- s.executables = #{execs.inspect} | |
- s.files = #{files.inspect} | |
-end | |
- GEMSPEC | |
- end | |
- | |
- private | |
- def version | |
- version = open(src) { |f| | |
- f.find { |s| /^\s*\w*VERSION\s*=(?!=)/ =~ s } | |
- } or return | |
- version.split(%r"=\s*", 2)[1].strip[/\A([\'\"])(.*?)\1/, 2] | |
- end | |
- | |
- def files | |
- file_collector = FileCollector.new(base_dir) | |
- file_collector.collect | |
- end | |
- end | |
- end | |
-end | |
-# :startdoc: | |
- | |
-install?(:ext, :comm, :gem) do | |
- $:.unshift(File.join(srcdir, "lib")) | |
- require("rubygems.rb") | |
- gem_dir = Gem.default_dir | |
- directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => $dir_mode) | |
- prepare "default gems", gem_dir, directories | |
- | |
- spec_dir = File.join(gem_dir, directories.grep(/^spec/)[0]) | |
- default_spec_dir = "#{spec_dir}/default" | |
- makedirs(default_spec_dir) | |
- | |
- gems = {} | |
- File.foreach(File.join(srcdir, "defs/default_gems")) do |line| | |
- line.chomp! | |
- line.sub!(/\s*#.*/, '') | |
- next if line.empty? | |
- words = [] | |
- line.scan(/\G\s*([^\[\]\s]+|\[([^\[\]]*)\])/) do | |
- words << ($2 ? $2.split : $1) | |
- end | |
- name, base_dir, src, execs = *words | |
- next unless name and base_dir and src | |
- | |
- src = File.join(srcdir, src) | |
- base_dir = File.join(srcdir, base_dir) | |
- specgen = RbInstall::Specs::Generator.new(name, base_dir, src, execs || []) | |
- gems[name] ||= specgen | |
- end | |
- | |
- Dir.glob(srcdir+"/{lib,ext}/**/*.gemspec").each do |src| | |
- specgen = RbInstall::Specs::Reader.new(src) | |
- gems[specgen.gemspec.name] ||= specgen | |
- end | |
- | |
- gems.sort.each do |name, specgen| | |
- gemspec = specgen.gemspec | |
- base_dir = specgen.src.sub(/\A#{Regexp.escape(srcdir)}\//, "") | |
- full_name = "#{gemspec.name}-#{gemspec.version}" | |
- | |
- puts "#{" "*30}#{gemspec.name} #{gemspec.version}" | |
- gemspec_path = File.join(default_spec_dir, "#{full_name}.gemspec") | |
- open_for_install(gemspec_path, $data_mode) do | |
- specgen.spec_source | |
- end | |
- | |
- unless gemspec.executables.empty? then | |
- bin_dir = File.join(gem_dir, 'gems', full_name, 'bin') | |
- makedirs(bin_dir) | |
- | |
- execs = gemspec.executables.map {|exec| File.join(srcdir, 'bin', exec)} | |
- install(execs, bin_dir, :mode => $prog_mode) | |
- end | |
- end | |
-end | |
- | |
-parse_args() | |
- | |
-include FileUtils | |
-include FileUtils::NoWrite if $dryrun | |
-@fileutils_output = STDOUT | |
-@fileutils_label = '' | |
- | |
-$install << :local << :ext if $install.empty? | |
-$install.each do |inst| | |
- if !(procs = $install_procs[inst]) || procs.empty? | |
- next warn("unknown install target - #{inst}") | |
- end | |
- procs.each do |block| | |
- dir = Dir.pwd | |
- begin | |
- block.call | |
- ensure | |
- Dir.chdir(dir) | |
- end | |
- end | |
-end | |
+RbInstall.run | |
# vi:set sw=2: | |
diff --git a/tool/rbinstall/gem/specification.rb b/tool/rbinstall/gem/specification.rb | |
new file mode 100644 | |
index 0000000..855fc83 | |
--- /dev/null | |
+++ b/tool/rbinstall/gem/specification.rb | |
@@ -0,0 +1,34 @@ | |
+module Gem | |
+ if defined?(Specification) | |
+ remove_const(:Specification) | |
+ end | |
+ | |
+ class Specification < OpenStruct | |
+ def initialize(*) | |
+ super | |
+ yield(self) if defined?(yield) | |
+ self.executables ||= [] | |
+ end | |
+ | |
+ def self.load(path) | |
+ src = File.open(path, "rb") {|f| f.read} | |
+ src.sub!(/\A#.*/, '') | |
+ eval(src, nil, path) | |
+ end | |
+ | |
+ def to_ruby | |
+ <<-GEMSPEC | |
+Gem::Specification.new do |s| | |
+ s.name = #{name.dump} | |
+ s.version = #{version.dump} | |
+ s.summary = #{summary.dump} | |
+ s.description = #{description.dump} | |
+ s.homepage = #{homepage.dump} | |
+ s.authors = #{authors.inspect} | |
+ s.email = #{email.inspect} | |
+ s.files = #{files.inspect} | |
+end | |
+ GEMSPEC | |
+ end | |
+ end | |
+end | |
diff --git a/tool/rbinstall/installers.rb b/tool/rbinstall/installers.rb | |
new file mode 100644 | |
index 0000000..cd6f7fe | |
--- /dev/null | |
+++ b/tool/rbinstall/installers.rb | |
@@ -0,0 +1,264 @@ | |
+class RbInstall | |
+ def install_binary_commands | |
+ prepare "binary commands", @bindir | |
+ | |
+ install @ruby_install_name+@exeext, @bindir, :mode => @prog_mode, :strip => @strip | |
+ if @rubyw_install_name and !@rubyw_install_name.empty? | |
+ install @rubyw_install_name+@exeext, @bindir, :mode => @prog_mode, :strip => @strip | |
+ end | |
+ if File.exist? @goruby_install_name+@exeext | |
+ install @goruby_install_name+@exeext, @bindir, :mode => @prog_mode, :strip => @strip | |
+ end | |
+ if @enable_shared and @dll != @lib | |
+ install @dll, @bindir, :mode => @prog_mode, :strip => @strip | |
+ end | |
+ end | |
+ | |
+ def install_base_libraries | |
+ prepare "base libraries", @libdir | |
+ | |
+ install @lib, @libdir, :mode => @prog_mode, :strip => @strip unless @lib == @arc | |
+ install @arc, @libdir, :mode => @data_mode | |
+ if @dll == @lib and @dll != @arc | |
+ for link in CONFIG["LIBRUBY_ALIASES"].split | |
+ ln_sf(@dll, File.join(@libdir, link)) | |
+ end | |
+ end | |
+ | |
+ prepare "arch files", @archlibdir | |
+ install "rbconfig.rb", @archlibdir, :mode => @data_mode | |
+ if CONFIG["ARCHFILE"] | |
+ for file in CONFIG["ARCHFILE"].split | |
+ install file, @archlibdir, :mode => @data_mode | |
+ end | |
+ end | |
+ end | |
+ | |
+ def install_data | |
+ pc = CONFIG["ruby_pc"] | |
+ if pc and File.file?(pc) and File.size?(pc) | |
+ prepare "pkgconfig data", pkgconfigdir = File.join(@libdir, "pkgconfig") | |
+ install pc, pkgconfigdir, :mode => @data_mode | |
+ end | |
+ end | |
+ | |
+ def install_arch_extension_objects | |
+ prepare "extension objects", @archlibdir | |
+ noinst = %w[-* -*/] | (CONFIG["no_install_files"] || "").split | |
+ install_recursive("#{@extout}/#{CONFIG['arch']}", @archlibdir, :no_install => noinst, :mode => @prog_mode, :strip => @strip) | |
+ prepare "extension objects", @sitearchlibdir | |
+ prepare "extension objects", @vendorarchlibdir | |
+ end | |
+ | |
+ def install_arch_extension_headers | |
+ prepare "extension headers", @archhdrdir | |
+ install_recursive("#{@extout}/include/#{CONFIG['arch']}", @archhdrdir, :glob => "*.h", :mode => @data_mode) | |
+ end | |
+ | |
+ def install_comm_extension_scripts | |
+ prepare "extension scripts", @rubylibdir | |
+ install_recursive("#{@extout}/common", @rubylibdir, :mode => @data_mode) | |
+ prepare "extension scripts", @sitelibdir | |
+ prepare "extension scripts", @vendorlibdir | |
+ end | |
+ | |
+ def install_comm_extension_headers | |
+ hdrdir = @rubyhdrdir + "/ruby" | |
+ prepare "extension headers", hdrdir | |
+ install_recursive("#{@extout}/include/ruby", hdrdir, :glob => "*.h", :mode => @data_mode) | |
+ end | |
+ | |
+ def install_rdoc | |
+ if @rdocdir | |
+ ridatadir = File.join(CONFIG['ridir'], CONFIG['ruby_version'], "system") | |
+ prepare "rdoc", ridatadir | |
+ install_recursive(@rdocdir, ridatadir, :mode => @data_mode) | |
+ end | |
+ end | |
+ | |
+ def install_capi_docs | |
+ prepare "capi-docs", @docdir | |
+ install_recursive "doc/capi", @docdir+"/capi", :mode => @data_mode | |
+ end | |
+ | |
+ def install_command_scripts | |
+ prepare "command scripts", @bindir | |
+ | |
+ ruby_shebang = File.join(@bindir, @ruby_install_name) | |
+ if File::ALT_SEPARATOR | |
+ ruby_bin = ruby_shebang.tr(File::SEPARATOR, File::ALT_SEPARATOR) | |
+ if @cmdtype == 'exe' | |
+ stub = File.open("rubystub.exe", "rb") {|f| f.read} << "\n" rescue nil | |
+ end | |
+ end | |
+ if trans = CONFIG["program_transform_name"] | |
+ exp = [] | |
+ trans.gsub!(/\$\$/, '$') | |
+ trans.scan(%r[\G[\s;]*(/(?:\\.|[^/])*/)?([sy])(\\?\W)((?:(?!\3)(?:\\.|.))*)\3((?:(?!\3)(?:\\.|.))*)\3([gi]*)]) do | |
+ |addr, cmd, sep, pat, rep, opt| | |
+ addr &&= Regexp.new(addr[/\A\/(.*)\/\z/, 1]) | |
+ case cmd | |
+ when 's' | |
+ next if pat == '^' and rep.empty? | |
+ exp << [addr, (opt.include?('g') ? :gsub! : :sub!), | |
+ Regexp.new(pat, opt.include?('i')), rep.gsub(/&/){'\&'}] | |
+ when 'y' | |
+ exp << [addr, :tr!, Regexp.quote(pat), rep] | |
+ end | |
+ end | |
+ trans = proc do |base| | |
+ exp.each {|addr, opt, pat, rep| base.__send__(opt, pat, rep) if !addr or addr =~ base} | |
+ base | |
+ end | |
+ elsif /ruby/ =~ @ruby_install_name | |
+ trans = proc {|base| @ruby_install_name.sub(/ruby/, base)} | |
+ else | |
+ trans = proc {|base| base} | |
+ end | |
+ install_recursive(File.join($srcdir, "bin"), @bindir, :maxdepth => 1) do |src, cmd| | |
+ cmd = cmd.sub(/[^\/]*\z/m) {|n| RbConfig.expand(trans[n])} | |
+ | |
+ shebang = '' | |
+ body = '' | |
+ open(src, "rb") do |f| | |
+ shebang = f.gets | |
+ body = f.read | |
+ end | |
+ shebang or raise "empty file - #{src}" | |
+ if @prolog_script | |
+ shebang.sub!(/\A(\#!.*?ruby\b)?/) {@prolog_script + ($1 || "#!ruby\n")} | |
+ else | |
+ shebang.sub!(/\A\#!.*?ruby\b/) {"#!" + ruby_shebang} | |
+ end | |
+ shebang.sub!(/\r$/, '') | |
+ body.gsub!(/\r$/, '') | |
+ | |
+ cmd << ".#{@cmdtype}" if @cmdtype | |
+ open_for_install(cmd, @script_mode) do | |
+ case @cmdtype | |
+ when "exe" | |
+ stub + shebang + body | |
+ when "bat" | |
+ [<<-"EOH".gsub(/^\s+/, ''), shebang, body, "__END__\n:endofruby\n"].join.gsub(/$/, "\r") | |
+ @echo off | |
+ @if not "%~d0" == "~d0" goto WinNT | |
+ #{ruby_bin} -x "#{cmd}" %1 %2 %3 %4 %5 %6 %7 %8 %9 | |
+ @goto endofruby | |
+ :WinNT | |
+ "%~dp0#{@ruby_install_name}" -x "%~f0" %* | |
+ @goto endofruby | |
+ EOH | |
+ when "cmd" | |
+ <<"/EOH" << shebang << body | |
+@"%~dp0#{@ruby_install_name}" -x "%~f0" %* | |
+@exit /b %ERRORLEVEL% | |
+/EOH | |
+ else | |
+ shebang + body | |
+ end | |
+ end | |
+ end | |
+ end | |
+ | |
+ def install_library_scripts | |
+ prepare "library scripts", @rubylibdir | |
+ noinst = %w[README* *.txt *.rdoc *.gemspec] | |
+ install_recursive(File.join($srcdir, "lib"), @rubylibdir, :no_install => noinst, :mode => @data_mode) | |
+ end | |
+ | |
+ def install_common_headers | |
+ prepare "common headers", @rubyhdrdir | |
+ | |
+ noinst = [] | |
+ unless RUBY_PLATFORM =~ /mswin|mingw|bccwin/ | |
+ noinst << "win32.h" | |
+ end | |
+ noinst = nil if noinst.empty? | |
+ install_recursive(File.join($srcdir, "include"), @rubyhdrdir, :no_install => noinst, :glob => "*.h", :mode => @data_mode) | |
+ end | |
+ | |
+ def install_manpages | |
+ mdocs = Dir["#{$srcdir}/man/*.[1-9]"] | |
+ prepare "manpages", @mandir, ([] | mdocs.collect {|mdoc| mdoc[/\d+$/]}).sort.collect {|sec| "man#{sec}"} | |
+ | |
+ @mandir = File.join(@mandir, "man") | |
+ has_goruby = File.exist?(@goruby_install_name+@exeext) | |
+ require File.join($srcdir, "tool/mdoc2man.rb") if @mantype != "doc" | |
+ mdocs.each do |mdoc| | |
+ next unless File.file?(mdoc) and open(mdoc){|fh| fh.read(1) == '.'} | |
+ base = File.basename(mdoc) | |
+ if base == "goruby.1" | |
+ next unless has_goruby | |
+ end | |
+ | |
+ destdir = @mandir + (section = mdoc[/\d+$/]) | |
+ destname = @ruby_install_name.sub(/ruby/, base.chomp(".#{section}")) | |
+ destfile = File.join(destdir, "#{destname}.#{section}") | |
+ | |
+ if @mantype == "doc" | |
+ install mdoc, destfile, :mode => @data_mode | |
+ else | |
+ class << (w = []) | |
+ alias print push | |
+ end | |
+ open(mdoc) {|r| Mdoc2Man.mdoc2man(r, w)} | |
+ open_for_install(destfile, @data_mode) {w.join("")} | |
+ end | |
+ end | |
+ end | |
+ | |
+ def install_default_gems | |
+ $:.unshift(File.join($srcdir, "lib")) | |
+ require("rubygems.rb") | |
+ gem_dir = Gem.default_dir | |
+ directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => @dir_mode) | |
+ prepare "default gems", gem_dir, directories | |
+ | |
+ spec_dir = File.join(gem_dir, directories.grep(/^spec/)[0]) | |
+ default_spec_dir = "#{spec_dir}/default" | |
+ makedirs(default_spec_dir) | |
+ | |
+ gems = {} | |
+ File.foreach(File.join($srcdir, "defs/default_gems")) do |line| | |
+ line.chomp! | |
+ line.sub!(/\s*#.*/, '') | |
+ next if line.empty? | |
+ words = [] | |
+ line.scan(/\G\s*([^\[\]\s]+|\[([^\[\]]*)\])/) do | |
+ words << ($2 ? $2.split : $1) | |
+ end | |
+ name, base_dir, src, execs = *words | |
+ next unless name and base_dir and src | |
+ | |
+ src = File.join($srcdir, src) | |
+ base_dir = File.join($srcdir, base_dir) | |
+ specgen = RbInstall::Specs::Generator.new(name, base_dir, src, execs || []) | |
+ gems[name] ||= specgen | |
+ end | |
+ | |
+ Dir.glob($srcdir+"/{lib,ext}/**/*.gemspec").each do |src| | |
+ specgen = RbInstall::Specs::Reader.new(src) | |
+ gems[specgen.gemspec.name] ||= specgen | |
+ end | |
+ | |
+ gems.sort.each do |name, specgen| | |
+ gemspec = specgen.gemspec | |
+ base_dir = specgen.src.sub(/\A#{Regexp.escape($srcdir)}\//, "") | |
+ full_name = "#{gemspec.name}-#{gemspec.version}" | |
+ | |
+ puts "#{" "*30}#{gemspec.name} #{gemspec.version}" | |
+ gemspec_path = File.join(default_spec_dir, "#{full_name}.gemspec") | |
+ open_for_install(gemspec_path, @data_mode) do | |
+ specgen.spec_source | |
+ end | |
+ | |
+ unless gemspec.executables.empty? then | |
+ bin_dir = File.join(gem_dir, 'gems', full_name, 'bin') | |
+ makedirs(bin_dir) | |
+ | |
+ execs = gemspec.executables.map {|exec| File.join($srcdir, 'bin', exec)} | |
+ install(execs, bin_dir, :mode => @prog_mode) | |
+ end | |
+ end | |
+ end | |
+end | |
\ No newline at end of file | |
diff --git a/tool/rbinstall/rbinstall.rb b/tool/rbinstall/rbinstall.rb | |
new file mode 100644 | |
index 0000000..57e0235 | |
--- /dev/null | |
+++ b/tool/rbinstall/rbinstall.rb | |
@@ -0,0 +1,408 @@ | |
+require 'fileutils' | |
+require 'shellwords' | |
+require 'optparse' | |
+require 'optparse/shellwords' | |
+require 'ostruct' | |
+ | |
+require_relative 'gem/specification' | |
+require_relative 'specs/file_collector' | |
+require_relative 'specs/reader' | |
+require_relative 'specs/generator' | |
+require_relative 'installers' | |
+ | |
+class RbInstall | |
+ def self.run | |
+ boot | |
+ rb_install = RbInstall.new | |
+ rb_install.run | |
+ end | |
+ | |
+ def self.boot | |
+ begin | |
+ load "./rbconfig.rb" | |
+ rescue LoadError | |
+ Object.const_set :CONFIG, Hash.new {""} | |
+ else | |
+ Object.class_eval { include RbConfig } | |
+ $".unshift File.expand_path("./rbconfig.rb") | |
+ end | |
+ | |
+ def CONFIG.[](name, mandatory = false) | |
+ value = super(name) | |
+ if mandatory | |
+ raise "CONFIG['#{name}'] must be set" if !value or value.empty? | |
+ end | |
+ value | |
+ end | |
+ | |
+ $srcdir = File.expand_path('../../..', __FILE__) | |
+ unless defined?(CROSS_COMPILING) and CROSS_COMPILING | |
+ $:.replace([$srcdir+"/lib", Dir.pwd]) | |
+ end | |
+ | |
+ STDOUT.sync = true | |
+ File.umask(0) | |
+ end | |
+ | |
+ def initialize | |
+ @install_procs = Hash.new {[]} | |
+ @made_dirs = {} | |
+ | |
+ @exeext = CONFIG["EXEEXT"] | |
+ | |
+ @ruby_install_name = CONFIG["ruby_install_name", true] | |
+ @rubyw_install_name = CONFIG["rubyw_install_name"] | |
+ @goruby_install_name = "go" + @ruby_install_name | |
+ | |
+ @bindir = CONFIG["bindir", true] | |
+ @libdir = CONFIG[CONFIG.fetch("libdirname", "libdir"), true] | |
+ @rubyhdrdir = CONFIG["rubyhdrdir", true] | |
+ @archhdrdir = CONFIG["rubyarchhdrdir"] || (@rubyhdrdir + "/" + CONFIG['arch']) | |
+ @rubylibdir = CONFIG["rubylibdir", true] | |
+ @archlibdir = CONFIG["rubyarchdir", true] | |
+ @sitelibdir = CONFIG["sitelibdir"] | |
+ @sitearchlibdir = CONFIG["sitearchdir"] | |
+ @vendorlibdir = CONFIG["vendorlibdir"] | |
+ @vendorarchlibdir = CONFIG["vendorarchdir"] | |
+ @mandir = CONFIG["mandir", true] | |
+ @docdir = CONFIG["docdir", true] | |
+ @configure_args = Shellwords.shellwords(CONFIG["configure_args"]) | |
+ @enable_shared = CONFIG["ENABLE_SHARED"] == 'yes' | |
+ @dll = CONFIG["LIBRUBY_SO", @enable_shared] | |
+ @lib = CONFIG["LIBRUBY", true] | |
+ @arc = CONFIG["LIBRUBY_A", true] | |
+ @major = CONFIG["MAJOR", true] | |
+ @minor = CONFIG["MINOR", true] | |
+ @load_relative = @configure_args.include?("--enable-load-relative") | |
+ | |
+ setup_installers | |
+ end | |
+ | |
+ def run | |
+ parse_args | |
+ | |
+ RbInstall.class_eval {include FileUtils} | |
+ RbInstall.class_eval {include FileUtils::NoWrite} if @dryrun | |
+ @fileutils_output = STDOUT | |
+ @fileutils_label = '' | |
+ | |
+ @install << :local << :ext if @install.empty? | |
+ @install.each do |inst| | |
+ if !(procs = @install_procs[inst]) || procs.empty? | |
+ next warn("unknown install target - #{inst}") | |
+ end | |
+ procs.each do |block| | |
+ dir = Dir.pwd | |
+ begin | |
+ block.call | |
+ ensure | |
+ Dir.chdir(dir) | |
+ end | |
+ end | |
+ end | |
+ end | |
+ | |
+ def setup_installers | |
+ install?(:local, :arch, :bin, :'bin-arch', &method(:install_binary_commands)) | |
+ install?(:local, :arch, :lib, &method(:install_base_libraries)) | |
+ install?(:local, :arch, :data, &method(:install_data)) | |
+ install?(:ext, :arch, :'ext-arch', &method(:install_arch_extension_objects)) | |
+ install?(:ext, :arch, :'ext-arch', &method(:install_arch_extension_headers)) | |
+ install?(:ext, :comm, :'ext-comm', &method(:install_comm_extension_scripts)) | |
+ install?(:ext, :comm, :'ext-comm', &method(:install_comm_extension_headers)) | |
+ install?(:doc, :rdoc, &method(:install_rdoc)) | |
+ install?(:doc, :capi, &method(:install_capi_docs)) | |
+ install?(:local, :comm, :bin, :'bin-comm', &method(:install_command_scripts)) | |
+ install?(:local, :comm, :lib, &method(:install_library_scripts)) | |
+ install?(:local, :arch, :lib, &method(:install_common_headers)) | |
+ install?(:local, :comm, :man, &method(:install_manpages)) | |
+ install?(:ext, :comm, :gem, &method(:install_default_gems)) | |
+ end | |
+ | |
+ def parse_args(argv = ARGV) | |
+ @mantype = 'doc' | |
+ @destdir = nil | |
+ @extout = nil | |
+ @make = 'make' | |
+ @mflags = [] | |
+ @install = [] | |
+ @installed_list = nil | |
+ @dryrun = false | |
+ @rdocdir = nil | |
+ @data_mode = 0644 | |
+ @prog_mode = 0755 | |
+ @dir_mode = nil | |
+ @script_mode = nil | |
+ @strip = false | |
+ @cmdtype = (if File::ALT_SEPARATOR == '\\' | |
+ File.exist?("rubystub.exe") ? 'exe' : 'bat' | |
+ end) | |
+ mflags = [] | |
+ opt = OptionParser.new | |
+ opt.on('-n', '--dry-run') {@dryrun = true} | |
+ opt.on('--dest-dir=DIR') {|dir| @destdir = dir} | |
+ opt.on('--extout=DIR') {|dir| @extout = (dir unless dir.empty?)} | |
+ opt.on('--make=COMMAND') {|make| @make = make} | |
+ opt.on('--mantype=MAN') {|man| @mantype = man} | |
+ opt.on('--make-flags=FLAGS', '--mflags', Shellwords) do |v| | |
+ if arg = v.first | |
+ arg.insert(0, '-') if /\A[^-][^=]*\Z/ =~ arg | |
+ end | |
+ @mflags.concat(v) | |
+ end | |
+ opt.on('-i', '--install=TYPE', @install_procs.keys) do |ins| | |
+ @install << ins | |
+ end | |
+ opt.on('--data-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| | |
+ @data_mode = mode | |
+ end | |
+ opt.on('--prog-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| | |
+ @prog_mode = mode | |
+ end | |
+ opt.on('--dir-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| | |
+ @dir_mode = mode | |
+ end | |
+ opt.on('--script-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| | |
+ @script_mode = mode | |
+ end | |
+ opt.on('--installed-list [FILENAME]') {|name| @installed_list = name} | |
+ opt.on('--rdoc-output [DIR]') {|dir| @rdocdir = dir} | |
+ opt.on('--cmd-type=TYPE', %w[bat cmd plain]) {|cmd| @cmdtype = (cmd unless cmd == 'plain')} | |
+ opt.on('--[no-]strip') {|strip| @strip = strip} | |
+ | |
+ opt.order!(argv) do |v| | |
+ case v | |
+ when /\AINSTALL[-_]([-\w]+)=(.*)/ | |
+ argv.unshift("--#{$1.tr('_', '-')}=#{$2}") | |
+ when /\A\w[-\w+]*=\z/ | |
+ mflags << v | |
+ when /\A\w[-\w+]*\z/ | |
+ @install << v.intern | |
+ else | |
+ raise OptionParser::InvalidArgument, v | |
+ end | |
+ end rescue abort "#{$!.message}\n#{opt.help}" | |
+ | |
+ unless defined?(RbConfig) | |
+ puts opt.help | |
+ exit | |
+ end | |
+ | |
+ @make, *rest = Shellwords.shellwords(@make) | |
+ @mflags.unshift(*rest) unless rest.empty? | |
+ @mflags.unshift(*mflags) | |
+ | |
+ def @mflags.set?(flag) | |
+ grep(/\A-(?!-).*#{flag.chr}/i) { return true } | |
+ false | |
+ end | |
+ def @mflags.defined?(var) | |
+ grep(/\A#{var}=(.*)/) {return block_given? ? yield($1) : $1} | |
+ false | |
+ end | |
+ | |
+ if @mflags.set?(?n) | |
+ @dryrun = true | |
+ else | |
+ @mflags << '-n' if @dryrun | |
+ end | |
+ | |
+ @destdir ||= @mflags.defined?("DESTDIR") | |
+ if @extout ||= @mflags.defined?("EXTOUT") | |
+ RbConfig.expand(@extout) | |
+ end | |
+ | |
+ @continue = @mflags.set?(?k) | |
+ | |
+ if @installed_list ||= @mflags.defined?('INSTALLED_LIST') | |
+ RbConfig.expand(@installed_list, RbConfig::CONFIG) | |
+ @installed_list = open(@installed_list, "ab") | |
+ @installed_list.sync = true | |
+ end | |
+ | |
+ @rdocdir ||= @mflags.defined?('RDOCOUT') | |
+ | |
+ @dir_mode ||= @prog_mode | 0700 | |
+ @script_mode ||= @prog_mode | |
+ end | |
+ | |
+ def install?(*types, &block) | |
+ @install_procs[:all] <<= block | |
+ types.each do |type| | |
+ @install_procs[type] <<= block | |
+ end | |
+ | |
+ if @load_relative | |
+ @prolog_script = <<EOS | |
+#!/bin/sh\n# -*- ruby -*- | |
+bindir=`#{CONFIG["CHDIR"]} "${0%/*}" 2>/dev/null; pwd` | |
+EOS | |
+ | |
+ if CONFIG["LIBRUBY_RELATIVE"] != 'yes' and libpathenv = CONFIG["LIBPATHENV"] | |
+ pathsep = File::PATH_SEPARATOR | |
+ @prolog_script << <<EOS | |
+prefix="${bindir%/bin}" | |
+export #{libpathenv}="$prefix/lib${#{libpathenv}#{pathsep}+#{pathsep}$#{libpathenv}}" | |
+EOS | |
+ end | |
+ @prolog_script << %Q[exec "$bindir/#{@ruby_install_name}" -x "$0" "$@"\n] | |
+ else | |
+ @prolog_script = nil | |
+ end | |
+ end | |
+ | |
+ def strip_file(files) | |
+ if !defined?(@strip_command) and (cmd = CONFIG["STRIP"]) | |
+ case cmd | |
+ when "", "true", ":" then return | |
+ else @strip_command = Shellwords.shellwords(cmd) | |
+ end | |
+ elsif !@strip_command | |
+ return | |
+ end | |
+ system(*(@strip_command + [files].flatten)) | |
+ end | |
+ | |
+ def install(src, dest, options = {}) | |
+ options = options.clone | |
+ strip = options.delete(:strip) | |
+ options[:preserve] = true | |
+ d = with_destdir(dest) | |
+ super(src, d, options) | |
+ srcs = Array(src) | |
+ if strip | |
+ d = srcs.map {|src| File.join(d, File.basename(src))} if @made_dirs[dest] | |
+ strip_file(d) | |
+ end | |
+ if @installed_list | |
+ dest = srcs.map {|src| File.join(dest, File.basename(src))} if @made_dirs[dest] | |
+ @installed_list.puts dest | |
+ end | |
+ end | |
+ | |
+ def ln_sf(src, dest) | |
+ super(src, with_destdir(dest)) | |
+ @installed_list.puts dest if @installed_list | |
+ end | |
+ | |
+ def makedirs(dirs) | |
+ dirs = fu_list(dirs) | |
+ dirs.collect! do |dir| | |
+ realdir = with_destdir(dir) | |
+ realdir unless @made_dirs.fetch(dir) do | |
+ @made_dirs[dir] = true | |
+ @installed_list.puts(File.join(dir, "")) if @installed_list | |
+ File.directory?(realdir) | |
+ end | |
+ end.compact! | |
+ super(dirs, :mode => @dir_mode) unless dirs.empty? | |
+ end | |
+ | |
+ FalseProc = proc {false} | |
+ | |
+ def path_matcher(pat) | |
+ if pat and !pat.empty? | |
+ proc {|f| pat.any? {|n| File.fnmatch?(n, f)}} | |
+ else | |
+ FalseProc | |
+ end | |
+ end | |
+ | |
+ def install_recursive(srcdir, dest, options = {}) | |
+ opts = options.clone | |
+ noinst = opts.delete(:no_install) | |
+ glob = opts.delete(:glob) || "*" | |
+ maxdepth = opts.delete(:maxdepth) | |
+ subpath = (srcdir.size+1)..-1 | |
+ prune = [] | |
+ skip = [] | |
+ if noinst | |
+ if Array === noinst | |
+ prune = noinst.grep(/#{File::SEPARATOR}/o).map!{|f| f.chomp(File::SEPARATOR)} | |
+ skip = noinst.grep(/\A[^#{File::SEPARATOR}]*\z/o) | |
+ else | |
+ if noinst.index(File::SEPARATOR) | |
+ prune = [noinst] | |
+ else | |
+ skip = [noinst] | |
+ end | |
+ end | |
+ end | |
+ skip |= %w"#*# *~ *.old *.bak *.orig *.rej *.diff *.patch *.core" | |
+ prune = path_matcher(prune) | |
+ skip = path_matcher(skip) | |
+ File.directory?(srcdir) or return rescue return | |
+ paths = [[srcdir, dest, 0]] | |
+ found = [] | |
+ while file = paths.shift | |
+ found << file | |
+ file, d, dir = *file | |
+ if dir | |
+ depth = dir + 1 | |
+ next if maxdepth and maxdepth < depth | |
+ files = [] | |
+ Dir.foreach(file) do |f| | |
+ src = File.join(file, f) | |
+ d = File.join(dest, dir = src[subpath]) | |
+ stat = File.lstat(src) rescue next | |
+ if stat.directory? | |
+ files << [src, d, depth] if maxdepth != depth and /\A\./ !~ f and !prune[dir] | |
+ elsif stat.symlink? | |
+ # skip | |
+ else | |
+ files << [src, d, false] if File.fnmatch?(glob, f) and !skip[f] | |
+ end | |
+ end | |
+ paths.insert(0, *files) | |
+ end | |
+ end | |
+ for src, d, dir in found | |
+ if dir | |
+ makedirs(d) | |
+ else | |
+ makedirs(d[/.*(?=\/)/m]) | |
+ if block_given? | |
+ yield src, d, opts | |
+ else | |
+ install src, d, opts | |
+ end | |
+ end | |
+ end | |
+ end | |
+ | |
+ def open_for_install(path, mode) | |
+ data = open(realpath = with_destdir(path), "rb") {|f| f.read} rescue nil | |
+ newdata = yield | |
+ unless @dryrun | |
+ unless newdata == data | |
+ open(realpath, "wb", mode) {|f| f.write newdata} | |
+ end | |
+ File.chmod(mode, realpath) | |
+ end | |
+ @installed_list.puts path if @installed_list | |
+ end | |
+ | |
+ def with_destdir(dir) | |
+ return dir if !@destdir or @destdir.empty? | |
+ dir = dir.sub(/\A\w:/, '') if File::PATH_SEPARATOR == ';' | |
+ @destdir + dir | |
+ end | |
+ | |
+ def prepare(mesg, basedir, subdirs=nil) | |
+ return unless basedir | |
+ case | |
+ when !subdirs | |
+ dirs = basedir | |
+ when subdirs.size == 0 | |
+ subdirs = nil | |
+ when subdirs.size == 1 | |
+ dirs = [basedir = File.join(basedir, subdirs)] | |
+ subdirs = nil | |
+ else | |
+ dirs = [basedir, *subdirs.collect {|dir| File.join(basedir, dir)}] | |
+ end | |
+ printf("installing %-18s %s%s\n", "#{mesg}:", basedir, | |
+ (subdirs ? " (#{subdirs.join(', ')})" : "")) | |
+ makedirs(dirs) | |
+ end | |
+end | |
diff --git a/tool/rbinstall/specs/file_collector.rb b/tool/rbinstall/specs/file_collector.rb | |
new file mode 100644 | |
index 0000000..f1d63fe | |
--- /dev/null | |
+++ b/tool/rbinstall/specs/file_collector.rb | |
@@ -0,0 +1,56 @@ | |
+class RbInstall | |
+ module Specs | |
+ class FileCollector | |
+ def initialize(base_dir) | |
+ @base_dir = base_dir | |
+ end | |
+ | |
+ def collect | |
+ ruby_libraries + built_libraries | |
+ end | |
+ | |
+ private | |
+ def type | |
+ /\/(ext|lib)?\/.*?\z/ =~ @base_dir | |
+ $1 | |
+ end | |
+ | |
+ def ruby_libraries | |
+ case type | |
+ when "ext" | |
+ prefix = "#{$extout}/common/" | |
+ base = "#{prefix}#{relative_base}" | |
+ when "lib" | |
+ base = @base_dir | |
+ prefix = base.sub(/lib\/.*?\z/, "") + "lib/" | |
+ end | |
+ | |
+ Dir.glob("#{base}{.rb,/**/*.rb}").collect do |ruby_source| | |
+ remove_prefix(prefix, ruby_source) | |
+ end | |
+ end | |
+ | |
+ def built_libraries | |
+ case type | |
+ when "ext" | |
+ prefix = "#{$extout}/#{CONFIG['arch']}/" | |
+ base = "#{prefix}#{relative_base}" | |
+ Dir.glob("#{base}{.so,/**/*.so}").collect do |built_library| | |
+ remove_prefix(prefix, built_library) | |
+ end | |
+ when "lib" | |
+ [] | |
+ end | |
+ end | |
+ | |
+ def relative_base | |
+ /\/#{Regexp.escape(type)}\/(.*?)\z/ =~ @base_dir | |
+ $1 | |
+ end | |
+ | |
+ def remove_prefix(prefix, string) | |
+ string.sub(/\A#{Regexp.escape(prefix)}/, "") | |
+ end | |
+ end | |
+ end | |
+end | |
\ No newline at end of file | |
diff --git a/tool/rbinstall/specs/generator.rb b/tool/rbinstall/specs/generator.rb | |
new file mode 100644 | |
index 0000000..7020954 | |
--- /dev/null | |
+++ b/tool/rbinstall/specs/generator.rb | |
@@ -0,0 +1,34 @@ | |
+class RbInstall | |
+ module Specs | |
+ class Generator < Struct.new(:name, :base_dir, :src, :execs) | |
+ def gemspec | |
+ @gemspec ||= eval spec_source | |
+ end | |
+ | |
+ def spec_source | |
+ <<-GEMSPEC | |
+Gem::Specification.new do |s| | |
+ s.name = #{name.dump} | |
+ s.version = #{version.dump} | |
+ s.summary = "This #{name} is bundled with Ruby" | |
+ s.executables = #{execs.inspect} | |
+ s.files = #{files.inspect} | |
+end | |
+ GEMSPEC | |
+ end | |
+ | |
+ private | |
+ def version | |
+ version = open(src) { |f| | |
+ f.find { |s| /^\s*\w*VERSION\s*=(?!=)/ =~ s } | |
+ } or return | |
+ version.split(%r"=\s*", 2)[1].strip[/\A([\'\"])(.*?)\1/, 2] | |
+ end | |
+ | |
+ def files | |
+ file_collector = FileCollector.new(base_dir) | |
+ file_collector.collect | |
+ end | |
+ end | |
+ end | |
+end | |
diff --git a/tool/rbinstall/specs/reader.rb b/tool/rbinstall/specs/reader.rb | |
new file mode 100644 | |
index 0000000..a1652a7 | |
--- /dev/null | |
+++ b/tool/rbinstall/specs/reader.rb | |
@@ -0,0 +1,18 @@ | |
+class RbInstall | |
+ module Specs | |
+ class Reader < Struct.new(:src) | |
+ def gemspec | |
+ @gemspec ||= begin | |
+ spec = Gem::Specification.load(src) || raise("invalid spec in #{src}") | |
+ file_collector = FileCollector.new(File.dirname(src)) | |
+ spec.files = file_collector.collect | |
+ spec | |
+ end | |
+ end | |
+ | |
+ def spec_source | |
+ @gemspec.to_ruby | |
+ end | |
+ end | |
+ end | |
+end | |
\ No newline at end of file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment