api_hashable: Make API path subs generic

This turns the ability to replace common paths with placeholders
into a mixin that can be used with both Casks and Formulae.

The idea here is to make formula hash generation more consistent.
This commit is contained in:
apainintheneck 2023-03-21 19:05:41 -07:00
parent d42e9b40d5
commit 38146893c3
7 changed files with 45 additions and 36 deletions

View File

@ -6,6 +6,7 @@ require "cask/config"
require "cask/dsl" require "cask/dsl"
require "cask/metadata" require "cask/metadata"
require "utils/bottles" require "utils/bottles"
require "extend/api_hashable"
module Cask module Cask
# An instance of a cask. # An instance of a cask.
@ -16,11 +17,9 @@ module Cask
extend Forwardable extend Forwardable
extend Predicable extend Predicable
extend APIHashable
include Metadata include Metadata
# Needs a leading slash to avoid `File.expand.path` complaining about non-absolute home.
HOME_PLACEHOLDER = "/$HOME"
HOMEBREW_PREFIX_PLACEHOLDER = "$HOMEBREW_PREFIX"
APPDIR_PLACEHOLDER = "$APPDIR" APPDIR_PLACEHOLDER = "$APPDIR"
# TODO: can be removed when API JSON is regenerated with HOMEBREW_PREFIX_PLACEHOLDER. # TODO: can be removed when API JSON is regenerated with HOMEBREW_PREFIX_PLACEHOLDER.
@ -31,37 +30,6 @@ module Cask
attr_predicate :loaded_from_api? attr_predicate :loaded_from_api?
class << self
def generating_hash!
return if generating_hash?
# Apply monkeypatches for API generation
@old_homebrew_prefix = HOMEBREW_PREFIX
@old_home = Dir.home
Object.send(:remove_const, :HOMEBREW_PREFIX)
Object.const_set(:HOMEBREW_PREFIX, Pathname(HOMEBREW_PREFIX_PLACEHOLDER))
ENV["HOME"] = HOME_PLACEHOLDER
@generating_hash = true
end
def generated_hash!
return unless generating_hash?
# Revert monkeypatches for API generation
Object.send(:remove_const, :HOMEBREW_PREFIX)
Object.const_set(:HOMEBREW_PREFIX, @old_homebrew_prefix)
ENV["HOME"] = @old_home
@generating_hash = false
end
def generating_hash?
@generating_hash ||= false
@generating_hash == true
end
end
def self.all def self.all
# TODO: ideally avoid using ARGV by moving to e.g. CLI::Parser # TODO: ideally avoid using ARGV by moving to e.g. CLI::Parser
if ARGV.exclude?("--eval-all") && !Homebrew::EnvConfig.eval_all? if ARGV.exclude?("--eval-all") && !Homebrew::EnvConfig.eval_all?

View File

@ -329,8 +329,8 @@ module Cask
# TODO: HOMEBREW_OLD_PREFIX_PLACEHOLDER can be removed when API JSON is # TODO: HOMEBREW_OLD_PREFIX_PLACEHOLDER can be removed when API JSON is
# regenerated with HOMEBREW_PREFIX_PLACEHOLDER. # regenerated with HOMEBREW_PREFIX_PLACEHOLDER.
string.to_s string.to_s
.gsub(Cask::HOME_PLACEHOLDER, Dir.home) .gsub(HOMEBREW_HOME_PLACEHOLDER, Dir.home)
.gsub(Cask::HOMEBREW_PREFIX_PLACEHOLDER, HOMEBREW_PREFIX) .gsub(HOMEBREW_PREFIX_PLACEHOLDER, HOMEBREW_PREFIX)
.gsub(Cask::APPDIR_PLACEHOLDER, appdir) .gsub(Cask::APPDIR_PLACEHOLDER, appdir)
.gsub(Cask::HOMEBREW_OLD_PREFIX_PLACEHOLDER, HOMEBREW_PREFIX) .gsub(Cask::HOMEBREW_OLD_PREFIX_PLACEHOLDER, HOMEBREW_PREFIX)
end end

View File

@ -50,6 +50,7 @@ module Homebrew
FileUtils.mkdir_p directories FileUtils.mkdir_p directories
Formulary.enable_factory_cache! Formulary.enable_factory_cache!
Formula.generating_hash!
tap.formula_names.each do |name| tap.formula_names.each do |name|
formula = Formulary.factory(name) formula = Formulary.factory(name)

