Merge pull request #8145 from MLH-Fellowship/integrate-uses

uses: Print cask uses
This commit is contained in:
Mike McQuaid 2020-08-03 09:07:22 +01:00 committed by GitHub
commit a3efb35b0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 171 additions and 107 deletions

View File

@ -4,7 +4,7 @@ require "formula"
require "ostruct" require "ostruct"
require "cli/parser" require "cli/parser"
require "cask/caskroom" require "cask/caskroom"
require "cask_dependent" require "dependencies_helpers"
module Homebrew module Homebrew
extend DependenciesHelpers extend DependenciesHelpers
@ -110,16 +110,6 @@ module Homebrew
puts all_deps puts all_deps
end end
def dependents(formulae_or_casks)
formulae_or_casks.map do |formula_or_cask|
if formula_or_cask.is_a?(Formula)
formula_or_cask
else
CaskDependent.new(formula_or_cask)
end
end
end
def sorted_dependents(formulae_or_casks) def sorted_dependents(formulae_or_casks)
dependents(formulae_or_casks).sort_by(&:name) dependents(formulae_or_casks).sort_by(&:name)
end end

View File

@ -6,6 +6,8 @@
require "formula" require "formula"
require "cli/parser" require "cli/parser"
require "cask/caskroom"
require "dependencies_helpers"
module Homebrew module Homebrew
extend DependenciesHelpers extend DependenciesHelpers
@ -68,39 +70,22 @@ module Homebrew
!args.include_optional? && !args.include_optional? &&
!args.skip_recommended? !args.skip_recommended?
recursive = args.recursive?
includes, ignores = args_includes_ignores(args)
uses = if use_runtime_dependents && !used_formulae_missing uses = if use_runtime_dependents && !used_formulae_missing
used_formulae.map(&:runtime_installed_formula_dependents) used_formulae.map(&:runtime_installed_formula_dependents)
.reduce(&:&) .reduce(&:&)
.select(&:any_version_installed?) .select(&:any_version_installed?) +
select_used_dependents(dependents(Cask::Caskroom.casks), used_formulae, recursive, includes, ignores)
else else
formulae = args.installed? ? Formula.installed : Formula deps = if args.installed?
recursive = args.recursive? dependents(Formula.installed + Cask::Caskroom.casks)
includes, ignores = args_includes_ignores(args) else
dependents(Formula.to_a + Cask::Cask.to_a)
formulae.select do |f|
deps = if recursive
recursive_includes(Dependency, f, includes, ignores)
else
reject_ignores(f.deps, ignores, includes)
end
used_formulae.all? do |ff|
deps.any? do |dep|
match = begin
dep.to_formula.full_name == ff.full_name if dep.name.include?("/")
rescue
nil
end
next match unless match.nil?
dep.name == ff.name
end
rescue FormulaUnavailableError
# Silently ignore this case as we don't care about things used in
# taps that aren't currently tapped.
next
end
end end
select_used_dependents(deps, used_formulae, recursive, includes, ignores)
end end
return if uses.empty? return if uses.empty?
@ -108,4 +93,31 @@ module Homebrew
puts Formatter.columns(uses.map(&:full_name).sort) puts Formatter.columns(uses.map(&:full_name).sort)
odie "Missing formulae should not have dependents!" if used_formulae_missing odie "Missing formulae should not have dependents!" if used_formulae_missing
end end
def select_used_dependents(dependents, used_formulae, recursive, includes, ignores)
dependents.select do |d|
deps = if recursive
recursive_includes(Dependency, d, includes, ignores)
else
reject_ignores(d.deps, ignores, includes)
end
used_formulae.all? do |ff|
deps.any? do |dep|
match = begin
dep.to_formula.full_name == ff.full_name if dep.name.include?("/")
rescue
nil
end
next match unless match.nil?
dep.name == ff.name
end
rescue FormulaUnavailableError
# Silently ignore this case as we don't care about things used in
# taps that aren't currently tapped.
next
end
end
end
end end

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "delegate" require "delegate"
require "cask_dependent"
class Dependencies < DelegateClass(Array) class Dependencies < DelegateClass(Array)
def initialize(*args) def initialize(*args)
@ -55,71 +56,3 @@ class Requirements < DelegateClass(Set)
"#<#{self.class.name}: {#{to_a.join(", ")}}>" "#<#{self.class.name}: {#{to_a.join(", ")}}>"
end end
end end
module DependenciesHelpers
def args_includes_ignores(args)
includes = []
ignores = []
if args.include_build?
includes << "build?"
else
ignores << "build?"
end
if args.include_test?
includes << "test?"
else
ignores << "test?"
end
if args.include_optional?
includes << "optional?"
else
ignores << "optional?"
end
ignores << "recommended?" if args.skip_recommended?
[includes, ignores]
end
def recursive_includes(klass, root_dependent, includes, ignores)
type = if klass == Dependency
:dependencies
elsif klass == Requirement
:requirements
else
raise ArgumentError, "Invalid class argument: #{klass}"
end
root_dependent.send("recursive_#{type}") do |dependent, dep|
if dep.recommended?
klass.prune if ignores.include?("recommended?") || dependent.build.without?(dep)
elsif dep.optional?
klass.prune if !includes.include?("optional?") && !dependent.build.with?(dep)
elsif dep.build? || dep.test?
keep = false
keep ||= dep.test? && includes.include?("test?") && dependent == root_dependent
keep ||= dep.build? && includes.include?("build?")
klass.prune unless keep
end
# If a tap isn't installed, we can't find the dependencies of one of
# its formulae, and an exception will be thrown if we try.
if type == :dependencies &&
dep.is_a?(TapDependency) &&
!dep.tap.installed?
Dependency.keep_but_prune_recursive_deps
end
end
end
def reject_ignores(dependables, ignores, includes)
dependables.reject do |dep|
next false unless ignores.any? { |ignore| dep.send(ignore) }
includes.none? { |include| dep.send(include) }
end
end
end

