Homebrew / brew

🍺 The missing package manager for macOS (or Linux)
https://brew.sh
BSD 2-Clause "Simplified" License
40.22k stars 9.44k forks source link

Wrong tap when listing installed casks from custom taps using `--json=v2 --installed` #17416

Open cdalvaro opened 1 month ago

cdalvaro commented 1 month ago

brew doctor output

Your system is ready to brew.

Verification

brew config output

HOMEBREW_VERSION: 4.3.3-2-g26a87c0
ORIGIN: https://github.com/Homebrew/brew
HEAD: 26a87c08f5767ac9681863c407f38e545c00ca0e
Last commit: 16 minutes ago
Core tap HEAD: 4b20c62ec63f00541062ab39e5a6d7dcb54c4c4a
Core tap last commit: 20 minutes ago
Core tap JSON: 03 Jun 12:05 UTC
Core cask tap JSON: 03 Jun 12:05 UTC
HOMEBREW_PREFIX: /opt/homebrew
HOMEBREW_CASK_OPTS: []
HOMEBREW_EDITOR: vimr
HOMEBREW_MAKE_JOBS: 8
HOMEBREW_SORBET_RUNTIME: set
Homebrew Ruby: 3.3.2 => /opt/homebrew/Library/Homebrew/vendor/portable-ruby/3.3.2/bin/ruby
CPU: octa-core 64-bit arm_firestorm_icestorm
Clang: 15.0.0 build 1500
Git: 2.45.2 => /opt/homebrew/bin/git
Curl: 8.6.0 => /usr/bin/curl
macOS: 14.5-arm64
CLT: 15.3.0.0.1.1708646388
Xcode: 15.4
Rosetta 2: false

What were you trying to do (and why)?

I'm trying to list all my installed formulae and casks, and looking for their corresponding taps using the command: brew info --json=v2 --installed.

However, I have discovered that casks from custom taps have homebrew/cask as the assigned tap. (This may only happens with casks that are also available from the homebrew/cask tap. Currently, I only have two casks in my custom tap cdalvaro/tap, but they are available at the official repository too).

I'm improving the mac_brew_pkg module for salt (https://github.com/saltstack/salt/pull/66611) and I have encountered this issue writing some tests.

What happened (include all command output)?

After installing a cask from a custom tap:

brew install --cask cdalvaro/tap/salt

The tap information is wrong when it is queried using: brew info --json=v2 --installed

brew info --json=v2 --installed | jq -r '.casks[] | select(.token == "salt") | .tap'
homebrew/cask

What did you expect to happen?

I expected to see cdalvaro/tap as the tap for the salt cask.

Step-by-step reproduction instructions (by running brew commands)

Carlos in Mac Studio in ~
⌘ brew info --json=v2 --installed | jq -r '.casks[] | select(.token == "salt") | .tap'
homebrew/cask

Carlos in Mac Studio in ~
⌘ brew uninstall --cask salt
==> Uninstalling Cask salt
==> Removing launchctl service com.saltstack.salt.api
==> Removing launchctl service com.saltstack.salt.master
==> Removing launchctl service com.saltstack.salt.minion
==> Removing launchctl service com.saltstack.salt.syndic
==> Uninstalling packages with sudo; the password may be necessary:
com.saltstack.salt
==> Purging files for version 3007.1 of Cask salt

Carlos in Mac Studio in ~
⌘ brew info --json=v2 --installed | jq -r '.casks[] | select(.token == "salt") | .tap'

Carlos in Mac Studio in ~
⌘ brew install --cask cdalvaro/tap/salt
==> Auto-updating Homebrew...
Adjust how often this is run with HOMEBREW_AUTO_UPDATE_SECS or disable with
HOMEBREW_NO_AUTO_UPDATE. Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Auto-updated Homebrew!
==> Updated Homebrew from 4.3.2 (e130e47f23) to 4.3.3 (26a87c08f5).
No changes to formulae or casks.

The 4.3.3 changelog can be found at:
  https://github.com/Homebrew/brew/releases/tag/4.3.3
==> Caveats
Included services:

sudo launchctl load -w /Library/LaunchDaemons/com.saltstack.salt.api.plist
sudo launchctl load -w /Library/LaunchDaemons/com.saltstack.salt.master.plist
sudo launchctl load -w /Library/LaunchDaemons/com.saltstack.salt.minion.plist
sudo launchctl load -w /Library/LaunchDaemons/com.saltstack.salt.syndic.plist

==> Downloading https://repo.saltproject.io/salt/py3/macos/minor/3007.1/salt-3007.1-py3-arm64.pkg
################################################################################################################################ 100.0%
==> Installing Cask salt
==> Running installer for salt with sudo; the password may be necessary.
installer: Package name is Salt 3007.1 (Python 3)
installer: Installing at base path /
installer: The install was successful.
🍺  salt was successfully installed!

Carlos in Mac Studio in ~
⌘ brew info --json=v2 --installed | jq -r '.casks[] | select(.token == "salt") | .tap'
homebrew/cask
apainintheneck commented 4 weeks ago

https://github.com/Homebrew/brew/blob/e8430b25a1d1321f32e5093d62b57b5cb7cfb3c3/Library/Homebrew/cask/caskroom.rb#L57-L66

This is the method that is used to load installed casks in the brew info command. It just grabs all directories in the caskroom and uses the base name of each of them to parse the token. Since this particular token is ambiguous (it's in multiple taps) and we're using the short token, it falls back to the first cask with a matching token which happens to be the one in homebrew/cask.

We do store the original caskfile that was used during installation so we could potentially try to get the full token from there. At the end of the day, this sort of situation will eventually be elegantly handled by adding an install receipt for casks (see https://github.com/Homebrew/brew/issues/17013).