Add a way to view the size of each installed formula/cask

Change styling based on output of brew typecheck and brew style

Changes as per PR comments

Remove --leaves flag functionality

Simplify formulae and cask parsing as well as style changes as per PR comments

Update cask and formulae parsing as per PR comment suggestion

Add column formatting function as well as PR comment suggestions

Add Sorbet struct for printing and minor logic changes as per PR comments

Minor changes as per PR comments and fix formatting issue in output
This commit is contained in:
Luka Rajic 2025-08-01 16:57:38 -04:00
parent ce237901a0
commit 0c78875616
2 changed files with 78 additions and 1 deletions

View File

@ -16,6 +16,12 @@ require "api"
module Homebrew module Homebrew
module Cmd module Cmd
class Info < AbstractCommand class Info < AbstractCommand
class NameSize < T::Struct
const :name, String
const :size, Integer
end
private_constant :NameSize
VALID_DAYS = %w[30 90 365].freeze VALID_DAYS = %w[30 90 365].freeze
VALID_FORMULA_CATEGORIES = %w[install install-on-request build-error].freeze VALID_FORMULA_CATEGORIES = %w[install install-on-request build-error].freeze
VALID_CATEGORIES = T.let((VALID_FORMULA_CATEGORIES + %w[cask-install os-version]).freeze, T::Array[String]) VALID_CATEGORIES = T.let((VALID_FORMULA_CATEGORIES + %w[cask-install os-version]).freeze, T::Array[String])
@ -67,6 +73,8 @@ module Homebrew
description: "Treat all named arguments as formulae." description: "Treat all named arguments as formulae."
switch "--cask", "--casks", switch "--cask", "--casks",
description: "Treat all named arguments as casks." description: "Treat all named arguments as casks."
switch "--sizes",
description: "Show the size of installed formulae and casks."
conflicts "--installed", "--eval-all" conflicts "--installed", "--eval-all"
conflicts "--installed", "--all" conflicts "--installed", "--all"
@ -79,7 +87,15 @@ module Homebrew
sig { override.void } sig { override.void }
def run def run
if args.analytics? if args.sizes?
if args.no_named?
print_sizes
else
formulae, casks = args.named.to_formulae_to_casks
formulae = T.cast(formulae, T::Array[Formula])
print_sizes(formulae:, casks:)
end
elsif args.analytics?
if args.days.present? && VALID_DAYS.exclude?(args.days) if args.days.present? && VALID_DAYS.exclude?(args.days)
raise UsageError, "`--days` must be one of #{VALID_DAYS.join(", ")}." raise UsageError, "`--days` must be one of #{VALID_DAYS.join(", ")}."
end end
@ -401,6 +417,64 @@ module Homebrew
Cask::Info.info(cask, args:) Cask::Info.info(cask, args:)
end end
sig { params(title: String, items: T::Array[NameSize]).void }
def print_sizes_table(title, items)
return if items.blank?
ohai title
total_size = items.sum(&:size)
total_size_str = disk_usage_readable(total_size)
name_width = (items.map { |item| item.name.length } + [5]).max
size_width = (items.map { |item| disk_usage_readable(item.size).length } + [total_size_str.length]).max
items.each do |item|
puts format("%-#{name_width}s %#{size_width}s", item.name,
disk_usage_readable(item.size))
end
puts format("%-#{name_width}s %#{size_width}s", "Total", total_size_str)
end
sig { params(formulae: T::Array[Formula], casks: T::Array[Cask::Cask]).void }
def print_sizes(formulae: [], casks: [])
if formulae.blank? &&
(args.formulae? || (!args.casks? && args.no_named?))
formulae = Formula.installed
end
if casks.blank? &&
(args.casks? || (!args.formulae? && args.no_named?))
casks = Cask::Caskroom.casks
end
unless args.casks?
formula_sizes = formulae.map do |formula|
kegs = formula.installed_kegs
size = kegs.sum(&:disk_usage)
NameSize.new(name: formula.full_name, size:)
end
formula_sizes.sort_by! { |f| -f.size }
print_sizes_table("Formulae sizes:", formula_sizes)
end
return if casks.blank? || args.formulae?
cask_sizes = casks.filter_map do |cask|
installed_version = cask.installed_version
next unless installed_version.present?
versioned_staged_path = cask.caskroom_path.join(installed_version)
next unless versioned_staged_path.exist?
size = versioned_staged_path.children.sum(&:disk_usage)
NameSize.new(name: cask.full_name, size:)
end
cask_sizes.sort_by! { |c| -c.size }
print_sizes_table("Casks sizes:", cask_sizes)
end
end end
end end
end end

View File

@ -50,6 +50,9 @@ class Homebrew::Cmd::Info::Args < Homebrew::CLI::Args
sig { returns(T.nilable(String)) } sig { returns(T.nilable(String)) }
def json; end def json; end
sig { returns(T::Boolean) }
def sizes?; end
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def variations?; end def variations?; end
end end