SlimTest 4.6.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +21 -0
- data/.gemtest +0 -0
- data/History.txt +795 -0
- data/Manifest.txt +38 -0
- data/README.txt +107 -0
- data/Rakefile +52 -0
- data/articles/Article.css +721 -0
- data/articles/getting_started_with_autotest.html +533 -0
- data/articles/how_to_use_zentest.txt +393 -0
- data/bin/slim-autotest +6 -0
- data/bin/slim-multigem +4 -0
- data/bin/slim-multiruby +76 -0
- data/bin/slim-multiruby_setup +74 -0
- data/bin/slim-unit_diff +38 -0
- data/bin/slim-zentest +23 -0
- data/example.txt +42 -0
- data/example1.rb +7 -0
- data/example2.rb +15 -0
- data/example_dot_autotest.rb +16 -0
- data/lib/autotest.rb +852 -0
- data/lib/autotest/autoupdate.rb +26 -0
- data/lib/autotest/bundler.rb +10 -0
- data/lib/autotest/isolate.rb +19 -0
- data/lib/autotest/once.rb +9 -0
- data/lib/autotest/preload.rb +56 -0
- data/lib/autotest/rcov.rb +27 -0
- data/lib/autotest/restart.rb +14 -0
- data/lib/autotest/timestamp.rb +9 -0
- data/lib/focus.rb +25 -0
- data/lib/functional_test_matrix.rb +92 -0
- data/lib/multiruby.rb +412 -0
- data/lib/unit_diff.rb +274 -0
- data/lib/zentest.rb +594 -0
- data/lib/zentest_mapping.rb +117 -0
- data/test/test_autotest.rb +527 -0
- data/test/test_focus.rb +35 -0
- data/test/test_unit_diff.rb +372 -0
- data/test/test_zentest.rb +566 -0
- data/test/test_zentest_mapping.rb +242 -0
- metadata +151 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module Autotest::AutoUpdate
|
2
|
+
@@sleep_time, @@update_cmd, @@updater = 60, "svn up", nil
|
3
|
+
|
4
|
+
def self.sleep_time= o
|
5
|
+
@@sleep_time = o
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.update_cmd= o
|
9
|
+
@@update_cmd = o
|
10
|
+
end
|
11
|
+
|
12
|
+
Autotest.add_hook :run_command do |at|
|
13
|
+
@@updater.kill if @@updater
|
14
|
+
end
|
15
|
+
|
16
|
+
Autotest.add_hook :ran_command do |at|
|
17
|
+
@@updater = Thread.start do
|
18
|
+
loop do
|
19
|
+
puts "# Waiting for #{@@sleep_time} seconds before updating"
|
20
|
+
sleep @@sleep_time
|
21
|
+
puts "# Running #{@@update_cmd}"
|
22
|
+
system @@update_cmd
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
##
|
2
|
+
# Run autotest with isolate support.
|
3
|
+
|
4
|
+
module Autotest::Isolate
|
5
|
+
@@dir = "tmp/isolate/#{Gem.ruby_engine}-#{RbConfig::CONFIG['ruby_version']}"
|
6
|
+
|
7
|
+
def self.dir= o
|
8
|
+
@@dir = o
|
9
|
+
end
|
10
|
+
|
11
|
+
Autotest.add_hook :initialize do |at|
|
12
|
+
ENV["GEM_HOME"] = @@dir
|
13
|
+
ENV["GEM_PATH"] = @@dir
|
14
|
+
ENV["PATH"] += ":#{@@dir}/bin"
|
15
|
+
|
16
|
+
Gem.clear_paths
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Autotest::Preload
|
2
|
+
def self.glob
|
3
|
+
@glob
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.glob= o
|
7
|
+
@glob = o
|
8
|
+
end
|
9
|
+
|
10
|
+
self.glob = "test/test_helper.rb"
|
11
|
+
|
12
|
+
Autotest.add_hook :post_initialize do |at, *args|
|
13
|
+
at.add_sigquit_handler
|
14
|
+
|
15
|
+
warn "pre-loading initializers"
|
16
|
+
t0 = Time.now
|
17
|
+
Dir[self.glob].each do |path|
|
18
|
+
require path
|
19
|
+
end
|
20
|
+
warn "done pre-loading initializers in %.2f seconds" % [Time.now - t0]
|
21
|
+
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Autotest
|
27
|
+
alias :old_run_tests :run_tests
|
28
|
+
|
29
|
+
def run_tests
|
30
|
+
hook :run_command
|
31
|
+
|
32
|
+
new_mtime = self.find_files_to_test
|
33
|
+
return unless new_mtime
|
34
|
+
self.last_mtime = new_mtime
|
35
|
+
|
36
|
+
begin
|
37
|
+
# TODO: deal with unit_diff and partial test runs later
|
38
|
+
original_argv = ARGV.dup
|
39
|
+
ARGV.clear
|
40
|
+
|
41
|
+
@child = fork do
|
42
|
+
trap "QUIT", "DEFAULT"
|
43
|
+
trap "INT", "DEFAULT"
|
44
|
+
files_to_test.keys.each do |file|
|
45
|
+
load file
|
46
|
+
end
|
47
|
+
end
|
48
|
+
Process.wait
|
49
|
+
ensure
|
50
|
+
@child = nil
|
51
|
+
ARGV.replace original_argv
|
52
|
+
end
|
53
|
+
|
54
|
+
hook :ran_command
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Autotest::RCov
|
2
|
+
@@command, @@options = "rcov", nil
|
3
|
+
|
4
|
+
def self.command= o
|
5
|
+
@@command = o
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.pattern= o
|
9
|
+
warn "RCov.pattern= no longer has any functionality. please remove."
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.options= o
|
13
|
+
@@options = o
|
14
|
+
end
|
15
|
+
|
16
|
+
Autotest.add_hook :all_good do |at|
|
17
|
+
options = @@options ? "RCOVOPTS=\"#{@@options}\"" : ""
|
18
|
+
system "rake #{@@command} #{options}"
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
Autotest.add_hook :initialize do |at|
|
23
|
+
at.add_exception 'coverage'
|
24
|
+
at.add_exception 'coverage.info'
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Autotest::Restart
|
2
|
+
Autotest.add_hook :initialize do |at|
|
3
|
+
configs = [File.expand_path('~/.autotest'), './.autotest']
|
4
|
+
at.extra_files.concat configs
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
Autotest.add_hook :updated do |at, *args|
|
9
|
+
unless args.flatten.grep(/\.autotest$/).empty? then
|
10
|
+
warn "Detected change to .autotest, restarting"
|
11
|
+
at.restart
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/focus.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Module
|
2
|
+
def focus *wanteds
|
3
|
+
wanteds.map! { |m| m.to_s }
|
4
|
+
unwanteds = public_instance_methods(false).grep(/test_/) - wanteds
|
5
|
+
unwanteds.each do |unwanted|
|
6
|
+
remove_method unwanted
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def focus_re regexp
|
11
|
+
focus(*public_instance_methods.grep(regexp))
|
12
|
+
end
|
13
|
+
|
14
|
+
def blur
|
15
|
+
parent = self.superclass
|
16
|
+
|
17
|
+
ObjectSpace.each_object Class do |klass|
|
18
|
+
next unless parent > klass
|
19
|
+
next if klass == self
|
20
|
+
|
21
|
+
klass.send :focus
|
22
|
+
klass.send :undef_method, :default_test
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
########################################################################
|
3
|
+
# The Idea:
|
4
|
+
#
|
5
|
+
# This is supposed to get us thinking about the various dimensions our
|
6
|
+
# testing should address. If there are states orthogonal to each other
|
7
|
+
# (eg. readable vs unreadable, logged in vs not logged in) each of
|
8
|
+
# those states should comprise a dimension in the matrix. By
|
9
|
+
# addressing it this way, we should be able to minimize the amount of
|
10
|
+
# setup/teardown code and get full coverage across our actions for all
|
11
|
+
# these edge cases and as a result have extremely clear tests.
|
12
|
+
#
|
13
|
+
########################################################################
|
14
|
+
# Example Test Matrix Specification:
|
15
|
+
#
|
16
|
+
# matrix :example, :edge1, :edge2, :edge3, ...
|
17
|
+
# action :action1, :OK, :e_NF, :mod, ...
|
18
|
+
# action :action2, :OK, :e_RO, :na, ...
|
19
|
+
# action ...
|
20
|
+
#
|
21
|
+
########################################################################
|
22
|
+
# Matrix:
|
23
|
+
#
|
24
|
+
# I envision the setups being a code that combines the different
|
25
|
+
# dimensions of edge case state.
|
26
|
+
#
|
27
|
+
# Something for a CMS might look like: `[df]_[ugo]_[rRwW]` where:
|
28
|
+
#
|
29
|
+
# + `[df]` for dir/file.
|
30
|
+
# + and the rest is in the style of symbolic args to chmod:
|
31
|
+
# + u/g/o = user, group, or other
|
32
|
+
# + lowercase `X` == `X`able, uppercase `X` == un`X`able, where `X`
|
33
|
+
# is read/write.
|
34
|
+
#
|
35
|
+
########################################################################
|
36
|
+
# Action:
|
37
|
+
#
|
38
|
+
# :new/:err/:del are just examples, they should have semantic info
|
39
|
+
# attached to them.
|
40
|
+
#
|
41
|
+
# Use :na to specify an inapplicable edge case for that action.
|
42
|
+
#
|
43
|
+
# Use :OK to specify the standard positive state. It is equivalent to
|
44
|
+
# a result with the same name as the action. (eg
|
45
|
+
# matrix_test_index). This cleans up the matrix a lot and allows for
|
46
|
+
# narrower and more readable columns.
|
47
|
+
#
|
48
|
+
# Edge cases specific to an action that fall outside the matrix are
|
49
|
+
# regular tests.
|
50
|
+
#
|
51
|
+
########################################################################
|
52
|
+
# Matrix Methods (the legos):
|
53
|
+
#
|
54
|
+
# Everything else basically equates to lego pieces:
|
55
|
+
#
|
56
|
+
# + There is one "init" method per matrix: matrix_init_#{descr}(setup_args)
|
57
|
+
# + There is one "setup" method per action: matrix_setup_#{action}(setup, expect)
|
58
|
+
# + There is one "test" method per result: matrix_test_#{result}(setup)
|
59
|
+
#
|
60
|
+
# Thus, for the matrix "example" above, the top left-most test will
|
61
|
+
# end up calling:
|
62
|
+
#
|
63
|
+
# matrix_init_example(:edge1)
|
64
|
+
# matrix_setup_action1(:edge1, :new)
|
65
|
+
# matrix_test_new(:edge1)
|
66
|
+
#
|
67
|
+
# Read the action method for exact details.
|
68
|
+
########################################################################
|
69
|
+
|
70
|
+
module FunctionalTestMatrix
|
71
|
+
def matrix(name, *setups)
|
72
|
+
@@matrix, @@setups = name, setups
|
73
|
+
end
|
74
|
+
|
75
|
+
def action(action, *results)
|
76
|
+
testcases = @@setups.zip(results).reject { |a,b| b == :na }
|
77
|
+
testcases = Hash[*testcases.flatten]
|
78
|
+
matrix = @@matrix # bind to local scope for define_method closure
|
79
|
+
|
80
|
+
testcases.each do |setup, expected|
|
81
|
+
expected_action = expected == :OK ? action : expected
|
82
|
+
define_method "test_#{matrix}_#{action}_#{setup}" do
|
83
|
+
@action = action
|
84
|
+
send "matrix_init_#{matrix}", *setup.to_s.split(/_/).map {|c| c.intern }
|
85
|
+
send "matrix_setup_#{action}", setup, expected
|
86
|
+
send "matrix_test_#{expected_action}", setup
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
module_function :matrix, :action
|
92
|
+
end
|
data/lib/multiruby.rb
ADDED
@@ -0,0 +1,412 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
##
|
5
|
+
# multiruby_setup is a script to help you manage multiruby.
|
6
|
+
#
|
7
|
+
# usage: multiruby_setup [-h|cmd|spec...]
|
8
|
+
#
|
9
|
+
# cmds:
|
10
|
+
#
|
11
|
+
# -h, --help, help = show this help.
|
12
|
+
# build = build and install everything. used internally.
|
13
|
+
# clean = clean scm build dirs and remove non-scm build dirs.
|
14
|
+
# list = print installed versions.
|
15
|
+
# rm:$version = remove a particular version.
|
16
|
+
# rubygems:merge = symlink all rubygem dirs to one dir.
|
17
|
+
# tags = list all tags from svn.
|
18
|
+
# update = update svn builds.
|
19
|
+
# update:rubygems = update rubygems and nuke install dirs.
|
20
|
+
#
|
21
|
+
# specs:
|
22
|
+
#
|
23
|
+
# the_usual = alias for latest versions from tar + rubygems
|
24
|
+
# mri:svn:current = alias for mri:svn:releases and mri:svn:branches.
|
25
|
+
# mri:svn:releases = alias for supported releases of mri ruby.
|
26
|
+
# mri:svn:branches = alias for active branches of mri ruby.
|
27
|
+
# mri:svn:branch:$branch = install a specific $branch of mri from svn.
|
28
|
+
# mri:svn:tag:$tag = install a specific $tag of mri from svn.
|
29
|
+
# mri:tar:$version = install a specific $version of mri from tarball.
|
30
|
+
#
|
31
|
+
# environment variables:
|
32
|
+
#
|
33
|
+
# GEM_URL = url for rubygems tarballs
|
34
|
+
# MRI_SVN = url for MRI SVN
|
35
|
+
# RUBY_URL = url for MRI tarballs
|
36
|
+
# VERSIONS = what versions to install
|
37
|
+
#
|
38
|
+
# RUBYOPT is cleared on installs.
|
39
|
+
#
|
40
|
+
# NOTES:
|
41
|
+
#
|
42
|
+
# * you can add a symlink to your rubinius build into ~/.multiruby/install
|
43
|
+
# * I need patches/maintainers for other implementations.
|
44
|
+
#
|
45
|
+
module Multiruby
|
46
|
+
def self.env name, fallback; ENV[name] || fallback; end # :nodoc:
|
47
|
+
|
48
|
+
TAGS = %w( 1_8_7 1_9_1 1_9_2)
|
49
|
+
BRANCHES = %w(1_8 1_8_7 1_9 trunk)
|
50
|
+
|
51
|
+
VERSIONS = env('VERSIONS', TAGS.join(":").gsub(/_/, '.')).split(/:/)
|
52
|
+
MRI_SVN = env 'MRI_SVN', 'http://svn.ruby-lang.org/repos/ruby'
|
53
|
+
RUBY_URL = env 'RUBY_URL', 'http://ftp.ruby-lang.org/pub/ruby'
|
54
|
+
GEM_URL = env 'GEM_URL', 'http://files.rubyforge.vm.bytemark.co.uk/rubygems'
|
55
|
+
|
56
|
+
HELP = []
|
57
|
+
|
58
|
+
File.readlines(__FILE__).each do |line|
|
59
|
+
next unless line =~ /^#( |$)/
|
60
|
+
HELP << line.sub(/^# ?/, '')
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.build_and_install
|
64
|
+
ENV.delete 'RUBYOPT'
|
65
|
+
|
66
|
+
root_dir = self.root_dir
|
67
|
+
versions = []
|
68
|
+
|
69
|
+
Dir.chdir root_dir do
|
70
|
+
self.setup_dirs
|
71
|
+
|
72
|
+
rubygems = Dir["versions/rubygems*.tgz"]
|
73
|
+
abort "You should delete all but one rubygem tarball" if rubygems.size > 1
|
74
|
+
rubygem_tarball = File.expand_path rubygems.last rescue nil
|
75
|
+
|
76
|
+
Dir.chdir "build" do
|
77
|
+
Dir["../versions/*"].sort.each do |tarball|
|
78
|
+
next if tarball =~ /rubygems/
|
79
|
+
|
80
|
+
build_dir = File.basename tarball, ".tar.gz"
|
81
|
+
version = build_dir.sub(/^ruby-?/, '')
|
82
|
+
versions << version
|
83
|
+
inst_dir = "#{root_dir}/install/#{version}"
|
84
|
+
|
85
|
+
unless test ?d, inst_dir then
|
86
|
+
unless test ?d, build_dir then
|
87
|
+
if test ?d, tarball then
|
88
|
+
dir = File.basename tarball
|
89
|
+
FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}"
|
90
|
+
else
|
91
|
+
puts "creating #{inst_dir}"
|
92
|
+
Dir.mkdir inst_dir
|
93
|
+
run "tar zxf #{tarball}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
Dir.chdir build_dir do
|
97
|
+
puts "building and installing #{version}"
|
98
|
+
if test ?f, "configure.in" then
|
99
|
+
gnu_utils_build inst_dir
|
100
|
+
elsif test ?f, "Rakefile" then
|
101
|
+
rake_build inst_dir
|
102
|
+
else
|
103
|
+
raise "dunno how to build"
|
104
|
+
end
|
105
|
+
|
106
|
+
if rubygem_tarball and version !~ /1[._-]9|mri_trunk|rubinius/ then
|
107
|
+
rubygems = File.basename rubygem_tarball, ".tgz"
|
108
|
+
run "tar zxf #{rubygem_tarball}" unless test ?d, rubygems
|
109
|
+
|
110
|
+
Dir.chdir rubygems do
|
111
|
+
run "../ruby ./setup.rb --no-rdoc --no-ri", "../log.rubygems"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
versions
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.clean
|
124
|
+
self.each_scm_build_dir do |style|
|
125
|
+
case style
|
126
|
+
when :svn then
|
127
|
+
if File.exist? "Rakefile" then
|
128
|
+
run "rake clean"
|
129
|
+
elsif File.exist? "Makefile" then
|
130
|
+
run "make clean"
|
131
|
+
end
|
132
|
+
else
|
133
|
+
FileUtils.rm_rf Dir.pwd
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.each_scm_build_dir
|
139
|
+
Multiruby.in_build_dir do
|
140
|
+
Dir["*"].each do |dir|
|
141
|
+
next unless File.directory? dir
|
142
|
+
Dir.chdir dir do
|
143
|
+
if File.exist?(".svn") then
|
144
|
+
yield :svn
|
145
|
+
else
|
146
|
+
yield :none
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.matching_versions url, matching=nil
|
154
|
+
file = URI.parse(url).read
|
155
|
+
|
156
|
+
map = {
|
157
|
+
"preview" => "beta",
|
158
|
+
"rc" => "beta2",
|
159
|
+
"p" => "release",
|
160
|
+
"tar" => "aargh",
|
161
|
+
"gz" => "aargh",
|
162
|
+
}
|
163
|
+
|
164
|
+
versions = file.scan(/href="(ruby.*tar.gz)"/).flatten.sort_by { |s|
|
165
|
+
s.scan(/\d+|[a-z]+/).map { |a| Integer(a) rescue map[a] || a }
|
166
|
+
}
|
167
|
+
|
168
|
+
versions = versions.grep(/#{Regexp.escape(matching)}/) if matching
|
169
|
+
|
170
|
+
versions
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.fetch_tar v
|
174
|
+
in_versions_dir do
|
175
|
+
warn " Determining latest version for #{v}"
|
176
|
+
ver = v[/\d+\.\d+/]
|
177
|
+
base = matching_versions("#{RUBY_URL}/#{ver}/", v).last
|
178
|
+
abort "Could not determine release for #{v}" unless base
|
179
|
+
url = File.join RUBY_URL, ver, base
|
180
|
+
unless File.file? base then
|
181
|
+
warn " Fetching #{base} via HTTP... this might take a while."
|
182
|
+
open(url) do |f|
|
183
|
+
File.open base, 'w' do |out|
|
184
|
+
out.write f.read
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.gnu_utils_build inst_dir
|
192
|
+
run "autoconf" unless test ?f, "configure"
|
193
|
+
run "./configure --enable-shared --prefix #{inst_dir}", "log.configure" unless
|
194
|
+
test ?f, "Makefile"
|
195
|
+
run "(nice make -j4; nice make)", "log.build"
|
196
|
+
run "make install", "log.install"
|
197
|
+
end
|
198
|
+
|
199
|
+
def self.help
|
200
|
+
puts HELP.join
|
201
|
+
end
|
202
|
+
|
203
|
+
def self.in_build_dir
|
204
|
+
in_root_dir "build" do
|
205
|
+
yield
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.in_install_dir
|
210
|
+
in_root_dir "install" do
|
211
|
+
yield
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.in_root_dir subdir = ""
|
216
|
+
Dir.chdir File.join(self.root_dir, subdir) do
|
217
|
+
yield
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def self.in_tmp_dir
|
222
|
+
in_root_dir "tmp" do
|
223
|
+
yield
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def self.in_versions_dir
|
228
|
+
in_root_dir "versions" do
|
229
|
+
yield
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def self.list
|
234
|
+
puts "Known versions:"
|
235
|
+
in_install_dir do
|
236
|
+
Dir["*"].sort.each do |d|
|
237
|
+
puts " #{d}"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def self.merge_rubygems
|
243
|
+
in_install_dir do
|
244
|
+
gems = Dir["*/lib/ruby/gems"]
|
245
|
+
|
246
|
+
unless test ?d, "../gems" then
|
247
|
+
FileUtils.mv gems.first, ".."
|
248
|
+
end
|
249
|
+
|
250
|
+
gems.each do |d|
|
251
|
+
FileUtils.rm_rf d
|
252
|
+
FileUtils.ln_sf "../../../../gems", d
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def self.mri_latest_tag v
|
258
|
+
Multiruby.tags.grep(/#{v}/).last
|
259
|
+
end
|
260
|
+
|
261
|
+
def self.rake_build inst_dir
|
262
|
+
run "rake", "log.build"
|
263
|
+
FileUtils.ln_sf "../build/#{File.basename Dir.pwd}", inst_dir
|
264
|
+
end
|
265
|
+
|
266
|
+
def self.rm name
|
267
|
+
Multiruby.in_root_dir do
|
268
|
+
FileUtils.rm_rf Dir["*/#{name}"]
|
269
|
+
f = "versions/ruby-#{name}.tar.gz"
|
270
|
+
File.unlink f if test ?f, f
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def self.root_dir
|
275
|
+
root_dir = File.expand_path(ENV['MULTIRUBY'] ||
|
276
|
+
File.join(ENV['HOME'], ".multiruby"))
|
277
|
+
|
278
|
+
unless test ?d, root_dir then
|
279
|
+
puts "creating #{root_dir}"
|
280
|
+
Dir.mkdir root_dir, 0700
|
281
|
+
end
|
282
|
+
|
283
|
+
root_dir
|
284
|
+
end
|
285
|
+
|
286
|
+
def self.run base_cmd, log = nil
|
287
|
+
cmd = base_cmd
|
288
|
+
cmd += " > #{log} 2>&1" if log
|
289
|
+
puts "Running command: #{cmd}"
|
290
|
+
raise "ERROR: Command failed with exit code #{$?}" unless system cmd
|
291
|
+
end
|
292
|
+
|
293
|
+
def self.setup_dirs download = true
|
294
|
+
%w(build install versions tmp).each do |dir|
|
295
|
+
unless test ?d, dir then
|
296
|
+
puts "creating #{dir}"
|
297
|
+
Dir.mkdir dir
|
298
|
+
if dir == "versions" && download then
|
299
|
+
warn " Downloading initial ruby tarballs to ~/.multiruby/versions:"
|
300
|
+
VERSIONS.each do |v|
|
301
|
+
self.fetch_tar v
|
302
|
+
end
|
303
|
+
warn " ...done"
|
304
|
+
warn " Put other ruby tarballs in ~/.multiruby/versions to use them."
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def self.svn_co url, dir
|
311
|
+
Multiruby.in_versions_dir do
|
312
|
+
Multiruby.run "svn co #{url} #{dir}" unless File.directory? dir
|
313
|
+
FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def self.tags
|
318
|
+
tags = nil
|
319
|
+
Multiruby.in_tmp_dir do
|
320
|
+
cache = "svn.tag.cache"
|
321
|
+
File.unlink cache if Time.now - File.mtime(cache) > 3600 rescue nil
|
322
|
+
|
323
|
+
File.open cache, "w" do |f|
|
324
|
+
f.write `svn ls #{MRI_SVN}/tags/`
|
325
|
+
end unless File.exist? cache
|
326
|
+
|
327
|
+
tags = File.read(cache).split(/\n/).grep(/^v/).reject {|s| s =~ /preview/}
|
328
|
+
end
|
329
|
+
|
330
|
+
tags = tags.sort_by { |s| s.scan(/\d+/).map { |s| s.to_i } }
|
331
|
+
end
|
332
|
+
|
333
|
+
def self.update
|
334
|
+
# TODO:
|
335
|
+
# update will look at the dir name and act accordingly rel_.* will
|
336
|
+
# figure out latest tag on that name and svn sw to it trunk and
|
337
|
+
# others will just svn update
|
338
|
+
|
339
|
+
clean = []
|
340
|
+
|
341
|
+
self.each_scm_build_dir do |style|
|
342
|
+
dir = File.basename(Dir.pwd)
|
343
|
+
warn dir
|
344
|
+
|
345
|
+
case style
|
346
|
+
when :svn then
|
347
|
+
case dir
|
348
|
+
when /mri_\d/ then
|
349
|
+
system "svn cleanup" # just in case
|
350
|
+
svn_up = `svn up`
|
351
|
+
in_build_dir do
|
352
|
+
if svn_up =~ /^[ADUCG] / then
|
353
|
+
clean << dir
|
354
|
+
else
|
355
|
+
warn " no update"
|
356
|
+
end
|
357
|
+
FileUtils.ln_sf "../build/#{dir}", "../versions/#{dir}"
|
358
|
+
end
|
359
|
+
when /mri_rel_(.+)/ then
|
360
|
+
ver = $1
|
361
|
+
url = `svn info`[/^URL: (.*)/, 1]
|
362
|
+
latest = self.mri_latest_tag(ver).chomp('/')
|
363
|
+
new_url = File.join(File.dirname(url), latest)
|
364
|
+
if new_url != url then
|
365
|
+
run "svn sw #{new_url}"
|
366
|
+
clean << dir
|
367
|
+
else
|
368
|
+
warn " no update"
|
369
|
+
end
|
370
|
+
else
|
371
|
+
warn " update in this svn dir not supported yet: #{dir}"
|
372
|
+
end
|
373
|
+
else
|
374
|
+
warn " update in non-svn dir not supported yet: #{dir}"
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
in_install_dir do
|
379
|
+
clean.each do |dir|
|
380
|
+
warn "removing install/#{dir}"
|
381
|
+
FileUtils.rm_rf dir
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
def self.update_rubygems
|
387
|
+
warn " Determining latest version for rubygems"
|
388
|
+
html = URI.parse(GEM_URL).read
|
389
|
+
|
390
|
+
versions = html.scan(/href="rubygems-update-(\d+(?:\.\d+)+).gem/i).flatten
|
391
|
+
latest = versions.sort_by { |s| s.scan(/\d+/).map { |s| s.to_i } }.last
|
392
|
+
|
393
|
+
Multiruby.in_versions_dir do
|
394
|
+
file = "rubygems-#{latest}.tgz"
|
395
|
+
unless File.file? file then
|
396
|
+
warn " Fetching rubygems-#{latest}.tgz via HTTP."
|
397
|
+
File.unlink(*Dir["rubygems*"])
|
398
|
+
File.open file, 'w' do |f|
|
399
|
+
f.write URI.parse(GEM_URL+"/"+file).read
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
Multiruby.in_build_dir do
|
405
|
+
FileUtils.rm_rf Dir["rubygems*"]
|
406
|
+
end
|
407
|
+
|
408
|
+
Multiruby.in_install_dir do
|
409
|
+
FileUtils.rm_rf Dir["*"]
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|