In Files

Multiruby

multiruby_setup is a script to help you manage multiruby.

usage: multiruby_setup [-h|cmd|spec…]

cmds:

  -h, --help, help = show this help.
  build            = build and install everything. used internally.
  clean            = clean scm build dirs and remove non-scm build dirs.
  list             = print installed versions.
  rm:$version      = remove a particular version.
  rubygems:merge   = symlink all rubygem dirs to one dir.
  tags             = list all tags from svn.
  update           = update svn builds.
  update:rubygems  = update rubygems and nuke install dirs.

specs:

  the_usual              = alias for latest versions from tar + rubygems
  mri:svn:current        = alias for mri:svn:releases and mri:svn:branches.
  mri:svn:releases       = alias for supported releases of mri ruby.
  mri:svn:branches       = alias for active branches of mri ruby.
  mri:svn:branch:$branch = install a specific $branch of mri from svn.
  mri:svn:tag:$tag       = install a specific $tag of mri from svn.
  mri:tar:$version       = install a specific $version of mri from tarball.

environment variables:

  GEM_URL  = url for rubygems tarballs
  MRI_SVN  = url for MRI SVN
  RUBY_URL = url for MRI tarballs
  VERSIONS = what versions to install

  RUBYOPT is cleared on installs.

NOTES:

Public Class Methods

build_and_install() click to toggle source
# File lib/multiruby.rb, line 63
def self.build_and_install
  ENV.delete 'RUBYOPT'

  root_dir = self.root_dir
  versions = []

  Dir.chdir root_dir do
    self.setup_dirs

    rubygems = Dir["versions/rubygems*.tgz"]
    abort "You should delete all but one rubygem tarball" if rubygems.size > 1
    rubygem_tarball = File.expand_path rubygems.last rescue nil

    Dir.chdir "build" do
      Dir["../versions/*"].sort.each do |tarball|
        next if tarball =~ /rubygems/

        build_dir = File.basename tarball, ".tar.gz"
        version = build_dir.sub(/^ruby-?/, '')
        versions << version
        inst_dir = "#{root_dir}/install/#{version}"

        unless test dd, inst_dir then
          unless test dd, build_dir then
            if test dd, tarball then
              dir = File.basename tarball
              FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}"
            else
              puts "creating #{inst_dir}"
              Dir.mkdir inst_dir
              run "tar zxf #{tarball}"
            end
          end
          Dir.chdir build_dir do
            puts "building and installing #{version}"
            if test ff, "configure.in" then
              gnu_utils_build inst_dir
            elsif test ff, "Rakefile" then
              rake_build inst_dir
            else
              raise "dunno how to build"
            end

            if rubygem_tarball and version !~ /1[._-]9|mri_trunk|rubinius/ then
              rubygems = File.basename rubygem_tarball, ".tgz"
              run "tar zxf #{rubygem_tarball}" unless test dd, rubygems

              Dir.chdir rubygems do
                run "../ruby ./setup.rb --no-rdoc --no-ri", "../log.rubygems"
              end
            end
          end
        end
      end
    end
  end

  versions
end
clean() click to toggle source
# File lib/multiruby.rb, line 123
def self.clean
  self.each_scm_build_dir do |style|
    case style
    when :svn then
      if File.exist? "Rakefile" then
        run "rake clean"
      elsif File.exist? "Makefile" then
        run "make clean"
      end
    else
      FileUtils.rm_rf Dir.pwd
    end
  end
end
each_scm_build_dir() click to toggle source
# File lib/multiruby.rb, line 138
def self.each_scm_build_dir
  Multiruby.in_build_dir do
    Dir["*"].each do |dir|
      next unless File.directory? dir
      Dir.chdir dir do
        if File.exist?(".svn") then
          yield :svn
        else
          yield :none
        end
      end
    end
  end
