From dcba99c7d132efb310ecf61eec717177cbacf7b9 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Mon, 2 Nov 2020 11:20:09 +0000 Subject: [PATCH] Revert "Revert "Improve @-versioned formulae linking."" --- Library/Homebrew/cmd/link.rb | 24 +++++++++++---------- Library/Homebrew/cmd/switch.rb | 3 +++ Library/Homebrew/cmd/unlink.rb | 7 ++----- Library/Homebrew/formula.rb | 8 +++---- Library/Homebrew/formula_installer.rb | 3 +++ Library/Homebrew/keg.rb | 2 ++ Library/Homebrew/unlink.rb | 30 +++++++++++++++++++++++++++ docs/Manpage.md | 4 ---- manpages/brew.1 | 3 --- 9 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 Library/Homebrew/unlink.rb diff --git a/Library/Homebrew/cmd/link.rb b/Library/Homebrew/cmd/link.rb index ad48c17792..f84fa9411d 100644 --- a/Library/Homebrew/cmd/link.rb +++ b/Library/Homebrew/cmd/link.rb @@ -4,6 +4,7 @@ require "ostruct" require "caveats" require "cli/parser" +require "unlink" module Homebrew module_function @@ -66,26 +67,27 @@ module Homebrew next end + formula = keg.to_formula + if keg_only - if Homebrew.default_prefix? - f = keg.to_formula - if f.keg_only_reason.by_macos? - caveats = Caveats.new(f) - opoo <<~EOS - Refusing to link macOS provided/shadowed software: #{keg.name} - #{caveats.keg_only_text(skip_reason: true).strip} - EOS - next - end + if Homebrew.default_prefix? && formula.keg_only_reason.by_macos? + caveats = Caveats.new(formula) + opoo <<~EOS + Refusing to link macOS provided/shadowed software: #{keg.name} + #{caveats.keg_only_text(skip_reason: true).strip} + EOS + next end - unless args.force? + if !formula.keg_only_reason.versioned_formula? && !args.force? opoo "#{keg.name} is keg-only and must be linked with --force" puts_keg_only_path_message(keg) next end end + Unlink.unlink_versioned_formulae(formula, verbose: args.verbose?) + keg.lock do print "Linking #{keg}... " puts if args.verbose? diff --git a/Library/Homebrew/cmd/switch.rb b/Library/Homebrew/cmd/switch.rb index 94389f2b8e..0877f51d09 100644 --- a/Library/Homebrew/cmd/switch.rb +++ b/Library/Homebrew/cmd/switch.rb @@ -17,6 +17,7 @@ module Homebrew EOS named 2 + hide_from_man_page! end end @@ -28,6 +29,8 @@ module Homebrew odie "#{name} not found in the Cellar." unless rack.directory? + # odeprecated "`brew switch`", "`brew link` @-versioned formulae" + versions = rack.subdirs .map { |d| Keg.new(d).version } .sort diff --git a/Library/Homebrew/cmd/unlink.rb b/Library/Homebrew/cmd/unlink.rb index 080bcd1636..2abbc3d947 100644 --- a/Library/Homebrew/cmd/unlink.rb +++ b/Library/Homebrew/cmd/unlink.rb @@ -3,6 +3,7 @@ require "ostruct" require "cli/parser" +require "unlink" module Homebrew module_function @@ -36,11 +37,7 @@ module Homebrew next end - keg.lock do - print "Unlinking #{keg}... " - puts if args.verbose? - puts "#{keg.unlink(**options)} symlinks removed" - end + Unlink.unlink(keg, dry_run: args.dry_run?, verbose: args.verbose?) end end end diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 6812b905f4..5dd79b65dd 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -414,12 +414,12 @@ class Formula name.include?("@") end - # Returns any `@`-versioned formulae for an non-`@`-versioned formula. + # Returns any `@`-versioned formulae for any formula (including versioned formulae). def versioned_formulae - return [] if versioned_formula? + Pathname.glob(path.to_s.gsub(/(@[\d.]+)?\.rb$/, "@*.rb")).map do |versioned_path| + next if versioned_path == path - Pathname.glob(path.to_s.gsub(/\.rb$/, "@*.rb")).map do |path| - Formula[path.basename(".rb").to_s] + Formula[versioned_path.basename(".rb").to_s] rescue FormulaUnavailableError nil end.compact.sort_by(&:version).reverse diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index c9a29c3315..57aedf4434 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -22,6 +22,7 @@ require "cmd/install" require "find" require "utils/spdx" require "deprecate_disable" +require "unlink" # Installer for a formula. # @@ -884,6 +885,8 @@ class FormulaInstaller keg.remove_linked_keg_record end + Homebrew::Unlink.unlink_versioned_formulae(formula, verbose: verbose?) + link_overwrite_backup = {} # Hash: conflict file -> backup file backup_dir = HOMEBREW_CACHE/"Backup" diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb index 902ed12f38..a06ac9617f 100644 --- a/Library/Homebrew/keg.rb +++ b/Library/Homebrew/keg.rb @@ -335,6 +335,7 @@ class Keg EOS end + # TODO: refactor to use keyword arguments. def unlink(**options) ObserverPathnameExtension.reset_counts! @@ -448,6 +449,7 @@ class Keg end end + # TODO: refactor to use keyword arguments. def link(**options) raise AlreadyLinkedError, self if linked_keg_record.directory? diff --git a/Library/Homebrew/unlink.rb b/Library/Homebrew/unlink.rb new file mode 100644 index 0000000000..bd265d5c5c --- /dev/null +++ b/Library/Homebrew/unlink.rb @@ -0,0 +1,30 @@ +# typed: false +# frozen_string_literal: true + +module Homebrew + # Provides helper methods for unlinking formulae and kegs with consistent output. + module Unlink + module_function + + def unlink_versioned_formulae(formula, verbose: false) + formula.versioned_formulae + .select(&:linked?) + .map(&:any_installed_keg) + .compact + .select(&:directory?) + .each do |keg| + unlink(keg, verbose: verbose) + end + end + + def unlink(keg, dry_run: false, verbose: false) + options = { dry_run: dry_run, verbose: verbose } + + keg.lock do + print "Unlinking #{keg}... " + puts if verbose + puts "#{keg.unlink(**options)} symlinks removed" + end + end + end +end diff --git a/docs/Manpage.md b/docs/Manpage.md index d3cbe3eeb5..f6f194eb7d 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -537,10 +537,6 @@ Print export statements. When run in a shell, this installation of Homebrew will The variables `HOMEBREW_PREFIX`, `HOMEBREW_CELLAR` and `HOMEBREW_REPOSITORY` are also exported to avoid querying them multiple times. Consider adding evaluation of this command's output to your dotfiles (e.g. `~/.profile`, `~/.bash_profile`, or `~/.zprofile`) with: `eval $(brew shellenv)` -### `switch` *`formula`* *`version`* - -Symlink all of the specified *`version`* of *`formula`*'s installation into Homebrew's prefix. - ### `tap` [*`options`*] [*`user`*`/`*`repo`*] [*`URL`*] Tap a formula repository. diff --git a/manpages/brew.1 b/manpages/brew.1 index 394ee5589f..dd87f709ac 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -773,9 +773,6 @@ Print export statements\. When run in a shell, this installation of Homebrew wil .P The variables \fBHOMEBREW_PREFIX\fR, \fBHOMEBREW_CELLAR\fR and \fBHOMEBREW_REPOSITORY\fR are also exported to avoid querying them multiple times\. Consider adding evaluation of this command\'s output to your dotfiles (e\.g\. \fB~/\.profile\fR, \fB~/\.bash_profile\fR, or \fB~/\.zprofile\fR) with: \fBeval $(brew shellenv)\fR . -.SS "\fBswitch\fR \fIformula\fR \fIversion\fR" -Symlink all of the specified \fIversion\fR of \fIformula\fR\'s installation into Homebrew\'s prefix\. -. .SS "\fBtap\fR [\fIoptions\fR] [\fIuser\fR\fB/\fR\fIrepo\fR] [\fIURL\fR]" Tap a formula repository\. .