Skip to content

Instantly share code, notes, and snippets.

@ctwise
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ctwise/9c062aa1c72e88c0b288 to your computer and use it in GitHub Desktop.
Save ctwise/9c062aa1c72e88c0b288 to your computer and use it in GitHub Desktop.
#!/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