Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/list: support listing formulae installed on request or automatically #17125

Merged
merged 12 commits into from
Apr 23, 2024
31 changes: 30 additions & 1 deletion Library/Homebrew/cmd/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require "cli/parser"
require "cask/list"
require "system_command"
require "tab"

module Homebrew
module Cmd
Expand Down Expand Up @@ -36,6 +37,11 @@ class List < AbstractCommand
switch "--pinned",
description: "List only pinned formulae, or only the specified (pinned) " \
"formulae if <formula> are provided. See also `pin`, `unpin`."
switch "--manual", "--installed-on-request",
description: "List the formulae installed on request."
switch "--auto", "--installed-as-dependency",
description: "List the formulae installed automatically."
MikeMcQuaid marked this conversation as resolved.
Show resolved Hide resolved
ZhongRuoyu marked this conversation as resolved.
Show resolved Hide resolved

# passed through to ls
switch "-1",
description: "Force output to be one entry per line. " \
Expand All @@ -54,11 +60,17 @@ class List < AbstractCommand
conflicts "--pinned", "--cask"
conflicts "--multiple", "--cask"
conflicts "--pinned", "--multiple"
["--manual", "--auto"].each do |flag|
conflicts "--cask", flag
conflicts "--versions", flag
conflicts "--pinned", flag
end
["-1", "-l", "-r", "-t"].each do |flag|
conflicts "--versions", flag
conflicts "--pinned", flag
end
["--versions", "--pinned", "-l", "-r", "-t"].each do |flag|
["--versions", "--pinned", "--manual", "--auto",
"-l", "-r", "-t"].each do |flag|
conflicts "--full-name", flag
end

Expand Down Expand Up @@ -91,6 +103,23 @@ def run
elsif args.versions?
filtered_list unless args.cask?
list_casks if args.cask? || (!args.formula? && !args.multiple? && args.no_named?)
elsif args.manual? || args.auto?
unless args.no_named?
raise UsageError,
"Cannot use `--manual` or `--auto` with formula arguments."
end

Formula.installed.sort.each do |formula|
tab = Tab.for_formula(formula)

if args.manual? && args.auto?
status = tab.installed_on_request ? "manual" : "auto"
puts "#{formula.name}: #{status}"
elsif (args.manual? && tab.installed_on_request) ||
(args.auto? && !tab.installed_on_request)
puts formula.name
end
end
elsif args.no_named?
ENV["CLICOLOR"] = nil

Expand Down
12 changes: 12 additions & 0 deletions Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/list.rbi

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions Library/Homebrew/test/cmd/list_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,24 @@

require "cmd/list"
require "cmd/shared_examples/args_parse"
require "tab"

RSpec.describe Homebrew::Cmd::List do
def setup_installation(formula_name, installed_on_request:)
setup_test_formula(formula_name)

keg_dir = HOMEBREW_CELLAR/formula_name/"1.0"
keg_dir.mkpath

tab = Tab.new(
"installed_on_request" => installed_on_request,
"tabfile" => keg_dir/Tab::FILENAME,
)
tab.write
Copy link
Contributor

Choose a reason for hiding this comment

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

Tangential: This is starting to crop up in the test code a bit more and I'm wondering if it'd be better to just add an option to setup_test_formula that facilitates that like with_tab: { "installed_on_request" => true }.

CC: @reitermarkus because we've talked about this a bit before

Copy link
Member

Choose a reason for hiding this comment

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

@apainintheneck good idea 👍🏻


keg_dir
end

let(:formulae) { %w[bar foo qux] }

it_behaves_like "parseable arguments"
Expand All @@ -18,4 +34,25 @@
.and not_to_output.to_stderr
.and be_a_success
end

it "lists the formulae installed on request or automatically",
:integration_test do
Copy link
Member

Choose a reason for hiding this comment

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

Don't think it's worth adding another (slow, sadly) integration test for this.

Copy link
Contributor

Choose a reason for hiding this comment

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

