Merge pull request #13577 from iMichka/glibc-install
install glibc/gcc automatically if too old.
This commit is contained in:
commit
61db6207d8
@ -28,6 +28,8 @@ class DependencyCollector
|
|||||||
def initialize
|
def initialize
|
||||||
@deps = Dependencies.new
|
@deps = Dependencies.new
|
||||||
@requirements = Requirements.new
|
@requirements = Requirements.new
|
||||||
|
|
||||||
|
init_global_dep_tree_if_needed!
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_copy(other)
|
def initialize_copy(other)
|
||||||
@ -68,6 +70,12 @@ class DependencyCollector
|
|||||||
parse_spec(spec, Array(tags))
|
parse_spec(spec, Array(tags))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(related_formula_names: T::Array[String]).returns(T.nilable(Dependency)) }
|
||||||
|
def gcc_dep_if_needed(related_formula_names); end
|
||||||
|
|
||||||
|
sig { params(related_formula_names: T::Array[String]).returns(T.nilable(Dependency)) }
|
||||||
|
def glibc_dep_if_needed(related_formula_names); end
|
||||||
|
|
||||||
def git_dep_if_needed(tags)
|
def git_dep_if_needed(tags)
|
||||||
return if Utils::Git.available?
|
return if Utils::Git.available?
|
||||||
|
|
||||||
@ -110,6 +118,9 @@ class DependencyCollector
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
sig { void }
|
||||||
|
def init_global_dep_tree_if_needed!; end
|
||||||
|
|
||||||
def parse_spec(spec, tags)
|
def parse_spec(spec, tags)
|
||||||
case spec
|
case spec
|
||||||
when String
|
when String
|
||||||
|
@ -98,6 +98,16 @@ class DevelopmentTools
|
|||||||
@gcc_version = {}
|
@gcc_version = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def build_system_too_old?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def system_gcc_too_old?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def ca_file_handles_most_https_certificates?
|
def ca_file_handles_most_https_certificates?
|
||||||
# The system CA file is too old for some modern HTTPS certificates on
|
# The system CA file is too old for some modern HTTPS certificates on
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
# typed: strict
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "extend/os/mac/dependency_collector" if OS.mac?
|
if OS.mac?
|
||||||
|
require "extend/os/mac/dependency_collector"
|
||||||
|
elsif OS.linux?
|
||||||
|
require "extend/os/linux/dependency_collector"
|
||||||
|
end
|
||||||
|
76
Library/Homebrew/extend/os/linux/dependency_collector.rb
Normal file
76
Library/Homebrew/extend/os/linux/dependency_collector.rb
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# typed: true
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "os/linux/glibc"
|
||||||
|
|
||||||
|
class DependencyCollector
|
||||||
|
extend T::Sig
|
||||||
|
|
||||||
|
undef gcc_dep_if_needed
|
||||||
|
undef glibc_dep_if_needed
|
||||||
|
undef init_global_dep_tree_if_needed!
|
||||||
|
|
||||||
|
sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
|
||||||
|
def gcc_dep_if_needed(related_formula_names)
|
||||||
|
return unless DevelopmentTools.system_gcc_too_old?
|
||||||
|
return if related_formula_names.include?(GCC)
|
||||||
|
return if global_dep_tree[GCC]&.intersect?(related_formula_names)
|
||||||
|
return if global_dep_tree[GLIBC]&.intersect?(related_formula_names) # gcc depends on glibc
|
||||||
|
|
||||||
|
Dependency.new(GCC)
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
|
||||||
|
def glibc_dep_if_needed(related_formula_names)
|
||||||
|
return unless OS::Linux::Glibc.below_ci_version?
|
||||||
|
return if global_dep_tree[GLIBC]&.intersect?(related_formula_names)
|
||||||
|
|
||||||
|
Dependency.new(GLIBC)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
GLIBC = "glibc"
|
||||||
|
GCC = CompilerSelector.preferred_gcc.freeze
|
||||||
|
|
||||||
|
# Use class variables to avoid this expensive logic needing to be done more
|
||||||
|
# than once.
|
||||||
|
# rubocop:disable Style/ClassVars
|
||||||
|
@@global_dep_tree = {}
|
||||||
|
|
||||||
|
sig { void }
|
||||||
|
def init_global_dep_tree_if_needed!
|
||||||
|
return unless DevelopmentTools.build_system_too_old?
|
||||||
|
return if @@global_dep_tree.present?
|
||||||
|
|
||||||
|
# Defined in precedence order (gcc depends on glibc).
|
||||||
|
global_deps = [GLIBC, GCC].freeze
|
||||||
|
|
||||||
|
@@global_dep_tree = global_deps.to_h { |name| [name, Set.new([name])] }
|
||||||
|
|
||||||
|
global_deps.each do |global_dep_name|
|
||||||
|
# This is an arbitrary number picked based on testing the current tree
|
||||||
|
# depth and just to ensure that this doesn't loop indefinitely if we
|
||||||
|
# introduce a circular dependency by mistake.
|
||||||
|
maximum_tree_depth = 10
|
||||||
|
current_tree_depth = 0
|
||||||
|
|
||||||
|
deps = Formula[global_dep_name].deps
|
||||||
|
while deps.present?
|
||||||
|
current_tree_depth += 1
|
||||||
|
if current_tree_depth > maximum_tree_depth
|
||||||
|
raise "maximum tree depth (#{maximum_tree_depth}) exceeded calculating #{global_dep_name} dependency tree!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@@global_dep_tree[global_dep_name].merge(deps.map(&:name))
|
||||||
|
deps = deps.flat_map { |dep| dep.to_formula.deps }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Hash[String, T::Set[String]]) }
|
||||||
|
def global_dep_tree
|
||||||
|
@@global_dep_tree
|
||||||
|
end
|
||||||
|
# rubocop:enable Style/ClassVars
|
||||||
|
end
|
@ -21,6 +21,18 @@ class DevelopmentTools
|
|||||||
:gcc
|
:gcc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def build_system_too_old?
|
||||||
|
return @build_system_too_old if defined? @build_system_too_old
|
||||||
|
|
||||||
|
@build_system_too_old = (system_gcc_too_old? || OS::Linux::Glibc.below_ci_version?)
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def system_gcc_too_old?
|
||||||
|
gcc_version("gcc") < OS::LINUX_GCC_CI_VERSION
|
||||||
|
end
|
||||||
|
|
||||||
sig { returns(T::Hash[String, T.nilable(String)]) }
|
sig { returns(T::Hash[String, T.nilable(String)]) }
|
||||||
def build_system_info
|
def build_system_info
|
||||||
generic_build_system_info.merge({
|
generic_build_system_info.merge({
|
||||||
|
@ -5,6 +5,7 @@ class Formula
|
|||||||
undef shared_library
|
undef shared_library
|
||||||
undef loader_path
|
undef loader_path
|
||||||
undef deuniversalize_machos
|
undef deuniversalize_machos
|
||||||
|
undef add_global_deps_to_spec
|
||||||
|
|
||||||
sig { params(name: String, version: T.nilable(T.any(String, Integer))).returns(String) }
|
sig { params(name: String, version: T.nilable(T.any(String, Integer))).returns(String) }
|
||||||
def shared_library(name, version = nil)
|
def shared_library(name, version = nil)
|
||||||
@ -23,4 +24,20 @@ class Formula
|
|||||||
|
|
||||||
sig { params(targets: T.nilable(T.any(Pathname, String))).void }
|
sig { params(targets: T.nilable(T.any(Pathname, String))).void }
|
||||||
def deuniversalize_machos(*targets); end
|
def deuniversalize_machos(*targets); end
|
||||||
|
|
||||||
|
sig { params(spec: SoftwareSpec).void }
|
||||||
|
def add_global_deps_to_spec(spec)
|
||||||
|
@global_deps ||= begin
|
||||||
|
dependency_collector = spec.dependency_collector
|
||||||
|
related_formula_names = Set.new([
|
||||||
|
name,
|
||||||
|
*versioned_formulae_names,
|
||||||
|
])
|
||||||
|
[
|
||||||
|
dependency_collector.gcc_dep_if_needed(related_formula_names),
|
||||||
|
dependency_collector.glibc_dep_if_needed(related_formula_names),
|
||||||
|
].compact.freeze
|
||||||
|
end
|
||||||
|
@global_deps.each { |dep| spec.dependency_collector.add(dep) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -80,9 +80,5 @@ class LinkageChecker
|
|||||||
@unwanted_system_dylibs = @system_dylibs.reject do |s|
|
@unwanted_system_dylibs = @system_dylibs.reject do |s|
|
||||||
SYSTEM_LIBRARY_ALLOWLIST.include? File.basename(s)
|
SYSTEM_LIBRARY_ALLOWLIST.include? File.basename(s)
|
||||||
end
|
end
|
||||||
# FIXME: Remove this when these dependencies are injected correctly (e.g. through `DependencyCollector`)
|
|
||||||
# See discussion at
|
|
||||||
# https://github.com/Homebrew/brew/pull/13577
|
|
||||||
@undeclared_deps -= [CompilerSelector.preferred_gcc, "glibc", "gcc"]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -262,9 +262,13 @@ class Formula
|
|||||||
return unless spec.url
|
return unless spec.url
|
||||||
|
|
||||||
spec.owner = self
|
spec.owner = self
|
||||||
|
add_global_deps_to_spec(spec)
|
||||||
instance_variable_set("@#{name}", spec)
|
instance_variable_set("@#{name}", spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(spec: SoftwareSpec).void }
|
||||||
|
def add_global_deps_to_spec(spec); end
|
||||||
|
|
||||||
def determine_active_spec(requested)
|
def determine_active_spec(requested)
|
||||||
spec = send(requested) || stable || head
|
spec = send(requested) || stable || head
|
||||||
spec || raise(FormulaSpecificationError, "formulae require at least a URL")
|
spec || raise(FormulaSpecificationError, "formulae require at least a URL")
|
||||||
@ -443,7 +447,7 @@ class Formula
|
|||||||
# Returns any `@`-versioned formulae names for any formula (including versioned formulae).
|
# Returns any `@`-versioned formulae names for any formula (including versioned formulae).
|
||||||
sig { returns(T::Array[String]) }
|
sig { returns(T::Array[String]) }
|
||||||
def versioned_formulae_names
|
def versioned_formulae_names
|
||||||
@versioned_formulae_names ||= Pathname.glob(path.to_s.gsub(/(@[\d.]+)?\.rb$/, "@*.rb")).map do |versioned_path|
|
Pathname.glob(path.to_s.gsub(/(@[\d.]+)?\.rb$/, "@*.rb")).map do |versioned_path|
|
||||||
next if versioned_path == path
|
next if versioned_path == path
|
||||||
|
|
||||||
versioned_path.basename(".rb").to_s
|
versioned_path.basename(".rb").to_s
|
||||||
@ -453,7 +457,7 @@ class Formula
|
|||||||
# Returns any `@`-versioned Formula objects for any Formula (including versioned formulae).
|
# Returns any `@`-versioned Formula objects for any Formula (including versioned formulae).
|
||||||
sig { returns(T::Array[Formula]) }
|
sig { returns(T::Array[Formula]) }
|
||||||
def versioned_formulae
|
def versioned_formulae
|
||||||
@versioned_formulae ||= versioned_formulae_names.map do |name|
|
versioned_formulae_names.map do |name|
|
||||||
Formula[name]
|
Formula[name]
|
||||||
rescue FormulaUnavailableError
|
rescue FormulaUnavailableError
|
||||||
nil
|
nil
|
||||||
|
@ -581,11 +581,9 @@ class FormulaInstaller
|
|||||||
end
|
end
|
||||||
|
|
||||||
def expand_dependencies_for_formula(formula, inherited_options)
|
def expand_dependencies_for_formula(formula, inherited_options)
|
||||||
any_bottle_used = false
|
|
||||||
|
|
||||||
# Cache for this expansion only. FormulaInstaller has a lot of inputs which can alter expansion.
|
# Cache for this expansion only. FormulaInstaller has a lot of inputs which can alter expansion.
|
||||||
cache_key = "FormulaInstaller-#{formula.full_name}-#{Time.now.to_f}"
|
cache_key = "FormulaInstaller-#{formula.full_name}-#{Time.now.to_f}"
|
||||||
expanded_deps = Dependency.expand(formula, cache_key: cache_key) do |dependent, dep|
|
Dependency.expand(formula, cache_key: cache_key) do |dependent, dep|
|
||||||
inherited_options[dep.name] |= inherited_options_for(dep)
|
inherited_options[dep.name] |= inherited_options_for(dep)
|
||||||
build = effective_build_options_for(
|
build = effective_build_options_for(
|
||||||
dependent,
|
dependent,
|
||||||
@ -601,36 +599,14 @@ class FormulaInstaller
|
|||||||
Dependency.prune
|
Dependency.prune
|
||||||
elsif dep.satisfied?(inherited_options[dep.name])
|
elsif dep.satisfied?(inherited_options[dep.name])
|
||||||
Dependency.skip
|
Dependency.skip
|
||||||
else
|
|
||||||
any_bottle_used ||= install_bottle_for?(dep.to_formula, build)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
[expanded_deps, any_bottle_used]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def expand_dependencies
|
def expand_dependencies
|
||||||
inherited_options = Hash.new { |hash, key| hash[key] = Options.new }
|
inherited_options = Hash.new { |hash, key| hash[key] = Options.new }
|
||||||
any_bottle_used = pour_bottle?
|
|
||||||
|
|
||||||
expanded_deps, any_dep_bottle_used = expand_dependencies_for_formula(formula, inherited_options)
|
expanded_deps = expand_dependencies_for_formula(formula, inherited_options)
|
||||||
any_bottle_used ||= any_dep_bottle_used
|
|
||||||
|
|
||||||
# We require some dependencies (glibc, GCC 5, etc.) if binaries were built.
|
|
||||||
# Native binaries shouldn't exist in cross-platform `all` bottles.
|
|
||||||
if any_bottle_used && !formula.bottled?(:all) && !Keg.bottle_dependencies.empty?
|
|
||||||
all_bottle_deps = Keg.bottle_dependencies.flat_map do |bottle_dep|
|
|
||||||
bottle_dep.recursive_dependencies.map(&:name) + [bottle_dep.name]
|
|
||||||
end
|
|
||||||
|
|
||||||
if all_bottle_deps.exclude?(formula.name)
|
|
||||||
bottle_deps = Keg.bottle_dependencies.flat_map do |bottle_dep|
|
|
||||||
expanded_bottle_deps, = expand_dependencies_for_formula(bottle_dep, inherited_options)
|
|
||||||
expanded_bottle_deps
|
|
||||||
end
|
|
||||||
expanded_deps = Dependency.merge_repeats(bottle_deps + expanded_deps)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
expanded_deps.map { |dep| [dep, inherited_options[dep.name]] }
|
expanded_deps.map { |dep| [dep, inherited_options[dep.name]] }
|
||||||
end
|
end
|
||||||
|
@ -366,17 +366,6 @@ class Keg
|
|||||||
def self.file_linked_libraries(_file, _string)
|
def self.file_linked_libraries(_file, _string)
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.bottle_dependencies
|
|
||||||
return [] unless Homebrew::SimulateSystem.simulating_or_running_on_linux?
|
|
||||||
|
|
||||||
@bottle_dependencies ||= begin
|
|
||||||
formulae = []
|
|
||||||
gcc = Formulary.factory(CompilerSelector.preferred_gcc)
|
|
||||||
formulae << gcc if DevelopmentTools.gcc_version("gcc") < gcc.version.to_i
|
|
||||||
formulae
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
require "extend/os/keg_relocate"
|
require "extend/os/keg_relocate"
|
||||||
|
@ -44,6 +44,11 @@ module OS
|
|||||||
def below_minimum_version?
|
def below_minimum_version?
|
||||||
system_version < minimum_version
|
system_version < minimum_version
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def below_ci_version?
|
||||||
|
system_version < LINUX_GLIBC_CI_VERSION
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -50,6 +50,11 @@ class SoftwareSpec
|
|||||||
@uses_from_macos_elements = []
|
@uses_from_macos_elements = []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def initialize_copy(other)
|
||||||
|
super
|
||||||
|
@dependency_collector = @dependency_collector.dup
|
||||||
|
end
|
||||||
|
|
||||||
def owner=(owner)
|
def owner=(owner)
|
||||||
@name = owner.name
|
@name = owner.name
|
||||||
@full_name = owner.full_name
|
@full_name = owner.full_name
|
||||||
|
@ -6,7 +6,20 @@ require "installed_dependents"
|
|||||||
describe InstalledDependents do
|
describe InstalledDependents do
|
||||||
include FileUtils
|
include FileUtils
|
||||||
|
|
||||||
def setup_test_keg(name, version)
|
def stub_formula(name, version = "1.0", &block)
|
||||||
|
f = formula(name) do
|
||||||
|
url "#{name}-#{version}"
|
||||||
|
|
||||||
|
instance_eval(&block) if block
|
||||||
|
end
|
||||||
|
stub_formula_loader f
|
||||||
|
stub_formula_loader f, "homebrew/core/#{f}"
|
||||||
|
f
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_test_keg(name, version, &block)
|
||||||
|
stub_formula(name, version, &block)
|
||||||
|
|
||||||
path = HOMEBREW_CELLAR/name/version
|
path = HOMEBREW_CELLAR/name/version
|
||||||
(path/"bin").mkpath
|
(path/"bin").mkpath
|
||||||
|
|
||||||
@ -18,27 +31,25 @@ describe InstalledDependents do
|
|||||||
end
|
end
|
||||||
|
|
||||||
let!(:keg) { setup_test_keg("foo", "1.0") }
|
let!(:keg) { setup_test_keg("foo", "1.0") }
|
||||||
|
let!(:keg_only_keg) do
|
||||||
|
setup_test_keg("foo-keg-only", "1.0") do
|
||||||
|
keg_only "a good reason"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "::find_some_installed_dependents" do
|
describe "::find_some_installed_dependents" do
|
||||||
def stub_formula_name(name)
|
def setup_test_keg(name, version, &block)
|
||||||
f = formula(name) { url "foo-1.0" }
|
|
||||||
stub_formula_loader f
|
|
||||||
stub_formula_loader f, "homebrew/core/#{f}"
|
|
||||||
f
|
|
||||||
end
|
|
||||||
|
|
||||||
def setup_test_keg(name, version)
|
|
||||||
f = stub_formula_name(name)
|
|
||||||
keg = super
|
keg = super
|
||||||
Tab.create(f, DevelopmentTools.default_compiler, :libcxx).write
|
Tab.create(keg.to_formula, DevelopmentTools.default_compiler, :libcxx).write
|
||||||
keg
|
keg
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
keg.link
|
keg.link
|
||||||
|
keg_only_keg.optlink
|
||||||
end
|
end
|
||||||
|
|
||||||
def alter_tab(keg = dependent)
|
def alter_tab(keg)
|
||||||
tab = Tab.for_keg(keg)
|
tab = Tab.for_keg(keg)
|
||||||
yield tab
|
yield tab
|
||||||
tab.write
|
tab.write
|
||||||
@ -46,24 +57,26 @@ describe InstalledDependents do
|
|||||||
|
|
||||||
# 1.1.6 is the earliest version of Homebrew that generates correct runtime
|
# 1.1.6 is the earliest version of Homebrew that generates correct runtime
|
||||||
# dependency lists in {Tab}s.
|
# dependency lists in {Tab}s.
|
||||||
def dependencies(deps, homebrew_version: "1.1.6")
|
def tab_dependencies(keg, deps, homebrew_version: "1.1.6")
|
||||||
alter_tab do |tab|
|
alter_tab(keg) do |tab|
|
||||||
tab.homebrew_version = homebrew_version
|
tab.homebrew_version = homebrew_version
|
||||||
tab.tabfile = dependent/Tab::FILENAME
|
tab.tabfile = keg/Tab::FILENAME
|
||||||
tab.runtime_dependencies = deps
|
tab.runtime_dependencies = deps
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def unreliable_dependencies(deps)
|
def unreliable_tab_dependencies(keg, deps)
|
||||||
# 1.1.5 is (hopefully!) the last version of Homebrew that generates
|
# 1.1.5 is (hopefully!) the last version of Homebrew that generates
|
||||||
# incorrect runtime dependency lists in {Tab}s.
|
# incorrect runtime dependency lists in {Tab}s.
|
||||||
dependencies(deps, homebrew_version: "1.1.5")
|
tab_dependencies(keg, deps, homebrew_version: "1.1.5")
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:dependent) { setup_test_keg("bar", "1.0") }
|
|
||||||
|
|
||||||
specify "a dependency with no Tap in Tab" do
|
specify "a dependency with no Tap in Tab" do
|
||||||
tap_dep = setup_test_keg("baz", "1.0")
|
tap_dep = setup_test_keg("baz", "1.0")
|
||||||
|
dependent = setup_test_keg("bar", "1.0") do
|
||||||
|
depends_on "foo"
|
||||||
|
depends_on "baz"
|
||||||
|
end
|
||||||
|
|
||||||
# allow tap_dep to be linked too
|
# allow tap_dep to be linked too
|
||||||
FileUtils.rm_r tap_dep/"bin"
|
FileUtils.rm_r tap_dep/"bin"
|
||||||
@ -71,83 +84,93 @@ describe InstalledDependents do
|
|||||||
|
|
||||||
alter_tab(keg) { |t| t.source["tap"] = nil }
|
alter_tab(keg) { |t| t.source["tap"] = nil }
|
||||||
|
|
||||||
dependencies nil
|
tab_dependencies dependent, nil
|
||||||
Formula["bar"].class.depends_on "foo"
|
|
||||||
Formula["bar"].class.depends_on "baz"
|
|
||||||
|
|
||||||
result = described_class.find_some_installed_dependents([keg, tap_dep])
|
result = described_class.find_some_installed_dependents([keg, tap_dep])
|
||||||
expect(result).to eq([[keg, tap_dep], ["bar"]])
|
expect(result).to eq([[keg, tap_dep], ["bar"]])
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "no dependencies anywhere" do
|
specify "no dependencies anywhere" do
|
||||||
dependencies nil
|
dependent = setup_test_keg("bar", "1.0")
|
||||||
|
tab_dependencies dependent, nil
|
||||||
expect(described_class.find_some_installed_dependents([keg])).to be_nil
|
expect(described_class.find_some_installed_dependents([keg])).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "missing Formula dependency" do
|
specify "missing Formula dependency" do
|
||||||
dependencies nil
|
dependent = setup_test_keg("bar", "1.0") do
|
||||||
Formula["bar"].class.depends_on "foo"
|
depends_on "foo"
|
||||||
|
end
|
||||||
|
tab_dependencies dependent, nil
|
||||||
expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
|
expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "uninstalling dependent and dependency" do
|
specify "uninstalling dependent and dependency" do
|
||||||
dependencies nil
|
dependent = setup_test_keg("bar", "1.0") do
|
||||||
Formula["bar"].class.depends_on "foo"
|
depends_on "foo"
|
||||||
|
end
|
||||||
|
tab_dependencies dependent, nil
|
||||||
expect(described_class.find_some_installed_dependents([keg, dependent])).to be_nil
|
expect(described_class.find_some_installed_dependents([keg, dependent])).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "renamed dependency" do
|
specify "renamed dependency" do
|
||||||
dependencies nil
|
dependent = setup_test_keg("bar", "1.0") do
|
||||||
|
depends_on "foo"
|
||||||
|
end
|
||||||
|
tab_dependencies dependent, nil
|
||||||
|
|
||||||
stub_formula_loader Formula["foo"], "homebrew/core/foo-old"
|
stub_formula_loader Formula["foo"], "homebrew/core/foo-old"
|
||||||
renamed_path = HOMEBREW_CELLAR/"foo-old"
|
renamed_path = HOMEBREW_CELLAR/"foo-old"
|
||||||
(HOMEBREW_CELLAR/"foo").rename(renamed_path)
|
(HOMEBREW_CELLAR/"foo").rename(renamed_path)
|
||||||
renamed_keg = Keg.new(renamed_path/"1.0")
|
renamed_keg = Keg.new(renamed_path/keg.version.to_s)
|
||||||
|
|
||||||
Formula["bar"].class.depends_on "foo"
|
|
||||||
|
|
||||||
result = described_class.find_some_installed_dependents([renamed_keg])
|
result = described_class.find_some_installed_dependents([renamed_keg])
|
||||||
expect(result).to eq([[renamed_keg], ["bar"]])
|
expect(result).to eq([[renamed_keg], ["bar"]])
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "empty dependencies in Tab" do
|
specify "empty dependencies in Tab" do
|
||||||
dependencies []
|
dependent = setup_test_keg("bar", "1.0")
|
||||||
|
tab_dependencies dependent, []
|
||||||
expect(described_class.find_some_installed_dependents([keg])).to be_nil
|
expect(described_class.find_some_installed_dependents([keg])).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "same name but different version in Tab" do
|
specify "same name but different version in Tab" do
|
||||||
dependencies [{ "full_name" => "foo", "version" => "1.1" }]
|
dependent = setup_test_keg("bar", "1.0")
|
||||||
|
tab_dependencies dependent, [{ "full_name" => keg.name, "version" => "1.1" }]
|
||||||
expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
|
expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "different name and same version in Tab" do
|
specify "different name and same version in Tab" do
|
||||||
stub_formula_name("baz")
|
stub_formula("baz")
|
||||||
dependencies [{ "full_name" => "baz", "version" => keg.version.to_s }]
|
dependent = setup_test_keg("bar", "1.0")
|
||||||
|
tab_dependencies dependent, [{ "full_name" => "baz", "version" => keg.version.to_s }]
|
||||||
expect(described_class.find_some_installed_dependents([keg])).to be_nil
|
expect(described_class.find_some_installed_dependents([keg])).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "same name and version in Tab" do
|
specify "same name and version in Tab" do
|
||||||
dependencies [{ "full_name" => "foo", "version" => "1.0" }]
|
dependent = setup_test_keg("bar", "1.0")
|
||||||
|
tab_dependencies dependent, [{ "full_name" => keg.name, "version" => keg.version.to_s }]
|
||||||
expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
|
expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "fallback for old versions" do
|
specify "fallback for old versions" do
|
||||||
unreliable_dependencies [{ "full_name" => "baz", "version" => "1.0" }]
|
dependent = setup_test_keg("bar", "1.0") do
|
||||||
Formula["bar"].class.depends_on "foo"
|
depends_on "foo"
|
||||||
|
end
|
||||||
|
unreliable_tab_dependencies dependent, [{ "full_name" => "baz", "version" => "1.0" }]
|
||||||
expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
|
expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "non-opt-linked" do
|
specify "non-opt-linked" do
|
||||||
keg.remove_opt_record
|
keg.remove_opt_record
|
||||||
dependencies [{ "full_name" => "foo", "version" => "1.0" }]
|
dependent = setup_test_keg("bar", "1.0")
|
||||||
|
tab_dependencies dependent, [{ "full_name" => keg.name, "version" => keg.version.to_s }]
|
||||||
expect(described_class.find_some_installed_dependents([keg])).to be_nil
|
expect(described_class.find_some_installed_dependents([keg])).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
specify "keg-only" do
|
specify "keg-only" do
|
||||||
keg.unlink
|
dependent = setup_test_keg("bar", "1.0")
|
||||||
Formula["foo"].class.keg_only "a good reason"
|
tab_dependencies dependent, [{ "full_name" => keg_only_keg.name, "version" => "1.1" }] # different version
|
||||||
dependencies [{ "full_name" => "foo", "version" => "1.1" }] # different version
|
expect(described_class.find_some_installed_dependents([keg_only_keg])).to eq([[keg_only_keg], ["bar"]])
|
||||||
expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def stub_cask_name(name, version, dependency)
|
def stub_cask_name(name, version, dependency)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user