dev-cmd/unbottled: add new command.

Add a new command to list formulae that aren't bottled for a given OS.
This commit is contained in:
Mike McQuaid 2020-11-26 08:17:20 +00:00
parent 4b1ef4e41b
commit 135b5a3679
No known key found for this signature in database
GPG Key ID: 48A898132FD8EE70
5 changed files with 201 additions and 0 deletions

View File

@ -0,0 +1,166 @@
# typed: true
# frozen_string_literal: true
require "cli/parser"
require "formula"
module Homebrew
extend T::Sig
module_function
sig { returns(CLI::Parser) }
def unbottled_args
Homebrew::CLI::Parser.new do
usage_banner <<~EOS
`unbottled` [<formula>]
Outputs the unbottled dependents of formulae.
EOS
flag "--tag=",
description: "Use the specified bottle tag (e.g. big_sur) instead of the current OS."
switch "--dependents",
description: "Don't get analytics data and sort by number of dependents instead."
switch "--total",
description: "Output the number of unbottled and total formulae."
conflicts "--dependents", "--total"
end
end
sig { void }
def unbottled
args = unbottled_args.parse
Formulary.enable_factory_cache!
@bottle_tag = if args.tag.present?
args.tag.to_sym
else
Utils::Bottles.tag
end
if args.named.blank?
ohai "Getting formulae..."
elsif args.total?
raise UsageError, "cannot specify `<formula>` and `--total`."
end
formulae, all_formulae, sort, formula_installs =
formulae_all_sort_installs_from_args(args)
deps_hash, uses_hash = deps_uses_from_formulae(all_formulae)
if args.dependents?
formula_dependents = {}
formulae = formulae.sort_by do |f|
dependents = uses_hash[f.name]&.length || 0
formula_dependents[f.name] ||= dependents
end.reverse
end
if args.total?
output_total(formulae)
return
end
noun, hash = if args.named.present?
[nil, {}]
elsif args.dependents?
["dependents", formula_dependents]
else
["installs", formula_installs]
end
output_unbottled(sort, formulae, deps_hash, noun, hash)
end
def formulae_all_sort_installs_from_args(args)
if args.named.present?
formulae = all_formulae = args.named.to_formulae
elsif args.total?
formulae = all_formulae = Formula.to_a
elsif args.dependents?
formulae = all_formulae = Formula.to_a
sort = " (sorted by installs in the last 90 days)"
else
formula_installs = {}
ohai "Getting analytics data..."
analytics = Utils::Analytics.formulae_brew_sh_json("analytics/install/90d.json")
formulae = analytics["items"].map do |i|
f = i["formula"].split.first
next if f.include?("/")
next if formula_installs[f].present?
formula_installs[f] = i["count"]
begin
Formula[f]
rescue FormulaUnavailableError
nil
end
end.compact
sort = " (sorted by installs in the last 90 days)"
all_formulae = Formula
end
[formulae, all_formulae, sort, formula_installs]
end
def deps_uses_from_formulae(all_formulae)
ohai "Populating dependency tree..."
deps_hash = {}
uses_hash = {}
all_formulae.each do |f|
next unless f.core_formula?
deps = f.recursive_dependencies do |_, dep|
Dependency.prune if dep.optional?
end.map(&:to_formula)
deps_hash[f.name] = deps
deps.each do |dep|
uses_hash[dep.name] ||= []
uses_hash[dep.name] << f
end
end
[deps_hash, uses_hash]
end
def output_total(formulae)
ohai "Unbottled :#{@bottle_tag} formulae"
unbottled_formulae = 0
formulae.each do |f|
next if f.bottle_specification.tag?(@bottle_tag)
next if f.bottle_unneeded?
unbottled_formulae += 1
end
puts "#{unbottled_formulae}/#{formulae.length} remaining."
end
def output_unbottled(sort, formulae, deps_hash, noun, hash)
ohai "Unbottled :#{@bottle_tag} dependencies#{sort}"
any_found = T.let(false, T::Boolean)
formulae.each do |f|
next if f.bottle_specification.tag?(@bottle_tag)
deps = Array(deps_hash[f.name]).reject do |dep|
dep.bottle_specification.tag?(@bottle_tag) || dep.bottle_unneeded?
end
next if deps.blank?
any_found ||= true
count = " (#{hash[f.name]} #{noun})" if noun
puts "#{f.name}#{count}: #{deps.join(" ")}"
end
return if any_found
puts "No unbottled dependencies found!"
end
end

View File

@ -0,0 +1,8 @@
# typed: false
# frozen_string_literal: true
require "cmd/shared_examples/args_parse"
describe "Homebrew.unbottled_args" do
it_behaves_like "parseable arguments"
end

View File

@ -87,6 +87,7 @@ tc
test test
tests tests
typecheck typecheck
unbottled
uninstal uninstal
uninstall uninstall
unlink unlink

View File

@ -1278,6 +1278,17 @@ Check for typechecking errors using Sorbet.
* `--ignore`: * `--ignore`:
Ignores input files that contain the given string in their paths (relative to the input path passed to Sorbet). Ignores input files that contain the given string in their paths (relative to the input path passed to Sorbet).
### `unbottled` [*`formula`*]
Outputs the unbottled dependents of formulae.
* `--tag`:
Use the specified bottle tag (e.g. big_sur) instead of the current OS.
* `--dependents`:
Don't get analytics data and sort by number of dependents instead.
* `--total`:
Output the number of unbottled and total formulae.
### `unpack` [*`options`*] *`formula`* ### `unpack` [*`options`*] *`formula`*
Unpack the source files for *`formula`* into subdirectories of the current Unpack the source files for *`formula`* into subdirectories of the current

View File

@ -1768,6 +1768,21 @@ Typecheck a single file\.
\fB\-\-ignore\fR \fB\-\-ignore\fR
Ignores input files that contain the given string in their paths (relative to the input path passed to Sorbet)\. Ignores input files that contain the given string in their paths (relative to the input path passed to Sorbet)\.
. .
.SS "\fBunbottled\fR [\fIformula\fR]"
Outputs the unbottled dependents of formulae\.
.
.TP
\fB\-\-tag\fR
Use the specified bottle tag (e\.g\. big_sur) instead of the current OS\.
.
.TP
\fB\-\-dependents\fR
Don\'t get analytics data and sort by number of dependents instead\.
.
.TP
\fB\-\-total\fR
Output the number of unbottled and total formulae\.
.
.SS "\fBunpack\fR [\fIoptions\fR] \fIformula\fR" .SS "\fBunpack\fR [\fIoptions\fR] \fIformula\fR"
Unpack the source files for \fIformula\fR into subdirectories of the current working directory\. Unpack the source files for \fIformula\fR into subdirectories of the current working directory\.
. .