Tangential: Now that each command is a separate class, do you think it'd be possible to create integration-like tests that don't require spinning up a new Ruby process? It might have been possible before but now it seems like a more viable option. Most of the slowness has to do with shelling out to a new Ruby process, right?

CC: @dduugg

Copy link
Member

Choose a reason for hiding this comment

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

@apainintheneck Yeh, I think this would be nice.

We still want to make sure we have some proper/slow integration coverage because it catches when the issues are in bin/brew or bin/brew.rb but that could be a smaller subset of critical commands e.g. brew install/brew upgrade/etc.

setup_installation "foo", installed_on_request: true
setup_installation "bar", installed_on_request: false

expect { brew "list", "--manual" }
.to be_a_success
.and output("foo\n").to_stdout
.and not_to_output.to_stderr

expect { brew "list", "--auto" }
.to be_a_success
.and output("bar\n").to_stdout
.and not_to_output.to_stderr

expect { brew "list", "--manual", "--auto" }
.to be_a_success
.and output("bar: auto\nfoo: manual\n").to_stdout
.and not_to_output.to_stderr
end
end
6 changes: 4 additions & 2 deletions Library/Homebrew/test/sorbet/tapioca/compilers/args_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
describe "#args_table" do
it "returns a mapping of list args to default values" do
expect(compiler.args_table(list_parser).keys).to contain_exactly(
:"1?", :cask?, :casks?, :d?, :debug?, :formula?, :formulae?, :full_name?, :h?, :help?, :l?, :multiple?,
:pinned?, :q?, :quiet?, :r?, :t?, :v?, :verbose?, :versions?
:"1?", :auto?, :cask?, :casks?, :d?, :debug?, :formula?, :formulae?,
:full_name?, :h?, :help?, :installed_as_dependency?,
:installed_on_request?, :l?, :manual?, :multiple?, :pinned?,
:q?, :quiet?, :r?, :t?, :v?, :verbose?, :versions?
)
end

Expand Down
4 changes: 4 additions & 0 deletions completions/bash/brew
Original file line number Diff line number Diff line change
Expand Up @@ -1415,11 +1415,13 @@ _brew_list() {
case "${cur}" in
-*)
__brewcomp "
--auto
--cask
--debug
--formula
--full-name
--help
--manual
--multiple
--pinned
--quiet
Expand Down Expand Up @@ -1517,11 +1519,13 @@ _brew_ls() {
case "${cur}" in
-*)
__brewcomp "
--auto
--cask
--debug
--formula
--full-name
--help
--manual
--multiple
--pinned
--quiet
Expand Down
4 changes: 4 additions & 0 deletions completions/fish/brew.fish
Original file line number Diff line number Diff line change
Expand Up @@ -990,11 +990,13 @@ __fish_brew_complete_arg 'linkage' -a '(__fish_brew_suggest_formulae_installed)'


__fish_brew_complete_cmd 'list' 'List all installed formulae and casks'
__fish_brew_complete_arg 'list' -l auto -d 'List the formulae installed automatically'
__fish_brew_complete_arg 'list' -l cask -d 'List only casks, or treat all named arguments as casks'
__fish_brew_complete_arg 'list' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg 'list' -l formula -d 'List only formulae, or treat all named arguments as formulae'
__fish_brew_complete_arg 'list' -l full-name -d 'Print formulae with fully-qualified names. Unless `--full-name`, `--versions` or `--pinned` are passed, other options (i.e. `-1`, `-l`, `-r` and `-t`) are passed to `ls`(1) which produces the actual output'
__fish_brew_complete_arg 'list' -l help -d 'Show this message'
__fish_brew_complete_arg 'list' -l manual -d 'List the formulae installed on request'
__fish_brew_complete_arg 'list' -l multiple -d 'Only show formulae with multiple versions installed'
__fish_brew_complete_arg 'list' -l pinned -d 'List only pinned formulae, or only the specified (pinned) formulae if formula are provided. See also `pin`, `unpin`'
__fish_brew_complete_arg 'list' -l quiet -d 'Make some output more quiet'
Expand Down Expand Up @@ -1056,11 +1058,13 @@ __fish_brew_complete_arg 'log; and not __fish_seen_argument -l formula -l formul


