lib/rye/box.rb in rye-0.7.4 vs lib/rye/box.rb in rye-0.7.5
- old
+ new
@@ -32,29 +32,38 @@
def host; @rye_host; end
def opts; @rye_opts; end
def safe; @rye_safe; end
def user; (@rye_opts || {})[:user]; end
+ # A storage area +@rye_stash+
+ def stash; @rye_stash; end
+ def nickname; @rye_nickname || host; end
+
def host=(val); @rye_host = val; end
def opts=(val); @rye_opts = val; end
+ # Returns the storage area +@rye_stash+
+ def stash=(val); @rye_stash = val; end
+ def nickname=(val); @rye_nickname = val; end
+
def enable_safe_mode; @rye_safe = true; end
def disable_safe_mode; @rye_safe = false; end
# The most recent value from Box.cd or Box.[]
def current_working_directory; @rye_current_working_directory; end
# The most recent valud for umask (or 0022)
def current_umask; @rye_current_umask; end
-
- def ssh; @rye_ssh; end
+
def info; @rye_info; end
def debug; @rye_debug; end
def error; @rye_error; end
def pre_command_hook=(val); @rye_pre_command_hook = val; end
def post_command_hook=(val); @rye_post_command_hook = val; end
+ # A Hash. The keys are exception classes, the values are Procs to execute
+ def exception_hook=(val); @rye_exception_hook = val; end
# * +host+ The hostname to connect to. The default is localhost.
# * +opts+ a hash of optional arguments.
#
# The +opts+ hash excepts the following keys:
@@ -70,10 +79,11 @@
#
# NOTE: +opts+ can also contain any parameter supported by
# Net::SSH.start that is not already mentioned above.
#
def initialize(host='localhost', opts={})
+ @rye_exception_hook = {}
@rye_host = host
# These opts are use by Rye::Box and also passed to Net::SSH
@rye_opts = {
:user => Rye.sysinfo.user,
@@ -220,11 +230,11 @@
if ret.is_a?(Rye::Rap)
debug "ssh-add exit_code: #{ret.exit_code}"
debug "ssh-add stdout: #{ret.stdout}"
debug "ssh-add stderr: #{ret.stderr}"
end
- self #MUST RETURN itself
+ self # MUST RETURN self
end
alias :add_key :add_keys
# Return the value of uname in lowercase
# This is a temporary fix. We can use SysInfo for this, upload
@@ -277,12 +287,12 @@
# Returns +user@rye_host+
def to_s; '%s@rye_%s' % [user, @rye_host]; end
def inspect
- %q{#<%s:%s cwd=%s umask=%s env=%s safe=%s opts=%s>} %
- [self.class.to_s, self.host,
+ %q{#<%s:%s name=%s cwd=%s umask=%s env=%s safe=%s opts=%s>} %
+ [self.class.to_s, self.host, self.nickname,
@rye_current_working_directory, @rye_current_umask,
(@rye_current_environment_variables || '').inspect,
self.safe, self.opts.inspect]
end
@@ -422,11 +432,13 @@
end
# A handler for undefined commands.
# Raises Rye::CommandNotFound exception.
def method_missing(meth, *args, &block)
- raise Rye::CommandNotFound, "#{meth.to_s}"
+ ex = Rye::CommandNotFound.new(meth.to_s)
+ raise ex unless @rye_exception_hook.has_key? ex.class
+ @rye_exception_hook[Rye::CommandNotFound].call ex
end
# Returns the command an arguments as a String.
def preview_command(*args)
prep_args(*args).join(' ')
@@ -442,10 +454,31 @@
def pre_command_hook(&block)
@rye_pre_command_hook = block if block
@rye_pre_command_hook
end
+ # Supply a block to be called whenever there's an Exception. It's called
+ # with 1 argument: the exception class. If the exception block returns
+ # :retry, the command will be executed again.
+ #
+ # e.g.
+ # rbox.exception_hook(CommandNotFound) do |ex|
+ # STDERR.puts "An error occurred: #{ex.class}"
+ # choice = Annoy.get_user_input('(S)kip (R)etry (A)bort: ')
+ # if choice == 'R'
+ # :retry
+ # elsif choice == 'S'
+ # # do nothing
+ # else
+ # exit # !
+ # end
+ # end
+ def exception_hook(klass, &block)
+ @rye_exception_hook[klass] = block if block
+ @rye_exception_hook[klass]
+ end
+
# Execute a block in the context of an instance of Rye::Box.
#
# rbox = Rye::Box.new
#
# rbox.batch do
@@ -620,16 +653,15 @@
if @rye_current_umask
cwd = Rye.escape(@rye_safe, 'umask', @rye_current_umask)
cmd_clean = [cwd, cmd_clean].join(' && ')
end
-
info "COMMAND: #{cmd_clean}"
debug "Executing: %s" % cmd_clean
if @rye_pre_command_hook.is_a?(Proc)
- @rye_pre_command_hook.call(cmd, args, user, host)
+ @rye_pre_command_hook.call(cmd, args, user, host, nickname)
end
## NOTE: Do not raise a CommandNotFound exception in this method.
# We want it to be possible to define methods to a single instance
# of Rye::Box. i.e. def rbox.rm()...
@@ -637,29 +669,34 @@
# return false. We could use self.respond_to? but it's possible
# to get a name collision. I could write a work around but I think
# this is good enough for now.
## raise Rye::CommandNotFound unless self.can?(cmd)
- stdout, stderr, ecode, esignal = net_ssh_exec!(cmd_clean)
-
- rap = Rye::Rap.new(self)
- rap.add_stdout(stdout || '')
- rap.add_stderr(stderr || '')
- rap.add_exit_code(ecode)
- rap.exit_signal = esignal
- rap.cmd = cmd
-
- if @rye_post_command_hook.is_a?(Proc)
- @rye_post_command_hook.call(rap)
- else
+ begin
+ stdout, stderr, ecode, esignal = net_ssh_exec!(cmd_clean)
+
+ rap = Rye::Rap.new(self)
+ rap.add_stdout(stdout || '')
+ rap.add_stderr(stderr || '')
+ rap.add_exit_code(ecode)
+ rap.exit_signal = esignal
+ rap.cmd = cmd
+
# It seems a convention for various commands to return -1
# when something only mildly concerning happens. ls even
# returns -1 for apparently no reason sometimes. In any
# case, the real errors are the ones greater than zero
raise Rye::CommandError.new(rap) if ecode > 0
+
+ rescue Exception => ex
+ raise ex unless @rye_exception_hook.has_key? ex.class
+ ret = @rye_exception_hook[ex.class].call(ex)
+ retry if ret == :retry
end
+ @rye_post_command_hook.call(rap) if @rye_post_command_hook.is_a?(Proc)
+
rap
end
alias :cmd :run_command
# Takes a list of arguments appropriate for run_command or
@@ -720,10 +757,10 @@
channel = @rye_ssh.exec(command, &block)
channel.wait # block until we get a response
channel.request_pty do |ch, success|
- raise "Could not obtain pty (i.e. an interactive ssh session)" if !success
+ raise Rye::NoPty if !success
end
channel[:exit_code] = 0 if channel[:exit_code] == nil
channel[:exit_code] &&= channel[:exit_code].to_i