HBASE-20467 Precommit personality should only run checkstyle once if we're going...
[hbase.git] / bin / hirb.rb
blob790ecdc276c69d38478fc3e784a31e461594edde
3 # Licensed to the Apache Software Foundation (ASF) under one
4 # or more contributor license agreements.  See the NOTICE file
5 # distributed with this work for additional information
6 # regarding copyright ownership.  The ASF licenses this file
7 # to you under the Apache License, Version 2.0 (the
8 # "License"); you may not use this file except in compliance
9 # with the License.  You may obtain a copy of the License at
11 #     http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
19 # File passed to org.jruby.Main by bin/hbase.  Pollutes jirb with hbase imports
20 # and hbase  commands and then loads jirb.  Outputs a banner that tells user
21 # where to find help, shell version, and loads up a custom hirb.
23 # In noninteractive mode, runs commands from stdin until completion or an error.
24 # On success will exit with status 0, on any problem will exit non-zero. Callers
25 # should only rely on "not equal to 0", because the current error exit code of 1
26 # will likely be updated to diffentiate e.g. invalid commands, incorrect args,
27 # permissions, etc.
29 # TODO: Interrupt a table creation or a connection to a bad master.  Currently
30 # has to time out.  Below we've set down the retries for rpc and hbase but
31 # still can be annoying (And there seem to be times when we'll retry for
32 # ever regardless)
33 # TODO: Add support for listing and manipulating catalog tables, etc.
34 # TODO: Encoding; need to know how to go from ruby String to UTF-8 bytes
36 # Run the java magic include and import basic HBase types that will help ease
37 # hbase hacking.
38 include Java
40 # Some goodies for hirb. Should these be left up to the user's discretion?
41 require 'irb/completion'
42 require 'pathname'
44 # Add the directory names in hbase.jruby.sources commandline option
45 # to the ruby load path so I can load up my HBase ruby modules
46 sources = java.lang.System.getProperty('hbase.ruby.sources')
47 $LOAD_PATH.unshift Pathname.new(sources)
50 # FIXME: Switch args processing to getopt
52 # See if there are args for this shell. If any, read and then strip from ARGV
53 # so they don't go through to irb.  Output shell 'usage' if user types '--help'
54 cmdline_help = <<HERE # HERE document output as shell usage
55 Usage: shell [OPTIONS] [SCRIPTFILE [ARGUMENTS]]
57  -d | --debug                   Set DEBUG log levels.
58  -h | --help                    This help.
59  -n | --noninteractive          Do not run within an IRB session
60                                 and exit with non-zero status on
61                                 first error.
62 HERE
63 found = []
64 script2run = nil
65 log_level = org.apache.log4j.Level::ERROR
66 @shell_debug = false
67 interactive = true
68 for arg in ARGV
69   if arg == '-h' || arg == '--help'
70     puts cmdline_help
71     exit
72   elsif arg == '-d' || arg == '--debug'
73     log_level = org.apache.log4j.Level::DEBUG
74     $fullBackTrace = true
75     @shell_debug = true
76     found.push(arg)
77     puts 'Setting DEBUG log level...'
78   elsif arg == '-n' || arg == '--noninteractive'
79     interactive = false
80     found.push(arg)
81   elsif arg == '-r' || arg == '--return-values'
82     warn '[INFO] the -r | --return-values option is ignored. we always behave '\
83          'as though it was given.'
84     found.push(arg)
85   else
86     # Presume it a script. Save it off for running later below
87     # after we've set up some environment.
88     script2run = arg
89     found.push(arg)
90     # Presume that any other args are meant for the script.
91     break
92   end
93 end
95 # Delete all processed args
96 found.each { |arg| ARGV.delete(arg) }
97 # Make sure debug flag gets back to IRB
98 ARGV.unshift('-d') if @shell_debug
100 # Set logging level to avoid verboseness
101 org.apache.log4j.Logger.getLogger('org.apache.zookeeper').setLevel(log_level)
102 org.apache.log4j.Logger.getLogger('org.apache.hadoop.hbase').setLevel(log_level)
104 # Require HBase now after setting log levels
105 require 'hbase_constants'
107 # Load hbase shell
108 require 'shell'
110 # Require formatter
111 require 'shell/formatter'
113 # Setup the HBase module.  Create a configuration.
114 @hbase = Hbase::Hbase.new
116 # Setup console
117 @shell = Shell::Shell.new(@hbase, interactive)
118 @shell.debug = @shell_debug
120 # Add commands to this namespace
121 # TODO avoid polluting main namespace by using a binding
122 @shell.export_commands(self)
124 # Add help command
125 def help(command = nil)
126   @shell.help(command)
129 # Backwards compatibility method
130 def tools
131   @shell.help_group('tools')
134 # Debugging method
135 def debug
136   if @shell_debug
137     @shell_debug = false
138     conf.back_trace_limit = 0
139     log_level = org.apache.log4j.Level::ERROR
140   else
141     @shell_debug = true
142     conf.back_trace_limit = 100
143     log_level = org.apache.log4j.Level::DEBUG
144   end
145   org.apache.log4j.Logger.getLogger('org.apache.zookeeper').setLevel(log_level)
146   org.apache.log4j.Logger.getLogger('org.apache.hadoop.hbase').setLevel(log_level)
147   debug?
150 def debug?
151   puts "Debug mode is #{@shell_debug ? 'ON' : 'OFF'}\n\n"
152   nil
155 # Include hbase constants
156 include HBaseConstants
158 # If script2run, try running it.  If we're in interactive mode, will go on to run the shell unless
159 # script calls 'exit' or 'exit 0' or 'exit errcode'.
160 load(script2run) if script2run
162 if interactive
163   # Output a banner message that tells users where to go for help
164   @shell.print_banner
166   require 'irb'
167   require 'irb/hirb'
169   module IRB
170     def self.start(ap_path = nil)
171       $0 = File.basename(ap_path, '.rb') if ap_path
173       IRB.setup(ap_path)
174       @CONF[:IRB_NAME] = 'hbase'
175       @CONF[:AP_NAME] = 'hbase'
176       @CONF[:BACK_TRACE_LIMIT] = 0 unless $fullBackTrace
178       hirb = if @CONF[:SCRIPT]
179                HIRB.new(nil, @CONF[:SCRIPT])
180              else
181                HIRB.new
182              end
184       @CONF[:IRB_RC].call(hirb.context) if @CONF[:IRB_RC]
185       @CONF[:MAIN_CONTEXT] = hirb.context
187       catch(:IRB_EXIT) do
188         hirb.eval_input
189       end
190     end
191   end
193   IRB.start
194 else
195   begin
196     # Noninteractive mode: if there is input on stdin, do a simple REPL.
197     # XXX Note that this purposefully uses STDIN and not Kernel.gets
198     #     in order to maintain compatibility with previous behavior where
199     #     a user could pass in script2run and then still pipe commands on
200     #     stdin.
201     require 'irb/ruby-lex'
202     require 'irb/workspace'
203     workspace = IRB::WorkSpace.new(binding)
204     scanner = RubyLex.new
206     # RubyLex claims to take an IO but really wants an InputMethod
207     module IOExtensions
208       def encoding
209         external_encoding
210       end
211     end
212     IO.include IOExtensions
214     scanner.set_input(STDIN)
215     scanner.each_top_level_statement do |statement, linenum|
216       puts(workspace.evaluate(nil, statement, 'stdin', linenum))
217     end
218   # XXX We're catching Exception on purpose, because we want to include
219   #     unwrapped java exceptions, syntax errors, eval failures, etc.
220   rescue Exception => exception
221     message = exception.to_s
222     # exception unwrapping in shell means we'll have to handle Java exceptions
223     # as a special case in order to format them properly.
224     if exception.is_a? java.lang.Exception
225       $stderr.puts 'java exception'
226       message = exception.get_message
227     end
228     # Include the 'ERROR' string to try to make transition easier for scripts that
229     # may have already been relying on grepping output.
230     puts "ERROR #{exception.class}: #{message}"
231     if $fullBacktrace
232       # re-raising the will include a backtrace and exit.
233       raise exception
234     else
235       exit 1
236     end
237   end