__fish_brew_complete_cmd 'ls' 'List all installed formulae and casks'
__fish_brew_complete_arg 'ls' -l auto -d 'List the formulae installed automatically'
__fish_brew_complete_arg 'ls' -l cask -d 'List only casks, or treat all named arguments as casks'
__fish_brew_complete_arg 'ls' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg 'ls' -l formula -d 'List only formulae, or treat all named arguments as formulae'
__fish_brew_complete_arg 'ls' -l full-name -d 'Print formulae with fully-qualified names. Unless `--full-name`, `--versions` or `--pinned` are passed, other options (i.e. `-1`, `-l`, `-r` and `-t`) are passed to `ls`(1) which produces the actual output'
__fish_brew_complete_arg 'ls' -l help -d 'Show this message'
__fish_brew_complete_arg 'ls' -l manual -d 'List the formulae installed on request'
__fish_brew_complete_arg 'ls' -l multiple -d 'Only show formulae with multiple versions installed'
__fish_brew_complete_arg 'ls' -l pinned -d 'List only pinned formulae, or only the specified (pinned) formulae if formula are provided. See also `pin`, `unpin`'
__fish_brew_complete_arg 'ls' -l quiet -d 'Make some output more quiet'
Expand Down
20 changes: 12 additions & 8 deletions completions/zsh/_brew
Original file line number Diff line number Diff line change
Expand Up @@ -1231,14 +1231,16 @@ _brew_linkage() {
# brew list
_brew_list() {
_arguments \
'(--cask --versions --pinned --full-name)--auto[List the formulae installed automatically]' \
'--debug[Display any debugging information]' \
'(--versions --pinned --l --r --t)--full-name[Print formulae with fully-qualified names. Unless `--full-name`, `--versions` or `--pinned` are passed, other options (i.e. `-1`, `-l`, `-r` and `-t`) are passed to `ls`(1) which produces the actual output]' \
'(--versions --pinned --manual --auto --l --r --t)--full-name[Print formulae with fully-qualified names. Unless `--full-name`, `--versions` or `--pinned` are passed, other options (i.e. `-1`, `-l`, `-r` and `-t`) are passed to `ls`(1) which produces the actual output]' \
'--help[Show this message]' \
'(--cask --versions --pinned --full-name)--manual[List the formulae installed on request]' \
'(--cask --pinned)--multiple[Only show formulae with multiple versions installed]' \
'(--cask --multiple --1 --l --r --t --full-name)--pinned[List only pinned formulae, or only the specified (pinned) formulae if formula are provided. See also `pin`, `unpin`]' \
'(--cask --multiple --manual --auto --1 --l --r --t --full-name)--pinned[List only pinned formulae, or only the specified (pinned) formulae if formula are provided. See also `pin`, `unpin`]' \
'--quiet[Make some output more quiet]' \
'--verbose[Make some output more verbose]' \
'(--1 --l --r --t --full-name)--versions[Show the version number for installed formulae, or only the specified formulae if formula are provided]' \
'(--manual --auto --1 --l --r --t --full-name)--versions[Show the version number for installed formulae, or only the specified formulae if formula are provided]' \
'-1[Force output to be one entry per line. This is the default when output is not to a terminal]' \
'-l[List formulae and/or casks in long format. Has no effect when a formula or cask name is passed as an argument]' \
'-r[Reverse the order of the formulae and/or casks sort to list the oldest entries first. Has no effect when a formula or cask name is passed as an argument]' \
Expand All @@ -1247,7 +1249,7 @@ _brew_list() {
'(--cask)--formula[List only formulae, or treat all named arguments as formulae]' \
'*::installed_formula:__brew_installed_formulae' \
- installed_cask \
'(--formula --pinned --multiple)--cask[List only casks, or treat all named arguments as casks]' \
'(--formula --pinned --multiple --manual --auto)--cask[List only casks, or treat all named arguments as casks]' \
'*::installed_cask:__brew_installed_casks'
}

Expand Down Expand Up @@ -1312,14 +1314,16 @@ _brew_log() {
# brew ls
_brew_ls() {
_arguments \
'(--cask --versions --pinned --full-name)--auto[List the formulae installed automatically]' \
'--debug[Display any debugging information]' \
'(--versions --pinned --l --r --t)--full-name[Print formulae with fully-qualified names. Unless `--full-name`, `--versions` or `--pinned` are passed, other options (i.e. `-1`, `-l`, `-r` and `-t`) are passed to `ls`(1) which produces the actual output]' \
'(--versions --pinned --manual --auto --l --r --t)--full-name[Print formulae with fully-qualified names. Unless `--full-name`, `--versions` or `--pinned` are passed, other options (i.e. `-1`, `-l`, `-r` and `-t`) are passed to `ls`(1) which produces the actual output]' \
'--help[Show this message]' \
'(--cask --versions --pinned --full-name)--manual[List the formulae installed on request]' \
'(--cask --pinned)--multiple[Only show formulae with multiple versions installed]' \
'(--cask --multiple --1 --l --r --t --full-name)--pinned[List only pinned formulae, or only the specified (pinned) formulae if formula are provided. See also `pin`, `unpin`]' \
'(--cask --multiple --manual --auto --1 --l --r --t --full-name)--pinned[List only pinned formulae, or only the specified (pinned) formulae if formula are provided. See also `pin`, `unpin`]' \
'--quiet[Make some output more quiet]' \
'--verbose[Make some output more verbose]' \
'(--1 --l --r --t --full-name)--versions[Show the version number for installed formulae, or only the specified formulae if formula are provided]' \
'(--manual --auto --1 --l --r --t --full-name)--versions[Show the version number for installed formulae, or only the specified formulae if formula are provided]' \
'-1[Force output to be one entry per line. This is the default when output is not to a terminal]' \
'-l[List formulae and/or casks in long format. Has no effect when a formula or cask name is passed as an argument]' \
'-r[Reverse the order of the formulae and/or casks sort to list the oldest entries first. Has no effect when a formula or cask name is passed as an argument]' \
Expand All @@ -1328,7 +1332,7 @@ _brew_ls() {
'(--cask)--formula[List only formulae, or treat all named arguments as formulae]' \
'*::installed_formula:__brew_installed_formulae' \
- installed_cask \
'(--formula --pinned --multiple)--cask[List only casks, or treat all named arguments as casks]' \
'(--formula --pinned --multiple --manual --auto)--cask[List only casks, or treat all named arguments as casks]' \
'*::installed_cask:__brew_installed_casks'
}

Expand Down
8 changes: 8 additions & 0 deletions docs/Manpage.md
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,14 @@ paths within its current keg. If *`cask`* is provided, list its artifacts.
: List only pinned formulae, or only the specified (pinned) formulae if
*`formula`* are provided. See also `pin`, `unpin`.

`--manual`

: List the formulae installed on request.

`--auto`

: List the formulae installed automatically.

`-1`

: Force output to be one entry per line. This is the default when output is not
Expand Down
6 changes: 6 additions & 0 deletions manpages/brew.1
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,12 @@ Only show formulae with multiple versions installed\.
\fB\-\-pinned\fP
List only pinned formulae, or only the specified (pinned) formulae if \fIformula\fP are provided\. See also \fBpin\fP, \fBunpin\fP\&\.
.TP
\fB\-\-manual\fP
List the formulae installed on request\.
.TP
\fB\-\-auto\fP
List the formulae installed automatically\.
.TP
\fB\-1\fP
Force output to be one entry per line\. This is the default when output is not to a terminal\.
.TP
Expand Down