brew/Library/Homebrew/cmd/versions.rb
Jack Nagel 8944cc6b66 versions: fix up error handling
Now we handle some things more explicitly and in the process get rid of
the blanket rescue on the mktemp block, which is something of an
antipattern.

By unloading the class *after* determining the version, we avoid the
case where the class had previously been unloaded but Formula.factory
failed, and trying to unload the nonexistent class results in a
NameError. Doing it this way, we avoid having to rescue NameError and
thereby avoid hiding other cases where it may occur.

We also rescue TypeError which gets us past a few more bad formula in
the history in some instances.

Signed-off-by: Jack Nagel <jacknagel@gmail.com>
2012-01-27 03:40:24 -06:00

80 lines
1.9 KiB
Ruby

require 'formula'
module Homebrew extend self
def versions
raise "Please `brew install git` first" unless system "/usr/bin/which -s git"
ARGV.formulae.all? do |f|
if ARGV.include? '--compact'
puts f.versions * " "
else
f.versions do |version, sha|
print Tty.white.to_s
print "#{version.ljust(8)} "
print Tty.reset.to_s
puts "git checkout #{sha} #{f.pretty_relative_path}"
end
end
end
end
end
class Formula
def versions
versions = []
rev_list.each do |sha|
version = version_for_sha sha
unless versions.include? version or version.nil?
yield version, sha if block_given?
versions << version
end
end
return versions
end
def pretty_relative_path
if Pathname.pwd == HOMEBREW_REPOSITORY
"Library/Formula/#{name}.rb"
else
"#{HOMEBREW_REPOSITORY}/Library/Formula/#{name}.rb"
end
end
private
def rev_list
HOMEBREW_REPOSITORY.cd do
`git rev-list --abbrev-commit HEAD -- Library/Formula/#{name}.rb`.split
end
end
def text_from_sha sha
HOMEBREW_REPOSITORY.cd do
`git cat-file blob #{sha}:Library/Formula/#{name}.rb`
end
end
def sha_for_version version
rev_list.find{ |sha| version == version_for_sha(sha) }
end
def version_for_sha sha
mktemp do
path = Pathname.new(Pathname.pwd+"#{name}.rb")
path.write text_from_sha(sha)
# Unload the class so Formula#version returns the correct value
# FIXME shouldn't have to do this?
begin
version = nostdout { Formula.factory(path).version }
Object.send(:remove_const, Formula.class_s(name))
version
rescue SyntaxError, TypeError
# We rescue these so that we can skip bad versions and
# continue walking the history
nil
end
end
end
end