From d64de40e52387a0e0c8f1d67791f718b9968a830 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sat, 10 Feb 2024 22:24:36 -0800 Subject: [PATCH 1/8] Update api code to load internal JSON v3 file --- Library/Homebrew/api.rb | 7 ++++ Library/Homebrew/api/formula.rb | 51 ++++++++++++++++++++++------- Library/Homebrew/extend/cachable.rb | 5 +++ Library/Homebrew/tap.rb | 2 ++ 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/Library/Homebrew/api.rb b/Library/Homebrew/api.rb index df733d69dd193..13a411987d02b 100644 --- a/Library/Homebrew/api.rb +++ b/Library/Homebrew/api.rb @@ -184,6 +184,13 @@ def self.tap_from_source_download(path) Tap.fetch(org, repo) end + + sig { returns(T::Boolean) } + def self.internal_json_v3? + return @internal_json_v3 if defined?(@internal_json_v3) + + @internal_json_v3 = ENV["HOMEBREW_INTERNAL_JSON_V3"].present? + end end # @api private diff --git a/Library/Homebrew/api/formula.rb b/Library/Homebrew/api/formula.rb index e9747c1ba420c..d27e963eff5b4 100644 --- a/Library/Homebrew/api/formula.rb +++ b/Library/Homebrew/api/formula.rb @@ -39,19 +39,24 @@ def self.source_download(formula) sig { returns(T::Boolean) } def self.download_and_cache_data! - json_formulae, updated = Homebrew::API.fetch_json_api_file "formula.jws.json" - - cache["aliases"] = {} - cache["renames"] = {} - cache["formulae"] = json_formulae.to_h do |json_formula| - json_formula["aliases"].each do |alias_name| - cache["aliases"][alias_name] = json_formula["name"] - end - (json_formula["oldnames"] || [json_formula["oldname"]].compact).each do |oldname| - cache["renames"][oldname] = json_formula["name"] + if Homebrew::API.internal_json_v3? + json_formulae, updated = Homebrew::API.fetch_json_api_file "internal/v3/homebrew-core.jws.json" + overwrite_cache! T.cast(json_formulae, T::Hash[String, T.untyped]) + else + json_formulae, updated = Homebrew::API.fetch_json_api_file "formula.jws.json" + + cache["aliases"] = {} + cache["renames"] = {} + cache["formulae"] = json_formulae.to_h do |json_formula| + json_formula["aliases"].each do |alias_name| + cache["aliases"][alias_name] = json_formula["name"] + end + (json_formula["oldnames"] || [json_formula["oldname"]].compact).each do |oldname| + cache["renames"][oldname] = json_formula["name"] + end + + [json_formula["name"], json_formula.except("name")] end - - [json_formula["name"], json_formula.except("name")] end updated @@ -88,6 +93,28 @@ def self.all_renames cache["renames"] end + sig { returns(Hash) } + def self.tap_migrations + # Not sure that we need to reload here. + unless cache.key?("tap_migrations") + json_updated = download_and_cache_data! + write_names_and_aliases(regenerate: json_updated) + end + + cache["tap_migrations"] + end + + sig { returns(String) } + def self.tap_git_head + # Note sure we need to reload here. + unless cache.key?("tap_git_head") + json_updated = download_and_cache_data! + write_names_and_aliases(regenerate: json_updated) + end + + cache["tap_git_head"] + end + sig { params(regenerate: T::Boolean).void } def self.write_names_and_aliases(regenerate: false) download_and_cache_data! unless cache.key?("formulae") diff --git a/Library/Homebrew/extend/cachable.rb b/Library/Homebrew/extend/cachable.rb index b124c638e63ab..785dff4c573a5 100644 --- a/Library/Homebrew/extend/cachable.rb +++ b/Library/Homebrew/extend/cachable.rb @@ -7,6 +7,11 @@ def cache @cache ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped])) end + sig { params(hash: T.nilable(T::Hash[T.untyped, T.untyped])).void } + def overwrite_cache!(hash) + @cache = hash + end + sig { void } def clear_cache cache.clear diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index 60df907f123fa..568e155706efc 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -1101,6 +1101,8 @@ def tap_migrations @tap_migrations ||= if Homebrew::EnvConfig.no_install_from_api? ensure_installed! super + elsif Homebrew::API.internal_json_v3? + Homebrew::API::Formula.tap_migrations else migrations, = Homebrew::API.fetch_json_api_file "formula_tap_migrations.jws.json", stale_seconds: TAP_MIGRATIONS_STALE_SECONDS From 670e2188d7d95d47e78c14eb9af796be4a888171 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sat, 10 Feb 2024 23:00:38 -0800 Subject: [PATCH 2/8] formulary: update api loader to load internal json v3 --- Library/Homebrew/formulary.rb | 37 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 41e443fe63baa..0681db1951954 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -251,8 +251,8 @@ def self.load_formula_from_api(name, flags:) desc json_formula["desc"] homepage json_formula["homepage"] license SPDX.string_to_license_expression(json_formula["license"]) - revision json_formula["revision"] - version_scheme json_formula["version_scheme"] + revision json_formula.fetch("revision", 0) + version_scheme json_formula.fetch("version_scheme", 0) if (urls_stable = json_formula["urls"]["stable"].presence) stable do @@ -262,7 +262,7 @@ def self.load_formula_from_api(name, flags:) using: urls_stable["using"]&.to_sym, }.compact url urls_stable["url"], **url_spec - version json_formula["versions"]["stable"] + version Homebrew::API.internal_json_v3? ? json_formula["version"] : json_formula["versions"]["stable"] sha256 urls_stable["checksum"] if urls_stable["checksum"].present? instance_exec(:stable, &add_deps) @@ -289,7 +289,13 @@ def self.load_formula_from_api(name, flags:) end end - if (bottles_stable = json_formula["bottle"]["stable"].presence) + bottles_stable = if Homebrew::API.internal_json_v3? + json_formula["bottle"] + else + json_formula["bottle"]["stable"] + end.presence + + if bottles_stable bottle do if Homebrew::EnvConfig.bottle_domain == HOMEBREW_BOTTLE_DEFAULT_DOMAIN root_url HOMEBREW_BOTTLE_DEFAULT_DOMAIN @@ -373,19 +379,26 @@ def caveats &.gsub(HOMEBREW_HOME_PLACEHOLDER, Dir.home) end - @tap_git_head_string = json_formula["tap_git_head"] + @tap_git_head_string = if Homebrew::API.internal_json_v3? + Homebrew::API::Formula.tap_git_head + else + json_formula["tap_git_head"] + end + def tap_git_head self.class.instance_variable_get(:@tap_git_head_string) end - @oldnames_array = json_formula["oldnames"] || [json_formula["oldname"]].compact - def oldnames - self.class.instance_variable_get(:@oldnames_array) - end + unless Homebrew::API.internal_json_v3? + @oldnames_array = json_formula["oldnames"] || [json_formula["oldname"]].compact + def oldnames + self.class.instance_variable_get(:@oldnames_array) + end - @aliases_array = json_formula.fetch("aliases", []) - def aliases - self.class.instance_variable_get(:@aliases_array) + @aliases_array = json_formula.fetch("aliases", []) + def aliases + self.class.instance_variable_get(:@aliases_array) + end end @versioned_formulae_array = json_formula.fetch("versioned_formulae", []) From cefd3273cc5d37540e4789ffbf98fb54bdb182e2 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sat, 17 Feb 2024 14:53:26 -0800 Subject: [PATCH 3/8] tap: Add helper to generate core formula API hash This abstracts away this helper to make it easier to test and reason about. --- .../Homebrew/dev-cmd/generate-formula-api.rb | 13 +------------ Library/Homebrew/tap.rb | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Library/Homebrew/dev-cmd/generate-formula-api.rb b/Library/Homebrew/dev-cmd/generate-formula-api.rb index bf149c8c317c7..9926fd04f5a4a 100644 --- a/Library/Homebrew/dev-cmd/generate-formula-api.rb +++ b/Library/Homebrew/dev-cmd/generate-formula-api.rb @@ -58,14 +58,6 @@ def generate_formula_api Formulary.enable_factory_cache! Formula.generating_hash! - homebrew_core_tap_hash = { - "tap_git_head" => tap.git_head, - "aliases" => tap.alias_table, - "renames" => tap.formula_renames, - "tap_migrations" => tap.tap_migrations, - "formulae" => {}, - } - tap.formula_names.each do |name| formula = Formulary.factory(name) name = formula.name @@ -77,15 +69,12 @@ def generate_formula_api File.write("api/formula/#{name}.json", FORMULA_JSON_TEMPLATE) File.write("formula/#{name}.html", html_template_name) end - - homebrew_core_tap_hash["formulae"][formula.name] = - formula.to_hash_with_variations(hash_method: :to_api_hash) rescue onoe "Error while generating data for formula '#{name}'." raise end - homebrew_core_tap_json = JSON.generate(homebrew_core_tap_hash) + homebrew_core_tap_json = JSON.generate(tap.to_api_hash) File.write("api/internal/v3/homebrew-core.json", homebrew_core_tap_json) unless args.dry_run? canonical_json = JSON.pretty_generate(tap.formula_renames.merge(tap.alias_table)) File.write("_data/formula_canonical.json", "#{canonical_json}\n") unless args.dry_run? diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index 568e155706efc..0f444b1153643 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -1190,6 +1190,23 @@ def formula_files_by_name hash[name] = Pathname(new_path) if existing_path.nil? || existing_path.to_s.length < new_path.length end end + + sig { returns(T::Hash[String, T.untyped]) } + def to_api_hash + formulae_api_hash = formula_names.to_h do |name| + formula = Formulary.factory(name) + formula_hash = formula.to_hash_with_variations(hash_method: :to_api_hash) + [name, formula_hash] + end + + { + "tap_git_head" => git_head, + "aliases" => alias_table, + "renames" => formula_renames, + "tap_migrations" => tap_migrations, + "formulae" => formulae_api_hash, + } + end end # A specialized {Tap} class for homebrew-cask. From e9a05d896afddc610be860b531b332b0c7c79c9c Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sat, 17 Feb 2024 17:16:16 -0800 Subject: [PATCH 4/8] cachable: make #overwrite_cache! private --- Library/Homebrew/extend/cachable.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Library/Homebrew/extend/cachable.rb b/Library/Homebrew/extend/cachable.rb index 785dff4c573a5..6472cca03f25d 100644 --- a/Library/Homebrew/extend/cachable.rb +++ b/Library/Homebrew/extend/cachable.rb @@ -7,13 +7,15 @@ def cache @cache ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped])) end - sig { params(hash: T.nilable(T::Hash[T.untyped, T.untyped])).void } - def overwrite_cache!(hash) - @cache = hash - end - sig { void } def clear_cache cache.clear end + + private + + sig { params(hash: T::Hash[T.untyped, T.untyped]).void } + def overwrite_cache!(hash) + @cache = hash + end end From 200fe2a6b71a35c6e44a147f9ab8ee3f9ed64564 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sun, 18 Feb 2024 19:28:44 -0800 Subject: [PATCH 5/8] api/formula: Add tests for internal JSON v3 These tests cover both generating and loading formulae from the JSON bundle. The tests are not comprehensive but they do provide a nice sanity check that things are working as expected. --- Library/Homebrew/api.rb | 4 +- .../api/internal_tap_json/formula_spec.rb | 127 ++++++++++++++++++ .../internal_tap_json/homebrew-core.json | 1 + .../homebrew-core/Formula/f/fennel.rb | 25 ++++ .../homebrew-core/Formula/p/ponyc.rb | 60 +++++++++ .../homebrew-core/formula_renames.json | 7 + .../homebrew-core/tap_migrations.json | 7 + 7 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 Library/Homebrew/test/api/internal_tap_json/formula_spec.rb create mode 100644 Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core.json create mode 100644 Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/Formula/f/fennel.rb create mode 100644 Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/Formula/p/ponyc.rb create mode 100644 Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/formula_renames.json create mode 100644 Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/tap_migrations.json diff --git a/Library/Homebrew/api.rb b/Library/Homebrew/api.rb index 13a411987d02b..1f194c59564a3 100644 --- a/Library/Homebrew/api.rb +++ b/Library/Homebrew/api.rb @@ -187,9 +187,7 @@ def self.tap_from_source_download(path) sig { returns(T::Boolean) } def self.internal_json_v3? - return @internal_json_v3 if defined?(@internal_json_v3) - - @internal_json_v3 = ENV["HOMEBREW_INTERNAL_JSON_V3"].present? + ENV["HOMEBREW_INTERNAL_JSON_V3"].present? end end diff --git a/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb b/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb new file mode 100644 index 0000000000000..e49d7f1de64a0 --- /dev/null +++ b/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +RSpec.describe "Internal Tap JSON -- Formula" do + let(:internal_tap_json) { File.read(TEST_FIXTURE_DIR/"internal_tap_json/homebrew-core.json").chomp } + let(:tap_git_head) { "9977471165641744a829d3e494fa563407503297" } + + context "when generating JSON", :needs_macos do + before do + cp_r(TEST_FIXTURE_DIR/"internal_tap_json/homebrew-core", Tap::TAP_DIRECTORY/"homebrew") + + # NOTE: Symlinks can't be copied recursively so we create them manually here. + (Tap::TAP_DIRECTORY/"homebrew/homebrew-core").tap do |core_tap| + mkdir(core_tap/"Aliases") + ln_s(core_tap/"Formula/f/fennel.rb", core_tap/"Aliases/fennel-lang") + ln_s(core_tap/"Formula/p/ponyc.rb", core_tap/"Aliases/ponyc-lang") + end + end + + it "creates the expected hash" do + api_hash = CoreTap.instance.to_api_hash + api_hash["tap_git_head"] = tap_git_head # tricky to mock + + expect(JSON.generate(api_hash)).to eq(internal_tap_json) + end + end + + context "when loading JSON" do + before do + ENV["HOMEBREW_INTERNAL_JSON_V3"] = "1" + ENV.delete("HOMEBREW_NO_INSTALL_FROM_API") + + allow(Homebrew::API).to receive(:fetch_json_api_file) + .with("internal/v3/homebrew-core.jws.json") + .and_return(JSON.parse(internal_tap_json), false) + end + + it "loads tap aliases" do + expect(CoreTap.instance.alias_table).to eq({ + "fennel-lang" => "fennel", + "ponyc-lang" => "ponyc", + }) + end + + it "loads formula renames" do + expect(CoreTap.instance.formula_renames).to eq({ + "advancemenu" => "advancemame", + "amtk" => "libgedit-amtk", + "annie" => "lux", + "antlr2" => "antlr@2", + "romanesco" => "fennel", + }) + end + + it "loads tap migrations" do + expect(CoreTap.instance.tap_migrations).to eq({ + "adobe-air-sdk" => "homebrew/cask", + "android-ndk" => "homebrew/cask", + "android-platform-tools" => "homebrew/cask", + "android-sdk" => "homebrew/cask", + "app-engine-go-32" => "homebrew/cask/google-cloud-sdk", + }) + end + + it "loads tap git head" do + expect(Homebrew::API::Formula.tap_git_head) + .to eq(tap_git_head) + end + + context "when loading formulae" do + let(:fennel_metadata) do + { + "dependencies" => ["lua"], + "desc" => "Lua Lisp Language", + "full_name" => "fennel", + "homepage" => "https://fennel-lang.org", + "license" => "MIT", + "name" => "fennel", + "ruby_source_path" => "Formula/f/fennel.rb", + "tap" => "homebrew/core", + "tap_git_head" => tap_git_head, + "versions" => { "bottle"=>true, "head"=>nil, "stable"=>"1.4.0" }, + } + end + + let(:ponyc_metadata) do + { + "desc" => "Object-oriented, actor-model, capabilities-secure programming language", + "full_name" => "ponyc", + "homepage" => "https://www.ponylang.io/", + "license" => "BSD-2-Clause", + "name" => "ponyc", + "ruby_source_path" => "Formula/p/ponyc.rb", + "tap" => "homebrew/core", + "tap_git_head" => tap_git_head, + "uses_from_macos" => [{ "llvm"=>[:build, :test] }, "zlib"], + "uses_from_macos_bounds" => [{}, {}], + "versions" => { "bottle"=>true, "head"=>nil, "stable"=>"0.58.1" }, + } + end + + it "loads fennel" do + fennel = Formulary.factory("fennel") + expect(fennel.to_hash).to include(**fennel_metadata) + end + + it "loads fennel from rename" do + fennel = Formulary.factory("romanesco") + expect(fennel.to_hash).to include(**fennel_metadata) + end + + it "loads fennel from alias" do + fennel = Formulary.factory("fennel-lang") + expect(fennel.to_hash).to include(**fennel_metadata) + end + + it "loads ponyc" do + ponyc = Formulary.factory("ponyc") + expect(ponyc.to_hash).to include(**ponyc_metadata) + end + + it "loads ponyc from alias" do + ponyc = Formulary.factory("ponyc-lang") + expect(ponyc.to_hash).to include(**ponyc_metadata) + end + end + end +end diff --git a/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core.json b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core.json new file mode 100644 index 0000000000000..0de2d1515ea7b --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core.json @@ -0,0 +1 @@ +{"tap_git_head":"9977471165641744a829d3e494fa563407503297","aliases":{"fennel-lang":"fennel","ponyc-lang":"ponyc"},"renames":{"advancemenu":"advancemame","amtk":"libgedit-amtk","annie":"lux","antlr2":"antlr@2","romanesco":"fennel"},"tap_migrations":{"adobe-air-sdk":"homebrew/cask","android-ndk":"homebrew/cask","android-platform-tools":"homebrew/cask","android-sdk":"homebrew/cask","app-engine-go-32":"homebrew/cask/google-cloud-sdk"},"formulae":{"fennel":{"desc":"Lua Lisp Language","license":"MIT","homepage":"https://fennel-lang.org","urls":{"stable":{"url":"https://github.com/bakpakin/Fennel/archive/refs/tags/1.4.0.tar.gz","checksum":"161eb7f17f86e95de09070214d042fb25372f71ad266f451431f3109e87965c7"}},"post_install_defined":false,"ruby_source_path":"Formula/f/fennel.rb","ruby_source_sha256":"5856e655fd1cea11496d67bc27fb14fee5cfbdea63c697c3773c7f247581197d","dependencies":["lua"],"version":"1.4.0","bottle":{"files":{"all":{"cellar":":any_skip_relocation","sha256":"f46028597883cbc38864c61bd3fa402da9cb90ce97415d51a7b5279bc17f7bd0"}}}},"ponyc":{"desc":"Object-oriented, actor-model, capabilities-secure programming language","license":"BSD-2-Clause","homepage":"https://www.ponylang.io/","urls":{"stable":{"url":"https://github.com/ponylang/ponyc.git","tag":"0.58.1","revision":"fe3895eb4af494bf36d7690641bdfb5755db8350"}},"post_install_defined":false,"ruby_source_path":"Formula/p/ponyc.rb","ruby_source_sha256":"81d51c25d18710191beb62f9f380bae3d878aad815a65ec1ee2a3b132c1fadb3","build_dependencies":["cmake","python@3.12"],"uses_from_macos":[{"llvm":["build","test"]},"zlib"],"uses_from_macos_bounds":[{},{}],"version":"0.58.1","bottle":{"files":{"arm64_sonoma":{"cellar":":any_skip_relocation","sha256":"e3aecfcf02aea56d53d82691e2ad7a780f771023d7070271bfce96b17439a34d"},"arm64_ventura":{"cellar":":any_skip_relocation","sha256":"6ff83717191e16e4f852fb3be8f838afba312cc39e601bb5cebd2a618a328658"},"arm64_monterey":{"cellar":":any_skip_relocation","sha256":"25c91bce200583a96f4cea34f31393c8f10eadcab363cc7d4d864d15f5f97e25"},"sonoma":{"cellar":":any_skip_relocation","sha256":"5f4c550ce33e2970e0ada18a409755fa62936181289a21c15582ff80343866b6"},"ventura":{"cellar":":any_skip_relocation","sha256":"f26c799f45013685da779bf2008ebe1907f9b3a93d5f260ce271a3f3b628da50"},"monterey":{"cellar":":any_skip_relocation","sha256":"1cff10d068b36b18b253d235424c4f5aef71ff9ee44f2522c4b041dd4383ec30"},"x86_64_linux":{"cellar":":any_skip_relocation","sha256":"ab49318d75eed3ee932c8e5add22f252ec0c852aad94945022877f926e93899f"}}}}}} diff --git a/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/Formula/f/fennel.rb b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/Formula/f/fennel.rb new file mode 100644 index 0000000000000..c98a3f26c274f --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/Formula/f/fennel.rb @@ -0,0 +1,25 @@ +class Fennel < Formula + desc "Lua Lisp Language" + homepage "https://fennel-lang.org" + url "https://github.com/bakpakin/Fennel/archive/refs/tags/1.4.0.tar.gz" + sha256 "161eb7f17f86e95de09070214d042fb25372f71ad266f451431f3109e87965c7" + license "MIT" + + bottle do + sha256 cellar: :any_skip_relocation, all: "f46028597883cbc38864c61bd3fa402da9cb90ce97415d51a7b5279bc17f7bd0" + end + + depends_on "lua" + + def install + system "make" + bin.install "fennel" + + lua = Formula["lua"] + (share/"lua"/lua.version.major_minor).install "fennel.lua" + end + + test do + assert_match "hello, world!", shell_output("#{bin}/fennel -e '(print \"hello, world!\")'") + end +end diff --git a/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/Formula/p/ponyc.rb b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/Formula/p/ponyc.rb new file mode 100644 index 0000000000000..63ad8bdfab5f4 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/Formula/p/ponyc.rb @@ -0,0 +1,60 @@ +class Ponyc < Formula + desc "Object-oriented, actor-model, capabilities-secure programming language" + homepage "https://www.ponylang.io/" + url "https://github.com/ponylang/ponyc.git", + tag: "0.58.1", + revision: "fe3895eb4af494bf36d7690641bdfb5755db8350" + license "BSD-2-Clause" + + bottle do + sha256 cellar: :any_skip_relocation, arm64_sonoma: "e3aecfcf02aea56d53d82691e2ad7a780f771023d7070271bfce96b17439a34d" + sha256 cellar: :any_skip_relocation, arm64_ventura: "6ff83717191e16e4f852fb3be8f838afba312cc39e601bb5cebd2a618a328658" + sha256 cellar: :any_skip_relocation, arm64_monterey: "25c91bce200583a96f4cea34f31393c8f10eadcab363cc7d4d864d15f5f97e25" + sha256 cellar: :any_skip_relocation, sonoma: "5f4c550ce33e2970e0ada18a409755fa62936181289a21c15582ff80343866b6" + sha256 cellar: :any_skip_relocation, ventura: "f26c799f45013685da779bf2008ebe1907f9b3a93d5f260ce271a3f3b628da50" + sha256 cellar: :any_skip_relocation, monterey: "1cff10d068b36b18b253d235424c4f5aef71ff9ee44f2522c4b041dd4383ec30" + sha256 cellar: :any_skip_relocation, x86_64_linux: "ab49318d75eed3ee932c8e5add22f252ec0c852aad94945022877f926e93899f" + end + + depends_on "cmake" => :build + depends_on "python@3.12" => :build + + uses_from_macos "llvm" => [:build, :test] + uses_from_macos "zlib" + + # We use LLVM to work around an error while building bundled `google-benchmark` with GCC + fails_with :gcc do + cause <<-EOS + .../src/gbenchmark/src/thread_manager.h:50:31: error: expected ')' before '(' token + 50 | GUARDED_BY(GetBenchmarkMutex()) Result results; + | ^ + EOS + end + + def install + inreplace "CMakeLists.txt", "PONY_COMPILER=\"${CMAKE_C_COMPILER}\"", "PONY_COMPILER=\"#{ENV.cc}\"" if OS.linux? + + ENV["CMAKE_FLAGS"] = "-DCMAKE_OSX_SYSROOT=#{MacOS.sdk_path}" if OS.mac? + ENV["MAKEFLAGS"] = "build_flags=-j#{ENV.make_jobs}" + + system "make", "libs" + system "make", "configure" + system "make", "build" + system "make", "install", "DESTDIR=#{prefix}" + end + + test do + # ENV["CC"] returns llvm_clang, which does not work in a test block. + ENV.clang + + system "#{bin}/ponyc", "-rexpr", "#{prefix}/packages/stdlib" + + (testpath/"test/main.pony").write <<~EOS + actor Main + new create(env: Env) => + env.out.print("Hello World!") + EOS + system "#{bin}/ponyc", "test" + assert_equal "Hello World!", shell_output("./test1").strip + end +end diff --git a/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/formula_renames.json b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/formula_renames.json new file mode 100644 index 0000000000000..ff923dc297cd6 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/formula_renames.json @@ -0,0 +1,7 @@ +{ + "advancemenu": "advancemame", + "amtk": "libgedit-amtk", + "annie": "lux", + "antlr2": "antlr@2", + "romanesco": "fennel" +} diff --git a/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/tap_migrations.json b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/tap_migrations.json new file mode 100644 index 0000000000000..2bdd3fd5c63b5 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core/tap_migrations.json @@ -0,0 +1,7 @@ +{ + "adobe-air-sdk": "homebrew/cask", + "android-ndk": "homebrew/cask", + "android-platform-tools": "homebrew/cask", + "android-sdk": "homebrew/cask", + "app-engine-go-32": "homebrew/cask/google-cloud-sdk" +} From bfe5e43ff4e70b5df7832ae07afc6907d2eff346 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sat, 24 Feb 2024 21:48:28 -0800 Subject: [PATCH 6/8] api/formula: Fix failing specs - clear the formula API cache - make the API cache directory - fix stubbed return values (thanks Sorbet!) --- Library/Homebrew/tap.rb | 1 + .../test/api/internal_tap_json/formula_spec.rb | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index 0f444b1153643..3f6d6e3b320dc 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -126,6 +126,7 @@ def clear_cache @formula_dir = nil @cask_dir = nil @command_dir = nil + @formula_names = nil @formula_files = nil @cask_files = nil @alias_dir = nil diff --git a/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb b/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb index e49d7f1de64a0..39112a8ee675b 100644 --- a/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb +++ b/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb @@ -31,7 +31,23 @@ allow(Homebrew::API).to receive(:fetch_json_api_file) .with("internal/v3/homebrew-core.jws.json") - .and_return(JSON.parse(internal_tap_json), false) + .and_return([JSON.parse(internal_tap_json), false]) + + # `Tap.reverse_tap_migrations_renames` looks for renames in every + # tap so `CoreCaskTap.tap_migrations` gets called and tries to + # fetch stuff from the API. This just avoids errors. + allow(Homebrew::API).to receive(:fetch_json_api_file) + .with("cask_tap_migrations.jws.json", anything) + .and_return([{}, false]) + + # To allow `formula_names.txt` to be written to the cache. + (HOMEBREW_CACHE/"api").mkdir + + Homebrew::API::Formula.clear_cache + end + + after do + Homebrew::API::Formula.clear_cache end it "loads tap aliases" do From f1f2e24aec567126eae93b0706579911240001c8 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sun, 25 Feb 2024 14:23:21 -0800 Subject: [PATCH 7/8] test fixture: pretty print JSON for readability --- .../api/internal_tap_json/formula_spec.rb | 2 +- .../internal_tap_json/homebrew-core.json | 117 +++++++++++++++++- 2 files changed, 117 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb b/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb index 39112a8ee675b..d6641351605be 100644 --- a/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb +++ b/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb @@ -20,7 +20,7 @@ api_hash = CoreTap.instance.to_api_hash api_hash["tap_git_head"] = tap_git_head # tricky to mock - expect(JSON.generate(api_hash)).to eq(internal_tap_json) + expect(JSON.pretty_generate(api_hash)).to eq(internal_tap_json) end end diff --git a/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core.json b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core.json index 0de2d1515ea7b..c823e3973fe6f 100644 --- a/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core.json +++ b/Library/Homebrew/test/support/fixtures/internal_tap_json/homebrew-core.json @@ -1 +1,116 @@ -{"tap_git_head":"9977471165641744a829d3e494fa563407503297","aliases":{"fennel-lang":"fennel","ponyc-lang":"ponyc"},"renames":{"advancemenu":"advancemame","amtk":"libgedit-amtk","annie":"lux","antlr2":"antlr@2","romanesco":"fennel"},"tap_migrations":{"adobe-air-sdk":"homebrew/cask","android-ndk":"homebrew/cask","android-platform-tools":"homebrew/cask","android-sdk":"homebrew/cask","app-engine-go-32":"homebrew/cask/google-cloud-sdk"},"formulae":{"fennel":{"desc":"Lua Lisp Language","license":"MIT","homepage":"https://fennel-lang.org","urls":{"stable":{"url":"https://github.com/bakpakin/Fennel/archive/refs/tags/1.4.0.tar.gz","checksum":"161eb7f17f86e95de09070214d042fb25372f71ad266f451431f3109e87965c7"}},"post_install_defined":false,"ruby_source_path":"Formula/f/fennel.rb","ruby_source_sha256":"5856e655fd1cea11496d67bc27fb14fee5cfbdea63c697c3773c7f247581197d","dependencies":["lua"],"version":"1.4.0","bottle":{"files":{"all":{"cellar":":any_skip_relocation","sha256":"f46028597883cbc38864c61bd3fa402da9cb90ce97415d51a7b5279bc17f7bd0"}}}},"ponyc":{"desc":"Object-oriented, actor-model, capabilities-secure programming language","license":"BSD-2-Clause","homepage":"https://www.ponylang.io/","urls":{"stable":{"url":"https://github.com/ponylang/ponyc.git","tag":"0.58.1","revision":"fe3895eb4af494bf36d7690641bdfb5755db8350"}},"post_install_defined":false,"ruby_source_path":"Formula/p/ponyc.rb","ruby_source_sha256":"81d51c25d18710191beb62f9f380bae3d878aad815a65ec1ee2a3b132c1fadb3","build_dependencies":["cmake","python@3.12"],"uses_from_macos":[{"llvm":["build","test"]},"zlib"],"uses_from_macos_bounds":[{},{}],"version":"0.58.1","bottle":{"files":{"arm64_sonoma":{"cellar":":any_skip_relocation","sha256":"e3aecfcf02aea56d53d82691e2ad7a780f771023d7070271bfce96b17439a34d"},"arm64_ventura":{"cellar":":any_skip_relocation","sha256":"6ff83717191e16e4f852fb3be8f838afba312cc39e601bb5cebd2a618a328658"},"arm64_monterey":{"cellar":":any_skip_relocation","sha256":"25c91bce200583a96f4cea34f31393c8f10eadcab363cc7d4d864d15f5f97e25"},"sonoma":{"cellar":":any_skip_relocation","sha256":"5f4c550ce33e2970e0ada18a409755fa62936181289a21c15582ff80343866b6"},"ventura":{"cellar":":any_skip_relocation","sha256":"f26c799f45013685da779bf2008ebe1907f9b3a93d5f260ce271a3f3b628da50"},"monterey":{"cellar":":any_skip_relocation","sha256":"1cff10d068b36b18b253d235424c4f5aef71ff9ee44f2522c4b041dd4383ec30"},"x86_64_linux":{"cellar":":any_skip_relocation","sha256":"ab49318d75eed3ee932c8e5add22f252ec0c852aad94945022877f926e93899f"}}}}}} +{ + "tap_git_head": "9977471165641744a829d3e494fa563407503297", + "aliases": { + "fennel-lang": "fennel", + "ponyc-lang": "ponyc" + }, + "renames": { + "advancemenu": "advancemame", + "amtk": "libgedit-amtk", + "annie": "lux", + "antlr2": "antlr@2", + "romanesco": "fennel" + }, + "tap_migrations": { + "adobe-air-sdk": "homebrew/cask", + "android-ndk": "homebrew/cask", + "android-platform-tools": "homebrew/cask", + "android-sdk": "homebrew/cask", + "app-engine-go-32": "homebrew/cask/google-cloud-sdk" + }, + "formulae": { + "fennel": { + "desc": "Lua Lisp Language", + "license": "MIT", + "homepage": "https://fennel-lang.org", + "urls": { + "stable": { + "url": "https://github.com/bakpakin/Fennel/archive/refs/tags/1.4.0.tar.gz", + "checksum": "161eb7f17f86e95de09070214d042fb25372f71ad266f451431f3109e87965c7" + } + }, + "post_install_defined": false, + "ruby_source_path": "Formula/f/fennel.rb", + "ruby_source_sha256": "5856e655fd1cea11496d67bc27fb14fee5cfbdea63c697c3773c7f247581197d", + "dependencies": [ + "lua" + ], + "version": "1.4.0", + "bottle": { + "files": { + "all": { + "cellar": ":any_skip_relocation", + "sha256": "f46028597883cbc38864c61bd3fa402da9cb90ce97415d51a7b5279bc17f7bd0" + } + } + } + }, + "ponyc": { + "desc": "Object-oriented, actor-model, capabilities-secure programming language", + "license": "BSD-2-Clause", + "homepage": "https://www.ponylang.io/", + "urls": { + "stable": { + "url": "https://github.com/ponylang/ponyc.git", + "tag": "0.58.1", + "revision": "fe3895eb4af494bf36d7690641bdfb5755db8350" + } + }, + "post_install_defined": false, + "ruby_source_path": "Formula/p/ponyc.rb", + "ruby_source_sha256": "81d51c25d18710191beb62f9f380bae3d878aad815a65ec1ee2a3b132c1fadb3", + "build_dependencies": [ + "cmake", + "python@3.12" + ], + "uses_from_macos": [ + { + "llvm": [ + "build", + "test" + ] + }, + "zlib" + ], + "uses_from_macos_bounds": [ + { + }, + { + } + ], + "version": "0.58.1", + "bottle": { + "files": { + "arm64_sonoma": { + "cellar": ":any_skip_relocation", + "sha256": "e3aecfcf02aea56d53d82691e2ad7a780f771023d7070271bfce96b17439a34d" + }, + "arm64_ventura": { + "cellar": ":any_skip_relocation", + "sha256": "6ff83717191e16e4f852fb3be8f838afba312cc39e601bb5cebd2a618a328658" + }, + "arm64_monterey": { + "cellar": ":any_skip_relocation", + "sha256": "25c91bce200583a96f4cea34f31393c8f10eadcab363cc7d4d864d15f5f97e25" + }, + "sonoma": { + "cellar": ":any_skip_relocation", + "sha256": "5f4c550ce33e2970e0ada18a409755fa62936181289a21c15582ff80343866b6" + }, + "ventura": { + "cellar": ":any_skip_relocation", + "sha256": "f26c799f45013685da779bf2008ebe1907f9b3a93d5f260ce271a3f3b628da50" + }, + "monterey": { + "cellar": ":any_skip_relocation", + "sha256": "1cff10d068b36b18b253d235424c4f5aef71ff9ee44f2522c4b041dd4383ec30" + }, + "x86_64_linux": { + "cellar": ":any_skip_relocation", + "sha256": "ab49318d75eed3ee932c8e5add22f252ec0c852aad94945022877f926e93899f" + } + } + } + } + } +} \ No newline at end of file From 99c101bfc11f75b22d8d51189be485abb19ea049 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Wed, 28 Feb 2024 10:49:36 +0000 Subject: [PATCH 8/8] internal_tap_json/formula_spec: add comment. --- Library/Homebrew/test/api/internal_tap_json/formula_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb b/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb index d6641351605be..076f6bd67302c 100644 --- a/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb +++ b/Library/Homebrew/test/api/internal_tap_json/formula_spec.rb @@ -108,6 +108,7 @@ "ruby_source_path" => "Formula/p/ponyc.rb", "tap" => "homebrew/core", "tap_git_head" => tap_git_head, + # TODO: improve this API before we ship internal API v3 to users "uses_from_macos" => [{ "llvm"=>[:build, :test] }, "zlib"], "uses_from_macos_bounds" => [{}, {}], "versions" => { "bottle"=>true, "head"=>nil, "stable"=>"0.58.1" },