mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
72 lines
2.2 KiB
Ruby
72 lines
2.2 KiB
Ruby
# 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|
|
|
next if accumulator.key?(cask_or_formula)
|
|
|
|
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) }
|
|
when Formula
|
|
formula_deps = cask_or_formula.deps
|
|
.reject(&:build?)
|
|
.reject(&:test?)
|
|
.map(&:to_formula)
|
|
cask_deps = cask_or_formula.requirements
|
|
.filter_map(&:cask)
|
|
.map { |c| Cask::CaskLoader.load(c, config: nil) }
|
|
else
|
|
T.absurd(cask_or_formula)
|
|
end
|
|
|
|
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
|