piggly 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +163 -0
  3. data/Rakefile +29 -15
  4. data/bin/piggly +4 -244
  5. data/lib/piggly.rb +19 -17
  6. data/lib/piggly/command.rb +9 -0
  7. data/lib/piggly/command/base.rb +148 -0
  8. data/lib/piggly/command/report.rb +162 -0
  9. data/lib/piggly/command/test.rb +157 -0
  10. data/lib/piggly/command/trace.rb +90 -0
  11. data/lib/piggly/command/untrace.rb +78 -0
  12. data/lib/piggly/compiler.rb +7 -5
  13. data/lib/piggly/compiler/cache_dir.rb +119 -0
  14. data/lib/piggly/compiler/coverage_report.rb +63 -0
  15. data/lib/piggly/compiler/trace_compiler.rb +105 -0
  16. data/lib/piggly/config.rb +47 -22
  17. data/lib/piggly/dumper.rb +9 -0
  18. data/lib/piggly/dumper/index.rb +121 -0
  19. data/lib/piggly/dumper/qualified_name.rb +36 -0
  20. data/lib/piggly/dumper/qualified_type.rb +81 -0
  21. data/lib/piggly/dumper/reified_procedure.rb +142 -0
  22. data/lib/piggly/dumper/skeleton_procedure.rb +102 -0
  23. data/lib/piggly/installer.rb +84 -42
  24. data/lib/piggly/parser.rb +43 -49
  25. data/lib/piggly/parser/grammar.tt +289 -313
  26. data/lib/piggly/parser/nodes.rb +270 -211
  27. data/lib/piggly/parser/traversal.rb +35 -33
  28. data/lib/piggly/parser/treetop_ruby19_patch.rb +1 -1
  29. data/lib/piggly/profile.rb +81 -60
  30. data/lib/piggly/reporter.rb +5 -18
  31. data/lib/piggly/reporter/base.rb +103 -0
  32. data/lib/piggly/reporter/html_dsl.rb +63 -0
  33. data/lib/piggly/reporter/index.rb +108 -0
  34. data/lib/piggly/reporter/procedure.rb +104 -0
  35. data/lib/piggly/reporter/resources/highlight.js +21 -0
  36. data/lib/piggly/reporter/{piggly.css → resources/piggly.css} +52 -12
  37. data/lib/piggly/reporter/{sortable.js → resources/sortable.js} +0 -0
  38. data/lib/piggly/tags.rb +280 -0
  39. data/lib/piggly/task.rb +191 -40
  40. data/lib/piggly/util.rb +8 -27
  41. data/lib/piggly/util/blankslate.rb +114 -0
  42. data/lib/piggly/util/cacheable.rb +19 -0
  43. data/lib/piggly/util/enumerable.rb +44 -0
  44. data/lib/piggly/util/file.rb +17 -0
  45. data/lib/piggly/util/process_queue.rb +96 -0
  46. data/lib/piggly/util/thunk.rb +39 -0
  47. data/lib/piggly/version.rb +8 -8
  48. data/spec/examples/compiler/cacheable_spec.rb +190 -0
  49. data/spec/examples/compiler/report_spec.rb +25 -0
  50. data/spec/{compiler → examples/compiler}/trace_spec.rb +7 -57
  51. data/spec/examples/config_spec.rb +61 -0
  52. data/spec/examples/dumper/index_spec.rb +197 -0
  53. data/spec/examples/dumper/procedure_spec.rb +116 -0
  54. data/spec/{grammar → examples/grammar}/expression_spec.rb +60 -60
  55. data/spec/{grammar → examples/grammar}/statements/assignment_spec.rb +15 -15
  56. data/spec/examples/grammar/statements/declaration_spec.rb +21 -0
  57. data/spec/{grammar → examples/grammar}/statements/exception_spec.rb +10 -10
  58. data/spec/{grammar → examples/grammar}/statements/if_spec.rb +47 -34
  59. data/spec/{grammar → examples/grammar}/statements/loop_spec.rb +5 -5
  60. data/spec/{grammar → examples/grammar}/statements/sql_spec.rb +11 -11
  61. data/spec/{grammar → examples/grammar}/tokens/comment_spec.rb +11 -11
  62. data/spec/{grammar → examples/grammar}/tokens/datatype_spec.rb +14 -8
  63. data/spec/{grammar → examples/grammar}/tokens/identifier_spec.rb +26 -10
  64. data/spec/{grammar → examples/grammar}/tokens/keyword_spec.rb +5 -5
  65. data/spec/{grammar → examples/grammar}/tokens/label_spec.rb +7 -7
  66. data/spec/{grammar → examples/grammar}/tokens/literal_spec.rb +1 -1
  67. data/spec/examples/grammar/tokens/lval_spec.rb +50 -0
  68. data/spec/{grammar → examples/grammar}/tokens/number_spec.rb +1 -1
  69. data/spec/{grammar → examples/grammar}/tokens/sqlkeywords_spec.rb +1 -1
  70. data/spec/{grammar → examples/grammar}/tokens/string_spec.rb +9 -9
  71. data/spec/{grammar → examples/grammar}/tokens/whitespace_spec.rb +1 -1
  72. data/spec/examples/installer_spec.rb +59 -0
  73. data/spec/examples/parser/nodes_spec.rb +73 -0
  74. data/spec/examples/parser/traversal_spec.rb +14 -0
  75. data/spec/examples/parser_spec.rb +115 -0
  76. data/spec/examples/profile_spec.rb +153 -0
  77. data/spec/{reporter/html_spec.rb → examples/reporter/html/dsl_spec.rb} +0 -0
  78. data/spec/examples/reporter/html/index_spec.rb +0 -0
  79. data/spec/examples/reporter/html_spec.rb +1 -0
  80. data/spec/examples/reporter_spec.rb +0 -0
  81. data/spec/{compiler → examples}/tags_spec.rb +10 -10
  82. data/spec/examples/task_spec.rb +0 -0
  83. data/spec/examples/util/cacheable_spec.rb +41 -0
  84. data/spec/examples/util/enumerable_spec.rb +64 -0
  85. data/spec/examples/util/file_spec.rb +40 -0
  86. data/spec/examples/util/process_queue_spec.rb +16 -0
  87. data/spec/examples/util/thunk_spec.rb +58 -0
  88. data/spec/examples/version_spec.rb +0 -0
  89. data/spec/issues/007_spec.rb +25 -0
  90. data/spec/issues/008_spec.rb +73 -0
  91. data/spec/issues/018_spec.rb +25 -0
  92. data/spec/spec_helper.rb +253 -9
  93. metadata +136 -93
  94. data/README.markdown +0 -116
  95. data/lib/piggly/compiler/cache.rb +0 -151
  96. data/lib/piggly/compiler/pretty.rb +0 -67
  97. data/lib/piggly/compiler/queue.rb +0 -46
  98. data/lib/piggly/compiler/tags.rb +0 -244
  99. data/lib/piggly/compiler/trace.rb +0 -91
  100. data/lib/piggly/filecache.rb +0 -40
  101. data/lib/piggly/parser/parser.rb +0 -11794
  102. data/lib/piggly/reporter/html.rb +0 -207
  103. data/spec/compiler/cache_spec.rb +0 -9
  104. data/spec/compiler/pretty_spec.rb +0 -9
  105. data/spec/compiler/queue_spec.rb +0 -3
  106. data/spec/compiler/rewrite_spec.rb +0 -3
  107. data/spec/config_spec.rb +0 -58
  108. data/spec/filecache_spec.rb +0 -70
  109. data/spec/fixtures/snippets.sql +0 -158
  110. data/spec/grammar/tokens/lval_spec.rb +0 -50
  111. data/spec/parser_spec.rb +0 -8
  112. data/spec/profile_spec.rb +0 -5
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6bc3e3b06dfb2ce02fc63e702216f7144165c2a0
4
+ data.tar.gz: 15a2d1da931923920ffce34f726096c3f31e8492
5
+ SHA512:
6
+ metadata.gz: 8409f7c8adde74c01dfaeb3dcf0e1a6df10b5e8d7552701d38586f938d47e9727457c34a3b2a539f1ad54ceb4e5450909bddfc3f4b43485a2094fd9dc045f97c
7
+ data.tar.gz: b4d409e5ab4f45112f27444720fa56ce6e034e8c9244c466a2f249fcf0cb3032269287ca8eb48927c01245e7e1e62bf42a0b15a32f3df408ed3278a962eeb1dc
@@ -0,0 +1,163 @@
1
+ # Piggly
2
+
3
+ PostgreSQL PL/pgSQL stored procedure code coverage [![Build Status](https://secure.travis-ci.org/kputnam/piggly.png)](http://travis-ci.org/kputnam/piggly)
4
+
5
+ ![Screenshot](http://kputnam.github.com/piggly/images/example.png)
6
+
7
+ ## Purpose
8
+
9
+ PL/pgSQL doesn't have much in the way of developer tools, and writing automated tests for
10
+ stored procedures can be much easier when you know what you haven't tested. Code coverage
11
+ allows you to see which parts of your code haven't been executed.
12
+
13
+ Piggly is a tool (written in Ruby, but you can write your tests in any language) to track
14
+ code coverage of PostgreSQL PL/pgSQL stored procedures. It reports on code coverage to help
15
+ you identify untested parts of your code.
16
+
17
+ ## How Does It Work?
18
+
19
+ Piggly tracks the execution of PostgreSQL's PL/pgSQL stored procedures by recompiling
20
+ the stored procedure with instrumentation code. Basically, RAISE WARNING statements notify the
21
+ client of an execution event (e.g., a branch condition evaluating to true or false). It records
22
+ these events and generates prettified source code that is annotated with coverage details.
23
+
24
+ ## Features
25
+
26
+ * Readable and easily-navigable reports (see [example] [5])
27
+ * Language agnostic - write your tests in Ruby, Python, Java, SQL scripts etc
28
+ * Branch, block, and loop coverage analysis
29
+ * Instrumenting source-to-source compiler
30
+ * Low test execution overhead
31
+ * Reduced compilation times by use of disk caching
32
+ * Possible to aggregate coverage across multiple runs
33
+
34
+ ## Limitations
35
+
36
+ * Not all PL/pgSQL grammar is currently supported, but the grammar is easy to modify
37
+ * Cannot parse nested dollar-quoted strings, eg $A$ ... $B$ ... $B$ ... $A$
38
+ * SQL statements are not instrumented, so their branches (COALESCE, WHERE-clauses, etc) aren't tracked
39
+
40
+ ## Requirements
41
+
42
+ * [Treetop] [2]: `gem install treetop`
43
+ * The [ruby-pg driver] [3]: `gem install pg`
44
+ * The examples require ActiveRecord: `gem install activerecord`
45
+
46
+ ## How to Install
47
+
48
+ To install the latest from github:
49
+
50
+ $ git clone git://github.com/kputnam/piggly.git
51
+ $ cd piggly
52
+ $ bundle install
53
+ $ bundle exec rake spec
54
+
55
+ $ rake gem
56
+ $ gem install pkg/*.gem --no-rdoc --no-ri
57
+
58
+ To install the latest release:
59
+
60
+ $ gem install piggly
61
+
62
+ ## Usage
63
+
64
+ Your stored procedures must already be loaded in the database. Configure your database connection in
65
+ a file named `config/database.yml` relative to where you want to run piggly. You can also specify the
66
+ `-d PATH` to an existing configuration file. The contents of the file follow ActiveRecord conventions:
67
+
68
+ piggly:
69
+ adapter: postgresql
70
+ database: cookbook
71
+ username: kputnam
72
+ password: secret
73
+ host: localhost
74
+
75
+ Here we'll add some stored procedures to the database we described above:
76
+
77
+ $ cat example/proc/*.sql | psql -U kputnam -h localhost cookbook
78
+
79
+ Note the connection is expected to be named `piggly` but you may specify the `-k DATABASE` option to
80
+ use a different connection name (eg `-k development` in Rails). See also `example/config/database.yml`.
81
+
82
+ Now you are ready to recompile and install your stored procedures. This reads the configuration from
83
+ `./config/database.yml` relative to the current working directory.
84
+
85
+ $ piggly trace
86
+ compiling 5 procedures
87
+ Compiling scramble
88
+ Compiling scramble
89
+ Compiling numberedargs
90
+ Compiling snippets
91
+ Compiling iterate
92
+ tracing 5 procedures
93
+
94
+ This caches the original version (without instrumentation) in `piggly/cache` so you can restore them
95
+ later. Piggly will only recompile procedures that have changed in the database since it last
96
+ made a copy in `piggly/cache`.
97
+
98
+ *WARNING*: piggly fetches your code from the database and replaces it (in the database) with the
99
+ instrumented code. If you run `piggly trace` twice consecutively, the second time will cause an error
100
+ because you are trying to re-instrument code that has already been instrumented. You need to run
101
+ `piggly untrace` or restore your original stored procedures manually before you can trace them again.
102
+
103
+ Now you're ready to execute your tests. Make sure your connection is configured to log `RAISE WARNING`
104
+ messages to a file -- or you can log them to `STDERR` and redirect that to a file. For instance you
105
+ might run:
106
+
107
+ $ ant test 2> messages.txt
108
+ $ make test 2> messages.txt
109
+ etc.
110
+
111
+ To build the coverage report, have piggly read that file in by executing `piggly report < messages.txt`,
112
+ or `piggly report -f messages.txt`. You don't actually need the intermediate file, you can pipe your
113
+ test suite directly in like `ant test 2>&1 | piggly report`.
114
+
115
+ Once the report is built you can open it in `piggly/reports/index.html`.
116
+
117
+ ## Running the Examples
118
+
119
+ $ cd piggly
120
+ $ bundle install
121
+ $ cat example/README
122
+ ...
123
+
124
+ $ ./example/run-tests
125
+ compiling 5 procedures
126
+ Compiling scramble
127
+ Compiling scramble
128
+ Compiling numberedargs
129
+ Compiling snippets
130
+ Compiling iterate
131
+ tracing 5 procedures
132
+ Loaded suite /home/kputnam/wd/piggly/example/test/iterate_test
133
+ Started
134
+ ......
135
+ Finished in 0.199236 seconds.
136
+
137
+ 6 tests, 6 assertions, 0 failures, 0 errors, 0 skips
138
+
139
+ Test run options: --seed 25290
140
+ clearing previous coverage
141
+ storing coverage profile
142
+ creating index
143
+ creating reports
144
+ reporting coverage for scramble
145
+ reporting coverage for scramble
146
+ reporting coverage for numberedargs
147
+ reporting coverage for snippets
148
+ reporting coverage for iterate: +0.0% block, +0.0% branch, +0.0% loop
149
+ restoring 5 procedures
150
+ OK, view /home/kputnam/wd/piggly/example/piggly/reports/index.html
151
+
152
+ $ ls -alh example/reports/index.html
153
+ -rw-r--r-- 1 kputnam kputnam 1.4K 2010-04-28 11:21 example/reports/index.html
154
+
155
+ ## Bugs & Issues
156
+
157
+ Please report any issues or feature requests on the [github tracker] [4].
158
+
159
+ [1]: http://github.com/relevance/rcov/
160
+ [2]: http://github.com/nathansobo/treetop
161
+ [3]: http://bitbucket.org/ged/ruby-pg/
162
+ [4]: http://github.com/kputnam/piggly/issues
163
+ [5]: http://kputnam.github.com/piggly/reports/index.html
data/Rakefile CHANGED
@@ -1,19 +1,33 @@
1
- dir = File.dirname(__FILE__)
2
- require 'rubygems'
3
- require 'rake'
4
-
5
1
  begin
6
- require 'spec/rake/spectask'
7
- Spec::Rake::SpecTask.new do |t|
8
- t.pattern = 'spec/**/*_spec.rb'
9
- end
10
- task :default => :spec
11
- rescue Exception
2
+ require "rubygems"
3
+ require "bundler/setup"
4
+ rescue LoadError
5
+ warn "couldn't load bundler:"
6
+ warn " #{$!}"
12
7
  end
13
8
 
14
- require 'rake/gempackagetask'
15
- load './piggly.gemspec'
16
- Rake::GemPackageTask.new(Piggly.gemspec) do |pkg|
17
- pkg.need_tar = false
18
- pkg.need_zip = false
9
+ begin # rspec-2
10
+ require "rspec/core/rake_task"
11
+ RSpec::Core::RakeTask.new do |t|
12
+ t.verbose = false
13
+ t.pattern = "spec/**/*_spec.rb"
14
+ t.rspec_opts = "--color --format=p"
15
+ end
16
+ rescue LoadError => first
17
+ begin # rspec-1
18
+ require "spec/rake/spectask"
19
+ Spec::Rake::SpecTask.new do |t|
20
+ t.pattern = "spec/**/*_spec.rb"
21
+ t.spec_opts << "--color"
22
+ t.spec_opts << "--format=p"
23
+ end
24
+ rescue LoadError => second
25
+ task :spec do
26
+ warn "couldn't load rspec version 1 or 2:"
27
+ warn " #{first}"
28
+ warn " #{second}"
29
+ end
30
+ end
19
31
  end
32
+
33
+ task :default => :spec
data/bin/piggly CHANGED
@@ -1,248 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
- require 'optparse'
3
- require 'rubygems'
4
- $:.push File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
5
- require 'piggly'
2
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), *%w(.. lib)))
3
+ require "piggly"
6
4
 
