Last active
August 29, 2015 14:06
-
-
Save ctwise/9c062aa1c72e88c0b288 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'nokogiri' | |
require 'open-uri' | |
require 'optparse' | |
CASK_DIR = '/usr/local/Library/Taps/caskroom/homebrew-cask/Casks' | |
# Force one version to be treated as another. Used when the local version and appcast version don't match up. | |
VERSION_MAPPING = { | |
'alfred' => [['2.4_279', '2.4']] | |
} | |
def extract_version(content) | |
content.split(/\n/).find {|line| line.strip =~ /^[0-9].*/} | |
end | |
options = {} | |
OptionParser.new do |opts| | |
opts.banner = "Usage: check_versions.rb [options] <cask-name>" | |
opts.on("-v", "--verbose", "Run verbosely") do |v| | |
options[:verbose] = v | |
end | |
end.parse! | |
target_cask_name = ARGV[0] if ARGV.size > 0 | |
# if a cask name was given on the command line, just check that one cask | |
if target_cask_name.nil? | |
cask_list = `brew cask list -1`.split(/\n/) | |
else | |
cask_list = [target_cask_name] | |
end | |
cask_list.each do |cask_name| | |
puts "Checking app #{cask_name}" if options[:verbose] | |
# get the cask version and app location from the cask formula | |
results = `brew cask info #{cask_name}`.split(/\n/) | |
cask_version = results[0].split(':')[1].strip | |
puts " Cask version #{cask_version}" if options[:verbose] | |
app_line = results.find {|line| line =~ /\.app \(/ } | |
if app_line | |
cask_location = "#{CASK_DIR}/#{cask_name}.rb" | |
app_location = app_line.gsub(/\(link\)/, '').split(/\//)[-1].strip | |
# check for the installed app version in two places, prefer the short version string to the long | |
short_local_version = extract_version(`defaults read "/Applications/#{app_location}/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null`) | |
long_local_version = extract_version(`defaults read "/Applications/#{app_location}/Contents/Info.plist" CFBundleVersion 2>/dev/null`) | |
local_version = short_local_version || long_local_version | |
puts " Installed app version #{local_version}" if options[:verbose] | |
if File.exists?(cask_location) | |
# since the appcast stanza doesn't show up in 'brew cask info', parse it from the formula file | |
appcast_line = File.open(cask_location).find {|line| line =~ /[\w]*appcast .*/} | |
if appcast_line | |
appcast_url = appcast_line.split("'")[1] | |
puts " Checking for sparkle info at #{appcast_url}" if options[:verbose] | |
# download the sparkle xml and parse it | |
doc = Nokogiri::HTML(open(appcast_url)) | |
# attempt to locate the newest version in the xml | |
cur_version = '0' | |
appcast_version = nil | |
doc.xpath('//rss/channel/item/enclosure').each do |ele| | |
# spark:version _should_ be comparable | |
item_version = ele['sparkle:version'] | |
begin | |
if Gem::Version.new(item_version) > Gem::Version.new(cur_version) | |
cur_version = item_version | |
appcast_version = ele['sparkle:shortversionstring'] || item_version | |
end | |
rescue | |
# if the spark:version isn't comparable, just assume this item is newer then the previous | |
cur_version = item_version | |
end | |
end | |
puts " Appcast version #{appcast_version}" if options[:verbose] | |
else | |
puts " No appcast entry for app" if options[:verbose] | |
end | |
end | |
# the latest version is the sparkle version if present, otherwise it's the cask formula version | |
latest_version = appcast_version || cask_version | |
# check for a version override in the VERSION_MAPPING entries | |
mapping = VERSION_MAPPING[cask_name] | |
compare_version = latest_version | |
if mapping | |
match_version = mapping.find {|entry| entry[0] == latest_version} | |
if match_version | |
compare_version = match_version[1] | |
end | |
end | |
# it all comes down to this, try to determine if there's a newer version. if the version numbers can't be | |
# parsed, just do a straight comparison. | |
begin | |
if (latest_version != 'latest') && (Gem::Version.new(compare_version) > Gem::Version.new(local_version)) | |
puts "#{cask_name} : latest version #{latest_version}, local version #{local_version}" | |
end | |
rescue | |
if (latest_version != 'latest') && (compare_version.strip != local_version.strip) | |
puts "#{cask_name} : latest version #{latest_version}, local version #{local_version}" | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment