bundle: add support for selective cleanup

This commit is contained in:
Bo Anderson 2025-05-23 06:16:22 +01:00
parent 241dbba55c
commit 418a771d12
No known key found for this signature in database
7 changed files with 63 additions and 26 deletions

View File

@ -25,13 +25,14 @@ module Homebrew
Homebrew::Bundle::BrewServices.reset! Homebrew::Bundle::BrewServices.reset!
end end
def self.run(global: false, file: nil, force: false, zap: false, dsl: nil) def self.run(global: false, file: nil, force: false, zap: false, dsl: nil,
brews: true, casks: true, taps: true, vscode: true)
@dsl ||= dsl @dsl ||= dsl
casks = casks_to_uninstall(global:, file:) casks = casks ? casks_to_uninstall(global:, file:) : []
formulae = formulae_to_uninstall(global:, file:) formulae = brews ? formulae_to_uninstall(global:, file:) : []
taps = taps_to_untap(global:, file:) taps = taps ? taps_to_untap(global:, file:) : []
vscode_extensions = vscode_extensions_to_uninstall(global:, file:) vscode_extensions = vscode ? vscode_extensions_to_uninstall(global:, file:) : []
if force if force
if casks.any? if casks.any?
args = zap ? ["--zap"] : [] args = zap ? ["--zap"] : []

View File

@ -102,17 +102,17 @@ module Homebrew
switch "--all", switch "--all",
description: "`list` all dependencies." description: "`list` all dependencies."
switch "--formula", "--brews", switch "--formula", "--brews",
description: "`list` or `dump` Homebrew formula dependencies." description: "`list`, `dump` or `cleanup` Homebrew formula dependencies."
switch "--cask", "--casks", switch "--cask", "--casks",
description: "`list` or `dump` Homebrew cask dependencies." description: "`list`, `dump` or `cleanup` Homebrew cask dependencies."
switch "--tap", "--taps", switch "--tap", "--taps",
description: "`list` or `dump` Homebrew tap dependencies." description: "`list`, `dump` or `cleanup` Homebrew tap dependencies."
switch "--mas", switch "--mas",
description: "`list` or `dump` Mac App Store dependencies." description: "`list` or `dump` Mac App Store dependencies."
switch "--whalebrew", switch "--whalebrew",
description: "`list` or `dump` Whalebrew dependencies." description: "`list` or `dump` Whalebrew dependencies."
switch "--vscode", switch "--vscode",
description: "`list` or `dump` VSCode (and forks/variants) extensions." description: "`list`, `dump` or `cleanup` VSCode (and forks/variants) extensions."
switch "--no-vscode", switch "--no-vscode",
env: :bundle_dump_no_vscode, env: :bundle_dump_no_vscode,
description: "`dump` without VSCode (and forks/variants) extensions. " \ description: "`dump` without VSCode (and forks/variants) extensions. " \
@ -226,7 +226,13 @@ module Homebrew
exec_editor(Homebrew::Bundle::Brewfile.path(global:, file:)) exec_editor(Homebrew::Bundle::Brewfile.path(global:, file:))
when "cleanup" when "cleanup"
require "bundle/commands/cleanup" require "bundle/commands/cleanup"
Homebrew::Bundle::Commands::Cleanup.run(global:, file:, force:, zap:) Homebrew::Bundle::Commands::Cleanup.run(
global:, file:, force:, zap:,
brews: args.brews? || no_type_args,
casks: args.casks? || no_type_args,
taps: args.taps? || no_type_args,
vscode: args.vscode? || no_type_args
)
when "check" when "check"
require "bundle/commands/check" require "bundle/commands/check"
Homebrew::Bundle::Commands::Check.run(global:, file:, no_upgrade:, verbose:) Homebrew::Bundle::Commands::Check.run(global:, file:, no_upgrade:, verbose:)

View File