7
5
  # Number of children to fork for parallel tasks
8
- Piggly::Queue.children = 2
6
+ Piggly::Util::ProcessQueue.concurrent = 2
9
7
 
10
- STDOUT.sync = true
11
-
12
- module Piggly
13
- module Command
14
- class << self
15
-
16
- def main
17
- benchmark do
18
- sources, tests = parse_options
19
- load_tests(tests)
20
- connect_to_database
21
- compile_procs(sources)
22
- install_procs(sources)
23
- clear_coverage
24
- execute_tests
25
- store_coverage
26
- uninstall_procs(sources)
27
- create_index(sources)
28
- create_reports(sources)
29
- exit! 0 # avoid running tests again
30
- end
31
- end
32
-
33
- private
34
-
35
- def benchmark
36
- start = Time.now
37
- yield
38
- puts " > Completed in #{'%0.2f' % (Time.now - start)} seconds"
39
- end
40
-
41
- def parse_options
42
- proc_paths = []
43
-
44
- opts = OptionParser.new do |opts|
45
- opts.on("-I", "--include PATHS", "Prepend paths to $: (colon separated list)") do |paths|
46
- $:.concat paths.split(':')
47
- end
48
-
49
- opts.on("-o", "--output PATH", "Report output directory") do |dir|
50
- Piggly::Config.report_root = dir
51
- end
52
-
53
- opts.on("-c", "--cache-root PATH", "Compiler cache directory") do |dir|
54
- Piggly::Config.cache_root = dir
55
- end
56
-
57
- opts.on("-s", "--proc-files PATH", "Stored procedures file list (may be specified many times)") do |dir|
58
- proc_paths << dir
59
- end
60
-
61
- # opts.on("-T", "--trace-prefix PATH", "Trace prefix") do |str|
62
- # Piggly::Config.trace_prefix = str
63
- # end
64
-
65
- opts.on("-a", "--aggregate", "Aggregate data from the previous run") do
66
- Piggly::Config.aggregate = true
67
- end
68
-
69
- opts.on("--version", "Show version") do
70
- puts "piggly #{Piggly::VERSION::STRING} #{Piggly::VERSION::RELEASE_DATE}"
71
- exit
72
- end
73
-
74
- opts.on("-h", "--help", "Show this message") do
75
- puts opts
76
- exit 0
77
- end
78
- end
79
-
80
- if index = ARGV.index('--')
81
- extra = ARGV.slice!(index..-1).slice(1..-1)
82
- else
83
- extra = []
84
- end
85
-
86
- begin
87
- opts.parse! ARGV
88
- raise OptionParser::MissingArgument, "no tests specified" if ARGV.empty?
89
- rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument
90
- puts opts
91
- puts
92
- puts $!.message
93
- exit -1
94
- end
95
-
96
- proc_paths = proc_paths.map{|p| Dir[p] }.flatten.sort
97
- test_paths = ARGV.map{|p| Dir[p] }.flatten.sort
98
-
99
- ARGV.clear
100
-
101
- return proc_paths, test_paths
102
- end
103
-
104
- def load_tests(tests)
105
- puts "Loading #{tests.size} test files"
106
-
107
- benchmark { tests.each{|file| load file } }
108
-
109
- # # TODO: this doesn't seem right, but workaround RSpec executing each spec twice
110
- # if defined? Spec::Runner::ExampleGroupRunner
111
- # Spec::Runner::ExampleGroupRunner.send(:define_method, :load_files) do |*args|
112
- # # don't do anything, we already loaded the files
113
- # end
114
- # end
115
- end
116
-
117
- def connect_to_database
118
- ActiveRecord::Base.connection.active?
119
- rescue
120
- ActiveRecord::Base.establish_connection
121
- end
122
-
123
- def compile_procs(sources)
124
- stale = sources.select{|f| Piggly::TraceCompiler.stale?(f) }
125
-
126
- # build the parser if needed
127
- Piggly::Parser.parser
128
-
129
- puts "Compiling #{stale.size} files"
130
- benchmark do
131
- stale.each do |file|
132
- Piggly::Queue.child do
133
- begin
134
- Piggly::TraceCompiler.cache(file)
135
- # rescue Errno::ENOENT, Piggly::Parser::Failure
136
- # puts "! #{File.basename file}"
137
- rescue
138
- puts
139
- puts "#{$!.class}: #{$!.message}"
140
- puts $!.backtrace.join("\n")
141
- end
142
- end
143
- end
144
- Piggly::Queue.start
145
- end
146
- end
147
-
148
- def install_procs(sources)
149
- puts "Installing #{sources.size} proc files"
150
-
151
- benchmark do
152
- sources.each do |file|
153
- begin
154
- Piggly::Installer.trace_proc(file)
155
- rescue Errno::ENOENT, Piggly::Parser::Failure
156
- # puts "! #{File.basename file}"
157
- rescue
158
- puts
159
- puts "#{$!.class}: #{$!.message}"
160
- puts $!.backtrace.join("\n")
161
- end
162
- end
163
-
164
- Piggly::Installer.install_trace
165
- end
166
- end
167
-
168
- def clear_coverage
169
- unless Piggly::Config.aggregate
170
- puts "Clearing previous run's profile"
171
- benchmark { Piggly::Profile.clear }
172
- end
173
- end
174
-
175
- def execute_tests
176
- if defined? Test::Unit::AutoRunner
177
- Test::Unit::AutoRunner.run
178
- elsif defined? Spec::Runner
179
- Spec::Runner.run
180
- else
181
- raise "Neither RSpec nor Test::Unit were detected"
182
- end
183
- end
184
-
185
- def store_coverage
186
- puts "Storing coverage profile"
187
- benchmark { Piggly::Profile.store }
188
- end
189
-
190
- def uninstall_procs(sources)
191
- puts "Removing trace code"
192
- benchmark do
193
- sources.each do |file|
194
- begin
195
- Piggly::Installer.untrace_proc(file)
196
- rescue Errno::ENOENT, Piggly::Parser::Failure
197
- # puts "! #{File.basename file}"
198
- rescue
199
- puts
200
- puts "#{$!.class}: #{$!.message}"
201
- puts $!.backtrace.join("\n")
202
- end
203
- end
204
-
205
- Piggly::Installer.uninstall_trace
206
- end
207
- end
208
-
209
- def create_index(sources)
210
- puts "Creating index"
211
- benchmark do
212
- Piggly::Reporter.install('piggly.css', 'sortable.js')
213
- Piggly::HtmlReporter::Index.output(sources)
214
- end
215
- end
216
-
217
- def create_reports(sources)
218
- puts "Creating reports"
219
- summary = Hash.new{|h,k| h[k] = Hash.new[:count => 0, :percent => 0]}
220
-
221
- benchmark do
222
- sources.each do |file|
223
- Piggly::Queue.child do
224
- begin
225
- summary = Piggly::Profile.summary(file)
226
- pretty = Piggly::PrettyCompiler.compile(file, Piggly::Profile)
227
-
228
- Piggly::HtmlReporter.output(file, pretty, summary)
229
- rescue Errno::ENOENT, Piggly::Parser::Failure
230
- # puts "! #{File.basename file}"
231
- rescue
232
- puts "#{$!.class}: #{$!.message}"
233
- puts $!.backtrace.join("\n")
234
- end
235
- end
236
- end
237
-
238
- Piggly::Queue.start
239
- end
240
- end
241
-
242
- end
243
- end
244
- end
245
-
246
- if __FILE__ == $0
247
- Piggly::Command.main
248
- end
8
+ Piggly::Command::Base.main(ARGV)