cuprum-cli 0.1.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/CHANGELOG.md +34 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE +21 -0
- data/README.md +163 -0
- data/lib/cuprum/cli/argument.rb +172 -0
- data/lib/cuprum/cli/arguments/class_methods.rb +283 -0
- data/lib/cuprum/cli/arguments.rb +16 -0
- data/lib/cuprum/cli/coercion.rb +131 -0
- data/lib/cuprum/cli/command.rb +102 -0
- data/lib/cuprum/cli/commands/ci/report.rb +121 -0
- data/lib/cuprum/cli/commands/ci/rspec_command.rb +108 -0
- data/lib/cuprum/cli/commands/ci/rspec_each_command.rb +185 -0
- data/lib/cuprum/cli/commands/ci.rb +12 -0
- data/lib/cuprum/cli/commands/echo_command.rb +76 -0
- data/lib/cuprum/cli/commands/file/generate_file.rb +141 -0
- data/lib/cuprum/cli/commands/file/new_command.rb +86 -0
- data/lib/cuprum/cli/commands/file/render_erb.rb +88 -0
- data/lib/cuprum/cli/commands/file/resolve_template.rb +136 -0
- data/lib/cuprum/cli/commands/file/templates/rspec.rb.erb +14 -0
- data/lib/cuprum/cli/commands/file/templates/ruby.rb.erb +29 -0
- data/lib/cuprum/cli/commands/file/templates.rb +71 -0
- data/lib/cuprum/cli/commands/file.rb +14 -0
- data/lib/cuprum/cli/commands.rb +12 -0
- data/lib/cuprum/cli/dependencies/file_system/mock.rb +297 -0
- data/lib/cuprum/cli/dependencies/file_system.rb +247 -0
- data/lib/cuprum/cli/dependencies/standard_io/helpers.rb +138 -0
- data/lib/cuprum/cli/dependencies/standard_io/mock.rb +85 -0
- data/lib/cuprum/cli/dependencies/standard_io.rb +110 -0
- data/lib/cuprum/cli/dependencies/system_command/mock.rb +57 -0
- data/lib/cuprum/cli/dependencies/system_command.rb +147 -0
- data/lib/cuprum/cli/dependencies.rb +25 -0
- data/lib/cuprum/cli/errors/files/file_not_writeable.rb +42 -0
- data/lib/cuprum/cli/errors/files/missing_parameter.rb +71 -0
- data/lib/cuprum/cli/errors/files/missing_template.rb +36 -0
- data/lib/cuprum/cli/errors/files/template_error.rb +37 -0
- data/lib/cuprum/cli/errors/files/template_not_resolved.rb +54 -0
- data/lib/cuprum/cli/errors/files.rb +19 -0
- data/lib/cuprum/cli/errors/system_command_failure.rb +44 -0
- data/lib/cuprum/cli/errors.rb +11 -0
- data/lib/cuprum/cli/integrations/thor/arguments_parser.rb +99 -0
- data/lib/cuprum/cli/integrations/thor/registry.rb +42 -0
- data/lib/cuprum/cli/integrations/thor/task.rb +211 -0
- data/lib/cuprum/cli/integrations/thor.rb +14 -0
- data/lib/cuprum/cli/integrations.rb +8 -0
- data/lib/cuprum/cli/metadata.rb +215 -0
- data/lib/cuprum/cli/option.rb +165 -0
- data/lib/cuprum/cli/options/class_methods.rb +232 -0
- data/lib/cuprum/cli/options/quiet.rb +32 -0
- data/lib/cuprum/cli/options/verbose.rb +32 -0
- data/lib/cuprum/cli/options.rb +18 -0
- data/lib/cuprum/cli/registry.rb +141 -0
- data/lib/cuprum/cli/rspec/deferred/arguments_examples.rb +203 -0
- data/lib/cuprum/cli/rspec/deferred/ci/report_examples.rb +450 -0
- data/lib/cuprum/cli/rspec/deferred/ci.rb +8 -0
- data/lib/cuprum/cli/rspec/deferred/dependencies/file_system_examples.rb +1469 -0
- data/lib/cuprum/cli/rspec/deferred/dependencies.rb +8 -0
- data/lib/cuprum/cli/rspec/deferred/metadata_examples.rb +856 -0
- data/lib/cuprum/cli/rspec/deferred/options_examples.rb +234 -0
- data/lib/cuprum/cli/rspec/deferred/registry_examples.rb +451 -0
- data/lib/cuprum/cli/rspec/deferred.rb +8 -0
- data/lib/cuprum/cli/rspec.rb +8 -0
- data/lib/cuprum/cli/version.rb +59 -0
- data/lib/cuprum/cli.rb +47 -0
- metadata +173 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'stringio'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/cli/dependencies/standard_io'
|
|
6
|
+
|
|
7
|
+
module Cuprum::Cli::Dependencies
|
|
8
|
+
# Mock implementation of StandardIo for testing purposes.
|
|
9
|
+
class StandardIo::Mock < Cuprum::Cli::Dependencies::StandardIo
|
|
10
|
+
# @overload append_for_read(*messages, io:)
|
|
11
|
+
# Utility method for appending readable data to a StringIO stream.
|
|
12
|
+
#
|
|
13
|
+
# @param messages [Array<String>] the messages to append. Will be appended
|
|
14
|
+
# to the stream in the provided order.
|
|
15
|
+
# @param io [IO] the io stream to append.
|
|
16
|
+
#
|
|
17
|
+
# @return [IO] the io stream.
|
|
18
|
+
def self.append_for_read(*messages, io:)
|
|
19
|
+
total_length = 0
|
|
20
|
+
|
|
21
|
+
messages.each do |message|
|
|
22
|
+
message += "\n" unless message.end_with?("\n")
|
|
23
|
+
|
|
24
|
+
io.print(message)
|
|
25
|
+
|
|
26
|
+
total_length += message.length
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
io.pos -= total_length
|
|
30
|
+
|
|
31
|
+
io
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @param error_stream [IO] the error stream. Defaults to an instance of
|
|
35
|
+
# StringIO.
|
|
36
|
+
# @param input_stream [IO] the input stream. Defaults to an instance of
|
|
37
|
+
# StringIO.
|
|
38
|
+
# @param output_stream [IO] the output stream. Defaulst to an instance of
|
|
39
|
+
# StringIO.
|
|
40
|
+
def initialize(
|
|
41
|
+
error_stream: StringIO.new,
|
|
42
|
+
input_stream: StringIO.new,
|
|
43
|
+
output_stream: StringIO.new
|
|
44
|
+
)
|
|
45
|
+
super
|
|
46
|
+
|
|
47
|
+
@combined_stream = StringIO.new
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [IO] a combined input/output stream representing all IO activity.
|
|
51
|
+
attr_reader :combined_stream
|
|
52
|
+
|
|
53
|
+
# @return [IO] the error stream
|
|
54
|
+
def error_stream = super # rubocop:disable Lint/UselessMethodDefinition
|
|
55
|
+
|
|
56
|
+
# @return [IO] the input stream.
|
|
57
|
+
def input_stream = super # rubocop:disable Lint/UselessMethodDefinition
|
|
58
|
+
|
|
59
|
+
# @return [IO] the output stream.
|
|
60
|
+
def output_stream = super # rubocop:disable Lint/UselessMethodDefinition
|
|
61
|
+
|
|
62
|
+
# (see Cuprum::Cli::Dependencies::StandardIo#read_input)
|
|
63
|
+
def read_input
|
|
64
|
+
message = super
|
|
65
|
+
|
|
66
|
+
combined_stream.print(message) if message
|
|
67
|
+
|
|
68
|
+
message
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# (see Cuprum::Cli::Dependencies::StandardIo#write_output)
|
|
72
|
+
def write_output(message = nil, newline: true)
|
|
73
|
+
super
|
|
74
|
+
|
|
75
|
+
newline ? combined_stream.puts(message) : combined_stream.print(message)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# (see Cuprum::Cli::Dependencies::StandardIo#write_error)
|
|
79
|
+
def write_error(message = nil, newline: true)
|
|
80
|
+
super
|
|
81
|
+
|
|
82
|
+
newline ? combined_stream.puts(message) : combined_stream.print(message)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli/dependencies'
|
|
4
|
+
|
|
5
|
+
module Cuprum::Cli::Dependencies
|
|
6
|
+
# Utility wrapping standard input, output, and error IO streams.
|
|
7
|
+
class StandardIo
|
|
8
|
+
autoload :Helpers, 'cuprum/cli/dependencies/standard_io/helpers'
|
|
9
|
+
autoload :Mock, 'cuprum/cli/dependencies/standard_io/mock'
|
|
10
|
+
|
|
11
|
+
ANSI_COLORS = {
|
|
12
|
+
'black' => 0,
|
|
13
|
+
'blue' => 34,
|
|
14
|
+
'green' => 32,
|
|
15
|
+
'purple' => 35,
|
|
16
|
+
'red' => 31,
|
|
17
|
+
'yellow' => 33
|
|
18
|
+
}.freeze
|
|
19
|
+
private_constant :ANSI_COLORS
|
|
20
|
+
|
|
21
|
+
# @param error_stream [IO] the error stream. Defaults to $stderr.
|
|
22
|
+
# @param input_stream [IO] the input stream. Defaults to $stdin.
|
|
23
|
+
# @param output_stream [IO] the output stream. Defaulst to $stdout.
|
|
24
|
+
def initialize(
|
|
25
|
+
error_stream: -> { $stderr },
|
|
26
|
+
input_stream: -> { $stdin },
|
|
27
|
+
output_stream: -> { $stdout }
|
|
28
|
+
)
|
|
29
|
+
@lazy_error_stream = error_stream
|
|
30
|
+
@lazy_input_stream = input_stream
|
|
31
|
+
@lazy_output_stream = output_stream
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Wraps the text in an ANSI color escape code.
|
|
35
|
+
#
|
|
36
|
+
# @param text [String] the text to colorize.
|
|
37
|
+
# @param color [String] the color to apply.
|
|
38
|
+
#
|
|
39
|
+
# @return [String] the colorized string.
|
|
40
|
+
#
|
|
41
|
+
# @raise [KeyError] if the requested color does not have an escape code.
|
|
42
|
+
def color(text, color)
|
|
43
|
+
color_code = ANSI_COLORS.fetch(color.to_s)
|
|
44
|
+
|
|
45
|
+
"\e[#{color_code}m#{text}\e[0m"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Requests a newline-terminated string from the input stream.
|
|
49
|
+
#
|
|
50
|
+
# @return [String] the returned input string.
|
|
51
|
+
def read_input
|
|
52
|
+
input_stream.gets
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Writes the given message to the error stream.
|
|
56
|
+
#
|
|
57
|
+
# If no error message is given, prints a newline only.
|
|
58
|
+
#
|
|
59
|
+
# @param message [String, nil] the message to write.
|
|
60
|
+
# @param newline [true, false] if true, appends a newline to the message if
|
|
61
|
+
# it does not have a newline. Defaults to true.
|
|
62
|
+
#
|
|
63
|
+
# @return [nil]
|
|
64
|
+
def write_error(message = nil, newline: true)
|
|
65
|
+
newline ? error_stream.puts(message) : error_stream.print(message)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Writes the given message to the output stream.
|
|
69
|
+
#
|
|
70
|
+
# If no message is given, prints a newline only.
|
|
71
|
+
#
|
|
72
|
+
# @param message [String, nil] the message to write.
|
|
73
|
+
# @param newline [true, false] if true, appends a newline to the message if
|
|
74
|
+
# it does not have a newline. Defaults to true.
|
|
75
|
+
#
|
|
76
|
+
# @return [nil]
|
|
77
|
+
def write_output(message = nil, newline: true)
|
|
78
|
+
newline ? output_stream.puts(message) : output_stream.print(message)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def error_stream
|
|
84
|
+
@error_stream ||=
|
|
85
|
+
if @lazy_error_stream.is_a?(Proc)
|
|
86
|
+
@lazy_error_stream.call
|
|
87
|
+
else
|
|
88
|
+
@lazy_error_stream
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def input_stream
|
|
93
|
+
@input_stream ||=
|
|
94
|
+
if @lazy_input_stream.is_a?(Proc)
|
|
95
|
+
@lazy_input_stream.call
|
|
96
|
+
else
|
|
97
|
+
@lazy_input_stream
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def output_stream
|
|
102
|
+
@output_stream ||=
|
|
103
|
+
if @lazy_output_stream.is_a?(Proc)
|
|
104
|
+
@lazy_output_stream.call
|
|
105
|
+
else
|
|
106
|
+
@lazy_output_stream
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli/dependencies/system_command'
|
|
4
|
+
|
|
5
|
+
module Cuprum::Cli::Dependencies
|
|
6
|
+
# Mock implementation of SystemCommand for testing purposes.
|
|
7
|
+
class SystemCommand::Mock < Cuprum::Cli::Dependencies::SystemCommand
|
|
8
|
+
# Data class providing a mock implementation of Process::Status.
|
|
9
|
+
MockStatus = Data.define(:exitstatus) do
|
|
10
|
+
# @return [true, false] true if the exit status is zero, otherwise false.
|
|
11
|
+
def success? = exitstatus.zero?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @param captures [Hash{String => Proc, Array[String, String, Integer]}]
|
|
15
|
+
# the captured values to return. If the captures Hash has a key matching
|
|
16
|
+
# the command, that value will be used to generate the result.
|
|
17
|
+
def initialize(captures: {})
|
|
18
|
+
super()
|
|
19
|
+
|
|
20
|
+
@captures = captures
|
|
21
|
+
@recorded_commands = []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [Array<String>] the commands recorded by the mock service.
|
|
25
|
+
attr_reader :recorded_commands
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
attr_reader :captures
|
|
30
|
+
|
|
31
|
+
def capture_command(command, **rest)
|
|
32
|
+
recorded_commands << build_command(command, **rest)
|
|
33
|
+
|
|
34
|
+
output, error, exitstatus =
|
|
35
|
+
captures
|
|
36
|
+
.fetch(command, ['', '', 0])
|
|
37
|
+
.then { |capture| capture.is_a?(Proc) ? capture.call(**rest) : capture }
|
|
38
|
+
|
|
39
|
+
CapturedOutput.new(
|
|
40
|
+
output:,
|
|
41
|
+
error:,
|
|
42
|
+
status: MockStatus.new(exitstatus:)
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def spawn_command(command, **rest)
|
|
47
|
+
recorded_commands << build_command(command, **rest)
|
|
48
|
+
|
|
49
|
+
_, _, exitstatus =
|
|
50
|
+
captures
|
|
51
|
+
.fetch(command, ['', '', 0])
|
|
52
|
+
.then { |capture| capture.is_a?(Proc) ? capture.call(**rest) : capture }
|
|
53
|
+
|
|
54
|
+
MockStatus.new(exitstatus:)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/cli/dependencies'
|
|
6
|
+
require 'cuprum/cli/errors/system_command_failure'
|
|
7
|
+
|
|
8
|
+
module Cuprum::Cli::Dependencies
|
|
9
|
+
# Utility wrapper for running system command and capturing output.
|
|
10
|
+
class SystemCommand
|
|
11
|
+
autoload :Mock, 'cuprum/cli/dependencies/system_command/mock'
|
|
12
|
+
|
|
13
|
+
# Data object representing the captured output and status of a process.
|
|
14
|
+
CapturedOutput = Data.define(:error, :output, :status) do
|
|
15
|
+
# @return [true, false] true if the process was successful, otherwise
|
|
16
|
+
# false.
|
|
17
|
+
def success? = status.success?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @overload capture(command,.arguments: [], environment: {}, options: {})
|
|
21
|
+
# Executes the system command and returns the captured output.
|
|
22
|
+
#
|
|
23
|
+
# @param command [String] the command to run.
|
|
24
|
+
# @param arguments [Array<String>] command-line flags or arguments to pass
|
|
25
|
+
# to the command.
|
|
26
|
+
# @param enviroment [Hash<String, Object>] environment variables to set
|
|
27
|
+
# for the command.
|
|
28
|
+
# @param options [Hash<String, Object>] command line options and values to
|
|
29
|
+
# pass to the command.
|
|
30
|
+
#
|
|
31
|
+
# @return [Cuprum::Result<Cuprum::Cli::Dependencies::SystemCommand::CapturedOutput>]
|
|
32
|
+
# a Result wrapping the process status and captured output. The Result
|
|
33
|
+
# will have a status of :success if the process ran successfully;
|
|
34
|
+
# otherwise, the Result will have a status of :failure
|
|
35
|
+
def capture(command, **)
|
|
36
|
+
value = capture_command(command, **)
|
|
37
|
+
|
|
38
|
+
return Cuprum::Result.new(value:) if value.success?
|
|
39
|
+
|
|
40
|
+
error = Cuprum::Cli::Errors::SystemCommandFailure.new(
|
|
41
|
+
command:,
|
|
42
|
+
details: value.error,
|
|
43
|
+
exit_status: value.status.exitstatus
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
Cuprum::Result.new(error:, value:)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @overload spawn(command, arguments: [], enviroment:, options: {})
|
|
50
|
+
# Spawns a process to run the system command.
|
|
51
|
+
#
|
|
52
|
+
# @param command [String] the command to run.
|
|
53
|
+
# @param arguments [Array<String>] command-line flags or arguments to pass
|
|
54
|
+
# to the command.
|
|
55
|
+
# @param enviroment [Hash<String, Object>] environment variables to set
|
|
56
|
+
# for the command.
|
|
57
|
+
# @param options [Hash<String, Object>] command line options and values to
|
|
58
|
+
# pass to the command.
|
|
59
|
+
#
|
|
60
|
+
# @return [Cuprum::Result<nil>] a result with status :success if the
|
|
61
|
+
# process ran successfully; otherwise, a result with status :failure and
|
|
62
|
+
# an Error.
|
|
63
|
+
def spawn(command, **)
|
|
64
|
+
status = spawn_command(command, **)
|
|
65
|
+
|
|
66
|
+
return Cuprum::Result.new if status.success?
|
|
67
|
+
|
|
68
|
+
error = Cuprum::Cli::Errors::SystemCommandFailure.new(
|
|
69
|
+
command:,
|
|
70
|
+
exit_status: status.exitstatus
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
Cuprum::Result.new(error:)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def blank?(value)
|
|
79
|
+
value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def build_command(command, arguments: nil, environment: nil, options: nil)
|
|
83
|
+
# @todo [RUBY_VERSION <= '3.3'] remove || {} fallbacks.
|
|
84
|
+
[
|
|
85
|
+
format_environment(**(environment || {})),
|
|
86
|
+
command,
|
|
87
|
+
format_arguments(*arguments),
|
|
88
|
+
format_options(**(options || {}))
|
|
89
|
+
]
|
|
90
|
+
.reject { |value| value.nil? || value.empty? }
|
|
91
|
+
.join(' ')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def capture_command(command, **)
|
|
95
|
+
command = build_command(command, **)
|
|
96
|
+
|
|
97
|
+
output, error, status = Open3.capture3(command)
|
|
98
|
+
|
|
99
|
+
CapturedOutput.new(output:, error:, status:)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def format_arguments(*arguments)
|
|
103
|
+
arguments.join(' ')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def format_environment(**environment)
|
|
107
|
+
environment
|
|
108
|
+
.reject { |_, value| blank?(value) }
|
|
109
|
+
.map do |key, value|
|
|
110
|
+
key = tools.string_tools.underscore(key.to_s).upcase
|
|
111
|
+
|
|
112
|
+
"#{key}=#{value.inspect}"
|
|
113
|
+
end
|
|
114
|
+
.join(' ')
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def format_options(**options) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
118
|
+
options
|
|
119
|
+
.reject { |_, value| blank?(value) }
|
|
120
|
+
.map do |key, value|
|
|
121
|
+
next if value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
|
122
|
+
|
|
123
|
+
key = key.to_s
|
|
124
|
+
value = value.inspect
|
|
125
|
+
|
|
126
|
+
next "#{key}=#{value}" if key.start_with?('-')
|
|
127
|
+
|
|
128
|
+
key = tools.string_tools.underscore(key).tr('_', '-')
|
|
129
|
+
|
|
130
|
+
"#{key.length == 1 ? '-' : '--'}#{key}=#{value}"
|
|
131
|
+
end
|
|
132
|
+
.join(' ')
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def spawn_command(command, **)
|
|
136
|
+
command = build_command(command, **)
|
|
137
|
+
pid = Process.spawn(command)
|
|
138
|
+
_, status = Process.wait2(pid)
|
|
139
|
+
|
|
140
|
+
status
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def tools
|
|
144
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'plumbum'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/cli'
|
|
6
|
+
|
|
7
|
+
module Cuprum::Cli
|
|
8
|
+
# Dependencies provide standard functionality to commands.
|
|
9
|
+
module Dependencies
|
|
10
|
+
autoload :FileSystem, 'cuprum/cli/dependencies/file_system'
|
|
11
|
+
autoload :StandardIo, 'cuprum/cli/dependencies/standard_io'
|
|
12
|
+
autoload :SystemCommand, 'cuprum/cli/dependencies/system_command'
|
|
13
|
+
|
|
14
|
+
# @return [Plumbum::Provider] the provider for the standard dependencies.
|
|
15
|
+
def self.provider
|
|
16
|
+
@provider ||= Plumbum::ManyProvider.new(
|
|
17
|
+
values: {
|
|
18
|
+
file_system: FileSystem.new,
|
|
19
|
+
standard_io: StandardIo.new,
|
|
20
|
+
system_command: SystemCommand.new
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/error'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/cli/errors/files'
|
|
6
|
+
|
|
7
|
+
module Cuprum::Cli::Errors::Files
|
|
8
|
+
# Error returned when attempting to generate a file in an invalid location.
|
|
9
|
+
class FileNotWriteable < Cuprum::Error
|
|
10
|
+
# Short string used to identify the type of error.
|
|
11
|
+
TYPE = 'cuprum.cli.errors.files.file_not_writeable'
|
|
12
|
+
|
|
13
|
+
# @param file_path [String] the path to the expected file.
|
|
14
|
+
# @param message [String] message describing the nature of the error.
|
|
15
|
+
# @param reason [String] additional details on the error.
|
|
16
|
+
def initialize(file_path:, message: nil, reason: nil)
|
|
17
|
+
@file_path = file_path
|
|
18
|
+
@reason = reason
|
|
19
|
+
message = default_message(file_path:, message:, reason:)
|
|
20
|
+
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [String] the path to the expected file.
|
|
25
|
+
attr_reader :file_path
|
|
26
|
+
|
|
27
|
+
# @return [String] additional details on the error.
|
|
28
|
+
attr_reader :reason
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def as_json_data = { 'file_path' => file_path, 'reason' => reason }.compact
|
|
33
|
+
|
|
34
|
+
def default_message(file_path:, message:, reason:)
|
|
35
|
+
message ||= "unable to write file #{file_path}"
|
|
36
|
+
|
|
37
|
+
return message unless reason
|
|
38
|
+
|
|
39
|
+
"#{message} - #{reason}"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli/errors/files'
|
|
4
|
+
require 'cuprum/cli/errors/files/template_error'
|
|
5
|
+
|
|
6
|
+
module Cuprum::Cli::Errors::Files
|
|
7
|
+
# Error returned when a required parameter is missing when rendering content.
|
|
8
|
+
class MissingParameter < Cuprum::Cli::Errors::Files::TemplateError
|
|
9
|
+
# Short string used to identify the type of error.
|
|
10
|
+
TYPE = 'cuprum.cli.errors.files.missing_parameter'
|
|
11
|
+
|
|
12
|
+
# @param parameter_name [String, Symbol] the name of the missing parameter.
|
|
13
|
+
# @param details [String] additional information about the error.
|
|
14
|
+
# @param format [String] the content format.
|
|
15
|
+
# @param message [String] an optional message to display.
|
|
16
|
+
# @param template_name [String] the name of the rendered content, if any,
|
|
17
|
+
def initialize(
|
|
18
|
+
parameter_name:,
|
|
19
|
+
details: nil,
|
|
20
|
+
format: nil,
|
|
21
|
+
message: nil,
|
|
22
|
+
template_name: nil
|
|
23
|
+
)
|
|
24
|
+
@parameter_name = parameter_name
|
|
25
|
+
@format = format
|
|
26
|
+
@template_name = template_name
|
|
27
|
+
|
|
28
|
+
super(
|
|
29
|
+
details:,
|
|
30
|
+
format:,
|
|
31
|
+
message: default_message(message),
|
|
32
|
+
parameter_name:,
|
|
33
|
+
template_name:
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @return [String] the content format.
|
|
38
|
+
attr_reader :format
|
|
39
|
+
|
|
40
|
+
# @return [String, Symbol] the name of the missing parameter.
|
|
41
|
+
attr_reader :parameter_name
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def as_json_data
|
|
46
|
+
super.merge(
|
|
47
|
+
'format' => format,
|
|
48
|
+
'parameter_name' => parameter_name.to_s
|
|
49
|
+
).compact
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def default_message(message)
|
|
53
|
+
str = "missing parameter #{parameter_name.inspect}"
|
|
54
|
+
|
|
55
|
+
if template_name?
|
|
56
|
+
str = "#{str} for template #{template_name}"
|
|
57
|
+
str = "#{str} with format #{format}" if format?
|
|
58
|
+
elsif format?
|
|
59
|
+
str = "#{str} for #{format} template"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
return str unless message && !message.empty?
|
|
63
|
+
|
|
64
|
+
"#{message} - #{str}"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def format? = format && !format.empty?
|
|
68
|
+
|
|
69
|
+
def template_name? = template_name && !template_name.empty?
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/error'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/cli/errors/files'
|
|
6
|
+
|
|
7
|
+
module Cuprum::Cli::Errors::Files
|
|
8
|
+
# Error returned when unable to load a template.
|
|
9
|
+
class MissingTemplate < Cuprum::Error
|
|
10
|
+
# Short string used to identify the type of error.
|
|
11
|
+
TYPE = 'cuprum.cli.errors.files.missing_template'
|
|
12
|
+
|
|
13
|
+
# @param template_path [String] the expected template path.
|
|
14
|
+
# @param message [String] an optional message to display.
|
|
15
|
+
def initialize(template_path:, message: nil)
|
|
16
|
+
@template_path = template_path
|
|
17
|
+
|
|
18
|
+
super(message: default_message(message), template_path:)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [String] the expected template path.
|
|
22
|
+
attr_reader :template_path
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def as_json_data = { 'template_path' => template_path }
|
|
27
|
+
|
|
28
|
+
def default_message(message)
|
|
29
|
+
str = "unable to load template #{template_path}"
|
|
30
|
+
|
|
31
|
+
return str unless message && !message.empty?
|
|
32
|
+
|
|
33
|
+
"#{message} - #{str}"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/error'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/cli/errors/files'
|
|
6
|
+
|
|
7
|
+
module Cuprum::Cli::Errors::Files
|
|
8
|
+
# Error returned when an error occurs when generating templated content.
|
|
9
|
+
class TemplateError < Cuprum::Error
|
|
10
|
+
# Short string used to identify the type of error.
|
|
11
|
+
TYPE = 'cuprum.cli.errors.files.template_error'
|
|
12
|
+
|
|
13
|
+
# @param message [String] message describing the nature of the error.
|
|
14
|
+
# @param details [String] additional information about the error.
|
|
15
|
+
# @param template_name [String] the name of the rendered content, if any,
|
|
16
|
+
def initialize(message:, details: nil, template_name: nil, **)
|
|
17
|
+
@details = details
|
|
18
|
+
@template_name = template_name
|
|
19
|
+
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @return [String] additional information about the error.
|
|
24
|
+
attr_reader :details
|
|
25
|
+
|
|
26
|
+
# @return [String] the name of the rendered content, if any,
|
|
27
|
+
attr_reader :template_name
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def as_json_data
|
|
32
|
+
super
|
|
33
|
+
.merge('details' => details, 'template_name' => template_name)
|
|
34
|
+
.compact
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli/errors/files'
|
|
4
|
+
require 'cuprum/cli/errors/files/template_error'
|
|
5
|
+
|
|
6
|
+
module Cuprum::Cli::Errors::Files
|
|
7
|
+
# Error returned when unable to resolve a template for a templated file.
|
|
8
|
+
class TemplateNotResolved < Cuprum::Cli::Errors::Files::TemplateError
|
|
9
|
+
# Short string used to identify the type of error.
|
|
10
|
+
TYPE = 'cuprum.cli.errors.files.template_not_resolved'
|
|
11
|
+
|
|
12
|
+
# @param file_path [String] the file path for the templated file.
|
|
13
|
+
# @param details [String] additional information about the error.
|
|
14
|
+
# @param message [String] an optional message to display.
|
|
15
|
+
# @param options [Hash] options used when attempting to resolve the
|
|
16
|
+
# template.
|
|
17
|
+
def initialize(file_path:, details: nil, message: nil, options: {})
|
|
18
|
+
@file_path = file_path
|
|
19
|
+
@options = options
|
|
20
|
+
|
|
21
|
+
super(details:, file_path:, message: default_message(message), options:)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [String] the file path for the templated file.
|
|
25
|
+
attr_reader :file_path
|
|
26
|
+
|
|
27
|
+
# @return [Hash] options used when attempting to resolve the template.
|
|
28
|
+
attr_reader :options
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def as_json_data
|
|
33
|
+
hsh = super
|
|
34
|
+
|
|
35
|
+
hsh['file_path'] = file_path
|
|
36
|
+
hsh['options'] = options.transform_keys(&:to_s) unless options.empty?
|
|
37
|
+
|
|
38
|
+
hsh
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def default_message(message)
|
|
42
|
+
str = "unable to resolve template for file #{file_path}"
|
|
43
|
+
str = "#{str} with options" unless options.empty?
|
|
44
|
+
|
|
45
|
+
options.each.with_index do |(key, value), index|
|
|
46
|
+
str += "#{',' unless index.zero?} #{key}: #{value.inspect}"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
return str unless message && !message.empty?
|
|
50
|
+
|
|
51
|
+
"#{str} - #{message}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli/errors'
|
|
4
|
+
|
|
5
|
+
module Cuprum::Cli::Errors
|
|
6
|
+
# Namespace for errors returned when creating or managing files.
|
|
7
|
+
module Files
|
|
8
|
+
autoload :FileNotWriteable,
|
|
9
|
+
'cuprum/cli/errors/files/file_not_writeable'
|
|
10
|
+
autoload :MissingParameter,
|
|
11
|
+
'cuprum/cli/errors/files/missing_parameter'
|
|
12
|
+
autoload :MissingTemplate,
|
|
13
|
+
'cuprum/cli/errors/files/missing_template'
|
|
14
|
+
autoload :TemplateError,
|
|
15
|
+
'cuprum/cli/errors/files/template_error'
|
|
16
|
+
autoload :TemplateNotResolved,
|
|
17
|
+
'cuprum/cli/errors/files/template_not_resolved'
|
|
18
|
+
end
|
|
19
|
+
end
|