From 21e77a2d33d32735c04c1f950f2cb5eca136bbf5 Mon Sep 17 00:00:00 2001 From: James Couball Date: Wed, 2 Jul 2025 10:58:59 -0700 Subject: [PATCH] chore: upgrade to ProcessExecuter 4.x --- git.gemspec | 2 +- lib/git/command_line.rb | 21 +++++++++--------- lib/git/command_line_result.rb | 12 +++++++--- tests/test_helper.rb | 38 ++++---------------------------- tests/units/test_command_line.rb | 9 +++----- 5 files changed, 28 insertions(+), 54 deletions(-) diff --git a/git.gemspec b/git.gemspec index e62b562b..4aa24899 100644 --- a/git.gemspec +++ b/git.gemspec @@ -29,7 +29,7 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'activesupport', '>= 5.0' s.add_runtime_dependency 'addressable', '~> 2.8' - s.add_runtime_dependency 'process_executer', '~> 1.3' + s.add_runtime_dependency 'process_executer', '~> 4.0' s.add_runtime_dependency 'rchardet', '~> 1.9' s.add_development_dependency 'create_github_release', '~> 2.1' diff --git a/lib/git/command_line.rb b/lib/git/command_line.rb index 6228a144..0b4a0e73 100644 --- a/lib/git/command_line.rb +++ b/lib/git/command_line.rb @@ -192,8 +192,13 @@ def initialize(env, binary_path, global_opts, logger) def run(*args, out: nil, err: nil, normalize:, chomp:, merge:, chdir: nil, timeout: nil) git_cmd = build_git_cmd(args) begin - result = ProcessExecuter.run(env, *git_cmd, out: out, err: err, merge:, chdir: (chdir || :not_set), timeout: timeout, raise_errors: false) - rescue ProcessExecuter::Command::ProcessIOError => e + options = { chdir: (chdir || :not_set), timeout_after: timeout, raise_errors: false } + options[:out] = out unless out.nil? + options[:err] = err unless err.nil? + options[:merge_output] = merge unless merge.nil? + + result = ProcessExecuter.run_with_capture(env, *git_cmd, **options) + rescue ProcessExecuter::ProcessIOError => e raise Git::ProcessIOError.new(e.message), cause: e.exception.cause end process_result(result, normalize, chomp, timeout) @@ -274,14 +279,10 @@ def post_process_all(raw_outputs, normalize, chomp) # @api private # def post_process(raw_output, normalize, chomp) - if raw_output.respond_to?(:string) - output = raw_output.string.dup - output = output.lines.map { |l| Git::EncodingUtils.normalize_encoding(l) }.join if normalize - output.chomp! if chomp - output - else - nil - end + output = raw_output.dup + output = output.lines.map { |l| Git::EncodingUtils.normalize_encoding(l) }.join if normalize + output.chomp! if chomp + output end end end diff --git a/lib/git/command_line_result.rb b/lib/git/command_line_result.rb index 9194a292..2a37c3c2 100644 --- a/lib/git/command_line_result.rb +++ b/lib/git/command_line_result.rb @@ -19,15 +19,21 @@ class CommandLineResult # result = Git::CommandLineResult.new(git_cmd, status, stdout, stderr) # # @param git_cmd [Array] the git command that was executed - # @param status [Process::Status] the status of the process - # @param stdout [String] the output of the process - # @param stderr [String] the error output of the process + # @param status [ProcessExecuter::ResultWithCapture] the status of the process + # @param stdout [String] the processed stdout of the process + # @param stderr [String] the processed stderr of the process # def initialize(git_cmd, status, stdout, stderr) @git_cmd = git_cmd @status = status @stdout = stdout @stderr = stderr + + # ProcessExecuter::ResultWithCapture changed the timeout? method to timed_out? + # in version 4.x. This is a compatibility layer to maintain the old method name + # for backward compatibility. + # + status.define_singleton_method(:timeout?) { timed_out? } end # @attribute [r] git_cmd diff --git a/tests/test_helper.rb b/tests/test_helper.rb index f35a0fcd..7378db7a 100644 --- a/tests/test_helper.rb +++ b/tests/test_helper.rb @@ -171,31 +171,6 @@ def windows_platform? RUBY_PLATFORM =~ win_platform_regex || RUBY_DESCRIPTION =~ win_platform_regex end - require 'delegate' - - # A wrapper around a ProcessExecuter::Status that also includes command output - # @api public - class CommandResult < SimpleDelegator - # Create a new CommandResult - # @example - # status = ProcessExecuter.spawn(*command, timeout:, out:, err:) - # CommandResult.new(status, out_buffer.string, err_buffer.string) - # @param status [ProcessExecuter::Status] The status of the process - # @param out [String] The standard output of the process - # @param err [String] The standard error of the process - def initialize(status, out, err) - super(status) - @out = out - @err = err - end - - # @return [String] The stdout output of the process - attr_reader :out - - # @return [String] The stderr output of the process - attr_reader :err - end - # Run a command and return the status including stdout and stderr output # # @example @@ -213,17 +188,12 @@ def initialize(status, out, err) # # @return [CommandResult] The result of running # - def run_command(*command, timeout: nil, raise_errors: true, error_message: "#{command[0]} failed") - out_buffer = StringIO.new - out = ProcessExecuter::MonitoredPipe.new(out_buffer) - err_buffer = StringIO.new - err = ProcessExecuter::MonitoredPipe.new(err_buffer) - - status = ProcessExecuter.spawn(*command, timeout: timeout, out: out, err: err) + def run_command(*command, raise_errors: true, error_message: "#{command[0]} failed") + result = ProcessExecuter.run_with_capture(*command, raise_errors: false) - raise "#{error_message}: #{err_buffer.string}" if raise_errors && !status.success? + raise "#{error_message}: #{result.stderr}" if raise_errors && !result.success? - CommandResult.new(status, out_buffer.string, err_buffer.string) + result end end diff --git a/tests/units/test_command_line.rb b/tests/units/test_command_line.rb index 7062d1aa..5f678b91 100644 --- a/tests/units/test_command_line.rb +++ b/tests/units/test_command_line.rb @@ -61,7 +61,7 @@ def merge command_line = Git::CommandLine.new(env, binary_path, global_opts, logger) args = [] error = assert_raise ArgumentError do - command_line.run(*args, out: out_writer, err: err_writer, normalize: normalize, chomp: chomp, merge: merge, timeout: 'not a number') + command_line.run(*args, normalize: normalize, chomp: chomp, timeout_after: 'not a number') end end @@ -97,7 +97,6 @@ def merge assert_equal([{}, 'ruby', 'bin/command_line_test', '--stdout=stdout output', '--stderr=stderr output'], result.git_cmd) assert_equal('stdout output', result.stdout.chomp) assert_equal('stderr output', result.stderr.chomp) - assert(result.status.is_a? ProcessExecuter::Command::Result) assert_equal(0, result.status.exitstatus) end @@ -239,10 +238,8 @@ def write(*args) command_line = Git::CommandLine.new(env, binary_path, global_opts, logger) args = ['--stderr=ERROR: fatal error', '--stdout=STARTING PROCESS'] Tempfile.create do |f| - err_writer = f - result = command_line.run(*args, out: out_writer, err: err_writer, normalize: normalize, chomp: chomp, merge: merge) - f.rewind - assert_equal('ERROR: fatal error', f.read.chomp) + result = command_line.run(*args, normalize: normalize, chomp: chomp, merge: merge) + assert_equal('ERROR: fatal error', result.stderr.chomp) end end