Permalink
Browse files

Makes thor tasks work when piped to `head`

`head` closes the pipe when it's done with the
input, which causes future attempts to write to
STDOUT (via puts, for example) to raise an EPIPE
error.

If an EPIPE error occurs, assume this has happened
and silently exit.
  • Loading branch information...
1 parent 2b97fc0 commit 5d1f449521f0168481a7ee2a8bf09631fc7cb22d tomhuda committed Apr 29, 2012
Showing with 26 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +6 −0 lib/thor/base.rb
  3. +19 −0 spec/exit_condition_spec.rb
View
1 .gitignore
@@ -41,3 +41,4 @@ tmp
tmtags
tramp
.rbx
+b/
View
6 lib/thor/base.rb
@@ -409,6 +409,12 @@ def start(given_args=ARGV, config={})
rescue Thor::Error => e
ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
exit(1) if exit_on_failure?
+ rescue Errno::EPIPE
+ # This happens if a thor task is piped to something like `head`,
+ # which closes the pipe when it's done reading. This will also
+ # mean that if the pipe is closed, further unnecessary
+ # computation will not occur.
+ exit(0)
end
# Allows to use private methods from parent in child classes as tasks.
View
19 spec/exit_condition_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+require 'thor/base'
+
+describe "Exit conditions" do
+ it "should exit 0, not bubble up EPIPE, if EPIPE is raised" do
+ epiped = false
+
+ task = Class.new(Thor) do
+ desc "my_action", "testing EPIPE"
+ define_method :my_action do
+ epiped = true
+ raise Errno::EPIPE
+ end
+ end
+
+ lambda { task.start(["my_action"]) }.should raise_error(SystemExit)
+ epiped.should == true
+ end
+end

0 comments on commit 5d1f449

Please sign in to comment.