Include recursive dependencies in cask tabs

This commit is contained in:
Rylan Polster 2024-07-09 15:25:57 -04:00
parent 119e02ceb0
commit d17da89382
No known key found for this signature in database
GPG Key ID: 46A744940CFF4D64
5 changed files with 172 additions and 67 deletions

View File

@ -50,36 +50,35 @@ module Cask
end
def self.runtime_deps_hash(cask, depends_on)
mappable_types = [:cask, :formula]
depends_on.to_h do |type, deps|
next [type, deps] unless mappable_types.include? type
cask_and_formula_dep_graph = ::Utils::TopologicalHash.graph_package_dependencies(cask)
cask_deps, formula_deps = cask_and_formula_dep_graph.values.flatten.uniq.partition do |dep|
dep.is_a?(Cask)
end
deps = deps.map do |dep|
if type == :cask
c = CaskLoader.load(dep)
runtime_deps = {}
if cask_deps.any?
runtime_deps[:cask] = cask_deps.map do |dep|
{
"full_name" => c.full_name,
"version" => c.version.to_s,
"declared_directly" => cask.depends_on.cask.include?(dep),
"full_name" => dep.full_name,
"version" => dep.version.to_s,
"declared_directly" => cask.depends_on.cask.include?(dep.full_name),
}
elsif type == :formula
f = Formulary.factory(dep, warn: false)
{
"full_name" => f.full_name,
"version" => f.version.to_s,
"revision" => f.revision,
"pkg_version" => f.pkg_version.to_s,
"declared_directly" => cask.depends_on.formula.include?(dep),
}
else
dep
end
end
[type, deps]
if formula_deps.any?
runtime_deps[:formula] = formula_deps.map do |dep|
formula_to_dep_hash(dep, cask.depends_on.formula)
end
end
runtime_deps[:macos] = depends_on.macos if depends_on.macos
runtime_deps[:arch] = depends_on.arch if depends_on.arch
runtime_deps
end
def version
source["version"]
end

View File

@ -93,6 +93,17 @@ class AbstractTab
new(attributes)
end
def self.formula_to_dep_hash(formula, declared_deps)
{
"full_name" => formula.full_name,
"version" => formula.version.to_s,
"revision" => formula.revision,
"pkg_version" => formula.pkg_version.to_s,
"declared_directly" => declared_deps.include?(formula.full_name),
}
end
private_class_method :formula_to_dep_hash
def initialize(attributes = {})
attributes.each { |key, value| instance_variable_set(:"@#{key}", value) }
end
@ -290,14 +301,7 @@ class Tab < AbstractTab
def self.runtime_deps_hash(formula, deps)
deps.map do |dep|
f = dep.to_formula
{
"full_name" => f.full_name,
"version" => f.version.to_s,
"revision" => f.revision,
"pkg_version" => f.pkg_version.to_s,
"declared_directly" => formula.deps.include?(dep),
}
formula_to_dep_hash(dep.to_formula, formula.deps.map(&:name))
end
end

View File

