Merge remote-tracking branch 'origin/master' into cache-optimization

This commit is contained in:
AndrewMcBurney 2018-04-25 10:04:36 -04:00
commit 27e5d1aee5
14 changed files with 109 additions and 29 deletions

View File

@ -472,9 +472,17 @@ class Pathname
} }
end end
def binary_executable?
false
end
def mach_o_bundle? def mach_o_bundle?
false false
end end
def dylib?
false
end
end end
require "extend/os/pathname" require "extend/os/pathname"

View File

@ -12,6 +12,7 @@ require "install_renamed"
require "pkg_version" require "pkg_version"
require "keg" require "keg"
require "migrator" require "migrator"
require "linkage_checker"
require "extend/ENV" require "extend/ENV"
require "language/python" require "language/python"
require "tab" require "tab"
@ -1486,22 +1487,50 @@ class Formula
Requirement.expand(self, &block) Requirement.expand(self, &block)
end end
# Returns a Keg for the opt_prefix or installed_prefix if they exist.
# If not, return nil.
# @private
def opt_or_installed_prefix_keg
if optlinked? && opt_prefix.exist?
Keg.new(opt_prefix)
elsif installed_prefix.directory?
Keg.new(installed_prefix)
end
end
# Returns a list of Dependency objects that are required at runtime. # Returns a list of Dependency objects that are required at runtime.
# @private # @private
def runtime_dependencies(read_from_tab: true) def runtime_dependencies(read_from_tab: true)
if read_from_tab && if read_from_tab &&
installed_prefix.directory? && installed_prefix.directory? &&
(keg = Keg.new(installed_prefix)) && (keg = opt_or_installed_prefix_keg) &&
(tab_deps = keg.runtime_dependencies) (tab_deps = keg.runtime_dependencies)
return tab_deps.map { |d| Dependency.new d["full_name"] }.compact return tab_deps.map { |d| Dependency.new d["full_name"] }.compact
end end
declared_runtime_dependencies | undeclared_runtime_dependencies
end
# Returns a list of Dependency objects that are declared in the formula.
# @private
def declared_runtime_dependencies
recursive_dependencies do |_, dependency| recursive_dependencies do |_, dependency|
Dependency.prune if dependency.build? Dependency.prune if dependency.build?
Dependency.prune if !dependency.required? && build.without?(dependency) Dependency.prune if !dependency.required? && build.without?(dependency)
end end
end end
# Returns a list of Dependency objects that are not declared in the formula
# but the formula links to.
# @private
def undeclared_runtime_dependencies
keg = opt_or_installed_prefix_keg
return [] unless keg
linkage_checker = LinkageChecker.new(keg, self)
linkage_checker.undeclared_deps.map { |n| Dependency.new(n) }
end
# Returns a list of formulae depended on by this formula that aren't # Returns a list of formulae depended on by this formula that aren't
# installed # installed
def missing_dependencies(hide: nil) def missing_dependencies(hide: nil)

View File

