diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml index f43fbe54c0..c94b248a3b 100644 --- a/Library/.rubocop.yml +++ b/Library/.rubocop.yml @@ -26,6 +26,9 @@ Layout/CaseIndentation: Layout/EmptyLineBetweenDefs: AllowAdjacentOneLineDefs: true +Layout/EndAlignment: + EnforcedStyleAlignWith: variable + Layout/IndentArray: EnforcedStyle: special_inside_parentheses @@ -52,9 +55,6 @@ Lint/AmbiguousBlockAssociation: Lint/AssignmentInCondition: Enabled: false -Lint/EndAlignment: - EnforcedStyleAlignWith: variable - # so many of these in formulae and can't be autocorrected Lint/ParenthesesAsGroupedExpression: Enabled: false @@ -205,7 +205,10 @@ Style/TernaryParentheses: EnforcedStyle: require_parentheses_when_complex # makes diffs nicer -Style/TrailingCommaInLiteral: +Style/TrailingCommaInArrayLiteral: + EnforcedStyleForMultiline: comma + +Style/TrailingCommaInHashLiteral: EnforcedStyleForMultiline: comma Style/TrailingCommaInArguments: @@ -215,6 +218,10 @@ Style/TrailingCommaInArguments: Naming/VariableNumber: Enabled: false +# doesn't make sense for Homebrew/brew but does for taps +Naming/UncommunicativeMethodParamName: + Enabled: true + Style/WordArray: MinSize: 4 diff --git a/Library/Homebrew/.rubocop.yml b/Library/Homebrew/.rubocop.yml index e0089e0500..58b911ca9f 100644 --- a/Library/Homebrew/.rubocop.yml +++ b/Library/Homebrew/.rubocop.yml @@ -68,6 +68,10 @@ Naming/PredicateName: - 'compat/**/*' NameWhitelist: is_32_bit?, is_64_bit? +# f meaning formulae is pretty standard +Naming/UncommunicativeMethodParamName: + Enabled: false + Style/BlockDelimiters: Exclude: - '**/*_spec.rb' diff --git a/Library/Homebrew/cask/lib/hbc/cask_loader.rb b/Library/Homebrew/cask/lib/hbc/cask_loader.rb index 74c39176d3..640282ec36 100644 --- a/Library/Homebrew/cask/lib/hbc/cask_loader.rb +++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb @@ -1,3 +1,5 @@ +require "uri" + module Hbc module CaskLoader class FromContentLoader diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb index dfb3019998..e5a7d9202b 100644 --- a/Library/Homebrew/cask/lib/hbc/system_command.rb +++ b/Library/Homebrew/cask/lib/hbc/system_command.rb @@ -85,7 +85,7 @@ module Hbc executable, *args = expanded_command raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = - Open3.popen3({ "PATH" => path }, executable, *args, **options) + Open3.popen3({ "PATH" => path }, [executable, executable], *args, **options) write_input_to(raw_stdin) raw_stdin.close_write diff --git a/Library/Homebrew/caveats.rb b/Library/Homebrew/caveats.rb index 8cd1053fbf..a289a12202 100644 --- a/Library/Homebrew/caveats.rb +++ b/Library/Homebrew/caveats.rb @@ -25,7 +25,6 @@ class Caveats caveats << function_completion_caveats(:zsh) caveats << function_completion_caveats(:fish) caveats << plist_caveats - caveats << python_caveats caveats << elisp_caveats caveats.compact.join("\n") end @@ -108,53 +107,6 @@ class Caveats end end - def python_caveats - return unless keg - return unless keg.python_site_packages_installed? - - s = nil - homebrew_site_packages = Language::Python.homebrew_site_packages - user_site_packages = Language::Python.user_site_packages "python" - pth_file = user_site_packages/"homebrew.pth" - instructions = <<~EOS.gsub(/^/, " ") - mkdir -p #{user_site_packages} - echo 'import site; site.addsitedir("#{homebrew_site_packages}")' >> #{pth_file} - EOS - - if f.keg_only? - keg_site_packages = f.opt_prefix/"lib/python2.7/site-packages" - unless Language::Python.in_sys_path?("python", keg_site_packages) - s = <<~EOS - If you need Python to find bindings for this keg-only formula, run: - echo #{keg_site_packages} >> #{homebrew_site_packages/f.name}.pth - EOS - s += instructions unless Language::Python.reads_brewed_pth_files?("python") - end - return s - end - - return if Language::Python.reads_brewed_pth_files?("python") - - if !Language::Python.in_sys_path?("python", homebrew_site_packages) - s = <<~EOS - Python modules have been installed and Homebrew's site-packages is not - in your Python sys.path, so you will not be able to import the modules - this formula installed. If you plan to develop with these modules, - please run: - EOS - s += instructions - elsif keg.python_pth_files_installed? - s = <<~EOS - This formula installed .pth files to Homebrew's site-packages and your - Python isn't configured to process them, so you will not be able to - import the modules this formula installed. If you plan to develop - with these modules, please run: - EOS - s += instructions - end - s - end - def elisp_caveats return if f.keg_only? return unless keg diff --git a/Library/Homebrew/cmd/deps.rb b/Library/Homebrew/cmd/deps.rb index 0627e84bdc..40aa2f413d 100644 --- a/Library/Homebrew/cmd/deps.rb +++ b/Library/Homebrew/cmd/deps.rb @@ -17,7 +17,8 @@ #: #: By default, `deps` shows required and recommended dependencies for #: . To include the `:build` type dependencies, pass `--include-build`. -#: Similarly, pass `--include-optional` to include `:optional` dependencies. +#: Similarly, pass `--include-optional` to include `:optional` dependencies or +#: `--include-test` to include `:test` dependencies. #: To skip `:recommended` type dependencies, pass `--skip-recommended`. #: To include requirements in addition to dependencies, pass `--include-requirements`. #: @@ -30,8 +31,8 @@ #: If `--installed` is passed, output a tree for every installed formula. #: #: The placeholder is any combination of options `--include-build`, -#: `--include-optional`, `--skip-recommended`, and `--include-requirements` as -#: documented above. +#: `--include-optional`, `--include-test`, `--skip-recommended`, and +#: `--include-requirements` as documented above. #: #: If `--annotate` is passed, the build, optional, and recommended dependencies #: are marked as such in the output. @@ -42,7 +43,8 @@ #: dependencies of that formula. #: #: The placeholder is any combination of options `--include-build`, -#: `--include-optional`, and `--skip-recommended` as documented above. +#: `--include-optional`, `--include-test`, and `--skip-recommended` as +#: documented above. # The undocumented `--for-each` option will switch into the mode used by `deps --all`, # but only list dependencies for specified formula, one specified formula per line. @@ -111,6 +113,7 @@ module Homebrew end if ARGV.include?("--annotate") str = "#{str} [build]" if dep.build? + str = "#{str} [test]" if dep.test? str = "#{str} [optional" if dep.optional? str = "#{str} [recommended]" if dep.recommended? end @@ -125,6 +128,11 @@ module Homebrew else ignores << "build?" end + if ARGV.include?("--include-test") + includes << "test?" + else + ignores << "test?" + end if ARGV.include?("--include-optional") includes << "optional?" else @@ -136,6 +144,9 @@ module Homebrew deps = f.recursive_dependencies do |dependent, dep| if dep.recommended? Dependency.prune if ignores.include?("recommended?") || dependent.build.without?(dep) + elsif dep.test? + next if includes.include?("test?") + Dependency.prune elsif dep.optional? Dependency.prune if !includes.include?("optional?") && !dependent.build.with?(dep) elsif dep.build? @@ -145,6 +156,9 @@ module Homebrew reqs = f.recursive_requirements do |dependent, req| if req.recommended? Requirement.prune if ignores.include?("recommended?") || dependent.build.without?(req) + elsif req.test? + next if includes.include?("test?") + Requirement.prune elsif req.optional? Requirement.prune if !includes.include?("optional?") && !dependent.build.with?(req) elsif req.build? @@ -191,6 +205,7 @@ module Homebrew dependables = reqs + deps dependables = dependables.reject(&:optional?) unless ARGV.include?("--include-optional") dependables = dependables.reject(&:build?) unless ARGV.include?("--include-build") + dependables = dependables.reject(&:test?) unless ARGV.include?("--include-test") dependables = dependables.reject(&:recommended?) if ARGV.include?("--skip-recommended") max = dependables.length - 1 @dep_stack.push f.name diff --git a/Library/Homebrew/cmd/gist-logs.rb b/Library/Homebrew/cmd/gist-logs.rb index ab81a017e2..c30ee85cd9 100644 --- a/Library/Homebrew/cmd/gist-logs.rb +++ b/Library/Homebrew/cmd/gist-logs.rb @@ -113,14 +113,14 @@ module Homebrew url = "https://api.github.com/gists" data = { "public" => true, "files" => files, "description" => description } scopes = GitHub::CREATE_GIST_SCOPES - GitHub.open(url, data: data, scopes: scopes)["html_url"] + GitHub.open_api(url, data: data, scopes: scopes)["html_url"] end def create_issue(repo, title, body) url = "https://api.github.com/repos/#{repo}/issues" data = { "title" => title, "body" => body } scopes = GitHub::CREATE_ISSUE_SCOPES - GitHub.open(url, data: data, scopes: scopes)["html_url"] + GitHub.open_api(url, data: data, scopes: scopes)["html_url"] end def gist_logs diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb index 27f719c57e..a0e1cd4756 100644 --- a/Library/Homebrew/cmd/info.rb +++ b/Library/Homebrew/cmd/info.rb @@ -137,7 +137,12 @@ module Homebrew EOS end - kegs = f.installed_kegs.sort_by(&:version) + kegs = f.installed_kegs + heads, versioned = kegs.partition { |k| k.version.head? } + kegs = [ + *heads.sort_by { |k| -Tab.for_keg(k).time.to_i }, + *versioned.sort_by(&:version), + ] if kegs.empty? puts "Not installed" else diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index e1e4712ea1..bacdb18f02 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -344,7 +344,7 @@ module Homebrew rescue FormulaInstallationAlreadyAttemptedError # We already attempted to install f as part of the dependency tree of # another formula. In that case, don't generate an error, just move on. - return + nil rescue CannotInstallFormulaError => e ofail e.message end diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index 7c62d8092a..420c08dfe8 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -47,7 +47,7 @@ module Homebrew fi.install fi.finish rescue FormulaInstallationAlreadyAttemptedError - return + nil rescue Exception # rubocop:disable Lint/RescueException ignore_interrupts { restore_backup(keg, keg_was_linked) } raise diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index 2c4d3de0c5..d241d17b06 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -13,7 +13,7 @@ module Homebrew module_function def update_preinstall_header - @header_already_printed ||= begin + @update_preinstall_header ||= begin ohai "Auto-updated Homebrew!" if ARGV.include?("--preinstall") true end diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index debd5eea2c..7cbbecbb25 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -10,8 +10,8 @@ #: repository's HEAD will be checked for updates when a new stable or devel #: version has been released. #: -#: If are given, upgrade only the specified brews (but do so even -#: if they are pinned; see `pin`, `unpin`). +#: If are given, upgrade only the specified brews (unless they +#: are pinned; see `pin`, `unpin`). require "cmd/install" require "cleanup" @@ -118,7 +118,7 @@ module Homebrew fi = FormulaInstaller.new(f) fi.options = options - fi.build_bottle = ARGV.build_bottle? || (!f.bottled? && f.build.build_bottle?) + fi.build_bottle = ARGV.build_bottle? || (!f.bottled? && f.build.bottle?) fi.installed_on_request = !ARGV.named.empty? fi.link_keg ||= keg_was_linked if keg_had_linked_opt if tab @@ -139,7 +139,7 @@ module Homebrew rescue FormulaInstallationAlreadyAttemptedError # We already attempted to upgrade f as part of the dependency tree of # another formula. In that case, don't generate an error, just move on. - return + nil rescue CannotInstallFormulaError => e ofail e rescue BuildError => e diff --git a/Library/Homebrew/compat/dependency_collector.rb b/Library/Homebrew/compat/dependency_collector.rb index 88d393488f..8bea8a5aa9 100644 --- a/Library/Homebrew/compat/dependency_collector.rb +++ b/Library/Homebrew/compat/dependency_collector.rb @@ -52,11 +52,11 @@ class DependencyCollector output_deprecation(spec, "open-mpi") Dependency.new("open-mpi", tags) when :python, :python2 + output_deprecation(spec, "python@2") + Dependency.new("python@2", tags) + when :python3 output_deprecation(spec, "python") Dependency.new("python", tags) - when :python3 - output_deprecation(spec, "python3") - Dependency.new("python3", tags) when :emacs, :mysql, :perl, :postgresql, :rbenv, :ruby output_deprecation(spec) Dependency.new(spec.to_s, tags) diff --git a/Library/Homebrew/compat/requirements.rb b/Library/Homebrew/compat/requirements.rb index 38344c1fcd..3dd5c74795 100644 --- a/Library/Homebrew/compat/requirements.rb +++ b/Library/Homebrew/compat/requirements.rb @@ -84,16 +84,16 @@ end class PythonRequirement < Requirement fatal true satisfy do - odeprecated("PythonRequirement", "'depends_on \"python\"'") - which "python" + odeprecated("PythonRequirement", "'depends_on \"python@2\"'") + which "python2" end end class Python3Requirement < Requirement fatal true satisfy do - odeprecated("Python3Requirement", "'depends_on \"python3\"'") - which "python3" + odeprecated("Python3Requirement", "'depends_on \"python\"'") + which "python" end end diff --git a/Library/Homebrew/compat/requirements/language_module_requirement.rb b/Library/Homebrew/compat/requirements/language_module_requirement.rb index 5ddce7a66b..fc9dcc4428 100644 --- a/Library/Homebrew/compat/requirements/language_module_requirement.rb +++ b/Library/Homebrew/compat/requirements/language_module_requirement.rb @@ -38,9 +38,9 @@ class LanguageModuleRequirement < Requirement when :perl ["/usr/bin/env", "perl", "-e", "use #{@import_name}"] when :python - ["/usr/bin/env", "python", "-c", "import #{@import_name}"] + ["/usr/bin/env", "python2", "-c", "import #{@import_name}"] when :python3 - ["/usr/bin/env", "python3", "-c", "import #{@import_name}"] + ["/usr/bin/env", "python", "-c", "import #{@import_name}"] when :ruby ["/usr/bin/env", "ruby", "-rubygems", "-e", "require '#{@import_name}'"] end @@ -51,8 +51,8 @@ class LanguageModuleRequirement < Requirement when :lua then "luarocks-5.2 install" when :lua51 then "luarocks-5.1 install" when :perl then "cpan -i" - when :python then "pip install" - when :python3 then "pip3 install" + when :python then "pip3 install" + when :python3 then "pip install" when :ruby then "gem install" end end diff --git a/Library/Homebrew/constants.rb b/Library/Homebrew/constants.rb index 9514320abe..77c69f3e43 100644 --- a/Library/Homebrew/constants.rb +++ b/Library/Homebrew/constants.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true # RuboCop version used for `brew style` and `brew cask style` -HOMEBREW_RUBOCOP_VERSION = "0.52.1" -HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.16.0" # has to be updated when RuboCop version changes +HOMEBREW_RUBOCOP_VERSION = "0.53.0" +HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.17.0" # has to be updated when RuboCop version changes diff --git a/Library/Homebrew/dependable.rb b/Library/Homebrew/dependable.rb index 785eb94d8f..8722188388 100644 --- a/Library/Homebrew/dependable.rb +++ b/Library/Homebrew/dependable.rb @@ -1,7 +1,7 @@ require "options" module Dependable - RESERVED_TAGS = [:build, :optional, :recommended, :run, :linked].freeze + RESERVED_TAGS = [:build, :optional, :recommended, :run, :test, :linked].freeze def build? tags.include? :build @@ -19,8 +19,12 @@ module Dependable tags.include? :run end + def test? + tags.include? :test + end + def required? - !build? && !optional? && !recommended? + !build? && !test? && !optional? && !recommended? end def option_tags diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 7f0e7fbffe..7ae0703609 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -143,8 +143,9 @@ class Dependency private def merge_tags(deps) - options = deps.flat_map(&:option_tags).uniq - merge_necessity(deps) + merge_temporality(deps) + options + other_tags = deps.flat_map(&:option_tags).uniq + other_tags << :test if deps.flat_map(&:tags).include?(:test) + merge_necessity(deps) + merge_temporality(deps) + other_tags end def merge_necessity(deps) diff --git a/Library/Homebrew/dependency_collector.rb b/Library/Homebrew/dependency_collector.rb index 7d3b90f9c6..74f42a6aaf 100644 --- a/Library/Homebrew/dependency_collector.rb +++ b/Library/Homebrew/dependency_collector.rb @@ -70,8 +70,8 @@ class DependencyCollector Dependency.new("xz", tags) unless which("xz") end - def zip_dep_if_needed(tags) - Dependency.new("zip", tags) unless which("zip") + def unzip_dep_if_needed(tags) + Dependency.new("unzip", tags) unless which("unzip") end def bzip2_dep_if_needed(tags) @@ -166,7 +166,7 @@ class DependencyCollector def parse_url_spec(url, tags) case File.extname(url) when ".xz" then xz_dep_if_needed(tags) - when ".zip" then zip_dep_if_needed(tags) + when ".zip" then unzip_dep_if_needed(tags) when ".bz2" then bzip2_dep_if_needed(tags) when ".lha", ".lzh" then Dependency.new("lha", tags) when ".lz" then Dependency.new("lzip", tags) diff --git a/Library/Homebrew/dev-cmd/test.rb b/Library/Homebrew/dev-cmd/test.rb index 6622a8c257..56f439e3e0 100644 --- a/Library/Homebrew/dev-cmd/test.rb +++ b/Library/Homebrew/dev-cmd/test.rb @@ -45,6 +45,18 @@ module Homebrew next end + # Don't test formulae missing test dependencies + missing_test_deps = f.recursive_dependencies do |_, dependency| + Dependency.prune if dependency.installed? + next if dependency.test? + Dependency.prune if dependency.optional? + Dependency.prune if dependency.build? + end.map(&:to_s) + unless missing_test_deps.empty? + ofail "#{f.full_name} is missing test dependencies: #{missing_test_deps.join(" ")}" + next + end + puts "Testing #{f.full_name}" env = ENV.to_hash diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index 8cbf124e61..706bb201a9 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -934,7 +934,7 @@ module Homebrew from your PATH variable. Python scripts will now install into #{HOMEBREW_PREFIX}/bin. You can delete anything, except 'Extras', from the #{HOMEBREW_PREFIX}/share/python - (and #{HOMEBREW_PREFIX}/share/python3) dir and install affected Python packages + (and #{HOMEBREW_PREFIX}/share/python@2) dir and install affected Python packages anew with `pip install --upgrade`. EOS end @@ -966,7 +966,7 @@ module Homebrew Putting non-prefixed coreutils in your path can cause gmp builds to fail. EOS rescue FormulaUnavailableError - return + nil end def check_for_non_prefixed_findutils @@ -981,7 +981,7 @@ module Homebrew Putting non-prefixed findutils in your path can cause python builds to fail. EOS rescue FormulaUnavailableError - return + nil end def check_for_pydistutils_cfg_in_home @@ -1016,24 +1016,6 @@ module Homebrew EOS end - def check_for_pth_support - homebrew_site_packages = Language::Python.homebrew_site_packages - return unless homebrew_site_packages.directory? - return if Language::Python.reads_brewed_pth_files?("python") != false - return unless Language::Python.in_sys_path?("python", homebrew_site_packages) - - user_site_packages = Language::Python.user_site_packages "python" - <<~EOS - Your default Python does not recognize the Homebrew site-packages - directory as a special site-packages directory, which means that .pth - files will not be followed. This means you will not be able to import - some modules after installing them with Homebrew, like wxpython. To fix - this for the current user, you can run: - mkdir -p #{user_site_packages} - echo 'import site; site.addsitedir("#{homebrew_site_packages}")' >> #{user_site_packages}/homebrew.pth - EOS - end - def check_for_external_cmd_name_conflict cmds = Tap.cmd_directories.flat_map { |p| Dir["#{p}/brew-*"] }.uniq cmds = cmds.select { |cmd| File.file?(cmd) && File.executable?(cmd) } diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index e85661d76d..6e750806f0 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -604,7 +604,7 @@ class GitHubPrivateRepositoryReleaseDownloadStrategy < GitHubPrivateRepositoryDo def fetch_release_metadata release_url = "https://api.github.com/repos/#{@owner}/#{@repo}/releases/tags/#{@tag}" - GitHub.open(release_url) + GitHub.open_api(release_url) end end diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 42c62338a8..20ad2a3788 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -343,8 +343,8 @@ class FormulaAmbiguousPythonError < RuntimeError def initialize(formula) super <<~EOS The version of python to use with the virtualenv in the `#{formula.full_name}` formula - cannot be guessed automatically. If the simultaneous use of python and python3 - is intentional, please add `:using => "python"` or `:using => "python3"` to + cannot be guessed automatically. If the simultaneous use of python and python@2 + is intentional, please add `:using => "python"` or `:using => "python@2"` to `virtualenv_install_with_resources` to resolve the ambiguity manually. EOS end diff --git a/Library/Homebrew/extend/ENV.rb b/Library/Homebrew/extend/ENV.rb index 374be49b92..002220764a 100644 --- a/Library/Homebrew/extend/ENV.rb +++ b/Library/Homebrew/extend/ENV.rb @@ -28,9 +28,9 @@ module EnvActivation end def clear_sensitive_environment! - ENV.each_key do |key| + each_key do |key| next unless /(cookie|key|token|password)/i =~ key - ENV.delete key + delete key end end end diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb index b4f0dfcac0..660b9b3a3c 100644 --- a/Library/Homebrew/extend/ENV/super.rb +++ b/Library/Homebrew/extend/ENV/super.rb @@ -173,11 +173,22 @@ module Superenv end def determine_library_paths - PATH.new( + paths = [ keg_only_deps.map(&:opt_lib), HOMEBREW_PREFIX/"lib", - homebrew_extra_library_paths, - ).existing + ] + + if compiler == :llvm_clang + if MacOS::CLT.installed? + paths << "/usr/lib" + else + paths << "#{MacOS.sdk_path}/usr/lib" + end + paths << Formula["llvm"].opt_lib.to_s + end + + paths += homebrew_extra_library_paths + PATH.new(paths).existing end def determine_dependencies diff --git a/Library/Homebrew/extend/os/linux/system_config.rb b/Library/Homebrew/extend/os/linux/system_config.rb index cf01765623..47eca7697e 100644 --- a/Library/Homebrew/extend/os/linux/system_config.rb +++ b/Library/Homebrew/extend/os/linux/system_config.rb @@ -31,7 +31,7 @@ class SystemConfig return "N/A" unless CoreTap.instance.installed? Formulary.factory(formula).linked_version || "N/A" rescue FormulaUnavailableError - return "N/A" + "N/A" end def dump_verbose_config(out = $stdout) diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 29f6c728da..e04ac1c936 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -2219,12 +2219,12 @@ class Formula # # `build.with?` or `build.without? "another_formula"`: # depends_on "postgresql" if build.without? "sqlite" # - #
# Python 2.7:
-    # depends_on "python"
- #
# Python 2.7 but use system Python where possible
-    # depends_on "python" if MacOS.version <= :snow_leopard
- #
# Python 3.x if the `--with-python3` is given to `brew install example`
+    # 
# Python 3.x if the `--with-python` is given to `brew install example`
     # depends_on "python3" => :optional
