Deprecate requirements harder

Remove more Requirement logic to enable future removal of default
formula logic. Also, output deprecations, convert symbol requirement
usage to deps and simplify the compatibility code for the direct
Requirement usage.
This commit is contained in:
Mike McQuaid 2018-01-17 10:43:14 +00:00
parent 892e1b5b4f
commit e5c82dd3d9
14 changed files with 140 additions and 463 deletions

View File

@ -27,57 +27,42 @@ class DependencyCollector
odeprecated "'depends_on :tex'"
TeXRequirement.new(tags)
when :autoconf, :automake, :bsdmake, :libtool
output_deprecation(spec, tags)
output_deprecation(spec)
autotools_dep(spec, tags)
when :cairo, :fontconfig, :freetype, :libpng, :pixman
output_deprecation(spec, tags)
output_deprecation(spec)
Dependency.new(spec.to_s, tags)
when :ant, :expat
# output_deprecation(spec, tags)
output_deprecation(spec)
Dependency.new(spec.to_s, tags)
when :libltdl
tags << :run
output_deprecation("libtool", tags)
output_deprecation("libtool")
Dependency.new("libtool", tags)
when :apr
output_deprecation(spec, tags, "apr-util")
output_deprecation(spec, "apr-util")
Dependency.new("apr-util", tags)
when :fortran
# output_deprecation(spec, tags, "gcc")
FortranRequirement.new(tags)
output_deprecation(spec, "gcc")
Dependency.new("gcc", tags)
when :gpg
# output_deprecation(spec, tags, "gnupg")
GPG2Requirement.new(tags)
output_deprecation(spec, "gnupg")
Dependency.new("gnupg", tags)
when :hg
# output_deprecation(spec, tags, "mercurial")
MercurialRequirement.new(tags)
output_deprecation(spec, "mercurial")
Dependency.new("mercurial", tags)
when :mpi
# output_deprecation(spec, tags, "open-mpi")
MPIRequirement.new(*tags)
when :emacs
# output_deprecation(spec, tags)
EmacsRequirement.new(tags)
when :mysql
# output_deprecation(spec, tags)
MysqlRequirement.new(tags)
when :perl
# output_deprecation(spec, tags)
PerlRequirement.new(tags)
when :postgresql
# output_deprecation(spec, tags)
PostgresqlRequirement.new(tags)
output_deprecation(spec, "open-mpi")
Dependency.new("open-mpi", tags)
when :python, :python2
# output_deprecation(spec, tags)
PythonRequirement.new(tags)
output_deprecation(spec, "python")
Dependency.new("python", tags)
when :python3
# output_deprecation(spec, tags)
Python3Requirement.new(tags)
when :rbenv
# output_deprecation(spec, tags)
RbenvRequirement.new(tags)
when :ruby
# output_deprecation(spec, tags)
RubyRequirement.new(tags)
output_deprecation(spec, "python3")
Dependency.new("python3", tags)
when :emacs, :mysql, :perl, :postgresql, :rbenv, :ruby
output_deprecation(spec)
Dependency.new(spec, tags)
else
_parse_symbol_spec(spec, tags)
end
@ -88,13 +73,8 @@ class DependencyCollector
Dependency.new(spec.to_s, tags)
end
def output_deprecation(dependency, tags, new_dependency = dependency)
tags_string = if tags.length > 1
" => [:#{tags.join ", :"}]"
elsif tags.length == 1
" => :#{tags.first}"
end
def output_deprecation(dependency, new_dependency = dependency)
odeprecated "'depends_on :#{dependency}'",
"'depends_on \"#{new_dependency}\"#{tags_string}'"
"'depends_on \"#{new_dependency}\"'"
end
end

View File

@ -1,76 +1,134 @@
require "requirements"
require "compat/requirements/emacs_requirement"
require "compat/requirements/fortran_requirement"
require "compat/requirements/language_module_requirement"
require "compat/requirements/mpi_requirement"
require "compat/requirements/perl_requirement"
require "compat/requirements/python_requirement"
require "compat/requirements/ruby_requirement"
require "compat/requirements/tex_requirement"
class MysqlRequirement < Requirement
fatal true
default_formula "mysql"
satisfy { which "mysql_config" }
end
class PostgresqlRequirement < Requirement
fatal true
default_formula "postgresql"
satisfy { which "pg_config" }
end
class RbenvRequirement < Requirement
fatal true
default_formula "rbenv"
satisfy { which "rbenv" }
end
class CVSRequirement < Requirement
fatal true
default_formula "cvs"
satisfy { which "cvs" }
satisfy do
odeprecated("CVSRequirement", "'depends_on \"cvs\"'")
which "cvs"
end
end
class MercurialRequirement < Requirement
class EmacsRequirement < Requirement
fatal true
default_formula "mercurial"
satisfy { which "hg" }
satisfy do
odeprecated("EmacsRequirement", "'depends_on \"cvs\"'")
which "emacs"
end
end
class GPG2Requirement < Requirement
class FortranRequirement < Requirement
fatal true
default_formula "gnupg"
satisfy { which "gpg" }
satisfy do
odeprecated("FortranRequirement", "'depends_on \"cvs\"'")
which "gfortran"
end
end
class GitRequirement < Requirement
fatal true
default_formula "git"
satisfy { Utils.git_available? }
satisfy do
odeprecated("GitRequirement", "'depends_on \"cvs\"'")
which "git"
end
end
class GPG2Requirement < Requirement
fatal true
satisfy do
odeprecated("GPG2Requirement", "'depends_on \"cvs\"'")
which "gpg"
end
end
class MercurialRequirement < Requirement
fatal true
satisfy do
odeprecated("MercurialRequirement", "'depends_on \"cvs\"'")
which "hg"
end
end
class MPIRequirement < Requirement
fatal true
satisfy do
odeprecated("MPIRequirement", "'depends_on \"cvs\"'")
which "mpicc"
end
end
class MysqlRequirement < Requirement
fatal true
satisfy do
odeprecated("MysqlRequirement", "'depends_on \"cvs\"'")
which "mysql_config"
end
end
class PerlRequirement < Requirement
fatal true
satisfy do
odeprecated("PerlRequirement", "'depends_on \"cvs\"'")
which "perl"
end
end
class PostgresqlRequirement < Requirement
fatal true
satisfy do
odeprecated("PostgresqlRequirement", "'depends_on \"cvs\"'")
which "pg_config"
end
end
class PythonRequirement < Requirement
fatal true
satisfy do
odeprecated("PythonRequirement", "'depends_on \"cvs\"'")
which "python"
end
end
class Python3Requirement < Requirement
fatal true
satisfy do
odeprecated("Python3Requirement", "'depends_on \"cvs\"'")
which "python3"
end
end
class RbenvRequirement < Requirement
fatal true
satisfy do
odeprecated("RbenvRequirement", "'depends_on \"cvs\"'")
which "rbenv"
end
end
class RubyRequirement < Requirement
fatal true
satisfy do
odeprecated("RubyRequirement", "'depends_on \"cvs\"'")
which "ruby"
end
end
class SubversionRequirement < Requirement
fatal true
default_formula "subversion"
satisfy { Utils.svn_available? }
satisfy do
odeprecated("SubversionRequirement", "'depends_on \"cvs\"'")
which "svn"
end
end
XcodeDependency = XcodeRequirement
MysqlDependency = MysqlRequirement
PostgresqlDependency = PostgresqlRequirement
GPGDependency = GPG2Requirement
GPGRequirement = GPG2Requirement
TeXDependency = TeXRequirement
MercurialDependency = MercurialRequirement
GitDependency = GitRequirement
FortranDependency = FortranRequirement
JavaDependency = JavaRequirement
LanguageModuleDependency = LanguageModuleRequirement
MPIDependency = MPIRequirement
OsxfuseDependency = OsxfuseRequirement
PythonDependency = PythonRequirement
TuntapDependency = TuntapRequirement
X11Dependency = X11Requirement
ConflictsWithBinaryOsxfuse = NonBinaryOsxfuseRequirement
MinimumMacOSRequirement = MacOSRequirement
class TeXRequirement < Requirement
fatal true
cask "mactex"
download "https://www.tug.org/mactex/"
satisfy do
odeprecated("TeXRequirement", "'depends_on \"cvs\"'")
which("tex") || which("latex")
end
end
MinimumMacOSRequirement = MacOSRequirement

View File

@ -1,35 +0,0 @@
class EmacsRequirement < Requirement
fatal true
default_formula "emacs"
def initialize(tags)
@version = tags.shift if /\d+\.*\d*/ =~ tags.first
super
end
satisfy build_env: false do
next false unless which "emacs"
next true unless @version
emacs_version = Utils.popen_read("emacs", "--batch", "--eval", "(princ emacs-version)")
Version.create(emacs_version) >= Version.create(@version)
end
env do
ENV.prepend_path "PATH", which("emacs").dirname
ENV["EMACS"] = "emacs"
end
def message
if @version
s = "Emacs #{@version} or later is required."
else
s = "Emacs is required."
end
s += super
s
end
def inspect
"#<#{self.class.name}: #{name.inspect} #{tags.inspect} version=#{@version.inspect}>"
end
end

View File