@ -100,7 +100,7 @@ class LinkageChecker
checked_dylibs = Set.new checked_dylibs = Set.new
@keg.find do |file| @keg.find do |file|
next if file.symlink? || file.directory? next if file.symlink? || file.directory?
next unless file.dylib? || file.binary_executable? || file.mach_o_bundle? next if !file.dylib? && !file.binary_executable? && !file.mach_o_bundle?
# weakly loaded dylibs may not actually exist on disk, so skip them # weakly loaded dylibs may not actually exist on disk, so skip them
# when checking for broken linkage # when checking for broken linkage
@ -145,10 +145,17 @@ class LinkageChecker
next false unless dep.optional? || dep.recommended? next false unless dep.optional? || dep.recommended?
formula.build.without?(dep) formula.build.without?(dep)
end end
declared_deps = formula.deps.reject { |dep| filter_out.call(dep) }.map(&:name) declared_deps = formula.deps.reject { |dep| filter_out.call(dep) }.map(&:name)
runtime_deps = keg.to_formula.runtime_dependencies(read_from_tab: false)
recursive_deps = runtime_deps.map { |dep| dep.to_formula.name }
declared_dep_names = declared_deps.map { |dep| dep.split("/").last } declared_dep_names = declared_deps.map { |dep| dep.split("/").last }
recursive_deps = formula.declared_runtime_dependencies.map do |dep|
begin
dep.to_formula.name
rescue FormulaUnavailableError
nil
end
end.compact
indirect_deps = [] indirect_deps = []
undeclared_deps = [] undeclared_deps = []
@brewed_dylibs.each_key do |full_name| @brewed_dylibs.each_key do |full_name|
@ -160,15 +167,19 @@ class LinkageChecker
undeclared_deps << full_name undeclared_deps << full_name
end end
end end
sort_by_formula_full_name!(indirect_deps) sort_by_formula_full_name!(indirect_deps)
sort_by_formula_full_name!(undeclared_deps) sort_by_formula_full_name!(undeclared_deps)
unnecessary_deps = declared_dep_names.reject do |full_name| unnecessary_deps = declared_dep_names.reject do |full_name|
name = full_name.split("/").last name = full_name.split("/").last
next true if Formula[name].bin.directory? next true if Formula[name].bin.directory?
@brewed_dylibs.keys.map { |x| x.split("/").last }.include?(name) @brewed_dylibs.keys.map { |x| x.split("/").last }.include?(name)
end end
missing_deps = @broken_deps.values.flatten.map { |d| dylib_to_dep(d) } missing_deps = @broken_deps.values.flatten.map { |d| dylib_to_dep(d) }
unnecessary_deps -= missing_deps unnecessary_deps -= missing_deps
[indirect_deps, undeclared_deps, unnecessary_deps] [indirect_deps, undeclared_deps, unnecessary_deps]
end end

View File

@ -93,7 +93,7 @@ module Homebrew
new_tap = old_tap.tap_migrations[name] new_tap = old_tap.tap_migrations[name]
next unless new_tap next unless new_tap
new_tap_user, new_tap_repo, = new_tap.split("/") new_tap_user, new_tap_repo, new_tap_new_name = new_tap.split("/")
new_tap_name = "#{new_tap_user}/#{new_tap_repo}" new_tap_name = "#{new_tap_user}/#{new_tap_repo}"
message = <<~EOS message = <<~EOS
@ -101,9 +101,18 @@ module Homebrew
EOS EOS
break if new_tap_name == CoreTap.instance.name break if new_tap_name == CoreTap.instance.name
install_cmd = if new_tap_user == "caskroom"
"cask install"
else
"install"
end
new_tap_new_name ||= name
message += <<~EOS message += <<~EOS
You can access it again by running: You can access it again by running:
brew tap #{new_tap_name} brew tap #{new_tap_name}
And then you can install it by running:
brew #{install_cmd} #{new_tap_new_name}
EOS EOS
break break
end end

View File

@ -2,7 +2,7 @@ require_relative "./extend/formula_cop"
module RuboCop module RuboCop
module Cop module Cop
module FormulaAuditStrict module FormulaAudit
# This cop checks for correct order of components in a Formula # This cop checks for correct order of components in a Formula
# #
# - component_precedence_list has component hierarchy in a nested list # - component_precedence_list has component hierarchy in a nested list
@ -62,8 +62,14 @@ module RuboCop
end end
end end
# `aspell`: options and resources should be grouped by language
WHITELIST = %w[
aspell
].freeze
# Method to format message for reporting component precedence violations # Method to format message for reporting component precedence violations
def component_problem(c1, c2) def component_problem(c1, c2)
return if WHITELIST.include?(@formula_name)
problem "`#{format_component(c1)}` (line #{line_number(c1)}) should be put before `#{format_component(c2)}` (line #{line_number(c2)})" problem "`#{format_component(c1)}` (line #{line_number(c1)}) should be put before `#{format_component(c2)}` (line #{line_number(c2)})"
end end

