Merge branch 'master' into undeclared_runtime_dependencies

This commit is contained in:
Alyssa Ross 2018-03-12 09:22:39 +00:00
commit 6cd195723f
No known key found for this signature in database
GPG Key ID: 6CF064D149E3ABDB
62 changed files with 511 additions and 291 deletions

View File

@ -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

View File

@ -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'

View File

@ -1,3 +1,5 @@
require "uri"
module Hbc
module CaskLoader
class FromContentLoader

View File

@ -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

View File

@ -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

View File

@ -17,7 +17,8 @@
#:
#: 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`.
#:
@ -30,8 +31,8 @@
#: 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.
@ -42,7 +43,8 @@
#: 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.
# 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -10,8 +10,8 @@
#: 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`).
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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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) }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -2219,12 +2219,12 @@ class Formula
# # `build.with?` or `build.without? "another_formula"`:
# depends_on "postgresql" if build.without? "sqlite"
#
# <pre># Python 2.7:
# depends_on "python"</pre>
# <pre># Python 2.7 but use system Python where possible
# depends_on "python" if MacOS.version <= :snow_leopard</pre>
# <pre># Python 3.x if the `--with-python3` is given to `brew install example`
# <pre># Python 3.x if the `--with-python` is given to `brew install example`
# depends_on "python3" => :optional</pre>
# <pre># Python 2.7:
# depends_on "python@2"</pre>
# <pre># Python 2.7 but use system Python where possible
# depends_on "python@2" if MacOS.version <= :snow_leopard</pre>
def depends_on(dep)
specs.each { |spec| spec.depends_on(dep) }
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 = []

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -4,6 +4,8 @@ require_relative "../../extend/string"
module RuboCop
module Cop
class FormulaCop < Cop
include RangeHelp
attr_accessor :file_path
@registry = Cop.registry

View File

@ -108,10 +108,10 @@ class Sandbox
unless logs.empty?
if @logfile
log = open(@logfile, "w")
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"
log.close
end
end
if @failed && ARGV.verbose?

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"])

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -109,7 +109,9 @@ def odeprecated(method, replacement = nil, disable: false, disable_on: nil, call
if ARGV.homebrew_developer? || disable ||
Homebrew.raise_deprecation_exceptions?
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"

View File

@ -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"]

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -38,15 +38,6 @@ tarballs should include the version in the filename whenever possible.
We dont accept software without a tagged version because they regularly break
due to upstream changes and we cant 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:

View File

@ -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 wont 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`.

View File

@ -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/<X>.<Y>/bin`) is:
```sh
python2 -m pip install --user --install-option="--prefix=" <package-name>
python -m pip install --user --install-option="--prefix=" <package-name>
```
## `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 <formula>`.)
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 <formula>`.)
**Warning!** Python may crash (see [Common Issues](Common-Issues.md)) if you `import <module>` from a brewed Python if you ran `brew install <formula_with_python_bindings>` 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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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