Merge branch 'master' into hbc_analytics

This commit is contained in:
Brian Morton 2018-08-17 16:18:40 -07:00
commit 7ced0be133
17 changed files with 169 additions and 35 deletions

View File

@ -1,5 +1,5 @@
# Contributing to Homebrew # Contributing to Homebrew
First time contributing to Homebrew? Read our [Code of Conduct](https://github.com/Homebrew/brew/blob/master/CODE_OF_CONDUCT.md#code-of-conduct). First time contributing to Homebrew? Read our [Code of Conduct](https://github.com/Homebrew/brew/blob/master/CODE_OF_CONDUCT.md#code-of-conduct) and review [How To Open a Homebrew Pull Request](https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request).
### Report a bug ### Report a bug

View File

@ -114,7 +114,7 @@ rescue UsageError => e
require "help" require "help"
Homebrew::Help.help cmd, usage_error: e.message Homebrew::Help.help cmd, usage_error: e.message
rescue SystemExit => e rescue SystemExit => e
onoe "Kernel.exit" if ARGV.verbose? && !e.success? onoe "Kernel.exit" if ARGV.debug? && !e.success?
$stderr.puts e.backtrace if ARGV.debug? $stderr.puts e.backtrace if ARGV.debug?
raise raise
rescue Interrupt rescue Interrupt

View File

@ -11,6 +11,8 @@ require "extend/ENV"
require "debrew" require "debrew"
require "fcntl" require "fcntl"
require "socket" require "socket"
require "json"
require "json/add/core"
class Build class Build
attr_reader :formula, :deps, :reqs attr_reader :formula, :deps, :reqs
@ -190,7 +192,17 @@ begin
build = Build.new(formula, options) build = Build.new(formula, options)
build.install build.install
rescue Exception => e # rubocop:disable Lint/RescueException rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, error_pipe) error_hash = JSON.parse e.to_json
# Special case: We need to toss our build state into the error hash
# for proper analytics reporting and sensible error messages.
if e.is_a?(BuildError)
error_hash["cmd"] = e.cmd
error_hash["args"] = e.args
error_hash["env"] = e.env
end
error_pipe.write error_hash.to_json
error_pipe.close error_pipe.close
exit! 1 exit! 1
end end

View File

@ -245,9 +245,9 @@ module Homebrew
end end
def cleanup_lockfiles(*lockfiles) def cleanup_lockfiles(*lockfiles)
return unless HOMEBREW_LOCK_DIR.directory? return if dry_run?
if lockfiles.empty? if lockfiles.empty? && HOMEBREW_LOCK_DIR.directory?
lockfiles = HOMEBREW_LOCK_DIR.children.select(&:file?) lockfiles = HOMEBREW_LOCK_DIR.children.select(&:file?)
end end
@ -256,7 +256,7 @@ module Homebrew
next unless file.open(File::RDWR).flock(File::LOCK_EX | File::LOCK_NB) next unless file.open(File::RDWR).flock(File::LOCK_EX | File::LOCK_NB)
begin begin
cleanup_path(file) { file.unlink } file.unlink
ensure ensure
file.open(File::RDWR).flock(File::LOCK_UN) if file.exist? file.open(File::RDWR).flock(File::LOCK_UN) if file.exist?
end end

View File

@ -4,7 +4,7 @@
#: Options for the `install` command are also valid here. #: Options for the `install` command are also valid here.
#: #:
#: If `--cleanup` is specified or `HOMEBREW_UPGRADE_CLEANUP` is set then remove #: If `--cleanup` is specified or `HOMEBREW_UPGRADE_CLEANUP` is set then remove
#: previously installed <formula> version(s). #: previously installed version(s) of upgraded <formulae>.
#: #:
#: If `--fetch-HEAD` is passed, fetch the upstream repository to detect if #: If `--fetch-HEAD` is passed, fetch the upstream repository to detect if
#: the HEAD installation of the formula is outdated. Otherwise, the #: the HEAD installation of the formula is outdated. Otherwise, the

View File

@ -772,7 +772,7 @@ module Homebrew
end end
bin_names.each do |name| bin_names.each do |name|
["system", "shell_output", "pipe_output"].each do |cmd| ["system", "shell_output", "pipe_output"].each do |cmd|
if text =~ %r{(def test|test do).*(#{Regexp.escape(HOMEBREW_PREFIX)}/bin/)?#{cmd}[\(\s]+['"]#{Regexp.escape(name)}[\s'"]}m if text =~ /test do.*#{cmd}[\(\s]+['"]#{Regexp.escape(name)}[\s'"]/m
problem %Q(fully scope test #{cmd} calls e.g. #{cmd} "\#{bin}/#{name}") problem %Q(fully scope test #{cmd} calls e.g. #{cmd} "\#{bin}/#{name}")
end end
end end
@ -803,10 +803,6 @@ module Homebrew
problem "Use separate make calls" if line.include?("make && make") problem "Use separate make calls" if line.include?("make && make")
if line =~ /shell_output\(['"].+['"], 0\)/
problem "Passing 0 to shell_output() is redundant"
end
if line =~ /JAVA_HOME/i && !formula.requirements.map(&:class).include?(JavaRequirement) if line =~ /JAVA_HOME/i && !formula.requirements.map(&:class).include?(JavaRequirement)
problem "Use `depends_on :java` to set JAVA_HOME" problem "Use `depends_on :java` to set JAVA_HOME"
end end

View File

@ -93,12 +93,14 @@ module Homebrew
exec(*args) exec(*args)
end end
end end
rescue ::Test::Unit::AssertionFailedError => e rescue ChildProcessError => e
ofail "#{f.full_name}: failed" ofail "#{f.full_name}: failed"
puts e.message case e.inner["json_class"]
rescue Exception => e # rubocop:disable Lint/RescueException when "Test::Unit::AssertionFailedError"
ofail "#{f.full_name}: failed" puts e.inner["m"]
puts e, e.backtrace else
puts e.inner["json_class"], e.backtrace
end
ensure ensure
ENV.replace(env) ENV.replace(env)
end end

View File

@ -352,14 +352,16 @@ class FormulaAmbiguousPythonError < RuntimeError
end end
class BuildError < RuntimeError class BuildError < RuntimeError
attr_reader :formula, :env attr_reader :formula, :cmd, :args, :env
attr_accessor :options attr_accessor :options
def initialize(formula, cmd, args, env) def initialize(formula, cmd, args, env)
@formula = formula @formula = formula
@cmd = cmd
@args = args
@env = env @env = env
args = args.map { |arg| arg.to_s.gsub " ", "\\ " }.join(" ") pretty_args = args.map { |arg| arg.to_s.gsub " ", "\\ " }.join(" ")
super "Failed executing: #{cmd} #{args}" super "Failed executing: #{cmd} #{pretty_args}"
end end
def issues def issues
@ -596,3 +598,20 @@ class BottleFormulaUnavailableError < RuntimeError
EOS EOS
end end
end end
# Raised when a child process sends us an exception over its error pipe.
class ChildProcessError < RuntimeError
attr_reader :inner
def initialize(inner)
@inner = inner
super <<~EOS
An exception occured within a build process:
#{inner["json_class"]}: #{inner["m"]}
EOS
# Clobber our real (but irrelevant) backtrace with that of the inner exception.
set_backtrace inner["b"]
end
end

View File

@ -763,14 +763,25 @@ class FormulaInstaller
raise "Empty installation" raise "Empty installation"
end end
rescue Exception => e # rubocop:disable Lint/RescueException rescue Exception => e # rubocop:disable Lint/RescueException
e.options = display_options(formula) if e.is_a?(BuildError) # If we've rescued a ChildProcessError and that ChildProcessError
# contains a BuildError, then we reconstruct the inner build error
# to make analytics happy.
if e.is_a?(ChildProcessError) && e.inner["json_class"] == "BuildError"
build_error = BuildError.new(formula, e["cmd"], e["args"], e["env"])
build_error.set_backtrace e.backtrace
build_error.options = display_options(formula)
e = build_error
end
ignore_interrupts do ignore_interrupts do
# any exceptions must leave us with nothing installed # any exceptions must leave us with nothing installed
formula.update_head_version formula.update_head_version
formula.prefix.rmtree if formula.prefix.directory? formula.prefix.rmtree if formula.prefix.directory?
formula.rack.rmdir_if_possible formula.rack.rmdir_if_possible
end end
raise
raise e
end end
def link(keg) def link(keg)

View File

@ -4,6 +4,7 @@ require "global"
require "debrew" require "debrew"
require "fcntl" require "fcntl"
require "socket" require "socket"
require "json/add/core"
begin begin
error_pipe = UNIXSocket.open(ENV["HOMEBREW_ERROR_PIPE"], &:recv_io) error_pipe = UNIXSocket.open(ENV["HOMEBREW_ERROR_PIPE"], &:recv_io)
@ -15,7 +16,7 @@ begin
formula.extend(Debrew::Formula) if ARGV.debug? formula.extend(Debrew::Formula) if ARGV.debug?
formula.run_post_install formula.run_post_install
rescue Exception => e # rubocop:disable Lint/RescueException rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, error_pipe) error_pipe.write e.to_json
error_pipe.close error_pipe.close
exit! 1 exit! 1
end end

View File

@ -22,6 +22,41 @@ module RuboCop
end end
end end
end end
class TestCalls < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
test = find_block(body_node, :test)
return unless test
test_calls(test) do |node, params|
p1, p2 = params
if match = string_content(p1).match(%r{(/usr/local/(s?bin))})
offending_node(p1)
problem "use \#{#{match[2]}} instead of #{match[1]} in #{node}"
end
if node == :shell_output && node_equals?(p2, 0)
offending_node(p2)
problem "Passing 0 to shell_output() is redundant"
end
end
end
def autocorrect(node)
lambda do |corrector|
case node.type
when :str, :dstr
corrector.replace(node.source_range, node.source.to_s.sub(%r{(/usr/local/(s?bin))}, '#{\2}'))
when :int
corrector.remove(range_with_surrounding_comma(range_with_surrounding_space(range: node.source_range, side: :left)))
end
end
end
def_node_search :test_calls, <<~EOS
(send nil? ${:system :shell_output :pipe_output} $...)
EOS
end
end end
module FormulaAuditStrict module FormulaAuditStrict

View File

@ -7,6 +7,7 @@ require "debrew"
require "formula_assertions" require "formula_assertions"
require "fcntl" require "fcntl"
require "socket" require "socket"
require "json/add/core"
TEST_TIMEOUT_SECONDS = 5 * 60 TEST_TIMEOUT_SECONDS = 5 * 60
@ -28,7 +29,7 @@ begin
raise "test returned false" if formula.run_test == false raise "test returned false" if formula.run_test == false
end end
rescue Exception => e # rubocop:disable Lint/RescueException rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, error_pipe) error_pipe.write e.to_json
error_pipe.close error_pipe.close
exit! 1 exit! 1
end end

View File

@ -48,6 +48,61 @@ describe RuboCop::Cop::FormulaAudit::ClassName do
end end
end end
describe RuboCop::Cop::FormulaAudit::TestCalls do
subject(:cop) { described_class.new }
it "reports an offense when /usr/local/bin is found in test calls" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://example.com/foo-1.0.tgz'
test do
system "/usr/local/bin/test"
^^^^^^^^^^^^^^^^^^^^^ use \#{bin} instead of /usr/local/bin in system
end
end
RUBY
end
it "reports an offense when passing 0 as the second parameter to shell_output" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://example.com/foo-1.0.tgz'
test do
shell_output("\#{bin}/test", 0)
^ Passing 0 to shell_output() is redundant
end
end
RUBY
end
it "supports auto-correcting test calls" do
source = <<~RUBY
class Foo < Formula
url 'https://example.com/foo-1.0.tgz'
test do
shell_output("/usr/local/sbin/test", 0)
end
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://example.com/foo-1.0.tgz'
test do
shell_output("\#{sbin}/test")
end
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
end
describe RuboCop::Cop::FormulaAuditStrict::Test do describe RuboCop::Cop::FormulaAuditStrict::Test do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }

View File

@ -1,5 +1,7 @@
require "fcntl" require "fcntl"
require "socket" require "socket"
require "json"
require "json/add/core"
module Utils module Utils
def self.safe_fork(&_block) def self.safe_fork(&_block)
@ -15,7 +17,7 @@ module Utils
write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
yield yield
rescue Exception => e # rubocop:disable Lint/RescueException rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, write) write.write e.to_json
write.close write.close
exit! exit!
else else
@ -36,7 +38,7 @@ module Utils
data = read.read data = read.read
read.close read.close
Process.wait(pid) unless socket.nil? Process.wait(pid) unless socket.nil?
raise Marshal.load(data) unless data.nil? || data.empty? # rubocop:disable Security/MarshalLoad raise ChildProcessError, JSON.parse(data) unless data.nil? || data.empty?
raise Interrupt if $CHILD_STATUS.exitstatus == 130 raise Interrupt if $CHILD_STATUS.exitstatus == 130
raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success? raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success?
end end

View File

@ -40,7 +40,7 @@ Homebrew's lead maintainer is [Mike McQuaid](https://github.com/mikemcquaid).
Homebrew's project leadership committee is [Mike McQuaid](https://github.com/mikemcquaid), [JCount](https://github.com/jcount), [Misty De Meo](https://github.com/mistydemeo) and [Markus Reiter](https://github.com/reitermarkus). Homebrew's project leadership committee is [Mike McQuaid](https://github.com/mikemcquaid), [JCount](https://github.com/jcount), [Misty De Meo](https://github.com/mistydemeo) and [Markus Reiter](https://github.com/reitermarkus).
Homebrew/brew's other current maintainers are [Dominyk Tiller](https://github.com/DomT4), [Claudia](https://github.com/claui), [Michka Popoff](https://github.com/imichka), [Shaun Jackman](https://github.com/sjackman), [Chongyu Zhu](https://github.com/lembacon), [commitay](https://github.com/commitay), [Vitor Galvao](https://github.com/vitorgalvao), [JCount](https://github.com/jcount), [Misty De Meo](https://github.com/mistydemeo), [Gautham Goli](https://github.com/GauthamGoli), [Markus Reiter](https://github.com/reitermarkus) and [William Woodruff](https://github.com/woodruffw). Homebrew/brew's other current maintainers are [Dominyk Tiller](https://github.com/DomT4), [Claudia](https://github.com/claui), [Michka Popoff](https://github.com/imichka), [Shaun Jackman](https://github.com/sjackman), [Chongyu Zhu](https://github.com/lembacon), [commitay](https://github.com/commitay), [Vitor Galvao](https://github.com/vitorgalvao), [JCount](https://github.com/jcount), [Misty De Meo](https://github.com/mistydemeo), [Gautham Goli](https://github.com/GauthamGoli), [Markus Reiter](https://github.com/reitermarkus), [Jonathan Chang](https://github.com/jonchang) and [William Woodruff](https://github.com/woodruffw).
Homebrew/brew's Linux support (and Linuxbrew) maintainers are [Michka Popoff](https://github.com/imichka) and [Shaun Jackman](https://github.com/sjackman). Homebrew/brew's Linux support (and Linuxbrew) maintainers are [Michka Popoff](https://github.com/imichka) and [Shaun Jackman](https://github.com/sjackman).

View File

@ -576,7 +576,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
Options for the `install` command are also valid here. Options for the `install` command are also valid here.
If `--cleanup` is specified or `HOMEBREW_UPGRADE_CLEANUP` is set then remove If `--cleanup` is specified or `HOMEBREW_UPGRADE_CLEANUP` is set then remove
previously installed `formula` version(s). previously installed version(s) of upgraded `formulae`.
If `--fetch-HEAD` is passed, fetch the upstream repository to detect if If `--fetch-HEAD` is passed, fetch the upstream repository to detect if
the HEAD installation of the formula is outdated. Otherwise, the the HEAD installation of the formula is outdated. Otherwise, the
@ -967,9 +967,9 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
`brew bundle check` [`--no-upgrade`] [`--file`=`path`|`--global`] `brew bundle check` [`--no-upgrade`] [`--file`=`path`|`--global`] [`--verbose`]
Check if all dependencies are installed in a Brewfile. Check if all dependencies are installed in a Brewfile. Missing dependencies are listed in verbose mode. `check` will exit on the first category missing a dependency unless in verbose mode.
@ -1316,7 +1316,7 @@ Homebrew's lead maintainer is Mike McQuaid.
Homebrew's project leadership committee is Mike McQuaid, JCount, Misty De Meo and Markus Reiter. Homebrew's project leadership committee is Mike McQuaid, JCount, Misty De Meo and Markus Reiter.
Homebrew/brew's other current maintainers are Dominyk Tiller, Claudia, Michka Popoff, Shaun Jackman, Chongyu Zhu, commitay, Vitor Galvao, JCount, Misty De Meo, Gautham Goli, Markus Reiter and William Woodruff. Homebrew/brew's other current maintainers are Dominyk Tiller, Claudia, Michka Popoff, Shaun Jackman, Chongyu Zhu, commitay, Vitor Galvao, JCount, Misty De Meo, Gautham Goli, Markus Reiter, Jonathan Chang and William Woodruff.
Homebrew/brew's Linux support (and Linuxbrew) maintainers are Michka Popoff and Shaun Jackman. Homebrew/brew's Linux support (and Linuxbrew) maintainers are Michka Popoff and Shaun Jackman.

View File

@ -524,7 +524,7 @@ If \fB\-\-force\fR (or \fB\-f\fR) is specified then always do a slower, full upd
Options for the \fBinstall\fR command are also valid here\. Options for the \fBinstall\fR command are also valid here\.
. .
.IP .IP
If \fB\-\-cleanup\fR is specified or \fBHOMEBREW_UPGRADE_CLEANUP\fR is set then remove previously installed \fIformula\fR version(s)\. If \fB\-\-cleanup\fR is specified or \fBHOMEBREW_UPGRADE_CLEANUP\fR is set then remove previously installed version(s) of upgraded \fIformulae\fR\.
. .
.IP .IP
If \fB\-\-fetch\-HEAD\fR is passed, fetch the upstream repository to detect if the HEAD installation of the formula is outdated\. Otherwise, the repository\'s HEAD will be checked for updates when a new stable or devel version has been released\. If \fB\-\-fetch\-HEAD\fR is passed, fetch the upstream repository to detect if the HEAD installation of the formula is outdated\. Otherwise, the repository\'s HEAD will be checked for updates when a new stable or devel version has been released\.
@ -914,10 +914,10 @@ Write all installed casks/formulae/taps into a Brewfile\.
Uninstall all dependencies not listed in a Brewfile\. Uninstall all dependencies not listed in a Brewfile\.
. .
.IP .IP
\fBbrew bundle check\fR [\fB\-\-no\-upgrade\fR] [\fB\-\-file\fR=\fIpath\fR|\fB\-\-global\fR] \fBbrew bundle check\fR [\fB\-\-no\-upgrade\fR] [\fB\-\-file\fR=\fIpath\fR|\fB\-\-global\fR] [\fB\-\-verbose\fR]
. .
.IP .IP
Check if all dependencies are installed in a Brewfile\. Check if all dependencies are installed in a Brewfile\. Missing dependencies are listed in verbose mode\. \fBcheck\fR will exit on the first category missing a dependency unless in verbose mode\.
. .
.IP .IP
\fBbrew bundle exec\fR \fIcommand\fR \fBbrew bundle exec\fR \fIcommand\fR
@ -1275,7 +1275,7 @@ Homebrew\'s lead maintainer is Mike McQuaid\.
Homebrew\'s project leadership committee is Mike McQuaid, JCount, Misty De Meo and Markus Reiter\. Homebrew\'s project leadership committee is Mike McQuaid, JCount, Misty De Meo and Markus Reiter\.
. .
.P .P
Homebrew/brew\'s other current maintainers are Dominyk Tiller, Claudia, Michka Popoff, Shaun Jackman, Chongyu Zhu, commitay, Vitor Galvao, JCount, Misty De Meo, Gautham Goli, Markus Reiter and William Woodruff\. Homebrew/brew\'s other current maintainers are Dominyk Tiller, Claudia, Michka Popoff, Shaun Jackman, Chongyu Zhu, commitay, Vitor Galvao, JCount, Misty De Meo, Gautham Goli, Markus Reiter, Jonathan Chang and William Woodruff\.
. .
.P .P
Homebrew/brew\'s Linux support (and Linuxbrew) maintainers are Michka Popoff and Shaun Jackman\. Homebrew/brew\'s Linux support (and Linuxbrew) maintainers are Michka Popoff and Shaun Jackman\.