ruby-prof 0.8.2 → 0.9.0
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/CHANGES +23 -13
- data/{README → README.rdoc} +118 -111
- data/Rakefile +14 -26
- data/bin/ruby-prof +16 -4
- data/examples/empty.png +0 -0
- data/examples/graph.dot +106 -0
- data/examples/graph.png +0 -0
- data/examples/minus.png +0 -0
- data/examples/multi.flat.txt +23 -0
- data/examples/multi.graph.html +906 -0
- data/examples/multi.grind.dat +194 -0
- data/examples/multi.stack.html +573 -0
- data/examples/plus.png +0 -0
- data/examples/stack.html +573 -0
- data/ext/ruby_prof/extconf.rb +0 -1
- data/ext/ruby_prof/measure_allocations.h +6 -6
- data/ext/ruby_prof/measure_cpu_time.h +5 -5
- data/ext/ruby_prof/measure_gc_runs.h +1 -1
- data/ext/ruby_prof/measure_gc_time.h +1 -1
- data/ext/ruby_prof/measure_memory.h +4 -4
- data/ext/ruby_prof/measure_process_time.h +1 -1
- data/ext/ruby_prof/measure_wall_time.h +1 -1
- data/ext/ruby_prof/ruby_prof.c +240 -167
- data/ext/ruby_prof/ruby_prof.h +12 -10
- data/ext/ruby_prof/version.h +3 -3
- data/lib/ruby-prof.rb +7 -1
- data/lib/ruby-prof/abstract_printer.rb +5 -5
- data/lib/ruby-prof/aggregate_call_info.rb +9 -3
- data/lib/ruby-prof/call_info.rb +66 -1
- data/lib/ruby-prof/call_stack_printer.rb +751 -0
- data/lib/ruby-prof/call_tree_printer.rb +2 -2
- data/lib/ruby-prof/dot_printer.rb +151 -0
- data/lib/ruby-prof/empty.png +0 -0
- data/lib/ruby-prof/flat_printer.rb +16 -16
- data/lib/ruby-prof/flat_printer_with_line_numbers.rb +13 -13
- data/lib/ruby-prof/graph_html_printer.rb +58 -36
- data/lib/ruby-prof/graph_printer.rb +30 -30
- data/lib/ruby-prof/method_info.rb +24 -4
- data/lib/ruby-prof/minus.png +0 -0
- data/lib/ruby-prof/multi_printer.rb +54 -0
- data/lib/ruby-prof/plus.png +0 -0
- data/lib/ruby-prof/rack.rb +28 -0
- data/lib/ruby-prof/result.rb +70 -0
- data/lib/ruby-prof/symbol_to_proc.rb +1 -1
- data/lib/ruby-prof/task.rb +19 -19
- data/lib/ruby-prof/test.rb +3 -3
- data/lib/ruby_prof.so +0 -0
- data/rails/environment/profile.rb +2 -2
- data/rails/example/example_test.rb +2 -2
- data/rails/profile_test_helper.rb +1 -1
- data/test/aggregate_test.rb +21 -6
- data/test/basic_test.rb +3 -3
- data/test/duplicate_names_test.rb +2 -2
- data/test/enumerable_test.rb +2 -2
- data/test/exceptions_test.rb +2 -2
- data/test/exclude_threads_test.rb +45 -45
- data/test/exec_test.rb +2 -2
- data/test/line_number_test.rb +11 -11
- data/test/measurement_test.rb +4 -3
- data/test/method_elimination_test.rb +74 -0
- data/test/module_test.rb +7 -7
- data/test/multi_printer_test.rb +81 -0
- data/test/no_method_class_test.rb +2 -2
- data/test/prime.rb +7 -10
- data/test/printers_test.rb +57 -47
- data/test/recursive_test.rb +23 -62
- data/test/singleton_test.rb +3 -2
- data/test/stack_printer_test.rb +74 -0
- data/test/stack_test.rb +1 -1
- data/test/start_stop_test.rb +2 -2
- data/test/test_suite.rb +9 -0
- data/test/thread_test.rb +17 -17
- data/test/unique_call_path_test.rb +4 -4
- metadata +29 -8
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'ruby-prof/abstract_printer'
|
2
2
|
|
3
3
|
module RubyProf
|
4
|
-
# Generates graph[link:files/examples/graph_txt.html] profile reports as text.
|
4
|
+
# Generates graph[link:files/examples/graph_txt.html] profile reports as text.
|
5
5
|
# To use the graph printer:
|
6
6
|
#
|
7
7
|
# result = RubyProf.profile do
|
@@ -17,8 +17,8 @@ module RubyProf
|
|
17
17
|
PERCENTAGE_WIDTH = 8
|
18
18
|
TIME_WIDTH = 10
|
19
19
|
CALL_WIDTH = 17
|
20
|
-
|
21
|
-
# Create a GraphPrinter. Result is a RubyProf::Result
|
20
|
+
|
21
|
+
# Create a GraphPrinter. Result is a RubyProf::Result
|
22
22
|
# object generated from a profiling run.
|
23
23
|
def initialize(result)
|
24
24
|
super(result)
|
@@ -28,22 +28,22 @@ module RubyProf
|
|
28
28
|
|
29
29
|
def calculate_thread_times
|
30
30
|
# Cache thread times since this is an expensive
|
31
|
-
# operation with the required sorting
|
31
|
+
# operation with the required sorting
|
32
32
|
@result.threads.each do |thread_id, methods|
|
33
33
|
top = methods.max
|
34
|
-
|
34
|
+
|
35
35
|
thread_time = [top.total_time, 0.01].max
|
36
|
-
|
37
|
-
@thread_times[thread_id] = thread_time
|
36
|
+
|
37
|
+
@thread_times[thread_id] = thread_time
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
# Print a graph report to the provided output.
|
42
|
-
#
|
43
|
-
# output - Any IO oject, including STDOUT or a file.
|
42
|
+
#
|
43
|
+
# output - Any IO oject, including STDOUT or a file.
|
44
44
|
# The default value is STDOUT.
|
45
|
-
#
|
46
|
-
# options - Hash of print options. See #setup_options
|
45
|
+
#
|
46
|
+
# options - Hash of print options. See #setup_options
|
47
47
|
# for more information.
|
48
48
|
#
|
49
49
|
def print(output = STDOUT, options = {})
|
@@ -52,7 +52,7 @@ module RubyProf
|
|
52
52
|
print_threads
|
53
53
|
end
|
54
54
|
|
55
|
-
private
|
55
|
+
private
|
56
56
|
def print_threads
|
57
57
|
# sort assumes that spawned threads have higher object_ids
|
58
58
|
@result.threads.sort.each do |thread_id, methods|
|
@@ -60,30 +60,30 @@ module RubyProf
|
|
60
60
|
@output << "\n" * 2
|
61
61
|
end
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def print_methods(thread_id, methods)
|
65
65
|
# Sort methods from longest to shortest total time
|
66
66
|
methods = methods.sort
|
67
|
-
|
67
|
+
|
68
68
|
toplevel = methods.last
|
69
69
|
total_time = toplevel.total_time
|
70
70
|
if total_time == 0
|
71
71
|
total_time = 0.01
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
print_heading(thread_id)
|
75
|
-
|
75
|
+
|
76
76
|
# Print each method in total time order
|
77
77
|
methods.reverse_each do |method|
|
78
78
|
total_percentage = (method.total_time/total_time) * 100
|
79
79
|
self_percentage = (method.self_time/total_time) * 100
|
80
|
-
|
80
|
+
|
81
81
|
next if total_percentage < min_percent
|
82
|
-
|
82
|
+
|
83
83
|
@output << "-" * 80 << "\n"
|
84
84
|
|
85
85
|
print_parents(thread_id, method)
|
86
|
-
|
86
|
+
|
87
87
|
# 1 is for % sign
|
88
88
|
@output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage)
|
89
89
|
@output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage)
|
@@ -95,18 +95,18 @@ module RubyProf
|
|
95
95
|
@output << sprintf(" %s", method_name(method))
|
96
96
|
if print_file
|
97
97
|
@output << sprintf(" %s:%s", method.source_file, method.line)
|
98
|
-
end
|
98
|
+
end
|
99
99
|
@output << "\n"
|
100
|
-
|
100
|
+
|
101
101
|
print_children(method)
|
102
102
|
end
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
def print_heading(thread_id)
|
106
106
|
@output << "Thread ID: #{thread_id}\n"
|
107
107
|
@output << "Total Time: #{@thread_times[thread_id]}\n"
|
108
108
|
@output << "\n"
|
109
|
-
|
109
|
+
|
110
110
|
# 1 is for % sign
|
111
111
|
@output << sprintf("%#{PERCENTAGE_WIDTH}s", "%total")
|
112
112
|
@output << sprintf("%#{PERCENTAGE_WIDTH}s", "%self")
|
@@ -118,7 +118,7 @@ module RubyProf
|
|
118
118
|
@output << " Name"
|
119
119
|
@output << "\n"
|
120
120
|
end
|
121
|
-
|
121
|
+
|
122
122
|
def print_parents(thread_id, method)
|
123
123
|
method.aggregate_parents.sort_by(&:total_time).each do |caller|
|
124
124
|
next unless caller.parent
|
@@ -127,20 +127,20 @@ module RubyProf
|
|
127
127
|
@output << sprintf("%#{TIME_WIDTH}.2f", caller.self_time)
|
128
128
|
@output << sprintf("%#{TIME_WIDTH}.2f", caller.wait_time)
|
129
129
|
@output << sprintf("%#{TIME_WIDTH}.2f", caller.children_time)
|
130
|
-
|
130
|
+
|
131
131
|
call_called = "#{caller.called}/#{method.called}"
|
132
132
|
@output << sprintf("%#{CALL_WIDTH}s", call_called)
|
133
133
|
@output << sprintf(" %s", caller.parent.target.full_name)
|
134
134
|
@output << "\n"
|
135
135
|
end
|
136
136
|
end
|
137
|
-
|
137
|
+
|
138
138
|
def print_children(method)
|
139
139
|
method.aggregate_children.sort_by(&:total_time).reverse.each do |child|
|
140
140
|
# Get children method
|
141
|
-
|
141
|
+
|
142
142
|
@output << " " * 2 * PERCENTAGE_WIDTH
|
143
|
-
|
143
|
+
|
144
144
|
@output << sprintf("%#{TIME_WIDTH}.2f", child.total_time)
|
145
145
|
@output << sprintf("%#{TIME_WIDTH}.2f", child.self_time)
|
146
146
|
@output << sprintf("%#{TIME_WIDTH}.2f", child.wait_time)
|
@@ -153,5 +153,5 @@ module RubyProf
|
|
153
153
|
end
|
154
154
|
end
|
155
155
|
end
|
156
|
-
end
|
156
|
+
end
|
157
157
|
|
@@ -27,11 +27,12 @@ module RubyProf
|
|
27
27
|
def total_time
|
28
28
|
@total_time ||= begin
|
29
29
|
call_infos.inject(0) do |sum, call_info|
|
30
|
-
sum += call_info.total_time
|
30
|
+
sum += call_info.total_time if call_info.minimal?
|
31
|
+
sum
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
34
|
-
|
35
|
+
|
35
36
|
def self_time
|
36
37
|
@self_time ||= begin
|
37
38
|
call_infos.inject(0) do |sum, call_info|
|
@@ -51,7 +52,8 @@ module RubyProf
|
|
51
52
|
def children_time
|
52
53
|
@children_time ||= begin
|
53
54
|
call_infos.inject(0) do |sum, call_info|
|
54
|
-
sum += call_info.children_time
|
55
|
+
sum += call_info.children_time if call_info.minimal?
|
56
|
+
sum
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
@@ -107,5 +109,23 @@ module RubyProf
|
|
107
109
|
def to_s
|
108
110
|
full_name
|
109
111
|
end
|
112
|
+
|
113
|
+
def dump
|
114
|
+
res = ""
|
115
|
+
res << "MINFO: #{klass_name}##{method_name} total_time: #{total_time} (#{full_name})\n"
|
116
|
+
call_infos.each do |ci|
|
117
|
+
pinfo = ci.root? ? "TOPLEVEL" : (p=ci.parent.target; "#{p.klass_name}##{p.method_name} (#{ci.parent.object_id}) (#{p.full_name})")
|
118
|
+
res << "CINFO[#{ci.object_id}] called #{ci.called} times from #{pinfo}\n"
|
119
|
+
end
|
120
|
+
res
|
121
|
+
end
|
122
|
+
|
123
|
+
# remove method from the call graph. should not be called directly.
|
124
|
+
def eliminate!
|
125
|
+
# $stderr.puts "eliminating #{self}"
|
126
|
+
call_infos.each{ |call_info| call_info.eliminate! }
|
127
|
+
call_infos.clear
|
128
|
+
end
|
129
|
+
|
110
130
|
end
|
111
|
-
end
|
131
|
+
end
|
Binary file
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module RubyProf
|
2
|
+
# Helper class to simplify printing profiles of several types from
|
3
|
+
# one profiling run. Currently prints a flat profile, a callgrind
|
4
|
+
# profile, a call stack profile and a graph profile.
|
5
|
+
class MultiPrinter
|
6
|
+
def initialize(result)
|
7
|
+
@stack_printer = CallStackPrinter.new(result)
|
8
|
+
@graph_printer = GraphHtmlPrinter.new(result)
|
9
|
+
@tree_printer = CallTreePrinter.new(result)
|
10
|
+
@flat_printer = FlatPrinter.new(result)
|
11
|
+
end
|
12
|
+
|
13
|
+
# create profile files under options[:path] or the current
|
14
|
+
# directory. options[:profile] is used as the base name for the
|
15
|
+
# pofile file, defaults to "profile".
|
16
|
+
def print(options)
|
17
|
+
@profile = options.delete(:profile) || "profile"
|
18
|
+
@directory = options.delete(:path) || File.expand_path(".")
|
19
|
+
File.open(stack_profile, "w") do |f|
|
20
|
+
@stack_printer.print(f, options.merge(:graph => "#{@profile}.graph.html"))
|
21
|
+
end
|
22
|
+
File.open(graph_profile, "w") do |f|
|
23
|
+
@graph_printer.print(f, options)
|
24
|
+
end
|
25
|
+
File.open(tree_profile, "w") do |f|
|
26
|
+
@tree_printer.print(f, options)
|
27
|
+
end
|
28
|
+
File.open(flat_profile, "w") do |f|
|
29
|
+
@flat_printer.print(f, options)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# the name of the call stack profile file
|
34
|
+
def stack_profile
|
35
|
+
"#{@directory}/#{@profile}.stack.html"
|
36
|
+
end
|
37
|
+
|
38
|
+
# the name of the graph profile file
|
39
|
+
def graph_profile
|
40
|
+
"#{@directory}/#{@profile}.graph.html"
|
41
|
+
end
|
42
|
+
|
43
|
+
# the name of the callgrind profile file
|
44
|
+
def tree_profile
|
45
|
+
"#{@directory}/#{@profile}.grind.dat"
|
46
|
+
end
|
47
|
+
|
48
|
+
# the name of the flat profile file
|
49
|
+
def flat_profile
|
50
|
+
"#{@directory}/#{@profile}.flat.txt"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
Binary file
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Rack
|
2
|
+
class RubyProf
|
3
|
+
def initialize(app)
|
4
|
+
@app = app
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
::RubyProf.start
|
9
|
+
result = @app.call(env)
|
10
|
+
data = ::RubyProf.stop
|
11
|
+
|
12
|
+
print(data)
|
13
|
+
result
|
14
|
+
end
|
15
|
+
|
16
|
+
def print
|
17
|
+
printers = {::RubyProf::FlatPrinter => 'c:/temp/profile.txt',
|
18
|
+
::RubyProf::GraphHtmlPrinter => 'c:/temp/profile.html'}
|
19
|
+
|
20
|
+
printers.each do |printer_klass, file_name|
|
21
|
+
printer = printer_klass.new(result)
|
22
|
+
::File.open(file_name, 'wb') do |file|
|
23
|
+
printer.print(file, :min_percent => 0.00000001 )
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'set'
|
2
|
+
module RubyProf
|
3
|
+
class Result
|
4
|
+
# this method gets called internally when profiling is stopped.
|
5
|
+
# it determines for each call_info whether it is minimal: a
|
6
|
+
# call_info is minimal in a call tree if the call_info is not a
|
7
|
+
# descendant of a call_info of the same method
|
8
|
+
def compute_minimality
|
9
|
+
threads.each do |threadid, method_infos|
|
10
|
+
root_methods = method_infos.select{|mi| mi.root?}
|
11
|
+
root_methods.each do |mi|
|
12
|
+
mi.call_infos.select{|ci| ci.root?}.each do |call_info_root|
|
13
|
+
call_info_root.compute_minimality(Set.new)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# eliminate some calls from the graph by merging the information into callers.
|
20
|
+
# matchers can be a list of strings or regular expressions or the name of a file containing regexps.
|
21
|
+
def eliminate_methods!(matchers)
|
22
|
+
matchers = read_regexps_from_file(matchers) if matchers.is_a?(String)
|
23
|
+
eliminated = []
|
24
|
+
threads.each do |thread_id, methods|
|
25
|
+
matchers.each{ |matcher| eliminated.concat(eliminate_methods(methods, matcher)) }
|
26
|
+
end
|
27
|
+
compute_minimality # is this really necessary?
|
28
|
+
eliminated
|
29
|
+
end
|
30
|
+
|
31
|
+
def dump
|
32
|
+
threads.each do |thread_id, methods|
|
33
|
+
$stderr.puts "Call Info Dump for thread id #{thread_id}"
|
34
|
+
methods.each do |method_info|
|
35
|
+
$stderr.puts method_info.dump
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# read regexps from file
|
43
|
+
def read_regexps_from_file(file_name)
|
44
|
+
matchers = []
|
45
|
+
File.open(matchers).each_line do |l|
|
46
|
+
next if (l =~ /^(#.*|\s*)$/) # emtpy lines and lines starting with #
|
47
|
+
matchers << Regexp.new(l.strip)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# eliminate methods matching matcher
|
52
|
+
def eliminate_methods(methods, matcher)
|
53
|
+
eliminated = []
|
54
|
+
i = 0
|
55
|
+
while i < methods.size
|
56
|
+
method_info = methods[i]
|
57
|
+
method_name = method_info.full_name
|
58
|
+
if matcher === method_name
|
59
|
+
raise "can't eliminate root method" if method_info.root?
|
60
|
+
eliminated << methods.delete_at(i)
|
61
|
+
method_info.eliminate!
|
62
|
+
else
|
63
|
+
i += 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
eliminated
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
data/lib/ruby-prof/task.rb
CHANGED
@@ -15,7 +15,7 @@ module RubyProf
|
|
15
15
|
#
|
16
16
|
# ruby-prof specific options include:
|
17
17
|
#
|
18
|
-
# output_dir - For each file specified an output
|
18
|
+
# output_dir - For each file specified an output
|
19
19
|
# file with profile information will be
|
20
20
|
# written to the output directory.
|
21
21
|
# By default, the output directory is
|
@@ -29,9 +29,9 @@ module RubyProf
|
|
29
29
|
# will not be written out.
|
30
30
|
#
|
31
31
|
# Example:
|
32
|
-
#
|
32
|
+
#
|
33
33
|
# require 'ruby-prof/task'
|
34
|
-
#
|
34
|
+
#
|
35
35
|
# RubyProf::ProfileTask.new do |t|
|
36
36
|
# t.test_files = FileList['test/test*.rb']
|
37
37
|
# t.output_dir = "c:/temp"
|
@@ -55,37 +55,37 @@ module RubyProf
|
|
55
55
|
# rake profile TEST=just_one_file.rb # run just one test file.
|
56
56
|
# rake profile TESTOPTS="-v" # run in verbose mode
|
57
57
|
# rake profile TESTOPTS="--runner=fox" # use the fox test runner
|
58
|
-
|
58
|
+
|
59
59
|
class ProfileTask < Rake::TestTask
|
60
|
-
attr_accessor :output_dir
|
61
|
-
attr_accessor :min_percent
|
60
|
+
attr_accessor :output_dir
|
61
|
+
attr_accessor :min_percent
|
62
62
|
attr_accessor :printer
|
63
|
-
|
63
|
+
|
64
64
|
def initialize(name = :profile)
|
65
65
|
super(name)
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
# Create the tasks defined by this task lib.
|
69
69
|
def define
|
70
70
|
lib_path = @libs.join(File::PATH_SEPARATOR)
|
71
71
|
desc "Profile" + (@name==:profile ? "" : " for #{@name}")
|
72
|
-
|
72
|
+
|
73
73
|
task @name do
|
74
74
|
create_output_directory
|
75
|
-
|
75
|
+
|
76
76
|
@ruby_opts.unshift( "-I#{lib_path}" )
|
77
77
|
@ruby_opts.unshift( "-w" ) if @warning
|
78
78
|
@ruby_opts.push("-S ruby-prof")
|
79
79
|
@ruby_opts.push("--printer #{@printer}")
|
80
80
|
@ruby_opts.push("--min_percent #{@min_percent}")
|
81
81
|
|
82
|
-
file_list.each do |file_path|
|
82
|
+
file_list.each do |file_path|
|
83
83
|
run_script(file_path)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
self
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
# Run script
|
90
90
|
def run_script(script_path)
|
91
91
|
run_code = ''
|
@@ -99,14 +99,14 @@ module RubyProf
|
|
99
99
|
else
|
100
100
|
file_name += ".txt"
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
output_file_path = File.join(output_directory, file_name)
|
104
|
-
|
105
|
-
command_line = @ruby_opts.join(" ") +
|
104
|
+
|
105
|
+
command_line = @ruby_opts.join(" ") +
|
106
106
|
" --file=" + output_file_path +
|
107
107
|
" " + script_path
|
108
108
|
|
109
|
-
puts "ruby " + command_line
|
109
|
+
puts "ruby " + command_line
|
110
110
|
# We have to catch the exeption to continue on. However,
|
111
111
|
# the error message will have been output to STDERR
|
112
112
|
# already by the time we get here so we don't have to
|
@@ -125,7 +125,7 @@ module RubyProf
|
|
125
125
|
def output_directory
|
126
126
|
File.expand_path(@output_dir)
|
127
127
|
end
|
128
|
-
|
128
|
+
|
129
129
|
def create_output_directory
|
130
130
|
if not File.exist?(output_directory)
|
131
131
|
Dir.mkdir(output_directory)
|
@@ -138,9 +138,9 @@ module RubyProf
|
|
138
138
|
FileUtils.rm(files)
|
139
139
|
end
|
140
140
|
end
|
141
|
-
|
141
|
+
|
142
142
|
def option_list # :nodoc:
|
143
143
|
ENV['OPTIONS'] || @options.join(" ") || ""
|
144
144
|
end
|
145
145
|
end
|
146
|
-
end
|
146
|
+
end
|