@ -158,6 +158,12 @@ RSpec.describe Homebrew::Bundle::Commands::Cleanup do
expect(described_class).to receive(:system_output_no_stderr).and_return("") expect(described_class).to receive(:system_output_no_stderr).and_return("")
expect { described_class.run(force: true) }.to output(/Uninstalled 2 casks/).to_stdout expect { described_class.run(force: true) }.to output(/Uninstalled 2 casks/).to_stdout
end end
it "does not uninstall casks if --brews is disabled" do
expect(Kernel).not_to receive(:system)
expect(described_class).to receive(:system_output_no_stderr).and_return("")
expect { described_class.run(force: true, casks: false) }.not_to output.to_stdout
end
end end
context "when there are casks to zap" do context "when there are casks to zap" do
@ -174,6 +180,12 @@ RSpec.describe Homebrew::Bundle::Commands::Cleanup do
expect(described_class).to receive(:system_output_no_stderr).and_return("") expect(described_class).to receive(:system_output_no_stderr).and_return("")
expect { described_class.run(force: true, zap: true) }.to output(/Uninstalled 2 casks/).to_stdout expect { described_class.run(force: true, zap: true) }.to output(/Uninstalled 2 casks/).to_stdout
end end
it "does not uninstall casks if --casks is disabled" do
expect(Kernel).not_to receive(:system)
expect(described_class).to receive(:system_output_no_stderr).and_return("")
expect { described_class.run(force: true, zap: true, casks: false) }.not_to output.to_stdout
end
end end
context "when there are formulae to uninstall" do context "when there are formulae to uninstall" do
@ -190,6 +202,12 @@ RSpec.describe Homebrew::Bundle::Commands::Cleanup do
expect(described_class).to receive(:system_output_no_stderr).and_return("") expect(described_class).to receive(:system_output_no_stderr).and_return("")
expect { described_class.run(force: true) }.to output(/Uninstalled 2 formulae/).to_stdout expect { described_class.run(force: true) }.to output(/Uninstalled 2 formulae/).to_stdout
end end
it "does not uninstall formulae if --casks is disabled" do
expect(Kernel).not_to receive(:system)
expect(described_class).to receive(:system_output_no_stderr).and_return("")
expect { described_class.run(force: true, brews: false) }.not_to output.to_stdout
end
end end
context "when there are taps to untap" do context "when there are taps to untap" do
@ -206,6 +224,12 @@ RSpec.describe Homebrew::Bundle::Commands::Cleanup do
expect(described_class).to receive(:system_output_no_stderr).and_return("") expect(described_class).to receive(:system_output_no_stderr).and_return("")
described_class.run(force: true) described_class.run(force: true)
end end
it "does not untap taps if --taps is disabled" do
expect(Kernel).not_to receive(:system)
expect(described_class).to receive(:system_output_no_stderr).and_return("")
described_class.run(force: true, taps: false)
end
end end
context "when there are VSCode extensions to uninstall" do context "when there are VSCode extensions to uninstall" do
@ -223,6 +247,12 @@ RSpec.describe Homebrew::Bundle::Commands::Cleanup do
expect(described_class).to receive(:system_output_no_stderr).and_return("") expect(described_class).to receive(:system_output_no_stderr).and_return("")
described_class.run(force: true) described_class.run(force: true)
end end
it "does not uninstall extensions if --vscode is disabled" do
expect(Kernel).not_to receive(:system)
expect(described_class).to receive(:system_output_no_stderr).and_return("")
described_class.run(force: true, vscode: false)
end
end end
context "when there are casks and formulae to uninstall and taps to untap but without passing `--force`" do context "when there are casks and formulae to uninstall and taps to untap but without passing `--force`" do

View File