View File

@ -2,7 +2,7 @@ require_relative "./extend/formula_cop"
module RuboCop module RuboCop
module Cop module Cop
module FormulaAuditStrict module FormulaAudit
# This cop checks if redundant components are present and other component errors # This cop checks if redundant components are present and other component errors
# #
# - `url|checksum|mirror` should be inside `stable` block # - `url|checksum|mirror` should be inside `stable` block

View File

@ -3,7 +3,7 @@ require_relative "../extend/string"
module RuboCop module RuboCop
module Cop module Cop
module FormulaAuditStrict module FormulaAudit
# This cop audits `desc` in Formulae # This cop audits `desc` in Formulae
# #
# - Checks for existence of `desc` # - Checks for existence of `desc`
@ -33,7 +33,9 @@ module RuboCop
"Length is calculated as #{@formula_name} + desc. (currently #{desc_length})" "Length is calculated as #{@formula_name} + desc. (currently #{desc_length})"
end end
end end
end
module FormulaAuditStrict
# This cop audits `desc` in Formulae # This cop audits `desc` in Formulae
# #
# - Checks if `desc` begins with an article # - Checks if `desc` begins with an article

View File

@ -191,8 +191,7 @@ module RuboCop
end end
end end
end end
end
module FormulaAuditStrict
class PyPiUrls < FormulaCop class PyPiUrls < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
urls = find_every_func_call_by_name(body_node, :url) urls = find_every_func_call_by_name(body_node, :url)

View File

@ -685,26 +685,42 @@ describe Formula do
expect(f5.runtime_dependencies.map(&:name)).to eq(["f1", "f4"]) expect(f5.runtime_dependencies.map(&:name)).to eq(["f1", "f4"])
end end
specify "runtime dependencies with optional deps from tap" do describe "#runtime_dependencies" do
tap_loader = double specify "runtime dependencies with optional deps from tap" do
tap_loader = double
allow(tap_loader).to receive(:get_formula).and_raise(RuntimeError, "tried resolving tap formula") allow(tap_loader).to receive(:get_formula).and_raise(RuntimeError, "tried resolving tap formula")
allow(Formulary).to receive(:loader_for).with("foo/bar/f1", from: nil).and_return(tap_loader) allow(Formulary).to receive(:loader_for).with("foo/bar/f1", from: nil).and_return(tap_loader)
stub_formula_loader(formula("f2") { url("f2-1.0") }, "baz/qux/f2") stub_formula_loader(formula("f2") { url("f2-1.0") }, "baz/qux/f2")
f3 = formula "f3" do f3 = formula "f3" do
url "f3-1.0" url "f3-1.0"
depends_on "foo/bar/f1" => :optional depends_on "foo/bar/f1" => :optional
depends_on "baz/qux/f2" depends_on "baz/qux/f2"
end
expect(f3.runtime_dependencies.map(&:name)).to eq(["baz/qux/f2"])
stub_formula_loader(formula("f1") { url("f1-1.0") }, "foo/bar/f1")
f3.build = BuildOptions.new(Options.create(["--with-f1"]), f3.options)
expect(f3.runtime_dependencies.map(&:name)).to eq(["foo/bar/f1", "baz/qux/f2"])
end end
expect(f3.runtime_dependencies.map(&:name)).to eq(["baz/qux/f2"]) it "includes non-declared direct dependencies", :focus do
formula = Class.new(Testball).new
dependency = formula("dependency") { url "f-1.0" }
stub_formula_loader(formula("f1") { url("f1-1.0") }, "foo/bar/f1") formula.brew { formula.install }
f3.build = BuildOptions.new(Options.create(["--with-f1"]), f3.options) keg = Keg.for(formula.installed_prefix)
keg.link
expect(f3.runtime_dependencies.map(&:name)).to eq(["foo/bar/f1", "baz/qux/f2"]) linkage_checker = double("linkage checker", undeclared_deps: [dependency.name])
allow(LinkageChecker).to receive(:new).and_return(linkage_checker)
expect(formula.runtime_dependencies.map(&:name)).to eq [dependency.name]
end
end end
specify "requirements" do specify "requirements" do