View File

@ -0,0 +1,34 @@
# typed: true
# frozen_string_literal: true
# Used to substitute common paths with generic placeholders when generating JSON for the API.
module APIHashable
def generating_hash!
return if generating_hash?
# Apply monkeypatches for API generation
@old_homebrew_prefix = HOMEBREW_PREFIX
@old_home = Dir.home
Object.send(:remove_const, :HOMEBREW_PREFIX)
Object.const_set(:HOMEBREW_PREFIX, Pathname.new(HOMEBREW_PREFIX_PLACEHOLDER))
ENV["HOME"] = HOMEBREW_HOME_PLACEHOLDER
@generating_hash = true
end
def generated_hash!
return unless generating_hash?
# Revert monkeypatches for API generation
Object.send(:remove_const, :HOMEBREW_PREFIX)
Object.const_set(:HOMEBREW_PREFIX, @old_homebrew_prefix)
ENV["HOME"] = @old_home
@generating_hash = false
end
def generating_hash?
@generating_hash ||= false
@generating_hash == true
end
end

View File

@ -30,6 +30,7 @@ require "find"
require "utils/spdx" require "utils/spdx"
require "extend/on_system" require "extend/on_system"
require "api" require "api"
require "extend/api_hashable"
# A formula provides instructions and metadata for Homebrew to install a piece # A formula provides instructions and metadata for Homebrew to install a piece
# of software. Every Homebrew formula is a {Formula}. # of software. Every Homebrew formula is a {Formula}.
@ -69,6 +70,7 @@ class Formula
extend Forwardable extend Forwardable
extend Cachable extend Cachable
extend Predicable extend Predicable
extend APIHashable
# The name of this {Formula}. # The name of this {Formula}.
# e.g. `this-formula` # e.g. `this-formula`

View File

@ -58,6 +58,8 @@ HOMEBREW_MACOS_ARM_DEFAULT_REPOSITORY = ENV.fetch("HOMEBREW_MACOS_ARM_DEFAULT_RE
HOMEBREW_LINUX_DEFAULT_PREFIX = ENV.fetch("HOMEBREW_LINUX_DEFAULT_PREFIX").freeze HOMEBREW_LINUX_DEFAULT_PREFIX = ENV.fetch("HOMEBREW_LINUX_DEFAULT_PREFIX").freeze
HOMEBREW_LINUX_DEFAULT_REPOSITORY = ENV.fetch("HOMEBREW_LINUX_DEFAULT_REPOSITORY").freeze HOMEBREW_LINUX_DEFAULT_REPOSITORY = ENV.fetch("HOMEBREW_LINUX_DEFAULT_REPOSITORY").freeze
HOMEBREW_PREFIX_PLACEHOLDER = "$HOMEBREW_PREFIX" HOMEBREW_PREFIX_PLACEHOLDER = "$HOMEBREW_PREFIX"
# Needs a leading slash to avoid `File.expand.path` complaining about non-absolute home.
HOMEBREW_HOME_PLACEHOLDER = "/$HOME"
HOMEBREW_MACOS_NEWEST_UNSUPPORTED = ENV.fetch("HOMEBREW_MACOS_NEWEST_UNSUPPORTED").freeze HOMEBREW_MACOS_NEWEST_UNSUPPORTED = ENV.fetch("HOMEBREW_MACOS_NEWEST_UNSUPPORTED").freeze
HOMEBREW_MACOS_OLDEST_SUPPORTED = ENV.fetch("HOMEBREW_MACOS_OLDEST_SUPPORTED").freeze HOMEBREW_MACOS_OLDEST_SUPPORTED = ENV.fetch("HOMEBREW_MACOS_OLDEST_SUPPORTED").freeze

View File

@ -337,6 +337,8 @@ describe Cask::Cask, :cask do
expect(JSON.pretty_generate(h["variations"])).to eq expected_sha256_variations.strip expect(JSON.pretty_generate(h["variations"])).to eq expected_sha256_variations.strip
end end
# @note The calls to `APIHashable.generating_hash!` and `APIHashable.generated_hash!`
# are not idempotent so they can only be used in one test.
it "returns the correct hash placeholders" do it "returns the correct hash placeholders" do
described_class.generating_hash! described_class.generating_hash!
expect(described_class).to be_generating_hash expect(described_class).to be_generating_hash