diff --git a/Library/Homebrew/bottle.rb b/Library/Homebrew/bottle.rb new file mode 100644 index 0000000000..6aa2aa3f26 --- /dev/null +++ b/Library/Homebrew/bottle.rb @@ -0,0 +1,219 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +class Bottle + include Downloadable + + class Filename + attr_reader :name, :version, :tag, :rebuild + + sig { params(formula: Formula, tag: Utils::Bottles::Tag, rebuild: Integer).returns(T.attached_class) } + def self.create(formula, tag, rebuild) + new(formula.name, formula.pkg_version, tag, rebuild) + end + + sig { params(name: String, version: PkgVersion, tag: Utils::Bottles::Tag, rebuild: Integer).void } + def initialize(name, version, tag, rebuild) + @name = File.basename name + + raise ArgumentError, "Invalid bottle name" unless Utils.safe_filename?(@name) + raise ArgumentError, "Invalid bottle version" unless Utils.safe_filename?(version.to_s) + + @version = version + @tag = tag.to_unstandardized_sym.to_s + @rebuild = rebuild + end + + sig { returns(String) } + def to_str + "#{name}--#{version}#{extname}" + end + + sig { returns(String) } + def to_s = to_str + + sig { returns(String) } + def json + "#{name}--#{version}.#{tag}.bottle.json" + end + + def url_encode + ERB::Util.url_encode("#{name}-#{version}#{extname}") + end + + def github_packages + "#{name}--#{version}#{extname}" + end + + sig { returns(String) } + def extname + s = rebuild.positive? ? ".#{rebuild}" : "" + ".#{tag}.bottle#{s}.tar.gz" + end + end + + extend Forwardable + + attr_reader :name, :resource, :tag, :cellar, :rebuild + + def_delegators :resource, :url, :verify_download_integrity + def_delegators :resource, :cached_download, :downloader + + def initialize(formula, spec, tag = nil) + super() + + @name = formula.name + @resource = Resource.new + @resource.owner = formula + @spec = spec + + tag_spec = spec.tag_specification_for(Utils::Bottles.tag(tag)) + + @tag = tag_spec.tag + @cellar = tag_spec.cellar + @rebuild = spec.rebuild + + @resource.version(formula.pkg_version.to_s) + @resource.checksum = tag_spec.checksum + + @fetch_tab_retried = false + + root_url(spec.root_url, spec.root_url_specs) + end + + sig { + override.params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T.nilable(T::Boolean), + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) + resource.fetch(verify_download_integrity:, timeout:, quiet:) + rescue DownloadError + raise unless fallback_on_error + + fetch_tab + retry + end + + sig { override.void } + def clear_cache + @resource.clear_cache + github_packages_manifest_resource&.clear_cache + @fetch_tab_retried = false + end + + def compatible_locations? + @spec.compatible_locations?(tag: @tag) + end + + # Does the bottle need to be relocated? + def skip_relocation? + @spec.skip_relocation?(tag: @tag) + end + + def stage = downloader.stage + + def fetch_tab(timeout: nil, quiet: false) + return unless (resource = github_packages_manifest_resource) + + begin + resource.fetch(timeout:, quiet:) + rescue DownloadError + raise unless fallback_on_error + + retry + rescue Resource::BottleManifest::Error + raise if @fetch_tab_retried + + @fetch_tab_retried = true + resource.clear_cache + retry + end + end + + def tab_attributes + if (resource = github_packages_manifest_resource) && resource.downloaded? + return resource.tab + end + + {} + end + + sig { returns(T.nilable(Integer)) } + def bottle_size + resource = github_packages_manifest_resource + return unless resource&.downloaded? + + resource.bottle_size + end + + sig { returns(T.nilable(Integer)) } + def installed_size + resource = github_packages_manifest_resource + return unless resource&.downloaded? + + resource.installed_size + end + + sig { returns(Filename) } + def filename + Filename.create(resource.owner, @tag, @spec.rebuild) + end + + sig { returns(T.nilable(Resource::BottleManifest)) } + def github_packages_manifest_resource + return if @resource.download_strategy != CurlGitHubPackagesDownloadStrategy + + @github_packages_manifest_resource ||= begin + resource = Resource::BottleManifest.new(self) + + version_rebuild = GitHubPackages.version_rebuild(@resource.version, rebuild) + resource.version(version_rebuild) + + image_name = GitHubPackages.image_formula_name(@name) + image_tag = GitHubPackages.image_version_rebuild(version_rebuild) + resource.url( + "#{root_url}/#{image_name}/manifests/#{image_tag}", + using: CurlGitHubPackagesDownloadStrategy, + headers: ["Accept: application/vnd.oci.image.index.v1+json"], + ) + T.cast(resource.downloader, CurlGitHubPackagesDownloadStrategy).resolved_basename = + "#{name}-#{version_rebuild}.bottle_manifest.json" + resource + end + end + + private + + def select_download_strategy(specs) + specs[:using] ||= DownloadStrategyDetector.detect(@root_url) + specs[:bottle] = true + specs + end + + def fallback_on_error + # Use the default bottle domain as a fallback mirror + if @resource.url.start_with?(Homebrew::EnvConfig.bottle_domain) && + Homebrew::EnvConfig.bottle_domain != HOMEBREW_BOTTLE_DEFAULT_DOMAIN + opoo "Bottle missing, falling back to the default domain..." + root_url(HOMEBREW_BOTTLE_DEFAULT_DOMAIN) + @github_packages_manifest_resource = nil + true + else + false + end + end + + def root_url(val = nil, specs = {}) + return @root_url if val.nil? + + @root_url = val + + filename = Filename.create(resource.owner, @tag, @spec.rebuild) + path, resolved_basename = Utils::Bottles.path_resolved_basename(val, name, resource.checksum, filename) + @resource.url("#{val}/#{path}", **select_download_strategy(specs)) + @resource.downloader.resolved_basename = resolved_basename if resolved_basename.present? + end +end diff --git a/Library/Homebrew/bottle_specification.rb b/Library/Homebrew/bottle_specification.rb new file mode 100644 index 0000000000..556659a8ee --- /dev/null +++ b/Library/Homebrew/bottle_specification.rb @@ -0,0 +1,135 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +class BottleSpecification + extend Attrable + RELOCATABLE_CELLARS = [:any, :any_skip_relocation].freeze + + attr_rw :rebuild + 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 + + 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. + priority = (tag.arch == :arm64) ? 2 : 1 + "#{priority}.#{version}_#{tag}" + rescue MacOSVersion::Error + # Sort non-macOS tags below macOS tags. + "0.#{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" diff --git a/Library/Homebrew/extend/os/bottle_specification.rb b/Library/Homebrew/extend/os/bottle_specification.rb new file mode 100644 index 0000000000..9e18d61961 --- /dev/null +++ b/Library/Homebrew/extend/os/bottle_specification.rb @@ -0,0 +1,4 @@ +# typed: strict +# frozen_string_literal: true + +require "extend/os/linux/bottle_specification" if OS.linux? diff --git a/Library/Homebrew/extend/os/linux/software_spec.rb b/Library/Homebrew/extend/os/linux/bottle_specification.rb similarity index 100% rename from Library/Homebrew/extend/os/linux/software_spec.rb rename to Library/Homebrew/extend/os/linux/bottle_specification.rb diff --git a/Library/Homebrew/extend/os/software_spec.rb b/Library/Homebrew/extend/os/software_spec.rb deleted file mode 100644 index 1e6f8f529c..0000000000 --- a/Library/Homebrew/extend/os/software_spec.rb +++ /dev/null @@ -1,4 +0,0 @@ -# typed: strict -# frozen_string_literal: true - -require "extend/os/linux/software_spec" if OS.linux? diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 575c2fd4bd..4dbd9124f1 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -19,6 +19,10 @@ require "build_environment" require "build_options" require "formulary" require "software_spec" +require "bottle" +require "pour_bottle_check" +require "head_software_spec" +require "bottle_specification" require "livecheck" require "service" require "install_renamed" diff --git a/Library/Homebrew/head_software_spec.rb b/Library/Homebrew/head_software_spec.rb new file mode 100644 index 0000000000..cb7498b713 --- /dev/null +++ b/Library/Homebrew/head_software_spec.rb @@ -0,0 +1,15 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +require "software_spec" + +class HeadSoftwareSpec < SoftwareSpec + def initialize(flags: []) + super + @resource.version(Version.new("HEAD")) + end + + def verify_download_integrity(_filename) + # no-op + end +end diff --git a/Library/Homebrew/pour_bottle_check.rb b/Library/Homebrew/pour_bottle_check.rb new file mode 100644 index 0000000000..3ec8bb8a2d --- /dev/null +++ b/Library/Homebrew/pour_bottle_check.rb @@ -0,0 +1,18 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +class PourBottleCheck + include OnSystem::MacOSAndLinux + + def initialize(formula) + @formula = formula + end + + def reason(reason) + @formula.pour_bottle_check_unsatisfied_reason = reason + end + + def satisfy(&block) + @formula.send(:define_method, :pour_bottle?, &block) + end +end diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index f8a4a981e9..bd5974db22 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -284,380 +284,3 @@ class SoftwareSpec end end end - -class HeadSoftwareSpec < SoftwareSpec - def initialize(flags: []) - super - @resource.version(Version.new("HEAD")) - end - - def verify_download_integrity(_filename) - # no-op - end -end - -class Bottle - include Downloadable - - class Filename - attr_reader :name, :version, :tag, :rebuild - - sig { params(formula: Formula, tag: Utils::Bottles::Tag, rebuild: Integer).returns(T.attached_class) } - def self.create(formula, tag, rebuild) - new(formula.name, formula.pkg_version, tag, rebuild) - end - - sig { params(name: String, version: PkgVersion, tag: Utils::Bottles::Tag, rebuild: Integer).void } - def initialize(name, version, tag, rebuild) - @name = File.basename name - - raise ArgumentError, "Invalid bottle name" unless Utils.safe_filename?(@name) - raise ArgumentError, "Invalid bottle version" unless Utils.safe_filename?(version.to_s) - - @version = version - @tag = tag.to_unstandardized_sym.to_s - @rebuild = rebuild - end - - sig { returns(String) } - def to_str - "#{name}--#{version}#{extname}" - end - - sig { returns(String) } - def to_s = to_str - - sig { returns(String) } - def json - "#{name}--#{version}.#{tag}.bottle.json" - end - - def url_encode - ERB::Util.url_encode("#{name}-#{version}#{extname}") - end - - def github_packages - "#{name}--#{version}#{extname}" - end - - sig { returns(String) } - def extname - s = rebuild.positive? ? ".#{rebuild}" : "" - ".#{tag}.bottle#{s}.tar.gz" - end - end - - extend Forwardable - - attr_reader :name, :resource, :tag, :cellar, :rebuild - - def_delegators :resource, :url, :verify_download_integrity - def_delegators :resource, :cached_download, :downloader - - def initialize(formula, spec, tag = nil) - super() - - @name = formula.name - @resource = Resource.new - @resource.owner = formula - @spec = spec - - tag_spec = spec.tag_specification_for(Utils::Bottles.tag(tag)) - - @tag = tag_spec.tag - @cellar = tag_spec.cellar - @rebuild = spec.rebuild - - @resource.version(formula.pkg_version.to_s) - @resource.checksum = tag_spec.checksum - - @fetch_tab_retried = false - - root_url(spec.root_url, spec.root_url_specs) - end - - sig { - override.params( - verify_download_integrity: T::Boolean, - timeout: T.nilable(T.any(Integer, Float)), - quiet: T.nilable(T::Boolean), - ).returns(Pathname) - } - def fetch(verify_download_integrity: true, timeout: nil, quiet: false) - resource.fetch(verify_download_integrity:, timeout:, quiet:) - rescue DownloadError - raise unless fallback_on_error - - fetch_tab - retry - end - - sig { override.void } - def clear_cache - @resource.clear_cache - github_packages_manifest_resource&.clear_cache - @fetch_tab_retried = false - end - - def compatible_locations? - @spec.compatible_locations?(tag: @tag) - end - - # Does the bottle need to be relocated? - def skip_relocation? - @spec.skip_relocation?(tag: @tag) - end - - def stage = downloader.stage - - def fetch_tab(timeout: nil, quiet: false) - return unless (resource = github_packages_manifest_resource) - - begin - resource.fetch(timeout:, quiet:) - rescue DownloadError - raise unless fallback_on_error - - retry - rescue Resource::BottleManifest::Error - raise if @fetch_tab_retried - - @fetch_tab_retried = true - resource.clear_cache - retry - end - end - - def tab_attributes - if (resource = github_packages_manifest_resource) && resource.downloaded? - return resource.tab - end - - {} - end - - sig { returns(T.nilable(Integer)) } - def bottle_size - resource = github_packages_manifest_resource - return unless resource&.downloaded? - - resource.bottle_size - end - - sig { returns(T.nilable(Integer)) } - def installed_size - resource = github_packages_manifest_resource - return unless resource&.downloaded? - - resource.installed_size - end - - sig { returns(Filename) } - def filename - Filename.create(resource.owner, @tag, @spec.rebuild) - end - - sig { returns(T.nilable(Resource::BottleManifest)) } - def github_packages_manifest_resource - return if @resource.download_strategy != CurlGitHubPackagesDownloadStrategy - - @github_packages_manifest_resource ||= begin - resource = Resource::BottleManifest.new(self) - - version_rebuild = GitHubPackages.version_rebuild(@resource.version, rebuild) - resource.version(version_rebuild) - - image_name = GitHubPackages.image_formula_name(@name) - image_tag = GitHubPackages.image_version_rebuild(version_rebuild) - resource.url( - "#{root_url}/#{image_name}/manifests/#{image_tag}", - using: CurlGitHubPackagesDownloadStrategy, - headers: ["Accept: application/vnd.oci.image.index.v1+json"], - ) - T.cast(resource.downloader, CurlGitHubPackagesDownloadStrategy).resolved_basename = - "#{name}-#{version_rebuild}.bottle_manifest.json" - resource - end - end - - private - - def select_download_strategy(specs) - specs[:using] ||= DownloadStrategyDetector.detect(@root_url) - specs[:bottle] = true - specs - end - - def fallback_on_error - # Use the default bottle domain as a fallback mirror - if @resource.url.start_with?(Homebrew::EnvConfig.bottle_domain) && - Homebrew::EnvConfig.bottle_domain != HOMEBREW_BOTTLE_DEFAULT_DOMAIN - opoo "Bottle missing, falling back to the default domain..." - root_url(HOMEBREW_BOTTLE_DEFAULT_DOMAIN) - @github_packages_manifest_resource = nil - true - else - false - end - end - - def root_url(val = nil, specs = {}) - return @root_url if val.nil? - - @root_url = val - - filename = Filename.create(resource.owner, @tag, @spec.rebuild) - path, resolved_basename = Utils::Bottles.path_resolved_basename(val, name, resource.checksum, filename) - @resource.url("#{val}/#{path}", **select_download_strategy(specs)) - @resource.downloader.resolved_basename = resolved_basename if resolved_basename.present? - end -end - -class BottleSpecification - extend Attrable - RELOCATABLE_CELLARS = [:any, :any_skip_relocation].freeze - - attr_rw :rebuild - 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 - - 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. - priority = (tag.arch == :arm64) ? 2 : 1 - "#{priority}.#{version}_#{tag}" - rescue MacOSVersion::Error - # Sort non-macOS tags below macOS tags. - "0.#{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 - -class PourBottleCheck - include OnSystem::MacOSAndLinux - - def initialize(formula) - @formula = formula - end - - def reason(reason) - @formula.pour_bottle_check_unsatisfied_reason = reason - end - - def satisfy(&block) - @formula.send(:define_method, :pour_bottle?, &block) - end -end - -require "extend/os/software_spec" diff --git a/Library/Homebrew/test/software_spec/bottle_spec.rb b/Library/Homebrew/test/bottle_spec.rb similarity index 94% rename from Library/Homebrew/test/software_spec/bottle_spec.rb rename to Library/Homebrew/test/bottle_spec.rb index e6d8d9928a..2e49cb3f61 100644 --- a/Library/Homebrew/test/software_spec/bottle_spec.rb +++ b/Library/Homebrew/test/bottle_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "software_spec" +require "bottle_specification" require "test/support/fixtures/testball_bottle" RSpec.describe Bottle do diff --git a/Library/Homebrew/test/software_spec/bottle_specification_spec.rb b/Library/Homebrew/test/bottle_specification_spec.rb similarity index 98% rename from Library/Homebrew/test/software_spec/bottle_specification_spec.rb rename to Library/Homebrew/test/bottle_specification_spec.rb index 98aa029bcd..cb2c82fd7d 100644 --- a/Library/Homebrew/test/software_spec/bottle_specification_spec.rb +++ b/Library/Homebrew/test/bottle_specification_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "software_spec" +require "bottle_specification" RSpec.describe BottleSpecification do subject(:bottle_spec) { described_class.new } diff --git a/Library/Homebrew/test/software_spec/head_spec.rb b/Library/Homebrew/test/head_software_spec_spec.rb similarity index 91% rename from Library/Homebrew/test/software_spec/head_spec.rb rename to Library/Homebrew/test/head_software_spec_spec.rb index eee9e59676..4e1d1021bc 100644 --- a/Library/Homebrew/test/software_spec/head_spec.rb +++ b/Library/Homebrew/test/head_software_spec_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "software_spec" +require "head_software_spec" RSpec.describe HeadSoftwareSpec do subject(:head_spec) { described_class.new }