Merge pull request #10029 from reitermarkus/bundle-version
Add `BundleVersion` class.
This commit is contained in:
commit
1ed31206bc
92
Library/Homebrew/bundle_version.rb
Normal file
92
Library/Homebrew/bundle_version.rb
Normal file
@ -0,0 +1,92 @@
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "system_command"
|
||||
|
||||
module Homebrew
|
||||
# Representation of a macOS bundle version, commonly found in `Info.plist` files.
|
||||
#
|
||||
# @api private
|
||||
class BundleVersion
|
||||
extend T::Sig
|
||||
|
||||
extend SystemCommand::Mixin
|
||||
|
||||
sig { params(info_plist_path: Pathname).returns(T.nilable(T.attached_class)) }
|
||||
def self.from_info_plist(info_plist_path)
|
||||
plist = system_command!("plutil", args: ["-convert", "xml1", "-o", "-", info_plist_path]).plist
|
||||
|
||||
short_version = plist["CFBundleShortVersionString"].presence
|
||||
version = plist["CFBundleVersion"].presence
|
||||
|
||||
new(short_version, version) if short_version || version
|
||||
end
|
||||
|
||||
sig { params(package_info_path: Pathname).returns(T.nilable(T.attached_class)) }
|
||||
def self.from_package_info(package_info_path)
|
||||
Homebrew.install_bundler_gems!
|
||||
require "nokogiri"
|
||||
|
||||
xml = Nokogiri::XML(package_info_path.read)
|
||||
|
||||
bundle_id = xml.xpath("//pkg-info//bundle-version//bundle").first&.attr("id")
|
||||
return unless bundle_id
|
||||
|
||||
bundle = xml.xpath("//pkg-info//bundle").find { |b| b["id"] == bundle_id }
|
||||
return unless bundle
|
||||
|
||||
short_version = bundle["CFBundleShortVersionString"]
|
||||
version = bundle["CFBundleVersion"]
|
||||
|
||||
new(short_version, version) if short_version || version
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
attr_reader :short_version, :version
|
||||
|
||||
sig { params(short_version: T.nilable(String), version: T.nilable(String)).void }
|
||||
def initialize(short_version, version)
|
||||
@short_version = short_version.presence
|
||||
@version = version.presence
|
||||
|
||||
return if @short_version || @version
|
||||
|
||||
raise ArgumentError, "`short_version` and `version` cannot both be `nil` or empty"
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
[version, short_version].map { |v| v&.yield_self(&Version.public_method(:new)) } <=>
|
||||
[other.version, other.short_version].map { |v| v&.yield_self(&Version.public_method(:new)) }
|
||||
end
|
||||
|
||||
# Create a nicely formatted version (on a best effor basis).
|
||||
sig { returns(String) }
|
||||
def nice_version
|
||||
nice_parts.join(",")
|
||||
end
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def nice_parts
|
||||
short_version = self.short_version
|
||||
version = self.version
|
||||
|
||||
short_version = short_version&.delete_suffix("(#{version})") if version
|
||||
|
||||
return [T.must(short_version)] if short_version == version
|
||||
|
||||
if short_version && version
|
||||
return [version] if version.match?(/\A\d+(\.\d+)+\Z/) && version.start_with?("#{short_version}.")
|
||||
return [short_version] if short_version.match?(/\A\d+(\.\d+)+\Z/) && short_version.start_with?("#{version}.")
|
||||
|
||||
if short_version.match?(/\A\d+(\.\d+)*\Z/) && version.match?(/\A\d+\Z/)
|
||||
return [short_version] if short_version.start_with?("#{version}.") || short_version.end_with?(".#{version}")
|
||||
|
||||
return [short_version, version]
|
||||
end
|
||||
end
|
||||
|
||||
[short_version, version].compact
|
||||
end
|
||||
private :nice_parts
|
||||
end
|
||||
end
|
||||
29
Library/Homebrew/test/bundle_version_spec.rb
Normal file
29
Library/Homebrew/test/bundle_version_spec.rb
Normal file
@ -0,0 +1,29 @@
|
||||
# typed: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "bundle_version"
|
||||
|
||||
describe Homebrew::BundleVersion do
|
||||
describe "#nice_version" do
|
||||
expected_mappings = {
|
||||
["1.2", nil] => "1.2",
|
||||
[nil, "1.2.3"] => "1.2.3",
|
||||
["1.2", "1.2.3"] => "1.2.3",
|
||||
["1.2.3", "1.2"] => "1.2.3",
|
||||
["1.2.3", "8312"] => "1.2.3,8312",
|
||||
["2021", "2006"] => "2021,2006",
|
||||
["1.0", "1"] => "1.0",
|
||||
["1.0", "0"] => "1.0",
|
||||
["1.2.3.4000", "4000"] => "1.2.3.4000",
|
||||
["5", "5.0.45"] => "5.0.45",
|
||||
["2.5.2(3329)", "3329"] => "2.5.2,3329",
|
||||
}
|
||||
|
||||
expected_mappings.each do |(short_version, version), expected_version|
|
||||
it "maps (#{short_version.inspect}, #{version.inspect}) to #{expected_version.inspect}" do
|
||||
expect(described_class.new(short_version, version).nice_version)
|
||||
.to eq expected_version
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,29 +0,0 @@
|
||||
# typed: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "unversioned_cask_checker"
|
||||
|
||||
describe Homebrew::UnversionedCaskChecker do
|
||||
describe "::decide_between_versions" do
|
||||
expected_mappings = {
|
||||
[nil, nil] => nil,
|
||||
["1.2", nil] => "1.2",
|
||||
[nil, "1.2.3"] => "1.2.3",
|
||||
["1.2", "1.2.3"] => "1.2.3",
|
||||
["1.2.3", "1.2"] => "1.2.3",
|
||||
["1.2.3", "8312"] => "1.2.3,8312",
|
||||
["2021", "2006"] => "2021,2006",
|
||||
["1.0", "1"] => "1.0",
|
||||
["1.0", "0"] => "1.0",
|
||||
["1.2.3.4000", "4000"] => "1.2.3.4000",
|
||||
["5", "5.0.45"] => "5.0.45",
|
||||
}
|
||||
|
||||
expected_mappings.each do |(short_version, version), expected_version|
|
||||
it "maps (#{short_version}, #{version}) to #{expected_version}" do
|
||||
expect(described_class.decide_between_versions(short_version, version))
|
||||
.to eq expected_version
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,6 +1,7 @@
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "bundle_version"
|
||||
require "cask/cask"
|
||||
require "cask/installer"
|
||||
|
||||
@ -45,56 +46,6 @@ module Homebrew
|
||||
pkgs.count == 1
|
||||
end
|
||||
|
||||
sig { params(info_plist_path: Pathname).returns(T.nilable(String)) }
|
||||
def self.version_from_info_plist(info_plist_path)
|
||||
plist = system_command!("plutil", args: ["-convert", "xml1", "-o", "-", info_plist_path]).plist
|
||||
|
||||
short_version = plist["CFBundleShortVersionString"].presence
|
||||
version = plist["CFBundleVersion"].presence
|
||||
|
||||
return decide_between_versions(short_version, version) if short_version && version
|
||||
end
|
||||
|
||||
sig { params(package_info_path: Pathname).returns(T.nilable(String)) }
|
||||
def self.version_from_package_info(package_info_path)
|
||||
Homebrew.install_bundler_gems!
|
||||
require "nokogiri"
|
||||
|
||||
xml = Nokogiri::XML(package_info_path.read)
|
||||
|
||||
bundle_id = xml.xpath("//pkg-info//bundle-version//bundle").first&.attr("id")
|
||||
return unless bundle_id
|
||||
|
||||
bundle = xml.xpath("//pkg-info//bundle").find { |b| b["id"] == bundle_id }
|
||||
return unless bundle
|
||||
|
||||
short_version = bundle["CFBundleShortVersionString"]
|
||||
version = bundle["CFBundleVersion"]
|
||||
|
||||
return decide_between_versions(short_version, version) if short_version && version
|
||||
end
|
||||
|
||||
sig do
|
||||
params(short_version: T.nilable(String), version: T.nilable(String))
|
||||
.returns(T.nilable(String))
|
||||
end
|
||||
def self.decide_between_versions(short_version, version)
|
||||
return short_version if short_version == version
|
||||
|
||||
if short_version && version
|
||||
return version if version.match?(/\A\d+(\.\d+)+\Z/) && version.start_with?("#{short_version}.")
|
||||
return short_version if short_version.match?(/\A\d+(\.\d+)+\Z/) && short_version.start_with?("#{version}.")
|
||||
|
||||
if short_version.match?(/\A\d+(\.\d+)*\Z/) && version.match?(/\A\d+\Z/)
|
||||
return short_version if short_version.start_with?("#{version}.") || short_version.end_with?(".#{version}")
|
||||
|
||||
return "#{short_version},#{version}"
|
||||
end
|
||||
end
|
||||
|
||||
short_version || version
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def guess_cask_version
|
||||
if apps.empty? && pkgs.empty?
|
||||
@ -120,7 +71,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
info_plist_paths.each do |info_plist_path|
|
||||
if (version = self.class.version_from_info_plist(info_plist_path))
|
||||
if (version = BundleVersion.from_info_plist(info_plist_path)&.nice_version)
|
||||
return version
|
||||
end
|
||||
end
|
||||
@ -149,7 +100,7 @@ module Homebrew
|
||||
|
||||
package_info_path = extract_dir/"PackageInfo"
|
||||
if package_info_path.exist?
|
||||
if (version = self.class.version_from_package_info(package_info_path))
|
||||
if (version = BundleVersion.from_package_info(package_info_path)&.nice_version)
|
||||
return version
|
||||
end
|
||||
elsif packages.count == 1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user