Skip to content
Snippets Groups Projects
Commit 3eea1434 authored by Michka Popoff's avatar Michka Popoff
Browse files

bottle: tag specific cellars

parent 33dafa44
No related branches found
No related tags found
No related merge requests found
......@@ -553,7 +553,7 @@ module Homebrew
return [mismatches, checksums] if old_keys.exclude? :sha256
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)
if new_value.present?
mismatches << "sha256 => #{tag}"
......
......@@ -1831,7 +1831,7 @@ class Formula
bottle_info["files"] = {}
bottle_spec.collector.each_key do |os|
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] = {
"url" => bottle_url,
"sha256" => checksum.hexdigest,
......
......@@ -302,7 +302,7 @@ class Bottle
@resource.specs[:bottle] = true
@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)
@resource.url("#{spec.root_url}/#{filename.bintray}",
......@@ -310,7 +310,7 @@ class Bottle
@resource.version = formula.pkg_version
@resource.checksum = checksum
@prefix = spec.prefix
@cellar = spec.cellar
@cellar = cellar
@rebuild = spec.rebuild
end
......@@ -338,15 +338,15 @@ end
class BottleSpecification
extend T::Sig
attr_rw :prefix, :cellar, :rebuild
attr_rw :prefix, :rebuild
attr_accessor :tap
attr_reader :checksum, :collector, :root_url_specs, :repository
attr_reader :all_tags_cellar, :checksum, :collector, :root_url_specs, :repository
sig { void }
def initialize
@rebuild = 0
@prefix = Homebrew::DEFAULT_PREFIX
@cellar = Homebrew::DEFAULT_CELLAR
@all_tags_cellar = Homebrew::DEFAULT_CELLAR
@repository = Homebrew::DEFAULT_REPOSITORY
@collector = Utils::Bottles::Collector.new
@root_url_specs = {}
......@@ -370,6 +370,12 @@ class BottleSpecification
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?
# this looks like it should check prefix and repository too but to be
# `cellar :any` actually requires no references to the cellar, prefix or
......@@ -398,17 +404,30 @@ class BottleSpecification
cellar == :any_skip_relocation
end
sig { params(tag: Symbol).returns(T::Boolean) }
def tag?(tag)
checksum_for(tag) ? true : false
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.
def sha256(val)
digest, tag = val.shift
collector[tag] = Checksum.new(digest)
# Example bottle block syntax:
# bottle do
# 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
sig { params(tag: Symbol).returns(T.nilable([Checksum, Symbol, T.any(Symbol, String)])) }
def checksum_for(tag)
collector.fetch_checksum_for(tag)
end
......@@ -420,10 +439,11 @@ class BottleSpecification
# Sort non-MacOS tags below MacOS tags.
"0.#{tag}"
end
sha256s = []
tags.reverse_each do |tag|
checksum = collector[tag]
sha256s << { checksum => tag }
sha256s = tags.reverse.map do |tag|
{
collector[tag][:checksum] => tag,
cellar: collector[tag][:cellar],
}
end
{ sha256: sha256s }
end
......
......@@ -8,6 +8,7 @@ require "tab"
require "cmd/install"
require "test/support/fixtures/testball"
require "test/support/fixtures/testball_bottle"
require "test/support/fixtures/testball_bottle_cellar"
describe FormulaInstaller do
alias_matcher :pour_bottle, :be_pour_bottle
......@@ -49,26 +50,43 @@ describe FormulaInstaller do
expect(formula).not_to be_latest_version_installed
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
allow(DevelopmentTools).to receive(:installed?).and_return(false)
Homebrew.install_args.parse(["testball_bottle"])
temporarily_install_bottle(TestballBottle.new) do |f|
# Copied directly from formula_installer_spec.rb
# as we expect the same behavior.
# Test that things made it into the Keg
expect(f.bin).to be_a_directory
expect(f.libexec).to be_a_directory
test_basic_formula_setup(f)
end
end
expect(f.prefix/"main.c").not_to exist
specify "basic bottle install with cellar information on sha256 line" do
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)
# Test that things made it into the Cellar
keg = Keg.new f.prefix
keg.link
# skip_relocation is always false on Linux but can be true on macOS.
# see: extend/os/linux/software_spec.rb
skip_relocation = !OS.linux?
bin = HOMEBREW_PREFIX/"bin"
expect(bin).to be_a_directory
expect(f.bottle_specification.skip_relocation?).to eq(skip_relocation)
end
end
......
......@@ -183,18 +183,38 @@ describe HeadSoftwareSpec do
end
describe BottleSpecification do
specify "#sha256" do
checksums = {
snow_leopard_32: "deadbeef" * 8,
snow_leopard: "faceb00c" * 8,
lion: "baadf00d" * 8,
mountain_lion: "8badf00d" * 8,
}
checksums.each_pair do |cat, digest|
subject.sha256(digest => cat)
checksum, = subject.checksum_for(cat)
expect(Checksum.new(digest)).to eq(checksum)
describe "#sha256" do
it "works without cellar" do
checksums = {
snow_leopard_32: "deadbeef" * 8,
snow_leopard: "faceb00c" * 8,
lion: "baadf00d" * 8,
mountain_lion: "8badf00d" * 8,
}
checksums.each_pair do |cat, digest|
subject.sha256(digest => cat)
checksum, = subject.checksum_for(cat)
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
......
# 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
it "returns passed tags" do
collector[:mojave] = "foo"
collector[:catalina] = "bar"
expect(collector.fetch_checksum_for(:catalina)).to eq(["bar", :catalina])
collector[:mojave] = { checksum: Checksum.new("foo_checksum"), cellar: "foo_cellar" }
collector[:catalina] = { checksum: Checksum.new("bar_checksum"), cellar: "bar_cellar" }
expect(collector.fetch_checksum_for(:catalina)).to eq(["bar_checksum", :catalina, "bar_cellar"])
end
it "returns nil if empty" do
......
......@@ -100,16 +100,17 @@ module Utils
extend Forwardable
def_delegators :@checksums, :keys, :[], :[]=, :key?, :each_key
def_delegators :@checksums, :keys, :[], :[]=, :key?, :each_key, :dig
sig { void }
def initialize
@checksums = {}
end
sig { params(tag: Symbol).returns(T.nilable([Checksum, Symbol, T.any(Symbol, String)])) }
def fetch_checksum_for(tag)
tag = find_matching_tag(tag)
return self[tag], tag if tag
return self[tag][:checksum], tag, self[tag][:cellar] if tag
end
private
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment