diff --git a/Library/Homebrew/compat/dependency_collector.rb b/Library/Homebrew/compat/dependency_collector.rb index fbcf1c2a0f..2e97d9d7fb 100644 --- a/Library/Homebrew/compat/dependency_collector.rb +++ b/Library/Homebrew/compat/dependency_collector.rb @@ -1,6 +1,21 @@ require "dependency_collector" class DependencyCollector + alias _parse_string_spec parse_string_spec + + # Define the languages that we can handle as external dependencies. + LANGUAGE_MODULES = Set[ + :lua, :lua51, :perl, :python, :python3, :ruby + ].freeze + + def parse_string_spec(spec, tags) + if (tag = tags.first) && LANGUAGE_MODULES.include?(tag) + LanguageModuleRequirement.new(tag, spec, tags[1]) + else + _parse_string_spec(spec, tags) + end + end + alias _parse_symbol_spec parse_symbol_spec def parse_symbol_spec(spec, tags) @@ -20,6 +35,18 @@ class DependencyCollector tags << :run output_deprecation("libtool", tags) Dependency.new("libtool", tags) + when :mysql + # output_deprecation("mysql", tags) + MysqlRequirement.new(tags) + when :postgresql + # output_deprecation("postgresql", tags) + PostgresqlRequirement.new(tags) + when :gpg + # output_deprecation("gnupg", tags) + GPG2Requirement.new(tags) + when :rbenv + # output_deprecation("rbenv", tags) + RbenvRequirement.new(tags) else _parse_symbol_spec(spec, tags) end diff --git a/Library/Homebrew/compat/requirements.rb b/Library/Homebrew/compat/requirements.rb index 3886cd7c7e..da6d867b3d 100644 --- a/Library/Homebrew/compat/requirements.rb +++ b/Library/Homebrew/compat/requirements.rb @@ -1,4 +1,42 @@ require "requirements" +require "compat/requirements/language_module_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" } +end + +class MercurialRequirement < Requirement + fatal true + default_formula "mercurial" + satisfy { which "hg" } +end + +class GPG2Requirement < Requirement + fatal true + default_formula "gnupg" + satisfy { which "gpg" } +end XcodeDependency = XcodeRequirement MysqlDependency = MysqlRequirement diff --git a/Library/Homebrew/requirements/language_module_requirement.rb b/Library/Homebrew/compat/requirements/language_module_requirement.rb similarity index 100% rename from Library/Homebrew/requirements/language_module_requirement.rb rename to Library/Homebrew/compat/requirements/language_module_requirement.rb diff --git a/Library/Homebrew/compat/requirements/tex_requirement.rb b/Library/Homebrew/compat/requirements/tex_requirement.rb new file mode 100644 index 0000000000..cb26a84779 --- /dev/null +++ b/Library/Homebrew/compat/requirements/tex_requirement.rb @@ -0,0 +1,20 @@ +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 diff --git a/Library/Homebrew/dependency_collector.rb b/Library/Homebrew/dependency_collector.rb index f8edbab069..5fe3aef30e 100644 --- a/Library/Homebrew/dependency_collector.rb +++ b/Library/Homebrew/dependency_collector.rb @@ -19,11 +19,6 @@ require "extend/cachable" class DependencyCollector extend Cachable - # Define the languages that we can handle as external dependencies. - LANGUAGE_MODULES = Set[ - :lua, :lua51, :perl, :python, :python3, :ruby - ].freeze - attr_reader :deps, :requirements def initialize @@ -58,16 +53,28 @@ class DependencyCollector parse_spec(spec, Array(tags)) end - def ant_dep(tags) + def ant_dep_if_needed(tags) Dependency.new("ant", tags) end - def xz_dep(tags) + def cvs_dep_if_needed(tags) + Dependency.new("cvs", tags) + end + + def xz_dep_if_needed(tags) Dependency.new("xz", tags) end + def expat_dep_if_needed(tags) + Dependency.new("expat", tags) + end + + def ld64_dep_if_needed(*) + LD64Dependency.new + end + def self.tar_needs_xz_dependency? - !new.xz_dep([]).nil? + !new.xz_dep_if_needed([]).nil? end private @@ -94,8 +101,6 @@ class DependencyCollector TapDependency.new(spec, tags) elsif tags.empty? Dependency.new(spec, tags) - elsif (tag = tags.first) && LANGUAGE_MODULES.include?(tag) - LanguageModuleRequirement.new(tag, spec, tags[1]) else Dependency.new(spec, tags) end @@ -107,30 +112,23 @@ class DependencyCollector when :xcode then XcodeRequirement.new(tags) when :linux then LinuxRequirement.new(tags) when :macos then MacOSRequirement.new(tags) - when :mysql then MysqlRequirement.new(tags) - when :postgresql then PostgresqlRequirement.new(tags) - when :gpg then GPG2Requirement.new(tags) when :fortran then FortranRequirement.new(tags) when :mpi then MPIRequirement.new(*tags) when :tex then TeXRequirement.new(tags) when :arch then ArchRequirement.new(tags) when :hg then MercurialRequirement.new(tags) when :python then PythonRequirement.new(tags) + when :python2 then PythonRequirement.new(tags) when :python3 then Python3Requirement.new(tags) when :java then JavaRequirement.new(tags) - when :rbenv then RbenvRequirement.new(tags) when :ruby then RubyRequirement.new(tags) when :osxfuse then OsxfuseRequirement.new(tags) when :perl then PerlRequirement.new(tags) when :tuntap then TuntapRequirement.new(tags) - when :ant then ant_dep(tags) + when :ant then ant_dep_if_needed(tags) when :emacs then EmacsRequirement.new(tags) - # Tiger's ld is too old to properly link some software - when :ld64 then LD64Dependency.new if MacOS.version < :leopard - # Tiger doesn't ship expat in /usr/lib - when :expat then Dependency.new("expat", tag) if MacOS.version < :leopard - when :python2 - PythonRequirement.new(tags) + when :ld64 then ld64_dep_if_needed(tags) + when :expat then expat_dep_if_needed(tags) else raise ArgumentError, "Unsupported special dependency #{spec.inspect}" end @@ -152,16 +150,16 @@ class DependencyCollector parse_url_spec(spec.url, tags) elsif strategy <= GitDownloadStrategy GitRequirement.new(tags) + elsif strategy <= SubversionDownloadStrategy + SubversionRequirement.new(tags) elsif strategy <= MercurialDownloadStrategy - MercurialRequirement.new(tags) + Dependency.new("hg", tags) elsif strategy <= FossilDownloadStrategy Dependency.new("fossil", tags) elsif strategy <= BazaarDownloadStrategy Dependency.new("bazaar", tags) elsif strategy <= CVSDownloadStrategy - CVSRequirement.new(tags) - elsif strategy <= SubversionDownloadStrategy - SubversionRequirement.new(tags) + cvs_dep_if_needed(tags) elsif strategy < AbstractDownloadStrategy # allow unknown strategies to pass through else @@ -172,7 +170,7 @@ class DependencyCollector def parse_url_spec(url, tags) case File.extname(url) - when ".xz" then xz_dep(tags) + when ".xz" then xz_dep_if_needed(tags) when ".lha", ".lzh" then Dependency.new("lha", tags) when ".lz" then Dependency.new("lzip", tags) when ".rar" then Dependency.new("unrar", tags) diff --git a/Library/Homebrew/extend/os/mac/dependency_collector.rb b/Library/Homebrew/extend/os/mac/dependency_collector.rb index 8d660321e6..66dcf3afe6 100644 --- a/Library/Homebrew/extend/os/mac/dependency_collector.rb +++ b/Library/Homebrew/extend/os/mac/dependency_collector.rb @@ -1,11 +1,28 @@ class DependencyCollector - def ant_dep(tags) + def ant_dep_if_needed(tags) return if MacOS.version < :mavericks Dependency.new("ant", tags) end - def xz_dep(tags) + def cvs_dep_if_needed(tags) + return if MacOS.version < :lion + Dependency.new("cvs", tags) + end + + def xz_dep_if_needed(tags) return if MacOS.version >= :mavericks Dependency.new("xz", tags) end + + def expat_dep_if_needed(tags) + # Tiger doesn't ship expat in /usr/lib + return if MacOS.version > :tiger + Dependency.new("expat", tags) + end + + def ld64_dep_if_needed(*) + # Tiger's ld is too old to properly link some software + return if MacOS.version > :tiger + LD64Dependency.new + end end diff --git a/Library/Homebrew/gpg.rb b/Library/Homebrew/gpg.rb index 83b525b444..f1b989a165 100644 --- a/Library/Homebrew/gpg.rb +++ b/Library/Homebrew/gpg.rb @@ -1,29 +1,17 @@ require "utils" class Gpg - def self.find_gpg(executable) - which_all(executable).detect do |gpg| - gpg_short_version = Utils.popen_read(gpg, "--version")[/\d\.\d/, 0] - next unless gpg_short_version - gpg_version = Version.create(gpg_short_version.to_s) - @version = gpg_version - gpg_version >= Version.create("2.0") - end + module_function + + def executable + which "gpg" end - def self.executable - find_gpg("gpg") || find_gpg("gpg2") - end - - def self.available? + def available? File.executable?(executable.to_s) end - def self.version - @version if available? - end - - def self.create_test_key(path) + def create_test_key(path) odie "No GPG present to test against!" unless available? (path/"batch.gpg").write <<~EOS @@ -40,8 +28,9 @@ class Gpg system executable, "--batch", "--gen-key", "batch.gpg" end - def self.cleanup_test_processes! + def cleanup_test_processes! odie "No GPG present to test against!" unless available? + gpgconf = Pathname.new(executable).parent/"gpgconf" system gpgconf, "--kill", "gpg-agent" @@ -49,7 +38,7 @@ class Gpg "gpg-agent" end - def self.test(path) + def test(path) create_test_key(path) begin yield diff --git a/Library/Homebrew/requirements.rb b/Library/Homebrew/requirements.rb index d5992b88d9..456dabd0a7 100644 --- a/Library/Homebrew/requirements.rb +++ b/Library/Homebrew/requirements.rb @@ -1,7 +1,5 @@ require "requirement" require "requirements/fortran_requirement" -require "requirements/gpg2_requirement" -require "requirements/language_module_requirement" require "requirements/linux_requirement" require "requirements/macos_requirement" require "requirements/maximum_macos_requirement" @@ -15,116 +13,8 @@ require "requirements/tuntap_requirement" require "requirements/unsigned_kext_requirement" require "requirements/x11_requirement" require "requirements/emacs_requirement" - -class XcodeRequirement < Requirement - fatal true - - satisfy(build_env: false) { xcode_installed_version } - - def initialize(tags) - @version = tags.find { |tag| tags.delete(tag) if tag =~ /(\d\.)+\d/ } - super - end - - def xcode_installed_version - return false unless MacOS::Xcode.installed? - return true unless @version - MacOS::Xcode.version >= @version - end - - def message - version = " #{@version}" if @version - message = <<~EOS - A full installation of Xcode.app#{version} is required to compile this software. - Installing just the Command Line Tools is not sufficient. - EOS - if MacOS.version >= :lion - message + <<~EOS - Xcode can be installed from the App Store. - EOS - else - message + <<~EOS - Xcode can be installed from #{Formatter.url("https://developer.apple.com/download/more/")}. - EOS - end - end - - def inspect - "#<#{self.class.name}: #{name.inspect} #{tags.inspect} version=#{@version.inspect}>" - end -end - -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 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 - -class ArchRequirement < Requirement - fatal true - - def initialize(arch) - @arch = arch.pop - super - end - - satisfy(build_env: false) do - case @arch - when :x86_64 then MacOS.prefer_64_bit? - when :intel, :ppc then Hardware::CPU.type == @arch - end - end - - def message - "This formula requires an #{@arch} architecture." - end -end - -class CVSRequirement < Requirement - fatal true - default_formula "cvs" - satisfy { which "cvs" } -end - -class MercurialRequirement < Requirement - fatal true - default_formula "mercurial" - satisfy { which("hg") } -end +require "requirements/arch_requirement" +require "requirements/xcode_requirement" class GitRequirement < Requirement fatal true diff --git a/Library/Homebrew/requirements/arch_requirement.rb b/Library/Homebrew/requirements/arch_requirement.rb new file mode 100644 index 0000000000..0ff52dfa82 --- /dev/null +++ b/Library/Homebrew/requirements/arch_requirement.rb @@ -0,0 +1,21 @@ +require "requirement" + +class ArchRequirement < Requirement + fatal true + + def initialize(arch) + @arch = arch.pop + super + end + + satisfy(build_env: false) do + case @arch + when :x86_64 then MacOS.prefer_64_bit? + when :intel, :ppc then Hardware::CPU.type == @arch + end + end + + def message + "This formula requires an #{@arch} architecture." + end +end diff --git a/Library/Homebrew/requirements/gpg2_requirement.rb b/Library/Homebrew/requirements/gpg2_requirement.rb deleted file mode 100644 index 04097f9be9..0000000000 --- a/Library/Homebrew/requirements/gpg2_requirement.rb +++ /dev/null @@ -1,12 +0,0 @@ -require "requirement" -require "gpg" - -class GPG2Requirement < Requirement - fatal true - default_formula "gnupg" - - # GPGTools installs GnuPG 2.0.x as a `gpg` symlink pointing - # to `gpg2`. Our `gnupg` installs only a non-symlink `gpg`. - # The aim is to retain support for any version above 2.0. - satisfy(build_env: false) { Gpg.available? } -end diff --git a/Library/Homebrew/requirements/xcode_requirement.rb b/Library/Homebrew/requirements/xcode_requirement.rb new file mode 100644 index 0000000000..ff167c6fdf --- /dev/null +++ b/Library/Homebrew/requirements/xcode_requirement.rb @@ -0,0 +1,39 @@ +require "requirement" + +class XcodeRequirement < Requirement + fatal true + + satisfy(build_env: false) { xcode_installed_version } + + def initialize(tags) + @version = tags.find { |tag| tags.delete(tag) if tag =~ /(\d\.)+\d/ } + super + end + + def xcode_installed_version + return false unless MacOS::Xcode.installed? + return true unless @version + MacOS::Xcode.version >= @version + end + + def message + version = " #{@version}" if @version + message = <<~EOS + A full installation of Xcode.app#{version} is required to compile this software. + Installing just the Command Line Tools is not sufficient. + EOS + if MacOS.version >= :lion + message + <<~EOS + Xcode can be installed from the App Store. + EOS + else + message + <<~EOS + Xcode can be installed from #{Formatter.url("https://developer.apple.com/download/more/")}. + EOS + end + end + + def inspect + "#<#{self.class.name}: #{name.inspect} #{tags.inspect} version=#{@version.inspect}>" + end +end diff --git a/Library/Homebrew/rubocops/lines_cop.rb b/Library/Homebrew/rubocops/lines_cop.rb index fdc31078f3..c96efd0b1c 100644 --- a/Library/Homebrew/rubocops/lines_cop.rb +++ b/Library/Homebrew/rubocops/lines_cop.rb @@ -6,12 +6,16 @@ module RuboCop # This cop checks for various miscellaneous Homebrew coding styles class Lines < FormulaCop def audit_formula(_node, _class_node, _parent_class_node, _body_node) - [:automake, :autoconf, :libtool].each do |dependency| + [:automake, :autoconf, :libtool, :mysql, :postgresql, :rbenv].each do |dependency| next unless depends_on?(dependency) problem ":#{dependency} is deprecated. Usage should be \"#{dependency}\"." end - problem ':apr is deprecated. Usage should be "apr-util".' if depends_on?(:apr) + { apr: "apr-util", gpg: "gnupg" }.each do |requirement, dependency| + next unless depends_on?(requirement) + problem ":#{requirement} is deprecated. Usage should be \"#{dependency}\"." + end + problem ":tex is deprecated." if depends_on?(:tex) end end diff --git a/Library/Homebrew/test/dependency_collector_spec.rb b/Library/Homebrew/test/dependency_collector_spec.rb index 3905717ad0..5ba3c20bdc 100644 --- a/Library/Homebrew/test/dependency_collector_spec.rb +++ b/Library/Homebrew/test/dependency_collector_spec.rb @@ -87,7 +87,7 @@ describe DependencyCollector do it "creates a resource dependency from a CVS URL" do resource = Resource.new resource.url(":pserver:anonymous:@example.com:/cvsroot/foo/bar", using: :cvs) - expect(subject.add(resource)).to be_an_instance_of(CVSRequirement) + expect(subject.add(resource)).to eq(Dependency.new("cvs", [:build])) end it "creates a resource dependency from a Subversion URL" do diff --git a/Library/Homebrew/test/gpg2_requirement_spec.rb b/Library/Homebrew/test/gpg2_requirement_spec.rb deleted file mode 100644 index 8b9040b82e..0000000000 --- a/Library/Homebrew/test/gpg2_requirement_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "requirements/gpg2_requirement" -require "fileutils" - -describe GPG2Requirement do - let(:dir) { mktmpdir } - - describe "#satisfied?" do - it "returns true if GPG2 is installed" do - ENV["PATH"] = dir/"bin" - (dir/"bin/gpg").write <<~EOS - #!/bin/bash - echo 2.1.20 - EOS - FileUtils.chmod 0755, dir/"bin/gpg" - - expect(subject).to be_satisfied - end - end -end diff --git a/Library/Homebrew/test/language_module_requirement_spec.rb b/Library/Homebrew/test/language_module_requirement_spec.rb index 7f2666855a..6ca8cbd0e8 100644 --- a/Library/Homebrew/test/language_module_requirement_spec.rb +++ b/Library/Homebrew/test/language_module_requirement_spec.rb @@ -1,6 +1,6 @@ -require "requirements/language_module_requirement" +require "compat/requirements/language_module_requirement" -describe LanguageModuleRequirement do +describe LanguageModuleRequirement, :needs_compat do specify "unique dependencies are not equal" do x = described_class.new(:node, "less") y = described_class.new(:node, "coffee-script")