brew/Library/Homebrew/utils/topological_hash.rb

72 lines
2.2 KiB
Ruby
Raw Normal View History

# typed: strict
# frozen_string_literal: true
require "tsort"
module Utils
# Topologically sortable hash map.
class TopologicalHash < Hash
extend T::Generic
include TSort
CaskOrFormula = T.type_alias { T.any(Cask::Cask, Formula) }
K = type_member { { fixed: CaskOrFormula } }
V = type_member { { fixed: T::Array[CaskOrFormula] } }
Elem = type_member(:out) { { fixed: [CaskOrFormula, T::Array[CaskOrFormula]] } }
sig {
params(
packages: T.any(CaskOrFormula, T::Array[CaskOrFormula]),
accumulator: TopologicalHash,
).returns(TopologicalHash)
}
def self.graph_package_dependencies(packages, accumulator = TopologicalHash.new)
packages = Array(packages)
packages.each do |cask_or_formula|
2021-11-12 13:50:53 -08:00
next if accumulator.key?(cask_or_formula)
2025-03-13 10:26:41 -07:00
case cask_or_formula
when Cask::Cask
formula_deps = cask_or_formula.depends_on
.formula
.map { |f| Formula[f] }
cask_deps = cask_or_formula.depends_on
.cask
.map { |c| Cask::CaskLoader.load(c, config: nil) }
2025-03-13 10:26:41 -07:00
when Formula
formula_deps = cask_or_formula.deps
.reject(&:build?)
2023-08-17 04:16:02 -07:00
.reject(&:test?)
.map(&:to_formula)
cask_deps = cask_or_formula.requirements
.filter_map(&:cask)
.map { |c| Cask::CaskLoader.load(c, config: nil) }
2025-03-13 10:26:41 -07:00
else
T.absurd(cask_or_formula)
end
2021-11-12 13:50:53 -08:00
accumulator[cask_or_formula] = formula_deps + cask_deps
graph_package_dependencies(formula_deps, accumulator)
graph_package_dependencies(cask_deps, accumulator)
end
accumulator
end
private
sig { params(block: T.proc.params(arg0: K).void).void }
def tsort_each_node(&block)
each_key(&block)
end
sig { params(node: K, block: T.proc.params(arg0: CaskOrFormula).void).returns(V) }
def tsort_each_child(node, &block)
fetch(node).each(&block)
end
end
end