Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions hbase-shell/src/main/ruby/irb/hirb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ def initialize(workspace = nil, interactive = true, input_method = nil)
`stty icrnl <&2`
end
@interactive = interactive
# Errors must abort a script run to set the exit code, but not a live prompt
@exit_on_error = !interactive || input_method.is_a?(::IRB::FileInputMethod)
super(workspace, input_method)
ensure
f.close
Expand Down Expand Up @@ -161,17 +163,13 @@ def eval_input
rescue Interrupt => exc
rescue SystemExit, SignalException
raise
rescue SyntaxError => exc
# HBASE-27726: Ignore SyntaxError to prevent exiting Shell on unexpected syntax.
raise exc unless @interactive
rescue NameError => exc
raise exc unless @interactive
# HBASE-26880: Ignore NameError to prevent exiting Shell on mistyped commands.
rescue Exception => exc
# HBASE-26741: Raise exception so Shell::exception_handler can catch it.
# This modifies this copied method from JRuby so that the HBase shell can
# manage the exception and set a proper exit code on the process.
raise exc
# Otherwise keep the session alive and report the error, as the shell did before
# HBASE-26741. Supersedes HBASE-26880 (NameError) and HBASE-27726 (SyntaxError).
raise if @exit_on_error
else
exc = nil
next
Expand Down
22 changes: 22 additions & 0 deletions hbase-shell/src/test/ruby/shell/general_test_cluster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
require 'hbase_shell'
require 'irb/hirb'
require 'stringio'
require 'tempfile'

class ShellTest < Test::Unit::TestCase
include Hbase::TestHelpers
Expand Down Expand Up @@ -226,4 +227,25 @@ def readable_after_eof?
assert_match(/WARN: 'scan' is a reserved HBase command/, err_output)
assert_match(/WARN: 'processlist' is a reserved HBase command/, err_output)
end

def new_hirb(input_method)
IRB.setup(__FILE__) unless IRB.conf[:IRB_NAME]
IRB::HIRB.new(@shell.workspace, true, input_method)
end
Comment thread
junegunn marked this conversation as resolved.

define_test 'Shell::Shell should keep an interactive session alive on any error' do
hirb = new_hirb(MockInputMethod.new(["1 + '2'\n", "my_var = 5\n"]))
capture_stdout { hirb.eval_input }
assert_equal(5, hirb.context.workspace.binding.local_variable_get(:my_var))
end

define_test 'Shell::Shell should abort a script on error even when interactive' do
Tempfile.create(['hirb_test', '.rb']) do |file|
file.write("1 + '2'\n")
file.close
# interactive is true, as it is for `hbase shell script.rb` without -n
hirb = new_hirb(IRB::HBaseLoader.file_for_load(file.path))
assert_raise(TypeError) { capture_stdout { hirb.eval_input } }
end
end
end