View File

@ -0,0 +1,82 @@
# frozen_string_literal: true
require "cask_dependent"
module DependenciesHelpers
def args_includes_ignores(args)
includes = []
ignores = []
if args.include_build?
includes << "build?"
else
ignores << "build?"
end
if args.include_test?
includes << "test?"
else
ignores << "test?"
end
if args.include_optional?
includes << "optional?"
else
ignores << "optional?"
end
ignores << "recommended?" if args.skip_recommended?
[includes, ignores]
end
def recursive_includes(klass, root_dependent, includes, ignores)
type = if klass == Dependency
:dependencies
elsif klass == Requirement
:requirements
else
raise ArgumentError, "Invalid class argument: #{klass}"
end
root_dependent.send("recursive_#{type}") do |dependent, dep|
if dep.recommended?
klass.prune if ignores.include?("recommended?") || dependent.build.without?(dep)
elsif dep.optional?
klass.prune if !includes.include?("optional?") && !dependent.build.with?(dep)
elsif dep.build? || dep.test?
keep = false
keep ||= dep.test? && includes.include?("test?") && dependent == root_dependent
keep ||= dep.build? && includes.include?("build?")
klass.prune unless keep
end
# If a tap isn't installed, we can't find the dependencies of one of
# its formulae, and an exception will be thrown if we try.
if type == :dependencies &&
dep.is_a?(TapDependency) &&
!dep.tap.installed?
Dependency.keep_but_prune_recursive_deps
end
end
end
def reject_ignores(dependables, ignores, includes)
dependables.reject do |dep|
next false unless ignores.any? { |ignore| dep.send(ignore) }
includes.none? { |include| dep.send(include) }
end
end
def dependents(formulae_or_casks)
formulae_or_casks.map do |formula_or_cask|
if formula_or_cask.is_a?(Formula)
formula_or_cask
else
CaskDependent.new(formula_or_cask)
end
end
end
module_function :dependents
end

View File

@ -0,0 +1,47 @@
# frozen_string_literal: true
require "dependencies_helpers"
describe DependenciesHelpers do
specify "#dependents" do
foo = formula "foo" do
url "foo"
version "1.0"
end
foo_cask = Cask::CaskLoader.load(+<<-RUBY)
cask "foo_cask" do
end
RUBY
bar = formula "bar" do
url "bar-url"
version "1.0"
end
bar_cask = Cask::CaskLoader.load(+<<-RUBY)
cask "bar-cask" do
end
RUBY
methods = [
:name,
:full_name,
:runtime_dependencies,
:deps,
:requirements,
:recursive_dependencies,
:recursive_requirements,
:any_version_installed?,
]
dependents = described_class.dependents([foo, foo_cask, bar, bar_cask])
dependents.each do |dependent|
methods.each do |method|
expect(dependent.respond_to?(method))
.to be true
end
end
end
end