bottle: tag specific cellars
This commit is contained in:
parent
33dafa4498
commit
3eea1434cc
@ -553,7 +553,7 @@ module Homebrew
|
|||||||
return [mismatches, checksums] if old_keys.exclude? :sha256
|
return [mismatches, checksums] if old_keys.exclude? :sha256
|
||||||
|
|
||||||
old_bottle_spec.collector.each_key do |tag|
|
old_bottle_spec.collector.each_key do |tag|
|
||||||
old_value = old_bottle_spec.collector[tag].hexdigest
|
old_value = old_bottle_spec.collector[tag][:checksum].hexdigest
|
||||||
new_value = new_bottle_hash.dig("tags", tag.to_s)
|
new_value = new_bottle_hash.dig("tags", tag.to_s)
|
||||||
if new_value.present?
|
if new_value.present?
|
||||||
mismatches << "sha256 => #{tag}"
|
mismatches << "sha256 => #{tag}"
|
||||||
|
@ -1831,7 +1831,7 @@ class Formula
|
|||||||
bottle_info["files"] = {}
|
bottle_info["files"] = {}
|
||||||
bottle_spec.collector.each_key do |os|
|
bottle_spec.collector.each_key do |os|
|
||||||
bottle_url = "#{bottle_spec.root_url}/#{Bottle::Filename.create(self, os, bottle_spec.rebuild).bintray}"
|
bottle_url = "#{bottle_spec.root_url}/#{Bottle::Filename.create(self, os, bottle_spec.rebuild).bintray}"
|
||||||
checksum = bottle_spec.collector[os]
|
checksum = bottle_spec.collector[os][:checksum]
|
||||||
bottle_info["files"][os] = {
|
bottle_info["files"][os] = {
|
||||||
"url" => bottle_url,
|
"url" => bottle_url,
|
||||||
"sha256" => checksum.hexdigest,
|
"sha256" => checksum.hexdigest,
|
||||||
|
@ -302,7 +302,7 @@ class Bottle
|
|||||||
@resource.specs[:bottle] = true
|
@resource.specs[:bottle] = true
|
||||||
@spec = spec
|
@spec = spec
|
||||||
|
|
||||||
checksum, tag = spec.checksum_for(Utils::Bottles.tag)
|
checksum, tag, cellar = spec.checksum_for(Utils::Bottles.tag)
|
||||||
|
|
||||||
filename = Filename.create(formula, tag, spec.rebuild)
|
filename = Filename.create(formula, tag, spec.rebuild)
|
||||||
@resource.url("#{spec.root_url}/#{filename.bintray}",
|
@resource.url("#{spec.root_url}/#{filename.bintray}",
|
||||||
@ -310,7 +310,7 @@ class Bottle
|
|||||||
@resource.version = formula.pkg_version
|
@resource.version = formula.pkg_version
|
||||||
@resource.checksum = checksum
|
@resource.checksum = checksum
|
||||||
@prefix = spec.prefix
|
@prefix = spec.prefix
|
||||||
@cellar = spec.cellar
|
@cellar = cellar
|
||||||
@rebuild = spec.rebuild
|
@rebuild = spec.rebuild
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -338,15 +338,15 @@ end
|
|||||||
class BottleSpecification
|
class BottleSpecification
|
||||||
extend T::Sig
|
extend T::Sig
|
||||||
|
|
||||||
attr_rw :prefix, :cellar, :rebuild
|
attr_rw :prefix, :rebuild
|
||||||
attr_accessor :tap
|
attr_accessor :tap
|
||||||
attr_reader :checksum, :collector, :root_url_specs, :repository
|
attr_reader :all_tags_cellar, :checksum, :collector, :root_url_specs, :repository
|
||||||
|
|
||||||
sig { void }
|
sig { void }
|
||||||
def initialize
|
def initialize
|
||||||
@rebuild = 0
|
@rebuild = 0
|
||||||
@prefix = Homebrew::DEFAULT_PREFIX
|
@prefix = Homebrew::DEFAULT_PREFIX
|
||||||
@cellar = Homebrew::DEFAULT_CELLAR
|
@all_tags_cellar = Homebrew::DEFAULT_CELLAR
|
||||||
@repository = Homebrew::DEFAULT_REPOSITORY
|
@repository = Homebrew::DEFAULT_REPOSITORY
|
||||||
@collector = Utils::Bottles::Collector.new
|
@collector = Utils::Bottles::Collector.new
|
||||||
@root_url_specs = {}
|
@root_url_specs = {}
|
||||||
@ -370,6 +370,12 @@ class BottleSpecification
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cellar(val = nil)
|
||||||
|
return collector.dig(Utils::Bottles.tag, :cellar) || @all_tags_cellar if val.nil?
|
||||||
|
|
||||||
|
@all_tags_cellar = val
|
||||||
|
end
|
||||||
|
|
||||||
def compatible_locations?
|
def compatible_locations?
|
||||||
# this looks like it should check prefix and repository too but to be
|
# this looks like it should check prefix and repository too but to be
|
||||||
# `cellar :any` actually requires no references to the cellar, prefix or
|
# `cellar :any` actually requires no references to the cellar, prefix or
|
||||||
@ -398,17 +404,30 @@ class BottleSpecification
|
|||||||
cellar == :any_skip_relocation
|
cellar == :any_skip_relocation
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(tag: Symbol).returns(T::Boolean) }
|
||||||
def tag?(tag)
|
def tag?(tag)
|
||||||
checksum_for(tag) ? true : false
|
checksum_for(tag) ? true : false
|
||||||
end
|
end
|
||||||
|
|
||||||
# Checksum methods in the DSL's bottle block optionally take
|
# Checksum methods in the DSL's bottle block take
|
||||||
# a Hash, which indicates the platform the checksum applies on.
|
# a Hash, which indicates the platform the checksum applies on.
|
||||||
def sha256(val)
|
# Example bottle block syntax:
|
||||||
digest, tag = val.shift
|
# bottle do
|
||||||
collector[tag] = Checksum.new(digest)
|
# sha256 "69489ae397e4645..." => :big_sur, :cellar => :any_skip_relocation
|
||||||
|
# sha256 "449de5ea35d0e94..." => :catalina, :cellar => :any
|
||||||
|
# end
|
||||||
|
# Example args:
|
||||||
|
# {"69489ae397e4645..."=> :big_sur, :cellar=>:any_skip_relocation}
|
||||||
|
def sha256(hash)
|
||||||
|
sha256_regex = /^[a-f0-9]{64}$/i
|
||||||
|
digest, tag = hash.find do |key, value|
|
||||||
|
key.is_a?(String) && value.is_a?(Symbol) && key.match?(sha256_regex)
|
||||||
|
end
|
||||||
|
cellar = hash[:cellar] || all_tags_cellar
|
||||||
|
collector[tag] = { checksum: Checksum.new(digest), cellar: cellar }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(tag: Symbol).returns(T.nilable([Checksum, Symbol, T.any(Symbol, String)])) }
|
||||||
def checksum_for(tag)
|
def checksum_for(tag)
|
||||||
collector.fetch_checksum_for(tag)
|
collector.fetch_checksum_for(tag)
|
||||||
end
|
end
|
||||||
@ -420,10 +439,11 @@ class BottleSpecification
|
|||||||
# Sort non-MacOS tags below MacOS tags.
|
# Sort non-MacOS tags below MacOS tags.
|
||||||
"0.#{tag}"
|
"0.#{tag}"
|
||||||
end
|
end
|
||||||
sha256s = []
|
sha256s = tags.reverse.map do |tag|
|
||||||
tags.reverse_each do |tag|
|
{
|
||||||
checksum = collector[tag]
|
collector[tag][:checksum] => tag,
|
||||||
sha256s << { checksum => tag }
|
cellar: collector[tag][:cellar],
|
||||||
|
}
|
||||||
end
|
end
|
||||||
{ sha256: sha256s }
|
{ sha256: sha256s }
|
||||||
end
|
end
|
||||||
|
@ -8,6 +8,7 @@ require "tab"
|
|||||||
require "cmd/install"
|
require "cmd/install"
|
||||||
require "test/support/fixtures/testball"
|
require "test/support/fixtures/testball"
|
||||||
require "test/support/fixtures/testball_bottle"
|
require "test/support/fixtures/testball_bottle"
|
||||||
|
require "test/support/fixtures/testball_bottle_cellar"
|
||||||
|
|
||||||
describe FormulaInstaller do
|
describe FormulaInstaller do
|
||||||
alias_matcher :pour_bottle, :be_pour_bottle
|
alias_matcher :pour_bottle, :be_pour_bottle
|
||||||
@ -49,26 +50,43 @@ describe FormulaInstaller do
|
|||||||
expect(formula).not_to be_latest_version_installed
|
expect(formula).not_to be_latest_version_installed
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_basic_formula_setup(f)
|
||||||
|
# Test that things made it into the Keg
|
||||||
|
expect(f.bin).to be_a_directory
|
||||||
|
|
||||||
|
expect(f.libexec).to be_a_directory
|
||||||
|
|
||||||
|
expect(f.prefix/"main.c").not_to exist
|
||||||
|
|
||||||
|
# Test that things made it into the Cellar
|
||||||
|
keg = Keg.new f.prefix
|
||||||
|
keg.link
|
||||||
|
|
||||||
|
bin = HOMEBREW_PREFIX/"bin"
|
||||||
|
expect(bin).to be_a_directory
|
||||||
|
|
||||||
|
expect(f.libexec).to be_a_directory
|
||||||
|
end
|
||||||
|
|
||||||
specify "basic bottle install" do
|
specify "basic bottle install" do
|
||||||
allow(DevelopmentTools).to receive(:installed?).and_return(false)
|
allow(DevelopmentTools).to receive(:installed?).and_return(false)
|
||||||
Homebrew.install_args.parse(["testball_bottle"])
|
Homebrew.install_args.parse(["testball_bottle"])
|
||||||
temporarily_install_bottle(TestballBottle.new) do |f|
|
temporarily_install_bottle(TestballBottle.new) do |f|
|
||||||
# Copied directly from formula_installer_spec.rb
|
test_basic_formula_setup(f)
|
||||||
# as we expect the same behavior.
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Test that things made it into the Keg
|
specify "basic bottle install with cellar information on sha256 line" do
|
||||||
expect(f.bin).to be_a_directory
|
allow(DevelopmentTools).to receive(:installed?).and_return(false)
|
||||||
|
Homebrew.install_args.parse(["testball_bottle_cellar"])
|
||||||
|
temporarily_install_bottle(TestballBottleCellar.new) do |f|
|
||||||
|
test_basic_formula_setup(f)
|
||||||
|
|
||||||
expect(f.libexec).to be_a_directory
|
# skip_relocation is always false on Linux but can be true on macOS.
|
||||||
|
# see: extend/os/linux/software_spec.rb
|
||||||
|
skip_relocation = !OS.linux?
|
||||||
|
|
||||||
expect(f.prefix/"main.c").not_to exist
|
expect(f.bottle_specification.skip_relocation?).to eq(skip_relocation)
|
||||||
|
|
||||||
# Test that things made it into the Cellar
|
|
||||||
keg = Keg.new f.prefix
|
|
||||||
keg.link
|
|
||||||
|
|
||||||
bin = HOMEBREW_PREFIX/"bin"
|
|
||||||
expect(bin).to be_a_directory
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -183,18 +183,38 @@ describe HeadSoftwareSpec do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe BottleSpecification do
|
describe BottleSpecification do
|
||||||
specify "#sha256" do
|
describe "#sha256" do
|
||||||
checksums = {
|
it "works without cellar" do
|
||||||
snow_leopard_32: "deadbeef" * 8,
|
checksums = {
|
||||||
snow_leopard: "faceb00c" * 8,
|
snow_leopard_32: "deadbeef" * 8,
|
||||||
lion: "baadf00d" * 8,
|
snow_leopard: "faceb00c" * 8,
|
||||||
mountain_lion: "8badf00d" * 8,
|
lion: "baadf00d" * 8,
|
||||||
}
|
mountain_lion: "8badf00d" * 8,
|
||||||
|
}
|
||||||
|
|
||||||
checksums.each_pair do |cat, digest|
|
checksums.each_pair do |cat, digest|
|
||||||
subject.sha256(digest => cat)
|
subject.sha256(digest => cat)
|
||||||
checksum, = subject.checksum_for(cat)
|
checksum, = subject.checksum_for(cat)
|
||||||
expect(Checksum.new(digest)).to eq(checksum)
|
expect(Checksum.new(digest)).to eq(checksum)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "works with cellar" do
|
||||||
|
checksums = [
|
||||||
|
{ digest: "deadbeef" * 8, tag: :snow_leopard_32, cellar: :any_skip_relocation },
|
||||||
|
{ digest: "faceb00c" * 8, tag: :snow_leopard, cellar: :any },
|
||||||
|
{ digest: "baadf00d" * 8, tag: :lion, cellar: "/usr/local/Cellar" },
|
||||||
|
{ digest: "8badf00d" * 8, tag: :mountain_lion, cellar: Homebrew::DEFAULT_CELLAR },
|
||||||
|
]
|
||||||
|
|
||||||
|
checksums.each do |checksum|
|
||||||
|
subject.sha256(checksum[:digest] => checksum[:tag], cellar: checksum[:cellar])
|
||||||
|
digest, tag, cellar = subject.checksum_for(checksum[:tag])
|
||||||
|
expect(Checksum.new(checksum[:digest])).to eq(digest)
|
||||||
|
expect(checksum[:tag]).to eq(tag)
|
||||||
|
checksum[:cellar] ||= Homebrew::DEFAULT_CELLAR
|
||||||
|
expect(checksum[:cellar]).to eq(cellar)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
# typed: true
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class TestballBottleCellar < Formula
|
||||||
|
def initialize(name = "testball_bottle", path = Pathname.new(__FILE__).expand_path, spec = :stable,
|
||||||
|
alias_path: nil, force_bottle: false)
|
||||||
|
self.class.instance_eval do
|
||||||
|
stable.url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz"
|
||||||
|
stable.sha256 TESTBALL_SHA256
|
||||||
|
hexdigest = "8f9aecd233463da6a4ea55f5f88fc5841718c013f3e2a7941350d6130f1dc149"
|
||||||
|
stable.bottle do
|
||||||
|
root_url "file://#{TEST_FIXTURE_DIR}/bottles"
|
||||||
|
sha256 hexdigest => Utils::Bottles.tag, :cellar => :any_skip_relocation
|
||||||
|
end
|
||||||
|
cxxstdlib_check :skip
|
||||||
|
end
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def install
|
||||||
|
prefix.install "bin"
|
||||||
|
prefix.install "libexec"
|
||||||
|
end
|
||||||
|
end
|
@ -8,9 +8,9 @@ describe Utils::Bottles::Collector do
|
|||||||
|
|
||||||
describe "#fetch_checksum_for" do
|
describe "#fetch_checksum_for" do
|
||||||
it "returns passed tags" do
|
it "returns passed tags" do
|
||||||
collector[:mojave] = "foo"
|
collector[:mojave] = { checksum: Checksum.new("foo_checksum"), cellar: "foo_cellar" }
|
||||||
collector[:catalina] = "bar"
|
collector[:catalina] = { checksum: Checksum.new("bar_checksum"), cellar: "bar_cellar" }
|
||||||
expect(collector.fetch_checksum_for(:catalina)).to eq(["bar", :catalina])
|
expect(collector.fetch_checksum_for(:catalina)).to eq(["bar_checksum", :catalina, "bar_cellar"])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns nil if empty" do
|
it "returns nil if empty" do
|
||||||
|
@ -100,16 +100,17 @@ module Utils
|
|||||||
|
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
|
|
||||||
def_delegators :@checksums, :keys, :[], :[]=, :key?, :each_key
|
def_delegators :@checksums, :keys, :[], :[]=, :key?, :each_key, :dig
|
||||||
|
|
||||||
sig { void }
|
sig { void }
|
||||||
def initialize
|
def initialize
|
||||||
@checksums = {}
|
@checksums = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(tag: Symbol).returns(T.nilable([Checksum, Symbol, T.any(Symbol, String)])) }
|
||||||
def fetch_checksum_for(tag)
|
def fetch_checksum_for(tag)
|
||||||
tag = find_matching_tag(tag)
|
tag = find_matching_tag(tag)
|
||||||
return self[tag], tag if tag
|
return self[tag][:checksum], tag, self[tag][:cellar] if tag
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
Loading…
x
Reference in New Issue
Block a user