cask: read bundle version from Info.plist when sensible.

If you're trying to use `brew info --json=v2` to get an installed
version and figure out if it is outdated: you're going to have a bad
time with `auto_updates` casks because `installed_version` alone is not
enough to get the actually currently installed version of the app.

Instead, in these cases, try to read from `Info.plist` if there is one
and use that version.

While we're here, add a `blank?` method to `Version` so we can use it
for `present?` checks (making a `null?` `Version` object `blank?`).

Co-authored-by: Markus Reiter <me@reitermark.us>
This commit is contained in:
Mike McQuaid 2024-03-05 17:11:55 +00:00
parent ea40447b87
commit 03e583e746
No known key found for this signature in database
GPG Key ID: 3338A31AFDB1D829
3 changed files with 32 additions and 1 deletions

View File

@ -2,6 +2,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "attrable" require "attrable"
require "bundle_version"
require "cask/cask_loader" require "cask/cask_loader"
require "cask/config" require "cask/config"
require "cask/dsl" require "cask/dsl"
@ -176,8 +177,20 @@ module Cask
sig { returns(T.nilable(String)) } sig { returns(T.nilable(String)) }
def installed_version def installed_version
return unless (installed_caskfile = self.installed_caskfile)
# <caskroom_path>/.metadata/<version>/<timestamp>/Casks/<token>.{rb,json} -> <version> # <caskroom_path>/.metadata/<version>/<timestamp>/Casks/<token>.{rb,json} -> <version>
installed_caskfile&.dirname&.dirname&.dirname&.basename&.to_s installed_caskfile.dirname.dirname.dirname.basename.to_s
end
sig { returns(T.nilable(String)) }
def bundle_short_version
bundle_version&.short_version
end
sig { returns(T.nilable(String)) }
def bundle_long_version
bundle_version&.version
end end
def config_path def config_path
@ -326,6 +339,8 @@ module Cask
"version" => version, "version" => version,
"installed" => installed_version, "installed" => installed_version,
"installed_time" => install_time&.to_i, "installed_time" => install_time&.to_i,
"bundle_version" => bundle_long_version,
"bundle_short_version" => bundle_short_version,
"outdated" => outdated?, "outdated" => outdated?,
"sha256" => sha256, "sha256" => sha256,
"artifacts" => artifacts_list, "artifacts" => artifacts_list,
@ -386,6 +401,14 @@ module Cask
private private
sig { returns(T.nilable(Homebrew::BundleVersion)) }
def bundle_version
@bundle_version ||= if (bundle = artifacts.find { |a| a.is_a?(Artifact::App) }&.target) &&
(plist = Pathname("#{bundle}/Contents/Info.plist")) && plist.exist?
Homebrew::BundleVersion.from_info_plist(plist)
end
end
def api_to_local_hash(hash) def api_to_local_hash(hash)
hash["token"] = token hash["token"] = token
hash["installed"] = installed_version hash["installed"] = installed_version

View File

@ -21,6 +21,8 @@
"version": "1.2.3", "version": "1.2.3",
"installed": null, "installed": null,
"installed_time": null, "installed_time": null,
"bundle_version": null,
"bundle_short_version": null,
"outdated": false, "outdated": false,
"sha256": "c64c05bdc0be845505d6e55e69e696a7f50d40846e76155f0c85d5ff5e7bbb84", "sha256": "c64c05bdc0be845505d6e55e69e696a7f50d40846e76155f0c85d5ff5e7bbb84",
"artifacts": [ "artifacts": [

View File

@ -94,6 +94,9 @@ class Version
def null? def null?
false false
end end
sig { returns(T::Boolean) }
def blank? = null?
end end
# A pseudo-token representing the absence of a token. # A pseudo-token representing the absence of a token.
@ -127,6 +130,9 @@ class Version
true true
end end
sig { returns(T::Boolean) }
def blank? = true
sig { override.returns(String) } sig { override.returns(String) }
def inspect def inspect
"#<#{self.class.name}>" "#<#{self.class.name}>"