airbnb-ruby-prof 0.0.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/CHANGES +483 -0
- data/LICENSE +25 -0
- data/README.rdoc +426 -0
- data/Rakefile +51 -0
- data/bin/ruby-prof +279 -0
- data/bin/ruby-prof-check-trace +45 -0
- data/examples/flat.txt +50 -0
- data/examples/graph.dot +84 -0
- data/examples/graph.html +823 -0
- data/examples/graph.txt +139 -0
- data/examples/multi.flat.txt +23 -0
- data/examples/multi.graph.html +760 -0
- data/examples/multi.grind.dat +114 -0
- data/examples/multi.stack.html +547 -0
- data/examples/stack.html +547 -0
- data/ext/ruby_prof/extconf.rb +67 -0
- data/ext/ruby_prof/rp_call_info.c +374 -0
- data/ext/ruby_prof/rp_call_info.h +59 -0
- data/ext/ruby_prof/rp_fast_call_tree_printer.c +247 -0
- data/ext/ruby_prof/rp_fast_call_tree_printer.h +10 -0
- data/ext/ruby_prof/rp_measure.c +71 -0
- data/ext/ruby_prof/rp_measure.h +56 -0
- data/ext/ruby_prof/rp_measure_allocations.c +74 -0
- data/ext/ruby_prof/rp_measure_cpu_time.c +134 -0
- data/ext/ruby_prof/rp_measure_gc_runs.c +71 -0
- data/ext/ruby_prof/rp_measure_gc_time.c +58 -0
- data/ext/ruby_prof/rp_measure_memory.c +75 -0
- data/ext/ruby_prof/rp_measure_process_time.c +69 -0
- data/ext/ruby_prof/rp_measure_wall_time.c +43 -0
- data/ext/ruby_prof/rp_method.c +717 -0
- data/ext/ruby_prof/rp_method.h +79 -0
- data/ext/ruby_prof/rp_stack.c +221 -0
- data/ext/ruby_prof/rp_stack.h +81 -0
- data/ext/ruby_prof/rp_thread.c +312 -0
- data/ext/ruby_prof/rp_thread.h +36 -0
- data/ext/ruby_prof/ruby_prof.c +800 -0
- data/ext/ruby_prof/ruby_prof.h +64 -0
- data/ext/ruby_prof/vc/ruby_prof.sln +32 -0
- data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +108 -0
- data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +110 -0
- data/ext/ruby_prof/vc/ruby_prof_20.vcxproj +110 -0
- data/lib/ruby-prof.rb +63 -0
- data/lib/ruby-prof/aggregate_call_info.rb +76 -0
- data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
- data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
- data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
- data/lib/ruby-prof/assets/flame_graph_printer.lib.css.html +149 -0
- data/lib/ruby-prof/assets/flame_graph_printer.lib.js.html +707 -0
- data/lib/ruby-prof/assets/flame_graph_printer.page.js.html +56 -0
- data/lib/ruby-prof/assets/flame_graph_printer.tmpl.html.erb +39 -0
- data/lib/ruby-prof/call_info.rb +111 -0
- data/lib/ruby-prof/call_info_visitor.rb +40 -0
- data/lib/ruby-prof/compatibility.rb +186 -0
- data/lib/ruby-prof/method_info.rb +109 -0
- data/lib/ruby-prof/printers/abstract_printer.rb +85 -0
- data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
- data/lib/ruby-prof/printers/call_stack_printer.rb +260 -0
- data/lib/ruby-prof/printers/call_tree_printer.rb +130 -0
- data/lib/ruby-prof/printers/dot_printer.rb +132 -0
- data/lib/ruby-prof/printers/fast_call_tree_printer.rb +87 -0
- data/lib/ruby-prof/printers/flame_graph_html_printer.rb +59 -0
- data/lib/ruby-prof/printers/flame_graph_json_printer.rb +157 -0
- data/lib/ruby-prof/printers/flat_printer.rb +70 -0
- data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +64 -0
- data/lib/ruby-prof/printers/graph_html_printer.rb +244 -0
- data/lib/ruby-prof/printers/graph_printer.rb +116 -0
- data/lib/ruby-prof/printers/multi_printer.rb +58 -0
- data/lib/ruby-prof/profile.rb +22 -0
- data/lib/ruby-prof/profile/exclude_common_methods.rb +201 -0
- data/lib/ruby-prof/rack.rb +95 -0
- data/lib/ruby-prof/task.rb +147 -0
- data/lib/ruby-prof/thread.rb +35 -0
- data/lib/ruby-prof/version.rb +4 -0
- data/lib/ruby-prof/walker.rb +95 -0
- data/lib/unprof.rb +10 -0
- data/ruby-prof.gemspec +56 -0
- data/test/aggregate_test.rb +136 -0
- data/test/basic_test.rb +128 -0
- data/test/block_test.rb +74 -0
- data/test/call_info_test.rb +78 -0
- data/test/call_info_visitor_test.rb +31 -0
- data/test/duplicate_names_test.rb +32 -0
- data/test/dynamic_method_test.rb +55 -0
- data/test/enumerable_test.rb +21 -0
- data/test/exceptions_test.rb +16 -0
- data/test/exclude_methods_test.rb +146 -0
- data/test/exclude_threads_test.rb +53 -0
- data/test/fiber_test.rb +79 -0
- data/test/issue137_test.rb +63 -0
- data/test/line_number_test.rb +71 -0
- data/test/measure_allocations_test.rb +26 -0
- data/test/measure_cpu_time_test.rb +213 -0
- data/test/measure_gc_runs_test.rb +32 -0
- data/test/measure_gc_time_test.rb +36 -0
- data/test/measure_memory_test.rb +33 -0
- data/test/measure_process_time_test.rb +63 -0
- data/test/measure_wall_time_test.rb +255 -0
- data/test/module_test.rb +45 -0
- data/test/multi_measure_test.rb +38 -0
- data/test/multi_printer_test.rb +83 -0
- data/test/no_method_class_test.rb +15 -0
- data/test/pause_resume_test.rb +166 -0
- data/test/prime.rb +54 -0
- data/test/printers_test.rb +255 -0
- data/test/printing_recursive_graph_test.rb +127 -0
- data/test/rack_test.rb +93 -0
- data/test/recursive_test.rb +212 -0
- data/test/singleton_test.rb +38 -0
- data/test/stack_printer_test.rb +65 -0
- data/test/stack_test.rb +138 -0
- data/test/start_stop_test.rb +112 -0
- data/test/test_helper.rb +264 -0
- data/test/thread_test.rb +187 -0
- data/test/unique_call_path_test.rb +202 -0
- data/test/yarv_test.rb +55 -0
- metadata +211 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'ruby-prof/profile/exclude_common_methods'
|
4
|
+
module RubyProf
|
5
|
+
class Profile
|
6
|
+
# Hides methods that, when represented as a call graph, have
|
7
|
+
# extremely large in and out degrees and make navigation impossible.
|
8
|
+
def exclude_common_methods!
|
9
|
+
ExcludeCommonMethods.apply!(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def exclude_methods!(mod, *method_or_methods)
|
13
|
+
[method_or_methods].flatten.each do |name|
|
14
|
+
exclude_method!(mod, name)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def exclude_singleton_methods!(mod, *method_or_methods)
|
19
|
+
exclude_methods!(mod.singleton_class, *method_or_methods)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module RubyProf
|
4
|
+
class Profile
|
5
|
+
class ExcludeCommonMethods
|
6
|
+
ENUMERABLE_NAMES = Enumerable.instance_methods(false)
|
7
|
+
|
8
|
+
def self.apply!(profile)
|
9
|
+
new(profile).apply!
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(profile)
|
13
|
+
@profile = profile
|
14
|
+
end
|
15
|
+
|
16
|
+
def apply!
|
17
|
+
##
|
18
|
+
# Kernel Methods
|
19
|
+
##
|
20
|
+
|
21
|
+
exclude_methods Kernel, [
|
22
|
+
:dup,
|
23
|
+
:initialize_dup,
|
24
|
+
:tap,
|
25
|
+
:send,
|
26
|
+
:public_send,
|
27
|
+
]
|
28
|
+
|
29
|
+
##
|
30
|
+
# Fundamental Types
|
31
|
+
##
|
32
|
+
|
33
|
+
exclude_methods BasicObject, :"!="
|
34
|
+
exclude_methods Method, :"[]"
|
35
|
+
exclude_methods Module, :new
|
36
|
+
exclude_methods Class, :new
|
37
|
+
exclude_methods Proc, :call, :yield
|
38
|
+
exclude_methods Range, :each
|
39
|
+
exclude_methods Integer, :times
|
40
|
+
|
41
|
+
##
|
42
|
+
# Value Types
|
43
|
+
##
|
44
|
+
|
45
|
+
exclude_methods String, [
|
46
|
+
:sub,
|
47
|
+
:sub!,
|
48
|
+
:gsub,
|
49
|
+
:gsub!,
|
50
|
+
]
|
51
|
+
|
52
|
+
##
|
53
|
+
# Emumerables
|
54
|
+
##
|
55
|
+
|
56
|
+
exclude_enumerable Enumerable
|
57
|
+
exclude_enumerable Enumerator
|
58
|
+
|
59
|
+
##
|
60
|
+
# Collections
|
61
|
+
##
|
62
|
+
|
63
|
+
exclude_enumerable Array, [
|
64
|
+
:each_index,
|
65
|
+
:map!,
|
66
|
+
:select!,
|
67
|
+
:reject!,
|
68
|
+
:collect!,
|
69
|
+
:sort!,
|
70
|
+
:sort_by!,
|
71
|
+
:index,
|
72
|
+
:delete_if,
|
73
|
+
:keep_if,
|
74
|
+
:drop_while,
|
75
|
+
:uniq,
|
76
|
+
:uniq!,
|
77
|
+
:"==",
|
78
|
+
:eql?,
|
79
|
+
:hash,
|
80
|
+
:to_json,
|
81
|
+
:as_json,
|
82
|
+
:encode_json,
|
83
|
+
]
|
84
|
+
|
85
|
+
exclude_enumerable Hash, [
|
86
|
+
:dup,
|
87
|
+
:initialize_dup,
|
88
|
+
:fetch,
|
89
|
+
:"[]",
|
90
|
+
:"[]=",
|
91
|
+
:each_key,
|
92
|
+
:each_value,
|
93
|
+
:each_pair,
|
94
|
+
:map!,
|
95
|
+
:select!,
|
96
|
+
:reject!,
|
97
|
+
:collect!,
|
98
|
+
:delete_if,
|
99
|
+
:keep_if,
|
100
|
+
:slice,
|
101
|
+
:slice!,
|
102
|
+
:except,
|
103
|
+
:except!,
|
104
|
+
:"==",
|
105
|
+
:eql?,
|
106
|
+
:hash,
|
107
|
+
:to_json,
|
108
|
+
:as_json,
|
109
|
+
:encode_json,
|
110
|
+
]
|
111
|
+
|
112
|
+
exclude_enumerable Set, [
|
113
|
+
:map!,
|
114
|
+
:select!,
|
115
|
+
:reject!,
|
116
|
+
:collect!,
|
117
|
+
:classify,
|
118
|
+
:delete_if,
|
119
|
+
:keep_if,
|
120
|
+
:divide,
|
121
|
+
:"==",
|
122
|
+
:eql?,
|
123
|
+
:hash,
|
124
|
+
:to_json,
|
125
|
+
:as_json,
|
126
|
+
:encode_json,
|
127
|
+
]
|
128
|
+
|
129
|
+
##
|
130
|
+
# Garbage Collection
|
131
|
+
##
|
132
|
+
|
133
|
+
exclude_singleton_methods GC, [
|
134
|
+
:start
|
135
|
+
]
|
136
|
+
|
137
|
+
##
|
138
|
+
# Unicorn
|
139
|
+
##
|
140
|
+
|
141
|
+
if defined?(Unicorn)
|
142
|
+
exclude_methods Unicorn::HttpServer, :process_client
|
143
|
+
end
|
144
|
+
|
145
|
+
if defined?(Unicorn::OobGC)
|
146
|
+
exclude_methods Unicorn::OobGC, :process_client
|
147
|
+
end
|
148
|
+
|
149
|
+
##
|
150
|
+
# New Relic
|
151
|
+
##
|
152
|
+
|
153
|
+
if defined?(NewRelic)
|
154
|
+
exclude_methods NewRelic::Agent::Instrumentation::MiddlewareTracing, [
|
155
|
+
:call
|
156
|
+
]
|
157
|
+
|
158
|
+
exclude_methods NewRelic::Agent::MethodTracerHelpers, [
|
159
|
+
:trace_execution_scoped,
|
160
|
+
:log_errors,
|
161
|
+
]
|
162
|
+
|
163
|
+
exclude_singleton_methods NewRelic::Agent::MethodTracerHelpers, [
|
164
|
+
:trace_execution_scoped,
|
165
|
+
:log_errors,
|
166
|
+
]
|
167
|
+
|
168
|
+
exclude_methods NewRelic::Agent::MethodTracer, [
|
169
|
+
:trace_execution_scoped,
|
170
|
+
:trace_execution_unscoped,
|
171
|
+
]
|
172
|
+
end
|
173
|
+
|
174
|
+
##
|
175
|
+
# Miscellaneous Methods
|
176
|
+
##
|
177
|
+
|
178
|
+
if defined?(Mustache)
|
179
|
+
exclude_methods Mustache::Context, [
|
180
|
+
:fetch
|
181
|
+
]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
def exclude_methods(mod, *method_or_methods)
|
188
|
+
@profile.exclude_methods!(mod, method_or_methods)
|
189
|
+
end
|
190
|
+
|
191
|
+
def exclude_singleton_methods(mod, *method_or_methods)
|
192
|
+
@profile.exclude_singleton_methods!(mod, method_or_methods)
|
193
|
+
end
|
194
|
+
|
195
|
+
def exclude_enumerable(mod, *method_or_methods)
|
196
|
+
exclude_methods(mod, [:each, *method_or_methods])
|
197
|
+
exclude_methods(mod, ENUMERABLE_NAMES)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
class RubyProf
|
6
|
+
def initialize(app, options = {})
|
7
|
+
@app = app
|
8
|
+
@options = options
|
9
|
+
@options[:min_percent] ||= 1
|
10
|
+
|
11
|
+
@tmpdir = options[:path] || Dir.tmpdir
|
12
|
+
FileUtils.mkdir_p(@tmpdir)
|
13
|
+
|
14
|
+
@printer_klasses = @options[:printers] || {::RubyProf::FlatPrinter => 'flat.txt',
|
15
|
+
::RubyProf::GraphPrinter => 'graph.txt',
|
16
|
+
::RubyProf::GraphHtmlPrinter => 'graph.html',
|
17
|
+
::RubyProf::CallStackPrinter => 'call_stack.html'}
|
18
|
+
|
19
|
+
@skip_paths = options[:skip_paths] || [%r{^/assets}, %r{\.(css|js|png|jpeg|jpg|gif)$}]
|
20
|
+
@only_paths = options[:only_paths]
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(env)
|
24
|
+
request = Rack::Request.new(env)
|
25
|
+
|
26
|
+
if should_profile?(request.path)
|
27
|
+
begin
|
28
|
+
result = nil
|
29
|
+
data = ::RubyProf::Profile.profile(profiling_options) do
|
30
|
+
result = @app.call(env)
|
31
|
+
end
|
32
|
+
|
33
|
+
path = request.path.gsub('/', '-')
|
34
|
+
path.slice!(0)
|
35
|
+
|
36
|
+
print(data, path)
|
37
|
+
result
|
38
|
+
end
|
39
|
+
else
|
40
|
+
@app.call(env)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def should_profile?(path)
|
47
|
+
return false if paths_match?(path, @skip_paths)
|
48
|
+
|
49
|
+
@only_paths ? paths_match?(path, @only_paths) : true
|
50
|
+
end
|
51
|
+
|
52
|
+
def paths_match?(path, paths)
|
53
|
+
paths.any? { |skip_path| skip_path =~ path }
|
54
|
+
end
|
55
|
+
|
56
|
+
def profiling_options
|
57
|
+
options = {}
|
58
|
+
options[:measure_modes] = [::RubyProf.measure_mode]
|
59
|
+
options[:exclude_threads] =
|
60
|
+
if @options[:ignore_existing_threads]
|
61
|
+
Thread.list.select{|t| t != Thread.current}
|
62
|
+
else
|
63
|
+
::RubyProf.exclude_threads
|
64
|
+
end
|
65
|
+
if @options[:request_thread_only]
|
66
|
+
options[:include_threads] = [Thread.current]
|
67
|
+
end
|
68
|
+
if @options[:merge_fibers]
|
69
|
+
options[:merge_fibers] = true
|
70
|
+
end
|
71
|
+
options
|
72
|
+
end
|
73
|
+
|
74
|
+
def print(data, path)
|
75
|
+
@printer_klasses.each do |printer_klass, base_name|
|
76
|
+
printer = printer_klass.new(data)
|
77
|
+
|
78
|
+
if base_name.respond_to?(:call)
|
79
|
+
base_name = base_name.call
|
80
|
+
end
|
81
|
+
|
82
|
+
if printer_klass == ::RubyProf::MultiPrinter
|
83
|
+
printer.print(@options.merge(:profile => "#{path}-#{base_name}"))
|
84
|
+
elsif printer_klass == ::RubyProf::CallTreePrinter
|
85
|
+
printer.print(@options.merge(:profile => "#{path}-#{base_name}"))
|
86
|
+
else
|
87
|
+
file_name = ::File.join(@tmpdir, "#{path}-#{base_name}")
|
88
|
+
::File.open(file_name, 'wb') do |file|
|
89
|
+
printer.print(file, @options)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module RubyProf
|
9
|
+
|
10
|
+
# Define a task library for profiling unit tests with ruby-prof.
|
11
|
+
#
|
12
|
+
# All of the options provided by
|
13
|
+
# the Rake:TestTask are supported except the loader
|
14
|
+
# which is set to ruby-prof. For detailed information
|
15
|
+
# please refer to the Rake:TestTask documentation.
|
16
|
+
#
|
17
|
+
# ruby-prof specific options include:
|
18
|
+
#
|
19
|
+
# output_dir - For each file specified an output
|
20
|
+
# file with profile information will be
|
21
|
+
# written to the output directory.
|
22
|
+
# By default, the output directory is
|
23
|
+
# called "profile" and is created underneath
|
24
|
+
# the current working directory.
|
25
|
+
#
|
26
|
+
# printer - Specifies the output printer. Valid values include
|
27
|
+
# :flat, :graph, :graph_html and :call_tree.
|
28
|
+
#
|
29
|
+
# min_percent - Methods that take less than the specified percent
|
30
|
+
# will not be written out.
|
31
|
+
#
|
32
|
+
# Example:
|
33
|
+
#
|
34
|
+
# require 'ruby-prof/task'
|
35
|
+
#
|
36
|
+
# RubyProf::ProfileTask.new do |t|
|
37
|
+
# t.test_files = FileList['test/test*.rb']
|
38
|
+
# t.output_dir = "c:/temp"
|
39
|
+
# t.printer = :graph
|
40
|
+
# t.min_percent = 10
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# If rake is invoked with a "TEST=filename" command line option,
|
44
|
+
# then the list of test files will be overridden to include only the
|
45
|
+
# filename specified on the command line. This provides an easy way
|
46
|
+
# to run just one test.
|
47
|
+
#
|
48
|
+
# If rake is invoked with a "TESTOPTS=options" command line option,
|
49
|
+
# then the given options are passed to the test process after a
|
50
|
+
# '--'. This allows Test::Unit options to be passed to the test
|
51
|
+
# suite.
|
52
|
+
#
|
53
|
+
# Examples:
|
54
|
+
#
|
55
|
+
# rake profile # run tests normally
|
56
|
+
# rake profile TEST=just_one_file.rb # run just one test file.
|
57
|
+
# rake profile TESTOPTS="-v" # run in verbose mode
|
58
|
+
# rake profile TESTOPTS="--runner=fox" # use the fox test runner
|
59
|
+
|
60
|
+
class ProfileTask < Rake::TestTask
|
61
|
+
attr_accessor :output_dir
|
62
|
+
attr_accessor :min_percent
|
63
|
+
attr_accessor :printer
|
64
|
+
|
65
|
+
def initialize(name = :profile)
|
66
|
+
super(name)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Create the tasks defined by this task lib.
|
70
|
+
def define
|
71
|
+
lib_path = @libs.join(File::PATH_SEPARATOR)
|
72
|
+
desc "Profile" + (@name==:profile ? "" : " for #{@name}")
|
73
|
+
|
74
|
+
task @name do
|
75
|
+
create_output_directory
|
76
|
+
|
77
|
+
@ruby_opts.unshift( "-I#{lib_path}" )
|
78
|
+
@ruby_opts.unshift( "-w" ) if @warning
|
79
|
+
@ruby_opts.push("-S ruby-prof")
|
80
|
+
@ruby_opts.push("--printer #{@printer}")
|
81
|
+
@ruby_opts.push("--min_percent #{@min_percent}")
|
82
|
+
|
83
|
+
file_list.each do |file_path|
|
84
|
+
run_script(file_path)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
# Run script
|
91
|
+
def run_script(script_path)
|
92
|
+
run_code = ''
|
93
|
+
RakeFileUtils.verbose(@verbose) do
|
94
|
+
file_name = File.basename(script_path, File.extname(script_path))
|
95
|
+
case @printer
|
96
|
+
when :flat, :graph, :call_tree
|
97
|
+
file_name += ".txt"
|
98
|
+
when :graph_html
|
99
|
+
file_name += ".html"
|
100
|
+
else
|
101
|
+
file_name += ".txt"
|
102
|
+
end
|
103
|
+
|
104
|
+
output_file_path = File.join(output_directory, file_name)
|
105
|
+
|
106
|
+
command_line = @ruby_opts.join(" ") +
|
107
|
+
" --file=" + output_file_path +
|
108
|
+
" " + script_path
|
109
|
+
|
110
|
+
puts "ruby " + command_line
|
111
|
+
# We have to catch the exeption to continue on. However,
|
112
|
+
# the error message will have been output to STDERR
|
113
|
+
# already by the time we get here so we don't have to
|
114
|
+
# do that again
|
115
|
+
begin
|
116
|
+
ruby command_line
|
117
|
+
rescue => e
|
118
|
+
STDOUT << e << "\n"
|
119
|
+
STDOUT.flush
|
120
|
+
end
|
121
|
+
puts ""
|
122
|
+
puts ""
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def output_directory
|
127
|
+
File.expand_path(@output_dir)
|
128
|
+
end
|
129
|
+
|
130
|
+
def create_output_directory
|
131
|
+
if not File.exist?(output_directory)
|
132
|
+
Dir.mkdir(output_directory)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def clean_output_directory
|
137
|
+
if File.exist?(output_directory)
|
138
|
+
files = Dir.glob(output_directory + '/*')
|
139
|
+
FileUtils.rm(files)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def option_list # :nodoc:
|
144
|
+
ENV['OPTIONS'] || @options.join(" ") || ""
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|