brew/Library/Homebrew/bottle_specification.rb

140 lines
4.3 KiB
Ruby
Raw Normal View History

# typed: true # rubocop:todo Sorbet/StrictSigil
# frozen_string_literal: true
class BottleSpecification
RELOCATABLE_CELLARS = [:any, :any_skip_relocation].freeze
attr_accessor :tap
attr_reader :collector, :root_url_specs, :repository
sig { void }
def initialize
@rebuild = 0
@repository = Homebrew::DEFAULT_REPOSITORY
@collector = Utils::Bottles::Collector.new
@root_url_specs = {}
end
sig { params(val: Integer).returns(T.nilable(Integer)) }
def rebuild(val = T.unsafe(nil))
2025-02-23 13:18:49 -08:00
val.nil? ? @rebuild : @rebuild = val
end
def root_url(var = nil, specs = {})
if var.nil?
@root_url ||= if (github_packages_url = GitHubPackages.root_url_if_match(Homebrew::EnvConfig.bottle_domain))
github_packages_url
else
Homebrew::EnvConfig.bottle_domain
end
else
@root_url = if (github_packages_url = GitHubPackages.root_url_if_match(var))
github_packages_url
else
var
end
@root_url_specs.merge!(specs)
end
end
def ==(other)
self.class == other.class && rebuild == other.rebuild && collector == other.collector &&
root_url == other.root_url && root_url_specs == other.root_url_specs && tap == other.tap
end
alias eql? ==
sig { params(tag: Utils::Bottles::Tag).returns(T.any(Symbol, String)) }
def tag_to_cellar(tag = Utils::Bottles.tag)
spec = collector.specification_for(tag)
if spec.present?
spec.cellar
else
tag.default_cellar
end
end
sig { params(tag: Utils::Bottles::Tag).returns(T::Boolean) }
def compatible_locations?(tag: Utils::Bottles.tag)
cellar = tag_to_cellar(tag)
return true if RELOCATABLE_CELLARS.include?(cellar)
prefix = Pathname(cellar.to_s).parent.to_s
cellar_relocatable = cellar.size >= HOMEBREW_CELLAR.to_s.size && ENV["HOMEBREW_RELOCATE_BUILD_PREFIX"].present?
prefix_relocatable = prefix.size >= HOMEBREW_PREFIX.to_s.size && ENV["HOMEBREW_RELOCATE_BUILD_PREFIX"].present?
compatible_cellar = cellar == HOMEBREW_CELLAR.to_s || cellar_relocatable
compatible_prefix = prefix == HOMEBREW_PREFIX.to_s || prefix_relocatable
compatible_cellar && compatible_prefix
end
# Does the {Bottle} this {BottleSpecification} belongs to need to be relocated?
sig { params(tag: Utils::Bottles::Tag).returns(T::Boolean) }
def skip_relocation?(tag: Utils::Bottles.tag)
spec = collector.specification_for(tag)
spec&.cellar == :any_skip_relocation
end
sig { params(tag: T.any(Symbol, Utils::Bottles::Tag), no_older_versions: T::Boolean).returns(T::Boolean) }
def tag?(tag, no_older_versions: false)
collector.tag?(tag, no_older_versions:)
end
# Checksum methods in the DSL's bottle block take
# a Hash, which indicates the platform the checksum applies on.
# Example bottle block syntax:
# bottle do
# sha256 cellar: :any_skip_relocation, big_sur: "69489ae397e4645..."
# sha256 cellar: :any, catalina: "449de5ea35d0e94..."
# end
def sha256(hash)
sha256_regex = /^[a-f0-9]{64}$/i
# find new `sha256 big_sur: "69489ae397e4645..."` format
tag, digest = hash.find do |key, value|
key.is_a?(Symbol) && value.is_a?(String) && value.match?(sha256_regex)
end
cellar = hash[:cellar] if digest && tag
tag = Utils::Bottles::Tag.from_symbol(tag)
cellar ||= tag.default_cellar
collector.add(tag, checksum: Checksum.new(digest), cellar:)
end
sig {
params(tag: Utils::Bottles::Tag, no_older_versions: T::Boolean)
.returns(T.nilable(Utils::Bottles::TagSpecification))
}
def tag_specification_for(tag, no_older_versions: false)
collector.specification_for(tag, no_older_versions:)
end
def checksums
tags = collector.tags.sort_by do |tag|
version = tag.to_macos_version
# Give `arm64` bottles a higher priority so they are first.
Fix bottle block generation and audit for arm64 Linux Before this change, `brew bottle` would add the `:arm64_linux` bottle lines last. This would make `brew style` complain because it wants the `arm64_*` bottles listed first. Let's fix this by retaining the existing style as closely as possible: - macOS bottles are listed first - for each OS, arm64 bottles are listed first (just as we do on macOS) In particular, `brew bottle` will now insert `:arm64_linux` bottle lines just above the `:x86_64_linux` bottle lines (but still below the macOS bottle lines). x86_64 may continue to be a more popular platform on Linux for quite some time. However, users looking for those bottles can continue to look in the same place as before this change (i.e., the last line of the bottle block). Taking this together with the consistency on macOS mentioned above, I think this is the right way forward here. For concreteness, here are some examples of bottle blocks before and after this change. Before this change, immediately after `brew bottle`: bottle do sha256 arm64_sequoia: "1a57e04052f4bae4172d546a7927c645fc29d2ef5fafbec19d08ee1dddc542fb" sha256 arm64_sonoma: "a58cf9af5d04d3d5709b5337f3793586087a79e178da51d1f3978c0c13b8cf34" sha256 ventura: "6d8b90b2cbb31dcb78394c6540f5454cd57232fc309921173814f880e63718f0" sha256 x86_64_linux: "cd5faac2834ba79e39429b9aac99e4f69d6e6023cbb1cbcd0b62e94cfc69bb2a" sha256 arm64_linux: "457d3e9bd0c287483e27f29a488a18c90e1f55be076fc49b07942ef396c419be" end Before this change, after doing `brew style --fix`: bottle do sha256 arm64_sequoia: "1a57e04052f4bae4172d546a7927c645fc29d2ef5fafbec19d08ee1dddc542fb" sha256 arm64_sonoma: "a58cf9af5d04d3d5709b5337f3793586087a79e178da51d1f3978c0c13b8cf34" sha256 arm64_linux: "457d3e9bd0c287483e27f29a488a18c90e1f55be076fc49b07942ef396c419be" sha256 ventura: "6d8b90b2cbb31dcb78394c6540f5454cd57232fc309921173814f880e63718f0" sha256 x86_64_linux: "cd5faac2834ba79e39429b9aac99e4f69d6e6023cbb1cbcd0b62e94cfc69bb2a" end After this change: bottle do sha256 arm64_sequoia: "1a57e04052f4bae4172d546a7927c645fc29d2ef5fafbec19d08ee1dddc542fb" sha256 arm64_sonoma: "a58cf9af5d04d3d5709b5337f3793586087a79e178da51d1f3978c0c13b8cf34" sha256 ventura: "6d8b90b2cbb31dcb78394c6540f5454cd57232fc309921173814f880e63718f0" sha256 arm64_linux: "457d3e9bd0c287483e27f29a488a18c90e1f55be076fc49b07942ef396c419be" sha256 x86_64_linux: "cd5faac2834ba79e39429b9aac99e4f69d6e6023cbb1cbcd0b62e94cfc69bb2a" end
2025-03-18 16:10:43 +08:00
priority = (tag.arch == :arm64) ? 3 : 2
"#{priority}.#{version}_#{tag}"
rescue MacOSVersion::Error
Fix bottle block generation and audit for arm64 Linux Before this change, `brew bottle` would add the `:arm64_linux` bottle lines last. This would make `brew style` complain because it wants the `arm64_*` bottles listed first. Let's fix this by retaining the existing style as closely as possible: - macOS bottles are listed first - for each OS, arm64 bottles are listed first (just as we do on macOS) In particular, `brew bottle` will now insert `:arm64_linux` bottle lines just above the `:x86_64_linux` bottle lines (but still below the macOS bottle lines). x86_64 may continue to be a more popular platform on Linux for quite some time. However, users looking for those bottles can continue to look in the same place as before this change (i.e., the last line of the bottle block). Taking this together with the consistency on macOS mentioned above, I think this is the right way forward here. For concreteness, here are some examples of bottle blocks before and after this change. Before this change, immediately after `brew bottle`: bottle do sha256 arm64_sequoia: "1a57e04052f4bae4172d546a7927c645fc29d2ef5fafbec19d08ee1dddc542fb" sha256 arm64_sonoma: "a58cf9af5d04d3d5709b5337f3793586087a79e178da51d1f3978c0c13b8cf34" sha256 ventura: "6d8b90b2cbb31dcb78394c6540f5454cd57232fc309921173814f880e63718f0" sha256 x86_64_linux: "cd5faac2834ba79e39429b9aac99e4f69d6e6023cbb1cbcd0b62e94cfc69bb2a" sha256 arm64_linux: "457d3e9bd0c287483e27f29a488a18c90e1f55be076fc49b07942ef396c419be" end Before this change, after doing `brew style --fix`: bottle do sha256 arm64_sequoia: "1a57e04052f4bae4172d546a7927c645fc29d2ef5fafbec19d08ee1dddc542fb" sha256 arm64_sonoma: "a58cf9af5d04d3d5709b5337f3793586087a79e178da51d1f3978c0c13b8cf34" sha256 arm64_linux: "457d3e9bd0c287483e27f29a488a18c90e1f55be076fc49b07942ef396c419be" sha256 ventura: "6d8b90b2cbb31dcb78394c6540f5454cd57232fc309921173814f880e63718f0" sha256 x86_64_linux: "cd5faac2834ba79e39429b9aac99e4f69d6e6023cbb1cbcd0b62e94cfc69bb2a" end After this change: bottle do sha256 arm64_sequoia: "1a57e04052f4bae4172d546a7927c645fc29d2ef5fafbec19d08ee1dddc542fb" sha256 arm64_sonoma: "a58cf9af5d04d3d5709b5337f3793586087a79e178da51d1f3978c0c13b8cf34" sha256 ventura: "6d8b90b2cbb31dcb78394c6540f5454cd57232fc309921173814f880e63718f0" sha256 arm64_linux: "457d3e9bd0c287483e27f29a488a18c90e1f55be076fc49b07942ef396c419be" sha256 x86_64_linux: "cd5faac2834ba79e39429b9aac99e4f69d6e6023cbb1cbcd0b62e94cfc69bb2a" end
2025-03-18 16:10:43 +08:00
# Sort non-macOS tags below macOS tags, and arm64 tags before other tags.
priority = (tag.arch == :arm64) ? 1 : 0
"#{priority}.#{tag}"
end
tags.reverse.map do |tag|
spec = collector.specification_for(tag)
{
"tag" => spec.tag.to_sym,
"digest" => spec.checksum,
"cellar" => spec.cellar,
}
end
end
end
require "extend/os/bottle_specification"