update-report: use tap inside Reporter
* Avoid tons of unnecessary file path manipulation. Use abstraction offered by Tap class if possible. * Handle formula rename/tap migration inside reporter in per tap basis. * Avoid duplicated computation. * Remove redundant/dead code.
This commit is contained in:
parent
87ecd621eb
commit
849e62c736
@ -115,119 +115,143 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
class Reporter
|
class Reporter
|
||||||
attr_reader :initial_revision, :current_revision, :repository
|
class ReporterRevisionUnsetError < RuntimeError
|
||||||
|
def initialize(var_name)
|
||||||
|
super "#{var_name} is unset!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.repository_variable(repository)
|
attr_reader :tap, :initial_revision, :current_revision
|
||||||
if repository == HOMEBREW_REPOSITORY
|
|
||||||
|
def initialize(tap)
|
||||||
|
@tap = tap
|
||||||
|
|
||||||
|
initial_revision_var = "HOMEBREW_UPDATE_BEFORE#{repo_var}"
|
||||||
|
@initial_revision = ENV[initial_revision_var].to_s
|
||||||
|
raise ReporterRevisionUnsetError, initial_revision_var if @initial_revision.empty?
|
||||||
|
|
||||||
|
current_revision_var = "HOMEBREW_UPDATE_AFTER#{repo_var}"
|
||||||
|
@current_revision = ENV[current_revision_var].to_s
|
||||||
|
raise ReporterRevisionUnsetError, current_revision_var if @current_revision.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def report
|
||||||
|
return @report if @report
|
||||||
|
|
||||||
|
@report = Hash.new { |h, k| h[k] = [] }
|
||||||
|
return @report unless updated?
|
||||||
|
|
||||||
|
diff.each_line do |line|
|
||||||
|
status, *paths = line.split
|
||||||
|
src = Pathname.new paths.first
|
||||||
|
dst = Pathname.new paths.last
|
||||||
|
|
||||||
|
next unless dst.extname == ".rb"
|
||||||
|
next unless paths.any? { |p| tap.formula_file?(p) }
|
||||||
|
|
||||||
|
case status
|
||||||
|
when "A", "D"
|
||||||
|
@report[status.to_sym] << tap.formula_file_to_name(src)
|
||||||
|
when "M"
|
||||||
|
begin
|
||||||
|
formula = Formulary.factory(tap.path/src)
|
||||||
|
new_version = formula.pkg_version
|
||||||
|
old_version = FormulaVersions.new(formula).formula_at_revision(@initial_revision, &:pkg_version)
|
||||||
|
next if new_version == old_version
|
||||||
|
rescue Exception => e
|
||||||
|
onoe e if ARGV.homebrew_developer?
|
||||||
|
end
|
||||||
|
@report[:M] << tap.formula_file_to_name(src)
|
||||||
|
when /^R\d{0,3}/
|
||||||
|
@report[:D] << tap.formula_file_to_name(src) if tap.formula_file?(src)
|
||||||
|
@report[:A] << tap.formula_file_to_name(dst) if tap.formula_file?(dst)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
renamed_formulae = []
|
||||||
|
@report[:D].each do |old_full_name|
|
||||||
|
old_name = old_full_name.split("/").last
|
||||||
|
new_name = tap.formula_renames[old_name]
|
||||||
|
next unless new_name
|
||||||
|
|
||||||
|
if tap.core_formula_repository?
|
||||||
|
new_full_name = new_name
|
||||||
|
else
|
||||||
|
new_full_name = "#{tap}/#{new_full_name}"
|
||||||
|
end
|
||||||
|
|
||||||
|
renamed_formulae << [old_full_name, new_full_name] if @report[:A].include? new_full_name
|
||||||
|
end
|
||||||
|
|
||||||
|
unless renamed_formulae.empty?
|
||||||
|
@report[:A] -= renamed_formulae.map(&:last)
|
||||||
|
@report[:D] -= renamed_formulae.map(&:first)
|
||||||
|
@report[:R] = renamed_formulae
|
||||||
|
end
|
||||||
|
|
||||||
|
@report
|
||||||
|
end
|
||||||
|
|
||||||
|
def updated?
|
||||||
|
initial_revision != current_revision
|
||||||
|
end
|
||||||
|
|
||||||
|
def migrate_tap_migration
|
||||||
|
report[:D].each do |full_name|
|
||||||
|
name = full_name.split("/").last
|
||||||
|
next unless (dir = HOMEBREW_CELLAR/name).exist? # skip if formula is not installed.
|
||||||
|
next unless new_tap_name = tap.tap_migrations[name] # skip if formula is not in tap_migrations list.
|
||||||
|
tabs = dir.subdirs.map { |d| Tab.for_keg(Keg.new(d)) }
|
||||||
|
next unless tabs.first.tap == tap # skip if installed formula is not from this tap.
|
||||||
|
new_tap = Tap.fetch(new_tap_name)
|
||||||
|
new_tap.install unless new_tap.installed?
|
||||||
|
# update tap for each Tab
|
||||||
|
tabs.each { |tab| tab.tap = new_tap }
|
||||||
|
tabs.each(&:write)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def migrate_formula_rename
|
||||||
|
report[:R].each do |old_full_name, new_full_name|
|
||||||
|
old_name = old_full_name.split("/").last
|
||||||
|
next unless (dir = HOMEBREW_CELLAR/old_name).directory? && !dir.subdirs.empty?
|
||||||
|
|
||||||
|
begin
|
||||||
|
f = Formulary.factory(new_full_name)
|
||||||
|
rescue Exception => e
|
||||||
|
onoe e if ARGV.homebrew_developer?
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
migrator = Migrator.new(f)
|
||||||
|
migrator.migrate
|
||||||
|
rescue Migrator::MigratorDifferentTapsError
|
||||||
|
rescue Exception => e
|
||||||
|
onoe e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def repo_var
|
||||||
|
@repo_var ||= if tap.path == HOMEBREW_REPOSITORY
|
||||||
""
|
""
|
||||||
else
|
else
|
||||||
repository.to_s.
|
tap.path.to_s.
|
||||||
strip_prefix(Tap::TAP_DIRECTORY.to_s).
|
strip_prefix(Tap::TAP_DIRECTORY.to_s).
|
||||||
tr("^A-Za-z0-9", "_").
|
tr("^A-Za-z0-9", "_").
|
||||||
upcase
|
upcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(repository)
|
|
||||||
@repository = repository
|
|
||||||
|
|
||||||
repo_var = Reporter.repository_variable(@repository)
|
|
||||||
initial_revision_var = "HOMEBREW_UPDATE_BEFORE#{repo_var}"
|
|
||||||
@initial_revision = ENV[initial_revision_var].to_s
|
|
||||||
if @initial_revision.empty?
|
|
||||||
raise "#{initial_revision_var} is unset!" if ARGV.homebrew_developer?
|
|
||||||
raise "update-report should not be called directly!"
|
|
||||||
end
|
|
||||||
|
|
||||||
current_revision_var = "HOMEBREW_UPDATE_AFTER#{repo_var}"
|
|
||||||
@current_revision = ENV[current_revision_var].to_s
|
|
||||||
if @current_revision.empty?
|
|
||||||
raise "#{current_revision_var} is unset!" if ARGV.homebrew_developer?
|
|
||||||
raise "update-report should not be called directly!"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def report
|
|
||||||
map = Hash.new { |h, k| h[k] = [] }
|
|
||||||
|
|
||||||
if initial_revision && initial_revision != current_revision
|
|
||||||
wc_revision = read_current_revision
|
|
||||||
|
|
||||||
diff.each_line do |line|
|
|
||||||
status, *paths = line.split
|
|
||||||
src = paths.first
|
|
||||||
dst = paths.last
|
|
||||||
|
|
||||||
next unless File.extname(dst) == ".rb"
|
|
||||||
next unless paths.any? { |p| File.dirname(p) == formula_directory }
|
|
||||||
|
|
||||||
case status
|
|
||||||
when "A", "D"
|
|
||||||
map[status.to_sym] << repository.join(src)
|
|
||||||
when "M"
|
|
||||||
file = repository.join(src)
|
|
||||||
begin
|
|
||||||
formula = Formulary.factory(file)
|
|
||||||
new_version = if wc_revision == current_revision
|
|
||||||
formula.pkg_version
|
|
||||||
else
|
|
||||||
FormulaVersions.new(formula).formula_at_revision(@current_revision, &:pkg_version)
|
|
||||||
end
|
|
||||||
old_version = FormulaVersions.new(formula).formula_at_revision(@initial_revision, &:pkg_version)
|
|
||||||
next if new_version == old_version
|
|
||||||
# short term fix to prevent situation like https://github.com/Homebrew/homebrew/issues/45616
|
|
||||||
rescue Exception => e
|
|
||||||
onoe e if ARGV.homebrew_developer?
|
|
||||||
end
|
|
||||||
map[:M] << file
|
|
||||||
when /^R\d{0,3}/
|
|
||||||
map[:D] << repository.join(src) if File.dirname(src) == formula_directory
|
|
||||||
map[:A] << repository.join(dst) if File.dirname(dst) == formula_directory
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
map
|
|
||||||
end
|
|
||||||
|
|
||||||
def updated?
|
|
||||||
initial_revision && initial_revision != current_revision
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def formula_directory
|
|
||||||
if repository == HOMEBREW_REPOSITORY
|
|
||||||
"Library/Formula"
|
|
||||||
elsif repository.join("Formula").directory?
|
|
||||||
"Formula"
|
|
||||||
elsif repository.join("HomebrewFormula").directory?
|
|
||||||
"HomebrewFormula"
|
|
||||||
else
|
|
||||||
"."
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def read_current_revision
|
|
||||||
`git rev-parse -q --verify HEAD`.chomp
|
|
||||||
end
|
|
||||||
|
|
||||||
def diff
|
def diff
|
||||||
Utils.popen_read(
|
Utils.popen_read(
|
||||||
"git", "diff-tree", "-r", "--name-status", "--diff-filter=AMDR",
|
"git", "-C", tap.path, "diff-tree", "-r", "--name-status", "--diff-filter=AMDR",
|
||||||
"-M85%", initial_revision, current_revision
|
"-M85%", initial_revision, current_revision
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def `(cmd)
|
|
||||||
out = super
|
|
||||||
unless $?.success?
|
|
||||||
$stderr.puts(out) unless out.empty?
|
|
||||||
raise ErrorDuringExecution.new(cmd)
|
|
||||||
end
|
|
||||||
ohai(cmd, out) if ARGV.verbose?
|
|
||||||
out
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Report
|
class Report
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user