1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
require 'mspec/guards/platform'
require 'mspec/helpers/tmp'
# The ruby_exe helper provides a wrapper for invoking the
# same Ruby interpreter with the same falgs as the one running
# the specs and getting the output from running the code.
# If +code+ is a file that exists, it will be run.
# Otherwise, +code+ should be Ruby code that will be run with
# the -e command line option. For example:
#
# ruby_exe('path/to/some/file.rb')
#
# will be executed as
#
# `#{RUBY_EXE} 'path/to/some/file.rb'`
#
# while
#
# ruby_exe('puts "hello, world."')
#
# will be executed as
#
# `#{RUBY_EXE} -e 'puts "hello, world."'`
#
# The ruby_exe helper also accepts an options hash with three
# keys: :options, :args and :env. For example:
#
# ruby_exe('file.rb', :options => "-w",
# :args => "> file.txt",
# :env => { :FOO => "bar" })
#
# will be executed as
#
# `#{RUBY_EXE} -w #{'file.rb'} > file.txt`
#
# with access to ENV["FOO"] with value "bar".
#
# If +nil+ is passed for the first argument, the command line
# will be built only from the options hash.
#
# The RUBY_EXE constant is setup by mspec automatically
# and is used by ruby_exe and ruby_cmd. The mspec runner script
# will set ENV['RUBY_EXE'] to the name of the executable used
# to invoke the mspec-run script. The value of RUBY_EXE will be
# constructed as follows:
#
# 1. the value of ENV['RUBY_EXE']
# 2. an explicit value based on RUBY_ENGINE
# 3. cwd/(RUBY_ENGINE + $(EXEEXT) || $(exeext) || '')
# 4. $(bindir)/$(RUBY_INSTALL_NAME)
#
# The value will only be used if the file exists and is executable.
# The flags will then be appended to the resulting value.
#
# These 4 ways correspond to the following scenarios:
#
# 1. Using the MSpec runner scripts, the name of the
# executable is explicitly passed by ENV['RUBY_EXE']
# so there is no ambiguity.
#
# Otherwise, if using RSpec (or something else)
#
# 2. Running the specs while developing an alternative
# Ruby implementation. This explicitly names the
# executable in the development directory based on
# the value of RUBY_ENGINE.
# 3. Running the specs within the source directory for
# some implementation. (E.g. a local build directory.)
# 4. Running the specs against some installed Ruby
# implementation.
#
# Additionally, the flags passed to mspec
# (with -T on the command line or in the config with set :flags)
# will be appended to RUBY_EXE so that the interpreter
# is always called with those flags.
def ruby_exe_options(option)
case option
when :env
ENV['RUBY_EXE']
when :engine
case RUBY_ENGINE
when 'rbx'
"bin/rbx"
when 'jruby'
"bin/jruby"
when 'maglev'
"maglev-ruby"
when 'topaz'
"topaz"
when 'ironruby'
"ir"
end
when :name
require 'rbconfig'
bin = RUBY_ENGINE + (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '')
File.join(".", bin)
when :install_name
require 'rbconfig'
bin = RbConfig::CONFIG["RUBY_INSTALL_NAME"] || RbConfig::CONFIG["ruby_install_name"]
bin << (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '')
File.join(RbConfig::CONFIG['bindir'], bin)
end
end
def resolve_ruby_exe
[:env, :engine, :name, :install_name].each do |option|
next unless exe = ruby_exe_options(option)
if File.file?(exe) and File.executable?(exe)
exe = File.expand_path(exe)
exe = exe.tr('/', '\\') if PlatformGuard.windows?
flags = ENV['RUBY_FLAGS']
if flags and !flags.empty?
return exe + ' ' + flags
else
return exe
end
end
end
raise Exception, "Unable to find a suitable ruby executable."
end
def ruby_exe(code, opts = {})
if opts[:dir]
raise "ruby_exe(..., dir: dir) is no longer supported, use Dir.chdir"
end
env = opts[:env] || {}
saved_env = {}
env.each do |key, value|
key = key.to_s
saved_env[key] = ENV[key] if ENV.key? key
ENV[key] = value
end
escape = opts.delete(:escape)
if code and !File.exist?(code) and escape != false
tmpfile = tmp("rubyexe.rb")
File.open(tmpfile, "w") { |f| f.write(code) }
code = tmpfile
end
begin
platform_is_not :opal do
`#{ruby_cmd(code, opts)}`
end
ensure
saved_env.each { |key, value| ENV[key] = value }
env.keys.each do |key|
key = key.to_s
ENV.delete key unless saved_env.key? key
end
File.delete tmpfile if tmpfile
end
end
def ruby_cmd(code, opts = {})
body = code
if opts[:escape]
raise "escape: true is no longer supported in ruby_cmd, use ruby_exe or a fixture"
end
if code and !File.exist?(code)
body = "-e #{code.inspect}"
end
[RUBY_EXE, opts[:options], body, opts[:args]].compact.join(' ')
end
unless Object.const_defined?(:RUBY_EXE) and RUBY_EXE
RUBY_EXE = resolve_ruby_exe
end
|