makit 0.0.112 → 0.0.126
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 +4 -4
- data/README.md +41 -41
- data/exe/makit +5 -5
- data/lib/makit/apache.rb +28 -28
- data/lib/makit/cli/build_commands.rb +500 -500
- data/lib/makit/cli/generators/base_generator.rb +74 -74
- data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
- data/lib/makit/cli/generators/generator_factory.rb +49 -49
- data/lib/makit/cli/generators/node_generator.rb +50 -50
- data/lib/makit/cli/generators/ruby_generator.rb +77 -77
- data/lib/makit/cli/generators/rust_generator.rb +50 -50
- data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
- data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
- data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
- data/lib/makit/cli/generators/templates/ruby/gemspec.rb +40 -40
- data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
- data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
- data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
- data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
- data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
- data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
- data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
- data/lib/makit/cli/main.rb +62 -62
- data/lib/makit/cli/project_commands.rb +868 -868
- data/lib/makit/cli/repository_commands.rb +661 -661
- data/lib/makit/cli/utility_commands.rb +521 -521
- data/lib/makit/commands/factory.rb +359 -359
- data/lib/makit/commands/middleware/base.rb +73 -73
- data/lib/makit/commands/middleware/cache.rb +248 -248
- data/lib/makit/commands/middleware/command_logger.rb +311 -320
- data/lib/makit/commands/middleware/validator.rb +269 -269
- data/lib/makit/commands/request.rb +316 -254
- data/lib/makit/commands/result.rb +323 -323
- data/lib/makit/commands/runner.rb +368 -337
- data/lib/makit/commands/strategies/base.rb +171 -160
- data/lib/makit/commands/strategies/synchronous.rb +139 -134
- data/lib/makit/commands.rb +50 -51
- data/lib/makit/configuration/gitlab_helper.rb +58 -60
- data/lib/makit/configuration/project.rb +167 -127
- data/lib/makit/configuration/rakefile_helper.rb +43 -43
- data/lib/makit/configuration/step.rb +34 -34
- data/lib/makit/configuration.rb +14 -14
- data/lib/makit/content/default_gitignore.rb +7 -7
- data/lib/makit/content/default_gitignore.txt +226 -0
- data/lib/makit/content/default_rakefile.rb +13 -13
- data/lib/makit/content/gem_rakefile.rb +16 -16
- data/lib/makit/context.rb +1 -1
- data/lib/makit/data.rb +49 -49
- data/lib/makit/directories.rb +140 -141
- data/lib/makit/directory.rb +262 -262
- data/lib/makit/docs/files.rb +89 -89
- data/lib/makit/docs/rake.rb +102 -102
- data/lib/makit/dotnet/cli.rb +69 -65
- data/lib/makit/dotnet/project.rb +217 -153
- data/lib/makit/dotnet/solution.rb +38 -38
- data/lib/makit/dotnet/solution_classlib.rb +239 -239
- data/lib/makit/dotnet/solution_console.rb +264 -264
- data/lib/makit/dotnet/solution_maui.rb +354 -354
- data/lib/makit/dotnet/solution_wasm.rb +275 -275
- data/lib/makit/dotnet/solution_wpf.rb +304 -304
- data/lib/makit/dotnet.rb +102 -102
- data/lib/makit/email.rb +90 -90
- data/lib/makit/environment.rb +142 -142
- data/lib/makit/examples/runner.rb +370 -370
- data/lib/makit/exceptions.rb +45 -45
- data/lib/makit/fileinfo.rb +24 -24
- data/lib/makit/files.rb +43 -43
- data/lib/makit/gems.rb +40 -40
- data/lib/makit/git/cli.rb +54 -54
- data/lib/makit/git/repository.rb +90 -90
- data/lib/makit/git.rb +98 -98
- data/lib/makit/gitlab_runner.rb +59 -59
- data/lib/makit/humanize.rb +137 -137
- data/lib/makit/indexer.rb +47 -47
- data/lib/makit/logging/configuration.rb +308 -305
- data/lib/makit/logging/format_registry.rb +84 -84
- data/lib/makit/logging/formatters/base.rb +39 -39
- data/lib/makit/logging/formatters/console_formatter.rb +140 -140
- data/lib/makit/logging/formatters/json_formatter.rb +65 -65
- data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
- data/lib/makit/logging/formatters/text_formatter.rb +64 -64
- data/lib/makit/logging/log_request.rb +119 -115
- data/lib/makit/logging/logger.rb +199 -163
- data/lib/makit/logging/sinks/base.rb +91 -91
- data/lib/makit/logging/sinks/console.rb +72 -72
- data/lib/makit/logging/sinks/file_sink.rb +92 -92
- data/lib/makit/logging/sinks/structured.rb +123 -129
- data/lib/makit/logging/sinks/unified_file_sink.rb +296 -303
- data/lib/makit/logging.rb +565 -530
- data/lib/makit/markdown.rb +75 -75
- data/lib/makit/mp/basic_object_mp.rb +17 -17
- data/lib/makit/mp/command_mp.rb +13 -13
- data/lib/makit/mp/command_request.mp.rb +17 -17
- data/lib/makit/mp/project_mp.rb +199 -199
- data/lib/makit/mp/string_mp.rb +191 -193
- data/lib/makit/nuget.rb +74 -74
- data/lib/makit/port.rb +32 -32
- data/lib/makit/process.rb +163 -163
- data/lib/makit/protoc.rb +107 -107
- data/lib/makit/rake/cli.rb +196 -196
- data/lib/makit/rake.rb +25 -25
- data/lib/makit/ruby/cli.rb +185 -185
- data/lib/makit/ruby.rb +25 -25
- data/lib/makit/secrets.rb +51 -51
- data/lib/makit/serializer.rb +130 -130
- data/lib/makit/services/builder.rb +186 -186
- data/lib/makit/services/error_handler.rb +226 -226
- data/lib/makit/services/repository_manager.rb +231 -229
- data/lib/makit/services/validator.rb +112 -112
- data/lib/makit/setup/classlib.rb +90 -53
- data/lib/makit/setup/gem.rb +268 -263
- data/lib/makit/setup/razorclasslib.rb +91 -0
- data/lib/makit/setup/runner.rb +54 -45
- data/lib/makit/setup.rb +5 -5
- data/lib/makit/show.rb +110 -110
- data/lib/makit/storage.rb +126 -126
- data/lib/makit/symbols.rb +170 -170
- data/lib/makit/task_info.rb +128 -128
- data/lib/makit/tasks/at_exit.rb +15 -13
- data/lib/makit/tasks/build.rb +22 -19
- data/lib/makit/tasks/clean.rb +13 -11
- data/lib/makit/tasks/configure.rb +10 -0
- data/lib/makit/tasks/format.rb +10 -0
- data/lib/makit/tasks/hook_manager.rb +391 -393
- data/lib/makit/tasks/init.rb +49 -47
- data/lib/makit/tasks/integrate.rb +29 -17
- data/lib/makit/tasks/pull_incoming.rb +13 -11
- data/lib/makit/tasks/setup.rb +13 -6
- data/lib/makit/tasks/sync.rb +17 -12
- data/lib/makit/tasks/tag.rb +16 -15
- data/lib/makit/tasks/task_monkey_patch.rb +81 -79
- data/lib/makit/tasks/test.rb +22 -0
- data/lib/makit/tasks/update.rb +18 -0
- data/lib/makit/tasks.rb +20 -15
- data/lib/makit/test_cache.rb +239 -239
- data/lib/makit/tree.rb +37 -37
- data/lib/makit/v1/makit.v1_pb.rb +35 -34
- data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
- data/lib/makit/version.rb +5 -5
- data/lib/makit/version_util.rb +21 -21
- data/lib/makit/wix.rb +95 -95
- data/lib/makit/yaml.rb +29 -29
- data/lib/makit/zip.rb +17 -17
- data/lib/makit copy.rb +44 -44
- data/lib/makit.rb +39 -40
- metadata +69 -7
- data/lib/makit/commands/middleware/unified_logger.rb +0 -243
@@ -1,254 +1,316 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "shellwords"
|
4
|
-
require "json"
|
5
|
-
|
6
|
-
module Makit
|
7
|
-
module Commands
|
8
|
-
# Enhanced request handling with validation and type safety.
|
9
|
-
# Uses plain Ruby objects - no protobuf dependency for better performance.
|
10
|
-
#
|
11
|
-
# @example Create a simple request
|
12
|
-
# request = Request.new(command: "git", arguments: ["--version"])
|
13
|
-
#
|
14
|
-
# @example Create request from string
|
15
|
-
# request = Request.from_string("git clone https://github.com/user/repo.git")
|
16
|
-
#
|
17
|
-
# @example Create request with full options
|
18
|
-
# request = Request.new(
|
19
|
-
# command: "bundle",
|
20
|
-
# arguments: ["install"],
|
21
|
-
# directory: "/path/to/project",
|
22
|
-
# environment: { "BUNDLE_JOBS" => "4" },
|
23
|
-
# timeout: 300,
|
24
|
-
# metadata: { operation: "dependency_install" }
|
25
|
-
# )
|
26
|
-
class Request
|
27
|
-
# Command execution request with validation and metadata.
|
28
|
-
#
|
29
|
-
# @!attribute [r] command
|
30
|
-
# @return [String] the command to execute
|
31
|
-
# @!attribute [r] arguments
|
32
|
-
# @return [Array<String>] command line arguments
|
33
|
-
# @!attribute [r] environment
|
34
|
-
# @return [Hash<String,String>] environment variables
|
35
|
-
# @!attribute [r] directory
|
36
|
-
# @return [String] working directory for execution
|
37
|
-
# @!attribute [r] timeout
|
38
|
-
# @return [Integer] timeout in seconds
|
39
|
-
# @!attribute [r] metadata
|
40
|
-
# @return [Hash] additional metadata for logging/tracking
|
41
|
-
attr_reader :command, :arguments, :environment, :directory, :timeout, :metadata
|
42
|
-
|
43
|
-
|
44
|
-
#
|
45
|
-
#
|
46
|
-
# @param
|
47
|
-
# @param
|
48
|
-
# @param
|
49
|
-
# @param
|
50
|
-
# @param
|
51
|
-
# @
|
52
|
-
|
53
|
-
|
54
|
-
@
|
55
|
-
@
|
56
|
-
@
|
57
|
-
@
|
58
|
-
@
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
#
|
95
|
-
#
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
#
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
#
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
end
|
163
|
-
|
164
|
-
#
|
165
|
-
#
|
166
|
-
# @
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
#
|
178
|
-
#
|
179
|
-
# @
|
180
|
-
def
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
#
|
219
|
-
#
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
#
|
238
|
-
#
|
239
|
-
# @param
|
240
|
-
# @return [
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shellwords"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module Makit
|
7
|
+
module Commands
|
8
|
+
# Enhanced request handling with validation and type safety.
|
9
|
+
# Uses plain Ruby objects - no protobuf dependency for better performance.
|
10
|
+
#
|
11
|
+
# @example Create a simple request
|
12
|
+
# request = Request.new(command: "git", arguments: ["--version"])
|
13
|
+
#
|
14
|
+
# @example Create request from string
|
15
|
+
# request = Request.from_string("git clone https://github.com/user/repo.git")
|
16
|
+
#
|
17
|
+
# @example Create request with full options
|
18
|
+
# request = Request.new(
|
19
|
+
# command: "bundle",
|
20
|
+
# arguments: ["install"],
|
21
|
+
# directory: "/path/to/project",
|
22
|
+
# environment: { "BUNDLE_JOBS" => "4" },
|
23
|
+
# timeout: 300,
|
24
|
+
# metadata: { operation: "dependency_install" }
|
25
|
+
# )
|
26
|
+
class Request
|
27
|
+
# Command execution request with validation and metadata.
|
28
|
+
#
|
29
|
+
# @!attribute [r] command
|
30
|
+
# @return [String] the command to execute
|
31
|
+
# @!attribute [r] arguments
|
32
|
+
# @return [Array<String>] command line arguments
|
33
|
+
# @!attribute [r] environment
|
34
|
+
# @return [Hash<String,String>] environment variables
|
35
|
+
# @!attribute [r] directory
|
36
|
+
# @return [String] working directory for execution
|
37
|
+
# @!attribute [r] timeout
|
38
|
+
# @return [Integer] timeout in seconds
|
39
|
+
# @!attribute [r] metadata
|
40
|
+
# @return [Hash] additional metadata for logging/tracking
|
41
|
+
attr_reader :command, :arguments, :environment, :directory, :timeout, :metadata
|
42
|
+
attr_writer :exit_on_failure, :show_stderr, :show_stdout
|
43
|
+
|
44
|
+
# Initialize a new command request.
|
45
|
+
#
|
46
|
+
# @param command [String] the command to execute
|
47
|
+
# @param arguments [Array<String>] command arguments
|
48
|
+
# @param environment [Hash<String,String>] environment variables
|
49
|
+
# @param directory [String] working directory
|
50
|
+
# @param timeout [Integer] timeout in seconds
|
51
|
+
# @param metadata [Hash] additional metadata
|
52
|
+
# @raise [ArgumentError] if command is invalid
|
53
|
+
def initialize(command:, arguments: [], **options)
|
54
|
+
@command = validate_command(command)
|
55
|
+
@arguments = validate_arguments(arguments)
|
56
|
+
@environment = options[:environment] || {}
|
57
|
+
@directory = options[:directory] || Dir.pwd
|
58
|
+
@timeout = options[:timeout] || 30
|
59
|
+
@metadata = options[:metadata] || {}
|
60
|
+
@exit_on_failure = options[:exit_on_failure] || true
|
61
|
+
@show_stderr = options[:show_stderr] || true
|
62
|
+
@show_stdout = options[:show_stdout] || false
|
63
|
+
validate_directory(@directory)
|
64
|
+
validate_timeout(@timeout)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Convert request to shell-executable command string.
|
68
|
+
#
|
69
|
+
# @return [String] shell command string
|
70
|
+
def to_shell_command
|
71
|
+
cmd_parts = [command] + arguments
|
72
|
+
Shellwords.join(cmd_parts)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Convert request to hash representation.
|
76
|
+
#
|
77
|
+
# @return [Hash] hash representation of the request
|
78
|
+
def to_h
|
79
|
+
{
|
80
|
+
command: command,
|
81
|
+
arguments: arguments,
|
82
|
+
environment: environment,
|
83
|
+
directory: directory,
|
84
|
+
timeout: timeout,
|
85
|
+
metadata: metadata,
|
86
|
+
exit_on_failure: exit_on_failure?,
|
87
|
+
show_stderr: show_stderr?,
|
88
|
+
show_stdout: show_stdout?,
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
# Convert request to JSON representation.
|
93
|
+
#
|
94
|
+
# @param args [Array] arguments passed to JSON.generate
|
95
|
+
# @return [String] JSON representation
|
96
|
+
def to_json(*args)
|
97
|
+
JSON.generate(to_h, *args)
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_json_pretty(*args)
|
101
|
+
JSON.pretty_generate(to_h, *args)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Create a request from a shell command string.
|
105
|
+
#
|
106
|
+
# @param command_string [String] shell command string to parse
|
107
|
+
# @param options [Hash] additional options
|
108
|
+
# @return [Request] new request object
|
109
|
+
# @raise [ArgumentError] if command string is invalid
|
110
|
+
# @example
|
111
|
+
# Request.from_string("git clone https://github.com/user/repo.git")
|
112
|
+
# Request.from_string("bundle install --jobs 4")
|
113
|
+
def self.from_string(command_string, **options)
|
114
|
+
raise ArgumentError, "Command string cannot be empty" if command_string.nil? || command_string.strip.empty?
|
115
|
+
|
116
|
+
# Parse shell command string into command and arguments
|
117
|
+
parts = Shellwords.split(command_string.strip)
|
118
|
+
command = parts.shift
|
119
|
+
arguments = parts
|
120
|
+
|
121
|
+
new(command: command, arguments: arguments, **options)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Create a request from hash representation.
|
125
|
+
#
|
126
|
+
# @param command_hash [Hash] hash containing command information
|
127
|
+
# @return [Request] new request object
|
128
|
+
# @raise [ArgumentError] if hash is invalid
|
129
|
+
# @example
|
130
|
+
# Request.from_hash({
|
131
|
+
# "command" => "git",
|
132
|
+
# "arguments" => ["clone", "https://github.com/user/repo.git"],
|
133
|
+
# "timeout" => 300
|
134
|
+
# })
|
135
|
+
def self.from_hash(command_hash)
|
136
|
+
raise ArgumentError, "Command hash cannot be nil" if command_hash.nil?
|
137
|
+
|
138
|
+
# Convert string keys to symbols for consistency
|
139
|
+
hash = command_hash.is_a?(Hash) ? normalize_hash_keys(command_hash) : command_hash
|
140
|
+
|
141
|
+
new(
|
142
|
+
command: hash[:command] || hash["command"],
|
143
|
+
arguments: hash[:arguments] || hash["arguments"] || [],
|
144
|
+
environment: hash[:environment] || hash["environment"] || {},
|
145
|
+
directory: hash[:directory] || hash["directory"],
|
146
|
+
timeout: hash[:timeout] || hash["timeout"],
|
147
|
+
metadata: hash[:metadata] || hash["metadata"] || {},
|
148
|
+
exit_on_failure: hash[:exit_on_failure] || hash["exit_on_failure"],
|
149
|
+
show_stderr: hash[:show_stderr] || hash["show_stderr"],
|
150
|
+
show_stdout: hash[:show_stdout] || hash["show_stdout"],
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Create a request from JSON string.
|
155
|
+
#
|
156
|
+
# @param json_string [String] JSON string representation
|
157
|
+
# @return [Request] new request object
|
158
|
+
# @raise [JSON::ParserError, ArgumentError] if JSON is invalid
|
159
|
+
def self.from_json(json_string)
|
160
|
+
hash = JSON.parse(json_string)
|
161
|
+
from_hash(hash)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Check if this request represents the same command.
|
165
|
+
#
|
166
|
+
# @param other [Request] another request to compare
|
167
|
+
# @return [Boolean] true if commands are equivalent
|
168
|
+
def equivalent_to?(other)
|
169
|
+
return false unless other.is_a?(Request)
|
170
|
+
|
171
|
+
command == other.command &&
|
172
|
+
arguments == other.arguments &&
|
173
|
+
environment == other.environment &&
|
174
|
+
directory == other.directory
|
175
|
+
end
|
176
|
+
|
177
|
+
# Generate a cache key for this request.
|
178
|
+
#
|
179
|
+
# @return [String] cache key based on command, arguments, and context
|
180
|
+
def cache_key
|
181
|
+
require "digest"
|
182
|
+
content = "#{command}:#{arguments.join(":")}:#{directory}"
|
183
|
+
Digest::SHA256.hexdigest(content)[0..16]
|
184
|
+
end
|
185
|
+
|
186
|
+
def exit_on_failure?
|
187
|
+
@exit_on_failure
|
188
|
+
end
|
189
|
+
|
190
|
+
def exit_on_failure(exit_on_failure)
|
191
|
+
@exit_on_failure = exit_on_failure
|
192
|
+
self
|
193
|
+
end
|
194
|
+
|
195
|
+
def show_stderr?
|
196
|
+
@show_stderr
|
197
|
+
end
|
198
|
+
|
199
|
+
def show_stderr(show_stderr)
|
200
|
+
@show_stderr = show_stderr
|
201
|
+
self
|
202
|
+
end
|
203
|
+
|
204
|
+
def show_stdout?
|
205
|
+
@show_stdout
|
206
|
+
end
|
207
|
+
|
208
|
+
def show_stdout(show_stdout)
|
209
|
+
@show_stdout = show_stdout
|
210
|
+
self
|
211
|
+
end
|
212
|
+
|
213
|
+
# Execute the command.
|
214
|
+
#
|
215
|
+
# @return [Result] execution result
|
216
|
+
# @raise [ArgumentError] if runner is not set
|
217
|
+
def run
|
218
|
+
# self.exit_on_failure = exit_on_failure
|
219
|
+
# self.show_stderr = true
|
220
|
+
result = Makit::Commands::Runner.default.execute(show_stderr(true))
|
221
|
+
|
222
|
+
# Display stderr if the command failed and show_stderr is enabled
|
223
|
+
puts result.stderr if result.failure? && show_stderr? && !result.stderr.empty?
|
224
|
+
|
225
|
+
# Exit with the command's exit code if it failed and exit_on_failure is enabled
|
226
|
+
exit result.exit_code if result.failure? && exit_on_failure?
|
227
|
+
|
228
|
+
result
|
229
|
+
end
|
230
|
+
|
231
|
+
def try
|
232
|
+
Makit::Commands::Runner.default.execute(exit_on_failure(false))
|
233
|
+
end
|
234
|
+
|
235
|
+
private
|
236
|
+
|
237
|
+
# Validate command parameter.
|
238
|
+
#
|
239
|
+
# @param command [String] command to validate
|
240
|
+
# @return [String] validated command
|
241
|
+
# @raise [ArgumentError] if command is invalid
|
242
|
+
def validate_command(command)
|
243
|
+
raise ArgumentError, "Command cannot be nil" if command.nil?
|
244
|
+
raise ArgumentError, "Command cannot be empty" if command.strip.empty?
|
245
|
+
|
246
|
+
cmd = command.strip
|
247
|
+
|
248
|
+
# Check for dangerous characters that could indicate command injection
|
249
|
+
raise ArgumentError, "Command contains potentially dangerous characters" if cmd.match?(/[;&|`$(){}]/)
|
250
|
+
|
251
|
+
cmd
|
252
|
+
end
|
253
|
+
|
254
|
+
# Validate arguments array.
|
255
|
+
#
|
256
|
+
# @param arguments [Array] arguments to validate
|
257
|
+
# @return [Array<String>] validated arguments
|
258
|
+
# @raise [ArgumentError] if arguments are invalid
|
259
|
+
def validate_arguments(arguments)
|
260
|
+
return [] if arguments.nil?
|
261
|
+
raise ArgumentError, "Arguments must be an array" unless arguments.is_a?(Array)
|
262
|
+
|
263
|
+
# Convert all arguments to strings and validate
|
264
|
+
arguments.map do |arg|
|
265
|
+
raise ArgumentError, "Argument cannot be nil" if arg.nil?
|
266
|
+
|
267
|
+
arg.to_s
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Validate directory parameter.
|
272
|
+
#
|
273
|
+
# @param directory [String] directory to validate
|
274
|
+
# @raise [ArgumentError] if directory is invalid
|
275
|
+
def validate_directory(directory)
|
276
|
+
return unless directory
|
277
|
+
|
278
|
+
raise ArgumentError, "Directory must be a string" unless directory.is_a?(String)
|
279
|
+
|
280
|
+
# NOTE: We don't validate directory existence here as it might be created later
|
281
|
+
# We just validate it's a reasonable path format
|
282
|
+
return unless directory.include?("\0")
|
283
|
+
|
284
|
+
raise ArgumentError, "Directory path contains null bytes"
|
285
|
+
end
|
286
|
+
|
287
|
+
# Validate timeout parameter.
|
288
|
+
#
|
289
|
+
# @param timeout [Integer] timeout to validate
|
290
|
+
# @raise [ArgumentError] if timeout is invalid
|
291
|
+
def validate_timeout(timeout)
|
292
|
+
raise ArgumentError, "Timeout must be a positive integer" unless timeout.is_a?(Integer) && timeout.positive?
|
293
|
+
|
294
|
+
return unless timeout > 3600 # 1 hour max
|
295
|
+
|
296
|
+
raise ArgumentError, "Timeout cannot exceed 3600 seconds"
|
297
|
+
end
|
298
|
+
|
299
|
+
# Normalize hash keys to support both string and symbol keys.
|
300
|
+
#
|
301
|
+
# @param hash [Hash] hash to normalize
|
302
|
+
# @return [Hash] hash with normalized keys
|
303
|
+
def self.normalize_hash_keys(hash)
|
304
|
+
normalized = {}
|
305
|
+
hash.each do |key, value|
|
306
|
+
normalized_key = key.is_a?(String) ? key.to_sym : key
|
307
|
+
normalized[key] = value # Keep original key
|
308
|
+
normalized[normalized_key] = value # Add symbol version
|
309
|
+
end
|
310
|
+
normalized
|
311
|
+
end
|
312
|
+
|
313
|
+
private_class_method :normalize_hash_keys
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|