+ #
# Python 2.7:
+    # depends_on "python@2"
+ #
# Python 2.7 but use system Python where possible
+    # depends_on "python@2" if MacOS.version <= :snow_leopard
def depends_on(dep) specs.each { |spec| spec.depends_on(dep) } end diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb index c10c69e674..67edba9c5e 100644 --- a/Library/Homebrew/formula_versions.rb +++ b/Library/Homebrew/formula_versions.rb @@ -44,7 +44,7 @@ class FormulaVersions # continue walking the history ohai "#{e} in #{name} at revision #{rev}", e.backtrace if ARGV.debug? rescue FormulaUnavailableError - return + nil ensure Homebrew.raise_deprecation_exceptions = false end diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb index e3b93fa728..4c81de33aa 100644 --- a/Library/Homebrew/keg.rb +++ b/Library/Homebrew/keg.rb @@ -256,7 +256,11 @@ class Keg aliases.each do |a| alias_symlink = opt/a - alias_symlink.delete if alias_symlink.symlink? || alias_symlink.exist? + if alias_symlink.symlink? && alias_symlink.exist? + alias_symlink.delete if alias_symlink.realpath == opt_record.realpath + elsif alias_symlink.symlink? || alias_symlink.exist? + alias_symlink.delete + end end Pathname.glob("#{opt_record}@*").each do |a| @@ -519,6 +523,7 @@ class Keg def delete_pyc_files! find { |pn| pn.delete if %w[.pyc .pyo].include?(pn.extname) } + find { |pn| pn.delete if pn.basename.to_s == "__pycache__" } end private diff --git a/Library/Homebrew/language/python.rb b/Library/Homebrew/language/python.rb index 648abb5b11..de373efda4 100644 --- a/Library/Homebrew/language/python.rb +++ b/Library/Homebrew/language/python.rb @@ -9,7 +9,7 @@ module Language Version.create(version.to_s) end - def self.homebrew_site_packages(version = "2.7") + def self.homebrew_site_packages(version = "3.6") HOMEBREW_PREFIX/"lib/python#{version}/site-packages" end @@ -89,7 +89,7 @@ module Language # @param venv_root [Pathname, String] the path to the root of the virtualenv # (often `libexec/"venv"`) # @param python [String] which interpreter to use (e.g. "python" - # or "python3") + # or "python2") # @param formula [Formula] the active Formula # @return [Virtualenv] a {Virtualenv} instance def virtualenv_create(venv_root, python = "python", formula = self) @@ -115,8 +115,8 @@ module Language # Returns true if a formula option for the specified python is currently # active or if the specified python is required by the formula. Valid - # inputs are "python", "python3", :python, and :python3. Note that - # "with-python", "without-python", "with-python3", and "without-python3" + # inputs are "python", "python2", :python, and :python2. Note that + # "with-python", "without-python", "with-python@2", and "without-python@2" # formula options are handled correctly even if not associated with any # corresponding depends_on statement. # @api private @@ -128,16 +128,17 @@ module Language # Helper method for the common case of installing a Python application. # Creates a virtualenv in `libexec`, installs all `resource`s defined # on the formula, and then installs the formula. An options hash may be - # passed (e.g., :using => "python3") to override the default, guessed - # formula preference for python or python3, or to resolve an ambiguous - # case where it's not clear whether python or python3 should be the + # passed (e.g., :using => "python") to override the default, guessed + # formula preference for python or python2, or to resolve an ambiguous + # case where it's not clear whether python or python2 should be the # default guess. def virtualenv_install_with_resources(options = {}) python = options[:using] if python.nil? - wanted = %w[python python@2 python@3 python3].select { |py| needs_python?(py) } + wanted = %w[python python@2 python2 python3 python@3].select { |py| needs_python?(py) } raise FormulaAmbiguousPythonError, self if wanted.size > 1 python = wanted.first || "python2.7" + python = "python3" if python == "python" end venv = virtualenv_create(libexec, python.delete("@")) venv.pip_install resources @@ -154,7 +155,7 @@ module Language # @param venv_root [Pathname, String] the path to the root of the # virtualenv # @param python [String] which interpreter to use; i.e. "python" or - # "python3" + # "python2" def initialize(formula, venv_root, python) @formula = formula @venv_root = Pathname.new(venv_root) @@ -180,11 +181,11 @@ module Language end end - # Robustify symlinks to survive python3 patch upgrades + # Robustify symlinks to survive python patch upgrades @venv_root.find do |f| next unless f.symlink? next unless (rp = f.realpath.to_s).start_with? HOMEBREW_CELLAR - python = rp.include?("python3") ? "python3" : "python" + python = rp.include?("python@2") ? "python@2" : "python" new_target = rp.sub %r{#{HOMEBREW_CELLAR}/#{python}/[^/]+}, Formula[python].opt_prefix f.unlink f.make_symlink new_target @@ -192,7 +193,7 @@ module Language Pathname.glob(@venv_root/"lib/python*/orig-prefix.txt").each do |prefix_file| prefix_path = prefix_file.read - python = prefix_path.include?("python3") ? "python3" : "python" + python = prefix_path.include?("python@2") ? "python@2" : "python" prefix_path.sub! %r{^#{HOMEBREW_CELLAR}/#{python}/[^/]+}, Formula[python].opt_prefix prefix_file.atomic_write prefix_path end diff --git a/Library/Homebrew/linkage_checker.rb b/Library/Homebrew/linkage_checker.rb index 345fde47e6..f6beae295b 100644 --- a/Library/Homebrew/linkage_checker.rb +++ b/Library/Homebrew/linkage_checker.rb @@ -63,8 +63,7 @@ class LinkageChecker formula.build.without?(dep) end declared_deps = formula.deps.reject { |dep| filter_out.call(dep) }.map(&:name) - recursive_deps = keg.to_formula.declared_runtime_dependencies - .map { |dep| dep.to_formula.full_name } + recursive_deps = keg.to_formula.declared_runtime_dependencies.map { |dep| dep.to_formula.name } declared_dep_names = declared_deps.map { |dep| dep.split("/").last } indirect_deps = [] undeclared_deps = [] diff --git a/Library/Homebrew/migrator.rb b/Library/Homebrew/migrator.rb index 8664d474be..503f889852 100644 --- a/Library/Homebrew/migrator.rb +++ b/Library/Homebrew/migrator.rb @@ -183,7 +183,7 @@ class Migrator end def migrate - oh1 "Migrating #{Formatter.identifier(oldname)} to #{Formatter.identifier(newname)}" + oh1 "Processing #{Formatter.identifier(oldname)} formula rename to #{Formatter.identifier(newname)}" lock unlink_oldname unlink_newname if new_cellar.exist? @@ -193,6 +193,14 @@ class Migrator link_oldname_opt link_newname unless old_linked_keg.nil? update_tabs + return unless formula.outdated? + opoo <<~EOS + #{Formatter.identifier(newname)} is outdated! + To avoid broken installations, as soon as possible please run: + brew upgrade + Or, if you're OK with a less reliable fix: + brew upgrade #{newname} + EOS rescue Interrupt ignore_interrupts { backup_oldname } rescue Exception => e # rubocop:disable Lint/RescueException @@ -226,7 +234,7 @@ class Migrator end end - oh1 "Moving #{Formatter.identifier(oldname)} children" + oh1 "Moving #{Formatter.identifier(oldname)} versions to #{new_cellar}" if new_cellar.exist? FileUtils.mv(old_cellar.children, new_cellar) else @@ -261,7 +269,7 @@ class Migrator end def unlink_newname - oh1 "Unlinking #{Formatter.identifier(newname)}" + oh1 "Temporarily unlinking #{Formatter.identifier(newname)}" new_cellar.subdirs.each do |d| keg = Keg.new(d) keg.unlink @@ -269,7 +277,7 @@ class Migrator end def link_newname - oh1 "Linking #{Formatter.identifier(newname)}" + oh1 "Relinking #{Formatter.identifier(newname)}" new_keg = Keg.new(new_linked_keg_record) # If old_keg wasn't linked then we just optlink a keg. @@ -288,7 +296,8 @@ class Migrator new_keg.remove_linked_keg_record if new_keg.linked? begin - new_keg.link + mode = OpenStruct.new(overwrite: true) + new_keg.link(mode) rescue Keg::ConflictError => e onoe "Error while executing `brew link` step on #{newname}" puts e diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index f977a066da..2e4ec63819 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -131,7 +131,7 @@ module OS xcodebuild_output = Utils.popen_read(xcodebuild_path, "-version") next unless $CHILD_STATUS.success? - xcode_version = xcodebuild_output[/Xcode (\d(\.\d)*)/, 1] + xcode_version = xcodebuild_output[/Xcode (\d+(\.\d+)*)/, 1] return xcode_version if xcode_version # Xcode 2.x's xcodebuild has a different version string diff --git a/Library/Homebrew/rubocops.rb b/Library/Homebrew/rubocops.rb index 8dc49bb459..f1923ee654 100644 --- a/Library/Homebrew/rubocops.rb +++ b/Library/Homebrew/rubocops.rb @@ -2,6 +2,7 @@ require_relative "./rubocops/bottle_block_cop" require_relative "./rubocops/formula_desc_cop" require_relative "./rubocops/components_order_cop" require_relative "./rubocops/components_redundancy_cop" +require_relative "./rubocops/dependency_order_cop" require_relative "./rubocops/homepage_cop" require_relative "./rubocops/text_cop" require_relative "./rubocops/caveats_cop" diff --git a/Library/Homebrew/rubocops/dependency_order_cop.rb b/Library/Homebrew/rubocops/dependency_order_cop.rb new file mode 100644 index 0000000000..1d1481f280 --- /dev/null +++ b/Library/Homebrew/rubocops/dependency_order_cop.rb @@ -0,0 +1,166 @@ +require_relative "./extend/formula_cop" + +module RuboCop + module Cop + module NewFormulaAudit + # This cop checks for correct order of `depends_on` in a Formula + # + # precedence order: + # build-time > run-time > normal > recommended > optional + class DependencyOrder < FormulaCop + def audit_formula(_node, _class_node, _parent_class_node, body_node) + check_dependency_nodes_order(body_node) + [:devel, :head, :stable].each do |block_name| + block = find_block(body_node, block_name) + next unless block + check_dependency_nodes_order(block.body) + end + end + + def check_dependency_nodes_order(parent_node) + return if parent_node.nil? + dependency_nodes = fetch_depends_on_nodes(parent_node) + ordered = dependency_nodes.sort { |a, b| sort_by_dependency_name(a, b) } + ordered = sort_dependencies_by_type(ordered) + sort_conditional_dependencies!(ordered) + verify_order_in_source(ordered) + end + + # Match all `depends_on` nodes among childnodes of given parent node + def fetch_depends_on_nodes(parent_node) + parent_node.each_child_node.select { |x| depends_on_node?(x) } + end + + def sort_by_dependency_name(a, b) + a_name = dependency_name(a) + b_name = dependency_name(b) + if a_name < b_name + -1 + elsif a_name > b_name + 1 + else + 0 + end + end + + # Separate dependencies according to precedence order: + # build-time > run-time > normal > recommended > optional + def sort_dependencies_by_type(dependency_nodes) + ordered = [] + ordered.concat(dependency_nodes.select { |dep| buildtime_dependency? dep }.to_a) + ordered.concat(dependency_nodes.select { |dep| runtime_dependency? dep }.to_a) + ordered.concat(dependency_nodes.reject { |dep| negate_normal_dependency? dep }.to_a) + ordered.concat(dependency_nodes.select { |dep| recommended_dependency? dep }.to_a) + ordered.concat(dependency_nodes.select { |dep| optional_dependency? dep }.to_a) + end + + # `depends_on :apple if build.with? "foo"` should always be defined + # after `depends_on :foo` + # This method reorders dependencies array according to above rule + def sort_conditional_dependencies!(ordered) + length = ordered.size + idx = 0 + while idx < length + idx1, idx2 = nil + ordered.each_with_index do |dep, pos| + idx = pos+1 + match_nodes = build_with_dependency_name(dep) + idx1 = pos if match_nodes && !match_nodes.empty? + next unless idx1 + idx2 = nil + ordered.drop(idx1+1).each_with_index do |dep2, pos2| + next unless match_nodes.index(dependency_name(dep2)) + idx2 = pos2 if idx2.nil? || pos2 > idx2 + end + break if idx2 + end + insert_after!(ordered, idx1, idx2+idx1) if idx2 + end + ordered + end + + # Verify actual order of sorted `depends_on` nodes in source code + # Else raise RuboCop problem + def verify_order_in_source(ordered) + ordered.each_with_index do |dependency_node_1, idx| + l1 = line_number(dependency_node_1) + dependency_node_2 = nil + ordered.drop(idx+1).each do |node2| + l2 = line_number(node2) + dependency_node_2 = node2 if l2 < l1 + end + next unless dependency_node_2 + @offensive_nodes = [dependency_node_1, dependency_node_2] + component_problem dependency_node_1, dependency_node_2 + end + end + + # Node pattern method to match + # `depends_on` variants + def_node_matcher :depends_on_node?, <<~EOS + {(if _ (send nil? :depends_on ...) nil?) + (send nil? :depends_on ...)} + EOS + + def_node_search :buildtime_dependency?, "(sym :build)" + + def_node_search :recommended_dependency?, "(sym :recommended)" + + def_node_search :runtime_dependency?, "(sym :run)" + + def_node_search :optional_dependency?, "(sym :optional)" + + def_node_search :negate_normal_dependency?, "(sym {:build :recommended :run :optional})" + + # Node pattern method to extract `name` in `depends_on :name` + def_node_search :dependency_name_node, <<~EOS + {(send nil? :depends_on {(hash (pair $_ _)) $({str sym} _)}) + (if _ (send nil? :depends_on {(hash (pair $_ _)) $({str sym} _)}) nil?)} + EOS + + # Node pattern method to extract `name` in `build.with? :name` + def_node_search :build_with_dependency_node, <<~EOS + (send (send nil? :build) :with? $({str sym} _)) + EOS + + def insert_after!(arr, idx1, idx2) + arr.insert(idx2+1, arr.delete_at(idx1)) + end + + def build_with_dependency_name(node) + match_nodes = build_with_dependency_node(node) + match_nodes = match_nodes.to_a.delete_if(&:nil?) + match_nodes.map { |n| string_content(n) } unless match_nodes.empty? + end + + def dependency_name(dependency_node) + match_node = dependency_name_node(dependency_node).to_a.first + string_content(match_node) if match_node + end + + def autocorrect(_node) + succeeding_node = @offensive_nodes[0] + preceding_node = @offensive_nodes[1] + lambda do |corrector| + reorder_components(corrector, succeeding_node, preceding_node) + end + end + + private + + def component_problem(c1, c2) + offending_node(c1) + problem "dependency \"#{dependency_name(c1)}\" (line #{line_number(c1)}) should be put before dependency \"#{dependency_name(c2)}\" (line #{line_number(c2)})" + end + + # Reorder two nodes in the source, using the corrector instance in autocorrect method + def reorder_components(corrector, node1, node2) + indentation = " " * (start_column(node2) - line_start_column(node2)) + line_breaks = "\n" + corrector.insert_before(node2.source_range, node1.source + line_breaks + indentation) + corrector.remove(range_with_surrounding_space(range: node1.source_range, side: :left)) + end + end + end + end +end diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb index e53c02a449..2c20e62dec 100644 --- a/Library/Homebrew/rubocops/extend/formula_cop.rb +++ b/Library/Homebrew/rubocops/extend/formula_cop.rb @@ -4,6 +4,8 @@ require_relative "../../extend/string" module RuboCop module Cop class FormulaCop < Cop + include RangeHelp + attr_accessor :file_path @registry = Cop.registry diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index ea74fae098..e59e2a5500 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -108,10 +108,10 @@ class Sandbox unless logs.empty? if @logfile - log = open(@logfile, "w") - log.write logs - log.write "\nWe use time to filter sandbox log. Therefore, unrelated logs may be recorded.\n" - log.close + File.open(@logfile, "w") do |log| + log.write logs + log.write "\nWe use time to filter sandbox log. Therefore, unrelated logs may be recorded.\n" + end end if @failed && ARGV.verbose? diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index aa0208d51a..0fed724a8d 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -326,8 +326,8 @@ class Tab < OpenStruct "time" => time, "source_modified_time" => source_modified_time.to_i, "HEAD" => self.HEAD, - "stdlib" => (stdlib.to_s if stdlib), - "compiler" => (compiler.to_s if compiler), + "stdlib" => (stdlib&.to_s), + "compiler" => (compiler&.to_s), "aliases" => aliases, "runtime_dependencies" => runtime_dependencies, "source" => source, diff --git a/Library/Homebrew/test/ENV_spec.rb b/Library/Homebrew/test/ENV_spec.rb index 07f6cdb6b0..8b39e52d78 100644 --- a/Library/Homebrew/test/ENV_spec.rb +++ b/Library/Homebrew/test/ENV_spec.rb @@ -141,6 +141,20 @@ shared_examples EnvActivation do expect(subject["MAKEFLAGS"]).to eq("-j4") end + + describe "#clear_sensitive_environment!" do + it "removes sensitive environment variables" do + subject["SECRET_TOKEN"] = "password" + subject.clear_sensitive_environment! + expect(subject).not_to include("SECRET_TOKEN") + end + + it "leaves non-sensitive environment variables alone" do + subject["FOO"] = "bar" + subject.clear_sensitive_environment! + expect(subject["FOO"]).to eq "bar" + end + end end describe Stdenv do diff --git a/Library/Homebrew/test/Gemfile.lock b/Library/Homebrew/test/Gemfile.lock index a3f9c4c47e..b69a5f0a71 100644 --- a/Library/Homebrew/test/Gemfile.lock +++ b/Library/Homebrew/test/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - ast (2.3.0) + ast (2.4.0) codecov (0.1.10) json simplecov @@ -9,36 +9,36 @@ GEM diff-lcs (1.3) docile (1.1.5) json (2.1.0) - parallel (1.12.0) - parallel_tests (2.17.0) + parallel (1.12.1) + parallel_tests (2.21.2) parallel - parser (2.4.0.2) - ast (~> 2.3) + parser (2.5.0.2) + ast (~> 2.4.0) powerpack (0.1.1) rainbow (3.0.0) - rspec (3.6.0) - rspec-core (~> 3.6.0) - rspec-expectations (~> 3.6.0) - rspec-mocks (~> 3.6.0) - rspec-core (3.6.0) - rspec-support (~> 3.6.0) - rspec-expectations (3.6.0) + rspec (3.7.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-core (3.7.1) + rspec-support (~> 3.7.0) + rspec-expectations (3.7.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.6.0) + rspec-support (~> 3.7.0) rspec-its (1.2.0) rspec-core (>= 3.0.0) rspec-expectations (>= 3.0.0) - rspec-mocks (3.6.0) + rspec-mocks (3.7.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.6.0) + rspec-support (~> 3.7.0) rspec-retry (0.5.6) rspec-core (> 3.3, < 3.8) - rspec-support (3.6.0) + rspec-support (3.7.1) rspec-wait (0.0.9) rspec (>= 3, < 4) - rubocop (0.52.1) + rubocop (0.53.0) parallel (~> 1.10) - parser (>= 2.4.0.2, < 3.0) + parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) @@ -62,7 +62,7 @@ DEPENDENCIES rspec-its rspec-retry rspec-wait - rubocop (= 0.52.1) + rubocop (= 0.53.0) simplecov BUNDLED WITH diff --git a/Library/Homebrew/test/caveats_spec.rb b/Library/Homebrew/test/caveats_spec.rb index 96ed7ea179..ec256f3e61 100644 --- a/Library/Homebrew/test/caveats_spec.rb +++ b/Library/Homebrew/test/caveats_spec.rb @@ -201,45 +201,5 @@ describe Caveats do expect(caveats).to include(HOMEBREW_PREFIX/"share/fish/vendor_completions.d") end end - - context "python caveats" do - before do - (f.prefix.resolved_path/"lib/python2.7/site-packages").mkpath - end - - context "when f is not keg_only" do - let(:f) { - formula do - url "foo-1.0" - end - } - let(:caveats) { described_class.new(f).caveats } - let(:user_site_packages) { Language::Python.user_site_packages("python") } - - it "give commands to run when Homebrew's site-packages is not in Python sys.path" do - expect(caveats).to include("Homebrew's site-packages is not\nin your Python sys.path") - expect(caveats).to include(user_site_packages) - expect(caveats).to include("import site") - end - - it "gives commands to run when python pth files are installed" do - allow(Homebrew).to receive(:_system).and_return(true) - allow(Dir).to receive(:[]).with(any_args).and_return(["blah.pth"]) - expect(caveats).to include(".pth files to Homebrew's site-packages and your\nPython isn't configured") - expect(caveats).to include(user_site_packages) - expect(caveats).to include("import site") - end - end - - it "gives commands to run when formula is keg_only" do - f = formula do - url "foo-1.0" - keg_only "some reason" - end - caveats = described_class.new(f).caveats - homebrew_site_packages = Language::Python.homebrew_site_packages - expect(caveats).to include("echo #{f.opt_prefix}/lib/python2.7/site-packages >> #{homebrew_site_packages/f.name}.pth") - end - end end end diff --git a/Library/Homebrew/test/cmd/migrate_spec.rb b/Library/Homebrew/test/cmd/migrate_spec.rb index 18c94fa018..83dee0cb65 100644 --- a/Library/Homebrew/test/cmd/migrate_spec.rb +++ b/Library/Homebrew/test/cmd/migrate_spec.rb @@ -29,7 +29,7 @@ describe "brew migrate", :integration_test do install_and_rename_coretap_formula "testball1", "testball2" expect { brew "migrate", "testball1" } - .to output(/Migrating testball1 to testball2/).to_stdout + .to output(/Processing testball1 formula rename to testball2/).to_stdout .and not_to_output.to_stderr .and be_a_success end diff --git a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb index eb256b9245..49678f3ace 100644 --- a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb +++ b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb @@ -16,7 +16,7 @@ describe Homebrew do ], } - allow(GitHub).to receive(:open).and_yield(json_response) + allow(GitHub).to receive(:open_api).and_yield(json_response) expect(described_class.search_taps("some-formula")) .to match(["homebrew/foo/some-formula"]) diff --git a/Library/Homebrew/test/download_strategies_spec.rb b/Library/Homebrew/test/download_strategies_spec.rb index 7ad070fc44..f1c64db717 100644 --- a/Library/Homebrew/test/download_strategies_spec.rb +++ b/Library/Homebrew/test/download_strategies_spec.rb @@ -116,7 +116,7 @@ describe GitHubPrivateRepositoryReleaseDownloadStrategy do describe "#fetch_release_metadata" do it "fetches release metadata from GitHub" do expected_release_url = "https://api.github.com/repos/owner/repo/releases/tags/tag" - expect(GitHub).to receive(:open).with(expected_release_url).and_return({}) + expect(GitHub).to receive(:open_api).with(expected_release_url).and_return({}) subject.send(:fetch_release_metadata) end end diff --git a/Library/Homebrew/test/language_module_requirement_spec.rb b/Library/Homebrew/test/language_module_requirement_spec.rb index 6ca8cbd0e8..74d092bac9 100644 --- a/Library/Homebrew/test/language_module_requirement_spec.rb +++ b/Library/Homebrew/test/language_module_requirement_spec.rb @@ -31,10 +31,6 @@ describe LanguageModuleRequirement, :needs_compat do it "does not satisfy invalid dependencies" do expect(described_class.new(:python, "notapackage")).not_to be_satisfied end - - it "satisfies valid dependencies" do - expect(described_class.new(:python, "datetime")).to be_satisfied - end end context "when the language is Ruby" do diff --git a/Library/Homebrew/test/os/linux/dependency_collector_spec.rb b/Library/Homebrew/test/os/linux/dependency_collector_spec.rb index 543ed39b0b..a8f85b4cac 100644 --- a/Library/Homebrew/test/os/linux/dependency_collector_spec.rb +++ b/Library/Homebrew/test/os/linux/dependency_collector_spec.rb @@ -10,7 +10,7 @@ describe DependencyCollector do describe "#add" do resource = Resource.new - context "when xz, zip, and bzip2 are not available" do + context "when xz, unzip, and bzip2 are not available" do it "creates a resource dependency from a '.xz' URL" do resource.url("http://example.com/foo.xz") allow_any_instance_of(Object).to receive(:which).with("xz") @@ -19,8 +19,8 @@ describe DependencyCollector do it "creates a resource dependency from a '.zip' URL" do resource.url("http://example.com/foo.zip") - allow_any_instance_of(Object).to receive(:which).with("zip") - expect(subject.add(resource)).to eq(Dependency.new("zip", [:build])) + allow_any_instance_of(Object).to receive(:which).with("unzip") + expect(subject.add(resource)).to eq(Dependency.new("unzip", [:build])) end it "creates a resource dependency from a '.bz2' URL" do @@ -39,7 +39,7 @@ describe DependencyCollector do it "does not create a resource dependency from a '.zip' URL" do resource.url("http://example.com/foo.zip") - allow_any_instance_of(Object).to receive(:which).with("zip").and_return(Pathname.new("foo")) + allow_any_instance_of(Object).to receive(:which).with("unzip").and_return(Pathname.new("foo")) expect(subject.add(resource)).to be nil end diff --git a/Library/Homebrew/test/rubocops/dependency_order_cop_spec.rb b/Library/Homebrew/test/rubocops/dependency_order_cop_spec.rb new file mode 100644 index 0000000000..92ca724750 --- /dev/null +++ b/Library/Homebrew/test/rubocops/dependency_order_cop_spec.rb @@ -0,0 +1,75 @@ +require_relative "../../rubocops/dependency_order_cop" + +describe RuboCop::Cop::NewFormulaAudit::DependencyOrder do + subject(:cop) { described_class.new } + + context "depends_on" do + it "wrong conditional depends_on order" do + expect_offense(<<~RUBY) + class Foo < Formula + homepage "http://example.com" + url "http://example.com/foo-1.0.tgz" + depends_on "apple" if build.with? "foo" + depends_on "foo" => :optional + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 5) should be put before dependency "apple" (line 4) + end + RUBY + end + + it "wrong alphabetical depends_on order" do + expect_offense(<<~RUBY) + class Foo < Formula + homepage "http://example.com" + url "http://example.com/foo-1.0.tgz" + depends_on "foo" + depends_on "bar" + ^^^^^^^^^^^^^^^^ dependency "bar" (line 5) should be put before dependency "foo" (line 4) + end + RUBY + end + + it "wrong conditional depends_on order" do + expect_offense(<<~RUBY) + class Foo < Formula + homepage "http://example.com" + url "http://example.com/foo-1.0.tgz" + head do + depends_on "apple" if build.with? "foo" + depends_on "bar" + ^^^^^^^^^^^^^^^^ dependency "bar" (line 6) should be put before dependency "apple" (line 5) + depends_on "foo" => :optional + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 7) should be put before dependency "apple" (line 5) + end + depends_on "apple" if build.with? "foo" + depends_on "foo" => :optional + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 10) should be put before dependency "apple" (line 9) + end + RUBY + end + end + + context "autocorrect" do + it "wrong conditional depends_on order" do + source = <<~EOS + class Foo < Formula + homepage "http://example.com" + url "http://example.com/foo-1.0.tgz" + depends_on "apple" if build.with? "foo" + depends_on "foo" => :optional + end + EOS + + correct_source = <<~EOS + class Foo < Formula + homepage "http://example.com" + url "http://example.com/foo-1.0.tgz" + depends_on "foo" => :optional + depends_on "apple" if build.with? "foo" + end + EOS + + corrected_source = autocorrect_source(source) + expect(corrected_source).to eq(correct_source) + end + end +end diff --git a/Library/Homebrew/test/support/lib/config.rb b/Library/Homebrew/test/support/lib/config.rb index e54fc111fa..a59d80c995 100644 --- a/Library/Homebrew/test/support/lib/config.rb +++ b/Library/Homebrew/test/support/lib/config.rb @@ -16,9 +16,9 @@ TEST_TMPDIR = ENV.fetch("HOMEBREW_TEST_TMPDIR") do |k| end # Paths pointing into the Homebrew code base that persist across test runs -HOMEBREW_LIBRARY_PATH = Pathname.new(File.expand_path("../../../..", __FILE__)) +HOMEBREW_LIBRARY_PATH = Pathname.new(File.expand_path("../../..", __dir__)) HOMEBREW_SHIMS_PATH = HOMEBREW_LIBRARY_PATH.parent+"Homebrew/shims" -HOMEBREW_LOAD_PATH = [File.expand_path("..", __FILE__), HOMEBREW_LIBRARY_PATH].join(":") +HOMEBREW_LOAD_PATH = [File.expand_path(__dir__), HOMEBREW_LIBRARY_PATH].join(":") # Paths redirected to a temporary directory and wiped at the end of the test run HOMEBREW_PREFIX = Pathname.new(TEST_TMPDIR).join("prefix") diff --git a/Library/Homebrew/test/utils/analytics_spec.rb b/Library/Homebrew/test/utils/analytics_spec.rb index bb6cda0b12..4526194d81 100644 --- a/Library/Homebrew/test/utils/analytics_spec.rb +++ b/Library/Homebrew/test/utils/analytics_spec.rb @@ -3,9 +3,9 @@ require "formula_installer" describe Utils::Analytics do describe "::os_prefix_ci" do - context "when anonymous_os_prefix_ci is not set" do + context "when os_prefix_ci is not set" do before(:each) do - described_class.clear_anonymous_os_prefix_ci_cache + described_class.clear_os_prefix_ci end it "returns OS_VERSION and prefix when HOMEBREW_PREFIX is not /usr/local" do diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index 03924dcef2..8d57c12d60 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -109,7 +109,9 @@ def odeprecated(method, replacement = nil, disable: false, disable_on: nil, call if ARGV.homebrew_developer? || disable || Homebrew.raise_deprecation_exceptions? - developer_message = message + "Or, even better, submit a PR to fix it!" + if replacement || tap_message + developer_message = message + "Or, even better, submit a PR to fix it!" + end raise MethodDeprecatedError, developer_message elsif !Homebrew.auditing? opoo "#{message}\n" diff --git a/Library/Homebrew/utils/analytics.rb b/Library/Homebrew/utils/analytics.rb index adef3e811d..7636789c53 100644 --- a/Library/Homebrew/utils/analytics.rb +++ b/Library/Homebrew/utils/analytics.rb @@ -3,13 +3,13 @@ require "erb" module Utils module Analytics class << self - def clear_anonymous_os_prefix_ci_cache - return unless instance_variable_defined?(:@anonymous_os_prefix_ci) - remove_instance_variable(:@anonymous_os_prefix_ci) + def clear_os_prefix_ci + return unless instance_variable_defined?(:@os_prefix_ci) + remove_instance_variable(:@os_prefix_ci) end def os_prefix_ci - @anonymous_os_prefix_ci ||= begin + @os_prefix_ci ||= begin os = OS_VERSION prefix = ", non-/usr/local" if HOMEBREW_PREFIX.to_s != "/usr/local" ci = ", CI" if ENV["CI"] diff --git a/Library/Homebrew/utils/bottles.rb b/Library/Homebrew/utils/bottles.rb index 3a61cf215e..f67ace4c19 100644 --- a/Library/Homebrew/utils/bottles.rb +++ b/Library/Homebrew/utils/bottles.rb @@ -5,7 +5,7 @@ module Utils class Bottles class << self def tag - @bottle_tag ||= "#{ENV["HOMEBREW_PROCESSOR"]}_#{ENV["HOMEBREW_SYSTEM"]}".downcase.to_sym + @tag ||= "#{ENV["HOMEBREW_PROCESSOR"]}_#{ENV["HOMEBREW_SYSTEM"]}".downcase.to_sym end def built_as?(f) diff --git a/Library/Homebrew/utils/git.rb b/Library/Homebrew/utils/git.rb index ac17967c53..0ffcab7b1d 100644 --- a/Library/Homebrew/utils/git.rb +++ b/Library/Homebrew/utils/git.rb @@ -27,7 +27,7 @@ end module Utils def self.git_available? - @git ||= quiet_system HOMEBREW_SHIMS_PATH/"scm/git", "--version" + @git_available ||= quiet_system HOMEBREW_SHIMS_PATH/"scm/git", "--version" end def self.git_path @@ -61,7 +61,7 @@ module Utils end def self.clear_git_available_cache - @git = nil + @git_available = nil @git_path = nil @git_version = nil end diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb index 0166763234..b6a27b3283 100644 --- a/Library/Homebrew/utils/github.rb +++ b/Library/Homebrew/utils/github.rb @@ -94,7 +94,7 @@ module GitHub def api_credentials_error_message(response_headers, needed_scopes) return if response_headers.empty? - @api_credentials_error_message_printed ||= begin + @api_credentials_error_message ||= begin unauthorized = (response_headers["http/1.1"] == "401 Unauthorized") scopes = response_headers["x-accepted-oauth-scopes"].to_s.split(", ") needed_human_scopes = needed_scopes.join(", ") @@ -125,7 +125,7 @@ module GitHub end end - def open(url, data: nil, scopes: [].freeze) + def open_api(url, data: nil, scopes: [].freeze) # This is a no-op if the user is opting out of using the GitHub API. return block_given? ? yield({}) : {} if ENV["HOMEBREW_NO_GITHUB_API"] @@ -226,7 +226,7 @@ module GitHub end def repository(user, repo) - open(url_to("repos", user, repo)) + open_api(url_to("repos", user, repo)) end def search_code(**qualifiers) @@ -255,7 +255,7 @@ module GitHub def private_repo?(full_name) uri = url_to "repos", full_name - open(uri) { |json| json["private"] } + open_api(uri) { |json| json["private"] } end def query_string(*main_params, **qualifiers) @@ -275,6 +275,6 @@ module GitHub def search(entity, *queries, **qualifiers) uri = url_to "search", entity uri.query = query_string(*queries, **qualifiers) - open(uri) { |json| json.fetch("items", []) } + open_api(uri) { |json| json.fetch("items", []) } end end diff --git a/bin/brew b/bin/brew index b3a4d62720..4a874ab9a7 100755 --- a/bin/brew +++ b/bin/brew @@ -66,9 +66,9 @@ then FILTERED_ENV=() # Filter all but the specific variables. - for VAR in HOME SHELL PATH TERM LOGNAME USER CI TRAVIS TRAVIS_SUDO SSH_AUTH_SOCK SUDO_ASKPASS \ + for VAR in HOME SHELL PATH TERM LOGNAME USER CI TRAVIS SSH_AUTH_SOCK SUDO_ASKPASS \ http_proxy https_proxy ftp_proxy no_proxy all_proxy HTTPS_PROXY FTP_PROXY ALL_PROXY \ - "${!HOMEBREW_@}" + "${!HOMEBREW_@}" "${!TRAVIS_@}" do # Skip if variable value is empty. [[ -z "${!VAR}" ]] && continue diff --git a/docs/Acceptable-Formulae.md b/docs/Acceptable-Formulae.md index df799bb1a7..5f6e6fcc62 100644 --- a/docs/Acceptable-Formulae.md +++ b/docs/Acceptable-Formulae.md @@ -38,15 +38,6 @@ tarballs should include the version in the filename whenever possible. We don’t accept software without a tagged version because they regularly break due to upstream changes and we can’t provide [bottles](Bottles.md) for them. -### Bindings -First check that there is not already a binding available via -[`gem`](https://rubygems.org/) or [`pip`](http://www.pip-installer.org/) -etc. - -If not, then put bindings in the formula they bind to. This is more -useful to people. Just install the stuff! Having to faff around with -foo-ruby, foo-perl etc. is a bad user experience. - ### Niche (or self-submitted) stuff The software in question must: diff --git a/docs/Gems,-Eggs-and-Perl-Modules.md b/docs/Gems,-Eggs-and-Perl-Modules.md index 4a1b1ba44b..14d38003b3 100644 --- a/docs/Gems,-Eggs-and-Perl-Modules.md +++ b/docs/Gems,-Eggs-and-Perl-Modules.md @@ -11,8 +11,8 @@ Starting with OS X Lion (10.7), you need `sudo` to install to these like so: `sudo gem install`, `sudo easy_install` or `sudo cpan -i`. An option to avoid sudo is to use an access control list: -`chmod +a 'user:YOUR_NAME_HERE allow add_subdirectory,add_file,delete_child,directory_inherit' /Library/Python/2.7/site-packages`, -for example, will let you add packages to Python 2.7 as yourself. That +`chmod +a 'user:YOUR_NAME_HERE allow add_subdirectory,add_file,delete_child,directory_inherit' /Library/Python/3.6/site-packages`, +for example, will let you add packages to Python 3.6 as yourself. That is probably safer than changing the group ownership of the directory. ### So why was I using sudo? @@ -29,14 +29,14 @@ Rather than changing the rights on `/Library/Python`, we recommend the following options: ### With a brewed Python -Note, `easy_install` is deprecated. We install `pip` (or `pip3` for -Python 3) along with python/python3. +Note, `easy_install` is deprecated. We install `pip` (or `pip2` for +Python 2) along with python/python2. We set up distutils such that `pip install` will always put modules in `$(brew --prefix)/lib/pythonX.Y/site-packages` and scripts in `$(brew --prefix)/share/python`. Therefore, you won’t need sudo! -Do `brew info python` or `brew info python3` for precise information +Do `brew info python` or `brew info python@2` for precise information about the paths. Note, a brewed Python still searches for modules in `/Library/Python/X.Y/site-packages` and also in `~/Library/Python/X.Y/lib/python/site-packages`. diff --git a/docs/Homebrew-and-Python.md b/docs/Homebrew-and-Python.md index eb96e57583..38e2f42463 100644 --- a/docs/Homebrew-and-Python.md +++ b/docs/Homebrew-and-Python.md @@ -4,33 +4,35 @@ This page describes how Python is handled in Homebrew for users. See [Python for Homebrew should work with any [CPython](https://stackoverflow.com/questions/2324208/is-there-any-difference-between-cpython-and-python) and defaults to the macOS system Python. -Homebrew provides formulae to brew a more up-to-date Python 2.7.x and 3.x. +Homebrew provides formulae to brew 3.x and a more up-to-date Python 2.7.x. -**Important:** If you choose to install a Python which isn't either of these two (system Python or brewed Python), the Homebrew team can only provide limited support. +**Important:** If you choose to install a Python which isn't either of these two (system Python or brewed Python), the Homebrew team cannot support any breakage that may occur. -## Python 2.x or Python 3.x -Homebrew provides one formula for Python 2.7.x and another for Python 3.x. The executables are organized as follows so that Python 2 and Python 3 can both be installed without conflict: -* `python` points to the macOS system Python (with no manual PATH modification) -* `python2` points to Homebrew's Python 2.7.x (if installed) +## Python 3.x or Python 2.x +Homebrew provides one formula for Python 3.x (`python`) and another for Python 2.7.x (`python@2`). + +The executables are organized as follows so that Python 2 and Python 3 can both be installed without conflict: * `python3` points to Homebrew's Python 3.x (if installed) -* `pip2` points to Homebrew's Python 2.7.x's pip (if installed) +* `python2` points to Homebrew's Python 2.7.x (if installed) +* `python` points to Homebrew's Python 2.7.x (if installed) otherwise the macOS system Python. Check out `brew info python` if you wish to add Homebrew's 3.x `python` to your `PATH`. * `pip3` points to Homebrew's Python 3.x's pip (if installed) +* `pip` and `pip2` point to Homebrew's Python 2.7.x's pip (if installed) ([Wondering which one to choose?](https://wiki.python.org/moin/Python2orPython3)) ## Setuptools, Pip, etc. -The Python formulae install [pip](http://www.pip-installer.org) (as `pip2` or `pip3`) and [Setuptools](https://pypi.python.org/pypi/setuptools). +The Python formulae install [pip](http://www.pip-installer.org) (as `pip` or `pip2`) and [Setuptools](https://pypi.python.org/pypi/setuptools). Setuptools can be updated via pip, without having to re-brew Python: ```sh -python2 -m pip install --upgrade setuptools +python -m pip install --upgrade setuptools ``` Similarly, pip can be used to upgrade itself via: ```sh -python2 -m pip install --upgrade pip +python -m pip install --upgrade pip ``` ### Note on `pip install --user` @@ -39,7 +41,7 @@ The normal `pip install --user` is disabled for brewed Python. This is because o A possible workaround (which puts executable scripts in `~/Library/Python/./bin`) is: ```sh -python2 -m pip install --user --install-option="--prefix=" +python -m pip install --user --install-option="--prefix=" ``` ## `site-packages` and the `PYTHONPATH` @@ -49,12 +51,12 @@ The `site-packages` is a directory that contains Python modules (especially bind $(brew --prefix)/lib/pythonX.Y/site-packages ``` -So, for Python 2.7.x, you'll find it at `/usr/local/lib/python2.7/site-packages`. +So, for Python 3.6.x, you'll find it at `/usr/local/lib/python3.6/site-packages`. -Python 2.7 also searches for modules in: +Python 3.6 also searches for modules in: -- `/Library/Python/2.7/site-packages` -- `~/Library/Python/2.7/lib/python/site-packages` +- `/Library/Python/3.6/site-packages` +- `~/Library/Python/3.6/lib/python/site-packages` Homebrew's `site-packages` directory is first created if (1) any Homebrew formula with Python bindings are installed, or (2) upon `brew install python`. @@ -62,9 +64,7 @@ Homebrew's `site-packages` directory is first created if (1) any Homebrew formul The reasoning for this location is to preserve your modules between (minor) upgrades or re-installations of Python. Additionally, Homebrew has a strict policy never to write stuff outside of the `brew --prefix`, so we don't spam your system. ## Homebrew-provided Python bindings -Some formulae provide Python bindings. Sometimes a `--with-python` or `--with-python3` option has to be passed to `brew install` in order to build the Python bindings. (Check with `brew options `.) - -Homebrew builds bindings against the first `python` (and `python-config`) in your `PATH`. (Check with `which python`). +Some formulae provide Python bindings. Sometimes a `--with-python` or `--with-python@2` option has to be passed to `brew install` in order to build the Python bindings. (Check with `brew options `.) **Warning!** Python may crash (see [Common Issues](Common-Issues.md)) if you `import ` from a brewed Python if you ran `brew install ` against the system Python. If you decide to switch to the brewed Python, then reinstall all formulae with Python bindings (e.g. `pyside`, `wxwidgets`, `pygtk`, `pygobject`, `opencv`, `vtk` and `boost-python`). @@ -89,4 +89,4 @@ Homebrew will still install Python modules into Homebrew's `site-packages` and * Virtualenv has a `--system-site-packages` switch to allow "global" (i.e. Homebrew's) `site-packages` to be accessible from within the virtualenv. ## Why is Homebrew's Python being installed as a dependency? -Formulae that declare an unconditional dependency on the `"python"` or `"python3"` formulae are bottled against Homebrew's Python 2.7.x or 3.x and require it to be installed. +Formulae that declare an unconditional dependency on the `"python"` or `"python@2"` formulae are bottled against Homebrew's Python 3.x or 2.7.x and require it to be installed. diff --git a/docs/Manpage.md b/docs/Manpage.md index ff33466856..388b886b45 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -96,7 +96,8 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note By default, `deps` shows required and recommended dependencies for `formulae`. To include the `:build` type dependencies, pass `--include-build`. - Similarly, pass `--include-optional` to include `:optional` dependencies. + Similarly, pass `--include-optional` to include `:optional` dependencies or + `--include-test` to include `:test` dependencies. To skip `:recommended` type dependencies, pass `--skip-recommended`. To include requirements in addition to dependencies, pass `--include-requirements`. @@ -109,8 +110,8 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note If `--installed` is passed, output a tree for every installed formula. The `filters` placeholder is any combination of options `--include-build`, - `--include-optional`, `--skip-recommended`, and `--include-requirements` as - documented above. + `--include-optional`, `--include-test`, `--skip-recommended`, and + `--include-requirements` as documented above. If `--annotate` is passed, the build, optional, and recommended dependencies are marked as such in the output. @@ -121,7 +122,8 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note dependencies of that formula. The `filters` placeholder is any combination of options `--include-build`, - `--include-optional`, and `--skip-recommended` as documented above. + `--include-optional`, `--include-test`, and `--skip-recommended` as + documented above. * `desc` `formula`: Display `formula`'s name and one-line description. @@ -559,8 +561,8 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note repository's HEAD will be checked for updates when a new stable or devel version has been released. - If `formulae` are given, upgrade only the specified brews (but do so even - if they are pinned; see `pin`, `unpin`). + If `formulae` are given, upgrade only the specified brews (unless they + are pinned; see `pin`, `unpin`). * `uses` [`--installed`] [`--recursive`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] [`--devel`|`--HEAD`] `formulae`: Show the formulae that specify `formulae` as a dependency. When given diff --git a/docs/Python-for-Formula-Authors.md b/docs/Python-for-Formula-Authors.md index a530dbef7d..e4d50e5246 100644 --- a/docs/Python-for-Formula-Authors.md +++ b/docs/Python-for-Formula-Authors.md @@ -16,16 +16,16 @@ Applications should unconditionally bundle all of their Python-language dependen ### Python declarations +Formulae for apps that require Python 3 **should** declare an unconditional dependency on `"python"`. These apps **must** work with the current Homebrew Python 3.x formula. + Applications that are compatible with Python 2 **should** use the Apple-provided system Python in `/usr/bin` on systems that provide Python 2.7. To do this, declare: ```ruby -depends_on "python" if MacOS.version <= :snow_leopard +depends_on "python@2" if MacOS.version <= :snow_leopard ``` No explicit Python dependency is needed on recent OS versions since `/usr/bin` is always in `PATH` for Homebrew formulae; on Leopard and older, the `python` in `PATH` is used if it's at least version 2.7, or else Homebrew's Python 2.7.x is installed. -Formulae for apps that require Python 3 **should** declare an unconditional dependency on `"python3"`. These apps **must** work with the current Homebrew Python 3.x formula. - ### Installing Applications should be installed into a Python [virtualenv](https://virtualenv.pypa.io/en/stable/) environment rooted in `libexec`. This prevents the app's Python modules from contaminating the system site-packages and vice versa. @@ -66,7 +66,7 @@ This is exactly the same as writing: ```ruby def install # Create a virtualenv in `libexec`. If your app needs Python 3, make sure that - # `depends_on "python3"` is declared, and use `virtualenv_create(libexec, "python3")`. + # `depends_on "python"` is declared, and use `virtualenv_create(libexec, "python")`. venv = virtualenv_create(libexec) # Install all of the resources declared on the formula into the virtualenv. venv.pip_install resources @@ -121,9 +121,9 @@ in case you need to do different things for different resources. ## Bindings -Build bindings with the system Python by default (don't add an option) and they should be usable with any binary-compatible Python. If that isn't the case, it's an upstream bug; [here's some advice for resolving it](http://blog.tim-smith.us/2015/09/python-extension-modules-os-x/). +To add bindings for Python 3, please add `depends_on "python"`. -To add bindings for Python 3, please add `depends_on "python3" => :optional` and make the bindings conditional on `build.with?("python3")`. +Build Python 2 bindings with the system Python by default (don't add an option) and they should be usable with any binary-compatible Python. If that isn't the case, it's an upstream bug; [here's some advice for resolving it](http://blog.tim-smith.us/2015/09/python-extension-modules-os-x/). ### Dependencies @@ -153,7 +153,9 @@ Sometimes we have to `inreplace` a `Makefile` to use our prefix for the Python b ### Python declarations -Python 2 libraries do not need a `depends_on "python"` declaration; they will be built with the system Python, but should still be usable with any other Python 2.7. If this is not the case, it is an upstream bug; [here is some advice for resolving it](http://blog.tim-smith.us/2015/09/python-extension-modules-os-x/). Libraries built for Python 3 should include `depends_on "python3"`, which will bottle against Homebrew's Python 3.x. If a library supports both Python 2.x and Python 3.x, the `"python3"` dependency should be `:optional`. Python 2.x libraries must function when they are installed against either the system Python or brewed Python. +Libraries built for Python 3 should include `depends_on "python"`, which will bottle against Homebrew's Python 3.x. Python 2.x libraries must function when they are installed against either the system Python or brewed Python. + +Python 2 libraries do not need a `depends_on "python@2"` declaration; they will be built with the system Python, but should still be usable with any other Python 2.7. If this is not the case, it is an upstream bug; [here is some advice for resolving it](http://blog.tim-smith.us/2015/09/python-extension-modules-os-x/). ### Installing diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1 index 29905fcce1..6b32a90518 100644 --- a/manpages/brew-cask.1 +++ b/manpages/brew-cask.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BREW\-CASK" "1" "February 2018" "Homebrew" "brew-cask" +.TH "BREW\-CASK" "1" "March 2018" "Homebrew" "brew-cask" . .SH "NAME" \fBbrew\-cask\fR \- a friendly binary installer for macOS diff --git a/manpages/brew.1 b/manpages/brew.1 index 60cd7cc808..2ac999dd58 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BREW" "1" "February 2018" "Homebrew" "brew" +.TH "BREW" "1" "March 2018" "Homebrew" "brew" . .SH "NAME" \fBbrew\fR \- The missing package manager for macOS @@ -107,7 +107,7 @@ If \fB\-\-full\-name\fR is passed, list dependencies by their full name\. If \fB\-\-installed\fR is passed, only list those dependencies that are currently installed\. . .IP -By default, \fBdeps\fR shows required and recommended dependencies for \fIformulae\fR\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR\. Similarly, pass \fB\-\-include\-optional\fR to include \fB:optional\fR dependencies\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\. To include requirements in addition to dependencies, pass \fB\-\-include\-requirements\fR\. +By default, \fBdeps\fR shows required and recommended dependencies for \fIformulae\fR\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR\. Similarly, pass \fB\-\-include\-optional\fR to include \fB:optional\fR dependencies or \fB\-\-include\-test\fR to include \fB:test\fR dependencies\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\. To include requirements in addition to dependencies, pass \fB\-\-include\-requirements\fR\. . .TP \fBdeps\fR \fB\-\-tree\fR [\fB\-\-1\fR] [\fIfilters\fR] [\fB\-\-annotate\fR] (\fIformulae\fR|\fB\-\-installed\fR) @@ -120,7 +120,7 @@ If \fB\-\-1\fR is passed, only one level of children is displayed\. If \fB\-\-installed\fR is passed, output a tree for every installed formula\. . .IP -The \fIfilters\fR placeholder is any combination of options \fB\-\-include\-build\fR, \fB\-\-include\-optional\fR, \fB\-\-skip\-recommended\fR, and \fB\-\-include\-requirements\fR as documented above\. +The \fIfilters\fR placeholder is any combination of options \fB\-\-include\-build\fR, \fB\-\-include\-optional\fR, \fB\-\-include\-test\fR, \fB\-\-skip\-recommended\fR, and \fB\-\-include\-requirements\fR as documented above\. . .IP If \fB\-\-annotate\fR is passed, the build, optional, and recommended dependencies are marked as such in the output\. @@ -130,7 +130,7 @@ If \fB\-\-annotate\fR is passed, the build, optional, and recommended dependenci Show dependencies for installed or all available formulae\. Every line of output starts with the formula name, followed by a colon and all direct dependencies of that formula\. . .IP -The \fIfilters\fR placeholder is any combination of options \fB\-\-include\-build\fR, \fB\-\-include\-optional\fR, and \fB\-\-skip\-recommended\fR as documented above\. +The \fIfilters\fR placeholder is any combination of options \fB\-\-include\-build\fR, \fB\-\-include\-optional\fR, \fB\-\-include\-test\fR, and \fB\-\-skip\-recommended\fR as documented above\. . .TP \fBdesc\fR \fIformula\fR @@ -576,7 +576,7 @@ If \fB\-\-cleanup\fR is specified then remove previously installed \fIformula\fR If \fB\-\-fetch\-HEAD\fR is passed, fetch the upstream repository to detect if the HEAD installation of the formula is outdated\. Otherwise, the repository\'s HEAD will be checked for updates when a new stable or devel version has been released\. . .IP -If \fIformulae\fR are given, upgrade only the specified brews (but do so even if they are pinned; see \fBpin\fR, \fBunpin\fR)\. +If \fIformulae\fR are given, upgrade only the specified brews (unless they are pinned; see \fBpin\fR, \fBunpin\fR)\. . .TP \fBuses\fR [\fB\-\-installed\fR] [\fB\-\-recursive\fR] [\fB\-\-include\-build\fR] [\fB\-\-include\-optional\fR] [\fB\-\-skip\-recommended\fR] [\fB\-\-devel\fR|\fB\-\-HEAD\fR] \fIformulae\fR