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

brew tab: new command for editing tab information #17449

Merged
merged 1 commit into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions Library/Homebrew/cmd/tab.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# typed: strict
# frozen_string_literal: true

require "abstract_command"
require "formula"
require "tab"

module Homebrew
module Cmd
class TabCmd < AbstractCommand
cmd_args do
description <<~EOS
Edit tab information for installed formulae.

This can be useful when you want to control whether an installed
formula should be removed by `brew autoremove`.
To prevent removal, mark the formula as installed on request;
to allow removal, mark the formula as not installed on request.
EOS

switch "--installed-on-request",
description: "Mark <formula> as installed on request."
switch "--no-installed-on-request",
description: "Mark <formula> as not installed on request."

conflicts "--installed-on-request", "--no-installed-on-request"

named_args :formula, min: 1
end

sig { override.void }
def run
installed_on_request = if args.installed_on_request?
true
elsif args.no_installed_on_request?
false
end
raise UsageError, "No marking option specified." if installed_on_request.nil?

formulae = args.named.to_formulae
if (formulae_not_installed = formulae.reject(&:any_version_installed?)).any?
formula_names = formulae_not_installed.map(&:name)
is_or_are = (formula_names.length == 1) ? "is" : "are"
odie "#{formula_names.to_sentence} #{is_or_are} not installed."

Check warning on line 44 in Library/Homebrew/cmd/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cmd/tab.rb#L44

Added line #L44 was not covered by tests
end

formulae.each do |formula|
update_tab formula, installed_on_request:
end
end

private

sig { params(formula: Formula, installed_on_request: T::Boolean).void }
def update_tab(formula, installed_on_request:)
tab = Tab.for_formula(formula)
unless tab.tabfile.exist?
raise ArgumentError,
"Tab file for #{formula.name} does not exist."
end

installed_on_request_str = "#{"not " unless installed_on_request}installed on request"
if (tab.installed_on_request && installed_on_request) ||
(!tab.installed_on_request && !installed_on_request)
ohai "#{formula.name} is already marked as #{installed_on_request_str}."
return

Check warning on line 66 in Library/Homebrew/cmd/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cmd/tab.rb#L66

Added line #L66 was not covered by tests
end

tab.installed_on_request = installed_on_request
tab.write
ohai "#{formula.name} is now marked as #{installed_on_request_str}."
end
end
end
end
19 changes: 19 additions & 0 deletions Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/tab_cmd.rbi

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

33 changes: 33 additions & 0 deletions Library/Homebrew/test/cmd/tab_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

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

RSpec.describe Homebrew::Cmd::TabCmd do
def installed_on_request?(formula)
# `brew` subprocesses can change the tab, invalidating the cached values.
Tab.clear_cache
Tab.for_formula(formula).installed_on_request
end

it_behaves_like "parseable arguments"

it "marks or unmarks a formula as installed on request", :integration_test do
setup_test_formula "foo",
tab_attributes: { "installed_on_request" => false }
foo = Formula["foo"]

expect { brew "tab", "--installed-on-request", "foo" }
.to be_a_success
.and output(/foo is now marked as installed on request/).to_stdout
.and not_to_output.to_stderr
expect(installed_on_request?(foo)).to be true

expect { brew "tab", "--no-installed-on-request", "foo" }
.to be_a_success
.and output(/foo is now marked as not installed on request/).to_stdout
.and not_to_output.to_stderr
expect(installed_on_request?(foo)).to be false
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ def brew_sh(*args)
end
end

def setup_test_formula(name, content = nil, tap: CoreTap.instance, bottle_block: nil)
def setup_test_formula(name, content = nil, tap: CoreTap.instance,
bottle_block: nil, tab_attributes: nil)
case name
when /^testball/
tarball = if OS.linux?
Expand Down Expand Up @@ -174,15 +175,29 @@ def install
RUBY
end

Formulary.find_formula_in_tap(name.downcase, tap).tap do |formula_path|
formula_path.write <<~RUBY
formula_path = Formulary.find_formula_in_tap(name.downcase, tap).tap do |path|
path.write <<~RUBY
class #{Formulary.class_s(name)} < Formula
#{content.gsub(/^(?!$)/, " ")}
end
RUBY

tap.clear_cache
end

return formula_path if tab_attributes.nil?

keg = Formula[name].prefix
keg.mkpath

tab = Tab.for_name(name)
tab.tabfile ||= keg/Tab::FILENAME
tab_attributes.each do |key, value|
tab.instance_variable_set(:"@#{key}", value)
end
tab.write

formula_path
end

def install_test_formula(name, content = nil, build_bottle: false)
Expand Down
20 changes: 20 additions & 0 deletions completions/bash/brew
Original file line number Diff line number Diff line change
Expand Up @@ -2107,6 +2107,25 @@ _brew_style() {
__brew_complete_casks
}

_brew_tab() {
local cur="${COMP_WORDS[COMP_CWORD]}"
case "${cur}" in
-*)
__brewcomp "
--debug
--help
--installed-on-request
--no-installed-on-request
--quiet
--verbose
"
return
;;
*) ;;
esac
__brew_complete_formulae
}