end
env(name, fallback;) click to toggle source
# File lib/multiruby.rb, line 46
def self.env name, fallback; ENV[name] || fallback; end
fetch_tar(v) click to toggle source
# File lib/multiruby.rb, line 173
def self.fetch_tar v
  in_versions_dir do
    warn "  Determining latest version for #{v}"
    ver = v[/\d+\.\d+/]
    base = matching_versions("#{RUBY_URL}/#{ver}/", v).last
    abort "Could not determine release for #{v}" unless base
    url = File.join RUBY_URL, ver, base
    unless File.file? base then
      warn "    Fetching #{base} via HTTP... this might take a while."
      open(url) do |f|
        File.open base, 'w' do |out|
          out.write f.read
        end
      end
    end
  end
end
gnu_utils_build(inst_dir) click to toggle source
# File lib/multiruby.rb, line 191
def self.gnu_utils_build inst_dir
  run "autoconf" unless test ff, "configure"
  run "./configure --enable-shared --prefix #{inst_dir}", "log.configure" unless
    test ff, "Makefile"
  run "(nice make -j4; nice make)", "log.build"
  run "make install", "log.install"
end
help() click to toggle source
# File lib/multiruby.rb, line 199
def self.help
  puts HELP.join
end
in_build_dir() click to toggle source
# File lib/multiruby.rb, line 203
def self.in_build_dir
  in_root_dir "build" do
    yield
  end
end
in_install_dir() click to toggle source
# File lib/multiruby.rb, line 209
def self.in_install_dir
  in_root_dir "install" do
    yield
  end
end
in_root_dir(subdir = "") click to toggle source
# File lib/multiruby.rb, line 215
def self.in_root_dir subdir = ""
  Dir.chdir File.join(self.root_dir, subdir) do
    yield
  end
end
in_tmp_dir() click to toggle source
# File lib/multiruby.rb, line 221
def self.in_tmp_dir
  in_root_dir "tmp" do
    yield
  end
end
in_versions_dir() click to toggle source
# File lib/multiruby.rb, line 227
def self.in_versions_dir
  in_root_dir "versions" do
    yield
  end
end
list() click to toggle source
# File lib/multiruby.rb, line 233
def self.list
  puts "Known versions:"
  in_install_dir do
    Dir["*"].sort.each do |d|
      puts "  #{d}"
    end
  end
end
matching_versions(url, matching=nil) click to toggle source
# File lib/multiruby.rb, line 153
def self.matching_versions url, matching=nil
  file = URI.parse(url).read

  map = {
    "preview" => "beta",
    "rc"      => "beta2",
    "p"       => "release",
    "tar"     => "aargh",
    "gz"      => "aargh",
  }

  versions = file.scan(/href="(ruby.*tar.gz)"/).flatten.sort_by { |s|
    s.scan(/\d+|[a-z]+/).map { |a| Integer(a) rescue map[a] || a }
  }

  versions = versions.grep(/#{Regexp.escape(matching)}/) if matching

  versions
end
merge_rubygems() click to toggle source
# File lib/multiruby.rb, line 242
def self.merge_rubygems
  in_install_dir do
    gems = Dir["*/lib/ruby/gems"]

    unless test dd, "../gems" then
      FileUtils.mv gems.first, ".."
    end

    gems.each do |d|
      FileUtils.rm_rf d
      FileUtils.ln_sf "../../../../gems", d
    end
  end
end
mri_latest_tag(v) click to toggle source
# File lib/multiruby.rb, line 257
def self.mri_latest_tag v
  Multiruby.tags.grep(/#{v}/).last
end
rake_build(inst_dir) click to toggle source
# File lib/multiruby.rb, line 261
def self.rake_build inst_dir
  run "rake", "log.build"
  FileUtils.ln_sf "../build/#{File.basename Dir.pwd}", inst_dir
end
rm(name) click to toggle source
# File lib/multiruby.rb, line 266
def self.rm name
  Multiruby.in_root_dir do
    FileUtils.rm_rf Dir["*/#{name}"]
    f = "versions/ruby-#{name}.tar.gz"
    File.unlink f if test ff, f
  end
end
root_dir() click to toggle source
# File lib/multiruby.rb, line 274
def self.root_dir
  root_dir = File.expand_path(ENV['MULTIRUBY'] ||
                              File.join(ENV['HOME'], ".multiruby"))

  unless test dd, root_dir then
    puts "creating #{root_dir}"
    Dir.mkdir root_dir, 0700
  end

  root_dir
end
run(base_cmd, log = nil) click to toggle source
# File lib/multiruby.rb, line 286
def self.run base_cmd, log = nil
  cmd = base_cmd
  cmd += " > #{log} 2>&1" if log
  puts "Running command: #{cmd}"
  raise "ERROR: Command failed with exit code #{$?}" unless system cmd
end
setup_dirs(download = true) click to toggle source
# File lib/multiruby.rb, line 293
def self.setup_dirs download = true
  %(build install versions tmp).each do |dir|
    unless test dd, dir then
      puts "creating #{dir}"
      Dir.mkdir dir
      if dir == "versions" && download then
        warn "  Downloading initial ruby tarballs to ~/.multiruby/versions:"
        VERSIONS.each do |v|
          self.fetch_tar v
        end
        warn "  ...done"
        warn "  Put other ruby tarballs in ~/.multiruby/versions to use them."
      end
    end
  end
end
svn_co(url, dir) click to toggle source
# File lib/multiruby.rb, line 310
def self.svn_co url, dir
  Multiruby.in_versions_dir do
    Multiruby.run "svn co #{url} #{dir}" unless File.directory? dir
    FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}"
  end
end
tags() click to toggle source
# File lib/multiruby.rb, line 317
def self.tags
  tags = nil
  Multiruby.in_tmp_dir do
    cache = "svn.tag.cache"
    File.unlink cache if Time.now - File.mtime(cache) > 3600 rescue nil

    File.open cache, "w" do |f|
      f.write `svn ls #{MRI_SVN}/tags/`
    end unless File.exist? cache

    tags = File.read(cache).split(/\n/).grep(/^v/).reject {|s| s =~ /preview/}
  end

  tags = tags.sort_by { |s| s.scan(/\d+/).map { |s| s.to_i } }
end
update() click to toggle source
# File lib/multiruby.rb, line 333
def self.update
  # TODO:
  # update will look at the dir name and act accordingly rel_.* will
  # figure out latest tag on that name and svn sw to it trunk and
  # others will just svn update

  clean = []

  self.each_scm_build_dir do |style|
    dir = File.basename(Dir.pwd)
    warn dir

    case style
    when :svn then
      case dir
      when /mri_\d/ then
        system "svn cleanup" # just in case
        svn_up = `svn up`
        in_build_dir do
          if svn_up =~ /^[ADUCG] / then
            clean << dir
          else
            warn "  no update"
          end
          FileUtils.ln_sf "../build/#{dir}", "../versions/#{dir}"
        end
      when /mri_rel_(.+)/ then
        ver = $1
        url = `svn info`[/^URL: (.*)/, 1]
        latest = self.mri_latest_tag(ver).chomp('/')
        new_url = File.join(File.dirname(url), latest)
        if new_url != url then
          run "svn sw #{new_url}"
          clean << dir
        else
          warn "  no update"
        end
      else
        warn "  update in this svn dir not supported yet: #{dir}"
      end
    else
      warn "  update in non-svn dir not supported yet: #{dir}"
    end
  end

  in_install_dir do
    clean.each do |dir|
      warn "removing install/#{dir}"
      FileUtils.rm_rf dir
    end
  end
end
update_rubygems() click to toggle source
# File lib/multiruby.rb, line 386
def self.update_rubygems
  warn "  Determining latest version for rubygems"
  html = URI.parse(GEM_URL).read

  versions = html.scan(/href="rubygems-update-(\d+(?:\.\d+)+).gem/).flatten
  latest = versions.sort_by { |s| s.scan(/\d+/).map { |s| s.to_i } }.last

  Multiruby.in_versions_dir do
    file = "rubygems-#{latest}.tgz"
    unless File.file? file then
      warn "    Fetching rubygems-#{latest}.tgz via HTTP."
      File.unlink(*Dir["rubygems*"])
      File.open file, 'w' do |f|
        f.write URI.parse(GEM_URL+"/"+file).read
      end
    end
  end

  Multiruby.in_build_dir do
    FileUtils.rm_rf Dir["rubygems*"]
  end

  Multiruby.in_install_dir do
    FileUtils.rm_rf Dir["*"]
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.