Merge pull request #20360 from lukarajic/cask-size

Add a flag to `brew info` to view the size of each formula and cask
This commit is contained in:
Mike McQuaid 2025-08-05 13:54:14 +00:00 committed by GitHub
commit 3f3ddb8b9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
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