From 5c3a1a2f2831fca0e8b33b7d11db97aa9259821a Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sat, 20 Jul 2024 11:14:53 -0700 Subject: [PATCH] Use cask tab to better identify installed casks Previously we would identify installed casks by token derived from directories present in the caskroom directory. That was error prone when the token was ambiguous. In that case, the `Cask::Caskroom.cask` method would default to the first cask which was not always correct. Now that we have the cask tab we can use the installed receipt to get the tap a cask came from. With both the tap and the token, we can be sure that we're loading the cask that is actually installed and not another cask from a different tap that just happens to have the same name. --- Library/Homebrew/cask/caskroom.rb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/cask/caskroom.rb b/Library/Homebrew/cask/caskroom.rb index 1c2d4dd0914c0..ca870ba87795e 100644 --- a/Library/Homebrew/cask/caskroom.rb +++ b/Library/Homebrew/cask/caskroom.rb @@ -28,6 +28,23 @@ def self.tokens paths.map { |path| path.basename.to_s } end + sig { returns(T::Array[String]) } + def self.full_tokens + require "cask/tab" + + paths.map do |path| + token = path.basename.to_s + # Cask tabs were only added on July 13, 2024 in + # https://github.com/Homebrew/brew/pull/17554 so + # they might not exist for older installs. + if (tab_path = path/".metadata"/AbstractTab::FILENAME).exist? + tap = Tab.from_file(tab_path).tap + token = "#{tap}/#{token}" if tap&.installed? + end + token + end + end + sig { returns(T::Boolean) } def self.any_casks_installed? paths.any? @@ -55,7 +72,7 @@ def self.ensure_caskroom_exists # @api internal sig { params(config: T.nilable(Config)).returns(T::Array[Cask]) } def self.casks(config: nil) - tokens.sort.filter_map do |token| + full_tokens.sort.filter_map do |token| CaskLoader.load(token, config:, warn: false) rescue TapCaskAmbiguityError => e T.must(e.loaders.first).load(config:)