1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#: * `uses` [`--installed`] [`--recursive`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] [`--devel`|`--HEAD`] <formulae>:
#: Show the formulae that specify <formulae> as a dependency. When given
#: multiple formula arguments, show the intersection of formulae that use
#: <formulae>.
#:
#: Use `--recursive` to resolve more than one level of dependencies.
#:
#: If `--installed` is passed, only list installed formulae.
#:
#: By default, `uses` shows all formulae that specify <formulae> as a required
#: or recommended dependency. To include the `:build` type dependencies, pass
#: `--include-build`. Similarly, pass `--include-optional` to include `:optional`
#: dependencies. To skip `:recommended` type dependencies, pass `--skip-recommended`.
#:
#: By default, `uses` shows usages of <formulae> by stable builds. To find
#: cases where <formulae> is used by development or HEAD build, pass
#: `--devel` or `--HEAD`.
require "formula"
# `brew uses foo bar` returns formulae that use both foo and bar
# If you want the union, run the command twice and concatenate the results.
# The intersection is harder to achieve with shell tools.
module Homebrew
module_function
def uses
raise FormulaUnspecifiedError if ARGV.named.empty?
used_formulae_missing = false
used_formulae = begin
ARGV.formulae
rescue FormulaUnavailableError => e
opoo e
used_formulae_missing = true
# If the formula doesn't exist: fake the needed formula object name.
ARGV.named.map { |name| OpenStruct.new name: name, full_name: name }
end
formulae = ARGV.include?("--installed") ? Formula.installed : Formula
recursive = ARGV.flag? "--recursive"
includes = []
ignores = []
if ARGV.include? "--include-build"
includes << "build?"
else
ignores << "build?"
end
if ARGV.include? "--include-optional"
includes << "optional?"
else
ignores << "optional?"
end
ignores << "recommended?" if ARGV.include? "--skip-recommended"
uses = formulae.select do |f|
used_formulae.all? do |ff|
begin
if recursive
deps = f.recursive_dependencies do |dependent, dep|
if dep.recommended?
Dependency.prune if ignores.include?("recommended?") || dependent.build.without?(dep)
elsif dep.optional?
Dependency.prune if !includes.include?("optional?") && !dependent.build.with?(dep)
elsif dep.build?
Dependency.prune unless includes.include?("build?")
end
# If a tap isn't installed, we can't find the dependencies of one
# its formulae, and an exception will be thrown if we try.
if dep.is_a?(TapDependency) && !dep.tap.installed?
Dependency.keep_but_prune_recursive_deps
end
end
dep_formulae = deps.flat_map do |dep|
begin
dep.to_formula
rescue
[]
end
end
reqs_by_formula = ([f] + dep_formulae).flat_map do |formula|
formula.requirements.map { |req| [formula, req] }
end
reqs_by_formula.reject! do |dependent, req|
if req.recommended?
ignores.include?("recommended?") || dependent.build.without?(req)
elsif req.optional?
!includes.include?("optional?") && !dependent.build.with?(req)
elsif req.build?
!includes.include?("build?")
end
end
reqs = reqs_by_formula.map(&:last)
else
deps = f.deps.reject do |dep|
ignores.any? { |ignore| dep.send(ignore) } && includes.none? { |include| dep.send(include) }
end
reqs = f.requirements.reject do |req|
ignores.any? { |ignore| req.send(ignore) } && includes.none? { |include| req.send(include) }
end
end
next true if deps.any? do |dep|
begin
dep.to_formula.full_name == ff.full_name
rescue
dep.name == ff.name
end
end
reqs.any? do |req|
req.name == ff.name || [ff.name, ff.full_name].include?(req.default_formula)
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
return if uses.empty?
puts Formatter.columns(uses.map(&:full_name).sort)
odie "Missing formulae should not have dependents!" if used_formulae_missing
end
end
|