diff --git a/Library/Homebrew/cask/cask.rb b/Library/Homebrew/cask/cask.rb index 6997ded4bb..bdae2457e1 100644 --- a/Library/Homebrew/cask/cask.rb +++ b/Library/Homebrew/cask/cask.rb @@ -60,13 +60,14 @@ module Cask source: T.nilable(String), tap: T.nilable(Tap), loaded_from_api: T::Boolean, + api_source: T.nilable(T::Hash[String, T.untyped]), config: T.nilable(Config), allow_reassignment: T::Boolean, loader: T.nilable(CaskLoader::ILoader), block: T.nilable(T.proc.bind(DSL).void), ).void } - def initialize(token, sourcefile_path: nil, source: nil, tap: nil, loaded_from_api: false, + def initialize(token, sourcefile_path: nil, source: nil, tap: nil, loaded_from_api: false, api_source: nil, config: nil, allow_reassignment: false, loader: nil, &block) @token = token @sourcefile_path = sourcefile_path @@ -74,6 +75,7 @@ module Cask @tap = tap @allow_reassignment = allow_reassignment @loaded_from_api = loaded_from_api + @api_source = api_source @loader = loader # Sorbet has trouble with bound procs assigned to instance variables: # https://github.com/sorbet/sorbet/issues/6843 @@ -91,6 +93,9 @@ module Cask sig { returns(T::Boolean) } def loaded_from_api? = @loaded_from_api + sig { returns(T.nilable(T::Hash[String, T.untyped])) } + attr_reader :api_source + # An old name for the cask. sig { returns(T::Array[String]) } def old_tokens @@ -407,8 +412,8 @@ module Cask private_constant :HASH_KEYS_TO_SKIP def to_hash_with_variations - if loaded_from_api? && !Homebrew::EnvConfig.no_install_from_api? - return api_to_local_hash(Homebrew::API::Cask.all_casks[token].dup) + if loaded_from_api? && (json_cask = api_source) && !Homebrew::EnvConfig.no_install_from_api? + return api_to_local_hash(json_cask.dup) end hash = to_h diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index d1903483aa..18666f40c4 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -336,6 +336,7 @@ module Cask cask_options = { loaded_from_api: true, + api_source: json_cask, sourcefile_path: @sourcefile_path, source: JSON.pretty_generate(json_cask), config:, diff --git a/Library/Homebrew/test/cask/cask_spec.rb b/Library/Homebrew/test/cask/cask_spec.rb index e08e8f90e4..106fd94625 100644 --- a/Library/Homebrew/test/cask/cask_spec.rb +++ b/Library/Homebrew/test/cask/cask_spec.rb @@ -533,5 +533,21 @@ RSpec.describe Cask::Cask, :cask do expect(h["artifacts"].first[:binary].first).to eq "$APPDIR/some/path" expect(h["caveats"]).to eq "$HOMEBREW_PREFIX and /$HOME\n" end + + context "when loaded from json file" do + let(:expected_json) { (TEST_FIXTURE_DIR/"cask/everything-with-variations.json").read.strip } + + it "returns expected hash with variations" do + expect(Homebrew::API::Cask).not_to receive(:source_download) + cask = Cask::CaskLoader::FromAPILoader.new("everything-with-variations", from_json: JSON.parse(expected_json)) + .load(config: nil) + + hash = cask.to_hash_with_variations + + expect(cask.loaded_from_api?).to be true + expect(hash).to be_a(Hash) + expect(JSON.pretty_generate(hash)).to eq(expected_json) + end + end end end diff --git a/Library/Homebrew/test/support/fixtures/cask/everything-with-variations.json b/Library/Homebrew/test/support/fixtures/cask/everything-with-variations.json new file mode 100644 index 0000000000..e8ba774113 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/everything-with-variations.json @@ -0,0 +1,122 @@ +{ + "token": "everything-with-variations", + "full_token": "everything-with-variations", + "old_tokens": [], + "tap": "homebrew/cask", + "name": [ + "Everything" + ], + "desc": "Little bit of everything", + "homepage": "https://www.everything.app/", + "url": "https://cachefly.everything.app/releases/Everything_1.2.3.zip", + "url_specs": { + "cookies": { + "ALL": "1234" + }, + "user_agent": ":fake" + }, + "version": "1.2.3", + "autobump": true, + "no_autobump_message": null, + "skip_livecheck": false, + "installed": null, + "installed_time": null, + "bundle_version": null, + "bundle_short_version": null, + "outdated": false, + "sha256": "c64c05bdc0be845505d6e55e69e696a7f50d40846e76155f0c85d5ff5e7bbb84", + "artifacts": [ + { + "uninstall": [ + { + "launchctl": "com.every.thing.agent", + "signal": [ + [ + "TERM", + "com.every.thing.controller1" + ], + [ + "TERM", + "com.every.thing.bin" + ] + ], + "kext": "com.every.thing.driver", + "delete": "/Library/EverythingHelperTools" + } + ] + }, + { + "installer": [ + { + "script": { + "executable": "~/just/another/path/install.sh", + "args": [ + "--mode=silent" + ], + "sudo": true, + "print_stderr": false + } + } + ] + }, + { + "app": [ + "Everything.app" + ] + }, + { + "zap": [ + { + "trash": [ + "~/.everything", + "~/Library/Everything" + ] + } + ] + } + ], + "caveats": "Installing everything might take a while...\n\neverything requires a kernel extension to work.\nIf the installation fails, retry after you enable it in:\n System Settings → Privacy & Security\n\nFor more information, refer to vendor documentation or this Apple Technical Note:\n https://developer.apple.com/library/content/technotes/tn2459/_index.html\n", + "depends_on": { + "cask": [ + "something" + ], + "macos": { + ">=": [ + "10.11" + ] + } + }, + "conflicts_with": { + "formula": [ + "nothing" + ] + }, + "container": { + "type": "naked" + }, + "auto_updates": true, + "deprecated": false, + "deprecation_date": null, + "deprecation_reason": null, + "deprecation_replacement_formula": null, + "deprecation_replacement_cask": null, + "disabled": false, + "disable_date": null, + "disable_reason": null, + "disable_replacement_formula": null, + "disable_replacement_cask": null, + "tap_git_head": "abcdef1234567890abcdef1234567890abcdef12", + "languages": [ + "en", + "eo" + ], + "ruby_source_path": "Casks/everything-with-variations.rb", + "ruby_source_checksum": { + "sha256": "d8d0d6b2e5ff65388eccb82236fd3aa157b4a29bb043a1f72b97f0e9b70e8320" + }, + "variations": { + "arm64_monterey": { + "url": "https://cachefly.everything.app/releases/arm64_monterey/Everything_1.2.3.zip" + } + } +}