@ -506,14 +506,14 @@ __fish_brew_complete_sub_cmd 'bundle' 'sh'
__fish_brew_complete_sub_cmd 'bundle' 'env' __fish_brew_complete_sub_cmd 'bundle' 'env'
__fish_brew_complete_sub_cmd 'bundle' 'edit' __fish_brew_complete_sub_cmd 'bundle' 'edit'
__fish_brew_complete_arg 'bundle' -l all -d '`list` all dependencies' __fish_brew_complete_arg 'bundle' -l all -d '`list` all dependencies'
__fish_brew_complete_arg 'bundle' -l cask -d '`list` or `dump` Homebrew cask dependencies' __fish_brew_complete_arg 'bundle' -l cask -d '`list`, `dump` or `cleanup` Homebrew cask dependencies'
__fish_brew_complete_arg 'bundle' -l check -d 'Check that all dependencies in the Brewfile are installed before running `exec`, `sh`, or `env`' __fish_brew_complete_arg 'bundle' -l check -d 'Check that all dependencies in the Brewfile are installed before running `exec`, `sh`, or `env`'
__fish_brew_complete_arg 'bundle' -l cleanup -d '`install` performs cleanup operation, same as running `cleanup --force`. This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed' __fish_brew_complete_arg 'bundle' -l cleanup -d '`install` performs cleanup operation, same as running `cleanup --force`. This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed'
__fish_brew_complete_arg 'bundle' -l debug -d 'Display any debugging information' __fish_brew_complete_arg 'bundle' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg 'bundle' -l describe -d '`dump` adds a description comment above each line, unless the dependency does not have a description. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set' __fish_brew_complete_arg 'bundle' -l describe -d '`dump` adds a description comment above each line, unless the dependency does not have a description. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set'
__fish_brew_complete_arg 'bundle' -l file -d 'Read from or write to the `Brewfile` from this location. Use `--file=-` to pipe to stdin/stdout' __fish_brew_complete_arg 'bundle' -l file -d 'Read from or write to the `Brewfile` from this location. Use `--file=-` to pipe to stdin/stdout'
__fish_brew_complete_arg 'bundle' -l force -d '`install` runs with `--force`/`--overwrite`. `dump` overwrites an existing `Brewfile`. `cleanup` actually performs its cleanup operations' __fish_brew_complete_arg 'bundle' -l force -d '`install` runs with `--force`/`--overwrite`. `dump` overwrites an existing `Brewfile`. `cleanup` actually performs its cleanup operations'
__fish_brew_complete_arg 'bundle' -l formula -d '`list` or `dump` Homebrew formula dependencies' __fish_brew_complete_arg 'bundle' -l formula -d '`list`, `dump` or `cleanup` Homebrew formula dependencies'
__fish_brew_complete_arg 'bundle' -l global -d 'Read from or write to the `Brewfile` from `$HOMEBREW_BUNDLE_FILE_GLOBAL` (if set), `${XDG_CONFIG_HOME}/homebrew/Brewfile` (if `$XDG_CONFIG_HOME` is set), `~/.homebrew/Brewfile` or `~/.Brewfile` otherwise' __fish_brew_complete_arg 'bundle' -l global -d 'Read from or write to the `Brewfile` from `$HOMEBREW_BUNDLE_FILE_GLOBAL` (if set), `${XDG_CONFIG_HOME}/homebrew/Brewfile` (if `$XDG_CONFIG_HOME` is set), `~/.homebrew/Brewfile` or `~/.Brewfile` otherwise'
__fish_brew_complete_arg 'bundle' -l help -d 'Show this message' __fish_brew_complete_arg 'bundle' -l help -d 'Show this message'
__fish_brew_complete_arg 'bundle' -l install -d 'Run `install` before continuing to other operations e.g. `exec`' __fish_brew_complete_arg 'bundle' -l install -d 'Run `install` before continuing to other operations e.g. `exec`'
@ -523,11 +523,11 @@ __fish_brew_complete_arg 'bundle' -l no-upgrade -d '`install` does not run `brew
__fish_brew_complete_arg 'bundle' -l no-vscode -d '`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set' __fish_brew_complete_arg 'bundle' -l no-vscode -d '`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set'
__fish_brew_complete_arg 'bundle' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'bundle' -l quiet -d 'Make some output more quiet'
__fish_brew_complete_arg 'bundle' -l services -d 'Temporarily start services while running the `exec` or `sh` command. This is enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set' __fish_brew_complete_arg 'bundle' -l services -d 'Temporarily start services while running the `exec` or `sh` command. This is enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set'
__fish_brew_complete_arg 'bundle' -l tap -d '`list` or `dump` Homebrew tap dependencies' __fish_brew_complete_arg 'bundle' -l tap -d '`list`, `dump` or `cleanup` Homebrew tap dependencies'
__fish_brew_complete_arg 'bundle' -l upgrade -d '`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set' __fish_brew_complete_arg 'bundle' -l upgrade -d '`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set'
__fish_brew_complete_arg 'bundle' -l upgrade-formulae -d '`install` runs `brew upgrade` on any of these comma-separated formulae, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set' __fish_brew_complete_arg 'bundle' -l upgrade-formulae -d '`install` runs `brew upgrade` on any of these comma-separated formulae, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set'
__fish_brew_complete_arg 'bundle' -l verbose -d '`install` prints output from commands as they are run. `check` lists all missing dependencies' __fish_brew_complete_arg 'bundle' -l verbose -d '`install` prints output from commands as they are run. `check` lists all missing dependencies'
__fish_brew_complete_arg 'bundle' -l vscode -d '`list` or `dump` VSCode (and forks/variants) extensions' __fish_brew_complete_arg 'bundle' -l vscode -d '`list`, `dump` or `cleanup` VSCode (and forks/variants) extensions'
__fish_brew_complete_arg 'bundle' -l whalebrew -d '`list` or `dump` Whalebrew dependencies' __fish_brew_complete_arg 'bundle' -l whalebrew -d '`list` or `dump` Whalebrew dependencies'
__fish_brew_complete_arg 'bundle' -l zap -d '`cleanup` casks using the `zap` command instead of `uninstall`' __fish_brew_complete_arg 'bundle' -l zap -d '`cleanup` casks using the `zap` command instead of `uninstall`'

