From f8ae5f3bc438cc1bf88b33e930d4cda55b150f1e Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Fri, 8 Jul 2022 10:21:57 -0700 Subject: [PATCH 1/8] cmd/uninstall: Add env variable that runs autoremove after uninstalls When HOMEBREW_UNINSTALL_AUTOREMOVE is set, `brew autoremove` is run after every successful call to `brew uninstall`. --- Library/Homebrew/cmd/uninstall.rb | 9 +++++++++ Library/Homebrew/env_config.rb | 4 ++++ .../Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi | 2 ++ docs/Manpage.md | 3 +++ manpages/brew.1 | 6 ++++++ 5 files changed, 24 insertions(+) diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb index 8c40d4219d..e8e1bb386c 100644 --- a/Library/Homebrew/cmd/uninstall.rb +++ b/Library/Homebrew/cmd/uninstall.rb @@ -50,6 +50,11 @@ module Homebrew all_kegs: args.force?, ) + # If ignore_unavailable is true and the named args + # are a series of invalid kegs and casks, + # #to_kegs_to_casks will return empty arrays. + return if all_kegs.blank? && casks.blank? + kegs_by_rack = all_kegs.group_by(&:rack) Uninstall.uninstall_kegs( @@ -73,5 +78,9 @@ module Homebrew force: args.force?, ) end + + return unless Homebrew::EnvConfig.uninstall_autoremove? + + system HOMEBREW_BREW_FILE, "autoremove" end end diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index 6397f0abb4..115b292a97 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -343,6 +343,10 @@ module Homebrew default_text: "macOS: `/private/tmp`, Linux: `/tmp`.", default: HOMEBREW_DEFAULT_TEMP, }, + HOMEBREW_UNINSTALL_AUTOREMOVE: { + description: "If set, `brew autoremove` is run after every successful call to `brew uninstall`.", + boolean: true, + }, HOMEBREW_UPDATE_REPORT_ALL_FORMULAE: { description: "If set, `brew update` lists changes to all formulae and cask files rather than only showing " \ "when they are new and not installed or outdated and installed.", diff --git a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi index ba6af6ace7..271c840e99 100644 --- a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi +++ b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi @@ -2572,6 +2572,8 @@ module Homebrew::EnvConfig def self.temp(); end + def self.uninstall_autoremove?(); end + def self.update_report_all_formulae?(); end def self.update_to_tag?(); end diff --git a/docs/Manpage.md b/docs/Manpage.md index f74003edb1..bd9abaa82a 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -2184,6 +2184,9 @@ example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just *Default:* macOS: `/private/tmp`, Linux: `/tmp`. +- `HOMEBREW_UNINSTALL_AUTOREMOVE` +
If set, `brew autoremove` is run after every successful call to `brew uninstall`. + - `HOMEBREW_UPDATE_REPORT_ALL_FORMULAE`
If set, `brew update` lists changes to all formulae and cask files rather than only showing when they are new and not installed or outdated and installed. diff --git a/manpages/brew.1 b/manpages/brew.1 index 87c2999563..d340397ea2 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -3207,6 +3207,12 @@ Use this path as the temporary directory for building packages\. Changing this m \fIDefault:\fR macOS: \fB/private/tmp\fR, Linux: \fB/tmp\fR\. . .TP +\fBHOMEBREW_UNINSTALL_AUTOREMOVE\fR +. +.br +If set, \fBbrew autoremove\fR is run after every successful call to \fBbrew uninstall\fR\. +. +.TP \fBHOMEBREW_UPDATE_REPORT_ALL_FORMULAE\fR . .br From 74f1eca14c9b2e353eb0c32e35a005dfbb333a9b Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Tue, 12 Jul 2022 00:28:25 -0700 Subject: [PATCH 2/8] autoremove.rb: moved logic out into formula.rb, and uninstall.rb This allows us to autoremove formulae in the autoremove and uninstall commands without having to shell out to brew. --- Library/Homebrew/cmd/autoremove.rb | 30 +-------------------------- Library/Homebrew/cmd/uninstall.rb | 2 +- Library/Homebrew/formula.rb | 33 +++++++++++++++++++++++++++++- Library/Homebrew/uninstall.rb | 14 +++++++++++++ 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/Library/Homebrew/cmd/autoremove.rb b/Library/Homebrew/cmd/autoremove.rb index a80cb4ae49..c1a9b65cec 100644 --- a/Library/Homebrew/cmd/autoremove.rb +++ b/Library/Homebrew/cmd/autoremove.rb @@ -20,37 +20,9 @@ module Homebrew end end - def get_removable_formulae(formulae) - removable_formulae = Formula.installed_formulae_with_no_dependents(formulae).reject do |f| - Tab.for_keg(f.any_installed_keg).installed_on_request - end - - removable_formulae += get_removable_formulae(formulae - removable_formulae) if removable_formulae.present? - - removable_formulae - end - def autoremove args = autoremove_args.parse - removable_formulae = get_removable_formulae(Formula.installed) - - if (casks = Cask::Caskroom.casks.presence) - removable_formulae -= casks.flat_map { |cask| cask.depends_on[:formula] } - .compact - .map { |f| Formula[f] } - .flat_map { |f| [f, *f.runtime_formula_dependencies].compact } - end - return if removable_formulae.blank? - - formulae_names = removable_formulae.map(&:full_name).sort - - verb = args.dry_run? ? "Would uninstall" : "Uninstalling" - oh1 "#{verb} #{formulae_names.count} unneeded #{"formula".pluralize(formulae_names.count)}:" - puts formulae_names.join("\n") - return if args.dry_run? - - kegs_by_rack = removable_formulae.map(&:any_installed_keg).group_by(&:rack) - Uninstall.uninstall_kegs(kegs_by_rack) + Uninstall.autoremove_kegs(Formula.removable_formulae, dry_run: args.dry_run?) end end diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb index e8e1bb386c..fffa54a69f 100644 --- a/Library/Homebrew/cmd/uninstall.rb +++ b/Library/Homebrew/cmd/uninstall.rb @@ -81,6 +81,6 @@ module Homebrew return unless Homebrew::EnvConfig.uninstall_autoremove? - system HOMEBREW_BREW_FILE, "autoremove" + Uninstall.autoremove_kegs(Formula.removable_formulae) end end diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 17488e0ed1..d367e157dd 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -1706,7 +1706,7 @@ class Formula end.uniq(&:name) end - # An array of all installed {Formula} without dependents + # An array of all installed {Formula} without {Formula} dependents # @private def self.installed_formulae_with_no_dependents(formulae = installed) return [] if formulae.blank? @@ -1720,6 +1720,37 @@ class Formula installed.select { |f| f.installed_alias_path == alias_path } end + # An array of all installed {Formula} with {Cask} dependents. + # @private + def self.installed_formulae_with_cask_dependents + Cask::Caskroom.casks + .flat_map { |cask| cask.depends_on[:formula] } + .compact + .map { |f| Formula[f] } + .flat_map { |f| [f, *f.runtime_formula_dependencies].compact } + end + + # An array of all installed {Formula} without {Formula} or {Cask} dependents + # that weren't installed on request. + # @private + def self.removable_formulae + formulae = installed + all_removable_formulae = T.let([], T::Array[Formula]) + + loop do + removable_formulae = installed_formulae_with_no_dependents(formulae).reject do |f| + Tab.for_keg(f.any_installed_keg).installed_on_request + end + + break if removable_formulae.blank? + + all_removable_formulae += removable_formulae + formulae -= removable_formulae + end + + all_removable_formulae - installed_formulae_with_cask_dependents + end + # an array of all alias files of core {Formula} # @private def self.core_alias_files diff --git a/Library/Homebrew/uninstall.rb b/Library/Homebrew/uninstall.rb index 1d9a1585e4..ee00fb849c 100644 --- a/Library/Homebrew/uninstall.rb +++ b/Library/Homebrew/uninstall.rb @@ -97,6 +97,20 @@ module Homebrew end end + def autoremove_kegs(removable_formulae, dry_run: false) + return if removable_formulae.blank? + + formulae_names = removable_formulae.map(&:full_name).sort + + verb = dry_run ? "Would uninstall" : "Uninstalling" + oh1 "#{verb} #{formulae_names.count} unneeded #{"formula".pluralize(formulae_names.count)}:" + puts formulae_names.join("\n") + return if dry_run + + kegs_by_rack = removable_formulae.map(&:any_installed_keg).group_by(&:rack) + Uninstall.uninstall_kegs(kegs_by_rack) + end + def handle_unsatisfied_dependents(kegs_by_rack, casks: [], ignore_dependencies: false, named_args: []) return if ignore_dependencies From 74f7b604cd00f1bd45410e6bbb6de36916ae9077 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Wed, 13 Jul 2022 11:28:54 -0700 Subject: [PATCH 3/8] Changed env variable to HOMEBREW_AUTOREMOVE --- Library/Homebrew/env_config.rb | 9 +++++---- .../sorbet/rbi/hidden-definitions/hidden.rbi | 4 ++-- docs/Manpage.md | 6 +++--- manpages/brew.1 | 12 ++++++------ 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index 115b292a97..b2b27fda69 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -36,6 +36,11 @@ module Homebrew "disable auto-update entirely with HOMEBREW_NO_AUTO_UPDATE.", default: 300, }, + HOMEBREW_AUTOREMOVE: { + description: "If set, calls to `brew install`, `brew upgrade`, `brew reinstall` and `brew uninstall` " \ + "will automatically remove unused formula dependents.", + boolean: true, + }, HOMEBREW_BAT: { description: "If set, use `bat` for the `brew cat` command.", boolean: true, @@ -343,10 +348,6 @@ module Homebrew default_text: "macOS: `/private/tmp`, Linux: `/tmp`.", default: HOMEBREW_DEFAULT_TEMP, }, - HOMEBREW_UNINSTALL_AUTOREMOVE: { - description: "If set, `brew autoremove` is run after every successful call to `brew uninstall`.", - boolean: true, - }, HOMEBREW_UPDATE_REPORT_ALL_FORMULAE: { description: "If set, `brew update` lists changes to all formulae and cask files rather than only showing " \ "when they are new and not installed or outdated and installed.", diff --git a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi index 271c840e99..f22b19bd3a 100644 --- a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi +++ b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi @@ -2442,6 +2442,8 @@ module Homebrew::EnvConfig def self.artifact_domain(); end + def self.autoremove?(); end + def self.auto_update_secs(); end def self.bat?(); end @@ -2572,8 +2574,6 @@ module Homebrew::EnvConfig def self.temp(); end - def self.uninstall_autoremove?(); end - def self.update_report_all_formulae?(); end def self.update_to_tag?(); end diff --git a/docs/Manpage.md b/docs/Manpage.md index bd9abaa82a..b7a7a28215 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -1945,6 +1945,9 @@ example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just *Default:* `300`. +- `HOMEBREW_AUTOREMOVE` +
If set, calls to `brew install`, `brew upgrade`, `brew reinstall` and `brew uninstall` will automatically remove unused formula dependents. + - `HOMEBREW_BAT`
If set, use `bat` for the `brew cat` command. @@ -2184,9 +2187,6 @@ example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just *Default:* macOS: `/private/tmp`, Linux: `/tmp`. -- `HOMEBREW_UNINSTALL_AUTOREMOVE` -
If set, `brew autoremove` is run after every successful call to `brew uninstall`. - - `HOMEBREW_UPDATE_REPORT_ALL_FORMULAE`
If set, `brew update` lists changes to all formulae and cask files rather than only showing when they are new and not installed or outdated and installed. diff --git a/manpages/brew.1 b/manpages/brew.1 index d340397ea2..680e979622 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -2757,6 +2757,12 @@ Run \fBbrew update\fR once every \fBHOMEBREW_AUTO_UPDATE_SECS\fR seconds before \fIDefault:\fR \fB300\fR\. . .TP +\fBHOMEBREW_AUTOREMOVE\fR +. +.br +If set, calls to \fBbrew install\fR, \fBbrew upgrade\fR, \fBbrew reinstall\fR and \fBbrew uninstall\fR will automatically remove unused formula dependents\. +. +.TP \fBHOMEBREW_BAT\fR . .br @@ -3207,12 +3213,6 @@ Use this path as the temporary directory for building packages\. Changing this m \fIDefault:\fR macOS: \fB/private/tmp\fR, Linux: \fB/tmp\fR\. . .TP -\fBHOMEBREW_UNINSTALL_AUTOREMOVE\fR -. -.br -If set, \fBbrew autoremove\fR is run after every successful call to \fBbrew uninstall\fR\. -. -.TP \fBHOMEBREW_UPDATE_REPORT_ALL_FORMULAE\fR . .br From fa43418bfbd7b0c1ceea3b03663b6d93282f4b84 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Wed, 13 Jul 2022 11:46:43 -0700 Subject: [PATCH 4/8] Moved autoremove logic into autoremove.rb This allows us to call that logic internally in other brew commands instead of having to shell out. --- Library/Homebrew/autoremove.rb | 64 ++++++++++++++++++++++++++++++ Library/Homebrew/cmd/autoremove.rb | 5 +-- Library/Homebrew/cmd/install.rb | 3 ++ Library/Homebrew/cmd/reinstall.rb | 3 ++ Library/Homebrew/cmd/uninstall.rb | 4 +- Library/Homebrew/cmd/upgrade.rb | 3 ++ Library/Homebrew/env_config.rb | 2 +- Library/Homebrew/formula.rb | 31 --------------- Library/Homebrew/uninstall.rb | 14 ------- 9 files changed, 77 insertions(+), 52 deletions(-) create mode 100644 Library/Homebrew/autoremove.rb diff --git a/Library/Homebrew/autoremove.rb b/Library/Homebrew/autoremove.rb new file mode 100644 index 0000000000..cebf54a1ab --- /dev/null +++ b/Library/Homebrew/autoremove.rb @@ -0,0 +1,64 @@ +# typed: false +# frozen_string_literal: true + +require "cask/caskroom" +require "formula" +require "uninstall" + +module Homebrew + # Helpers for removing unused formulae. + # + # @api private + module Autoremove + module_function + + def remove_unused_formulae(dry_run: false) + removable_formulae = unused_formulae_with_no_dependents + + return if removable_formulae.blank? + + formulae_names = removable_formulae.map(&:full_name).sort + + verb = dry_run ? "Would autoremove" : "Autoremoving" + oh1 "#{verb} #{formulae_names.count} unneeded #{"formula".pluralize(formulae_names.count)}:" + puts formulae_names.join("\n") + return if dry_run + + kegs_by_rack = removable_formulae.map(&:any_installed_keg).group_by(&:rack) + Uninstall.uninstall_kegs(kegs_by_rack) + end + + # An array of installed {Formula} without {Formula} or {Cask} + # dependents that weren't installed on request. + # @private + def unused_formulae_with_no_dependents + unused_formulae = unused_formulae_with_no_formula_dependents(Formula.installed) + unused_formulae - installed_formulae_with_cask_dependents + end + + # Recursive function that returns an array of installed {Formula} without + # {Formula} dependents that weren't installed on request. + # @private + def unused_formulae_with_no_formula_dependents(formulae) + unused_formulae = Formula.installed_formulae_with_no_dependents(formulae).reject do |f| + Tab.for_keg(f.any_installed_keg).installed_on_request + end + + if unused_formulae.present? + unused_formulae += unused_formulae_with_no_formula_dependents(formulae - unused_formulae) + end + + unused_formulae + end + + # An array of all installed {Formula} with {Cask} dependents. + # @private + def installed_formulae_with_cask_dependents + Cask::Caskroom.casks + .flat_map { |cask| cask.depends_on[:formula] } + .compact + .map { |f| Formula[f] } + .flat_map { |f| [f, *f.runtime_formula_dependencies].compact } + end + end +end diff --git a/Library/Homebrew/cmd/autoremove.rb b/Library/Homebrew/cmd/autoremove.rb index c1a9b65cec..9cd02cb40a 100644 --- a/Library/Homebrew/cmd/autoremove.rb +++ b/Library/Homebrew/cmd/autoremove.rb @@ -1,9 +1,8 @@ # typed: true # frozen_string_literal: true -require "formula" +require "autoremove" require "cli/parser" -require "uninstall" module Homebrew module_function @@ -23,6 +22,6 @@ module Homebrew def autoremove args = autoremove_args.parse - Uninstall.autoremove_kegs(Formula.removable_formulae, dry_run: args.dry_run?) + Autoremove.remove_unused_formulae(dry_run: args.dry_run?) end end diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index cff794979e..8c555b92ee 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -1,6 +1,7 @@ # typed: false # frozen_string_literal: true +require "autoremove" require "cask/config" require "cask/cmd" require "cask/cmd/install" @@ -254,6 +255,8 @@ module Homebrew ) Homebrew.messages.display_messages(display_times: args.display_times?) + + Autoremove.remove_unused_formulae if Homebrew::EnvConfig.autoremove? rescue FormulaUnreadableError, FormulaClassUnavailableError, TapFormulaUnreadableError, TapFormulaClassUnavailableError => e # Need to rescue before `FormulaUnavailableError` (superclass of this) diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index bc6bca5053..e24f30ce74 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -1,6 +1,7 @@ # typed: false # frozen_string_literal: true +require "autoremove" require "formula_installer" require "development_tools" require "messages" @@ -152,5 +153,7 @@ module Homebrew end Homebrew.messages.display_messages(display_times: args.display_times?) + + Autoremove.remove_unused_formulae if Homebrew::EnvConfig.autoremove? end end diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb index fffa54a69f..0ba3018709 100644 --- a/Library/Homebrew/cmd/uninstall.rb +++ b/Library/Homebrew/cmd/uninstall.rb @@ -79,8 +79,6 @@ module Homebrew ) end - return unless Homebrew::EnvConfig.uninstall_autoremove? - - Uninstall.autoremove_kegs(Formula.removable_formulae) + Autoremove.remove_unused_formulae if Homebrew::EnvConfig.autoremove? end end diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index ec7520a7c3..62b5e7cbc1 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -1,6 +1,7 @@ # typed: false # frozen_string_literal: true +require "autoremove" require "cli/parser" require "formula_installer" require "install" @@ -111,6 +112,8 @@ module Homebrew upgrade_outdated_casks(casks, args: args) unless only_upgrade_formulae Homebrew.messages.display_messages(display_times: args.display_times?) + + Autoremove.remove_unused_formulae(dry_run: args.dry_run?) if Homebrew::EnvConfig.autoremove? end sig { params(formulae: T::Array[Formula], args: CLI::Args).returns(T::Boolean) } diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index b2b27fda69..f56c3a0ddb 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -36,7 +36,7 @@ module Homebrew "disable auto-update entirely with HOMEBREW_NO_AUTO_UPDATE.", default: 300, }, - HOMEBREW_AUTOREMOVE: { + HOMEBREW_AUTOREMOVE: { description: "If set, calls to `brew install`, `brew upgrade`, `brew reinstall` and `brew uninstall` " \ "will automatically remove unused formula dependents.", boolean: true, diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index d367e157dd..fc496d4e8d 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -1720,37 +1720,6 @@ class Formula installed.select { |f| f.installed_alias_path == alias_path } end - # An array of all installed {Formula} with {Cask} dependents. - # @private - def self.installed_formulae_with_cask_dependents - Cask::Caskroom.casks - .flat_map { |cask| cask.depends_on[:formula] } - .compact - .map { |f| Formula[f] } - .flat_map { |f| [f, *f.runtime_formula_dependencies].compact } - end - - # An array of all installed {Formula} without {Formula} or {Cask} dependents - # that weren't installed on request. - # @private - def self.removable_formulae - formulae = installed - all_removable_formulae = T.let([], T::Array[Formula]) - - loop do - removable_formulae = installed_formulae_with_no_dependents(formulae).reject do |f| - Tab.for_keg(f.any_installed_keg).installed_on_request - end - - break if removable_formulae.blank? - - all_removable_formulae += removable_formulae - formulae -= removable_formulae - end - - all_removable_formulae - installed_formulae_with_cask_dependents - end - # an array of all alias files of core {Formula} # @private def self.core_alias_files diff --git a/Library/Homebrew/uninstall.rb b/Library/Homebrew/uninstall.rb index ee00fb849c..1d9a1585e4 100644 --- a/Library/Homebrew/uninstall.rb +++ b/Library/Homebrew/uninstall.rb @@ -97,20 +97,6 @@ module Homebrew end end - def autoremove_kegs(removable_formulae, dry_run: false) - return if removable_formulae.blank? - - formulae_names = removable_formulae.map(&:full_name).sort - - verb = dry_run ? "Would uninstall" : "Uninstalling" - oh1 "#{verb} #{formulae_names.count} unneeded #{"formula".pluralize(formulae_names.count)}:" - puts formulae_names.join("\n") - return if dry_run - - kegs_by_rack = removable_formulae.map(&:any_installed_keg).group_by(&:rack) - Uninstall.uninstall_kegs(kegs_by_rack) - end - def handle_unsatisfied_dependents(kegs_by_rack, casks: [], ignore_dependencies: false, named_args: []) return if ignore_dependencies From fe83500617293a1e777cb8c7cec404574513fd20 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Thu, 14 Jul 2022 13:16:26 -0700 Subject: [PATCH 5/8] Moved autoremove logic into cleanup.rb and formula.rb Cleanup.rb: - Added #autoremove method - #autoremove is called in clean when HOMEBREW_AUTOREMOVE is set Formula.rb: - Added #unused_formulae_with_no_dependents and helpers Removed old autoremove.rb module. --- Library/Homebrew/autoremove.rb | 64 --------------------------- Library/Homebrew/cleanup.rb | 23 ++++++++++ Library/Homebrew/cmd/autoremove.rb | 4 +- Library/Homebrew/cmd/install.rb | 3 -- Library/Homebrew/cmd/leaves.rb | 2 +- Library/Homebrew/cmd/reinstall.rb | 3 -- Library/Homebrew/cmd/uninstall.rb | 2 +- Library/Homebrew/cmd/upgrade.rb | 3 -- Library/Homebrew/formula.rb | 37 +++++++++++++++- Library/Homebrew/test/formula_spec.rb | 6 +-- 10 files changed, 66 insertions(+), 81 deletions(-) delete mode 100644 Library/Homebrew/autoremove.rb diff --git a/Library/Homebrew/autoremove.rb b/Library/Homebrew/autoremove.rb deleted file mode 100644 index cebf54a1ab..0000000000 --- a/Library/Homebrew/autoremove.rb +++ /dev/null @@ -1,64 +0,0 @@ -# typed: false -# frozen_string_literal: true - -require "cask/caskroom" -require "formula" -require "uninstall" - -module Homebrew - # Helpers for removing unused formulae. - # - # @api private - module Autoremove - module_function - - def remove_unused_formulae(dry_run: false) - removable_formulae = unused_formulae_with_no_dependents - - return if removable_formulae.blank? - - formulae_names = removable_formulae.map(&:full_name).sort - - verb = dry_run ? "Would autoremove" : "Autoremoving" - oh1 "#{verb} #{formulae_names.count} unneeded #{"formula".pluralize(formulae_names.count)}:" - puts formulae_names.join("\n") - return if dry_run - - kegs_by_rack = removable_formulae.map(&:any_installed_keg).group_by(&:rack) - Uninstall.uninstall_kegs(kegs_by_rack) - end - - # An array of installed {Formula} without {Formula} or {Cask} - # dependents that weren't installed on request. - # @private - def unused_formulae_with_no_dependents - unused_formulae = unused_formulae_with_no_formula_dependents(Formula.installed) - unused_formulae - installed_formulae_with_cask_dependents - end - - # Recursive function that returns an array of installed {Formula} without - # {Formula} dependents that weren't installed on request. - # @private - def unused_formulae_with_no_formula_dependents(formulae) - unused_formulae = Formula.installed_formulae_with_no_dependents(formulae).reject do |f| - Tab.for_keg(f.any_installed_keg).installed_on_request - end - - if unused_formulae.present? - unused_formulae += unused_formulae_with_no_formula_dependents(formulae - unused_formulae) - end - - unused_formulae - end - - # An array of all installed {Formula} with {Cask} dependents. - # @private - def installed_formulae_with_cask_dependents - Cask::Caskroom.casks - .flat_map { |cask| cask.depends_on[:formula] } - .compact - .map { |f| Formula[f] } - .flat_map { |f| [f, *f.runtime_formula_dependencies].compact } - end - end -end diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb index 4eb4689c9b..d31a51fca1 100644 --- a/Library/Homebrew/cleanup.rb +++ b/Library/Homebrew/cleanup.rb @@ -219,6 +219,9 @@ module Homebrew .each do |formula| cleanup_formula(formula, quiet: quiet, ds_store: false, cache_db: false) end + + Cleanup.autoremove(dry_run: dry_run?) if Homebrew::EnvConfig.autoremove? + cleanup_cache cleanup_logs cleanup_lockfiles @@ -261,6 +264,8 @@ module Homebrew end cleanup_cask(cask) if cask end + + Cleanup.autoremove(dry_run: dry_run?) if Homebrew::EnvConfig.autoremove? end end @@ -519,5 +524,23 @@ module Homebrew print "and #{d} directories " if d.positive? puts "from #{HOMEBREW_PREFIX}" end + + def self.autoremove(dry_run: false) + removable_formulae = Formula.unused_formulae_with_no_dependents + + return if removable_formulae.blank? + + formulae_names = removable_formulae.map(&:full_name).sort + + verb = dry_run ? "Would autoremove" : "Autoremoving" + oh1 "#{verb} #{formulae_names.count} unneeded #{"formula".pluralize(formulae_names.count)}:" + puts formulae_names.join("\n") + return if dry_run + + require "uninstall" + + kegs_by_rack = removable_formulae.map(&:any_installed_keg).group_by(&:rack) + Uninstall.uninstall_kegs(kegs_by_rack) + end end end diff --git a/Library/Homebrew/cmd/autoremove.rb b/Library/Homebrew/cmd/autoremove.rb index 9cd02cb40a..94dea99605 100644 --- a/Library/Homebrew/cmd/autoremove.rb +++ b/Library/Homebrew/cmd/autoremove.rb @@ -1,7 +1,7 @@ # typed: true # frozen_string_literal: true -require "autoremove" +require "cleanup" require "cli/parser" module Homebrew @@ -22,6 +22,6 @@ module Homebrew def autoremove args = autoremove_args.parse - Autoremove.remove_unused_formulae(dry_run: args.dry_run?) + Cleanup.autoremove(dry_run: args.dry_run?) end end diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 8c555b92ee..cff794979e 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -1,7 +1,6 @@ # typed: false # frozen_string_literal: true -require "autoremove" require "cask/config" require "cask/cmd" require "cask/cmd/install" @@ -255,8 +254,6 @@ module Homebrew ) Homebrew.messages.display_messages(display_times: args.display_times?) - - Autoremove.remove_unused_formulae if Homebrew::EnvConfig.autoremove? rescue FormulaUnreadableError, FormulaClassUnavailableError, TapFormulaUnreadableError, TapFormulaClassUnavailableError => e # Need to rescue before `FormulaUnavailableError` (superclass of this) diff --git a/Library/Homebrew/cmd/leaves.rb b/Library/Homebrew/cmd/leaves.rb index 1c003b4b96..f14bed7dfc 100644 --- a/Library/Homebrew/cmd/leaves.rb +++ b/Library/Homebrew/cmd/leaves.rb @@ -37,7 +37,7 @@ module Homebrew def leaves args = leaves_args.parse - leaves_list = Formula.installed_formulae_with_no_dependents + leaves_list = Formula.installed_formulae_with_no_formula_dependents leaves_list.select!(&method(:installed_on_request?)) if args.installed_on_request? leaves_list.select!(&method(:installed_as_dependency?)) if args.installed_as_dependency? diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index e24f30ce74..bc6bca5053 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -1,7 +1,6 @@ # typed: false # frozen_string_literal: true -require "autoremove" require "formula_installer" require "development_tools" require "messages" @@ -153,7 +152,5 @@ module Homebrew end Homebrew.messages.display_messages(display_times: args.display_times?) - - Autoremove.remove_unused_formulae if Homebrew::EnvConfig.autoremove? end end diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb index 0ba3018709..50a9abd5d1 100644 --- a/Library/Homebrew/cmd/uninstall.rb +++ b/Library/Homebrew/cmd/uninstall.rb @@ -79,6 +79,6 @@ module Homebrew ) end - Autoremove.remove_unused_formulae if Homebrew::EnvConfig.autoremove? + Cleanup.autoremove if Homebrew::EnvConfig.autoremove? end end diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index 62b5e7cbc1..ec7520a7c3 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -1,7 +1,6 @@ # typed: false # frozen_string_literal: true -require "autoremove" require "cli/parser" require "formula_installer" require "install" @@ -112,8 +111,6 @@ module Homebrew upgrade_outdated_casks(casks, args: args) unless only_upgrade_formulae Homebrew.messages.display_messages(display_times: args.display_times?) - - Autoremove.remove_unused_formulae(dry_run: args.dry_run?) if Homebrew::EnvConfig.autoremove? end sig { params(formulae: T::Array[Formula], args: CLI::Args).returns(T::Boolean) } diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index fc496d4e8d..5caa3876fd 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -1706,14 +1706,49 @@ class Formula end.uniq(&:name) end + # An array of all installed {Formula} with {Cask} dependents. + # @private + def self.installed_formulae_with_cask_dependents + require "cask/caskroom" + + Cask::Caskroom.casks + .flat_map { |cask| cask.depends_on[:formula] } + .compact + .map { |f| Formula[f] } + .flat_map { |f| [f, *f.runtime_formula_dependencies].compact } + end + # An array of all installed {Formula} without {Formula} dependents # @private - def self.installed_formulae_with_no_dependents(formulae = installed) + def self.installed_formulae_with_no_formula_dependents(formulae = installed) return [] if formulae.blank? formulae - formulae.flat_map(&:runtime_formula_dependencies) end + # Recursive function that returns an array of installed {Formula} without + # {Formula} dependents that weren't installed on request. + # @private + def self.unused_formulae_with_no_formula_dependents(formulae) + unused_formulae = installed_formulae_with_no_formula_dependents(formulae).reject do |f| + Tab.for_keg(f.any_installed_keg).installed_on_request + end + + if unused_formulae.present? + unused_formulae += unused_formulae_with_no_formula_dependents(formulae - unused_formulae) + end + + unused_formulae + end + + # An array of installed {Formula} without {Formula} or {Cask} + # dependents that weren't installed on request. + # @private + def self.unused_formulae_with_no_dependents + unused_formulae = unused_formulae_with_no_formula_dependents(installed) + unused_formulae - installed_formulae_with_cask_dependents + end + def self.installed_with_alias_path(alias_path) return [] if alias_path.nil? diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb index e47a197361..e8f3fa81d6 100644 --- a/Library/Homebrew/test/formula_spec.rb +++ b/Library/Homebrew/test/formula_spec.rb @@ -446,7 +446,7 @@ describe Formula do end end - describe "::installed_formulae_with_no_dependents" do + describe "::installed_formulae_with_no_formula_dependents" do let(:formula_is_dep) do formula "foo" do url "foo-1.1" @@ -473,12 +473,12 @@ describe Formula do specify "without formulae parameter" do allow(described_class).to receive(:installed).and_return(formulae) - expect(described_class.installed_formulae_with_no_dependents) + expect(described_class.installed_formulae_with_no_formula_dependents) .to eq([formula_with_deps]) end specify "with formulae parameter" do - expect(described_class.installed_formulae_with_no_dependents(formulae)) + expect(described_class.installed_formulae_with_no_formula_dependents(formulae)) .to eq([formula_with_deps]) end end From cb91f8b66503557221a495fe8d853f19c904eaf6 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Fri, 15 Jul 2022 16:27:22 -0700 Subject: [PATCH 6/8] Add tests for retrieving formula based on dependents Also, made sure to clear formula cache before and after autoremoving packages. --- Library/Homebrew/cleanup.rb | 25 ++++-- Library/Homebrew/cmd/leaves.rb | 2 +- Library/Homebrew/formula.rb | 27 +++--- Library/Homebrew/test/formula_spec.rb | 123 ++++++++++++++++++++++---- 4 files changed, 139 insertions(+), 38 deletions(-) diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb index d31a51fca1..e381088a1d 100644 --- a/Library/Homebrew/cleanup.rb +++ b/Library/Homebrew/cleanup.rb @@ -160,7 +160,7 @@ module Homebrew cleanup = Cleanup.new(dry_run: dry_run) if cleanup.periodic_clean_due? cleanup.periodic_clean! - elsif f.latest_version_installed? && !cleanup.skip_clean_formula?(f) + elsif f.latest_version_installed? && !Cleanup.skip_clean_formula?(f) ohai "Running `brew cleanup #{f}`..." puts_no_install_cleanup_disable_message_if_not_already! cleanup.cleanup_formula(f) @@ -177,7 +177,7 @@ module Homebrew @puts_no_install_cleanup_disable_message_if_not_already = true end - def skip_clean_formula?(f) + def self.skip_clean_formula?(f) return false if Homebrew::EnvConfig.no_cleanup_formulae.blank? skip_clean_formulae = Homebrew::EnvConfig.no_cleanup_formulae.split(",") @@ -215,7 +215,7 @@ module Homebrew if args.empty? Formula.installed .sort_by(&:name) - .reject { |f| skip_clean_formula?(f) } + .reject { |f| Cleanup.skip_clean_formula?(f) } .each do |formula| cleanup_formula(formula, quiet: quiet, ds_store: false, cache_db: false) end @@ -256,7 +256,7 @@ module Homebrew nil end - if formula && skip_clean_formula?(formula) + if formula && Cleanup.skip_clean_formula?(formula) onoe "Refusing to clean #{formula} because it is listed in " \ "#{Tty.bold}HOMEBREW_NO_CLEANUP_FORMULAE#{Tty.reset}!" elsif formula @@ -264,8 +264,6 @@ module Homebrew end cleanup_cask(cask) if cask end - - Cleanup.autoremove(dry_run: dry_run?) if Homebrew::EnvConfig.autoremove? end end @@ -526,7 +524,17 @@ module Homebrew end def self.autoremove(dry_run: false) - removable_formulae = Formula.unused_formulae_with_no_dependents + require "cask/caskroom" + + # If this runs after install, uninstall, reinstall or upgrade, + # the cache of installed formulae may no longer be valid. + Formula.clear_cache unless dry_run + + # Remove formulae listed in HOMEBREW_NO_CLEANUP_FORMULAE. + formulae = Formula.installed.reject(&method(:skip_clean_formula?)) + casks = Cask::Caskroom.casks + + removable_formulae = Formula.unused_formulae_with_no_dependents(formulae, casks) return if removable_formulae.blank? @@ -541,6 +549,9 @@ module Homebrew kegs_by_rack = removable_formulae.map(&:any_installed_keg).group_by(&:rack) Uninstall.uninstall_kegs(kegs_by_rack) + + # The installed formula cache will be invalid after uninstalling. + Formula.clear_cache end end end diff --git a/Library/Homebrew/cmd/leaves.rb b/Library/Homebrew/cmd/leaves.rb index f14bed7dfc..ec134de4a1 100644 --- a/Library/Homebrew/cmd/leaves.rb +++ b/Library/Homebrew/cmd/leaves.rb @@ -37,7 +37,7 @@ module Homebrew def leaves args = leaves_args.parse - leaves_list = Formula.installed_formulae_with_no_formula_dependents + leaves_list = Formula.formulae_with_no_formula_dependents(Formula.installed) leaves_list.select!(&method(:installed_on_request?)) if args.installed_on_request? leaves_list.select!(&method(:installed_as_dependency?)) if args.installed_as_dependency? diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 5caa3876fd..4db86ebed3 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -1708,29 +1708,26 @@ class Formula # An array of all installed {Formula} with {Cask} dependents. # @private - def self.installed_formulae_with_cask_dependents - require "cask/caskroom" - - Cask::Caskroom.casks - .flat_map { |cask| cask.depends_on[:formula] } - .compact - .map { |f| Formula[f] } - .flat_map { |f| [f, *f.runtime_formula_dependencies].compact } + def self.formulae_with_cask_dependents(casks) + casks.flat_map { |cask| cask.depends_on[:formula] } + .compact + .map { |f| Formula[f] } + .flat_map { |f| [f, *f.runtime_formula_dependencies].compact } end # An array of all installed {Formula} without {Formula} dependents # @private - def self.installed_formulae_with_no_formula_dependents(formulae = installed) + def self.formulae_with_no_formula_dependents(formulae) return [] if formulae.blank? formulae - formulae.flat_map(&:runtime_formula_dependencies) end - # Recursive function that returns an array of installed {Formula} without + # Recursive function that returns an array of {Formula} without # {Formula} dependents that weren't installed on request. # @private def self.unused_formulae_with_no_formula_dependents(formulae) - unused_formulae = installed_formulae_with_no_formula_dependents(formulae).reject do |f| + unused_formulae = formulae_with_no_formula_dependents(formulae).reject do |f| Tab.for_keg(f.any_installed_keg).installed_on_request end @@ -1741,12 +1738,12 @@ class Formula unused_formulae end - # An array of installed {Formula} without {Formula} or {Cask} + # An array of {Formula} without {Formula} or {Cask} # dependents that weren't installed on request. # @private - def self.unused_formulae_with_no_dependents - unused_formulae = unused_formulae_with_no_formula_dependents(installed) - unused_formulae - installed_formulae_with_cask_dependents + def self.unused_formulae_with_no_dependents(formulae, casks) + unused_formulae = unused_formulae_with_no_formula_dependents(formulae) + unused_formulae - formulae_with_cask_dependents(casks) end def self.installed_with_alias_path(alias_path) diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb index e8f3fa81d6..1ed7890557 100644 --- a/Library/Homebrew/test/formula_spec.rb +++ b/Library/Homebrew/test/formula_spec.rb @@ -446,40 +446,133 @@ describe Formula do end end - describe "::installed_formulae_with_no_formula_dependents" do - let(:formula_is_dep) do - formula "foo" do - url "foo-1.1" + shared_context "with formulae for dependency testing" do + let(:formula_with_deps) do + formula "zero" do + url "zero-1.0" end end - let(:formula_with_deps) do - formula "bar" do - url "bar-1.0" + let(:formula_is_dep1) do + formula "one" do + url "one-1.1" + end + end + + let(:formula_is_dep2) do + formula "two" do + url "two-1.1" end end let(:formulae) do [ formula_with_deps, - formula_is_dep, + formula_is_dep1, + formula_is_dep2, ] end before do - allow(formula_with_deps).to receive(:runtime_formula_dependencies).and_return([formula_is_dep]) + allow(formula_with_deps).to receive(:runtime_formula_dependencies).and_return([formula_is_dep1, + formula_is_dep2]) + allow(formula_is_dep1).to receive(:runtime_formula_dependencies).and_return([formula_is_dep2]) end + end - specify "without formulae parameter" do - allow(described_class).to receive(:installed).and_return(formulae) + describe "::formulae_with_no_formula_dependents" do + include_context "with formulae for dependency testing" - expect(described_class.installed_formulae_with_no_formula_dependents) + it "filters out dependencies" do + expect(described_class.formulae_with_no_formula_dependents(formulae)) .to eq([formula_with_deps]) end + end - specify "with formulae parameter" do - expect(described_class.installed_formulae_with_no_formula_dependents(formulae)) - .to eq([formula_with_deps]) + describe "::unused_formulae_with_no_formula_dependents" do + include_context "with formulae for dependency testing" + + let(:tab_from_keg) { double } + + before do + allow(Tab).to receive(:for_keg).and_return(tab_from_keg) + end + + specify "installed on request" do + allow(tab_from_keg).to receive(:installed_on_request).and_return(true) + expect(described_class.unused_formulae_with_no_formula_dependents(formulae)) + .to eq([]) + end + + specify "not installed on request" do + allow(tab_from_keg).to receive(:installed_on_request).and_return(false) + expect(described_class.unused_formulae_with_no_formula_dependents(formulae)) + .to eq(formulae) + end + end + + shared_context "with formulae and casks for dependency testing" do + include_context "with formulae for dependency testing" + + require "cask/cask_loader" + + let(:cask_one_dep) do + Cask::CaskLoader.load(+<<-RUBY) + cask "red" do + depends_on formula: "two" + end + RUBY + end + + let(:cask_multiple_deps) do + Cask::CaskLoader.load(+<<-RUBY) + cask "blue" do + depends_on formula: "zero" + end + RUBY + end + + let(:cask_no_deps1) do + Cask::CaskLoader.load(+<<-RUBY) + cask "green" do + end + RUBY + end + + let(:cask_no_deps2) do + Cask::CaskLoader.load(+<<-RUBY) + cask "purple" do + end + RUBY + end + + let(:casks_no_deps) { [cask_no_deps1, cask_no_deps2] } + let(:casks_one_dep) { [cask_no_deps1, cask_no_deps2, cask_one_dep] } + let(:casks_multiple_deps) { [cask_no_deps1, cask_no_deps2, cask_multiple_deps] } + + before do + allow(described_class).to receive("[]").with("zero").and_return(formula_with_deps) + allow(described_class).to receive("[]").with("one").and_return(formula_is_dep1) + allow(described_class).to receive("[]").with("two").and_return(formula_is_dep2) + end + end + + describe "::formulae_with_cask_dependents" do + include_context "with formulae and casks for dependency testing" + + specify "no dependents" do + expect(described_class.formulae_with_cask_dependents(casks_no_deps)) + .to eq([]) + end + + specify "one dependent" do + expect(described_class.formulae_with_cask_dependents(casks_one_dep)) + .to eq([formula_is_dep2]) + end + + specify "multiple dependents" do + expect(described_class.formulae_with_cask_dependents(casks_multiple_deps)) + .to eq(formulae) end end From 85cf0ca6d4b3d9d934c61150891baaeea3209ae2 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sun, 17 Jul 2022 00:59:43 -0700 Subject: [PATCH 7/8] Updated env variable docs on manpage Updated docs for: HOMEBREW_AUTOREMOVE HOMEBREW_NO_CLEANUP_FORMULAE --- Library/Homebrew/env_config.rb | 9 +++++---- docs/Manpage.md | 4 ++-- manpages/brew.1 | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index f56c3a0ddb..014b24d27d 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -37,8 +37,9 @@ module Homebrew default: 300, }, HOMEBREW_AUTOREMOVE: { - description: "If set, calls to `brew install`, `brew upgrade`, `brew reinstall` and `brew uninstall` " \ - "will automatically remove unused formula dependents.", + description: "If set, calls to `brew cleanup` and `brew uninstall` will automatically " \ + "remove unused formula dependents and if HOMEBREW_NO_INSTALL_CLEANUP is not set, " \ + "`brew cleanup` will start running `brew autoremove` periodically.", boolean: true, }, HOMEBREW_BAT: { @@ -268,8 +269,8 @@ module Homebrew boolean: true, }, HOMEBREW_NO_CLEANUP_FORMULAE: { - description: "A comma-separated list of formulae. Homebrew will refuse to clean up a " \ - "formula if it appears on this list.", + description: "A comma-separated list of formulae. Homebrew will refuse to clean up " \ + "or autoremove a formula if it appears on this list.", }, HOMEBREW_NO_COLOR: { description: "If set, do not print text with colour added.", diff --git a/docs/Manpage.md b/docs/Manpage.md index b7a7a28215..370adf8034 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -1946,7 +1946,7 @@ example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just *Default:* `300`. - `HOMEBREW_AUTOREMOVE` -
If set, calls to `brew install`, `brew upgrade`, `brew reinstall` and `brew uninstall` will automatically remove unused formula dependents. +
If set, calls to `brew cleanup` and `brew uninstall` will automatically remove unused formula dependents and if HOMEBREW_NO_INSTALL_CLEANUP is not set, `brew cleanup` will start running `brew autoremove` periodically. - `HOMEBREW_BAT`
If set, use `bat` for the `brew cat` command. @@ -2128,7 +2128,7 @@ example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just
If set, do not check for broken linkage of dependents or outdated dependents after installing, upgrading or reinstalling formulae. This will result in fewer dependents (and their dependencies) being upgraded or reinstalled but may result in more breakage from running `brew install *`formula`*` or `brew upgrade *`formula`*`. - `HOMEBREW_NO_CLEANUP_FORMULAE` -
A comma-separated list of formulae. Homebrew will refuse to clean up a formula if it appears on this list. +
A comma-separated list of formulae. Homebrew will refuse to clean up or autoremove a formula if it appears on this list. - `HOMEBREW_NO_COLOR`
If set, do not print text with colour added. diff --git a/manpages/brew.1 b/manpages/brew.1 index 680e979622..2de072478d 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -2760,7 +2760,7 @@ Run \fBbrew update\fR once every \fBHOMEBREW_AUTO_UPDATE_SECS\fR seconds before \fBHOMEBREW_AUTOREMOVE\fR . .br -If set, calls to \fBbrew install\fR, \fBbrew upgrade\fR, \fBbrew reinstall\fR and \fBbrew uninstall\fR will automatically remove unused formula dependents\. +If set, calls to \fBbrew cleanup\fR and \fBbrew uninstall\fR will automatically remove unused formula dependents and if HOMEBREW_NO_INSTALL_CLEANUP is not set, \fBbrew cleanup\fR will start running \fBbrew autoremove\fR periodically\. . .TP \fBHOMEBREW_BAT\fR @@ -3102,7 +3102,7 @@ If set, do not check for broken linkage of dependents or outdated dependents aft \fBHOMEBREW_NO_CLEANUP_FORMULAE\fR . .br -A comma\-separated list of formulae\. Homebrew will refuse to clean up a formula if it appears on this list\. +A comma\-separated list of formulae\. Homebrew will refuse to clean up or autoremove a formula if it appears on this list\. . .TP \fBHOMEBREW_NO_COLOR\fR From d04051a9b94553fb4290929f12aeb5c72062d2aa Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Fri, 29 Jul 2022 23:49:23 -0700 Subject: [PATCH 8/8] Add integration tests for autoremove cmd --- Library/Homebrew/test/cmd/autoremove_spec.rb | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Library/Homebrew/test/cmd/autoremove_spec.rb b/Library/Homebrew/test/cmd/autoremove_spec.rb index 24069e0bb7..1644fbf009 100644 --- a/Library/Homebrew/test/cmd/autoremove_spec.rb +++ b/Library/Homebrew/test/cmd/autoremove_spec.rb @@ -5,4 +5,34 @@ require "cmd/shared_examples/args_parse" describe "brew autoremove" do it_behaves_like "parseable arguments" + + describe "integration test" do + let(:requested_formula) { Formula["testball1"] } + let(:unused_formula) { Formula["testball2"] } + + before do + install_test_formula "testball1" + install_test_formula "testball2" + + # Make testball2 an unused dependency + tab = Tab.for_name("testball2") + tab.installed_on_request = false + tab.installed_as_dependency = true + tab.write + end + + it "only removes unused dependencies", :integration_test do + expect(requested_formula.any_version_installed?).to be true + expect(unused_formula.any_version_installed?).to be true + + # When there are unused dependencies + expect { brew "autoremove" } + .to be_a_success + .and output(/Autoremoving/).to_stdout + .and not_to_output.to_stderr + + expect(requested_formula.any_version_installed?).to be true + expect(unused_formula.any_version_installed?).to be false + end + end end