diff options
Diffstat (limited to 'Library')
37 files changed, 515 insertions, 172 deletions
diff --git a/Library/.auditcops.yml b/Library/.auditcops.yml new file mode 100644 index 000000000..b5b7a8b58 --- /dev/null +++ b/Library/.auditcops.yml @@ -0,0 +1,5 @@ +inherit_from: + - ./.rubocop.yml + +NewFormulaAudit: + Enabled: true diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml index dbff189ef..cb065a1a4 100644 --- a/Library/.rubocop.yml +++ b/Library/.rubocop.yml @@ -6,35 +6,14 @@ AllCops: require: ./Homebrew/rubocops.rb -FormulaAudit/Text: +FormulaAudit: Enabled: true -FormulaAudit/Caveats: +FormulaAuditStrict: Enabled: true -FormulaAudit/Checksum: - Enabled: true - -FormulaAudit/ChecksumCase: - Enabled: true - -FormulaAuditStrict/BottleBlock: - Enabled: true - -FormulaAuditStrict/Desc: - Enabled: true - -FormulaAuditStrict/ComponentsOrder: - Enabled: true - -FormulaAuditStrict/ComponentsRedundancy: - Enabled: true - -FormulaAudit/Homepage: - Enabled: true - -FormulaAudit/LegacyPatches: - Enabled: true +NewFormulaAudit: + Enabled: false # `system` is a special case and aligns on second argument Layout/AlignParameters: diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb index 11ea8df67..ec86bd794 100644 --- a/Library/Homebrew/brew.rb +++ b/Library/Homebrew/brew.rb @@ -11,7 +11,9 @@ raise "Homebrew must be run under Ruby 2!" unless RUBY_TWO require "pathname" HOMEBREW_LIBRARY_PATH = Pathname.new(__FILE__).realpath.parent require "English" -$LOAD_PATH.unshift(HOMEBREW_LIBRARY_PATH.to_s) +unless $LOAD_PATH.include?(HOMEBREW_LIBRARY_PATH.to_s) + $LOAD_PATH.unshift(HOMEBREW_LIBRARY_PATH.to_s) +end require "global" require "tap" diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index 97c3b7f86..638e9dc19 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -1,4 +1,4 @@ -HOMEBREW_VERSION="$(git -C "$HOMEBREW_REPOSITORY" describe --tags --dirty 2>/dev/null)" +HOMEBREW_VERSION="$(git -C "$HOMEBREW_REPOSITORY" describe --tags --dirty --abbrev=7 2>/dev/null)" HOMEBREW_USER_AGENT_VERSION="$HOMEBREW_VERSION" if [[ -z "$HOMEBREW_VERSION" ]] then diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index c0f15158d..8dd4fb245 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -102,53 +102,52 @@ class Build end end - old_tmpdir = ENV["TMPDIR"] - old_temp = ENV["TEMP"] - old_tmp = ENV["TMP"] - ENV["TMPDIR"] = ENV["TEMP"] = ENV["TMP"] = HOMEBREW_TEMP + new_env = { + "TMPDIR" => HOMEBREW_TEMP, + "TEMP" => HOMEBREW_TEMP, + "TMP" => HOMEBREW_TEMP, + } - formula.extend(Debrew::Formula) if ARGV.debug? + with_env(new_env) do + formula.extend(Debrew::Formula) if ARGV.debug? - formula.brew do |_formula, staging| - staging.retain! if ARGV.keep_tmp? - formula.patch - - if ARGV.git? - system "git", "init" - system "git", "add", "-A" - end - if ARGV.interactive? - ohai "Entering interactive mode" - puts "Type `exit' to return and finalize the installation" - puts "Install to this prefix: #{formula.prefix}" + formula.brew do |_formula, staging| + staging.retain! if ARGV.keep_tmp? + formula.patch if ARGV.git? - puts "This directory is now a git repo. Make your changes and then use:" - puts " git diff | pbcopy" - puts "to copy the diff to the clipboard." + system "git", "init" + system "git", "add", "-A" + end + if ARGV.interactive? + ohai "Entering interactive mode" + puts "Type `exit' to return and finalize the installation" + puts "Install to this prefix: #{formula.prefix}" + + if ARGV.git? + puts "This directory is now a git repo. Make your changes and then use:" + puts " git diff | pbcopy" + puts "to copy the diff to the clipboard." + end + + interactive_shell(formula) + else + formula.prefix.mkpath + + (formula.logs/"00.options.out").write \ + "#{formula.full_name} #{formula.build.used_options.sort.join(" ")}".strip + formula.install + + stdlibs = detect_stdlibs(ENV.compiler) + tab = Tab.create(formula, ENV.compiler, stdlibs.first) + tab.write + + # Find and link metafiles + formula.prefix.install_metafiles formula.buildpath + formula.prefix.install_metafiles formula.libexec if formula.libexec.exist? end - - interactive_shell(formula) - else - formula.prefix.mkpath - - (formula.logs/"00.options.out").write \ - "#{formula.full_name} #{formula.build.used_options.sort.join(" ")}".strip - formula.install - - stdlibs = detect_stdlibs(ENV.compiler) - tab = Tab.create(formula, ENV.compiler, stdlibs.first) - tab.write - - # Find and link metafiles - formula.prefix.install_metafiles formula.buildpath - formula.prefix.install_metafiles formula.libexec if formula.libexec.exist? end end - ensure - ENV["TMPDIR"] = old_tmpdir - ENV["TEMP"] = old_temp - ENV["TMP"] = old_tmp end def detect_stdlibs(compiler) diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index e413bac6f..da48582d2 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -1,4 +1,4 @@ -#: * `install` [`--debug`] [`--env=`(`std`|`super`)] [`--ignore-dependencies`|`--only-dependencies`] [`--cc=`<compiler>] [`--build-from-source`|`--force-bottle`] [`--devel`|`--HEAD`] [`--keep-tmp`] [`--build-bottle`] <formula>: +#: * `install` [`--debug`] [`--env=`(`std`|`super`)] [`--ignore-dependencies`|`--only-dependencies`] [`--cc=`<compiler>] [`--build-from-source`|`--force-bottle`] [`--devel`|`--HEAD`] [`--keep-tmp`] [`--build-bottle`] <formula> [<options> ...]: #: Install <formula>. #: #: <formula> is usually the name of the formula to install, but it can be specified @@ -47,6 +47,9 @@ #: If `--build-bottle` is passed, prepare the formula for eventual bottling #: during installation. #: +#: Installation options specific to <formula> may be appended to the command, +#: and can be listed with `brew options` <formula>. +#: #: * `install` `--interactive` [`--git`] <formula>: #: If `--interactive` (or `-i`) is passed, download and patch <formula>, then #: open a shell. This allows the user to run `./configure --help` and diff --git a/Library/Homebrew/cmd/style.rb b/Library/Homebrew/cmd/style.rb index 7158fe5b9..b0f46fadc 100644 --- a/Library/Homebrew/cmd/style.rb +++ b/Library/Homebrew/cmd/style.rb @@ -47,7 +47,9 @@ module Homebrew elsif !except_cops.empty? options[:except_cops] = except_cops elsif only_cops.empty? && except_cops.empty? - options[:except_cops] = %w[FormulaAuditStrict FormulaAudit] + options[:except_cops] = %w[FormulaAudit + FormulaAuditStrict + NewFormulaAudit] end Homebrew.failed = check_style_and_print(target, options) @@ -107,7 +109,7 @@ module Homebrew args << "--config" << HOMEBREW_LIBRARY_PATH/".rubocop.yml" args << HOMEBREW_LIBRARY_PATH else - args << "--config" << HOMEBREW_LIBRARY/".rubocop.yml" + args << "--config" << HOMEBREW_LIBRARY/".auditcops.yml" args += files end diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index 77a5c1cd2..fb6a3459c 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -336,7 +336,7 @@ homebrew-update() { *) odie <<EOS This command updates brew itself, and does not take formula names. -Use 'brew upgrade <formula>'. +Use 'brew upgrade $@' instead. EOS ;; esac diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index ff6b17b45..4bcfdd128 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -87,10 +87,14 @@ module Homebrew if !only_cops.empty? options[:only_cops] = only_cops ARGV.push("--only=style") + elsif new_formula + options[:only_cops] = [:FormulaAudit, :FormulaAuditStrict, :NewFormulaAudit] + elsif strict + options[:only_cops] = [:FormulaAudit, :FormulaAuditStrict] elsif !except_cops.empty? options[:except_cops] = except_cops elsif !strict - options[:except_cops] = [:FormulaAuditStrict] + options[:except_cops] = [:FormulaAuditStrict, :NewFormulaAudit] end # Check style in a single batch run up front for performance @@ -519,15 +523,6 @@ class FormulaAuditor problem "Ambiguous conflicting formula #{c.name.inspect}." end end - - versioned_conflicts_whitelist = %w[node@ bash-completion@].freeze - - return unless formula.conflicts.any? && formula.versioned_formula? - return if formula.name.start_with?(*versioned_conflicts_whitelist) - problem <<-EOS - Versioned formulae should not use `conflicts_with`. - Use `keg_only :versioned_formula` instead. - EOS end def audit_keg_only_style @@ -562,34 +557,6 @@ class FormulaAuditor problem "keg_only reason should not end with a period." end - def audit_options - formula.options.each do |o| - if o.name == "32-bit" - problem "macOS has been 64-bit only since 10.6 so 32-bit options are deprecated." - end - - next unless @strict - - if o.name == "universal" - problem "macOS has been 64-bit only since 10.6 so universal options are deprecated." - end - - if o.name !~ /with(out)?-/ && o.name != "c++11" && o.name != "universal" - problem "Options should begin with with/without. Migrate '--#{o.name}' with `deprecated_option`." - end - - next unless o.name =~ /^with(out)?-(?:checks?|tests)$/ - unless formula.deps.any? { |d| d.name == "check" && (d.optional? || d.recommended?) } - problem "Use '--with#{Regexp.last_match(1)}-test' instead of '--#{o.name}'. Migrate '--#{o.name}' with `deprecated_option`." - end - end - - return unless @new_formula - return if formula.deprecated_options.empty? - return if formula.versioned_formula? - problem "New formulae should not use `deprecated_option`." - end - def audit_homepage homepage = formula.homepage diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb index 7ca22575f..472bb7c2b 100644 --- a/Library/Homebrew/dev-cmd/man.rb +++ b/Library/Homebrew/dev-cmd/man.rb @@ -65,7 +65,9 @@ module Homebrew readme = HOMEBREW_REPOSITORY/"README.md" variables[:lead_maintainer] = readme.read[/(Homebrew's lead maintainer .*\.)/, 1] .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') - variables[:maintainers] = readme.read[/(Homebrew's current maintainers .*\.)/, 1] + variables[:core_maintainer] = readme.read[%r{(Homebrew/homebrew-core's lead maintainer .*\.)}, 1] + .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') + variables[:maintainers] = readme.read[/(Homebrew's other current maintainers .*\.)/, 1] .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') variables[:former_maintainers] = readme.read[/(Former maintainers .*\.)/, 1] .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index 658f2e2f3..af9dcc575 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -53,10 +53,7 @@ module Homebrew ENV["GIT_#{role}_DATE"] = "Sun Jan 22 19:59:13 2017 +0000" end - # TODO: unpin this version when this error no longer shows: - # bundler-1.15.0/lib/bundler/shared_helpers.rb:25: - # stack level too deep (SystemStackError) - Homebrew.install_gem_setup_path! "bundler", "1.14.6" + Homebrew.install_gem_setup_path! "bundler" system "bundle", "install" unless quiet_system("bundle", "check") parallel = true diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index a5adfeb63..ceb6ad4d1 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -98,6 +98,17 @@ module Homebrew EOS end + def check_build_from_source + return unless ENV["HOMEBREW_BUILD_FROM_SOURCE"] + + <<-EOS.undent + You have HOMEBREW_BUILD_FROM_SOURCE set. This environment variable is + intended for use by Homebrew developers. If you are encountering errors, + please try unsetting this. Please do not file issues if you encounter + errors when using this environment variable. + EOS + end + # See https://github.com/Homebrew/legacy-homebrew/pull/9986 def check_path_for_trailing_slashes bad_paths = PATH.new(ENV["HOMEBREW_PATH"]).select { |p| p.end_with?("/") } diff --git a/Library/Homebrew/extend/fileutils.rb b/Library/Homebrew/extend/fileutils.rb index 287a1408f..52d4cbf51 100644 --- a/Library/Homebrew/extend/fileutils.rb +++ b/Library/Homebrew/extend/fileutils.rb @@ -111,10 +111,18 @@ module FileUtils # path to the actually-installed make on Tiger or older. def make(*args) if Utils.popen_read("/usr/bin/make", "--version").match(/Make (\d\.\d+)/)[1] > "3.80" - system "/usr/bin/make", *args + make_path = "/usr/bin/make" else make = Formula["make"].opt_bin/"make" make_path = make.exist? ? make.to_s : (Formula["make"].opt_bin/"gmake").to_s + end + + if superenv? + make_name = File.basename(make_path) + with_env "HOMEBREW_MAKE" => make_name do + system "make", *args + end + else system make_path, *args end end diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index da375d8a7..b2e4ff988 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -955,30 +955,27 @@ class Formula build = self.build self.build = Tab.for_formula(self) - old_tmpdir = ENV["TMPDIR"] - old_temp = ENV["TEMP"] - old_tmp = ENV["TMP"] - old_path = ENV["HOMEBREW_PATH"] - - ENV["TMPDIR"] = ENV["TEMP"] = ENV["TMP"] = HOMEBREW_TEMP - ENV["HOMEBREW_PATH"] = nil + new_env = { + "TMPDIR" => HOMEBREW_TEMP, + "TEMP" => HOMEBREW_TEMP, + "TMP" => HOMEBREW_TEMP, + "HOMEBREW_PATH" => nil, + } - ENV.clear_sensitive_environment! + with_env(new_env) do + ENV.clear_sensitive_environment! - Pathname.glob("#{bottle_prefix}/{etc,var}/**/*") do |path| - path.extend(InstallRenamed) - path.cp_path_sub(bottle_prefix, HOMEBREW_PREFIX) - end + Pathname.glob("#{bottle_prefix}/{etc,var}/**/*") do |path| + path.extend(InstallRenamed) + path.cp_path_sub(bottle_prefix, HOMEBREW_PREFIX) + end - with_logging("post_install") do - post_install + with_logging("post_install") do + post_install + end end ensure self.build = build - ENV["TMPDIR"] = old_tmpdir - ENV["TEMP"] = old_temp - ENV["TMP"] = old_tmp - ENV["HOMEBREW_PATH"] = old_path @prefix_returns_versioned_prefix = false end diff --git a/Library/Homebrew/language/python_virtualenv_constants.rb b/Library/Homebrew/language/python_virtualenv_constants.rb index c8b71aa85..4efd2ce1d 100644 --- a/Library/Homebrew/language/python_virtualenv_constants.rb +++ b/Library/Homebrew/language/python_virtualenv_constants.rb @@ -1,2 +1,2 @@ -PYTHON_VIRTUALENV_URL = "https://files.pythonhosted.org/packages/5c/79/5dae7494b9f5ed061cff9a8ab8d6e1f02db352f3facf907d9eb614fb80e9/virtualenv-15.0.2.tar.gz".freeze -PYTHON_VIRTUALENV_SHA256 = "fab40f32d9ad298fba04a260f3073505a16d52539a84843cf8c8369d4fd17167".freeze +PYTHON_VIRTUALENV_URL = "https://files.pythonhosted.org/packages/d4/0c/9840c08189e030873387a73b90ada981885010dd9aea134d6de30cd24cb8/virtualenv-15.1.0.tar.gz".freeze +PYTHON_VIRTUALENV_SHA256 = "02f8102c2436bb03b3ee6dede1919d1dac8a427541652e5ec95171ec8adbc93a".freeze diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb index 0baa96755..589527d20 100644 --- a/Library/Homebrew/manpages/brew.1.md.erb +++ b/Library/Homebrew/manpages/brew.1.md.erb @@ -260,6 +260,8 @@ Homebrew Documentation: <https://github.com/Homebrew/brew/blob/master/docs/> <%= lead_maintainer.concat("\n") %> +<%= core_maintainer.concat("\n") %> + <%= maintainers.concat("\n") %> <%= former_maintainers.concat("\n") %> diff --git a/Library/Homebrew/os/mac/linkage_checker.rb b/Library/Homebrew/os/mac/linkage_checker.rb index f332c2d7a..786827852 100644 --- a/Library/Homebrew/os/mac/linkage_checker.rb +++ b/Library/Homebrew/os/mac/linkage_checker.rb @@ -118,9 +118,12 @@ class LinkageChecker # Whether or not dylib is a harmless broken link, meaning that it's # okay to skip (and not report) as broken. def harmless_broken_link?(dylib) - # libgcc_s_ppc64 is referenced by programs that use the Java Service Wrapper, + # libgcc_s_* is referenced by programs that use the Java Service Wrapper, # and is harmless on x86(_64) machines - ["/usr/lib/libgcc_s_ppc64.1.dylib"].include?(dylib) + [ + "/usr/lib/libgcc_s_ppc64.1.dylib", + "/opt/local/lib/libgcc/libgcc_s.1.dylib", + ].include?(dylib) end # Display a list of things. diff --git a/Library/Homebrew/os/mac/pkgconfig/10.13/sqlite3.pc b/Library/Homebrew/os/mac/pkgconfig/10.13/sqlite3.pc index aa78d2c1d..86ac8b0ce 100644 --- a/Library/Homebrew/os/mac/pkgconfig/10.13/sqlite3.pc +++ b/Library/Homebrew/os/mac/pkgconfig/10.13/sqlite3.pc @@ -5,7 +5,7 @@ includedir=${prefix}/include Name: SQLite Description: SQL database engine -Version: 3.18.0 +Version: 3.19.3 Libs: -L${libdir} -lsqlite3 Libs.private: Cflags: -I${includedir} diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index 1d70c3981..ec38512e8 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -216,7 +216,7 @@ module OS # on the older supported platform for that Xcode release, i.e there's no # CLT package for 10.11 that contains the Clang version from Xcode 8. case MacOS.version - when "10.13" then "900.0.26" + when "10.13" then "900.0.28.1" when "10.12" then "802.0.42" when "10.11" then "800.0.42.1" when "10.10" then "700.1.81" diff --git a/Library/Homebrew/requirements/python_requirement.rb b/Library/Homebrew/requirements/python_requirement.rb index e62ec4cfe..c162b072c 100644 --- a/Library/Homebrew/requirements/python_requirement.rb +++ b/Library/Homebrew/requirements/python_requirement.rb @@ -18,11 +18,12 @@ class PythonRequirement < Requirement if !system_python? && short_version == Version.create("2.7") ENV.prepend_path "PATH", which_python.dirname - # Homebrew Python should take precedence over older Pythons in the PATH - elsif short_version != Version.create("2.7") - ENV.prepend_path "PATH", Formula["python"].opt_bin 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" + ENV["PYTHONPATH"] = "#{HOMEBREW_PREFIX}/lib/python#{short_version}/site-packages" end diff --git a/Library/Homebrew/rubocops.rb b/Library/Homebrew/rubocops.rb index e27f91867..f673720a6 100644 --- a/Library/Homebrew/rubocops.rb +++ b/Library/Homebrew/rubocops.rb @@ -7,3 +7,5 @@ require_relative "./rubocops/text_cop" require_relative "./rubocops/caveats_cop" require_relative "./rubocops/checksum_cop" require_relative "./rubocops/legacy_patches_cop" +require_relative "./rubocops/conflicts_cop" +require_relative "./rubocops/options_cop" diff --git a/Library/Homebrew/rubocops/conflicts_cop.rb b/Library/Homebrew/rubocops/conflicts_cop.rb new file mode 100644 index 000000000..c1b801559 --- /dev/null +++ b/Library/Homebrew/rubocops/conflicts_cop.rb @@ -0,0 +1,27 @@ +require_relative "./extend/formula_cop" +require_relative "../extend/string" + +module RuboCop + module Cop + module FormulaAudit + # This cop audits versioned Formulae for `conflicts_with` + class Conflicts < FormulaCop + MSG = <<-EOS.undent + Versioned formulae should not use `conflicts_with`. + Use `keg_only :versioned_formula` instead. + EOS + + WHITELIST = %w[ + node@ + bash-completion@ + ].freeze + + def audit_formula(_node, _class_node, _parent_class_node, body) + return unless versioned_formula? + problem MSG if !formula_file_name.start_with?(*WHITELIST) && + method_called_ever?(body, :conflicts_with) + end + end + end + end +end diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb index 439fde6a5..7165ee354 100644 --- a/Library/Homebrew/rubocops/extend/formula_cop.rb +++ b/Library/Homebrew/rubocops/extend/formula_cop.rb @@ -102,14 +102,11 @@ module RuboCop # Returns nil if does not depend on dependency_name # args: node - dependency_name - dependency's name - def depends_on?(dependency_name) + def depends_on?(dependency_name, *types) + types = [:required, :build, :optional, :recommended, :run] if types.empty? dependency_nodes = find_every_method_call_by_name(@body, :depends_on) idx = dependency_nodes.index do |n| - depends_on_name_type?(n, dependency_name, :required) || - depends_on_name_type?(n, dependency_name, :build) || - depends_on_name_type?(n, dependency_name, :optional) || - depends_on_name_type?(n, dependency_name, :recommended) || - depends_on_name_type?(n, dependency_name, :run) + types.any? { |type| depends_on_name_type?(n, dependency_name, type) } end return if idx.nil? @offense_source_range = dependency_nodes[idx].source_range @@ -138,6 +135,8 @@ module RuboCop if type_match && !name_match name_match = node_equals?(node.method_args.first.keys.first.children.first, name) end + else + type_match = false end if type_match || name_match @@ -334,16 +333,28 @@ module RuboCop def string_content(node) case node.type when :str - return node.str_content if node.type == :str + node.str_content when :dstr - return node.each_child_node(:str).map(&:str_content).join("") if node.type == :dstr + node.each_child_node(:str).map(&:str_content).join("") when :const - return node.const_name if node.type == :const + node.const_name + when :sym + node.children.first.to_s else "" end end + # Returns true if the formula is versioned + def versioned_formula? + formula_file_name.include?("@") || @formula_name.match(/AT\d+/) + end + + # Returns filename of the formula without the extension + def formula_file_name + File.basename(processed_source.buffer.name, ".rb") + end + # Returns printable component name def format_component(component_node) return component_node.method_name if component_node.send_type? || component_node.block_type? diff --git a/Library/Homebrew/rubocops/options_cop.rb b/Library/Homebrew/rubocops/options_cop.rb new file mode 100644 index 000000000..c16244161 --- /dev/null +++ b/Library/Homebrew/rubocops/options_cop.rb @@ -0,0 +1,58 @@ +require_relative "./extend/formula_cop" + +module RuboCop + module Cop + module FormulaAudit + # This cop audits `options` in Formulae + class Options < FormulaCop + DEPRECATION_MSG = "macOS has been 64-bit only since 10.6 so 32-bit options are deprecated.".freeze + + def audit_formula(_node, _class_node, _parent_class_node, body_node) + option_call_nodes = find_every_method_call_by_name(body_node, :option) + option_call_nodes.each do |option_call| + option = parameters(option_call).first + problem DEPRECATION_MSG if regex_match_group(option, /32-bit/) + end + end + end + end + + module FormulaAuditStrict + class Options < FormulaCop + DEPRECATION_MSG = "macOS has been 64-bit only since 10.6 so universal options are deprecated.".freeze + + def audit_formula(_node, _class_node, _parent_class_node, body_node) + option_call_nodes = find_every_method_call_by_name(body_node, :option) + option_call_nodes.each do |option_call| + offending_node(option_call) + option = string_content(parameters(option_call).first) + problem DEPRECATION_MSG if option == "universal" + + if option !~ /with(out)?-/ && + option != "cxx11" && + option != "universal" + problem "Options should begin with with/without."\ + " Migrate '--#{option}' with `deprecated_option`." + end + + next unless option =~ /^with(out)?-(?:checks?|tests)$/ + next if depends_on?("check", :optional, :recommended) + problem "Use '--with#{Regexp.last_match(1)}-test' instead of '--#{option}'."\ + " Migrate '--#{option}' with `deprecated_option`." + end + end + end + end + + module NewFormulaAudit + class Options < FormulaCop + MSG = "New Formula should not use `deprecated_option`".freeze + + def audit_formula(_node, _class_node, _parent_class_node, body_node) + return if versioned_formula? + problem MSG if method_called_ever?(body_node, :deprecated_option) + end + end + end + end +end diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index e2ff84ac5..e72ecb950 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -156,6 +156,7 @@ class Sandbox (literal "/dev/ptmx") (literal "/dev/dtracehelper") (literal "/dev/null") + (literal "/dev/random") (literal "/dev/zero") (regex #"^/dev/fd/[0-9]+$") (regex #"^/dev/ttys?[0-9]*$") diff --git a/Library/Homebrew/shims/super/make b/Library/Homebrew/shims/super/make index 028e3462a..7b49e56c0 100755 --- a/Library/Homebrew/shims/super/make +++ b/Library/Homebrew/shims/super/make @@ -1,4 +1,5 @@ #!/bin/bash +export MAKE=${HOMEBREW_MAKE:-make} export HOMEBREW_CCCFG="O$HOMEBREW_CCCFG" -exec xcrun make "$@" +exec xcrun $MAKE "$@" diff --git a/Library/Homebrew/system_config.rb b/Library/Homebrew/system_config.rb index f89c79306..5663295c2 100644 --- a/Library/Homebrew/system_config.rb +++ b/Library/Homebrew/system_config.rb @@ -77,7 +77,14 @@ class SystemConfig end def describe_python - python = which "python" + python = begin + python_path = PATH.new(ENV["HOMEBREW_PATH"]) + .prepend(Formula["python"].opt_libexec/"bin") + which "python", python_path + rescue FormulaUnavailableError + which "python" + end + return "N/A" if python.nil? python_binary = Utils.popen_read python, "-c", "import sys; sys.stdout.write(sys.executable)" python_binary = Pathname.new(python_binary).realpath diff --git a/Library/Homebrew/test/cmd/style_spec.rb b/Library/Homebrew/test/cmd/style_spec.rb index 3c4c3f809..4701036f1 100644 --- a/Library/Homebrew/test/cmd/style_spec.rb +++ b/Library/Homebrew/test/cmd/style_spec.rb @@ -4,12 +4,12 @@ describe "brew style" do around(:each) do |example| begin FileUtils.ln_s HOMEBREW_LIBRARY_PATH, HOMEBREW_LIBRARY/"Homebrew" - FileUtils.ln_s HOMEBREW_LIBRARY_PATH.parent/".rubocop.yml", HOMEBREW_LIBRARY/".rubocop.yml" + FileUtils.ln_s HOMEBREW_LIBRARY_PATH.parent/".rubocop.yml", HOMEBREW_LIBRARY/".auditcops.yml" example.run ensure FileUtils.rm_f HOMEBREW_LIBRARY/"Homebrew" - FileUtils.rm_f HOMEBREW_LIBRARY/".rubocop.yml" + FileUtils.rm_f HOMEBREW_LIBRARY/".auditcops.yml" end end diff --git a/Library/Homebrew/test/diagnostic_spec.rb b/Library/Homebrew/test/diagnostic_spec.rb index 058b9823c..8a25413ed 100644 --- a/Library/Homebrew/test/diagnostic_spec.rb +++ b/Library/Homebrew/test/diagnostic_spec.rb @@ -12,6 +12,12 @@ describe Homebrew::Diagnostic::Checks do .to match("Some directories in your path end in a slash") end + specify "#check_build_from_source" do + ENV["HOMEBREW_BUILD_FROM_SOURCE"] = "1" + expect(subject.check_build_from_source) + .to match("You have HOMEBREW_BUILD_FROM_SOURCE set.") + end + specify "#check_for_anaconda" do mktmpdir do |path| anaconda = "#{path}/anaconda" diff --git a/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb b/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb index a775b0b17..563f7ad4b 100644 --- a/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb @@ -18,7 +18,7 @@ describe RuboCop::Cop::FormulaAuditStrict::BottleBlock do end EOS - expected_offenses = [{ message: "Use rebuild instead of revision in bottle block", + expected_offenses = [{ message: described_class::MSG, severity: :convention, line: 5, column: 4, diff --git a/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb b/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb new file mode 100644 index 000000000..4fbab6c9e --- /dev/null +++ b/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb @@ -0,0 +1,43 @@ +require "rubocop" +require "rubocop/rspec/support" +require_relative "../../extend/string" +require_relative "../../rubocops/conflicts_cop" + +describe RuboCop::Cop::FormulaAudit::Conflicts do + subject(:cop) { described_class.new } + + context "When auditing formula for conflicts with" do + it "multiple conflicts_with" do + source = <<-EOS.undent + class FooAT20 < Formula + url 'http://example.com/foo-2.0.tgz' + conflicts_with "mysql", "mariadb", "percona-server", + :because => "both install plugins" + end + EOS + + expected_offenses = [{ message: described_class::MSG, + severity: :convention, + line: 3, + column: 2, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "no conflicts_with" do + source = <<-EOS.undent + class FooAT20 < Formula + url 'http://example.com/foo-2.0.tgz' + desc 'Bar' + end + EOS + inspect_source(cop, source) + expect(cop.offenses).to eq([]) + end + end +end diff --git a/Library/Homebrew/test/rubocops/options_cop_spec.rb b/Library/Homebrew/test/rubocops/options_cop_spec.rb new file mode 100644 index 000000000..b89b3d9b5 --- /dev/null +++ b/Library/Homebrew/test/rubocops/options_cop_spec.rb @@ -0,0 +1,132 @@ +require "rubocop" +require "rubocop/rspec/support" +require_relative "../../extend/string" +require_relative "../../rubocops/options_cop" + +describe RuboCop::Cop::FormulaAudit::Options do + subject(:cop) { described_class.new } + + context "When auditing options" do + it "32-bit" do + source = <<-EOS.undent + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + option "32-bit", "with 32-bit" + end + EOS + + expected_offenses = [{ message: described_class::DEPRECATION_MSG, + severity: :convention, + line: 3, + column: 10, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + end +end + +describe RuboCop::Cop::FormulaAuditStrict::Options do + subject(:cop) { described_class.new } + + context "When auditing options strictly" do + it "with universal" do + source = <<-EOS.undent + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + option :universal + end + EOS + + expected_offenses = [{ message: described_class::DEPRECATION_MSG, + severity: :convention, + line: 3, + column: 2, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "with deprecated options" do + source = <<-EOS.undent + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + option :cxx11 + option "examples", "with-examples" + end + EOS + + MSG_1 = "Options should begin with with/without."\ + " Migrate '--examples' with `deprecated_option`.".freeze + expected_offenses = [{ message: MSG_1, + severity: :convention, + line: 4, + column: 2, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "with misc deprecated options" do + source = <<-EOS.undent + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + option "without-check" + end + EOS + + MSG_2 = "Use '--without-test' instead of '--without-check'."\ + " Migrate '--without-check' with `deprecated_option`.".freeze + expected_offenses = [{ message: MSG_2, + severity: :convention, + line: 3, + column: 2, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + end +end + +describe RuboCop::Cop::NewFormulaAudit::Options do + subject(:cop) { described_class.new } + + context "When auditing options for a new formula" do + it "with deprecated options" do + source = <<-EOS.undent + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + deprecated_option "examples" => "with-examples" + end + EOS + + expected_offenses = [{ message: described_class::MSG, + severity: :convention, + line: 3, + column: 2, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + end +end diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb index d04ca0088..222f85fc4 100644 --- a/Library/Homebrew/test/spec_helper.rb +++ b/Library/Homebrew/test/spec_helper.rb @@ -42,6 +42,8 @@ TEST_DIRECTORIES = [ RSpec.configure do |config| config.order = :random + config.filter_run_when_matching :focus + config.include(Test::Helper::Shutup) config.include(Test::Helper::Fixtures) config.include(Test::Helper::Formula) diff --git a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb index ae1854f58..cf9c13fb8 100644 --- a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb +++ b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb @@ -77,20 +77,43 @@ RSpec.shared_context "integration test" do "HOMEBREW_INTEGRATION_TEST" => command_id_from_args(args), "HOMEBREW_TEST_TMPDIR" => TEST_TMPDIR, "HOMEBREW_DEVELOPER" => ENV["HOMEBREW_DEVELOPER"], + "GEM_HOME" => nil, ) - ruby_args = [ - "-W0", - "-I", "#{HOMEBREW_LIBRARY_PATH}/test/support/lib", - "-I", HOMEBREW_LIBRARY_PATH.to_s, - "-rconfig" - ] - ruby_args << "-rsimplecov" if ENV["HOMEBREW_TESTS_COVERAGE"] - ruby_args << "-rtest/support/helper/integration_mocks" - ruby_args << (HOMEBREW_LIBRARY_PATH/"brew.rb").resolved_path.to_s - - Bundler.with_original_env do - stdout, stderr, status = Open3.capture3(env, RUBY_PATH, *ruby_args, *args) + @ruby_args ||= begin + ruby_args = [ + "-W0", + "-I", "#{HOMEBREW_LIBRARY_PATH}/test/support/lib", + "-I", HOMEBREW_LIBRARY_PATH.to_s, + "-rconfig" + ] + if ENV["HOMEBREW_TESTS_COVERAGE"] + simplecov_spec = Gem.loaded_specs["simplecov"] + specs = [simplecov_spec] + simplecov_spec.runtime_dependencies.each do |dep| + begin + specs += dep.to_specs + rescue Gem::LoadError => e + onoe e + end + end + libs = specs.flat_map do |spec| + full_gem_path = spec.full_gem_path + # full_require_paths isn't available in RubyGems < 2.2. + spec.require_paths.map do |lib| + next lib if lib.include?(full_gem_path) + "#{full_gem_path}/#{lib}" + end + end + libs.each { |lib| ruby_args << "-I" << lib } + ruby_args << "-rsimplecov" + end + ruby_args << "-rtest/support/helper/integration_mocks" + ruby_args << (HOMEBREW_LIBRARY_PATH/"brew.rb").resolved_path.to_s + end + + Bundler.with_clean_env do + stdout, stderr, status = Open3.capture3(env, RUBY_PATH, *@ruby_args, *args) $stdout.print stdout $stderr.print stderr status diff --git a/Library/Homebrew/test/utils_spec.rb b/Library/Homebrew/test/utils_spec.rb index f3bf98486..37bd83c4f 100644 --- a/Library/Homebrew/test/utils_spec.rb +++ b/Library/Homebrew/test/utils_spec.rb @@ -270,4 +270,30 @@ describe "globally-scoped helper methods" do }.to raise_error(MethodDeprecatedError, %r{method.*replacement.*homebrew/homebrew-core.*homebrew/core}m) end end + + describe "#with_env" do + it "sets environment variables within the block" do + expect(ENV["PATH"]).not_to eq("/bin") + with_env "PATH" => "/bin" do + expect(ENV["PATH"]).to eq("/bin") + end + end + + it "restores ENV after the block" do + with_env "PATH" => "/bin" do + expect(ENV["PATH"]).to eq("/bin") + end + expect(ENV["PATH"]).not_to eq("/bin") + end + + it "restores ENV if an exception is raised" do + expect { + with_env "PATH" => "/bin" do + raise StandardError, "boom" + end + }.to raise_error(StandardError) + + expect(ENV["PATH"]).not_to eq("/bin") + end + end end diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index 529f3492d..5a6295394 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -287,10 +287,9 @@ ensure end def run_as_not_developer(&_block) - old = ENV.delete "HOMEBREW_DEVELOPER" - yield -ensure - ENV["HOMEBREW_DEVELOPER"] = old + with_env "HOMEBREW_DEVELOPER" => nil do + yield + end end # Kernel.system but with exceptions @@ -533,3 +532,27 @@ def migrate_legacy_keg_symlinks_if_necessary end FileUtils.rm_rf legacy_pinned_kegs end + +# Calls the given block with the passed environment variables +# added to ENV, then restores ENV afterwards. +# Example: +# with_env "PATH" => "/bin" do +# system "echo $PATH" +# end +# +# Note that this method is *not* thread-safe - other threads +# which happen to be scheduled during the block will also +# see these environment variables. +def with_env(hash) + old_values = {} + begin + hash.each do |key, value| + old_values[key] = ENV.delete(key) + ENV[key] = value + end + + yield if block_given? + ensure + ENV.update(old_values) + end +end diff --git a/Library/README.md b/Library/README.md new file mode 100644 index 000000000..1b3977172 --- /dev/null +++ b/Library/README.md @@ -0,0 +1,3 @@ +# Library + +This directory contains all the code run by the official `brew` and `brew cask` commands in `Homebrew` and all formulae (package descriptions) in taps (repositories containing formulae) in `Taps` subdirectories. |
