-
-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
formulae_dependents: apply some optimisations #841
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,8 +8,10 @@ class FormulaeDependents < TestFormulae | |
def run!(args:) | ||
@source_tested_dependents = [] | ||
@bottle_tested_dependents = [] | ||
@testable_formulae = @testing_formulae - skipped_or_failed_formulae | ||
@postinstalled_formulae = [] | ||
|
||
(@testing_formulae - skipped_or_failed_formulae).each do |f| | ||
@testable_formulae.each do |f| | ||
dependent_formulae!(f, args: args) | ||
puts | ||
end | ||
|
@@ -22,19 +24,29 @@ def dependent_formulae!(formula_name, args:) | |
|
||
test_header(:FormulaeDependents, method: "dependent_formulae!(#{formula_name})") | ||
|
||
formula = Formulary.factory(formula_name) | ||
|
||
source_dependents, bottled_dependents, testable_dependents = | ||
dependents_for_formula(formula, formula_name, args: args) | ||
|
||
return if source_dependents.blank? && | ||
bottled_dependents.blank? && | ||
testable_dependents.blank? | ||
|
||
# Install formula dependencies. These will have been uninstalled after building. | ||
test "brew", "install", "--only-dependencies", formula_name, | ||
env: { "HOMEBREW_DEVELOPER" => nil } | ||
return if steps.last.failed? | ||
|
||
# Restore etc/var files that may have been nuked in the build stage. | ||
test "brew", "postinstall", formula_name | ||
formula_dependencies = Utils.safe_popen_read("brew", "deps", formula_name).split("\n") | ||
# Some dependencies will need postinstalling too. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not clear to me why this is the case, can you explain more? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suppose testing formula includes Whenever we test |
||
postinstall_dependencies = @testable_formulae & formula_dependencies | ||
postinstall_formulae = [formula_name, *postinstall_dependencies] - @postinstalled_formulae | ||
test "brew", "postinstall", *postinstall_formulae | ||
return if steps.last.failed? | ||
|
||
formula = Formulary.factory(formula_name) | ||
|
||
source_dependents, bottled_dependents, testable_dependents = | ||
dependents_for_formula(formula, formula_name, args: args) | ||
@postinstalled_formulae += postinstall_formulae | ||
|
||
source_dependents.each do |dependent| | ||
next if @source_tested_dependents.include?(dependent) | ||
|
@@ -54,6 +66,21 @@ def dependent_formulae!(formula_name, args:) | |
end | ||
|
||
def dependents_for_formula(formula, formula_name, args:) | ||
# Calling `brew uses` is slow, so let's reserve doing that for | ||
# if we can find a formula in the same tap that declares a dependency | ||
# on the formula we are testing. | ||
has_dependents = formula.tap.potential_formula_dirs.any? do |dir| | ||
next false unless dir.exist? | ||
|
||
dir.children.any? do |child| | ||
next false unless child.file? | ||
next false unless child.extname == ".rb" | ||
|
||
child.read.include? "depends_on \"#{formula_name}\"" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd really love to avoid something this hacky as this when we have RuboCop AST methods to do this sort of thing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we construct the AST without loading the formula? Because that's part of what's slow here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For example, doing this instead: has_dependents = formula.tap.formula_names.any? do |name|
Formula[name].deps.map(&:name).include? formula_name
end We get:
It's faster than just doing |
||
end | ||
end | ||
return unless has_dependents | ||
|
||
info_header "Determining dependents..." | ||
|
||
uses_args = %w[--formula --eval-all] | ||
|
@@ -64,13 +91,16 @@ def dependents_for_formula(formula, formula_name, args:) | |
.split("\n") | ||
end | ||
|
||
# TODO: Consider handling the following case better. | ||
# `foo` has a build dependency on `bar`, and `bar` has a runtime dependency on | ||
# `baz`. When testing `baz` with `--build-dependents-from-source`, `foo` is | ||
# not tested, but maybe should be. | ||
dependents += with_env(HOMEBREW_STDERR: "1") do | ||
Utils.safe_popen_read("brew", "uses", *uses_args, "--include-build", formula_name) | ||
.split("\n") | ||
# We care about build dependents only if we are building them from source. | ||
if args.build_dependents_from_source? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call. |
||
# TODO: Consider handling the following case better. | ||
# `foo` has a build dependency on `bar`, and `bar` has a runtime dependency on | ||
# `baz`. When testing `baz` with `--build-dependents-from-source`, `foo` is | ||
# not tested, but maybe should be. | ||
dependents += with_env(HOMEBREW_STDERR: "1") do | ||
Utils.safe_popen_read("brew", "uses", *uses_args, "--include-build", formula_name) | ||
.split("\n") | ||
end | ||
end | ||
dependents&.uniq! | ||
dependents&.sort! | ||
|
@@ -104,7 +134,7 @@ def dependents_for_formula(formula, formula_name, args:) | |
next false if OS.linux? && dependent.requirements.exclude?(LinuxRequirement.new) | ||
|
||
all_deps_bottled_or_built = deps.all? do |d| | ||
bottled_or_built?(d.to_formula, @testing_formulae - @skipped_or_failed_formulae) | ||
bottled_or_built?(d.to_formula, @testable_formulae) | ||
end | ||
args.build_dependents_from_source? && all_deps_bottled_or_built | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we calling
brew deps
anywhere else? If so, worth caching?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll have a look, but I don't think so it's used elsewhere.