Extract history introspection from "versions" command
This commit is contained in:
parent
17a27d3464
commit
56b041ca25
@ -2,7 +2,7 @@ require 'formula'
|
||||
require 'bottles'
|
||||
require 'tab'
|
||||
require 'keg'
|
||||
require 'cmd/versions'
|
||||
require 'formula_versions'
|
||||
require 'utils/inreplace'
|
||||
require 'erb'
|
||||
require 'extend/pathname'
|
||||
@ -123,7 +123,9 @@ module Homebrew extend self
|
||||
if ARGV.include? '--no-revision'
|
||||
bottle_revision = 0
|
||||
else
|
||||
max = f.bottle_version_map('origin/master')[f.pkg_version].max
|
||||
ohai "Determining #{f.name} bottle revision..."
|
||||
versions = FormulaVersions.new(f)
|
||||
max = versions.bottle_version_map("origin/master")[f.pkg_version].max
|
||||
bottle_revision = max ? max + 1 : 0
|
||||
end
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
require 'formula'
|
||||
require "formula"
|
||||
require "formula_versions"
|
||||
|
||||
module Homebrew extend self
|
||||
def versions
|
||||
raise "Please `brew install git` first" unless which "git"
|
||||
raise "Please `brew update' first" unless (HOMEBREW_REPOSITORY/".git").directory?
|
||||
|
||||
raise "Please `brew update` first" unless (HOMEBREW_REPOSITORY/".git").directory?
|
||||
raise FormulaUnspecifiedError if ARGV.named.empty?
|
||||
|
||||
opoo <<-EOS.undent
|
||||
@ -13,107 +13,12 @@ module Homebrew extend self
|
||||
https://github.com/Homebrew/homebrew-versions
|
||||
EOS
|
||||
ARGV.formulae.all? do |f|
|
||||
relative_path = f.pretty_relative_path
|
||||
f.versions do |version, sha|
|
||||
print Tty.white.to_s
|
||||
print "#{version.to_s.ljust(8)} "
|
||||
print Tty.reset.to_s
|
||||
puts "git checkout #{sha} #{relative_path}"
|
||||
versions = FormulaVersions.new(f)
|
||||
path = versions.repository_path
|
||||
versions.each do |version, rev|
|
||||
print "#{Tty.white}#{version.to_s.ljust(8)}#{Tty.reset} "
|
||||
puts "git checkout #{rev} #{path}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Formula
|
||||
def versions
|
||||
versions = []
|
||||
rev_list 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 bottle_version_map branch='HEAD'
|
||||
map = Hash.new { |h, k| h[k] = [] }
|
||||
rev_list(branch) do |rev|
|
||||
formula_for_sha(rev) do |f|
|
||||
bottle = f.stable.bottle_specification
|
||||
unless bottle.checksums.empty?
|
||||
map[f.pkg_version] << bottle.revision
|
||||
end
|
||||
end
|
||||
end
|
||||
map
|
||||
end
|
||||
|
||||
def pretty_relative_path
|
||||
if Pathname.pwd == repository
|
||||
entry_name
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def repository
|
||||
@repository ||= begin
|
||||
if path.to_s =~ HOMEBREW_TAP_DIR_REGEX
|
||||
HOMEBREW_REPOSITORY/"Library/Taps/#$1/#$2"
|
||||
else
|
||||
HOMEBREW_REPOSITORY
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def entry_name
|
||||
@entry_name ||= path.relative_path_from(repository).to_s
|
||||
end
|
||||
|
||||
def rev_list branch='HEAD'
|
||||
repository.cd do
|
||||
IO.popen("git rev-list --abbrev-commit --remove-empty #{branch} -- #{entry_name}") do |io|
|
||||
yield io.readline.chomp until io.eof?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def text_from_sha sha
|
||||
repository.cd do
|
||||
`git cat-file blob #{sha}:#{entry_name}`
|
||||
end
|
||||
end
|
||||
|
||||
IGNORED_EXCEPTIONS = [SyntaxError, TypeError, NameError,
|
||||
ArgumentError, FormulaSpecificationError,
|
||||
FormulaValidationError,]
|
||||
|
||||
def version_for_sha sha
|
||||
formula_for_sha(sha) {|f| f.version }
|
||||
end
|
||||
|
||||
def formula_for_sha sha, &block
|
||||
mktemp do
|
||||
path = Pathname.pwd.join("#{name}.rb")
|
||||
path.write text_from_sha(sha)
|
||||
|
||||
# Unload the class so Formula#version returns the correct value
|
||||
begin
|
||||
old_const = Formulary.unload_formula name
|
||||
nostdout { yield Formula.factory(path.to_s) }
|
||||
rescue *IGNORED_EXCEPTIONS => e
|
||||
# We rescue these so that we can skip bad versions and
|
||||
# continue walking the history
|
||||
ohai "#{e} in #{name} at revision #{sha}", e.backtrace if ARGV.debug?
|
||||
rescue FormulaUnavailableError
|
||||
# Suppress this error
|
||||
ensure
|
||||
Formulary.restore_formula name, old_const
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
86
Library/Homebrew/formula_versions.rb
Normal file
86
Library/Homebrew/formula_versions.rb
Normal file
@ -0,0 +1,86 @@
|
||||
class FormulaVersions
|
||||
IGNORED_EXCEPTIONS = [
|
||||
ArgumentError, NameError, SyntaxError, TypeError,
|
||||
FormulaSpecificationError, FormulaValidationError,
|
||||
]
|
||||
|
||||
attr_reader :f
|
||||
|
||||
def initialize(f)
|
||||
@f = f
|
||||
end
|
||||
|
||||
def repository
|
||||
@repository ||= if f.path.to_s =~ HOMEBREW_TAP_DIR_REGEX
|
||||
HOMEBREW_REPOSITORY/"Library/Taps/#$1/#$2"
|
||||
else
|
||||
HOMEBREW_REPOSITORY
|
||||
end
|
||||
end
|
||||
|
||||
def entry_name
|
||||
@entry_name ||= f.path.relative_path_from(repository).to_s
|
||||
end
|
||||
|
||||
def each
|
||||
versions = Set.new
|
||||
rev_list do |rev|
|
||||
version = version_at_revision(rev)
|
||||
next if version.nil?
|
||||
yield version, rev if versions.add?(version)
|
||||
end
|
||||
end
|
||||
|
||||
def repository_path
|
||||
Pathname.pwd == repository ? entry_name : f.path
|
||||
end
|
||||
|
||||
def rev_list(branch="HEAD")
|
||||
repository.cd do
|
||||
IO.popen("git rev-list --abbrev-commit --remove-empty #{branch} -- #{entry_name}") do |io|
|
||||
yield io.readline.chomp until io.eof?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def file_contents_at_revision(rev)
|
||||
repository.cd { `git cat-file blob #{rev}:#{entry_name}` }
|
||||
end
|
||||
|
||||
def version_at_revision(rev)
|
||||
formula_at_revision(rev) { |f| f.version }
|
||||
end
|
||||
|
||||
def formula_at_revision rev, &block
|
||||
f.mktemp do
|
||||
path = Pathname.pwd.join("#{f.name}.rb")
|
||||
path.write file_contents_at_revision(rev)
|
||||
|
||||
begin
|
||||
old_const = Formulary.unload_formula(f.name)
|
||||
nostdout { yield Formula.factory(path.to_s) }
|
||||
rescue *IGNORED_EXCEPTIONS => e
|
||||
# We rescue these so that we can skip bad versions and
|
||||
# continue walking the history
|
||||
ohai "#{e} in #{f.name} at revision #{rev}", e.backtrace if ARGV.debug?
|
||||
rescue FormulaUnavailableError
|
||||
# Suppress this error
|
||||
ensure
|
||||
Formulary.restore_formula(f.name, old_const)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def bottle_version_map(branch="HEAD")
|
||||
map = Hash.new { |h, k| h[k] = [] }
|
||||
rev_list(branch) do |rev|
|
||||
formula_at_revision(rev) do |f|
|
||||
bottle = f.stable.bottle_specification
|
||||
unless bottle.checksums.empty?
|
||||
map[f.pkg_version] << bottle.revision
|
||||
end
|
||||
end
|
||||
end
|
||||
map
|
||||
end
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user