rexe 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/LICENSE.txt +201 -21
- data/README.md +140 -53
- data/exe/rexe +254 -164
- data/rexe.gemspec +2 -0
- metadata +17 -3
data/exe/rexe
CHANGED
@@ -10,115 +10,141 @@ require 'optparse'
|
|
10
10
|
require 'ostruct'
|
11
11
|
require 'shellwords'
|
12
12
|
|
13
|
-
class Rexe
|
14
|
-
:input_format,
|
15
|
-
:input_mode,
|
16
|
-
:loads,
|
17
|
-
:output_format,
|
18
|
-
:requires,
|
19
|
-
:log_format,
|
20
|
-
:noop)
|
13
|
+
class Rexe
|
21
14
|
|
15
|
+
VERSION = '0.13.0'
|
22
16
|
|
23
|
-
|
17
|
+
PROJECT_URL = 'https://github.com/keithrbennett/rexe'
|
24
18
|
|
25
19
|
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
class Options < Struct.new(
|
21
|
+
:input_format,
|
22
|
+
:input_mode,
|
23
|
+
:loads,
|
24
|
+
:output_format,
|
25
|
+
:requires,
|
26
|
+
:log_format,
|
27
|
+
:noop)
|
29
28
|
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
'b' => :one_big_string,
|
36
|
-
'n' => :no_input
|
37
|
-
}
|
38
|
-
end
|
30
|
+
def initialize
|
31
|
+
super
|
32
|
+
clear
|
33
|
+
end
|
39
34
|
|
40
35
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
36
|
+
def clear
|
37
|
+
self.input_format = :none
|
38
|
+
self.input_mode = :no_input
|
39
|
+
self.output_format = :puts
|
40
|
+
self.loads = []
|
41
|
+
self.requires = []
|
42
|
+
self.log_format = :none
|
43
|
+
self.noop = false
|
44
|
+
end
|
48
45
|
end
|
49
46
|
|
50
47
|
|
51
|
-
def input_parsers
|
52
|
-
@input_parsers ||= {
|
53
|
-
json: ->(obj) { JSON.parse(obj) },
|
54
|
-
marshal: ->(obj) { Marshal.load(obj) },
|
55
|
-
none: ->(obj) { obj },
|
56
|
-
yaml: ->(obj) { YAML.load(obj) },
|
57
|
-
}
|
58
|
-
end
|
59
48
|
|
60
49
|
|
61
|
-
def output_formats
|
62
|
-
@output_formats ||= {
|
63
|
-
'a' => :awesome_print,
|
64
|
-
'i' => :inspect,
|
65
|
-
'j' => :json,
|
66
|
-
'J' => :pretty_json,
|
67
|
-
'm' => :marshal,
|
68
|
-
'n' => :no_output,
|
69
|
-
'p' => :puts, # default
|
70
|
-
'P' => :pretty_print,
|
71
|
-
's' => :to_s,
|
72
|
-
'y' => :yaml,
|
73
|
-
}
|
74
|
-
end
|
75
50
|
|
51
|
+
class Lookups
|
52
|
+
def input_modes
|
53
|
+
@input_modes ||= {
|
54
|
+
'l' => :line,
|
55
|
+
'e' => :enumerator,
|
56
|
+
'b' => :one_big_string,
|
57
|
+
'n' => :no_input
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def input_formats
|
63
|
+
@input_formats ||= {
|
64
|
+
'j' => :json,
|
65
|
+
'm' => :marshal,
|
66
|
+
'n' => :none,
|
67
|
+
'y' => :yaml,
|
68
|
+
}
|
69
|
+
end
|
76
70
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
71
|
+
|
72
|
+
def input_parsers
|
73
|
+
@input_parsers ||= {
|
74
|
+
json: ->(obj) { JSON.parse(obj) },
|
75
|
+
marshal: ->(obj) { Marshal.load(obj) },
|
76
|
+
none: ->(obj) { obj },
|
77
|
+
yaml: ->(obj) { YAML.load(obj) },
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def output_formats
|
83
|
+
@output_formats ||= {
|
84
|
+
'a' => :awesome_print,
|
85
|
+
'i' => :inspect,
|
86
|
+
'j' => :json,
|
87
|
+
'J' => :pretty_json,
|
88
|
+
'm' => :marshal,
|
89
|
+
'n' => :no_output,
|
90
|
+
'p' => :puts, # default
|
91
|
+
'P' => :pretty_print,
|
92
|
+
's' => :to_s,
|
93
|
+
'y' => :yaml,
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def formatters
|
99
|
+
@formatters ||= {
|
100
|
+
awesome_print: ->(obj) { obj.ai },
|
101
|
+
inspect: ->(obj) { obj.inspect + "\n" },
|
102
|
+
json: ->(obj) { obj.to_json },
|
103
|
+
marshal: ->(obj) { Marshal.dump(obj) },
|
104
|
+
no_output: ->(_obj) { nil },
|
105
|
+
pretty_json: ->(obj) { JSON.pretty_generate(obj) },
|
106
|
+
pretty_print: ->(obj) { obj.pretty_inspect },
|
107
|
+
puts: ->(obj) { sio = StringIO.new; sio.puts(obj); sio.string }, # default
|
108
|
+
to_s: ->(obj) { obj.to_s + "\n" },
|
109
|
+
yaml: ->(obj) { obj.to_yaml },
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def format_requires
|
114
|
+
@format_requires ||= {
|
115
|
+
json: 'json',
|
116
|
+
pretty_json: 'json',
|
117
|
+
awesome_print: 'awesome_print',
|
118
|
+
pretty_print: 'pp',
|
119
|
+
yaml: 'yaml'
|
120
|
+
}
|
121
|
+
end
|
90
122
|
end
|
91
123
|
|
92
124
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
require(r) if r
|
125
|
+
|
126
|
+
attr_reader :callable, :input_parser, :lookups, :options, :output_formatter,
|
127
|
+
:log_formatter, :start_time, :user_source_code
|
128
|
+
|
129
|
+
|
130
|
+
def initialize
|
131
|
+
@start_time = DateTime.now
|
132
|
+
@options = Options.new
|
133
|
+
@lookups = Lookups.new
|
103
134
|
end
|
104
135
|
|
105
136
|
|
106
|
-
#
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
self.output_format = :puts
|
111
|
-
self.loads = []
|
112
|
-
self.requires = []
|
113
|
-
self.log_format = :none
|
114
|
-
self.noop = false
|
137
|
+
# Requires the 'require' appropriate to the specified format.
|
138
|
+
private def require_format_require(format)
|
139
|
+
r = lookups.format_requires[format]
|
140
|
+
require!(r) if r
|
115
141
|
end
|
116
142
|
|
117
143
|
|
118
144
|
def help_text
|
119
145
|
<<~HEREDOC
|
120
146
|
|
121
|
-
rexe -- Ruby Command Line Executor/Filter -- v#{VERSION} --
|
147
|
+
rexe -- Ruby Command Line Executor/Filter -- v#{VERSION} -- #{PROJECT_URL}
|
122
148
|
|
123
149
|
Executes Ruby code on the command line, optionally taking standard input and writing to standard output.
|
124
150
|
|
@@ -134,7 +160,8 @@ class Rexe < Struct.new(
|
|
134
160
|
-im Marshal
|
135
161
|
-in None
|
136
162
|
-iy YAML
|
137
|
-
-l, --load RUBY_FILE(S) Ruby file(s) to load, comma separated
|
163
|
+
-l, --load RUBY_FILE(S) Ruby file(s) to load, comma separated;
|
164
|
+
! to clear all, or precede a name with '-' to remove
|
138
165
|
-m, --input_mode MODE Mode with which to handle input (i.e. what `self` will be in your code):
|
139
166
|
-ml line mode; each line is ingested as a separate string
|
140
167
|
-me enumerator mode
|
@@ -151,7 +178,8 @@ class Rexe < Struct.new(
|
|
151
178
|
-op Puts (default)
|
152
179
|
-os to_s
|
153
180
|
-oy YAML
|
154
|
-
-r, --require REQUIRE(S) Gems and built-in libraries to require, comma separated
|
181
|
+
-r, --require REQUIRE(S) Gems and built-in libraries to require, comma separated;
|
182
|
+
! to clear all, or precede a name with '-' to remove
|
155
183
|
|
156
184
|
If there is an .rexerc file in your home directory, it will be run as Ruby code
|
157
185
|
before processing the input.
|
@@ -163,7 +191,8 @@ class Rexe < Struct.new(
|
|
163
191
|
end
|
164
192
|
|
165
193
|
|
166
|
-
|
194
|
+
# Inserts contents of REXE_OPTIONS environment variable at the beginning of ARGV.
|
195
|
+
private def prepend_environment_options
|
167
196
|
env_opt_string = ENV['REXE_OPTIONS']
|
168
197
|
if env_opt_string
|
169
198
|
args_to_prepend = Shellwords.shellsplit(env_opt_string)
|
@@ -172,15 +201,38 @@ class Rexe < Struct.new(
|
|
172
201
|
end
|
173
202
|
|
174
203
|
|
175
|
-
def
|
204
|
+
def open_resource(resource_identifier)
|
205
|
+
command = case (`uname`.chomp)
|
206
|
+
when 'Darwin'
|
207
|
+
'open'
|
208
|
+
when 'Linux'
|
209
|
+
'xdg-open'
|
210
|
+
else
|
211
|
+
'start'
|
212
|
+
end
|
213
|
+
|
214
|
+
`#{command} #{resource_identifier}`
|
215
|
+
end
|
216
|
+
|
217
|
+
|
218
|
+
def add_format_requires_to_requires_list
|
219
|
+
formats = [options.input_format, options.output_format, options.log_format]
|
220
|
+
requires = formats.map { |format| lookups.format_requires[format] }.uniq.compact
|
221
|
+
requires.each { |r| options.requires << r }
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
# Using 'optparse', parses the command line.
|
226
|
+
# Settings go into this instance's properties (see Struct declaration).
|
227
|
+
private def parse_command_line
|
176
228
|
|
177
229
|
OptionParser.new do |parser|
|
178
230
|
|
179
231
|
parser.on('-g', '--log_format FORMAT', 'Log format, logs to stderr, defaults to none (see -o for format options)') do |v|
|
180
|
-
|
181
|
-
if
|
232
|
+
options.log_format = lookups.output_formats[v]
|
233
|
+
if options.log_format.nil?
|
182
234
|
puts help_text
|
183
|
-
raise "Output mode was '#{v}' but must be one of #{output_formats.keys}."
|
235
|
+
raise "Output mode was '#{v}' but must be one of #{lookups.output_formats.keys}."
|
184
236
|
end
|
185
237
|
end
|
186
238
|
|
@@ -192,58 +244,68 @@ class Rexe < Struct.new(
|
|
192
244
|
parser.on('-i', '--input_format FORMAT',
|
193
245
|
'Mode with which to parse input values (n = none (default), j = JSON, m = Marshal, y = YAML') do |v|
|
194
246
|
|
195
|
-
|
196
|
-
if
|
247
|
+
options.input_format = lookups.input_formats[v]
|
248
|
+
if options.input_format.nil?
|
197
249
|
puts help_text
|
198
|
-
raise "Input mode was '#{v}' but must be one of #{input_formats.keys}."
|
250
|
+
raise "Input mode was '#{v}' but must be one of #{lookups.input_formats.keys}."
|
199
251
|
end
|
200
252
|
end
|
201
253
|
|
202
254
|
parser.on('-l', '--load RUBY_FILE(S)', 'Ruby file(s) to load, comma separated, or ! to clear') do |v|
|
203
255
|
if v == '!'
|
204
|
-
|
256
|
+
options.loads.clear
|
205
257
|
else
|
206
258
|
loadfiles = v.split(',').map(&:strip)
|
207
|
-
|
259
|
+
removes, adds = loadfiles.partition { |filespec| filespec[0] == '-' }
|
260
|
+
|
261
|
+
existent, nonexistent = adds.partition { |filespec| File.exists?(filespec) }
|
208
262
|
if nonexistent.any?
|
209
|
-
raise("\nDid not find the following files to load: #{nonexistent
|
263
|
+
raise("\nDid not find the following files to load: #{nonexistent}\n\n")
|
210
264
|
else
|
211
|
-
existent.each { |filespec|
|
265
|
+
existent.each { |filespec| options.loads << filespec }
|
212
266
|
end
|
267
|
+
|
268
|
+
removes.each { |filespec| options.loads -= [filespec[1..-1]] }
|
213
269
|
end
|
214
270
|
end
|
215
271
|
|
216
272
|
parser.on('-m', '--input_mode MODE',
|
217
273
|
'Mode with which to handle input (-ml, -me, -mb, -mn (default)') do |v|
|
218
274
|
|
219
|
-
|
220
|
-
if
|
275
|
+
options.input_mode = lookups.input_modes[v]
|
276
|
+
if options.input_mode.nil?
|
221
277
|
puts help_text
|
222
|
-
raise "Input mode was '#{v}' but must be one of #{input_modes.keys}."
|
278
|
+
raise "Input mode was '#{v}' but must be one of #{lookups.input_modes.keys}."
|
223
279
|
end
|
224
280
|
end
|
225
281
|
|
226
282
|
parser.on('-o', '--output_format FORMAT',
|
227
283
|
'Mode with which to format values for output (`-o` + [aijJmnpsy])') do |v|
|
228
284
|
|
229
|
-
|
230
|
-
if
|
285
|
+
options.output_format = lookups.output_formats[v]
|
286
|
+
if options.output_format.nil?
|
231
287
|
puts help_text
|
232
|
-
raise "Output mode was '#{v}' but must be one of #{output_formats.keys}."
|
288
|
+
raise "Output mode was '#{v}' but must be one of #{lookups.output_formats.keys}."
|
233
289
|
end
|
234
290
|
end
|
235
291
|
|
236
292
|
parser.on('-r', '--require REQUIRE(S)',
|
237
293
|
'Gems and built-in libraries (e.g. shellwords, yaml) to require, comma separated, or ! to clear') do |v|
|
238
294
|
if v == '!'
|
239
|
-
|
295
|
+
options.requires.clear
|
240
296
|
else
|
241
|
-
v.split(',').map(&:strip).each
|
297
|
+
v.split(',').map(&:strip).each do |r|
|
298
|
+
if r[0] == '-'
|
299
|
+
options.requires -= [r[1..-1]]
|
300
|
+
else
|
301
|
+
options.requires << r
|
302
|
+
end
|
303
|
+
end
|
242
304
|
end
|
243
305
|
end
|
244
306
|
|
245
307
|
parser.on('-c', '--clear_options', "Clear all previous command line options") do |v|
|
246
|
-
|
308
|
+
options.clear
|
247
309
|
end
|
248
310
|
|
249
311
|
# See https://stackoverflow.com/questions/54576873/ruby-optionparser-short-code-for-boolean-option
|
@@ -251,34 +313,55 @@ class Rexe < Struct.new(
|
|
251
313
|
# According to the answer, valid options are:
|
252
314
|
# -n no, -n yes, -n false, -n true, -n n, -n y, -n +, but not -n -.
|
253
315
|
parser.on('-n', '--[no-]noop [FLAG]', TrueClass, "Do not execute the code (useful with -g)") do |v|
|
254
|
-
|
316
|
+
options.noop = (v.nil? ? true : v)
|
255
317
|
end
|
256
318
|
|
257
319
|
parser.on('-v', '--version', 'Print version') do
|
258
320
|
puts VERSION
|
259
321
|
exit
|
260
322
|
end
|
323
|
+
|
324
|
+
# Undocumented feature
|
325
|
+
parser.on('', '--open-project') do
|
326
|
+
open_resource(PROJECT_URL)
|
327
|
+
exit(0)
|
328
|
+
end
|
329
|
+
|
261
330
|
end.parse!
|
262
331
|
|
263
|
-
|
264
|
-
|
332
|
+
# We want to do this after all options have been processed because we don't want any clearing of the
|
333
|
+
# options (by '-c', etc.) to result in exclusion of these needed requires.
|
334
|
+
add_format_requires_to_requires_list
|
335
|
+
|
336
|
+
options.requires.uniq!
|
337
|
+
options.loads.uniq!
|
265
338
|
|
266
339
|
end
|
267
340
|
|
268
341
|
|
269
|
-
def load_global_config_if_exists
|
342
|
+
private def load_global_config_if_exists
|
270
343
|
filespec = File.join(Dir.home, '.rexerc')
|
271
344
|
load(filespec) if File.exists?(filespec)
|
272
345
|
end
|
273
346
|
|
274
347
|
|
275
|
-
def
|
276
|
-
|
348
|
+
private def init_parser_and_formatters
|
349
|
+
@input_parser = lookups.input_parsers[options.input_format]
|
350
|
+
@output_formatter = lookups.formatters[options.output_format]
|
351
|
+
@log_formatter = lookups.formatters[options.log_format]
|
352
|
+
end
|
353
|
+
|
354
|
+
|
355
|
+
# Executes the user specified code in the manner appropriate to the input mode.
|
356
|
+
# Performs any optionally specified parsing on input and formatting on output.
|
357
|
+
private def execute(eval_context_object, code)
|
358
|
+
if options.input_format != :none && options.input_mode != :no_input
|
277
359
|
eval_context_object = input_parser.(eval_context_object)
|
278
360
|
end
|
279
361
|
|
280
362
|
value = eval_context_object.instance_eval(&code)
|
281
|
-
|
363
|
+
|
364
|
+
unless options.output_format == :no_output
|
282
365
|
print output_formatter.(value)
|
283
366
|
end
|
284
367
|
rescue Errno::EPIPE
|
@@ -286,84 +369,91 @@ class Rexe < Struct.new(
|
|
286
369
|
end
|
287
370
|
|
288
371
|
|
289
|
-
|
290
|
-
|
372
|
+
# The global $RC (Rexe Context) OpenStruct is available in your user code.
|
373
|
+
# In order to make it possible to access this object in your loaded files, we are not creating
|
374
|
+
# it here; instead we add properties to it. This way, you can initialize an OpenStruct yourself
|
375
|
+
# in your loaded code and it will still work. If you do that, beware, any properties you add will be
|
376
|
+
# included in the log output. If the to_s of your added objects is large, that might be a pain.
|
377
|
+
private def init_rexe_context
|
378
|
+
$RC ||= OpenStruct.new
|
379
|
+
$RC.count = 0
|
380
|
+
$RC.rexe_version = VERSION
|
381
|
+
$RC.start_time = start_time.iso8601
|
382
|
+
$RC.source_code = user_source_code
|
383
|
+
$RC.options = options.to_h
|
291
384
|
|
292
|
-
|
293
|
-
|
385
|
+
def $RC.i; count end # `i` aliases `count` so you can more concisely get the count in your user code
|
386
|
+
end
|
294
387
|
|
295
|
-
|
296
|
-
|
388
|
+
|
389
|
+
private def create_callable
|
390
|
+
if user_source_code.empty? && (! options.noop)
|
297
391
|
STDERR.puts "No source code provided. Use -h to display help."
|
298
392
|
exit(-1)
|
299
393
|
end
|
300
394
|
|
301
|
-
|
302
|
-
|
303
|
-
loads.each { |file| load(file) }
|
395
|
+
eval("Proc.new { #{user_source_code} }")
|
396
|
+
end
|
304
397
|
|
305
|
-
callable = eval("Proc.new { #{user_source_code} }")
|
306
398
|
|
307
|
-
|
399
|
+
private def lookup_action(mode)
|
400
|
+
{
|
308
401
|
line: -> { STDIN.each { |l| execute(l.chomp, callable); $RC.count += 1 } },
|
309
402
|
enumerator: -> { execute(STDIN.each_line, callable); $RC.count += 1 },
|
310
403
|
one_big_string: -> { big_string = STDIN.read; execute(big_string, callable); $RC.count += 1 },
|
311
404
|
no_input: -> { execute(Object.new, callable) }
|
312
|
-
}
|
313
|
-
|
314
|
-
# This global $RC (Rexe Context) OpenStruct is available in your user code.
|
315
|
-
# In order to make it possible to access this hash in your loaded files, we are not initializing
|
316
|
-
# the hash here; instead we add key/value pairs to it. This way, you can initialize a hash yourself
|
317
|
-
# in your loaded code.
|
318
|
-
$RC ||= OpenStruct.new
|
319
|
-
$RC.count = 0
|
320
|
-
$RC.rexe_version = VERSION
|
321
|
-
$RC.start_time = start_time.iso8601
|
322
|
-
$RC.source_code = user_source_code
|
323
|
-
$RC.options = self.to_h
|
324
|
-
|
325
|
-
def $RC.i; count end # `i` aliases `count` so you can more concisely get the count in your user code
|
405
|
+
}[mode]
|
406
|
+
end
|
326
407
|
|
327
|
-
actions[input_mode].() unless self.noop
|
328
408
|
|
329
|
-
|
409
|
+
private def output_log_entry
|
410
|
+
if options.log_format != :none
|
330
411
|
$RC.duration_secs = Time.now - start_time.to_time
|
331
412
|
STDERR.puts(log_formatter.($RC.to_h))
|
332
413
|
end
|
333
414
|
end
|
334
|
-
end
|
335
415
|
|
336
416
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
417
|
+
# Bypasses Bundler's restriction on loading gems
|
418
|
+
# (see https://stackoverflow.com/questions/55144094/bundler-doesnt-permit-using-gems-in-project-home-directory)
|
419
|
+
private def require!(the_require)
|
420
|
+
begin
|
421
|
+
require the_require
|
422
|
+
rescue LoadError => error
|
423
|
+
gem_path = `gem which #{the_require}`
|
424
|
+
if gem_path.chomp.strip.empty?
|
425
|
+
raise error # re-raise the error, can't fix it
|
426
|
+
else
|
427
|
+
load_dir = File.dirname(gem_path)
|
428
|
+
$LOAD_PATH << load_dir
|
429
|
+
require the_require
|
430
|
+
end
|
431
|
+
end
|
341
432
|
end
|
342
|
-
@input_parser
|
343
|
-
end
|
344
433
|
|
345
434
|
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
@output_formatter
|
352
|
-
end
|
435
|
+
# This class' entry point.
|
436
|
+
def call
|
437
|
+
|
438
|
+
prepend_environment_options
|
439
|
+
parse_command_line
|
353
440
|
|
441
|
+
options.requires.each { |r| require!(r) }
|
442
|
+
load_global_config_if_exists
|
443
|
+
options.loads.each { |file| load(file) }
|
444
|
+
|
445
|
+
@user_source_code = ARGV.join(' ')
|
446
|
+
@callable = create_callable
|
447
|
+
|
448
|
+
init_rexe_context
|
449
|
+
init_parser_and_formatters
|
354
450
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
451
|
+
# This is where the user's source code will be executed; the action will in turn call `execute`.
|
452
|
+
lookup_action(options.input_mode).call unless options.noop
|
453
|
+
|
454
|
+
output_log_entry
|
359
455
|
end
|
360
|
-
@log_formatter
|
361
456
|
end
|
362
457
|
|
363
458
|
|
364
|
-
|
365
|
-
# and must not have it run at that time:
|
366
|
-
called_as_script = (File.basename($0) == File.basename(__FILE__))
|
367
|
-
if called_as_script
|
368
|
-
Bundler.with_clean_env { Rexe.new.call }
|
369
|
-
end
|
459
|
+
Bundler.with_clean_env { Rexe.new.call }
|