From 418a771d1239a595d7e0f1bd7c2b6855cd7334dd Mon Sep 17 00:00:00 2001 From: Bo Anderson Date: Fri, 23 May 2025 06:16:22 +0100 Subject: [PATCH] bundle: add support for selective cleanup --- Library/Homebrew/bundle/commands/cleanup.rb | 11 +++---- Library/Homebrew/cmd/bundle.rb | 16 ++++++---- .../test/bundle/commands/cleanup_spec.rb | 30 +++++++++++++++++++ completions/fish/brew.fish | 8 ++--- completions/zsh/_brew | 8 ++--- docs/Manpage.md | 8 ++--- manpages/brew.1 | 8 ++--- 7 files changed, 63 insertions(+), 26 deletions(-) diff --git a/Library/Homebrew/bundle/commands/cleanup.rb b/Library/Homebrew/bundle/commands/cleanup.rb index a42f07d980..7a6da0c6c3 100644 --- a/Library/Homebrew/bundle/commands/cleanup.rb +++ b/Library/Homebrew/bundle/commands/cleanup.rb @@ -25,13 +25,14 @@ module Homebrew Homebrew::Bundle::BrewServices.reset! 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 - casks = casks_to_uninstall(global:, file:) - formulae = formulae_to_uninstall(global:, file:) - taps = taps_to_untap(global:, file:) - vscode_extensions = vscode_extensions_to_uninstall(global:, file:) + casks = casks ? casks_to_uninstall(global:, file:) : [] + formulae = brews ? formulae_to_uninstall(global:, file:) : [] + taps = taps ? taps_to_untap(global:, file:) : [] + vscode_extensions = vscode ? vscode_extensions_to_uninstall(global:, file:) : [] if force if casks.any? args = zap ? ["--zap"] : [] diff --git a/Library/Homebrew/cmd/bundle.rb b/Library/Homebrew/cmd/bundle.rb index 84e6b3ab23..4dfb7a60f0 100755 --- a/Library/Homebrew/cmd/bundle.rb +++ b/Library/Homebrew/cmd/bundle.rb @@ -102,17 +102,17 @@ module Homebrew switch "--all", description: "`list` all dependencies." switch "--formula", "--brews", - description: "`list` or `dump` Homebrew formula dependencies." + description: "`list`, `dump` or `cleanup` Homebrew formula dependencies." switch "--cask", "--casks", - description: "`list` or `dump` Homebrew cask dependencies." + description: "`list`, `dump` or `cleanup` Homebrew cask dependencies." switch "--tap", "--taps", - description: "`list` or `dump` Homebrew tap dependencies." + description: "`list`, `dump` or `cleanup` Homebrew tap dependencies." switch "--mas", description: "`list` or `dump` Mac App Store dependencies." switch "--whalebrew", description: "`list` or `dump` Whalebrew dependencies." switch "--vscode", - description: "`list` or `dump` VSCode (and forks/variants) extensions." + description: "`list`, `dump` or `cleanup` VSCode (and forks/variants) extensions." switch "--no-vscode", env: :bundle_dump_no_vscode, description: "`dump` without VSCode (and forks/variants) extensions. " \ @@ -226,7 +226,13 @@ module Homebrew exec_editor(Homebrew::Bundle::Brewfile.path(global:, file:)) when "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" require "bundle/commands/check" Homebrew::Bundle::Commands::Check.run(global:, file:, no_upgrade:, verbose:) diff --git a/Library/Homebrew/test/bundle/commands/cleanup_spec.rb b/Library/Homebrew/test/bundle/commands/cleanup_spec.rb index d234f07b1e..e85f78ddc7 100644 --- a/Library/Homebrew/test/bundle/commands/cleanup_spec.rb +++ b/Library/Homebrew/test/bundle/commands/cleanup_spec.rb @@ -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.run(force: true) }.to output(/Uninstalled 2 casks/).to_stdout 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 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.run(force: true, zap: true) }.to output(/Uninstalled 2 casks/).to_stdout 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 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.run(force: true) }.to output(/Uninstalled 2 formulae/).to_stdout 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 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("") described_class.run(force: true) 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 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("") described_class.run(force: true) 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 context "when there are casks and formulae to uninstall and taps to untap but without passing `--force`" do diff --git a/completions/fish/brew.fish b/completions/fish/brew.fish index e569c1be4f..ad49769c46 100644 --- a/completions/fish/brew.fish +++ b/completions/fish/brew.fish @@ -506,14 +506,14 @@ __fish_brew_complete_sub_cmd 'bundle' 'sh' __fish_brew_complete_sub_cmd 'bundle' 'env' __fish_brew_complete_sub_cmd 'bundle' 'edit' __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 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 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 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 help -d 'Show this message' __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 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 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-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 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 zap -d '`cleanup` casks using the `zap` command instead of `uninstall`' diff --git a/completions/zsh/_brew b/completions/zsh/_brew index bdba3d7058..3c00aa1e16 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -649,14 +649,14 @@ _brew_bump_unversioned_casks() { _brew_bundle() { _arguments \ '(--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`]' \ '--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]' \ '--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]' \ '--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]' \ '--help[Show this message]' \ '(--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]' \ '--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]' \ - '--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]' \ '--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]' \ - '(--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]' \ '--zap[`cleanup` casks using the `zap` command instead of `uninstall`]' \ - subcommand \ diff --git a/docs/Manpage.md b/docs/Manpage.md index 09eb8c5b9f..50734eddaa 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -278,15 +278,15 @@ flags which will help with finding keg-only dependencies like `openssl`, `--formula` -: `list` or `dump` Homebrew formula dependencies. +: `list`, `dump` or `cleanup` Homebrew formula dependencies. `--cask` -: `list` or `dump` Homebrew cask dependencies. +: `list`, `dump` or `cleanup` Homebrew cask dependencies. `--tap` -: `list` or `dump` Homebrew tap dependencies. +: `list`, `dump` or `cleanup` Homebrew tap dependencies. `--mas` @@ -298,7 +298,7 @@ flags which will help with finding keg-only dependencies like `openssl`, `--vscode` -: `list` or `dump` VSCode (and forks/variants) extensions. +: `list`, `dump` or `cleanup` VSCode (and forks/variants) extensions. `--no-vscode` diff --git a/manpages/brew.1 b/manpages/brew.1 index 05cd33ae03..c9d84fcd31 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -169,13 +169,13 @@ Temporarily start services while running the \fBexec\fP or \fBsh\fP command\. Th \fBlist\fP all dependencies\. .TP \fB\-\-formula\fP -\fBlist\fP or \fBdump\fP Homebrew formula dependencies\. +\fBlist\fP, \fBdump\fP or \fBcleanup\fP Homebrew formula dependencies\. .TP \fB\-\-cask\fP -\fBlist\fP or \fBdump\fP Homebrew cask dependencies\. +\fBlist\fP, \fBdump\fP or \fBcleanup\fP Homebrew cask dependencies\. .TP \fB\-\-tap\fP -\fBlist\fP or \fBdump\fP Homebrew tap dependencies\. +\fBlist\fP, \fBdump\fP or \fBcleanup\fP Homebrew tap dependencies\. .TP \fB\-\-mas\fP \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\. .TP \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 \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\.