From 2760d981d3d7b74bb1ff194ed843f6d150904dd0 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Sat, 12 Jun 2021 18:02:23 -0400 Subject: [PATCH 1/5] Allow for homebrew/core to be untapped --- Library/Homebrew/cmd/untap.rb | 2 +- Library/Homebrew/cmd/update-report.rb | 1 + Library/Homebrew/dependency.rb | 11 +++++++++++ Library/Homebrew/exceptions.rb | 7 +++++++ Library/Homebrew/formulary.rb | 4 ++++ Library/Homebrew/tap.rb | 9 ++++++--- 6 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Library/Homebrew/cmd/untap.rb b/Library/Homebrew/cmd/untap.rb index 888d768e47..b8924c1eb6 100644 --- a/Library/Homebrew/cmd/untap.rb +++ b/Library/Homebrew/cmd/untap.rb @@ -25,7 +25,7 @@ module Homebrew args = untap_args.parse args.named.to_installed_taps.each do |tap| - odie "Untapping #{tap} is not allowed" if tap.core_tap? + odie "Untapping #{tap} is not allowed" if tap.core_tap? && !ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] installed_tap_formulae = Formula.installed.select { |formula| formula.tap == tap } installed_tap_casks = Cask::Caskroom.casks.select { |cask| cask.tap == tap } diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index cc83b687b6..88321d8f29 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -207,6 +207,7 @@ module Homebrew def install_core_tap_if_necessary return if ENV["HOMEBREW_UPDATE_TEST"] + return if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] core_tap = CoreTap.instance return if core_tap.installed? diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 7ac088dc16..2a37fe6671 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -46,6 +46,15 @@ class Dependency formula end + def unavailable_core_formula? + to_formula + false + rescue CoreTapFormulaUnavailableError + true + rescue + false + end + def installed? to_formula.latest_version_installed? end @@ -130,6 +139,8 @@ class Dependency def action(dependent, dep, &block) catch(:action) do + prune if dep.unavailable_core_formula? + if block yield dependent, dep elsif dep.optional? || dep.recommended? diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 06e58d3962..09765e0068 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -221,6 +221,13 @@ class TapFormulaUnavailableError < FormulaUnavailableError end end +# Raised when a formula in a the core tap is unavailable. +class CoreTapFormulaUnavailableError < TapFormulaUnavailableError + def initialize(name) + super CoreTap.instance, name + end +end + # Raised when a formula in a specific tap does not contain a formula class. class TapFormulaClassUnavailableError < TapFormulaUnavailableError include FormulaClassUnavailableErrorModule diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 867d7237ee..7934ef2e59 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -361,6 +361,10 @@ module Formulary end def get_formula(*) + if !CoreTap.instance.installed? && ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] + raise CoreTapFormulaUnavailableError, name + end + raise FormulaUnavailableError, name end end diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index ae604f1a72..aef4973d63 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -734,6 +734,7 @@ class CoreTap < Tap def self.ensure_installed! return if instance.installed? + return if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] safe_system HOMEBREW_BREW_FILE, "tap", instance.name end @@ -748,9 +749,11 @@ class CoreTap < Tap end # @private - sig { void } - def uninstall - raise "Tap#uninstall is not available for CoreTap" + sig { params(manual: T::Boolean).void } + def uninstall(manual: false) + raise "Tap#uninstall is not available for CoreTap" unless ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] + + super end # @private From b096bf1fed0a50fe02f621f433a544dd840c9fcc Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Fri, 18 Jun 2021 12:03:22 -0400 Subject: [PATCH 2/5] `dependency::expand`: only prune missing deps with flag --- Library/Homebrew/cask_dependent.rb | 8 ++++---- Library/Homebrew/dependency.rb | 12 ++++++------ Library/Homebrew/installed_dependents.rb | 3 ++- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Library/Homebrew/cask_dependent.rb b/Library/Homebrew/cask_dependent.rb index 74b7419714..bf9a57c23f 100644 --- a/Library/Homebrew/cask_dependent.rb +++ b/Library/Homebrew/cask_dependent.rb @@ -15,8 +15,8 @@ class CaskDependent @cask.full_name end - def runtime_dependencies - recursive_dependencies + def runtime_dependencies(ignore_missing: false) + recursive_dependencies ignore_missing: ignore_missing end def deps @@ -43,8 +43,8 @@ class CaskDependent end end - def recursive_dependencies(&block) - Dependency.expand(self, &block) + def recursive_dependencies(ignore_missing: false, &block) + Dependency.expand(self, ignore_missing: ignore_missing, &block) end def recursive_requirements(&block) diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 2a37fe6671..aa5375112a 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -98,7 +98,7 @@ class Dependency # the list. # The default filter, which is applied when a block is not given, omits # optionals and recommendeds based on what the dependent has asked for - def expand(dependent, deps = dependent.deps, cache_key: nil, &block) + def expand(dependent, deps = dependent.deps, cache_key: nil, ignore_missing: false, &block) # Keep track dependencies to avoid infinite cyclic dependency recursion. @expand_stack ||= [] @expand_stack.push dependent.name @@ -113,19 +113,19 @@ class Dependency deps.each do |dep| next if dependent.name == dep.name - case action(dependent, dep, &block) + case action(dependent, dep, ignore_missing: ignore_missing, &block) when :prune next when :skip next if @expand_stack.include? dep.name - expanded_deps.concat(expand(dep.to_formula, cache_key: cache_key, &block)) + expanded_deps.concat(expand(dep.to_formula, cache_key: cache_key, ignore_missing: ignore_missing, &block)) when :keep_but_prune_recursive_deps expanded_deps << dep else next if @expand_stack.include? dep.name - expanded_deps.concat(expand(dep.to_formula, cache_key: cache_key, &block)) + expanded_deps.concat(expand(dep.to_formula, cache_key: cache_key, ignore_missing: ignore_missing, &block)) expanded_deps << dep end end @@ -137,9 +137,9 @@ class Dependency @expand_stack.pop end - def action(dependent, dep, &block) + def action(dependent, dep, ignore_missing: false, &block) catch(:action) do - prune if dep.unavailable_core_formula? + prune if ignore_missing && dep.unavailable_core_formula? if block yield dependent, dep diff --git a/Library/Homebrew/installed_dependents.rb b/Library/Homebrew/installed_dependents.rb index 20a7440e7d..7d231943e7 100644 --- a/Library/Homebrew/installed_dependents.rb +++ b/Library/Homebrew/installed_dependents.rb @@ -50,7 +50,8 @@ module InstalledDependents when Formula dependent.missing_dependencies(hide: keg_names) when Cask::Cask - CaskDependent.new(dependent).runtime_dependencies.map(&:to_formula) + # When checking for cask dependents, we don't care about missing dependencies + CaskDependent.new(dependent).runtime_dependencies(ignore_missing: true).map(&:to_formula) end required_kegs = required.map do |f| From 1d516b628ba61ebc1d10358b5a483864f4c073a6 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Fri, 18 Jun 2021 12:07:34 -0400 Subject: [PATCH 3/5] Use `#present?` and `#blank?` to check env variable --- Library/Homebrew/cmd/untap.rb | 2 +- Library/Homebrew/cmd/update-report.rb | 2 +- Library/Homebrew/formulary.rb | 2 +- Library/Homebrew/tap.rb | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Library/Homebrew/cmd/untap.rb b/Library/Homebrew/cmd/untap.rb index b8924c1eb6..3d7b5bd6e9 100644 --- a/Library/Homebrew/cmd/untap.rb +++ b/Library/Homebrew/cmd/untap.rb @@ -25,7 +25,7 @@ module Homebrew args = untap_args.parse args.named.to_installed_taps.each do |tap| - odie "Untapping #{tap} is not allowed" if tap.core_tap? && !ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] + odie "Untapping #{tap} is not allowed" if tap.core_tap? && ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].blank? installed_tap_formulae = Formula.installed.select { |formula| formula.tap == tap } installed_tap_casks = Cask::Caskroom.casks.select { |cask| cask.tap == tap } diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index 88321d8f29..ebc2a3237f 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -207,7 +207,7 @@ module Homebrew def install_core_tap_if_necessary return if ENV["HOMEBREW_UPDATE_TEST"] - return if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] + return if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].present? core_tap = CoreTap.instance return if core_tap.installed? diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 7934ef2e59..f1508af9c4 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -361,7 +361,7 @@ module Formulary end def get_formula(*) - if !CoreTap.instance.installed? && ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] + if !CoreTap.instance.installed? && ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].present? raise CoreTapFormulaUnavailableError, name end diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index aef4973d63..4fdca5d2dd 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -734,7 +734,7 @@ class CoreTap < Tap def self.ensure_installed! return if instance.installed? - return if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] + return if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].present? safe_system HOMEBREW_BREW_FILE, "tap", instance.name end @@ -751,7 +751,7 @@ class CoreTap < Tap # @private sig { params(manual: T::Boolean).void } def uninstall(manual: false) - raise "Tap#uninstall is not available for CoreTap" unless ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"] + raise "Tap#uninstall is not available for CoreTap" if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].blank? super end From 60203afdd501308360f71066140ebb5a6cbf6f4b Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Fri, 18 Jun 2021 12:10:26 -0400 Subject: [PATCH 4/5] Merge env variables into `HOMEBREW_JSON_CORE` --- Library/Homebrew/cmd/untap.rb | 2 +- Library/Homebrew/cmd/update-report.rb | 2 +- Library/Homebrew/formulary.rb | 8 ++++---- Library/Homebrew/tap.rb | 4 ++-- Library/Homebrew/test/formulary_spec.rb | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Library/Homebrew/cmd/untap.rb b/Library/Homebrew/cmd/untap.rb index 3d7b5bd6e9..02ba88f316 100644 --- a/Library/Homebrew/cmd/untap.rb +++ b/Library/Homebrew/cmd/untap.rb @@ -25,7 +25,7 @@ module Homebrew args = untap_args.parse args.named.to_installed_taps.each do |tap| - odie "Untapping #{tap} is not allowed" if tap.core_tap? && ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].blank? + odie "Untapping #{tap} is not allowed" if tap.core_tap? && ENV["HOMEBREW_JSON_CORE"].blank? installed_tap_formulae = Formula.installed.select { |formula| formula.tap == tap } installed_tap_casks = Cask::Caskroom.casks.select { |cask| cask.tap == tap } diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index ebc2a3237f..cdc44a7e72 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -207,7 +207,7 @@ module Homebrew def install_core_tap_if_necessary return if ENV["HOMEBREW_UPDATE_TEST"] - return if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].present? + return if ENV["HOMEBREW_JSON_CORE"].present? core_tap = CoreTap.instance return if core_tap.installed? diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index f1508af9c4..0aee3df7a1 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -361,7 +361,7 @@ module Formulary end def get_formula(*) - if !CoreTap.instance.installed? && ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].present? + if !CoreTap.instance.installed? && ENV["HOMEBREW_JSON_CORE"].present? raise CoreTapFormulaUnavailableError, name end @@ -399,7 +399,7 @@ module Formulary ) raise ArgumentError, "Formulae must have a ref!" unless ref - if ENV["HOMEBREW_BOTTLE_JSON"].present? && + if ENV["HOMEBREW_JSON_CORE"].present? && @formula_name_local_bottle_path_map.present? && @formula_name_local_bottle_path_map.key?(ref) ref = @formula_name_local_bottle_path_map[ref] @@ -431,8 +431,8 @@ module Formulary # @param formula_name the formula name string to map. # @param local_bottle_path a path pointing to the target bottle archive. def self.map_formula_name_to_local_bottle_path(formula_name, local_bottle_path) - if ENV["HOMEBREW_BOTTLE_JSON"].blank? - raise UsageError, "HOMEBREW_BOTTLE_JSON not set but required for #{__method__}!" + if ENV["HOMEBREW_JSON_CORE"].blank? + raise UsageError, "HOMEBREW_JSON_CORE not set but required for #{__method__}!" end @formula_name_local_bottle_path_map ||= {} diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index 4fdca5d2dd..99d0081059 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -734,7 +734,7 @@ class CoreTap < Tap def self.ensure_installed! return if instance.installed? - return if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].present? + return if ENV["HOMEBREW_JSON_CORE"].present? safe_system HOMEBREW_BREW_FILE, "tap", instance.name end @@ -751,7 +751,7 @@ class CoreTap < Tap # @private sig { params(manual: T::Boolean).void } def uninstall(manual: false) - raise "Tap#uninstall is not available for CoreTap" if ENV["HOMEBREW_UNTAP_HOMEBREW_CORE"].blank? + raise "Tap#uninstall is not available for CoreTap" if ENV["HOMEBREW_JSON_CORE"].blank? super end diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index c98916820a..7370a04d13 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -216,12 +216,12 @@ describe Formulary do described_class.factory("formula-to-map") }.to raise_error(FormulaUnavailableError) - ENV["HOMEBREW_BOTTLE_JSON"] = nil + ENV["HOMEBREW_JSON_CORE"] = nil expect { described_class.map_formula_name_to_local_bottle_path "formula-to-map", formula_path - }.to raise_error(UsageError, /HOMEBREW_BOTTLE_JSON not set/) + }.to raise_error(UsageError, /HOMEBREW_JSON_CORE not set/) - ENV["HOMEBREW_BOTTLE_JSON"] = "1" + ENV["HOMEBREW_JSON_CORE"] = "1" described_class.map_formula_name_to_local_bottle_path "formula-to-map", formula_path expect(described_class.factory("formula-to-map")).to be_kind_of(Formula) From 044da5d5ac2c49ab05cc38572ba8d68d285818b7 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Fri, 18 Jun 2021 15:30:14 -0400 Subject: [PATCH 5/5] Fix style --- Library/Homebrew/formulary.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 0aee3df7a1..45b6136723 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -361,9 +361,7 @@ module Formulary end def get_formula(*) - if !CoreTap.instance.installed? && ENV["HOMEBREW_JSON_CORE"].present? - raise CoreTapFormulaUnavailableError, name - end + raise CoreTapFormulaUnavailableError, name if !CoreTap.instance.installed? && ENV["HOMEBREW_JSON_CORE"].present? raise FormulaUnavailableError, name end @@ -431,9 +429,7 @@ module Formulary # @param formula_name the formula name string to map. # @param local_bottle_path a path pointing to the target bottle archive. def self.map_formula_name_to_local_bottle_path(formula_name, local_bottle_path) - if ENV["HOMEBREW_JSON_CORE"].blank? - raise UsageError, "HOMEBREW_JSON_CORE not set but required for #{__method__}!" - end + raise UsageError, "HOMEBREW_JSON_CORE not set but required for #{__method__}!" if ENV["HOMEBREW_JSON_CORE"].blank? @formula_name_local_bottle_path_map ||= {} @formula_name_local_bottle_path_map[formula_name] = Pathname(local_bottle_path).realpath