View File

@ -1,6 +1,6 @@
require_relative "../../rubocops/components_order_cop" require_relative "../../rubocops/components_order_cop"
describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "When auditing formula components order" do context "When auditing formula components order" do

View File

@ -1,6 +1,6 @@
require_relative "../../rubocops/components_redundancy_cop" require_relative "../../rubocops/components_redundancy_cop"
describe RuboCop::Cop::FormulaAuditStrict::ComponentsRedundancy do describe RuboCop::Cop::FormulaAudit::ComponentsRedundancy do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "When auditing formula components common errors" do context "When auditing formula components common errors" do

View File

@ -1,6 +1,6 @@
require_relative "../../rubocops/formula_desc_cop" require_relative "../../rubocops/formula_desc_cop"
describe RuboCop::Cop::FormulaAuditStrict::DescLength do describe RuboCop::Cop::FormulaAudit::DescLength do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "When auditing formula desc" do context "When auditing formula desc" do

View File

@ -164,7 +164,7 @@ describe RuboCop::Cop::FormulaAudit::Urls do
end end
end end
describe RuboCop::Cop::FormulaAuditStrict::PyPiUrls do describe RuboCop::Cop::FormulaAudit::PyPiUrls do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "when a pypi.python.org URL is used" do context "when a pypi.python.org URL is used" do

View File

@ -22,7 +22,7 @@ Second, read the [Troubleshooting Checklist](https://docs.brew.sh/Troubleshootin
[![Travis](https://img.shields.io/travis/Homebrew/brew.svg)](https://travis-ci.org/Homebrew/brew) [![Travis](https://img.shields.io/travis/Homebrew/brew.svg)](https://travis-ci.org/Homebrew/brew)
[![Codecov](https://img.shields.io/codecov/c/github/Homebrew/brew.svg)](https://codecov.io/gh/Homebrew/brew) [![Codecov](https://img.shields.io/codecov/c/github/Homebrew/brew.svg)](https://codecov.io/gh/Homebrew/brew)
We'd love you to contribute to Homebrew. First, please read our [Contribution Guide](https://github.com/Homebrew/brew/blob/master/CONTRIBUTING.md) and [Code of Conduct](https://github.com/Homebrew/brew/blob/master/CODE_OF_CONDUCT.md#code-of-conduct). We'd love you to contribute to Homebrew. First, please read our [Contribution Guide](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md#code-of-conduct).
We explicitly welcome contributions from people who have never contributed to open-source before: we were all beginners once! We can help build on a partially working pull request with the aim of getting it merged. We are also actively seeking to diversify our contributors and especially welcome contributions from women from all backgrounds and people of colour. We explicitly welcome contributions from people who have never contributed to open-source before: we were all beginners once! We can help build on a partially working pull request with the aim of getting it merged. We are also actively seeking to diversify our contributors and especially welcome contributions from women from all backgrounds and people of colour.
@ -52,7 +52,7 @@ Former maintainers with significant contributions include [Tim Smith](https://gi
- [@MacHomebrew (Twitter)](https://twitter.com/MacHomebrew) - [@MacHomebrew (Twitter)](https://twitter.com/MacHomebrew)
## License ## License
Code is under the [BSD 2-clause "Simplified" License](https://github.com/Homebrew/brew/tree/master/LICENSE.txt). Code is under the [BSD 2-clause "Simplified" License](LICENSE.txt).
Documentation is under the [Creative Commons Attribution license](https://creativecommons.org/licenses/by/4.0/). Documentation is under the [Creative Commons Attribution license](https://creativecommons.org/licenses/by/4.0/).
## Donations ## Donations