SlimTest 4.6.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|