@ -1,13 +0,0 @@
require "requirement"
class FortranRequirement < Requirement
fatal true
default_formula "gcc"
env { ENV.fortran }
satisfy build_env: false do
which(ENV["FC"] || "gfortran")
end
end

View File

@ -1,66 +0,0 @@
require "requirement"
# There are multiple implementations of MPI-2 available.
# http://www.mpi-forum.org/
# This requirement is used to find an appropriate one.
class MPIRequirement < Requirement
attr_reader :lang_list
fatal true
default_formula "open-mpi"
env :userpaths
# This method must accept varargs rather than an array for
# backwards compatibility with formulae that call it directly.
def initialize(*tags)
@non_functional = []
@unknown_langs = []
@lang_list = [:cc, :cxx, :f77, :f90] & tags
tags -= @lang_list
super(tags)
end
def mpi_wrapper_works?(compiler)
compiler = which compiler
return false if compiler.nil? || !compiler.executable?
# Some wrappers are non-functional and will return a non-zero exit code
# when invoked for version info.
#
# NOTE: A better test may be to do a small test compilation a la autotools.
quiet_system compiler, "--version"
end
def inspect
"#<#{self.class.name}: #{name.inspect} #{tags.inspect} lang_list=#{@lang_list.inspect}>"
end
satisfy do
@lang_list.each do |lang|
case lang
when :cc, :cxx, :f90, :f77
compiler = "mpi" + lang.to_s
@non_functional << compiler unless mpi_wrapper_works? compiler
else
@unknown_langs << lang.to_s
end
end
@unknown_langs.empty? && @non_functional.empty?
end
env do
# Set environment variables to help configure scripts find MPI compilers.
# Variable names taken from:
# https://www.gnu.org/software/autoconf-archive/ax_mpi.html
@lang_list.each do |lang|
compiler = "mpi" + lang.to_s
mpi_path = which compiler
# Fortran 90 environment var has a different name
compiler = "MPIFC" if lang == :f90
ENV[compiler.upcase] = mpi_path
end
end
end

View File

@ -1,36 +0,0 @@
class PerlRequirement < Requirement
fatal true
default_formula "perl"
def initialize(tags)
@version = tags.shift if /^\d+\.\d+$/ =~ tags.first
raise "PerlRequirement requires a version!" unless @version
super
end
satisfy(build_env: false) do
which_all("perl").detect do |perl|
perl_version = Utils.popen_read(perl, "--version")[/v(\d+\.\d+)(?:\.\d+)?/, 1]
next unless perl_version
Version.create(perl_version.to_s) >= Version.create(@version)
end
end
def message
s = "Perl #{@version} is required to install this formula."
s += super
s
end
def inspect
"#<#{self.class.name}: #{name.inspect} #{tags.inspect} version=#{@version.inspect}>"
end
def display_s
if @version
"#{name} >= #{@version}"
else
name
end
end
end

View File

@ -1,68 +0,0 @@
require "language/python"
class PythonRequirement < Requirement
fatal true
default_formula "python"
satisfy build_env: false do
python = which_python
next unless python
next unless short_version
# Always use Python 2.7 for consistency on older versions of Mac OS X.
short_version == Version.create("2.7")
end
env do
if !system_python? && short_version == Version.create("2.7")
ENV.prepend_path "PATH", which_python.dirname
end
# Homebrew Python should take precedence over other Pythons in the PATH
ENV.prepend_path "PATH", Formula["python"].opt_bin
ENV.prepend_path "PATH", Formula["python"].opt_libexec/"bin"
if system_python?
ENV["PYTHONPATH"] = "#{HOMEBREW_PREFIX}/lib/python#{short_version}/site-packages"
end
end
private
def short_version
@short_version ||= Language::Python.major_minor_version which_python
end
def which_python
python = which python_binary
return unless python
Pathname.new Utils.popen_read(python, "-c", "import sys; print(sys.executable)").strip
end
def system_python
"/usr/bin/#{python_binary}"
end
def system_python?
system_python == which_python.to_s
end
def python_binary
"python2.7"
end
# Deprecated
alias to_s python_binary
end
class Python3Requirement < PythonRequirement
fatal true
default_formula "python3"
satisfy(build_env: false) { which_python }
private
def python_binary
"python3"
end
end

View File

@ -1,56 +0,0 @@
class RubyRequirement < Requirement
fatal true
default_formula "ruby"
def initialize(tags)
@version = tags.shift if /(\d\.)+\d/ =~ tags.first
raise "RubyRequirement requires a version!" unless @version
super
end
satisfy(build_env: false) { new_enough_ruby }
env do
ENV.prepend_path "PATH", new_enough_ruby.dirname
end
def message
s = "Ruby >= #{@version} is required to install this formula."
s += super
s
end
def inspect
"#<#{self.class.name}: #{name.inspect} #{tags.inspect} version=#{@version.inspect}>"
end
def display_s
if @version
"#{name} >= #{@version}"
else
name
end
end
private
def new_enough_ruby
rubies.detect { |ruby| new_enough?(ruby) }
end
def rubies
rubies = which_all("ruby")
ruby_formula = Formula["ruby"]
rubies.unshift ruby_formula.bin/"ruby" if ruby_formula&.installed?
rubies.uniq
end
def new_enough?(ruby)
version = Utils.popen_read(ruby, "-e", "print RUBY_VERSION").strip
version =~ /^\d+\.\d+/ && Version.create(version) >= min_version
end
def min_version
@min_version ||= Version.create(@version)
end
end

View File

@ -1,20 +0,0 @@
require "requirement"
class TeXRequirement < Requirement
fatal true
cask "mactex"
download "https://www.tug.org/mactex/"
satisfy { which("tex") || which("latex") }
def message
s = <<~EOS
A LaTeX distribution is required for Homebrew to install this formula.
Make sure that "/usr/texbin", or the location you installed it to, is in
your PATH before proceeding.
EOS
s += super
s
end
end

View File

@ -1,8 +1,6 @@
require "language/java"
class JavaRequirement < Requirement
default_formula "jdk"
env do
env_java_common
env_oracle_jdk

View File

@ -14,6 +14,7 @@ require "tap"
require "keg"
require "migrator"
require "extend/ENV"
require "language/python"
# A formula provides instructions and metadata for Homebrew to install a piece
# of software. Every Homebrew formula is a {Formula}.

View File

@ -66,11 +66,6 @@ describe DependencyCollector do
expect(dep).to be_optional
end
specify "ant dependency", :needs_compat do
subject.add ant: :build
expect(find_dependency("ant")).to eq(Dependency.new("ant", [:build]))
end
it "doesn't mutate the dependency spec" do
spec = { "foo" => :optional }
copy = spec.dup

View File

@ -132,64 +132,4 @@ describe FormulaInstaller do
fi.check_install_sanity
}.to raise_error(CannotInstallFormulaError)
end
describe "#install_requirement_formula?", :needs_compat do
before do
@requirement = Python3Requirement.new
@requirement_dependency = @requirement.to_dependency
@install_bottle_for_dependent = false
allow(@requirement).to receive(:satisfied?).and_return(satisfied?)
allow(@requirement).to receive(:satisfied_by_formula?).and_return(satisfied_by_formula?)
allow(@requirement).to receive(:build?).and_return(build?)
@dependent = formula do
url "foo"
version "0.1"
depends_on :python3
end
allow(@dependent).to receive(:installed?).and_return(installed?)
@fi = FormulaInstaller.new(@dependent)
end
subject { @fi.install_requirement_formula?(@requirement_dependency, @requirement, @dependent, @install_bottle_for_dependent) }
context "it returns false when requirement is satisfied" do
let(:satisfied?) { true }
let(:satisfied_by_formula?) { false }
let(:build?) { false }
let(:installed?) { false }
it { is_expected.to be false }
end
context "it returns false when requirement is satisfied but default formula is installed" do
let(:satisfied?) { true }
let(:satisfied_by_formula?) { false }
let(:build?) { false }
let(:installed?) { false }
it { is_expected.to be false }
end
context "it returns false when requirement is :build and dependent is installed" do
let(:satisfied?) { false }
let(:satisfied_by_formula?) { false }
let(:build?) { true }
let(:installed?) { true }
it { is_expected.to be false }
end
context "it returns true when requirement isn't satisfied" do
let(:satisfied?) { false }
let(:satisfied_by_formula?) { false }
let(:build?) { false }
let(:installed?) { false }
it { is_expected.to be true }
end
context "it returns true when requirement is satisfied by a formula" do
let(:satisfied?) { true }
let(:satisfied_by_formula?) { true }
let(:build?) { false }
let(:installed?) { false }
it { is_expected.to be true }
end
end
end

View File

@ -1,14 +1,13 @@
require "compat/requirements/mpi_requirement"
require "compat/requirements"
describe MPIRequirement, :needs_compat do
describe "::new" do
subject { described_class.new(*(wrappers + tags)) }
subject { described_class.new(wrappers + tags) }
let(:wrappers) { [:cc, :cxx, :f77] }
let(:tags) { [:optional, "some-other-tag"] }
it "untangles wrappers and tags" do
expect(subject.lang_list).to eq(wrappers)
expect(subject.tags).to eq(tags)
it "stores wrappers as tags" do
expect(subject.tags).to eq(wrappers + tags)
end
end
end