App-Fair / App

Open-source browser and installer for Homebrew casks and macOS/iOS apps
https://appfair.app
GNU Affero General Public License v3.0
63 stars 1 forks source link

Slow installation for some casks on ARM Macs #1

Closed marcprux closed 2 years ago

marcprux commented 2 years ago

When installing an app from the "Homebrew casks" catalog on an ARM Mac, the installation sometimes seems to freeze at around 75%, although it eventually completes. The catalog view looks like:

Screen Shot 2022-01-25 at 9 44 36 AM

The issue is that the we pre-download the expected artifact so we can support progress monitoring & cancellation (as well as provide a reasonable user-facing error if the checksum fails), and then we fork brew to complete the installation. However, the JSON API at https://formulae.brew.sh/api/cask.json only ever lists the Intel version of any cask (due to https://github.com/Homebrew/brew/issues/12786), so when we fork brew to complete the installation, it doesn't utilize the pre-cached Intel version, but instead downloads the ARM version, which means that the two separate cask artifacts are downloaded.

Ideally the cask formula would be enhanced to list all the artifact architectures (and associated sha256 checksums), but in the meantime we could generate the JSON locally (which will use the local architecture) to “pre-flight” the cask. E.g., brew info --json=v2 --casks signal will result in:

{
  "formulae": [

  ],
  "casks": [
    {
      "token": "signal",
      "full_token": "signal",
      "tap": "homebrew/cask",
      "name": [
        "Signal"
      ],
      "desc": "Instant messaging application focusing on security",
      "homepage": "https://signal.org/",
      "url": "https://updates.signal.org/desktop/signal-desktop-mac-arm64-5.29.0.dmg",
      "appcast": null,
      "version": "5.29.0",
      "versions": {
      },
      "installed": "5.29.0",
      "outdated": false,
      "sha256": "fb7d12460c0207d1dcdfd1ae136a7f4e2dd5f6770d7c064b1aad3f1605e92169",
      "artifacts": [
        [
          "Signal.app"
        ],
        {
          "trash": [
            "~/Library/Application Support/Signal",
            "~/Library/Preferences/org.whispersystems.signal-desktop.helper.plist",
            "~/Library/Preferences/org.whispersystems.signal-desktop.plist",
            "~/Library/Saved Application State/org.whispersystems.signal-desktop.savedState"
          ],
          "signal": {
          }
        }
      ],
      "caveats": null,
      "depends_on": {
      },
      "conflicts_with": null,
      "container": null,
      "auto_updates": true
    }
  ]
}

Alternatively, we could do some simplistic parsing of the ruby to come up with all the possible permutations of the cask artifact that will be installed:

cask "signal" do
  arch = Hardware::CPU.intel? ? "x64" : "arm64"

  version "5.29.0"

  if Hardware::CPU.intel?
    sha256 "bda244f082328caedc95d46c4b76b7d134337d27bb7c8e85b827c801d7d2e5c6"
  else
    sha256 "fb7d12460c0207d1dcdfd1ae136a7f4e2dd5f6770d7c064b1aad3f1605e92169"
  end

  url "https://updates.signal.org/desktop/signal-desktop-mac-#{arch}-#{version}.dmg"
  name "Signal"
  desc "Instant messaging application focusing on security"
  homepage "https://signal.org/"

  livecheck do
    url "https://updates.signal.org/desktop/latest-mac.yml"
    strategy :electron_builder
  end

  auto_updates true

  app "Signal.app"

  zap trash: [
    "~/Library/Application Support/Signal",
    "~/Library/Preferences/org.whispersystems.signal-desktop.helper.plist",
    "~/Library/Preferences/org.whispersystems.signal-desktop.plist",
    "~/Library/Saved Application State/org.whispersystems.signal-desktop.savedState",
  ]
end
marcprux commented 2 years ago

We work around this limitation by downloading the ruby version of the formula locally and then executing brew info --json=v2 --cask <formula>.rb to get the actual url & sha256 for the current architecture and language. It's not ideal since we need to fork the brew process before the first time we download something, but it works.