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
 | 
			
		||||
 | 
			
		||||
    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_basic_formula_setup(f)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
      # Test that things made it into the Keg
 | 
			
		||||
      expect(f.bin).to be_a_directory
 | 
			
		||||
  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)
 | 
			
		||||
 | 
			
		||||
      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
 | 
			
		||||
 | 
			
		||||
      # 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.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,
 | 
			
		||||
    }
 | 
			
		||||
  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)
 | 
			
		||||
      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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user