Created
February 8, 2009 03:15
-
-
Save adzap/60159 to your computer and use it in GitHub Desktop.
A copy of the changes to multiruby from a pastie (http://pastie.org/375339)
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
require 'fileutils' | |
require 'open-uri' | |
## | |
# multiruby_setup is a script to help you manage multiruby. | |
# | |
# usage: multiruby_setup [-h|cmd|spec...] | |
# | |
# cmds: | |
# | |
# h, help - show this help. | |
# list - print installed versions. | |
# update - update svn builds. | |
# update:rubygems - update rubygems and nuke install dirs. | |
# rubygems:merge - symlink all rubygem dirs to one dir. | |
# rm:$version - remove a particular version. | |
# clean - clean scm build dirs and remove non-scm build dirs. | |
# | |
# specs: | |
# | |
# 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. | |
# rbx:ln:$dir - symlink your rbx $dir | |
# rbx:git:current - install rbx from git | |
# | |
# NOTES: | |
# | |
# * you can add a symlink to your rubinius build into ~/.multiruby/install | |
# * I'll get to adding support for other implementations soon. | |
# | |
module Multiruby | |
MRI_SVN = "http://svn.ruby-lang.org/repos/ruby" | |
RBX_GIT = "git://git.rubini.us" | |
TAGS = %w( 1_8_6 1_8_7 1_9 ) | |
BRANCHES = %w(1_8 1_8_6 1_8_7 trunk) | |
HELP = [] | |
File.readlines(__FILE__).each do |line| | |
next unless line =~ /^#( |$)/ | |
HELP << line.sub(/^# ?/, '') | |
end | |
def self.build_and_install | |
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/*"].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 ?d, inst_dir then | |
unless test ?d, build_dir then | |
if test ?d, 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 ?f, "configure.in" then | |
gnu_utils_build inst_dir | |
elsif test ?f, "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 ?d, rubygems | |
Dir.chdir rubygems do | |
run "../ruby ./setup.rb --no-rdoc --no-ri > ../log.rubygems" | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
versions | |
end | |
def self.clean | |
self.each_scm_build_dir do |style| | |
case style | |
when :svn, :git 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 | |
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") || File.exist?(".git") then | |
scm = File.exist?(".svn") ? :svn : :git | |
yield scm | |
else | |
yield :none | |
end | |
end | |
end | |
end | |
end | |
def self.extract_latest_version url, matching=nil | |
file = URI.parse(url).read | |
versions = file.scan(/href="(ruby.*tar.gz)"/).flatten.reject { |s| | |
s =~ /preview/ | |
}.sort_by { |s| | |
s.split(/\D+/).map { |i| i.to_i } | |
}.flatten | |
versions = versions.grep(/#{Regexp.escape(matching)}/) if matching | |
versions.last | |
end | |
def self.fetch_tar v | |
require 'open-uri' | |
base_url = "http://ftp.ruby-lang.org/pub/ruby" | |
in_versions_dir do | |
warn " Determining latest version for #{v}" | |
ver = v[/\d+\.\d+/] | |
base = extract_latest_version("#{base_url}/#{ver}/", v) | |
abort "Could not determine release for #{v}" unless base | |
url = File.join base_url, ver, base | |
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 | |
def self.git_clone url, dir | |
Multiruby.in_versions_dir do | |
Multiruby.run "git clone #{url} #{dir}" unless File.directory? dir | |
FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}" | |
end | |
end | |
def self.gnu_utils_build inst_dir | |
run "autoconf" unless test ?f, "configure" | |
run "./configure --prefix #{inst_dir} > log.configure" unless test ?f, "Makefile" | |
run "nice make -j4 > log.build" | |
run "make install > log.install" | |
end | |
def self.rake_build inst_dir | |
run "rake > log.build" | |
FileUtils.ln_sf "../build/#{File.basename Dir.pwd}", inst_dir | |
end | |
def self.help | |
puts HELP.join | |
end | |
def self.in_build_dir | |
Dir.chdir File.join(self.root_dir, "build") do | |
yield | |
end | |
end | |
def self.in_install_dir | |
Dir.chdir File.join(self.root_dir, "install") do | |
yield | |
end | |
end | |
def self.in_root_dir | |
Dir.chdir self.root_dir do | |
yield | |
end | |
end | |
def self.in_tmp_dir | |
Dir.chdir File.join(self.root_dir, "tmp") do | |
yield | |
end | |
end | |
def self.in_versions_dir | |
Dir.chdir File.join(self.root_dir, "versions") do | |
yield | |
end | |
end | |
def self.list | |
puts "Known versions:" | |
in_install_dir do | |
Dir["*"].sort.each do |d| | |
puts " #{d}" | |
end | |
end | |
end | |
def self.merge_rubygems | |
in_install_dir do | |
gems = Dir["*/lib/ruby/gems"] | |
unless test ?d, "../gems" then | |
FileUtils.mv gems.first, ".." | |
end | |
gems.each do |d| | |
FileUtils.rm_rf d | |
FileUtils.ln_sf "../../../../gems", d | |
end | |
end | |
end | |
def self.mri_latest_tag v | |
Multiruby.tags.grep(/#{v}/).last | |
end | |
def self.rbx_ln dir | |
dir = File.expand_path dir | |
Multiruby.in_versions_dir do | |
FileUtils.ln_sf dir, "rubinius" | |
FileUtils.ln_sf "../versions/rubinius", "../install/rubinius" | |
end | |
end | |
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 ?f, f | |
end | |
end | |
def self.root_dir | |
root_dir = File.expand_path(ENV['MULTIRUBY'] || | |
File.join(ENV['HOME'], ".multiruby")) | |
unless test ?d, root_dir then | |
puts "creating #{root_dir}" | |
Dir.mkdir root_dir, 0700 | |
end | |
root_dir | |
end | |
def self.run(cmd) | |
puts "Running command: #{cmd}" | |
raise "ERROR: Command failed with exit code #{$?}" unless system cmd | |
end | |
def self.setup_dirs(download = true) | |
%w(build install versions tmp).each do |dir| | |
unless test ?d, dir then | |
puts "creating #{dir}" | |
Dir.mkdir dir | |
if dir == "versions" && download then | |
warn " Downloading initial ruby tarballs to ~/.multiruby/versions:" | |
%w(1.8 1.9).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 | |
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 | |
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 | |
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 | |
when :git then | |
case dir | |
when /rubinius/ then | |
run "rake git:update build" # minor cheat by building here | |
else | |
warn " update in this git 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 | |
def self.update_rubygems | |
base = "http://rubyforge.org" | |
url = "#{base}/frs/?group_id=126" | |
html = URI.parse(url).read | |
link, latest = html.scan(/href="(.*rubygems-(\d+(?:\.\d+)+).tgz)"/).first | |
Multiruby.in_versions_dir do | |
File.unlink(*Dir["rubygems*"]) | |
file = "rubygems-#{latest}.tgz" | |
File.open file, 'w' do |f| | |
f.write URI.parse(base+link).read | |
end | |
end | |
Multiruby.in_install_dir do | |
FileUtils.rm_rf Dir["*"] | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment