Skip to content

info: add --deps flag to --sizes for dependency footprint breakdown#22582

Open
EdenRochmanSharabi wants to merge 5 commits into
Homebrew:mainfrom
EdenRochmanSharabi:info-sizes-deps
Open

info: add --deps flag to --sizes for dependency footprint breakdown#22582
EdenRochmanSharabi wants to merge 5 commits into
Homebrew:mainfrom
EdenRochmanSharabi:info-sizes-deps

Conversation

@EdenRochmanSharabi

Copy link
Copy Markdown

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them? Performance claims (e.g. "this is faster") must include Hyperfine benchmarks.
  • Have you written new tests (excluding integration tests) for your changes? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) with your changes locally?

  • AI was used to generate or assist with generating this PR.

Git processing (branch management, rebasing, PR submission) was assisted by Claude. The implementation logic was written through manual analysis of the existing --sizes code path and Keg#runtime_dependencies.


Summary

Adds a --deps flag (depends on --sizes) to brew info that shows dependency size breakdown:

  • brew info --sizes --deps displays a table with Direct, Exclusive Deps, and Total Footprint columns for all installed formulae
  • brew info --sizes --deps <formula> shows detailed breakdown including exclusive and shared dependencies
  • brew info --sizes --deps -v <formula> shows the full dependency listing with sizes

This addresses the feedback from #22391 where @MikeMcQuaid suggested integrating footprint analysis into --sizes rather than creating a separate command. Replaces #22576 which couldn't be reopened after I mistakenly deleted the branch.

Notes

  • Tests and brew lgtm not yet run (will address once the approach is confirmed)
  • The --eval-all flag was marked as hidden/deprecated in the same commit; happy to split that into a separate PR if preferred

When used with --sizes, the new --deps flag shows the true disk cost
of installed formulae by analyzing exclusive vs shared dependencies.

This addresses the feedback from Homebrew#22391 to integrate footprint analysis
directly into `brew info --sizes` rather than as a separate command.

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You definitely promise you wrote 100% of the actual code by hand and just used Claude for analysis?

Need to slim this down a lot, it's a lot of code for a relatively simple feature. Also needs some (non-integration) tests.

Thanks!

Comment thread Library/Homebrew/cmd/info.rb Outdated
Comment thread Library/Homebrew/cmd/info.rb Outdated
Comment thread Library/Homebrew/cmd/info.rb Outdated
Comment thread Library/Homebrew/cmd/info.rb Outdated
Comment thread Library/Homebrew/cmd/info.rb Outdated
@EdenRochmanSharabi

Copy link
Copy Markdown
Author

Yes, I wrote all the code by hand. I used Claude to review it and suggest improvements, but I always rewrote those suggestions myself to avoid the endless slop you get from AI-generated code. That's why I wrote that I wrote the code by hand. Maybe my coding level isn't quite there yet for this project, sorry. I'd understand if you rejected it.

I'll slim it down and add tests.

@MikeMcQuaid

Copy link
Copy Markdown
Member

Thanks for clarifying and opening the PR @EdenRochmanSharabi!

EdenRochmanSharabi and others added 2 commits June 8, 2026 15:25
Inline build_reverse_dep_map, analyze_formula_footprint,
print_footprint_table, and print_footprint_single into
print_sizes_with_deps since each was only called once.
Use Array() instead of is_a?(Array) guard for runtime_dependencies.
Add four non-integration tests covering no-deps, exclusive deps,
shared deps, and table output formats.
Comment thread Library/Homebrew/cmd/info.rb Outdated
keg = installed_formula.any_installed_keg
next unless keg

Array(keg.runtime_dependencies).each do |dep|

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use installed_formula.runtime_dependencies?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, switched to formula.runtime_dependencies in both loops.

Comment thread Library/Homebrew/cmd/info.rb Outdated
next unless full_name

dep_name = Utils.name_from_full_name(full_name)
(reverse_map[dep_name] ||= Set.new).add(installed_formula.name)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(reverse_map[dep_name] ||= Set.new).add(installed_formula.name)
reverse_map[dep_name] ||= Set.new
reverse_map[dep_name] << installed_formula.name

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, thanks!

Comment thread Library/Homebrew/cmd/info.rb Outdated
exclusive_deps = T.let([], T::Array[T::Hash[Symbol, T.untyped]])
shared_deps = T.let([], T::Array[T::Hash[Symbol, T.untyped]])

Array(keg&.runtime_dependencies).each do |dep|

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread Library/Homebrew/cmd/info.rb Outdated
next unless keg

Array(keg.runtime_dependencies).each do |dep|
next unless dep.is_a?(Hash)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is it not?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I'm using formula.runtime_dependencies, the FormulaUnavailableError rescue shouldn't be necessary because the dependencies are resolved from the formula DSL. Should I remove it entirely and just keep the installed_kegs.empty? guard?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes unless you can reproduce the error locally

Comment thread Library/Homebrew/cmd/info.rb Outdated
Comment on lines +1060 to +1063
exclusive_deps << { name: dep_name, size: dep_size }
else
also_needed_by = (dependents.to_a - [formula.name]).sort
shared_deps << { name: dep_name, size: dep_size, also_needed_by: }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T::Struct might be nicer than a hash here

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, done, thanks!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EdenRochmanSharabi you don't seem to have pushed yet?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't pushed yet. I'm not sure about the FormulaUnavailableError guard. Should I remove it and just keep the installed_kegs.empty? check, or keep it as a safety net?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove for now. aim to simplify and minimise the amount of code as much as possible.

EdenRochmanSharabi and others added 2 commits June 18, 2026 11:35
…r hashes, remove FormulaUnavailableError guard, simplify reverse map building

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @EdenRochmanSharabi. Thanks for the work so far. This isn't really making sense to me so far and even --sizes on testing doesn't make much sense either:

  • brew info ffmpeg-full --sizes or brew info ffmpeg-full --deps doesn't seem to work when ffmpeg-full isn't installed
  • brew info ffmpeg-full already displays the size when ffmpeg-full is installed
  • brew info ffmpeg-full lists the various dependencies

If anything I'm inclined to say we don't add this, we odeprecate --sizes (as it's broken enough to be pretty useless) and, if it doesn't negatively affect performance, we instead add size information into the dependencies section of brew info.

Alternatively, just fix --sizes to do the same brew info output as everything else but fetch/include/use size information for the package and all the deps.

Comment on lines +106 to +108
switch "--deps",
depends_on: "--sizes",
description: "Show dependency size breakdown with exclusive deps and total disk footprint."

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
switch "--deps",
depends_on: "--sizes",
description: "Show dependency size breakdown with exclusive deps and total disk footprint."
switch "--dependencies", "--deps",
depends_on: "--sizes",
description: "Show dependency size breakdown with exclusive dependencies and total disk footprint."

formulae = if args.no_named?
Formula.installed
else
args.named.to_formulae

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails if passed any casks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants