Hint at new location of migrated formulae

Partial implementation of
https://github.com/Homebrew/brew-evolution/pull/15, along with the ability to
search for deleted formulae in git history (inspired by #1996) which is not
described in the proposal.

See also: #1371.
This commit is contained in:
Zhiming Wang 2016-12-25 18:54:08 -05:00 committed by Mike McQuaid
parent 00af5250f0
commit 1c10a6260f
5 changed files with 148 additions and 3 deletions

View File

@ -23,6 +23,7 @@ require "formula"
require "keg" require "keg"
require "tab" require "tab"
require "json" require "json"
require "historic"
module Homebrew module Homebrew
module_function module_function
@ -54,10 +55,25 @@ module Homebrew
else else
info_formula Formulary.find_with_priority(f) info_formula Formulary.find_with_priority(f)
end end
rescue FormulaUnavailableError rescue FormulaUnavailableError => e
# No formula with this name, try a blacklist lookup # No formula with this name, try a blacklist lookup
raise unless (blacklist = blacklisted?(f)) if (blacklist = blacklisted?(f))
puts blacklist ofail "#{e.message}\n#{blacklist}"
else
ofail e.message
# No point in searching if the specified tap isn't tapped yet
next if e.instance_of?(TapFormulaUnavailableError) && !e.tap.installed?
migrations = search_for_migrated_formula(f)
next unless migrations.empty?
ohai "Searching among deleted formulae..."
begin
search_for_deleted_formula(f)
rescue
nil
end
end
end end
end end
end end

View File

@ -62,6 +62,7 @@ require "formula_installer"
require "tap" require "tap"
require "hardware" require "hardware"
require "development_tools" require "development_tools"
require "historic"
module Homebrew module Homebrew
module_function module_function
@ -212,6 +213,18 @@ module Homebrew
ofail "What's updog?" ofail "What's updog?"
else else
ofail e.message ofail e.message
migrations = search_for_migrated_formula(e.name)
return unless migrations.empty?
ohai "Searching among deleted formulae..."
begin
search_for_deleted_formula(e.name)
return
rescue
nil
end
query = query_regexp(e.name) query = query_regexp(e.name)
ohai "Searching for similarly named formulae..." ohai "Searching for similarly named formulae..."

View File

@ -94,6 +94,19 @@ class TapFormulaUnavailableError < FormulaUnavailableError
end end
end end
class FormulaExistsError < RuntimeError
attr_reader :name, :path
def initialize(name, path)
@name = name
@path = path
end
def to_s
"Formula #{name} exists in #{path}"
end
end
class FormulaClassUnavailableError < FormulaUnavailableError class FormulaClassUnavailableError < FormulaUnavailableError
attr_reader :path attr_reader :path
attr_reader :class_name attr_reader :class_name

View File

@ -0,0 +1,57 @@
require "formulary"
require "tap"
module Homebrew
module_function
# name should not be qualified, since migration of qualified names is already
# handled in Formulary::TapLoader.formula_name_path.
def search_for_migrated_formula(name, options = {})
print_messages = options.fetch(:print_messages, true)
migrations = []
Tap.each do |old_tap|
new_tap_name = old_tap.tap_migrations[name]
next unless new_tap_name
migrations << [old_tap, new_tap_name]
next unless print_messages
deprecation = (new_tap_name == "homebrew/boneyard") ? "deprecated " : ""
puts "A #{deprecation}formula named \"#{name}\" has been migrated from #{old_tap} to #{new_tap_name}."
end
migrations
end
# name may be qualified.
def search_for_deleted_formula(name, options = {})
print_messages = options.fetch(:print_messages, true)
warn_shallow = options.fetch(:warn_shallow, false)
path = Formulary.path name
raise FormulaExistsError.new(name, path) if File.exist? path
path.to_s =~ HOMEBREW_TAP_PATH_REGEX
tap = Tap.new ($1 == "Homebrew" ? "homebrew" : $1), $2.strip_prefix("homebrew-")
raise TapUnavailableError, tap.name unless File.exist? tap.path
relpath = path.relative_path_from tap.path
cd tap.path
if warn_shallow && File.exist?(".git/shallow")
opoo <<-EOS.undend
The git repository is a shallow clone therefore the output may be incomplete.
Use `git fetch -C #{tap.path} --unshallow` to get the full repository.
EOS
end
log_cmd = "git log --name-only --max-count=1 --format=$'format:%H\\n%h' -- #{relpath}"
hash, hash_abbrev, relpath = Utils.popen_read(log_cmd).lines.map(&:chomp)
if hash.to_s.empty? || hash_abbrev.to_s.empty? || relpath.to_s.empty?
raise FormulaUnavailableError, name
end
if print_messages
puts "#{name} was deleted from #{tap.name} in commit #{hash_abbrev}."
puts "Run `brew boneyard #{name}` to show the formula's content prior to its removal."
end
[tap, relpath, hash, hash_abbrev]
end
end

View File

@ -0,0 +1,46 @@
require "testing_env"
require "historic"
class HistoricTest < Homebrew::TestCase
def setup
super
@path = Tap::TAP_DIRECTORY/"homebrew/homebrew-foo"
@path.mkpath
@tap = Tap.new("Homebrew", "foo")
(@path/"tap_migrations.json").write <<-EOS.undent
{ "migrated-formula": "homebrew/bar" }
EOS
(@path/"Formula/to-delete.rb").write "placeholder"
@path.cd do
shutup do
system "git", "init"
system "git", "add", "--all"
system "git", "commit", "-m", "initial state"
system "git", "rm", "Formula/to-delete.rb"
system "git", "commit", "-m", "delete formula 'to-delete'"
end
end
end
def teardown
@path.rmtree
super
end
def test_search_for_migrated_formula
migrations = Homebrew.search_for_migrated_formula("migrated-formula", print_messages: false)
assert_equal [[@tap, "homebrew/bar"]], migrations
end
def test_search_for_deleted_formula
tap, relpath, hash, = Homebrew.search_for_deleted_formula("homebrew/foo/to-delete",
print_messages: false)
assert_equal tap, @tap
assert_equal relpath, "Formula/to-delete.rb"
assert_equal `git rev-parse HEAD`.chomp, hash
end
end