@ -85,17 +85,67 @@ RSpec.describe Cask::Tab, :cask do
expect(tab.runtime_dependencies).not_to be_nil
end
specify "::runtime_deps_hash" do
describe "::runtime_deps_hash" do
specify "with no dependencies" do
cask = Cask::CaskLoader.load("local-transmission")
expect(described_class.runtime_deps_hash(cask, cask.depends_on)).to eq({})
end
specify "with cask dependencies" do
cask = Cask::CaskLoader.load("with-depends-on-cask")
expected_hash = {
cask: [
{ "full_name"=>"local-transmission", "version"=>"2.61", "declared_directly"=>true },
],
}
expect(described_class.runtime_deps_hash(cask, cask.depends_on)).to eq(expected_hash)
end
specify "with macos symbol dependencies" do
cask = Cask::CaskLoader.load("with-depends-on-macos-symbol")
expected_hash = {
macos: MacOSRequirement.new([MacOS.version.to_sym], comparator: "=="),
}
expect(described_class.runtime_deps_hash(cask, cask.depends_on)).to eq(expected_hash)
end
specify "with macos array dependencies" do
cask = Cask::CaskLoader.load("with-depends-on-macos-array")
expected_hash = {
macos: MacOSRequirement.new([[:catalina, MacOS.version.to_sym]], comparator: "=="),
}
expect(described_class.runtime_deps_hash(cask, cask.depends_on)).to eq(expected_hash)
end
specify "with arch dependencies" do
cask = Cask::CaskLoader.load("with-depends-on-arch")
expected_hash = {
arch: [
{ type: :intel, bits: 64 },
{ type: :arm, bits: 64 },
],
}
expect(described_class.runtime_deps_hash(cask, cask.depends_on)).to eq(expected_hash)
end
specify "with all types of dependencies" do
cask = Cask::CaskLoader.load("with-depends-on-everything")
unar = instance_double(Formula, full_name: "unar", version: "1.2", revision: 0, pkg_version: "1.2")
expect(Formulary).to receive(:factory).with("unar", { warn: false }).and_return(unar)
unar = instance_double(Formula, full_name: "unar", version: "1.2", revision: 0, pkg_version: "1.2",
deps: [], requirements: [])
expect(Formulary).to receive(:factory).with("unar").and_return(unar)
expected_hash = {
arch: [{ type: :intel, bits: 64 }, { type: :arm, bits: 64 }],
cask: [
{ "full_name"=>"local-caffeine", "version"=>"1.2.3", "declared_directly"=>true },
{ "full_name"=>"local-transmission", "version"=>"2.61", "declared_directly"=>true },
{ "full_name"=>"with-depends-on-cask", "version"=>"1.2.3", "declared_directly"=>true },
{ "full_name"=>"local-transmission", "version"=>"2.61", "declared_directly"=>false },
],
formula: [
{ "full_name"=>"unar", "version"=>"1.2", "revision"=>0, "pkg_version"=>"1.2", "declared_directly"=>true },
@ -108,6 +158,7 @@ RSpec.describe Cask::Tab, :cask do
tab.runtime_dependencies = runtime_deps_hash
expect(tab.runtime_dependencies).to eql(expected_hash)
end
end
specify "other attributes" do
expect(tab.tap.name).to eq("homebrew/cask")

View File

@ -7,7 +7,7 @@ cask "with-depends-on-everything" do
depends_on arch: [:intel, :arm64]
depends_on cask: "local-caffeine"
depends_on cask: "local-transmission"
depends_on cask: "with-depends-on-cask"
depends_on formula: "unar"
depends_on macos: ">= :el_capitan"

View File

@ -155,7 +155,8 @@ RSpec.describe Tab do
expect(tab.runtime_dependencies).not_to be_nil
end
specify "::runtime_deps_hash" do
describe "::runtime_deps_hash" do
it "handles older Homebrew versions correctly" do
runtime_deps = [Dependency.new("foo")]
foo = formula("foo") { url "foo-1.0" }
stub_formula_loader foo
@ -169,6 +170,56 @@ RSpec.describe Tab do
)
end
it "include declared dependencies" do
foo = formula("foo") { url "foo-1.0" }
stub_formula_loader foo
runtime_deps = [Dependency.new("foo")]
formula = instance_double(Formula, deps: runtime_deps)
expected_output = [
{
"full_name" => "foo",
"version" => "1.0",
"revision" => 0,
"pkg_version" => "1.0",
"declared_directly" => true,
},
]
expect(described_class.runtime_deps_hash(formula, runtime_deps)).to eq(expected_output)
end
it "includes recursive dependencies" do
foo = formula("foo") { url "foo-1.0" }
stub_formula_loader foo
bar = formula("bar") { url "bar-2.0" }
stub_formula_loader bar
# Simulating dependencies formula => foo => bar
formula_declared_deps = [Dependency.new("foo")]
formula_recursive_deps = [Dependency.new("foo"), Dependency.new("bar")]
formula = instance_double(Formula, deps: formula_declared_deps)
expected_output = [
{
"full_name" => "foo",
"version" => "1.0",
"revision" => 0,
"pkg_version" => "1.0",
"declared_directly" => true,
},
{
"full_name" => "bar",
"version" => "2.0",
"revision" => 0,
"pkg_version" => "2.0",
"declared_directly" => false,
},
]
expect(described_class.runtime_deps_hash(formula, formula_recursive_deps)).to eq(expected_output)
end
end
specify "#cxxstdlib" do
expect(tab.cxxstdlib.compiler).to eq(:clang)
expect(tab.cxxstdlib.type).to eq(:libcxx)