_brew_tap() {
local cur="${COMP_WORDS[COMP_CWORD]}"
case "${cur}" in
Expand Down Expand Up @@ -2765,6 +2784,7 @@ _brew() {
search) _brew_search ;;
sh) _brew_sh ;;
style) _brew_style ;;
tab) _brew_tab ;;
tap) _brew_tap ;;
tap-info) _brew_tap_info ;;
tap-new) _brew_tap_new ;;
Expand Down
10 changes: 10 additions & 0 deletions completions/fish/brew.fish
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,16 @@ __fish_brew_complete_arg 'style; and not __fish_seen_argument -l cask -l casks'
__fish_brew_complete_arg 'style; and not __fish_seen_argument -l formula -l formulae' -a '(__fish_brew_suggest_casks_all)'


__fish_brew_complete_cmd 'tab' 'Edit tab information for installed formulae'
__fish_brew_complete_arg 'tab' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg 'tab' -l help -d 'Show this message'
__fish_brew_complete_arg 'tab' -l installed-on-request -d 'Mark formula as installed on request'
__fish_brew_complete_arg 'tab' -l no-installed-on-request -d 'Mark formula as not installed on request'
__fish_brew_complete_arg 'tab' -l quiet -d 'Make some output more quiet'
__fish_brew_complete_arg 'tab' -l verbose -d 'Make some output more verbose'
__fish_brew_complete_arg 'tab' -a '(__fish_brew_suggest_formulae_all)'


__fish_brew_complete_cmd 'tap' 'Tap a formula repository'
__fish_brew_complete_arg 'tap' -l custom-remote -d 'Install or change a tap with a custom remote. Useful for mirrors'
__fish_brew_complete_arg 'tap' -l debug -d 'Display any debugging information'
Expand Down
1 change: 1 addition & 0 deletions completions/internal_commands_list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ setup-ruby
sh
shellenv
style
tab
tap
tap-info
tap-new
Expand Down
14 changes: 14 additions & 0 deletions completions/zsh/_brew
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ __brew_internal_commands() {
'sh:Enter an interactive shell for Homebrew'\''s build environment'
'shellenv:Print export statements'
'style:Check formulae or files for conformance to Homebrew style guidelines'
'tab:Edit tab information for installed formulae'
'tap:Tap a formula repository'
'tap-info:Show detailed information about one or more taps'
'tap-new:Generate the template files for a new tap'
Expand Down Expand Up @@ -1747,6 +1748,19 @@ _brew_style() {
'*::cask:__brew_casks'
}

# brew tab
_brew_tab() {
_arguments \
'--debug[Display any debugging information]' \
'--help[Show this message]' \
'(--no-installed-on-request)--installed-on-request[Mark formula as installed on request]' \
'(--installed-on-request)--no-installed-on-request[Mark formula as not installed on request]' \
'--quiet[Make some output more quiet]' \
'--verbose[Make some output more verbose]' \
- formula \
'*::formula:__brew_formulae'
}

# brew tap
_brew_tap() {
_arguments \
Expand Down
17 changes: 17 additions & 0 deletions docs/Manpage.md
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,23 @@ evaluation of this command's output to your dotfiles (e.g. `~/.bash_profile` or
The shell can be specified explicitly with a supported shell name parameter.
Unknown shells will output POSIX exports.

### `tab` \[`--installed-on-request`\] \[`--no-installed-on-request`\] *`formula`* \[...\]

Edit tab information for installed formulae.

This can be useful when you want to control whether an installed formula should
be removed by `brew autoremove`. To prevent removal, mark the formula as
installed on request; to allow removal, mark the formula as not installed on
request.

`--installed-on-request`

: Mark *`formula`* as installed on request.

`--no-installed-on-request`

: Mark *`formula`* as not installed on request.

### `tap` \[*`options`*\] \[*`user`*`/`*`repo`*\] \[*`URL`*\]

Tap a formula repository. If no arguments are provided, list all installed taps.
Expand Down
10 changes: 10 additions & 0 deletions manpages/brew.1
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,16 @@ Print export statements\. When run in a shell, this installation of Homebrew wil
The variables \fBHOMEBREW_PREFIX\fP, \fBHOMEBREW_CELLAR\fP and \fBHOMEBREW_REPOSITORY\fP are also exported to avoid querying them multiple times\. To help guarantee idempotence, this command produces no output when Homebrew\[u2019]s \fBbin\fP and \fBsbin\fP directories are first and second respectively in your \fBPATH\fP\&\. Consider adding evaluation of this command\[u2019]s output to your dotfiles (e\.g\. \fB~/\.bash_profile\fP or \fB~/\.zprofile\fP on macOS and \fB~/\.bashrc\fP or \fB~/\.zshrc\fP on Linux) with: \fBeval "$(brew shellenv)"\fP
.P
The shell can be specified explicitly with a supported shell name parameter\. Unknown shells will output POSIX exports\.
.SS "\fBtab\fP \fR[\fB\-\-installed\-on\-request\fP] \fR[\fB\-\-no\-installed\-on\-request\fP] \fIformula\fP \fR[\.\.\.]"
Edit tab information for installed formulae\.
.P
This can be useful when you want to control whether an installed formula should be removed by \fBbrew autoremove\fP\&\. To prevent removal, mark the formula as installed on request; to allow removal, mark the formula as not installed on request\.
.TP
\fB\-\-installed\-on\-request\fP
Mark \fIformula\fP as installed on request\.
.TP
\fB\-\-no\-installed\-on\-request\fP
Mark \fIformula\fP as not installed on request\.
.SS "\fBtap\fP \fR[\fIoptions\fP] \fR[\fIuser\fP\fB/\fP\fIrepo\fP] \fR[\fIURL\fP]"
Tap a formula repository\. If no arguments are provided, list all installed taps\.
.P
Expand Down
Loading