@@ -162,4 +162,59 @@ def windows_platform?
162
162
win_platform_regex = /mingw|mswin/
163
163
RUBY_PLATFORM =~ win_platform_regex || RUBY_DESCRIPTION =~ win_platform_regex
164
164
end
165
+
166
+ require 'delegate'
167
+
168
+ # A wrapper around a ProcessExecuter::Status that also includes command output
169
+ # @api public
170
+ class CommandResult < SimpleDelegator
171
+ # Create a new CommandResult
172
+ # @example
173
+ # status = ProcessExecuter.spawn(*command, timeout:, out:, err:)
174
+ # CommandResult.new(status, out_buffer.string, err_buffer.string)
175
+ # @param status [ProcessExecuter::Status] The status of the process
176
+ # @param out [String] The standard output of the process
177
+ # @param err [String] The standard error of the process
178
+ def initialize ( status , out , err )
179
+ super ( status )
180
+ @out = out
181
+ @err = err
182
+ end
183
+
184
+ # @return [String] The stdout output of the process
185
+ attr_reader :out
186
+
187
+ # @return [String] The stderr output of the process
188
+ attr_reader :err
189
+ end
190
+
191
+ # Run a command and return the status including stdout and stderr output
192
+ #
193
+ # @example
194
+ # command = %w[git status]
195
+ # status = run(command)
196
+ # status.success? # => true
197
+ # status.exitstatus # => 0
198
+ # status.out # => "On branch master\nnothing to commit, working tree clean\n"
199
+ # status.err # => ""
200
+ #
201
+ # @param command [Array<String>] The command to run
202
+ # @param timeout [Numeric, nil] Seconds to allow command to run before killing it or nil for no timeout
203
+ # @param raise_errors [Boolean] Raise an exception if the command fails
204
+ # @param error_message [String] The message to use when raising an exception
205
+ #
206
+ # @return [CommandResult] The result of running
207
+ #
208
+ def run_command ( *command , timeout : nil , raise_errors : true , error_message : "#{ command [ 0 ] } failed" )
209
+ out_buffer = StringIO . new
210
+ out = ProcessExecuter ::MonitoredPipe . new ( out_buffer )
211
+ err_buffer = StringIO . new
212
+ err = ProcessExecuter ::MonitoredPipe . new ( err_buffer )
213
+
214
+ status = ProcessExecuter . spawn ( *command , timeout : timeout , out : out , err : err )
215
+
216
+ raise "#{ error_message } : #{ err_buffer . string } " if raise_errors && !status . success?
217
+
218
+ CommandResult . new ( status , out_buffer . string , err_buffer . string )
219
+ end
165
220
end
0 commit comments