diff --git a/lib/airbrussh/command_formatter.rb b/lib/airbrussh/command_formatter.rb new file mode 100644 index 0000000..80f138b --- /dev/null +++ b/lib/airbrussh/command_formatter.rb @@ -0,0 +1,76 @@ +require "airbrussh/colors" +# rubocop:disable Style/AsciiComments + +module Airbrussh + # Decorates an SSHKit::Command to add string output helpers. + class CommandFormatter < SimpleDelegator + include Airbrussh::Colors + + # Prefixes the line with the command number and removes the newline. + # + # format_output("hello\n") # => "01 hello" + # + def format_output(line) + "#{number} #{line.chomp}" + end + + # Returns the abbreviated command (in yellow) with the number prefix. + # + # start_message # => "01 echo hello" + # + def start_message + "#{number} #{yellow(abbreviated)}" + end + + # Returns a green (success) or red (failure) message depending on the + # exit status. + # + # exit_message # => "✔ 01 user@host 0.084s" + # exit_message # => "✘ 01 user@host 0.084s" + # + # If `log_file` is specified, it is appended to the message + # in the failure case. + # + # exit_message("out.log") + # # => "✘ 01 user@host (see out.log for details) 0.084s" + # + def exit_message(log_file=nil) + if failure? + message = red(failure_message(log_file)) + else + message = green(success_message) + end + message << " #{gray(runtime)}" + end + + private + + def user_at_host + user_str = user { host.user } + host_str = host.to_s + [user_str, host_str].join("@") + end + + def runtime + format("%5.3fs", super) + end + + def abbreviated + to_s.sub(%r{^/usr/bin/env }, "") + end + + def number + format("%02d", position + 1) + end + + def success_message + "✔ #{number} #{user_at_host}" + end + + def failure_message(log_file) + message = "✘ #{number} #{user_at_host}" + message << " (see #{log_file} for details)" if log_file + message + end + end +end diff --git a/lib/airbrussh/formatter.rb b/lib/airbrussh/formatter.rb index b1a6ef6..1ce4d74 100644 --- a/lib/airbrussh/formatter.rb +++ b/lib/airbrussh/formatter.rb @@ -1,15 +1,17 @@ # encoding: UTF-8 +require "airbrussh/colors" +require "airbrussh/command_formatter" require "airbrussh/command_output" require "airbrussh/console" require "airbrussh/rake/command" require "airbrussh/rake/context" -require "colorize" -require "ostruct" require "sshkit" module Airbrussh class Formatter < SSHKit::Formatter::Abstract + include Airbrussh::Colors extend Forwardable + attr_reader :config, :context def_delegator :context, :current_task_name @@ -34,10 +36,6 @@ def create_log_file_formatter ) end - def print_line(string) - @console.print_line(string) - end - def write_banner return unless config.banner if config.banner == :auto @@ -115,17 +113,13 @@ def on_deploy_failure def write_log_message(log_message) return if debug?(log_message) print_task_if_changed - @console.print_line(light_black(" " + log_message.to_s)) + print_indented_line(gray(log_message.to_s)) end def write_command_start(command) return if debug?(command) print_task_if_changed - - if command.first_execution? - shell_string = shell_string(command) - print_line " #{command_number(command)} #{yellow(shell_string)}" - end + print_indented_line(command.start_message) if command.first_execution? end # Prints the data from the stdout and stderr streams of the given command, @@ -143,7 +137,7 @@ def write_command_output(command) def write_command_output_line(command, stream, line) hide_command_output = !config.public_send("command_output_#{stream}?") return if hide_command_output || debug?(command) - print_line " #{command_number(command)} #{line.chomp}" + print_indented_line(command.format_output(line)) end def print_task_if_changed @@ -156,32 +150,7 @@ def print_task_if_changed def write_command_exit(command) return if debug?(command) - print_line " #{format_exit_status(command)} #{runtime(command)}" - end - - def format_exit_status(command) - user = command.user { command.host.user } - host = command.host.to_s - user_at_host = [user, host].join("@") - number = command_number(command) - - if command.failure? - red("✘ #{number} #{user_at_host} (see #{@log_file} for details)") - else - green("✔ #{number} #{user_at_host}") - end - end - - def runtime(command) - light_black(format("%5.3fs", command.runtime)) - end - - def shell_string(command) - command.to_s.sub(%r{^/usr/bin/env }, "") - end - - def command_number(command) - format("%02d", command.position + 1) + print_indented_line(command.exit_message(@log_file), -2) end def clock @@ -194,18 +163,21 @@ def clock format("%02d:%02d", minutes, seconds) end - %w(light_black red blue green yellow).each do |color| - define_method(color) do |string| - string.to_s.colorize(color.to_sym) - end - end - def debug?(obj) obj.verbosity <= SSHKit::Logger::DEBUG end def decorate(command) - @context.decorate_command(command) + Airbrussh::CommandFormatter.new(@context.decorate_command(command)) + end + + def print_line(string) + @console.print_line(string) + end + + def print_indented_line(string, offset=0) + indent = " " * (6 + offset) + print_line([indent, string].join) end end end diff --git a/test/airbrussh/command_formatter_test.rb b/test/airbrussh/command_formatter_test.rb new file mode 100644 index 0000000..d5b04d0 --- /dev/null +++ b/test/airbrussh/command_formatter_test.rb @@ -0,0 +1,42 @@ +require "minitest_helper" +require "ostruct" +require "airbrussh/command_formatter" + +class Airbrussh::CommandFormatterTest < Minitest::Test + def setup + sshkit_command = OpenStruct.new( + :host => "12.34.56.78", + :user => "deployer", + :runtime => 1.23456, + :position => 0, + :failure? => false + ) + def sshkit_command.to_s + "/usr/bin/env echo hello" + end + @command = Airbrussh::CommandFormatter.new(sshkit_command) + end + + def test_format_output + assert_equal("01 hello", @command.format_output("hello\n")) + end + + def test_start_message + assert_equal("01 \e[0;33;49mecho hello\e[0m", @command.start_message) + end + + def test_exit_message_success + assert_equal( + "\e[0;32;49m✔ 01 deployer@12.34.56.78\e[0m \e[0;90;49m1.235s\e[0m", + @command.exit_message) + end + + def test_exit_message_failure + @command.stub(:failure?, true) do + assert_equal( + "\e[0;31;49m✘ 01 deployer@12.34.56.78 (see out.log for details)\e[0m "\ + "\e[0;90;49m1.235s\e[0m", + @command.exit_message("out.log")) + end + end +end