From 07d571bebc5b05a86e5dc8ebf9c51ec9836da81d Mon Sep 17 00:00:00 2001 From: Gibson Fahnestock Date: Wed, 2 Jun 2021 11:52:01 +0100 Subject: [PATCH] fix(vendor-gems): redirect bundler stdout to stderr When running brew commands and interpreting the output, e.g. running `brew livecheck --json`, it's necessary to stop other programs Homebrew happens to execute from writing logging output to stdout. Most programs don't do this, but `bundle install` does seem to. To reproduce the issue you can run: ```shell git -C "$(brew --prefix)" clean -ffdx Library/Homebrew/vendor stdout=$(HOMEBREW_FORCE_VENDOR_RUBY=1 brew livecheck --newer-only --json --cask $(brew --repo homebrew/cask)/Casks/grid.rb) echo "^^^ was stderr, >>> is stdout: $stdout" ``` If you run it without this change it will print a bunch of output like this to the stdout before printing out the livecheck JSON output: ```text Using bundler 1.17.3 Fetching byebug 11.1.3 Fetching coderay 1.1.3 Installing byebug 11.1.3 with native extensions Installing coderay 1.1.3 Fetching colorize 0.8.1 Installing colorize 0.8.1 [ # Contents of the JSON block. ] ``` With this change the stdout from `bundle install` will be redirected to brew's stderr, meaning only the JSON goes to stdout, and the rest goes to stderr. --- Library/Homebrew/dev-cmd/vendor-gems.rb | 2 +- Library/Homebrew/utils.rb | 13 +++++++++++++ Library/Homebrew/utils/gems.rb | 4 +++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/dev-cmd/vendor-gems.rb b/Library/Homebrew/dev-cmd/vendor-gems.rb index 56e1de3a4..bae2c0a6e 100644 --- a/Library/Homebrew/dev-cmd/vendor-gems.rb +++ b/Library/Homebrew/dev-cmd/vendor-gems.rb @@ -40,7 +40,7 @@ module Homebrew end ohai "bundle install --standalone" - safe_system "bundle", "install", "--standalone" + safe_system_redirect_stdout_to_stderr "bundle", "install", "--standalone" ohai "bundle pristine" safe_system "bundle", "pristine" diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index b041cfee9..52e931306 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -332,6 +332,19 @@ module Kernel end end + # Redirects stdout to stderr, throws exception on command failure. + def safe_system_redirect_stdout_to_stderr(cmd, *args) + return if Homebrew._system(cmd, *args) do + # Redirect stdout stream to stderr stream. This is useful to prevent + # subprocesses from writing to stdout and interfering with the intended + # output, e.g. when running a brew command with `--json` for programs + # automating brew commands. + $stdout.reopen($stderr) + end + + raise ErrorDuringExecution.new([cmd, *args], status: $CHILD_STATUS) + end + def which(cmd, path = ENV["PATH"]) PATH.new(path).each do |p| begin diff --git a/Library/Homebrew/utils/gems.rb b/Library/Homebrew/utils/gems.rb index bc2337834..a616477d8 100644 --- a/Library/Homebrew/utils/gems.rb +++ b/Library/Homebrew/utils/gems.rb @@ -144,7 +144,9 @@ module Homebrew # for some reason sometimes the exit code lies so check the output too. if bundle_check_failed || bundle_check_output.include?("Install missing gems") - unless system bundle, "install" + begin + safe_system_redirect_stdout_to_stderr bundle, "install" + rescue ErrorDuringExecution message = <<~EOS failed to run `#{bundle} install`! EOS