View File

@ -649,14 +649,14 @@ _brew_bump_unversioned_casks() {
_brew_bundle() { _brew_bundle() {
_arguments \ _arguments \
'(--no-vscode)--all[`list` all dependencies]' \ '(--no-vscode)--all[`list` all dependencies]' \
'--cask[`list` or `dump` Homebrew cask dependencies]' \ '--cask[`list`, `dump` or `cleanup` Homebrew cask dependencies]' \
'--check[Check that all dependencies in the Brewfile are installed before running `exec`, `sh`, or `env`]' \ '--check[Check that all dependencies in the Brewfile are installed before running `exec`, `sh`, or `env`]' \
'--cleanup[`install` performs cleanup operation, same as running `cleanup --force`. This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed]' \ '--cleanup[`install` performs cleanup operation, same as running `cleanup --force`. This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed]' \
'--debug[Display any debugging information]' \ '--debug[Display any debugging information]' \
'--describe[`dump` adds a description comment above each line, unless the dependency does not have a description. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set]' \ '--describe[`dump` adds a description comment above each line, unless the dependency does not have a description. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set]' \
'--file[Read from or write to the `Brewfile` from this location. Use `--file=-` to pipe to stdin/stdout]' \ '--file[Read from or write to the `Brewfile` from this location. Use `--file=-` to pipe to stdin/stdout]' \
'--force[`install` runs with `--force`/`--overwrite`. `dump` overwrites an existing `Brewfile`. `cleanup` actually performs its cleanup operations]' \ '--force[`install` runs with `--force`/`--overwrite`. `dump` overwrites an existing `Brewfile`. `cleanup` actually performs its cleanup operations]' \
'--formula[`list` or `dump` Homebrew formula dependencies]' \ '--formula[`list`, `dump` or `cleanup` Homebrew formula dependencies]' \
'--global[Read from or write to the `Brewfile` from `$HOMEBREW_BUNDLE_FILE_GLOBAL` (if set), `${XDG_CONFIG_HOME}/homebrew/Brewfile` (if `$XDG_CONFIG_HOME` is set), `~/.homebrew/Brewfile` or `~/.Brewfile` otherwise]' \ '--global[Read from or write to the `Brewfile` from `$HOMEBREW_BUNDLE_FILE_GLOBAL` (if set), `${XDG_CONFIG_HOME}/homebrew/Brewfile` (if `$XDG_CONFIG_HOME` is set), `~/.homebrew/Brewfile` or `~/.Brewfile` otherwise]' \
'--help[Show this message]' \ '--help[Show this message]' \
'(--upgrade)--install[Run `install` before continuing to other operations e.g. `exec`]' \ '(--upgrade)--install[Run `install` before continuing to other operations e.g. `exec`]' \
@ -666,11 +666,11 @@ _brew_bundle() {
'(--all --vscode)--no-vscode[`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set]' \ '(--all --vscode)--no-vscode[`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set]' \
'--quiet[Make some output more quiet]' \ '--quiet[Make some output more quiet]' \
'--services[Temporarily start services while running the `exec` or `sh` command. This is enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set]' \ '--services[Temporarily start services while running the `exec` or `sh` command. This is enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set]' \
'--tap[`list` or `dump` Homebrew tap dependencies]' \ '--tap[`list`, `dump` or `cleanup` Homebrew tap dependencies]' \
'(--install)--upgrade[`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \ '(--install)--upgrade[`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \
'--upgrade-formulae[`install` runs `brew upgrade` on any of these comma-separated formulae, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \ '--upgrade-formulae[`install` runs `brew upgrade` on any of these comma-separated formulae, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \
'--verbose[`install` prints output from commands as they are run. `check` lists all missing dependencies]' \ '--verbose[`install` prints output from commands as they are run. `check` lists all missing dependencies]' \
'(--no-vscode)--vscode[`list` or `dump` VSCode (and forks/variants) extensions]' \ '(--no-vscode)--vscode[`list`, `dump` or `cleanup` VSCode (and forks/variants) extensions]' \
'--whalebrew[`list` or `dump` Whalebrew dependencies]' \ '--whalebrew[`list` or `dump` Whalebrew dependencies]' \
'--zap[`cleanup` casks using the `zap` command instead of `uninstall`]' \ '--zap[`cleanup` casks using the `zap` command instead of `uninstall`]' \
- subcommand \ - subcommand \

View File

@ -278,15 +278,15 @@ flags which will help with finding keg-only dependencies like `openssl`,
`--formula` `--formula`
: `list` or `dump` Homebrew formula dependencies. : `list`, `dump` or `cleanup` Homebrew formula dependencies.
`--cask` `--cask`
: `list` or `dump` Homebrew cask dependencies. : `list`, `dump` or `cleanup` Homebrew cask dependencies.
`--tap` `--tap`
: `list` or `dump` Homebrew tap dependencies. : `list`, `dump` or `cleanup` Homebrew tap dependencies.
`--mas` `--mas`
@ -298,7 +298,7 @@ flags which will help with finding keg-only dependencies like `openssl`,
`--vscode` `--vscode`
: `list` or `dump` VSCode (and forks/variants) extensions. : `list`, `dump` or `cleanup` VSCode (and forks/variants) extensions.
`--no-vscode` `--no-vscode`

View File

@ -169,13 +169,13 @@ Temporarily start services while running the \fBexec\fP or \fBsh\fP command\. Th
\fBlist\fP all dependencies\. \fBlist\fP all dependencies\.
.TP .TP
\fB\-\-formula\fP \fB\-\-formula\fP
\fBlist\fP or \fBdump\fP Homebrew formula dependencies\. \fBlist\fP, \fBdump\fP or \fBcleanup\fP Homebrew formula dependencies\.
.TP .TP
\fB\-\-cask\fP \fB\-\-cask\fP
\fBlist\fP or \fBdump\fP Homebrew cask dependencies\. \fBlist\fP, \fBdump\fP or \fBcleanup\fP Homebrew cask dependencies\.
.TP .TP
\fB\-\-tap\fP \fB\-\-tap\fP
\fBlist\fP or \fBdump\fP Homebrew tap dependencies\. \fBlist\fP, \fBdump\fP or \fBcleanup\fP Homebrew tap dependencies\.
.TP .TP
\fB\-\-mas\fP \fB\-\-mas\fP
\fBlist\fP or \fBdump\fP Mac App Store dependencies\. \fBlist\fP or \fBdump\fP Mac App Store dependencies\.
@ -184,7 +184,7 @@ Temporarily start services while running the \fBexec\fP or \fBsh\fP command\. Th
\fBlist\fP or \fBdump\fP Whalebrew dependencies\. \fBlist\fP or \fBdump\fP Whalebrew dependencies\.
.TP .TP
\fB\-\-vscode\fP \fB\-\-vscode\fP
\fBlist\fP or \fBdump\fP VSCode (and forks/variants) extensions\. \fBlist\fP, \fBdump\fP or \fBcleanup\fP VSCode (and forks/variants) extensions\.
.TP .TP
\fB\-\-no\-vscode\fP \fB\-\-no\-vscode\fP
\fBdump\fP without VSCode (and forks/variants) extensions\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_NO_VSCODE\fP is set\. \fBdump\fP without VSCode (and forks/variants) extensions\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_NO_VSCODE\fP is set\.