@@ -189,13 +189,14 @@ def initialize(env, binary_path, global_opts, logger)
189
189
#
190
190
# @raise [Git::TimeoutError] if the command times out
191
191
#
192
- def run ( *args , out :, err :, normalize :, chomp :, merge :, chdir : nil , timeout : nil )
192
+ def run ( *args , out : nil , err : nil , normalize :, chomp :, merge :, chdir : nil , timeout : nil )
193
193
git_cmd = build_git_cmd ( args )
194
- out ||= StringIO . new
195
- err ||= ( merge ? out : StringIO . new )
196
- status = execute ( git_cmd , out , err , chdir : ( chdir || :not_set ) , timeout : timeout )
197
-
198
- process_result ( git_cmd , status , out , err , normalize , chomp , timeout )
194
+ begin
195
+ result = ProcessExecuter . run ( env , *git_cmd , out : out , err : err , merge :, chdir : ( chdir || :not_set ) , timeout : timeout , raise_errors : false )
196
+ rescue ProcessExecuter ::Command ::ProcessIOError => e
197
+ raise Git ::ProcessIOError . new ( e . message ) , cause : e . exception . cause
198
+ end
199
+ process_result ( result , normalize , chomp , timeout )
199
200
end
200
201
201
202
private
@@ -210,121 +211,12 @@ def build_git_cmd(args)
210
211
[ binary_path , *global_opts , *args ] . map { |e | e . to_s }
211
212
end
212
213
213
- # Determine the output to return in the `CommandLineResult`
214
- #
215
- # If the writer can return the output by calling `#string` (such as a StringIO),
216
- # then return the result of normalizing the encoding and chomping the output
217
- # as requested.
218
- #
219
- # If the writer does not support `#string`, then return nil. The output is
220
- # assumed to be collected by the writer itself such as when the writer
221
- # is a file instead of a StringIO.
222
- #
223
- # @param writer [#string] the writer to post-process
224
- #
225
- # @return [String, nil]
226
- #
227
- # @api private
228
- #
229
- def post_process ( writer , normalize , chomp )
230
- if writer . respond_to? ( :string )
231
- output = writer . string . dup
232
- output = output . lines . map { |l | Git ::EncodingUtils . normalize_encoding ( l ) } . join if normalize
233
- output . chomp! if chomp
234
- output
235
- else
236
- nil
237
- end
238
- end
239
-
240
- # Post-process all writers and return an array of the results
241
- #
242
- # @param writers [Array<#write>] the writers to post-process
243
- # @param normalize [Boolean] whether to normalize the output of each writer
244
- # @param chomp [Boolean] whether to chomp the output of each writer
245
- #
246
- # @return [Array<String, nil>] the output of each writer that supports `#string`
247
- #
248
- # @api private
249
- #
250
- def post_process_all ( writers , normalize , chomp )
251
- Array . new . tap do |result |
252
- writers . each { |writer | result << post_process ( writer , normalize , chomp ) }
253
- end
254
- end
255
-
256
- # Raise an error when there was exception while collecting the subprocess output
257
- #
258
- # @param git_cmd [Array<String>] the git command that was executed
259
- # @param pipe_name [Symbol] the name of the pipe that raised the exception
260
- # @param pipe [ProcessExecuter::MonitoredPipe] the pipe that raised the exception
261
- #
262
- # @raise [Git::ProcessIOError]
263
- #
264
- # @return [void] this method always raises an error
265
- #
266
- # @api private
267
- #
268
- def raise_pipe_error ( git_cmd , pipe_name , pipe )
269
- raise Git ::ProcessIOError . new ( "Pipe Exception for #{ git_cmd } : #{ pipe_name } " ) , cause : pipe . exception
270
- end
271
-
272
- # Execute the git command and collect the output
273
- #
274
- # @param cmd [Array<String>] the git command to execute
275
- # @param chdir [String] the directory to run the command in
276
- # @param timeout [Numeric, nil] the maximum seconds to wait for the command to complete
277
- #
278
- # If timeout is zero of nil, the command will not time out. If the command
279
- # times out, it is killed via a SIGKILL signal and `Git::TimeoutError` is raised.
280
- #
281
- # If the command does not respond to SIGKILL, it will hang this method.
282
- #
283
- # @raise [Git::ProcessIOError] if an exception was raised while collecting subprocess output
284
- # @raise [Git::TimeoutError] if the command times out
285
- #
286
- # @return [ProcessExecuter::Status] the status of the completed subprocess
287
- #
288
- # @api private
289
- #
290
- def spawn ( cmd , out_writers , err_writers , chdir :, timeout :)
291
- out_pipe = ProcessExecuter ::MonitoredPipe . new ( *out_writers , chunk_size : 10_000 )
292
- err_pipe = ProcessExecuter ::MonitoredPipe . new ( *err_writers , chunk_size : 10_000 )
293
- ProcessExecuter . spawn ( env , *cmd , out : out_pipe , err : err_pipe , chdir : chdir , timeout : timeout )
294
- ensure
295
- out_pipe . close
296
- err_pipe . close
297
- raise_pipe_error ( cmd , :stdout , out_pipe ) if out_pipe . exception
298
- raise_pipe_error ( cmd , :stderr , err_pipe ) if err_pipe . exception
299
- end
300
-
301
- # The writers that will be used to collect stdout and stderr
302
- #
303
- # Additional writers could be added here if you wanted to tee output
304
- # or send output to the terminal.
305
- #
306
- # @param out [#write] the object to write stdout to
307
- # @param err [#write] the object to write stderr to
308
- #
309
- # @return [Array<Array<#write>, Array<#write>>] the writers for stdout and stderr
310
- #
311
- # @api private
312
- #
313
- def writers ( out , err )
314
- out_writers = [ out ]
315
- err_writers = [ err ]
316
- [ out_writers , err_writers ]
317
- end
318
-
319
214
# Process the result of the command and return a Git::CommandLineResult
320
215
#
321
216
# Post process output, log the command and result, and raise an error if the
322
217
# command failed.
323
218
#
324
- # @param git_cmd [Array<String>] the git command that was executed
325
- # @param status [Process::Status] the status of the completed subprocess
326
- # @param out [#write] the object that stdout was written to
327
- # @param err [#write] the object that stderr was written to
219
+ # @param result [ProcessExecuter::Command::Result] the result it is a Process::Status and include command, stdout, and stderr
328
220
# @param normalize [Boolean] whether to normalize the output of each writer
329
221
# @param chomp [Boolean] whether to chomp the output of each writer
330
222
# @param timeout [Numeric, nil] the maximum seconds to wait for the command to complete
@@ -338,40 +230,58 @@ def writers(out, err)
338
230
#
339
231
# @api private
340
232
#
341
- def process_result ( git_cmd , status , out , err , normalize , chomp , timeout )
342
- out_str , err_str = post_process_all ( [ out , err ] , normalize , chomp )
343
- logger . info { "#{ git_cmd } exited with status #{ status } " }
344
- logger . debug { "stdout:\n #{ out_str . inspect } \n stderr:\n #{ err_str . inspect } " }
345
- Git ::CommandLineResult . new ( git_cmd , status , out_str , err_str ) . tap do |result |
346
- raise Git ::TimeoutError . new ( result , timeout ) if status . timeout?
347
- raise Git ::SignaledError . new ( result ) if status . signaled?
348
- raise Git ::FailedError . new ( result ) unless status . success?
233
+ def process_result ( result , normalize , chomp , timeout )
234
+ command = result . command
235
+ processed_out , processed_err = post_process_all ( [ result . stdout , result . stderr ] , normalize , chomp )
236
+ logger . info { "#{ command } exited with status #{ result } " }
237
+ logger . debug { "stdout:\n #{ processed_out . inspect } \n stderr:\n #{ processed_err . inspect } " }
238
+ Git ::CommandLineResult . new ( command , result , processed_out , processed_err ) . tap do |processed_result |
239
+ raise Git ::TimeoutError . new ( processed_result , timeout ) if result . timeout?
240
+ raise Git ::SignaledError . new ( processed_result ) if result . signaled?
241
+ raise Git ::FailedError . new ( processed_result ) unless result . success?
349
242
end
350
243
end
351
244
352
- # Execute the git command and write the command output to out and err
245
+ # Post-process command output and return an array of the results
353
246
#
354
- # @param git_cmd [Array<String>] the git command to execute
355
- # @param out [#write] the object to write stdout to
356
- # @param err [#write] the object to write stderr to
357
- # @param chdir [String] the directory to run the command in
358
- # @param timeout [Numeric, nil] the maximum seconds to wait for the command to complete
247
+ # @param raw_outputs [Array] the output to post-process
248
+ # @param normalize [Boolean] whether to normalize the output of each writer
249
+ # @param chomp [Boolean] whether to chomp the output of each writer
359
250
#
360
- # If timeout is zero of nil, the command will not time out. If the command
361
- # times out, it is killed via a SIGKILL signal and `Git::TimeoutError` is raised.
251
+ # @return [Array<String, nil>] the processed output of each command output object that supports `#string`
362
252
#
363
- # If the command does not respond to SIGKILL, it will hang this method.
253
+ # @api private
364
254
#
365
- # @raise [Git::ProcessIOError] if an exception was raised while collecting subprocess output
366
- # @raise [Git::TimeoutError] if the command times out
255
+ def post_process_all ( raw_outputs , normalize , chomp )
256
+ Array . new . tap do |result |
257
+ raw_outputs . each { |raw_output | result << post_process ( raw_output , normalize , chomp ) }
258
+ end
259
+ end
260
+
261
+ # Determine the output to return in the `CommandLineResult`
367
262
#
368
- # @return [Git::CommandLineResult] the result of the command to return to the caller
263
+ # If the writer can return the output by calling `#string` (such as a StringIO),
264
+ # then return the result of normalizing the encoding and chomping the output
265
+ # as requested.
266
+ #
267
+ # If the writer does not support `#string`, then return nil. The output is
268
+ # assumed to be collected by the writer itself such as when the writer
269
+ # is a file instead of a StringIO.
270
+ #
271
+ # @param raw_output [#string] the output to post-process
272
+ # @return [String, nil]
369
273
#
370
274
# @api private
371
275
#
372
- def execute ( git_cmd , out , err , chdir :, timeout :)
373
- out_writers , err_writers = writers ( out , err )
374
- spawn ( git_cmd , out_writers , err_writers , chdir : chdir , timeout : timeout )
276
+ def post_process ( raw_output , normalize , chomp )
277
+ if raw_output . respond_to? ( :string )
278
+ output = raw_output . string . dup
279
+ output = output . lines . map { |l | Git ::EncodingUtils . normalize_encoding ( l ) } . join if normalize
280
+ output . chomp! if chomp
281
+ output
282
+ else
283
+ nil
284
+ end
375
285
end
376
286
end
377
287
end
0 commit comments