Search code examples
rubythor

Ruby/Thor exit status in case of an error


I'm new to Thor (and to Ruby) and I'm considering using it within a build script, as it's said it can be a replacement to Rake (thus to Make). However after a short trial, I'm confused about the error status it returns. I quickly went through the wiki but haven't seen any mention about that.

With just the first "Simple Example", test.thor:

class Test < Thor
  desc "example", "an example task"
  def example
    puts "I'm a thor task!"
  end
end

version #:

eruve>thor version
Thor 0.18.1

I tried the following, an erroneous command on purpose:

eruve>ruby --version; thor test:example badarg; echo exit status: $?

ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-darwin10.8.0]
ERROR: thor example was called with arguments ["badarg"]
Usage: "thor test:example".
exit status: 0

So, there was an error but it exits with status 0 nonetheless... meaning I'd rather not use it in a (non-ruby) script, or else the script would continue running even though it should terminate. Subsequent errors might be difficult to analyse.

I must be missing something, hence my questions:

  • Is there an easy way to get a non-zero status by default in case of an error (config file, etc.)?

  • If not, what am I supposed to do to get it right?

Thank you.


Solution

  • Based on bundler's solution (many thanks @fontno), and more investigation on my side, here is a hack in order to have it working with a normal shell. WARNING: it's not elegant, prints out the exception stack crap, but I think that works (please don't hesitate to tell me otherwise).

    class Thorough < Thor
      ENV["THOR_DEBUG"] = "1"
      check_unknown_options!
    private
      def subcommand(*_) super subcommand(*_)
      rescue Thor::Error => e
        $stderr.puts e.message
        exit 1
      end
    end
    
    class Test < Thor#ough
      desc "example", "an example task"
      def example
        puts "I'm a thor task!"
      end
    end
    

    Written as above, it has the same behavior as before (I believe). Now, after removing the # from Thor#ough, it should exit with status 1 if Thor has raised an Error, thus allowing some control from e.g. a non-ruby shell.

    eruve>thor test:example badarg; echo $?
    /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/base.rb:482:in `handle_argument_error': ERROR: thor example was called with arguments ["badarg"] (Thor::InvocationError)
    Usage: "thor test:example".
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/command.rb:35:in `rescue in run'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/command.rb:21:in `run'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/invocation.rb:120:in `invoke_command'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor.rb:363:in `dispatch'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/base.rb:439:in `start'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/runner.rb:36:in `method_missing'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/command.rb:29:in `run'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/command.rb:128:in `run'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/invocation.rb:120:in `invoke_command'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor.rb:363:in `dispatch'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/base.rb:439:in `start'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/bin/thor:6:in `<top (required)>'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/bin/thor:23:in `load'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/bin/thor:23:in `<main>'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/bin/ruby_noexec_wrapper:14:in `eval'
        from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/bin/ruby_noexec_wrapper:14:in `<main>'
    1
    
    eruve>thor test:example; echo $?
    I'm a thor task!
    0
    
    eruve>thor test:example badarg 2>/dev/null; echo $?
    1
    

    Cheers. PS: I wonder, are there many gotchas like this in Thor? If it's an expected behavior, its purpose/philosophy is incompatible with the needs of my project... hacks are not a reliable solution.