convoy 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.irbrc +3 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +705 -0
- data/Rakefile +1 -0
- data/convoy.gemspec +24 -0
- data/examples/.my_apprc +24 -0
- data/examples/basic +10 -0
- data/examples/basic_config_file +16 -0
- data/examples/basic_conflicts +17 -0
- data/examples/basic_depends_on +25 -0
- data/examples/basic_flags +15 -0
- data/examples/basic_options +14 -0
- data/examples/basic_options_multi +15 -0
- data/examples/basic_require_arguments +17 -0
- data/examples/basic_texts +21 -0
- data/examples/basic_validations +21 -0
- data/examples/basic_with_everything +30 -0
- data/examples/commands/example_command.rb +13 -0
- data/examples/suite_complex +65 -0
- data/examples/suite_simple +19 -0
- data/examples/suite_with_sub_commands +94 -0
- data/lib/convoy.rb +83 -0
- data/lib/convoy/action_command/base.rb +85 -0
- data/lib/convoy/action_command/escort_utility_command.rb +53 -0
- data/lib/convoy/app.rb +127 -0
- data/lib/convoy/arguments.rb +20 -0
- data/lib/convoy/auto_options.rb +71 -0
- data/lib/convoy/error/error.rb +33 -0
- data/lib/convoy/formatter/command.rb +87 -0
- data/lib/convoy/formatter/commands.rb +37 -0
- data/lib/convoy/formatter/cursor_position.rb +29 -0
- data/lib/convoy/formatter/default_help_formatter.rb +117 -0
- data/lib/convoy/formatter/global_command.rb +17 -0
- data/lib/convoy/formatter/option.rb +152 -0
- data/lib/convoy/formatter/options.rb +28 -0
- data/lib/convoy/formatter/shell_command_executor.rb +49 -0
- data/lib/convoy/formatter/stream_output_formatter.rb +88 -0
- data/lib/convoy/formatter/string_grid.rb +108 -0
- data/lib/convoy/formatter/string_splitter.rb +50 -0
- data/lib/convoy/formatter/terminal.rb +30 -0
- data/lib/convoy/global_pre_parser.rb +43 -0
- data/lib/convoy/logger.rb +75 -0
- data/lib/convoy/option_dependency_validator.rb +82 -0
- data/lib/convoy/option_parser.rb +155 -0
- data/lib/convoy/setup/configuration/generator.rb +75 -0
- data/lib/convoy/setup/configuration/instance.rb +34 -0
- data/lib/convoy/setup/configuration/loader.rb +43 -0
- data/lib/convoy/setup/configuration/locator/base.rb +19 -0
- data/lib/convoy/setup/configuration/locator/chaining.rb +29 -0
- data/lib/convoy/setup/configuration/locator/descending_to_home.rb +23 -0
- data/lib/convoy/setup/configuration/locator/executing_script_directory.rb +15 -0
- data/lib/convoy/setup/configuration/locator/specified_directory.rb +21 -0
- data/lib/convoy/setup/configuration/merge_tool.rb +38 -0
- data/lib/convoy/setup/configuration/reader.rb +36 -0
- data/lib/convoy/setup/configuration/writer.rb +46 -0
- data/lib/convoy/setup/dsl/action.rb +17 -0
- data/lib/convoy/setup/dsl/command.rb +67 -0
- data/lib/convoy/setup/dsl/config_file.rb +13 -0
- data/lib/convoy/setup/dsl/global.rb +29 -0
- data/lib/convoy/setup/dsl/options.rb +81 -0
- data/lib/convoy/setup_accessor.rb +206 -0
- data/lib/convoy/trollop.rb +861 -0
- data/lib/convoy/utils.rb +21 -0
- data/lib/convoy/validator.rb +45 -0
- data/spec/integration/basic_config_file_spec.rb +126 -0
- data/spec/integration/basic_conflicts_spec.rb +47 -0
- data/spec/integration/basic_depends_on_spec.rb +275 -0
- data/spec/integration/basic_options_spec.rb +41 -0
- data/spec/integration/basic_options_with_multi_spec.rb +30 -0
- data/spec/integration/basic_spec.rb +38 -0
- data/spec/integration/basic_validations_spec.rb +77 -0
- data/spec/integration/basic_with_arguments_spec.rb +35 -0
- data/spec/integration/basic_with_text_fields_spec.rb +21 -0
- data/spec/integration/suite_simple_spec.rb +45 -0
- data/spec/integration/suite_sub_command_spec.rb +51 -0
- data/spec/lib/convoy/action_command/base_spec.rb +200 -0
- data/spec/lib/convoy/formatter/command_spec.rb +238 -0
- data/spec/lib/convoy/formatter/global_command_spec.rb +50 -0
- data/spec/lib/convoy/formatter/option_spec.rb +300 -0
- data/spec/lib/convoy/formatter/shell_command_executor_spec.rb +59 -0
- data/spec/lib/convoy/formatter/stream_output_formatter_spec.rb +214 -0
- data/spec/lib/convoy/formatter/string_grid_spec.rb +59 -0
- data/spec/lib/convoy/formatter/string_splitter_spec.rb +50 -0
- data/spec/lib/convoy/formatter/terminal_spec.rb +19 -0
- data/spec/lib/convoy/setup/configuration/generator_spec.rb +101 -0
- data/spec/lib/convoy/setup/configuration/loader_spec.rb +79 -0
- data/spec/lib/convoy/setup/configuration/locator/chaining_spec.rb +81 -0
- data/spec/lib/convoy/setup/configuration/locator/descending_to_home_spec.rb +57 -0
- data/spec/lib/convoy/setup/configuration/locator/executing_script_directory_spec.rb +29 -0
- data/spec/lib/convoy/setup/configuration/locator/specified_directory_spec.rb +33 -0
- data/spec/lib/convoy/setup/configuration/merge_tool_spec.rb +41 -0
- data/spec/lib/convoy/setup/configuration/reader_spec.rb +41 -0
- data/spec/lib/convoy/setup/configuration/writer_spec.rb +75 -0
- data/spec/lib/convoy/setup_accessor_spec.rb +226 -0
- data/spec/lib/convoy/utils_spec.rb +30 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/integration_helpers.rb +2 -0
- data/spec/support/matchers/execute_action_for_command_matcher.rb +21 -0
- data/spec/support/matchers/execute_action_with_arguments_matcher.rb +25 -0
- data/spec/support/matchers/execute_action_with_options_matcher.rb +29 -0
- data/spec/support/matchers/exit_with_code_matcher.rb +29 -0
- data/spec/support/shared_contexts/integration_setup.rb +34 -0
- metadata +292 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'open3'
|
|
2
|
+
|
|
3
|
+
module Convoy
|
|
4
|
+
module Formatter
|
|
5
|
+
class ShellCommandExecutor
|
|
6
|
+
attr_reader :command
|
|
7
|
+
|
|
8
|
+
def initialize(command)
|
|
9
|
+
@command = command
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def execute_in_current_shell(success_callback = nil, error_callback = nil)
|
|
13
|
+
begin
|
|
14
|
+
result = `#{command}`
|
|
15
|
+
process_status = $?
|
|
16
|
+
raise Convoy::InternalError.new("Shell command exited with a non-zero (#{process_status.exitstatus}) exit code") if process_status.exitstatus != 0
|
|
17
|
+
success_callback.call(command, result) if success_callback
|
|
18
|
+
rescue => e
|
|
19
|
+
error_callback.call(command, e) if error_callback
|
|
20
|
+
nil
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
#def execute_in_new_shell(success_callback = nil, error_callback = nil)
|
|
25
|
+
#stdin, stdout, stderr = nil, nil, nil
|
|
26
|
+
#begin
|
|
27
|
+
#stdin, stdout, stderr, thread = ensure_successful_exit do
|
|
28
|
+
#Open3.popen3(command)
|
|
29
|
+
#end
|
|
30
|
+
#success_callback.call(command, stdin, stdout, stderr) if success_callback
|
|
31
|
+
#rescue => e
|
|
32
|
+
#error_callback.call(command, e) if error_callback
|
|
33
|
+
#nil
|
|
34
|
+
#ensure
|
|
35
|
+
#[stdin, stdout, stderr].each {|io| io.close if io}
|
|
36
|
+
#end
|
|
37
|
+
#end
|
|
38
|
+
|
|
39
|
+
#private
|
|
40
|
+
|
|
41
|
+
#def ensure_successful_exit(&block)
|
|
42
|
+
#stdin, stdout, stderr, thread = block.call
|
|
43
|
+
#process_status = thread.value
|
|
44
|
+
#raise Convoy::InternalError.new("Shell command exited with a non-zero (#{process_status.exitstatus}) exit code") if process_status.exitstatus != 0
|
|
45
|
+
#[stdin, stdout, stderr, thread]
|
|
46
|
+
#end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module Convoy
|
|
2
|
+
module Formatter
|
|
3
|
+
class StreamOutputFormatter
|
|
4
|
+
DEFAULT_OUTPUT_WIDTH = 80
|
|
5
|
+
DEFAULT_INDENT_STRING = ' '
|
|
6
|
+
DEFAULT_INDENT = 0
|
|
7
|
+
|
|
8
|
+
attr_reader :stream, :indent_string, :current_indent, :max_output_width, :cursor_position
|
|
9
|
+
|
|
10
|
+
def initialize(stream = $stdout, options = {}, &block)
|
|
11
|
+
@stream = stream
|
|
12
|
+
@max_output_width = options[:max_output_width] || DEFAULT_OUTPUT_WIDTH
|
|
13
|
+
@indent_string = options[:indent_string] || DEFAULT_INDENT_STRING
|
|
14
|
+
@current_indent = options[:current_indent] || DEFAULT_INDENT
|
|
15
|
+
@cursor_position = CursorPosition.new(@max_output_width)
|
|
16
|
+
block.call(self) if block_given?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def print(string)
|
|
20
|
+
splitter_input = pad_string_to_account_for_cursor_position(string.to_s)
|
|
21
|
+
segments = StringSplitter.new(max_output_width).split(splitter_input)
|
|
22
|
+
segments = remove_padding_that_account_for_cursor_position(segments)
|
|
23
|
+
segments.each do |segment|
|
|
24
|
+
output_string = "#{current_indent_string}#{segment}"
|
|
25
|
+
output_string = segment unless cursor_position.newline?
|
|
26
|
+
stream.print output_string
|
|
27
|
+
cursor_position.update_for(segment)
|
|
28
|
+
newline if segments.last != segment
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def puts(string, options = {:newlines => 1})
|
|
33
|
+
print(string)
|
|
34
|
+
newline(options[:newlines])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def newline(newline_count = 1)
|
|
38
|
+
stream.print("\n" * newline_count)
|
|
39
|
+
cursor_position.reset if newline_count > 0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def indent(count, &block)
|
|
43
|
+
newline unless cursor_position.newline?
|
|
44
|
+
new_indent = current_indent + count
|
|
45
|
+
self.class.new(stream, :max_output_width => max_output_width - count, :indent_string => indent_string, :current_indent => new_indent, &block)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def grid(options = {}, &block)
|
|
49
|
+
if block_given?
|
|
50
|
+
options[:width] ||= max_output_width
|
|
51
|
+
grid = StringGrid.new(options, &block)
|
|
52
|
+
puts grid.to_s
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def pad_string_to_account_for_cursor_position(string)
|
|
59
|
+
"#{padding_string}#{string}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def remove_padding_that_account_for_cursor_position(segments)
|
|
63
|
+
first_string = segments.first
|
|
64
|
+
if first_string
|
|
65
|
+
segments[0] = first_string.sub(/#{padding_string}/, '')
|
|
66
|
+
end
|
|
67
|
+
segments
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def padding_string
|
|
71
|
+
"." * cursor_position.position
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def current_indent_width
|
|
75
|
+
current_indent_string.length
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def current_indent_string
|
|
79
|
+
indent_string * current_indent
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
#def table(options = {}, &block)
|
|
83
|
+
#BorderlessTable.new(self, options).output(&block)
|
|
84
|
+
#newline(options[:newlines] || 1)
|
|
85
|
+
#end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module Convoy
|
|
2
|
+
module Formatter
|
|
3
|
+
class StringGrid
|
|
4
|
+
DEFAULT_WIDTH = 80
|
|
5
|
+
|
|
6
|
+
attr_reader :column_count, :width
|
|
7
|
+
attr_accessor :rows
|
|
8
|
+
|
|
9
|
+
def initialize(options = {}, &block)
|
|
10
|
+
@width = options[:width] || DEFAULT_WIDTH
|
|
11
|
+
@column_count = options[:columns] || 3
|
|
12
|
+
@rows = []
|
|
13
|
+
block.call(self) if block_given?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def row(*column_values)
|
|
17
|
+
while column_values.size < @column_count
|
|
18
|
+
column_values << ''
|
|
19
|
+
end
|
|
20
|
+
rows << column_values.map(&:to_s)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_s
|
|
24
|
+
buffer = []
|
|
25
|
+
rows.each do |cells|
|
|
26
|
+
virtual_row = normalize_virtual_row(virtual_row_for(cells))
|
|
27
|
+
physical_row_count_for(virtual_row).times do |physical_count|
|
|
28
|
+
physical_row = format_physical_row_values(physical_row_for(virtual_row, physical_count))
|
|
29
|
+
buffer << physical_row.join("").chomp
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
buffer.join("\n")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def format_physical_row_values(physical_row)
|
|
38
|
+
physical_row.each_with_index.map do |value, index|
|
|
39
|
+
cell_value(value, index)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def physical_row_for(virtual_row, index)
|
|
44
|
+
virtual_row.map { |physical| physical[index] }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def virtual_row_for(column_values)
|
|
48
|
+
virtual_row = []
|
|
49
|
+
column_values.each_with_index do |cell, index|
|
|
50
|
+
virtual_row << Convoy::Formatter::StringSplitter.new(column_width(index) - 1).split(cell)
|
|
51
|
+
end
|
|
52
|
+
normalize_virtual_row(virtual_row)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def normalize_virtual_row(virtual_row)
|
|
56
|
+
virtual_row.map do |physical|
|
|
57
|
+
while physical.size < physical_row_count_for(virtual_row)
|
|
58
|
+
physical << ""
|
|
59
|
+
end
|
|
60
|
+
physical
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def physical_row_count_for(virtual_row)
|
|
65
|
+
virtual_row.map { |physical| physical.size }.max
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def column_width(column_index)
|
|
69
|
+
width = fair_column_width(column_index)
|
|
70
|
+
if column_index == column_count - 1
|
|
71
|
+
width = last_column_width
|
|
72
|
+
end
|
|
73
|
+
width
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def fair_column_width(index)
|
|
77
|
+
width = values_in_column(index).map(&:length).max
|
|
78
|
+
width = width + 1
|
|
79
|
+
width > max_column_width ? max_column_width : width
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def last_column_width
|
|
83
|
+
full_fair_column_width = max_column_width * column_count + max_column_width_remainder
|
|
84
|
+
all_but_last_fair_column_width = 0
|
|
85
|
+
(column_count - 1).times do |index|
|
|
86
|
+
all_but_last_fair_column_width += fair_column_width(index)
|
|
87
|
+
end
|
|
88
|
+
full_fair_column_width - all_but_last_fair_column_width
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def values_in_column(column_index)
|
|
92
|
+
rows.map { |cells| cells[column_index] }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def max_column_width
|
|
96
|
+
width/column_count
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def max_column_width_remainder
|
|
100
|
+
width%column_count
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def cell_value(value, column_index)
|
|
104
|
+
sprintf("%-#{column_width(column_index)}s", value)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Convoy
|
|
2
|
+
module Formatter
|
|
3
|
+
class StringSplitter
|
|
4
|
+
attr_reader :max_segment_width #, :first_segment_max_length
|
|
5
|
+
|
|
6
|
+
def initialize(max_segment_width, options = {})
|
|
7
|
+
@max_segment_width = max_segment_width
|
|
8
|
+
#@first_segment_max_length = options[:first_segment_max_length] || max_segment_width
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def split(input_string)
|
|
12
|
+
input_strings = input_string.split("\n")
|
|
13
|
+
[split_strings(input_strings)].flatten
|
|
14
|
+
#first_string = strings.shift
|
|
15
|
+
#other_strings = strings
|
|
16
|
+
#result = [split_first_string(first_string) + split_strings(other_strings)].flatten
|
|
17
|
+
#result
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
#def split_first_string(string)
|
|
23
|
+
#if first_segment_max_length >= string.length
|
|
24
|
+
#split_string(string)
|
|
25
|
+
#else
|
|
26
|
+
#first = string.slice(0, first_segment_max_length)
|
|
27
|
+
#last = string.slice(first_segment_max_length..-1)
|
|
28
|
+
#split_strings([first, last])
|
|
29
|
+
#end
|
|
30
|
+
#end
|
|
31
|
+
|
|
32
|
+
def split_strings(strings)
|
|
33
|
+
strings.map { |s| split_string(s) }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def split_string(string)
|
|
37
|
+
result = []
|
|
38
|
+
if string.length > max_segment_width
|
|
39
|
+
first_part = string.slice(0, max_segment_width)
|
|
40
|
+
second_part = string.slice(max_segment_width..-1)
|
|
41
|
+
result << first_part
|
|
42
|
+
result << split_string(second_part)
|
|
43
|
+
else
|
|
44
|
+
result << string
|
|
45
|
+
end
|
|
46
|
+
result
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Convoy
|
|
2
|
+
module Formatter
|
|
3
|
+
class Terminal
|
|
4
|
+
DEFAULT_WIDTH = 80
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def width
|
|
8
|
+
tput_width
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def tput_width
|
|
14
|
+
ShellCommandExecutor.new('/usr/bin/env tput cols').execute_in_current_shell(tput_cols_command_success_callback, tput_cols_command_error_callback) || DEFAULT_WIDTH
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def tput_cols_command_success_callback
|
|
18
|
+
lambda { |command, result| result.to_i }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def tput_cols_command_error_callback
|
|
22
|
+
lambda do |command, e|
|
|
23
|
+
error_logger.debug { e }
|
|
24
|
+
error_logger.info { "Unable to find terminal width via '#{command}', using default of #{DEFAULT_WIDTH}" }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Convoy
|
|
2
|
+
class GlobalPreParser
|
|
3
|
+
attr_reader :setup
|
|
4
|
+
|
|
5
|
+
def initialize(setup)
|
|
6
|
+
@setup = setup
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def parse(cli_options)
|
|
10
|
+
AutoOptions.new(parse_global_options(cli_options))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def parse_global_options(cli_options, context = [])
|
|
16
|
+
stop_words = setup.command_names_for(context).map(&:to_s)
|
|
17
|
+
parser = init_parser(stop_words)
|
|
18
|
+
parser = add_setup_options_to(parser, context)
|
|
19
|
+
parser.version(setup.version) #set the version if it was provided
|
|
20
|
+
parser.help_formatter(Convoy::Formatter::DefaultHelpFormatter.new(setup, context))
|
|
21
|
+
parsed_options = parse_options_string(parser, cli_options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def init_parser(stop_words)
|
|
25
|
+
Trollop::Parser.new.tap do |parser|
|
|
26
|
+
parser.stop_on(stop_words)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def add_setup_options_to(parser, context = [])
|
|
31
|
+
setup.options_for(context).each do |name, opts|
|
|
32
|
+
parser.opt name, opts[:desc] || "", opts
|
|
33
|
+
end
|
|
34
|
+
parser
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def parse_options_string(parser, cli_options)
|
|
38
|
+
Trollop::with_standard_exception_handling(parser) do
|
|
39
|
+
parser.parse(cli_options)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'logger'
|
|
2
|
+
|
|
3
|
+
module Convoy
|
|
4
|
+
class Logger
|
|
5
|
+
class << self
|
|
6
|
+
def close
|
|
7
|
+
error.close
|
|
8
|
+
output.close
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def error
|
|
12
|
+
@error_logger ||= ::Logger.new($stderr).tap do |l|
|
|
13
|
+
#l.formatter = advanced_error_formatter
|
|
14
|
+
l.formatter = basic_error_formatter
|
|
15
|
+
l.sev_threshold = ::Logger::WARN
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def output
|
|
20
|
+
@output_logger ||= ::Logger.new($stdout).tap do |l|
|
|
21
|
+
l.formatter = output_formatter
|
|
22
|
+
l.sev_threshold = ::Logger::DEBUG
|
|
23
|
+
l.instance_eval do
|
|
24
|
+
def puts(message = nil, &block)
|
|
25
|
+
if block_given?
|
|
26
|
+
fatal(&block)
|
|
27
|
+
else
|
|
28
|
+
fatal(message || "")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def setup_error_logger(auto_options)
|
|
36
|
+
error.formatter = send(:"#{auto_options.error_formatter}_error_formatter")
|
|
37
|
+
error.sev_threshold = ::Logger.const_get(auto_options.verbosity)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def basic_error_formatter
|
|
43
|
+
proc do |severity, datetime, progname, msg|
|
|
44
|
+
"#{msg2str(msg)}\n"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
#"#{severity} [#{datetime.strftime("%d/%b/%Y %H:%M:%S")}] \"#{msg}\"\n"
|
|
49
|
+
def advanced_error_formatter
|
|
50
|
+
proc do |severity, datetime, progname, msg|
|
|
51
|
+
sprintf("%-8s #{msg2str(msg, 10)}\n", severity)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def output_formatter
|
|
56
|
+
proc do |severity, datetime, progname, msg|
|
|
57
|
+
"#{msg}\n"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def msg2str(msg, backtrace_indent = 0)
|
|
62
|
+
case msg
|
|
63
|
+
when ::String
|
|
64
|
+
msg
|
|
65
|
+
when ::Exception
|
|
66
|
+
"#{msg.message} (#{ msg.class })\n" <<
|
|
67
|
+
(msg.backtrace || []).map { |line| sprintf("%#{backtrace_indent}s#{line}", "") }.join("\n")
|
|
68
|
+
else
|
|
69
|
+
msg.inspect
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|