diff --git a/.gitignore b/.gitignore index 201be91d83..7b1678561d 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,13 @@ !/docs !/manpages +# Ignore generated documentation site +/docs/_site +/docs/.bundle +/docs/bin +/docs/vendor +/docs/Gemfile.lock + # Unignore our shell completion !/completions diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a2924fce1c..2875818caf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ First time contributing to Homebrew? Read our [Code of Conduct](https://github.c * run `brew update` (twice) * run and read `brew doctor` -* read [the Troubleshooting Checklist](https://github.com/Homebrew/brew/blob/master/docs/Troubleshooting.md#troubleshooting) +* read [the Troubleshooting Checklist](http://docs.brew.sh/Troubleshooting.html) * open an issue on the formula's repository or on Homebrew/brew if it's not a formula-specific issue ### Propose a feature diff --git a/LICENSE.txt b/LICENSE.txt index 1efd08cffe..12500f7e56 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ BSD 2-Clause License -Copyright (c) 2009-2016, Homebrew contributors +Copyright (c) 2009-present, Homebrew contributors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Library/Homebrew/.rubocop_todo.yml b/Library/Homebrew/.rubocop_todo.yml index 3705170fdc..99080b5461 100644 --- a/Library/Homebrew/.rubocop_todo.yml +++ b/Library/Homebrew/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 100` -# on 2016-10-24 17:14:14 +0200 using RuboCop version 0.44.1. +# on 2016-12-31 22:41:53 +0000 using RuboCop version 0.45.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -59,31 +59,24 @@ Lint/ShadowedException: Exclude: - 'utils/fork.rb' -# Offense count: 14 +# Offense count: 13 Metrics/BlockNesting: Max: 5 # Offense count: 19 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 367 + Max: 400 -# Offense count: 2 +# Offense count: 1 # Configuration parameters: CountKeywordArgs. Metrics/ParameterLists: Max: 6 -# Offense count: 8 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: percent_q, bare_percent -Style/BarePercentLiterals: +# Offense count: 1 +Style/AccessorMethodName: Exclude: - - 'dev-cmd/audit.rb' - - 'test/test_diagnostic.rb' - - 'test/test_exceptions.rb' - - 'test/test_patch.rb' - - 'test/test_string.rb' + - 'extend/ENV/super.rb' # Offense count: 6 Style/ClassVars: diff --git a/Library/Homebrew/README.md b/Library/Homebrew/README.md index b8bf5fd998..18a41e3636 100644 --- a/Library/Homebrew/README.md +++ b/Library/Homebrew/README.md @@ -3,6 +3,6 @@ This is the (partially) documented public API for Homebrew. The main class you should look at is the {Formula} class (and classes linked from there). That's the class that's used to create Homebrew formulae (i.e. package descriptions). Assume anything else you stumble upon is private. -You may also find the [Formula Cookbook](https://github.com/Homebrew/brew/blob/master/docs/Formula-Cookbook.md) and [Ruby Style Guide](https://github.com/styleguide/ruby) helpful in creating formulae. +You may also find the [Formula Cookbook](http://docs.brew.sh/Formula-Cookbook.html) and [Ruby Style Guide](https://github.com/styleguide/ruby) helpful in creating formulae. Good luck! diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index 92953001d3..81a52f4744 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -82,6 +82,9 @@ unset GEM_PATH # bash processes inside builds unset BASH_ENV +# Users may have this set, breaking grep's output. +unset GREP_OPTIONS + HOMEBREW_SYSTEM="$(uname -s)" case "$HOMEBREW_SYSTEM" in Darwin) HOMEBREW_MACOS="1" ;; diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index c4e903642b..c0f15158d1 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -48,7 +48,7 @@ class Build Requirement.prune elsif req.build? && dependent != formula Requirement.prune - elsif req.satisfied? && req.default_formula? && (dep = req.to_dependency).installed? + elsif req.satisfied? && (dep = req.to_dependency) && dep.installed? deps << dep Requirement.prune end diff --git a/Library/Homebrew/cask/LICENSE b/Library/Homebrew/cask/LICENSE deleted file mode 100644 index 62542ae576..0000000000 --- a/Library/Homebrew/cask/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright © 2013-2016, Paul Hinze & Contributors -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Library/Homebrew/cask/lib/hbc.rb b/Library/Homebrew/cask/lib/hbc.rb index 69b6e8f21c..775b9229f0 100644 --- a/Library/Homebrew/cask/lib/hbc.rb +++ b/Library/Homebrew/cask/lib/hbc.rb @@ -46,7 +46,7 @@ module Hbc def self.init Cache.ensure_cache_exists - Cache.migrate_legacy_cache + Cache.delete_legacy_cache Caskroom.migrate_caskroom_from_repo_to_prefix Caskroom.ensure_caskroom_exists diff --git a/Library/Homebrew/cask/lib/hbc/artifact/base.rb b/Library/Homebrew/cask/lib/hbc/artifact/base.rb index 05dbedd8fc..b53c13f08e 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/base.rb @@ -46,7 +46,7 @@ module Hbc arguments = { executable: arguments } if arguments.is_a?(String) # key sanity - permitted_keys = [:args, :input, :executable, :must_succeed, :sudo, :bsexec, :print_stdout, :print_stderr] + permitted_keys = [:args, :input, :executable, :must_succeed, :sudo, :print_stdout, :print_stderr] unknown_keys = arguments.keys - permitted_keys unless unknown_keys.empty? opoo %Q{Unknown arguments to #{description} -- #{unknown_keys.inspect} (ignored). Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.} diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb index ab2f1bce54..12cefb9395 100644 --- a/Library/Homebrew/cask/lib/hbc/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/audit.rb @@ -60,6 +60,7 @@ module Hbc def check_version return unless cask.version check_no_string_version_latest + check_no_file_separator_in_version end def check_no_string_version_latest @@ -68,6 +69,13 @@ module Hbc add_error "you should use version :latest instead of version 'latest'" end + def check_no_file_separator_in_version + odebug "Verifying version does not contain '#{File::SEPARATOR}'" + return unless cask.version.raw_version.is_a?(String) + return unless cask.version.raw_version.include?(File::SEPARATOR) + add_error "version should not contain '#{File::SEPARATOR}'" + end + def check_sha256 return unless cask.sha256 check_sha256_no_check_if_latest @@ -125,20 +133,19 @@ module Hbc def check_appcast_checkpoint_accuracy odebug "Verifying appcast checkpoint is accurate" - result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, cask.appcast], print_stderr: false) - if result.success? - processed_appcast_text = result.stdout.gsub(%r{[^<]*}, "") - # This step is necessary to replicate running `sed` from the command line - processed_appcast_text << "\n" unless processed_appcast_text.end_with?("\n") + result = cask.appcast.calculate_checkpoint + + actual_checkpoint = result[:checkpoint] + + if actual_checkpoint.nil? + add_warning "error retrieving appcast: #{result[:command_result].stderr}" + else expected = cask.appcast.checkpoint - actual = Digest::SHA2.hexdigest(processed_appcast_text) - add_warning <<-EOS.undent unless expected == actual + add_warning <<-EOS.undent unless expected == actual_checkpoint appcast checkpoint mismatch Expected: #{expected} - Actual: #{actual} + Actual: #{actual_checkpoint} EOS - else - add_warning "error retrieving appcast: #{result.stderr}" end end diff --git a/Library/Homebrew/cask/lib/hbc/cache.rb b/Library/Homebrew/cask/lib/hbc/cache.rb index e343da3faf..7b586528ed 100644 --- a/Library/Homebrew/cask/lib/hbc/cache.rb +++ b/Library/Homebrew/cask/lib/hbc/cache.rb @@ -9,27 +9,10 @@ module Hbc Hbc.cache.mkpath end - def migrate_legacy_cache + def delete_legacy_cache return unless Hbc.legacy_cache.exist? - ohai "Migrating cached files to #{Hbc.cache}..." - Hbc.legacy_cache.children.select(&:symlink?).each do |symlink| - file = symlink.readlink - - new_name = file.basename - .sub(/\-((?:(\d|#{DSL::Version::DIVIDER_REGEX})*\-\2*)*[^\-]+)$/x, - '--\1') - - renamed_file = Hbc.cache.join(new_name) - - if file.exist? - puts "#{file} -> #{renamed_file}" - FileUtils.mv(file, renamed_file) - end - - FileUtils.rm(symlink) - end - + ohai "Deleting legacy cache at #{Hbc.legacy_cache}..." FileUtils.remove_entry_secure(Hbc.legacy_cache) end end diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb index c9625c7e20..36fae30349 100644 --- a/Library/Homebrew/cask/lib/hbc/cli.rb +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -19,11 +19,11 @@ require "hbc/cli/reinstall" require "hbc/cli/search" require "hbc/cli/style" require "hbc/cli/uninstall" -require "hbc/cli/update" require "hbc/cli/zap" require "hbc/cli/internal_use_base" require "hbc/cli/internal_audit_modified_casks" +require "hbc/cli/internal_appcast_checkpoint" require "hbc/cli/internal_checkurl" require "hbc/cli/internal_dump" require "hbc/cli/internal_help" @@ -77,6 +77,7 @@ module Hbc def self.command_classes @command_classes ||= constants.map(&method(:const_get)) .select { |sym| sym.respond_to?(:run) } + .sort_by(&:command_name) end def self.commands diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb new file mode 100644 index 0000000000..790e917b22 --- /dev/null +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb @@ -0,0 +1,61 @@ +module Hbc + class CLI + class InternalAppcastCheckpoint < InternalUseBase + def self.run(*args) + calculate = args.include? "--calculate" + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + + if cask_tokens.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ } + appcask_checkpoint_for_url(cask_tokens) + else + appcask_checkpoint(cask_tokens, calculate) + end + end + + def self.appcask_checkpoint_for_url(urls) + urls.each do |url| + appcast = DSL::Appcast.new(url) + puts appcast.calculate_checkpoint[:checkpoint] + end + end + + def self.appcask_checkpoint(cask_tokens, calculate) + count = 0 + + cask_tokens.each do |cask_token| + cask = Hbc.load(cask_token) + + if cask.appcast.nil? + opoo "Cask '#{cask}' is missing an `appcast` stanza." + else + if calculate + result = cask.appcast.calculate_checkpoint + + checkpoint = result[:checkpoint] + else + checkpoint = cask.appcast.checkpoint + end + + if checkpoint.nil? + onoe "Could not retrieve `appcast` checkpoint for cask '#{cask}': #{result[:command_result].stderr}" + else + puts cask_tokens.count > 1 ? "#{checkpoint} #{cask}": checkpoint + count += 1 + end + end + end + + count == cask_tokens.count + end + + def self.help + "prints or calculates a given Cask's or URL's appcast checkpoint" + end + + def self.needs_init? + true + end + end + end +end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb index af1494e5f9..ac1b204939 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb @@ -27,7 +27,7 @@ module Hbc end def self.help - "Dump the given Cask in YAML format" + "dump the given Cask in YAML format" end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb index 6c646cfd7f..0908ee05ef 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb @@ -16,7 +16,7 @@ module Hbc end def self.help - "Print help strings for unstable internal-use commands" + "print help strings for unstable internal-use commands" end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb index e5c04ee514..105e946d75 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb @@ -50,12 +50,12 @@ module Hbc :uninstall_postflight, ] - def self.run(*arguments) - table = arguments.include? "--table" - quiet = arguments.include? "--quiet" - format = :to_yaml if arguments.include? "--yaml" - format = :inspect if arguments.include? "--inspect" - cask_tokens = arguments.reject { |arg| arg.chars.first == "-" } + def self.run(*args) + table = args.include? "--table" + quiet = args.include? "--quiet" + format = :to_yaml if args.include? "--yaml" + format = :inspect if args.include? "--inspect" + cask_tokens = cask_tokens_from(args) stanza = cask_tokens.shift.to_sym cask_tokens = Hbc.all_tokens if cask_tokens.empty? @@ -125,7 +125,7 @@ module Hbc end def self.help - "Extract and render a specific stanza for the given Casks" + "extract and render a specific stanza for the given Casks" end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/update.rb b/Library/Homebrew/cask/lib/hbc/cli/update.rb deleted file mode 100644 index 86d02bb55b..0000000000 --- a/Library/Homebrew/cask/lib/hbc/cli/update.rb +++ /dev/null @@ -1,20 +0,0 @@ -module Hbc - class CLI - class Update < Base - def self.run(*_ignored) - result = SystemCommand.run(HOMEBREW_BREW_FILE, - args: ["update"]) - # TODO: separating stderr/stdout is undesirable here. - # Hbc::SystemCommand should have an option for plain - # unbuffered output. - print result.stdout - $stderr.print result.stderr - exit result.exit_status - end - - def self.help - "a synonym for 'brew update'" - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb index 2f1245d3d9..e27870622c 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb @@ -1,3 +1,5 @@ +require "hbc/system_command" + module Hbc class DSL class Appcast @@ -9,6 +11,20 @@ module Hbc @checkpoint = @parameters[:checkpoint] end + def calculate_checkpoint + result = SystemCommand.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, @uri], print_stderr: false) + + checkpoint = if result.success? + processed_appcast_text = result.stdout.gsub(%r{[^<]*}m, "") + Digest::SHA2.hexdigest(processed_appcast_text) + end + + { + checkpoint: checkpoint, + command_result: result, + } + end + def to_yaml [@uri, @parameters].to_yaml end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb b/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb index 2168b70900..a8c1a1b738 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb @@ -13,30 +13,9 @@ module Hbc ].freeze VALID_ARCHES = { - intel: { type: :intel, bits: [32, 64] }, - ppc: { type: :ppc, bits: [32, 64] }, + intel: { type: :intel, bits: 64 }, # specific - i386: { type: :intel, bits: 32 }, x86_64: { type: :intel, bits: 64 }, - ppc_7400: { type: :ppc, bits: 32 }, - ppc_64: { type: :ppc, bits: 64 }, - }.freeze - - # Intentionally undocumented: catch variant spellings. - ARCH_SYNONYMS = { - x86_32: :i386, - x8632: :i386, - x8664: :x86_64, - intel_32: :i386, - intel32: :i386, - intel_64: :x86_64, - intel64: :x86_64, - amd_64: :x86_64, - amd64: :x86_64, - ppc7400: :ppc_7400, - ppc_32: :ppc_7400, - ppc32: :ppc_7400, - ppc64: :ppc_64, }.freeze attr_accessor :java @@ -100,8 +79,7 @@ module Hbc def arch=(*args) @arch ||= [] arches = args.map do |elt| - elt = elt.to_s.downcase.sub(/^:/, "").tr("-", "_").to_sym - ARCH_SYNONYMS.key?(elt) ? ARCH_SYNONYMS[elt] : elt + elt.to_s.downcase.sub(/^:/, "").tr("-", "_").to_sym end invalid_arches = arches - VALID_ARCHES.keys raise "invalid 'depends_on arch' values: #{invalid_arches.inspect}" unless invalid_arches.empty? diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index 3875e1c8fe..465011735e 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -141,8 +141,8 @@ module Hbc artifacts.each do |artifact| odebug "Installing artifact of class #{artifact}" - already_installed_artifacts.unshift(artifact) artifact.new(@cask, options).install_phase + already_installed_artifacts.unshift(artifact) end rescue StandardError => e begin diff --git a/Library/Homebrew/cask/lib/hbc/locations.rb b/Library/Homebrew/cask/lib/hbc/locations.rb index f28e84b2ef..292b45d0ca 100644 --- a/Library/Homebrew/cask/lib/hbc/locations.rb +++ b/Library/Homebrew/cask/lib/hbc/locations.rb @@ -1,3 +1,5 @@ +require "tap" + module Hbc module Locations def self.included(base) diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb index 6380693862..06ce276dfc 100644 --- a/Library/Homebrew/cask/lib/hbc/system_command.rb +++ b/Library/Homebrew/cask/lib/hbc/system_command.rb @@ -48,13 +48,11 @@ module Hbc def process_options! options.extend(HashValidator) - .assert_valid_keys :input, :print_stdout, :print_stderr, :args, :must_succeed, :sudo, :bsexec + .assert_valid_keys :input, :print_stdout, :print_stderr, :args, :must_succeed, :sudo sudo_prefix = %w[/usr/bin/sudo -E --] sudo_prefix = sudo_prefix.insert(1, "-A") unless ENV["SUDO_ASKPASS"].nil? - bsexec_prefix = ["/bin/launchctl", "bsexec", options[:bsexec] == :startup ? "/" : options[:bsexec]] @command = [executable] options[:print_stderr] = true unless options.key?(:print_stderr) - @command.unshift(*bsexec_prefix) if options[:bsexec] @command.unshift(*sudo_prefix) if options[:sudo] @command.concat(options[:args]) if options.key?(:args) && !options[:args].empty? @command[0] = Shellwords.shellescape(@command[0]) if @command.size == 1 diff --git a/Library/Homebrew/cask/spec/cask/audit_spec.rb b/Library/Homebrew/cask/spec/cask/audit_spec.rb index c12063a1d6..193b58fd60 100644 --- a/Library/Homebrew/cask/spec/cask/audit_spec.rb +++ b/Library/Homebrew/cask/spec/cask/audit_spec.rb @@ -162,7 +162,7 @@ describe Hbc::Audit do before do allow(audit).to receive(:check_appcast_http_code) - allow(fake_system_command).to receive(:run).and_return(fake_curl_result) + allow(Hbc::SystemCommand).to receive(:run).and_return(fake_curl_result) allow(fake_curl_result).to receive(:success?).and_return(success) end diff --git a/Library/Homebrew/cask/spec/cask/cli_spec.rb b/Library/Homebrew/cask/spec/cask/cli_spec.rb index 9964275f10..6b2313a41c 100644 --- a/Library/Homebrew/cask/spec/cask/cli_spec.rb +++ b/Library/Homebrew/cask/spec/cask/cli_spec.rb @@ -39,17 +39,17 @@ describe Hbc::CLI do end it "respects the env variable when choosing what appdir to create" do - with_environment "HOMEBREW_CASK_OPTS" => "--appdir=/custom/appdir" do - expect(Hbc).to receive(:appdir=).with(Pathname("/custom/appdir")) - described_class.process("noop") - end + allow(ENV).to receive(:[]) + allow(ENV).to receive(:[]).with("HOMEBREW_CASK_OPTS").and_return("--appdir=/custom/appdir") + expect(Hbc).to receive(:appdir=).with(Pathname.new("/custom/appdir")) + described_class.process("noop") end it "respects the env variable when choosing a non-default Caskroom location" do - with_environment "HOMEBREW_CASK_OPTS" => "--caskroom=/custom/caskdir" do - expect(Hbc).to receive(:caskroom=).with(Pathname("/custom/caskdir")) - described_class.process("noop") - end + allow(ENV).to receive(:[]) + allow(ENV).to receive(:[]).with("HOMEBREW_CASK_OPTS").and_return("--caskroom=/custom/caskdir") + expect(Hbc).to receive(:caskroom=).with(Pathname.new("/custom/caskdir")) + described_class.process("noop") end it "exits with a status of 1 when something goes wrong" do diff --git a/Library/Homebrew/cask/spec/spec_helper.rb b/Library/Homebrew/cask/spec/spec_helper.rb index 458fe00f4f..162cb3b8f3 100644 --- a/Library/Homebrew/cask/spec/spec_helper.rb +++ b/Library/Homebrew/cask/spec/spec_helper.rb @@ -15,7 +15,6 @@ require "global" # add Homebrew-Cask to load path $LOAD_PATH.push(HOMEBREW_LIBRARY_PATH.join("cask", "lib").to_s) -require "test/support/helper/env" require "test/support/helper/shutup" Pathname.glob(HOMEBREW_LIBRARY_PATH.join("cask", "spec", "support", "*.rb")).each(&method(:require)) @@ -38,6 +37,5 @@ end RSpec.configure do |config| config.order = :random - config.include(Test::Helper::Env) config.include(Test::Helper::Shutup) end diff --git a/Library/Homebrew/cask/test/cask/artifact/suite_test.rb b/Library/Homebrew/cask/test/cask/artifact/suite_test.rb index b2949950ec..ed151e45cd 100644 --- a/Library/Homebrew/cask/test/cask/artifact/suite_test.rb +++ b/Library/Homebrew/cask/test/cask/artifact/suite_test.rb @@ -13,6 +13,8 @@ describe Hbc::Artifact::Suite do end it "moves the suite to the proper directory" do + skip("flaky test") + shutup do install_phase.call end diff --git a/Library/Homebrew/cask/test/cask/depends_on_test.rb b/Library/Homebrew/cask/test/cask/depends_on_test.rb index ce2e541783..4516dad37e 100644 --- a/Library/Homebrew/cask/test/cask/depends_on_test.rb +++ b/Library/Homebrew/cask/test/cask/depends_on_test.rb @@ -79,15 +79,6 @@ describe "Satisfy Dependencies and Requirements" do Hbc::Installer.new(arch_cask).install end end - - it "raises an exception when depends_on arch is not satisfied" do - arch_cask = Hbc.load("with-depends-on-arch-failure") - lambda { - shutup do - Hbc::Installer.new(arch_cask).install - end - }.must_raise(Hbc::CaskError) - end end describe "depends_on x11" do diff --git a/Library/Homebrew/cask/test/cask/dsl_test.rb b/Library/Homebrew/cask/test/cask/dsl_test.rb index 96d24a1a14..0ea928f40e 100644 --- a/Library/Homebrew/cask/test/cask/dsl_test.rb +++ b/Library/Homebrew/cask/test/cask/dsl_test.rb @@ -69,7 +69,11 @@ describe Hbc::DSL do end it "may use deprecated DSL version hash syntax" do - with_environment "HOMEBREW_DEVELOPER" => nil do + stub = proc do |arg| + arg == "HOMEBREW_DEVELOPER" ? nil : ENV[arg] + end + + ENV.stub :[], stub do shutup do test_cask = Hbc.load("with-dsl-version") test_cask.token.must_equal "with-dsl-version" diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-arch-failure.rb b/Library/Homebrew/cask/test/support/Casks/with-depends-on-arch-failure.rb deleted file mode 100644 index 14c9165735..0000000000 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-arch-failure.rb +++ /dev/null @@ -1,12 +0,0 @@ -test_cask 'with-depends-on-arch-failure' do - version '1.2.3' - sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' - - url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" - homepage 'http://example.com/with-depends-on-arch-failure' - - # guarantee mismatched hardware - depends_on arch: Hardware::CPU.intel? ? :ppc : :intel - - app 'Caffeine.app' -end diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-arch.rb b/Library/Homebrew/cask/test/support/Casks/with-depends-on-arch.rb index fe5e4ba032..e0c4e3fa7c 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-arch.rb +++ b/Library/Homebrew/cask/test/support/Casks/with-depends-on-arch.rb @@ -6,7 +6,7 @@ test_cask 'with-depends-on-arch' do homepage 'http://example.com/with-depends-on-arch' # covers all known hardware; always succeeds - depends_on arch: [:ppc, :intel] + depends_on arch: :intel app 'Caffeine.app' end diff --git a/Library/Homebrew/cask/test/test_helper.rb b/Library/Homebrew/cask/test/test_helper.rb index 275ede3048..7315839f58 100644 --- a/Library/Homebrew/cask/test/test_helper.rb +++ b/Library/Homebrew/cask/test/test_helper.rb @@ -13,9 +13,7 @@ require "global" # add Homebrew-Cask to load path $LOAD_PATH.push(HOMEBREW_LIBRARY_PATH.join("cask", "lib").to_s) -require "test/support/helper/env" require "test/support/helper/shutup" -include Test::Helper::Env include Test::Helper::Shutup def sudo(*args) diff --git a/Library/Homebrew/caveats.rb b/Library/Homebrew/caveats.rb index 3dfdb1c872..d1dda9d4cb 100644 --- a/Library/Homebrew/caveats.rb +++ b/Library/Homebrew/caveats.rb @@ -23,7 +23,6 @@ class Caveats caveats << fish_function_caveats caveats << plist_caveats caveats << python_caveats - caveats << app_caveats caveats << elisp_caveats caveats.compact.join("\n") end @@ -169,16 +168,6 @@ class Caveats s end - def app_caveats - return unless keg - return unless keg.app_installed? - - <<-EOS.undent - .app bundles were installed. - Run `brew linkapps #{keg.name}` to symlink these to /Applications. - EOS - end - def elisp_caveats return if f.keg_only? return unless keg diff --git a/Library/Homebrew/cmd/--prefix.rb b/Library/Homebrew/cmd/--prefix.rb index c59830833b..f6e7d2ee29 100644 --- a/Library/Homebrew/cmd/--prefix.rb +++ b/Library/Homebrew/cmd/--prefix.rb @@ -11,7 +11,7 @@ module Homebrew if ARGV.named.empty? puts HOMEBREW_PREFIX else - puts ARGV.resolved_formulae.map { |f| f.opt_prefix.exist? ? f.opt_prefix : f.installed_prefix } + puts ARGV.resolved_formulae.map(&:installed_prefix) end end end diff --git a/Library/Homebrew/cmd/analytics.rb b/Library/Homebrew/cmd/analytics.rb index 2efa5a2d23..8a67a54a4c 100644 --- a/Library/Homebrew/cmd/analytics.rb +++ b/Library/Homebrew/cmd/analytics.rb @@ -1,6 +1,6 @@ #: * `analytics` [`state`]: #: Display anonymous user behaviour analytics state. -#: Read more at . +#: Read more at . #: #: * `analytics` (`on`|`off`): #: Turn on/off Homebrew's analytics. diff --git a/Library/Homebrew/cmd/deps.rb b/Library/Homebrew/cmd/deps.rb index a5089392fc..205cbe172b 100644 --- a/Library/Homebrew/cmd/deps.rb +++ b/Library/Homebrew/cmd/deps.rb @@ -66,16 +66,16 @@ module Homebrew else all_deps = deps_for_formulae(ARGV.formulae, !ARGV.one?, &(mode.union? ? :| : :&)) all_deps = all_deps.select(&:installed?) if mode.installed? - all_deps = if ARGV.include? "--full-name" - all_deps.map(&:to_formula).map(&:full_name) - else - all_deps.map(&:name) - end.uniq + all_deps = all_deps.map(&method(:dep_display_name)).uniq all_deps.sort! unless mode.topo_order? puts all_deps end end + def dep_display_name(d) + ARGV.include?("--full-name") ? d.to_formula.full_name : d.name + end + def deps_for_formula(f, recursive = false) includes = [] ignores = [] @@ -127,7 +127,10 @@ module Homebrew end def puts_deps(formulae) - formulae.each { |f| puts "#{f.full_name}: #{deps_for_formula(f).sort_by(&:name) * " "}" } + formulae.each do |f| + deps = deps_for_formula(f).sort_by(&:name).map(&method(:dep_display_name)) + puts "#{f.full_name}: #{deps.join(" ")}" + end end def puts_deps_tree(formulae) @@ -140,17 +143,25 @@ module Homebrew def recursive_deps_tree(f, prefix) reqs = f.requirements.select(&:default_formula?) + deps = f.deps.default max = reqs.length - 1 reqs.each_with_index do |req, i| - chr = i == max ? "└──" : "├──" - puts prefix + "#{chr} :#{req.to_dependency.name}" + chr = if i == max && deps.empty? + "└──" + else + "├──" + end + puts prefix + "#{chr} :#{dep_display_name(req.to_dependency)}" end - deps = f.deps.default max = deps.length - 1 deps.each_with_index do |dep, i| - chr = i == max ? "└──" : "├──" + chr = if i == max + "└──" + else + "├──" + end prefix_ext = i == max ? " " : "│ " - puts prefix + "#{chr} #{dep.name}" + puts prefix + "#{chr} #{dep_display_name(dep)}" recursive_deps_tree(Formulary.factory(dep.name), prefix + prefix_ext) end end diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index f92ef03b23..820a27e316 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -18,8 +18,9 @@ #: If `--build-from-source` is passed, download the source rather than a #: bottle. #: -#: If `--force-bottle` is passed, download a bottle if it exists for the current -#: version of macOS, even if it would not be used during installation. +#: If `--force-bottle` is passed, download a bottle if it exists for the +#: current or newest version of macOS, even if it would not be used during +#: installation. require "formula" diff --git a/Library/Homebrew/cmd/help.rb b/Library/Homebrew/cmd/help.rb index 982e249655..1378e7b1f7 100644 --- a/Library/Homebrew/cmd/help.rb +++ b/Library/Homebrew/cmd/help.rb @@ -16,7 +16,7 @@ Troubleshooting: Developers: brew create [URL [--no-fetch]] brew edit [FORMULA...] - https://github.com/Homebrew/brew/blob/master/docs/Formula-Cookbook.md + http://docs.brew.sh/Formula-Cookbook.html Further help: man brew diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb index fc47e1731c..1850ae003e 100644 --- a/Library/Homebrew/cmd/info.rb +++ b/Library/Homebrew/cmd/info.rb @@ -14,7 +14,7 @@ #: information on all installed formulae. #: #: See the docs for examples of using the JSON: -#: +#: require "blacklist" require "caveats" diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 700cd9c3d0..5a3aeb7b32 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -32,10 +32,10 @@ #: passed, then both and the dependencies installed as part of this process #: are built from source even if bottles are available. #: -# Hidden developer option: -# If `--force-bottle` is passed, install from a bottle if it exists -# for the current version of macOS, even if custom options are given. -# +#: If `--force-bottle` is passed, install from a bottle if it exists for the +#: current or newest version of macOS, even if it would not normally be used +#: for installation. +#: #: If `--devel` is passed, and defines it, install the development version. #: #: If `--HEAD` is passed, and defines it, install the HEAD version, @@ -44,9 +44,6 @@ #: If `--keep-tmp` is passed, the temporary files created during installation #: are not deleted. #: -#: To install a newer version of HEAD use -#: `brew rm && brew install --HEAD `. -#: #: * `install` `--interactive` [`--git`] : #: Download and patch , then open a shell. This allows the user to #: run `./configure --help` and otherwise determine how to turn the software @@ -187,6 +184,14 @@ module Homebrew # FormulaInstaller will handle this case. formulae << f end + + # Even if we don't install this formula mark it as no longer just + # installed as a dependency. + next unless f.opt_prefix.directory? + keg = Keg.new(f.opt_prefix.resolved_path) + tab = Tab.for_keg(keg) + tab.installed_on_request = true + tab.write end perform_preinstall_checks diff --git a/Library/Homebrew/cmd/linkapps.rb b/Library/Homebrew/cmd/linkapps.rb index bd88409aaa..7dd1a6b939 100644 --- a/Library/Homebrew/cmd/linkapps.rb +++ b/Library/Homebrew/cmd/linkapps.rb @@ -1,6 +1,11 @@ #: * `linkapps` [`--local`] []: #: Find installed formulae that provide `.app`-style macOS apps and symlink them -#: into `/Applications`, allowing for easier access. +#: into `/Applications`, allowing for easier access (deprecated). +#: +#: Unfortunately `brew linkapps` cannot behave nicely with e.g. Spotlight using +#: either aliases or symlinks and Homebrew formulae do not build "proper" `.app` +#: bundles that can be relocated. Instead, please consider using `brew cask` and +#: migrate formulae using `.app`s to casks. #: #: If no are provided, all of them will have their apps symlinked. #: @@ -14,6 +19,15 @@ module Homebrew module_function def linkapps + opoo <<-EOS.undent + `brew linkapps` has been deprecated and will eventually be removed! + + Unfortunately `brew linkapps` cannot behave nicely with e.g. Spotlight using + either aliases or symlinks and Homebrew formulae do not build "proper" `.app` + bundles that can be relocated. Instead, please consider using `brew cask` and + migrate formulae using `.app`s to casks. + EOS + target_dir = linkapps_target(local: ARGV.include?("--local")) unless target_dir.directory? diff --git a/Library/Homebrew/cmd/tap-info.rb b/Library/Homebrew/cmd/tap-info.rb index 0d9f8db3d9..b46de30c12 100644 --- a/Library/Homebrew/cmd/tap-info.rb +++ b/Library/Homebrew/cmd/tap-info.rb @@ -13,7 +13,7 @@ #: Pass `--installed` to get information on installed taps. #: #: See the docs for examples of using the JSON: -#: +#: require "tap" diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb index 505d4e4b2b..5d02ebd1e8 100644 --- a/Library/Homebrew/cmd/uninstall.rb +++ b/Library/Homebrew/cmd/uninstall.rb @@ -102,8 +102,8 @@ module Homebrew attr_reader :reqs, :deps def initialize(requireds, dependents) - @reqs = requireds.compact - @deps = dependents.compact + @reqs = requireds + @deps = dependents end protected @@ -121,7 +121,7 @@ module Homebrew end def sample_command - "brew uninstall --ignore-dependencies #{list reqs.map(&:name)}" + "brew uninstall --ignore-dependencies #{ARGV.named.join(" ")}" end def are_required_by_deps diff --git a/Library/Homebrew/cmd/unlinkapps.rb b/Library/Homebrew/cmd/unlinkapps.rb index d04ef9ee40..b2ba458bf6 100644 --- a/Library/Homebrew/cmd/unlinkapps.rb +++ b/Library/Homebrew/cmd/unlinkapps.rb @@ -1,5 +1,10 @@ #: * `unlinkapps` [`--local`] [`--dry-run`] []: -#: Remove symlinks created by `brew linkapps` from `/Applications`. +#: Remove symlinks created by `brew linkapps` from `/Applications` (deprecated). +#: +#: Unfortunately `brew linkapps` cannot behave nicely with e.g. Spotlight using +#: either aliases or symlinks and Homebrew formulae do not build "proper" `.app` +#: bundles that can be relocated. Instead, please consider using `brew cask` and +#: migrate formulae using `.app`s to casks. #: #: If no are provided, all linked apps will be removed. #: @@ -15,6 +20,12 @@ module Homebrew module_function def unlinkapps + opoo <<-EOS.undent + `brew unlinkapps` has been deprecated and will eventually be removed! + + Unfortunately `brew linkapps` cannot behave nicely with e.g. Spotlight using either aliases or symlinks and Homebrew formulae do not build "proper" `.app` bundles that can be relocated. Instead, please consider using `brew cask` and migrate formulae using `.app`s to casks. + EOS + target_dir = linkapps_target(local: ARGV.include?("--local")) unlinkapps_from_dir(target_dir, dry_run: ARGV.dry_run?) diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index 10b433dd25..dcf2891d90 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -35,7 +35,7 @@ module Homebrew ohai "Homebrew has enabled anonymous aggregate user behaviour analytics." puts <<-EOS.undent #{Tty.bold}Read the analytics documentation (and how to opt-out) here: - #{Formatter.url("https://git.io/brew-analytics")}#{Tty.reset} + #{Formatter.url("http://docs.brew.sh/Analytics.html")}#{Tty.reset} EOS @@ -387,7 +387,7 @@ class Reporter end end - renamed_formulae = [] + renamed_formulae = Set.new @report[:D].each do |old_full_name| old_name = old_full_name.split("/").last new_name = tap.formula_renames[old_name] @@ -402,10 +402,24 @@ class Reporter renamed_formulae << [old_full_name, new_full_name] if @report[:A].include? new_full_name end + @report[:A].each do |new_full_name| + new_name = new_full_name.split("/").last + old_name = tap.formula_renames.key(new_name) + next unless old_name + + if tap.core_tap? + old_full_name = old_name + else + old_full_name = "#{tap}/#{old_name}" + end + + renamed_formulae << [old_full_name, new_full_name] + end + unless renamed_formulae.empty? @report[:A] -= renamed_formulae.map(&:last) @report[:D] -= renamed_formulae.map(&:first) - @report[:R] = renamed_formulae + @report[:R] = renamed_formulae.to_a end @report @@ -421,18 +435,27 @@ class Reporter new_tap_name = tap.tap_migrations[name] next if new_tap_name.nil? # skip if not in tap_migrations list. + new_tap_user, new_tap_repo, new_tap_new_name = new_tap_name.split("/") + new_name = if new_tap_new_name + new_full_name = new_tap_new_name + new_tap_name = "#{new_tap_user}/#{new_tap_repo}" + new_tap_new_name + else + new_full_name = "#{new_tap_name}/#{name}" + name + end + # This means it is a Cask if report[:DC].include? full_name - next unless (HOMEBREW_PREFIX/"Caskroom"/name).exist? + next unless (HOMEBREW_PREFIX/"Caskroom"/new_name).exist? new_tap = Tap.fetch(new_tap_name) new_tap.install unless new_tap.installed? ohai "#{name} has been moved to Homebrew.", <<-EOS.undent To uninstall the cask run: brew cask uninstall --force #{name} EOS - new_full_name = "#{new_tap_name}/#{name}" - next if (HOMEBREW_CELLAR/name.split("/").last).directory? - ohai "Installing #{name}..." + next if (HOMEBREW_CELLAR/new_name.split("/").last).directory? + ohai "Installing #{new_name}..." system HOMEBREW_BREW_FILE, "install", new_full_name begin unless Formulary.factory(new_full_name).keg_only? @@ -456,13 +479,13 @@ class Reporter system HOMEBREW_BREW_FILE, "uninstall", "--force", name ohai "brew prune" system HOMEBREW_BREW_FILE, "prune" - ohai "brew cask install #{name}" - system HOMEBREW_BREW_FILE, "cask", "install", name + ohai "brew cask install #{new_name}" + system HOMEBREW_BREW_FILE, "cask", "install", new_name else ohai "#{name} has been moved to Homebrew-Cask.", <<-EOS.undent To uninstall the formula and install the cask run: brew uninstall --force #{name} - brew cask install #{name} + brew cask install #{new_name} EOS end else diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index 5b49a9f65b..ce892f85ce 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -94,14 +94,24 @@ module Homebrew .select(&:directory?) .map { |k| Keg.new(k.resolved_path) } + if f.opt_prefix.directory? + keg = Keg.new(f.opt_prefix.resolved_path) + tab = Tab.for_keg(keg) + end + fi = FormulaInstaller.new(f) - fi.options = f.build.used_options - fi.options &= f.options - fi.build_bottle = ARGV.build_bottle? || (!f.bottled? && f.build.build_bottle?) - fi.build_from_source = ARGV.build_from_source? || ARGV.build_all_from_source? - fi.verbose = ARGV.verbose? - fi.quieter = ARGV.quieter? - fi.debug = ARGV.debug? + fi.options = f.build.used_options + fi.options &= f.options + fi.build_bottle = ARGV.build_bottle? || (!f.bottled? && f.build.build_bottle?) + fi.build_from_source = ARGV.build_from_source? || ARGV.build_all_from_source? + fi.verbose = ARGV.verbose? + fi.quieter = ARGV.quieter? + fi.debug = ARGV.debug? + fi.installed_on_request = !ARGV.named.empty? + if tab + fi.installed_as_dependency = tab.installed_as_dependency + fi.installed_on_request ||= tab.installed_on_request + end fi.prelude oh1 "Upgrading #{f.full_specified_name} #{fi.options.to_a.join " "}" diff --git a/Library/Homebrew/cmd/uses.rb b/Library/Homebrew/cmd/uses.rb index fb11a31a74..5f6611dfc5 100644 --- a/Library/Homebrew/cmd/uses.rb +++ b/Library/Homebrew/cmd/uses.rb @@ -57,16 +57,36 @@ module Homebrew elsif dep.build? Dependency.prune unless includes.include?("build?") end - end - reqs = f.recursive_requirements do |dependent, req| - if req.recommended? - Requirement.prune if ignores.include?("recommended?") || dependent.build.without?(req) - elsif req.optional? - Requirement.prune if !includes.include?("optional?") && !dependent.build.with?(req) - elsif req.build? - Requirement.prune unless includes.include?("build?") + + # If a tap isn't installed, we can't find the dependencies of one + # its formulae, and an exception will be thrown if we try. + if dep.is_a?(TapDependency) && !dep.tap.installed? + Dependency.keep_but_prune_recursive_deps end end + + dep_formulae = deps.map do |dep| + begin + dep.to_formula + rescue + end + end.compact + + reqs_by_formula = ([f] + dep_formulae).flat_map do |formula| + formula.requirements.map { |req| [formula, req] } + end + + reqs_by_formula.reject! do |dependent, req| + if req.recommended? + ignores.include?("recommended?") || dependent.build.without?(req) + elsif req.optional? + !includes.include?("optional?") && !dependent.build.with?(req) + elsif req.build? + !includes.include?("build?") + end + end + + reqs = reqs_by_formula.map(&:last) else deps = f.deps.reject do |dep| ignores.any? { |ignore| dep.send(ignore) } && !includes.any? { |include| dep.send(include) } diff --git a/Library/Homebrew/compat.rb b/Library/Homebrew/compat.rb index 5d78c715f1..92b687725a 100644 --- a/Library/Homebrew/compat.rb +++ b/Library/Homebrew/compat.rb @@ -22,3 +22,6 @@ require "compat/json" require "compat/ARGV" require "compat/build_options" require "compat/tab" +require "compat/ENV/shared" +require "compat/ENV/std" +require "compat/ENV/super" diff --git a/Library/Homebrew/compat/ENV/shared.rb b/Library/Homebrew/compat/ENV/shared.rb new file mode 100644 index 0000000000..200e7b132b --- /dev/null +++ b/Library/Homebrew/compat/ENV/shared.rb @@ -0,0 +1,6 @@ +module SharedEnvExtension + def j1 + odeprecated "ENV.j1", "ENV.deparallelize" + deparallelize + end +end diff --git a/Library/Homebrew/compat/ENV/std.rb b/Library/Homebrew/compat/ENV/std.rb new file mode 100644 index 0000000000..26dabe440d --- /dev/null +++ b/Library/Homebrew/compat/ENV/std.rb @@ -0,0 +1,27 @@ +module Stdenv + def fast + odeprecated "ENV.fast" + end + + def O4 + odeprecated "ENV.O4" + end + + def Og + odeprecated "ENV.Og" + end + + def gcc_4_0_1 + odeprecated "ENV.gcc_4_0_1", "ENV.gcc_4_0" + gcc_4_0 + end + + def gcc + odeprecated "ENV.gcc", "ENV.gcc_4_2" + gcc_4_2 + end + + def libpng + odeprecated "ENV.libpng", "ENV.x11" + end +end diff --git a/Library/Homebrew/compat/ENV/super.rb b/Library/Homebrew/compat/ENV/super.rb new file mode 100644 index 0000000000..2020ad752c --- /dev/null +++ b/Library/Homebrew/compat/ENV/super.rb @@ -0,0 +1,47 @@ +module Superenv + def fast + odeprecated "ENV.fast" + end + + def O4 + odeprecated "ENV.O4" + end + + def Og + odeprecated "ENV.Og" + end + + def gcc_4_0_1 + odeprecated "ENV.gcc_4_0_1", "ENV.gcc_4_0" + gcc_4_0 + end + + def gcc + odeprecated "ENV.gcc", "ENV.gcc_4_2" + gcc_4_2 + end + + def libxml2 + odeprecated "ENV.libxml2" + end + + def minimal_optimization + odeprecated "ENV.minimal_optimization" + end + + def no_optimization + odeprecated "ENV.no_optimization" + end + + def enable_warnings + odeprecated "ENV.enable_warnings" + end + + def macosxsdk + odeprecated "ENV.macosxsdk" + end + + def remove_macosxsdk + odeprecated "ENV.remove_macosxsdk" + end +end diff --git a/Library/Homebrew/compat/hbc.rb b/Library/Homebrew/compat/hbc.rb index a1d1414a59..179639953e 100644 --- a/Library/Homebrew/compat/hbc.rb +++ b/Library/Homebrew/compat/hbc.rb @@ -1 +1,2 @@ require "compat/hbc/cask_loader" +require "compat/hbc/cli/update" diff --git a/Library/Homebrew/compat/hbc/cli/update.rb b/Library/Homebrew/compat/hbc/cli/update.rb new file mode 100644 index 0000000000..7820997cbb --- /dev/null +++ b/Library/Homebrew/compat/hbc/cli/update.rb @@ -0,0 +1,23 @@ +require "cask/lib/hbc/cli/base" + +module Hbc + class CLI + class Update < Base + def self.run(*_ignored) + odeprecated "`brew cask update`", "`brew update`", disable_on: Time.utc(2017, 7, 1) + result = SystemCommand.run(HOMEBREW_BREW_FILE, args: ["update"], + print_stderr: true, + print_stdout: true) + exit result.exit_status + end + + def self.visible + false + end + + def self.help + "a synonym for 'brew update'" + end + end + end +end diff --git a/Library/Homebrew/compat/macos.rb b/Library/Homebrew/compat/macos.rb index 17f4670cc7..3acd2f9ef7 100644 --- a/Library/Homebrew/compat/macos.rb +++ b/Library/Homebrew/compat/macos.rb @@ -100,23 +100,23 @@ module OS end def gcc_40_build_version - odeprecated "MacOS.gcc_40_build_version", "DevelopmentTools.gcc_40_build_version" - DevelopmentTools.gcc_40_build_version + odeprecated "MacOS.gcc_40_build_version", "DevelopmentTools.gcc_4_0_build_version" + DevelopmentTools.gcc_4_0_build_version end def gcc_4_0_build_version - odeprecated "MacOS.gcc_4_0_build_version", "DevelopmentTools.gcc_40_build_version" - DevelopmentTools.gcc_40_build_version + odeprecated "MacOS.gcc_4_0_build_version", "DevelopmentTools.gcc_4_0_build_version" + DevelopmentTools.gcc_4_0_build_version end def gcc_42_build_version - odeprecated "MacOS.gcc_42_build_version", "DevelopmentTools.gcc_42_build_version" - DevelopmentTools.gcc_42_build_version + odeprecated "MacOS.gcc_42_build_version", "DevelopmentTools.gcc_4_2_build_version" + DevelopmentTools.gcc_4_2_build_version end def gcc_build_version - odeprecated "MacOS.gcc_build_version", "DevelopmentTools.gcc_42_build_version" - DevelopmentTools.gcc_42_build_version + odeprecated "MacOS.gcc_build_version", "DevelopmentTools.gcc_4_2_build_version" + DevelopmentTools.gcc_4_2_build_version end def llvm_build_version diff --git a/Library/Homebrew/compilers.rb b/Library/Homebrew/compilers.rb index 9ee847db0e..628e71e9b8 100644 --- a/Library/Homebrew/compilers.rb +++ b/Library/Homebrew/compilers.rb @@ -4,7 +4,7 @@ module CompilerConstants GNU_GCC_REGEXP = /^gcc-(4\.[3-9]|[5-7])$/ COMPILER_SYMBOL_MAP = { "gcc-4.0" => :gcc_4_0, - "gcc-4.2" => :gcc, + "gcc-4.2" => :gcc_4_2, "clang" => :clang, "llvm_clang" => :llvm_clang, }.freeze @@ -68,7 +68,7 @@ class CompilerFailure COLLECTIONS = { cxx11: [ create(:gcc_4_0), - create(:gcc), + create(:gcc_4_2), create(:clang) { build 425 }, create(gcc: "4.3"), create(gcc: "4.4"), @@ -87,9 +87,9 @@ class CompilerSelector Compiler = Struct.new(:name, :version) COMPILER_PRIORITY = { - clang: [:clang, :gcc, :gnu, :gcc_4_0, :llvm_clang], - gcc: [:gcc, :gnu, :clang, :gcc_4_0], - gcc_4_0: [:gcc_4_0, :gcc, :gnu, :clang], + clang: [:clang, :gcc_4_2, :gnu, :gcc_4_0, :llvm_clang], + gcc_4_2: [:gcc_4_2, :gnu, :clang, :gcc_4_0], + gcc_4_0: [:gcc_4_0, :gcc_4_2, :gnu, :clang], }.freeze def self.select_for(formula, compilers = self.compilers) diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 253ba4bee7..4a452440a7 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -175,7 +175,7 @@ class TapDependency < Dependency attr_reader :tap def initialize(name, tags = [], env_proc = DEFAULT_ENV_PROC, option_names = [name.split("/").last]) - @tap = name.rpartition("/").first + @tap = Tap.fetch(name.rpartition("/").first) super(name, tags, env_proc, option_names) end diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index fffe14b47a..af1e4a71bf 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -169,6 +169,33 @@ class FormulaAuditor @specs = %w[stable devel head].map { |s| formula.send(s) }.compact end + def url_status_code(url, range: false, user_agent: :default) + # The system Curl is too old and unreliable with HTTPS homepages on + # Yosemite and below. + return "200" unless DevelopmentTools.curl_handles_most_https_homepages? + + extra_args = [ + "--connect-timeout", "15", + "--output", "/dev/null", + "--write-out", "%{http_code}" + ] + extra_args << "--range" << "0-0" if range + extra_args << url + + args = curl_args( + extra_args: extra_args, + show_output: true, + user_agent: user_agent + ) + retries = 3 + status_code = nil + retries.times do + status_code = Open3.popen3(*args) { |_, stdout, _, _| stdout.read } + break if status_code.start_with? "20" + end + status_code + end + def audit_style return unless @style_offenses display_cop_names = ARGV.include?("--display-cop-names") @@ -432,6 +459,14 @@ class FormulaAuditor end def audit_conflicts + if formula.conflicts.any? && formula.versioned_formula? + problem <<-EOS + Versioned formulae should not use `conflicts_with`. + Use `keg_only :versioned_formula` instead. + EOS + return + end + formula.conflicts.each do |c| begin Formulary.factory(c.name) @@ -454,6 +489,10 @@ class FormulaAuditor next unless @strict + if o.name == "universal" && !Formula["wine"].recursive_dependencies.map(&:name).include?(formula.name) + problem "macOS has been 64-bit only since 10.6 so universal options are deprecated." + end + if o.name !~ /with(out)?-/ && o.name != "c++11" && o.name != "universal" problem "Options should begin with with/without. Migrate '--#{o.name}' with `deprecated_option`." end @@ -466,7 +505,7 @@ class FormulaAuditor return unless @new_formula return if formula.deprecated_options.empty? - return if formula.name.include?("@") + return if formula.versioned_formula? problem "New formulae should not use `deprecated_option`." end @@ -569,11 +608,10 @@ class FormulaAuditor end return unless @online - begin - nostdout { curl "--connect-timeout", "15", "-o", "/dev/null", homepage } - rescue ErrorDuringExecution - problem "The homepage is not reachable (curl exit code #{$?.exitstatus})" - end + + status_code = url_status_code(homepage, user_agent: :browser) + return if status_code.start_with? "20" + problem "The homepage #{homepage} is not reachable (HTTP status code #{status_code})" end def audit_bottle_spec @@ -652,11 +690,47 @@ class FormulaAuditor end end + unstable_whitelist = %w[ + aalib 1.4rc5 + automysqlbackup 3.0-rc6 + aview 1.3.0rc1 + distcc 3.2rc1 + elm-format 0.5.2-alpha + ftgl 2.1.3-rc5 + hidapi 0.8.0-rc1 + libcaca 0.99b19 + premake 4.4-beta5 + pwnat 0.3-beta + pxz 4.999.9 + recode 3.7-beta2 + speexdsp 1.2rc3 + sqoop 1.4.6 + tcptraceroute 1.5beta7 + testssl 2.8rc3 + tiny-fugue 5.0b8 + vbindiff 3.0_beta4 + ].each_slice(2).to_a.map do |formula, version| + [formula, version.sub(/\d+$/, "")] + end + + gnome_devel_whitelist = %w[ + gtk-doc 1.25 + libart 2.3.21 + pygtkglext 1.1.0 + ].each_slice(2).to_a.map do |formula, version| + [formula, version.split(".")[0..1].join(".")] + end + stable = formula.stable case stable && stable.url when /[\d\._-](alpha|beta|rc\d)/ - problem "Stable version URLs should not contain #{$1}" + matched = $1 + version_prefix = stable.version.to_s.sub(/\d+$/, "") + return if unstable_whitelist.include?([formula.name, version_prefix]) + problem "Stable version URLs should not contain #{matched}" when %r{download\.gnome\.org/sources}, %r{ftp\.gnome\.org/pub/GNOME/sources}i + version_prefix = stable.version.to_s.split(".")[0..1].join(".") + return if gnome_devel_whitelist.include?([formula.name, version_prefix]) version = Version.parse(stable.url) if version >= Version.create("1.0") minor_version = version.to_s.split(".", 3)[1].to_i @@ -789,6 +863,15 @@ class FormulaAuditor problem "Please set plist_options when using a formula-defined plist." end + if text =~ /depends_on\s+['"]openssl['"]/ && text =~ /depends_on\s+['"]libressl['"]/ + problem "Formulae should not depend on both OpenSSL and LibreSSL (even optionally)." + end + + if text =~ /virtualenv_(create|install_with_resources)/ && + text =~ /resource\s+['"]setuptools['"]\s+do/ + problem "Formulae using virtualenvs do not need a `setuptools` resource." + end + return unless text.include?('require "language/go"') && !text.include?("go_resource") problem "require \"language/go\" is unnecessary unless using `go_resource`s" end @@ -1018,6 +1101,8 @@ class FormulaAuditor return unless @strict + problem "`#{$1}` in formulae is deprecated" if line =~ /(env :(std|userpaths))/ + if line =~ /system ((["'])[^"' ]*(?:\s[^"' ]*)+\2)/ bad_system = $1 unless %w[| < > & ; *].any? { |c| bad_system.include? c } diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 9618cf4121..7367e5c372 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -435,6 +435,7 @@ module Homebrew else string = s.sub!( /( + (\ {2}\#[^\n]*\n)* # comments \ {2}( # two spaces at the beginning (url|head)\ ['"][\S\ ]+['"] # url or head with a string ( @@ -442,7 +443,7 @@ module Homebrew (\n^\ {3}[\S\ ]+$)* # options can be in multiple lines )?| (homepage|desc|sha1|sha256|version|mirror)\ ['"][\S\ ]+['"]| # specs with a string - rebuild\ \d+ # rebuild with a number + revision\ \d+ # revision with a number )\n+ # multiple empty lines )+ /mx, '\0' + output + "\n" diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index b1f851b8db..68bf32d0bf 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -124,6 +124,8 @@ module Homebrew false elsif !hash_type odie "#{formula}: no tag/revision specified!" + elsif !new_url + odie "#{formula}: no url specified!" else rsrc_url = if requested_spec != :devel && new_url =~ /.*ftpmirror.gnu.*/ new_mirror = new_url.sub "ftpmirror.gnu.org", "ftp.gnu.org/gnu" @@ -156,7 +158,9 @@ module Homebrew replacement_pairs << [/^ revision \d+\n(\n( head "))?/m, "\\2"] end - replacement_pairs << [/(^ mirror .*\n)?/, ""] if requested_spec == :stable + replacement_pairs += formula_spec.mirrors.map do |mirror| + [/ +mirror \"#{mirror}\"\n/m, ""] + end replacement_pairs += if new_url_hash [ diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb index f684f95f6c..b4cda0fad5 100644 --- a/Library/Homebrew/dev-cmd/create.rb +++ b/Library/Homebrew/dev-cmd/create.rb @@ -1,4 +1,4 @@ -#: * `create` [`--autotools`|`--cmake`] [`--no-fetch`] [`--set-name` ] [`--set-version` ] [`--tap` `/`]: +#: * `create` [`--autotools`|`--cmake`|`--meson`] [`--no-fetch`] [`--set-name` ] [`--set-version` ] [`--tap` `/`]: #: Generate a formula for the downloadable file at and open it in the editor. #: Homebrew will attempt to automatically derive the formula name #: and version, but if it fails, you'll have to make your own template. The `wget` @@ -8,6 +8,7 @@ #: #: If `--autotools` is passed, create a basic template for an Autotools-style build. #: If `--cmake` is passed, create a basic template for a CMake-style build. +#: If `--meson` is passed, create a basic template for a Meson-style build. #: #: If `--no-fetch` is passed, Homebrew will not download to the cache and #: will thus not add the SHA256 to the formula for you. @@ -59,6 +60,8 @@ module Homebrew :cmake elsif ARGV.include? "--autotools" :autotools + elsif ARGV.include? "--meson" + :meson end if fc.name.nil? || fc.name.strip.empty? @@ -139,12 +142,10 @@ class FormulaCreator def generate! raise "#{path} already exists" if path.exist? - if version.nil? + if version.nil? || version.null? opoo "Version cannot be determined from URL." puts "You'll need to add an explicit 'version' to the formula." - end - - if fetch? && version + elsif fetch? r = Resource.new r.url(url) r.version(version) @@ -156,7 +157,7 @@ class FormulaCreator end def template; <<-EOS.undent - # Documentation: https://github.com/Homebrew/brew/blob/master/docs/Formula-Cookbook.md + # Documentation: http://docs.brew.sh/Formula-Cookbook.html # http://www.rubydoc.info/github/Homebrew/brew/master/Formula # PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST! @@ -175,10 +176,12 @@ class FormulaCreator <% if mode == :cmake %> depends_on "cmake" => :build + <% elsif mode == :meson %> + depends_on "meson" => :build + depends_on "ninja" => :build <% elsif mode.nil? %> # depends_on "cmake" => :build <% end %> - depends_on :x11 # if your formula requires any X11/XQuartz components def install # ENV.deparallelize # if your formula fails when building in parallel @@ -191,6 +194,13 @@ class FormulaCreator "--disable-dependency-tracking", "--disable-silent-rules", "--prefix=\#{prefix}" + <% elsif mode == :meson %> + mkdir "build" do + system "meson", "--prefix=\#{prefix}", ".." + system "ninja" + system "ninja", "test" + system "ninja", "install" + end <% else %> # Remove unrecognized options if warned by configure system "./configure", "--disable-debug", @@ -199,7 +209,9 @@ class FormulaCreator "--prefix=\#{prefix}" # system "cmake", ".", *std_cmake_args <% end %> + <% if mode != :meson %> system "make", "install" # if this fails, try separate make/make install steps + <% end %> end test do diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index b4f3c2d40d..05bdda8d2e 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -34,6 +34,7 @@ module Homebrew %w[AUTHOR COMMITTER].each do |role| ENV["GIT_#{role}_NAME"] = "brew tests" ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost" + ENV["GIT_#{role}_DATE"] = "Sun Jan 22 19:59:13 2017 +0000" end Homebrew.install_gem_setup_path! "bundler" diff --git a/Library/Homebrew/development_tools.rb b/Library/Homebrew/development_tools.rb index ea7f5837d0..625d5ea86b 100644 --- a/Library/Homebrew/development_tools.rb +++ b/Library/Homebrew/development_tools.rb @@ -34,15 +34,11 @@ class DevelopmentTools end def default_compiler - if default_cc =~ /^gcc/ - :gcc - else - :clang - end + :clang end - def gcc_40_build_version - @gcc_40_build_version ||= begin + def gcc_4_0_build_version + @gcc_4_0_build_version ||= begin if (path = locate("gcc-4.0")) && build_version = `#{path} --version 2>/dev/null`[/build (\d{4,})/, 1] Version.new build_version @@ -51,10 +47,9 @@ class DevelopmentTools end end end - alias gcc_4_0_build_version gcc_40_build_version - def gcc_42_build_version - @gcc_42_build_version ||= begin + def gcc_4_2_build_version + @gcc_4_2_build_version ||= begin gcc = locate("gcc-4.2") || HOMEBREW_PREFIX.join("opt/apple-gcc42/bin/gcc-4.2") if gcc.exist? && !gcc.realpath.basename.to_s.start_with?("llvm")&& build_version = `#{gcc} --version 2>/dev/null`[/build (\d{4,})/, 1] @@ -64,7 +59,6 @@ class DevelopmentTools end end end - alias gcc_build_version gcc_42_build_version def clang_version @clang_version ||= begin @@ -115,13 +109,13 @@ class DevelopmentTools end def clear_version_cache - @gcc_40_build_version = @gcc_42_build_version = nil + @gcc_4_0_build_version = @gcc_4_2_build_version = nil @clang_version = @clang_build_version = nil @non_apple_gcc_version = {} end - def tar_supports_xz? - false + def curl_handles_most_https_homepages? + true end end end diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index 81404c6252..5ac57273a0 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -1087,6 +1087,29 @@ module Homebrew message end + def check_for_tap_ruby_files_locations + bad_tap_files = {} + Tap.each do |tap| + unused_formula_dirs = tap.potential_formula_dirs - [tap.formula_dir] + unused_formula_dirs.each do |dir| + next unless dir.exist? + dir.children.each do |path| + next unless path.extname == ".rb" + bad_tap_files[tap] ||= [] + bad_tap_files[tap] << path + end + end + end + return if bad_tap_files.empty? + bad_tap_files.keys.map do |tap| + <<-EOS.undent + Found Ruby file outside #{tap} tap formula directory + (#{tap.formula_dir}): + #{bad_tap_files[tap].join("\n ")} + EOS + end.join("\n") + end + def all methods.map(&:to_s).grep(/^check_/) end diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 9f9b2ababe..bd036067df 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -532,6 +532,110 @@ class S3DownloadStrategy < CurlDownloadStrategy end end +# GitHubPrivateRepositoryDownloadStrategy downloads contents from GitHub +# Private Repository. To use it, add +# ":using => GitHubPrivateRepositoryDownloadStrategy" to the URL section of +# your formula. This download strategy uses GitHub access tokens (in the +# environment variables HOMEBREW_GITHUB_API_TOKEN) to sign the request. This +# strategy is suitable for corporate use just like S3DownloadStrategy, because +# it lets you use a private GttHub repository for internal distribution. It +# works with public one, but in that case simply use CurlDownloadStrategy. +class GitHubPrivateRepositoryDownloadStrategy < CurlDownloadStrategy + require "utils/formatter" + require "utils/github" + + def initialize(name, resource) + super + parse_url_pattern + set_github_token + end + + def parse_url_pattern + url_pattern = %r{https://github.com/([^/]+)/([^/]+)/(\S+)} + unless @url =~ url_pattern + raise CurlDownloadStrategyError, "Invalid url pattern for GitHub Repository." + end + + _, @owner, @repo, @filepath = *@url.match(url_pattern) + end + + def download_url + "https://#{@github_token}@github.com/#{@owner}/#{@repo}/#{@filepath}" + end + + def _fetch + curl download_url, "-C", downloaded_size, "-o", temporary_path + end + + private + + def set_github_token + @github_token = ENV["HOMEBREW_GITHUB_API_TOKEN"] + unless @github_token + raise CurlDownloadStrategyError, "Environmental variable HOMEBREW_GITHUB_API_TOKEN is required." + end + validate_github_repository_access! + end + + def validate_github_repository_access! + # Test access to the repository + GitHub.repository(@owner, @repo) + rescue GitHub::HTTPNotFoundError + # We only handle HTTPNotFoundError here, + # becase AuthenticationFailedError is handled within util/github. + message = <<-EOS.undent + HOMEBREW_GITHUB_API_TOKEN can not access the repository: #{@owner}/#{@repo} + This token may not have permission to access the repository or the url of formula may be incorrect. + EOS + raise CurlDownloadStrategyError, message + end +end + +# GitHubPrivateRepositoryReleaseDownloadStrategy downloads tarballs from GitHub +# Release assets. To use it, add +# ":using => GitHubPrivateRepositoryReleaseDownloadStrategy" to the URL section +# of your formula. This download strategy uses GitHub access tokens (in the +# environment variables HOMEBREW_GITHUB_API_TOKEN) to sign the request. +class GitHubPrivateRepositoryReleaseDownloadStrategy < GitHubPrivateRepositoryDownloadStrategy + def parse_url_pattern + url_pattern = %r{https://github.com/([^/]+)/([^/]+)/releases/download/([^/]+)/(\S+)} + unless @url =~ url_pattern + raise CurlDownloadStrategyError, "Invalid url pattern for GitHub Release." + end + + _, @owner, @repo, @tag, @filename = *@url.match(url_pattern) + end + + def download_url + "https://#{@github_token}@api.github.com/repos/#{@owner}/#{@repo}/releases/assets/#{asset_id}" + end + + def _fetch + # HTTP request header `Accept: application/octet-stream` is required. + # Without this, the GitHub API will respond with metadata, not binary. + curl download_url, "-C", downloaded_size, "-o", temporary_path, "-H", "Accept: application/octet-stream" + end + + private + + def asset_id + @asset_id ||= resolve_asset_id + end + + def resolve_asset_id + release_metadata = fetch_release_metadata + assets = release_metadata["assets"].select { |a| a["name"] == @filename } + raise CurlDownloadStrategyError, "Asset file not found." if assets.empty? + + assets.first["id"] + end + + def fetch_release_metadata + release_url = "https://api.github.com/repos/#{@owner}/#{@repo}/releases/tags/#{@tag}" + GitHub.open(release_url) + end +end + class SubversionDownloadStrategy < VCSDownloadStrategy def initialize(name, resource) super diff --git a/Library/Homebrew/emoji.rb b/Library/Homebrew/emoji.rb index 8c58ca8952..43fa781e6b 100644 --- a/Library/Homebrew/emoji.rb +++ b/Library/Homebrew/emoji.rb @@ -1,17 +1,7 @@ module Emoji class << self - def tick - # necessary for 1.8.7 unicode handling since many installs are on 1.8.7 - @tick ||= ["2714".hex].pack("U*") - end - - def cross - # necessary for 1.8.7 unicode handling since many installs are on 1.8.7 - @cross ||= ["2718".hex].pack("U*") - end - def install_badge - ENV["HOMEBREW_INSTALL_BADGE"] || "\xf0\x9f\x8d\xba" + ENV["HOMEBREW_INSTALL_BADGE"] || "🍺" end def enabled? diff --git a/Library/Homebrew/extend/ARGV.rb b/Library/Homebrew/extend/ARGV.rb index d361a99a8f..767ddc6e3e 100644 --- a/Library/Homebrew/extend/ARGV.rb +++ b/Library/Homebrew/extend/ARGV.rb @@ -44,7 +44,7 @@ module HomebrewArgvExtension else Formulary.find_with_priority(name, spec) end - end + end.uniq(&:name) end def resolved_formulae @@ -79,7 +79,7 @@ module HomebrewArgvExtension f.follow_installed_alias = false f - end + end.uniq(&:name) end def casks diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb index a93c1ee1f6..7b468574ad 100644 --- a/Library/Homebrew/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/ENV/shared.rb @@ -17,7 +17,7 @@ module SharedEnvExtension FC_FLAG_VARS = %w[FCFLAGS FFLAGS].freeze # @private SANITIZED_VARS = %w[ - CDPATH GREP_OPTIONS CLICOLOR_FORCE + CDPATH CLICOLOR_FORCE CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH CC CXX OBJC OBJCXX CPP MAKE LD LDSHARED CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS diff --git a/Library/Homebrew/extend/ENV/std.rb b/Library/Homebrew/extend/ENV/std.rb index 14f9b81b8e..403ea19783 100644 --- a/Library/Homebrew/extend/ENV/std.rb +++ b/Library/Homebrew/extend/ENV/std.rb @@ -82,10 +82,6 @@ module Stdenv old end - alias j1 deparallelize - - # These methods are no-ops for compatibility. - %w[fast O4 Og].each { |opt| define_method(opt) {} } %w[O3 O2 O1 O0 Os].each do |opt| define_method opt do @@ -110,13 +106,11 @@ module Stdenv super set_cpu_cflags "-march=nocona -mssse3" end - alias gcc_4_0_1 gcc_4_0 - def gcc + def gcc_4_2 super set_cpu_cflags end - alias gcc_4_2 gcc GNU_GCC_VERSIONS.each do |n| define_method(:"gcc-#{n}") do @@ -144,13 +138,6 @@ module Stdenv end alias generic_no_optimization no_optimization - def libxml2 - end - - def x11 - end - alias libpng x11 - # we've seen some packages fail to build when warnings are disabled! def enable_warnings remove_from_cflags "-w" diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb index a75cba406d..39ddb66819 100644 --- a/Library/Homebrew/extend/ENV/super.rb +++ b/Library/Homebrew/extend/ENV/super.rb @@ -16,9 +16,7 @@ module Superenv # @private attr_accessor :keg_only_deps, :deps - attr_accessor :x11 - alias x11? x11 def self.extended(base) base.keg_only_deps = [] @@ -263,7 +261,6 @@ module Superenv old end - alias j1 deparallelize def make_jobs self["MAKEFLAGS"] =~ /-\w*j(\d+)/ @@ -329,23 +326,10 @@ module Superenv def set_x11_env_if_installed end + # This method does nothing in superenv since there's no custom CFLAGS API # @private - def noop(*_args); end - - # These methods are no longer necessary under superenv, but are needed to - # maintain an interface compatible with stdenv. - alias fast noop - alias O4 noop - alias Og noop - alias libxml2 noop - alias set_cpu_flags noop - - # These methods provide functionality that has not yet been ported to - # superenv. - alias gcc_4_0_1 noop - alias minimal_optimization noop - alias no_optimization noop - alias enable_warnings noop + def set_cpu_flags(*_args) + end end class Array diff --git a/Library/Homebrew/extend/fileutils.rb b/Library/Homebrew/extend/fileutils.rb index 4f20d36a3b..287a1408f4 100644 --- a/Library/Homebrew/extend/fileutils.rb +++ b/Library/Homebrew/extend/fileutils.rb @@ -3,7 +3,7 @@ require "tmpdir" require "etc" # Homebrew extends Ruby's `FileUtils` to make our code more readable. -# @see http://ruby-doc.org/stdlib-1.8.7/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API +# @see http://ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API module FileUtils # Create a temporary directory then yield. When the block returns, # recursively delete the temporary directory. Passing opts[:retain] diff --git a/Library/Homebrew/extend/os/linux/hardware/cpu.rb b/Library/Homebrew/extend/os/linux/hardware/cpu.rb index 2472c60ed1..9d779f789a 100644 --- a/Library/Homebrew/extend/os/linux/hardware/cpu.rb +++ b/Library/Homebrew/extend/os/linux/hardware/cpu.rb @@ -47,6 +47,8 @@ module Hardware :haswell when 0x3d, 0x47, 0x4f, 0x56 :broadwell + when 0x8e + :kabylake else cpu_family_model end diff --git a/Library/Homebrew/extend/os/mac/development_tools.rb b/Library/Homebrew/extend/os/mac/development_tools.rb index 7c97b9d69e..1bb12a3d13 100644 --- a/Library/Homebrew/extend/os/mac/development_tools.rb +++ b/Library/Homebrew/extend/os/mac/development_tools.rb @@ -64,21 +64,22 @@ class DevelopmentTools case default_cc # if GCC 4.2 is installed, e.g. via Tigerbrew, prefer it # over the system's GCC 4.0 - when /^gcc-4\.0/ then gcc_42_build_version ? :gcc : :gcc_4_0 - when /^gcc/ then :gcc + when /^gcc-4\.0/ then gcc_4_2_build_version ? :gcc_4_2 : :gcc_4_0 + when /^gcc/ then :gcc_4_2 when "clang" then :clang else # guess :( if MacOS::Xcode.version >= "4.3" :clang else - :gcc + :gcc_4_2 end end end - def tar_supports_xz? - false + def curl_handles_most_https_homepages? + # The system Curl is too old for some modern HTTPS homepages on Yosemite. + MacOS.version >= :el_capitan end end end diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb index 5f4a3e4aa8..f97a2dbbbf 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb @@ -1,4 +1,6 @@ module Superenv + alias x11? x11 + # @private def self.bin return unless DevelopmentTools.installed? @@ -120,9 +122,4 @@ module Superenv def no_weak_imports append "HOMEBREW_CCCFG", "w" if no_weak_imports_support? end - - # These methods are no longer necessary under superenv, but are needed to - # maintain an interface compatible with stdenv. - alias macosxsdk noop - alias remove_macosxsdk noop end diff --git a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb index 8bc42ad35f..5b1c648bff 100644 --- a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb +++ b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb @@ -6,6 +6,8 @@ module FormulaCellarChecks formula.name.start_with?(formula_name) end + return if formula.name =~ /^php\d+$/ + return if MacOS.version < :mavericks && formula.name.start_with?("postgresql") return if MacOS.version < :yosemite && formula.name.start_with?("memcached") diff --git a/Library/Homebrew/extend/os/mac/keg_relocate.rb b/Library/Homebrew/extend/os/mac/keg_relocate.rb index 8f73daba59..f44a97b31d 100644 --- a/Library/Homebrew/extend/os/mac/keg_relocate.rb +++ b/Library/Homebrew/extend/os/mac/keg_relocate.rb @@ -6,7 +6,9 @@ class Keg each_install_name_for(file) do |bad_name| # Don't fix absolute paths unless they are rooted in the build directory - next if bad_name.start_with?("/") && !bad_name.start_with?(HOMEBREW_TEMP.to_s) + next if bad_name.start_with?("/") && + !bad_name.start_with?(HOMEBREW_TEMP.to_s) && + !bad_name.start_with?(HOMEBREW_TEMP.realpath.to_s) new_name = fixed_name(file, bad_name) change_install_name(bad_name, new_name, file) unless new_name == bad_name diff --git a/Library/Homebrew/extend/os/mac/utils/bottles.rb b/Library/Homebrew/extend/os/mac/utils/bottles.rb index 18312c9fa8..c54e4e5b77 100644 --- a/Library/Homebrew/extend/os/mac/utils/bottles.rb +++ b/Library/Homebrew/extend/os/mac/utils/bottles.rb @@ -49,6 +49,8 @@ module Utils if key.to_s.end_with?("_or_later") later_tag = key.to_s[/(\w+)_or_later$/, 1].to_sym MacOS::Version.from_symbol(later_tag) <= tag_version + elsif ARGV.force_bottle? + true end end end diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index 976ea7dd83..cfb0287041 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -26,11 +26,17 @@ module DiskUsageExtension private def compute_disk_usage - if directory? + path = if symlink? + resolved_path + else + self + end + + if path.directory? scanned_files = Set.new @file_count = 0 @disk_usage = 0 - find do |f| + path.find do |f| if f.directory? @disk_usage += f.lstat.size else @@ -47,7 +53,7 @@ module DiskUsageExtension end else @file_count = 1 - @disk_usage = lstat.size + @disk_usage = path.lstat.size end end end diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index b3927d260b..6df1eb4deb 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -26,7 +26,7 @@ require "migrator" # @see SharedEnvExtension # @see FileUtils # @see Pathname -# @see https://github.com/Homebrew/brew/blob/master/docs/Formula-Cookbook.md Formula Cookbook +# @see http://docs.brew.sh/Formula-Cookbook.html Formula Cookbook # @see https://github.com/styleguide/ruby Ruby Style Guide # #
class Wget < Formula
@@ -198,6 +198,7 @@ class Formula
     @build = active_spec.build
     @pin = FormulaPin.new(self)
     @follow_installed_alias = true
+    @prefix_returns_versioned_prefix = false
   end
 
   # @private
@@ -325,13 +326,13 @@ class Formula
     active_spec.bottle_disable_reason
   end
 
-  # Does the currently active {SoftwareSpec} has any bottle?
+  # Does the currently active {SoftwareSpec} have any bottle?
   # @private
   def bottle_defined?
     active_spec.bottle_defined?
   end
 
-  # Does the currently active {SoftwareSpec} has an installable bottle?
+  # Does the currently active {SoftwareSpec} have an installable bottle?
   # @private
   def bottled?
     active_spec.bottled?
@@ -381,6 +382,11 @@ class Formula
     PkgVersion.new(version, revision)
   end
 
+  # If this is a `@`-versioned formula.
+  def versioned_formula?
+    name.include?("@")
+  end
+
   # A named Resource for the currently active {SoftwareSpec}.
   # Additional downloads can be defined as {#resource}s.
   # {Resource#stage} will create a temporary directory and yield to a block.
@@ -548,9 +554,17 @@ class Formula
   end
 
   # The directory in the cellar that the formula is installed to.
-  # This directory contains the formula's name and version.
+  # This directory points to {#opt_prefix} if it exists and if #{prefix} is not
+  # called from within the same formula's {#install} or {#post_install} methods.
+  # Otherwise, return the full path to the formula's versioned cellar.
   def prefix(v = pkg_version)
-    Pathname.new("#{HOMEBREW_CELLAR}/#{name}/#{v}")
+    versioned_prefix = versioned_prefix(v)
+    if !@prefix_returns_versioned_prefix && v == pkg_version &&
+       versioned_prefix.directory? && Keg.new(versioned_prefix).optlinked?
+      opt_prefix
+    else
+      versioned_prefix
+    end
   end
 
   # Is the formula linked?
@@ -566,7 +580,7 @@ class Formula
   # Is formula's linked keg points to the prefix.
   def prefix_linked?(v = pkg_version)
     return false unless linked?
-    linked_keg.resolved_path == prefix(v)
+    linked_keg.resolved_path == versioned_prefix(v)
   end
 
   # {PkgVersion} of the linked keg for the formula.
@@ -579,7 +593,7 @@ class Formula
   # installed versions of this software
   # @private
   def rack
-    prefix.parent
+    Pathname.new("#{HOMEBREW_CELLAR}/#{name}")
   end
 
   # All currently installed prefix directories.
@@ -994,6 +1008,7 @@ class Formula
 
   # @private
   def run_post_install
+    @prefix_returns_versioned_prefix = true
     build = self.build
     self.build = Tab.for_formula(self)
     old_tmpdir = ENV["TMPDIR"]
@@ -1008,6 +1023,7 @@ class Formula
     ENV["TMPDIR"] = old_tmpdir
     ENV["TEMP"] = old_temp
     ENV["TMP"] = old_tmp
+    @prefix_returns_versioned_prefix = false
   end
 
   # Tell the user about any caveats regarding this package.
@@ -1110,6 +1126,7 @@ class Formula
   # where staging is a Mktemp staging context
   # @private
   def brew
+    @prefix_returns_versioned_prefix = true
     stage do |staging|
       staging.retain! if ARGV.keep_tmp?
       prepare_patches
@@ -1123,6 +1140,8 @@ class Formula
         cp Dir["config.log", "CMakeCache.txt"], logs
       end
     end
+  ensure
+    @prefix_returns_versioned_prefix = false
   end
 
   # @private
@@ -1406,7 +1425,7 @@ class Formula
         Formulary.from_rack(rack)
       rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
       end
-    end.compact
+    end.compact.uniq(&:name)
   end
 
   def self.installed_with_alias_path(alias_path)
@@ -1505,7 +1524,15 @@ class Formula
   # Returns a list of Dependency objects that are required at runtime.
   # @private
   def runtime_dependencies
-    recursive_dependencies.reject(&:build?)
+    runtime_dependencies = recursive_dependencies do |_, dependency|
+      Dependency.prune if dependency.build?
+      Dependency.prune if !dependency.required? && build.without?(dependency)
+    end
+    runtime_requirement_deps = recursive_requirements do |_, requirement|
+      Requirement.prune if requirement.build?
+      Requirement.prune if !requirement.required? && build.without?(requirement)
+    end.map(&:to_dependency).compact
+    runtime_dependencies + runtime_requirement_deps
   end
 
   # Returns a list of formulae depended on by this formula that aren't
@@ -1601,6 +1628,9 @@ class Formula
         "used_options" => tab.used_options.as_flags,
         "built_as_bottle" => tab.built_as_bottle,
         "poured_from_bottle" => tab.poured_from_bottle,
+        "runtime_dependencies" => tab.runtime_dependencies,
+        "installed_as_dependency" => tab.installed_as_dependency,
+        "installed_on_request" => tab.installed_on_request,
       }
     end
 
@@ -1621,6 +1651,7 @@ class Formula
 
   # @private
   def run_test
+    @prefix_returns_versioned_prefix = true
     old_home = ENV["HOME"]
     old_curl_home = ENV["CURL_HOME"]
     old_tmpdir = ENV["TMPDIR"]
@@ -1652,6 +1683,7 @@ class Formula
     ENV["TEMP"] = old_temp
     ENV["TMP"] = old_tmp
     ENV["TERM"] = old_term
+    @prefix_returns_versioned_prefix = false
   end
 
   # @private
@@ -1836,6 +1868,12 @@ class Formula
 
   private
 
+  # Returns the prefix for a given formula version number.
+  # @private
+  def versioned_prefix(v)
+    rack/v
+  end
+
   def exec_cmd(cmd, args, out, logfn)
     ENV["HOMEBREW_CC_LOG_PATH"] = logfn
 
@@ -2041,7 +2079,7 @@ class Formula
     # and you haven't passed or previously used any options on this formula.
     #
     # If you maintain your own repository, you can add your own bottle links.
-    # https://github.com/Homebrew/brew/blob/master/docs/Bottles.md
+    # http://docs.brew.sh/Bottles.html
     # You can ignore this block entirely if submitting to Homebrew/Homebrew, It'll be
     # handled for you by the Brew Test Bot.
     #
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index bd1cc93799..e8f0e4bf81 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -32,6 +32,7 @@ class FormulaInstaller
 
   attr_reader :formula
   attr_accessor :options, :build_bottle, :invalid_option_names
+  attr_accessor :installed_as_dependency, :installed_on_request
   mode_attr_accessor :show_summary_heading, :show_header
   mode_attr_accessor :build_from_source, :force_bottle
   mode_attr_accessor :ignore_deps, :only_deps, :interactive, :git
@@ -50,6 +51,8 @@ class FormulaInstaller
     @verbose = false
     @quieter = false
     @debug = false
+    @installed_as_dependency = false
+    @installed_on_request = true
     @options = Options.new
     @invalid_option_names = []
     @requirement_messages = []
@@ -146,7 +149,29 @@ class FormulaInstaller
     return if ignore_deps?
 
     recursive_deps = formula.recursive_dependencies
-    unlinked_deps = recursive_deps.map(&:to_formula).select do |dep|
+    recursive_formulae = recursive_deps.map(&:to_formula)
+
+    if ENV["HOMEBREW_CHECK_RECURSIVE_VERSION_DEPENDENCIES"]
+      version_hash = {}
+      version_conflicts = Set.new
+      recursive_formulae.each do |f|
+        name = f.name
+        unversioned_name, = name.split("@")
+        version_hash[unversioned_name] ||= Set.new
+        version_hash[unversioned_name] << name
+        next if version_hash[unversioned_name].length < 2
+        version_conflicts += version_hash[unversioned_name]
+      end
+      unless version_conflicts.empty?
+        raise CannotInstallFormulaError, <<-EOS.undent
+          #{formula.full_name} contains conflicting version recursive dependencies:
+            #{version_conflicts.to_a.join ", "}
+          View these with `brew deps --tree #{formula.full_name}`.
+        EOS
+      end
+    end
+
+    unlinked_deps = recursive_formulae.select do |dep|
       dep.installed? && !dep.keg_only? && !dep.linked_keg.directory?
     end
 
@@ -228,6 +253,12 @@ class FormulaInstaller
       category = "install"
       action = ([formula.full_name] + options).join(" ")
       Utils::Analytics.report_event(category, action)
+
+      if installed_on_request
+        category = "install_on_request"
+        action = ([formula.full_name] + options).join(" ")
+        Utils::Analytics.report_event(category, action)
+      end
     end
 
     @@attempted << formula
@@ -265,6 +296,12 @@ class FormulaInstaller
       brew_prefix = formula.prefix/".brew"
       brew_prefix.mkdir
       Pathname(brew_prefix/"#{formula.name}.rb").atomic_write(s)
+
+      keg = Keg.new(formula.prefix)
+      tab = Tab.for_keg(keg)
+      tab.installed_as_dependency = installed_as_dependency
+      tab.installed_on_request = installed_on_request
+      tab.write
     end
 
     build_bottle_postinstall if build_bottle?
@@ -348,8 +385,8 @@ class FormulaInstaller
     raise UnsatisfiedRequirements, fatals
   end
 
-  def install_requirement_default_formula?(req, dependent, build)
-    return false unless req.default_formula?
+  def install_requirement_formula?(req, dependent, build)
+    return false unless req.to_dependency
     return true unless req.satisfied?
     return false if req.run?
     install_bottle_for?(dependent, build) || build_bottle?
@@ -368,7 +405,7 @@ class FormulaInstaller
           Requirement.prune
         elsif req.build? && install_bottle_for?(dependent, build)
           Requirement.prune
-        elsif install_requirement_default_formula?(req, dependent, build)
+        elsif install_requirement_formula?(req, dependent, build)
           dep = req.to_dependency
           deps.unshift(dep)
           formulae.unshift(dep.to_formula)
@@ -461,6 +498,8 @@ class FormulaInstaller
     fi.build_from_source  = ARGV.build_formula_from_source?(df)
     fi.verbose            = verbose? && !quieter?
     fi.debug              = debug?
+    fi.installed_as_dependency = true
+    fi.installed_on_request = false
     fi.prelude
     oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}"
     fi.install
@@ -524,7 +563,7 @@ class FormulaInstaller
   def summary
     s = ""
     s << "#{Emoji.install_badge}  " if Emoji.enabled?
-    s << "#{formula.prefix}: #{formula.prefix.abv}"
+    s << "#{formula.prefix.resolved_path}: #{formula.prefix.abv}"
     s << ", built in #{pretty_duration build_time}" if build_time
     s
   end
@@ -786,6 +825,9 @@ class FormulaInstaller
     tab.poured_from_bottle = true
     tab.time = Time.now.to_i
     tab.head = HOMEBREW_REPOSITORY.git_head
+    tab.source["path"] = formula.specified_path.to_s
+    tab.installed_as_dependency = installed_as_dependency
+    tab.installed_on_request = installed_on_request
     tab.write
   end
 
diff --git a/Library/Homebrew/formula_support.rb b/Library/Homebrew/formula_support.rb
index e4f8003644..dcb995a6be 100644
--- a/Library/Homebrew/formula_support.rb
+++ b/Library/Homebrew/formula_support.rb
@@ -29,27 +29,32 @@ class KegOnlyReason
   def to_s
     return @explanation unless @explanation.empty?
     case @reason
-    when :provided_by_macos, :provided_by_osx then <<-EOS
-macOS already provides this software and installing another version in
-parallel can cause all kinds of trouble.
-EOS
-    when :shadowed_by_macos, :shadowed_by_osx then <<-EOS
-macOS provides similar software and installing this software in
-parallel can cause all kinds of trouble.
-EOS
-    when :provided_pre_mountain_lion then <<-EOS
-macOS already provides this software in versions before Mountain Lion.
-EOS
-    when :provided_pre_mavericks then <<-EOS
-macOS already provides this software in versions before Mavericks.
-EOS
-    when :provided_pre_el_capitan then <<-EOS
-macOS already provides this software in versions before El Capitan.
-EOS
-    when :provided_until_xcode43
-      "Xcode provides this software prior to version 4.3."
-    when :provided_until_xcode5
-      "Xcode provides this software prior to version 5."
+    when :versioned_formula then <<-EOS.undent
+      This is an alternate version of another formula.
+    EOS
+    when :provided_by_macos, :provided_by_osx then <<-EOS.undent
+      macOS already provides this software and installing another version in
+      parallel can cause all kinds of trouble.
+    EOS
+    when :shadowed_by_macos, :shadowed_by_osx then <<-EOS.undent
+      macOS provides similar software and installing this software in
+      parallel can cause all kinds of trouble.
+    EOS
+    when :provided_pre_mountain_lion then <<-EOS.undent
+      macOS already provides this software in versions before Mountain Lion.
+    EOS
+    when :provided_pre_mavericks then <<-EOS.undent
+      macOS already provides this software in versions before Mavericks.
+    EOS
+    when :provided_pre_el_capitan then <<-EOS.undent
+      macOS already provides this software in versions before El Capitan.
+    EOS
+    when :provided_until_xcode43 then <<-EOS.undent
+      Xcode provides this software prior to version 4.3.
+    EOS
+    when :provided_until_xcode5 then <<-EOS.undent
+      Xcode provides this software prior to version 5.
+    EOS
     else
       @reason
     end.strip
diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb
index 28c2a3be85..34b766fde1 100644
--- a/Library/Homebrew/formula_versions.rb
+++ b/Library/Homebrew/formula_versions.rb
@@ -15,6 +15,7 @@ class FormulaVersions
     @repository = formula.tap.path
     @entry_name = @path.relative_path_from(repository).to_s
     @max_depth = options[:max_depth]
+    @current_formula = formula
   end
 
   def rev_list(branch)
@@ -64,25 +65,33 @@ class FormulaVersions
 
     attributes.each do |attribute|
       attributes_map[attribute] ||= {}
+      # Set the attributes for the current formula in case it's not been
+      # committed yet.
+      set_attribute_map(attributes_map[attribute], @current_formula, attribute)
     end
 
     rev_list(branch) do |rev|
       formula_at_revision(rev) do |f|
         attributes.each do |attribute|
-          map = attributes_map[attribute]
-          if f.stable
-            map[:stable] ||= {}
-            map[:stable][f.stable.version] ||= []
-            map[:stable][f.stable.version] << f.send(attribute)
-          end
-          next unless f.devel
-          map[:devel] ||= {}
-          map[:devel][f.devel.version] ||= []
-          map[:devel][f.devel.version] << f.send(attribute)
+          set_attribute_map(attributes_map[attribute], f, attribute)
         end
       end
     end
 
     attributes_map
   end
+
+  private
+
+  def set_attribute_map(map, f, attribute)
+    if f.stable
+      map[:stable] ||= {}
+      map[:stable][f.stable.version] ||= []
+      map[:stable][f.stable.version] << f.send(attribute)
+    end
+    return unless f.devel
+    map[:devel] ||= {}
+    map[:devel][f.devel.version] ||= []
+    map[:devel][f.devel.version] << f.send(attribute)
+  end
 end
diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb
index 90e0dc2d46..25df57cdc2 100644
--- a/Library/Homebrew/formulary.rb
+++ b/Library/Homebrew/formulary.rb
@@ -186,6 +186,8 @@ class Formulary
           name = new_name
           new_name = @tap.core_tap? ? name : "#{@tap}/#{name}"
         elsif (new_tap_name = @tap.tap_migrations[name])
+          new_tap_user, new_tap_repo, = new_tap_name.split("/")
+          new_tap_name = "#{new_tap_user}/#{new_tap_repo}"
           new_tap = Tap.fetch new_tap_name
           new_tap.install unless new_tap.installed?
           new_tapped_name = "#{new_tap_name}/#{name}"
@@ -333,7 +335,9 @@ class Formulary
       return TapLoader.new(ref, from: from)
     end
 
-    return FromPathLoader.new(ref) if File.extname(ref) == ".rb"
+    if File.extname(ref) == ".rb" && Pathname.new(ref).expand_path.exist?
+      return FromPathLoader.new(ref)
+    end
 
     formula_with_that_name = core_path(ref)
     if formula_with_that_name.file?
@@ -376,6 +380,11 @@ class Formulary
       return TapLoader.new(possible_tap_newname_formulae.first, from: from)
     end
 
+    possible_keg_formula = Pathname.new("#{HOMEBREW_PREFIX}/opt/#{ref}/.brew/#{ref}.rb")
+    if possible_keg_formula.file?
+      return FormulaLoader.new(ref, possible_keg_formula)
+    end
+
     possible_cached_formula = Pathname.new("#{HOMEBREW_CACHE_FORMULA}/#{ref}.rb")
     if possible_cached_formula.file?
       return FormulaLoader.new(ref, possible_cached_formula)
diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb
index eabc4c164c..0311784212 100644
--- a/Library/Homebrew/global.rb
+++ b/Library/Homebrew/global.rb
@@ -26,14 +26,7 @@ RUBY_BIN = RUBY_PATH.dirname
 
 HOMEBREW_USER_AGENT_CURL = ENV["HOMEBREW_USER_AGENT_CURL"]
 HOMEBREW_USER_AGENT_RUBY = "#{ENV["HOMEBREW_USER_AGENT"]} ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}".freeze
-
-HOMEBREW_CURL_ARGS = [
-  "--fail",
-  "--progress-bar",
-  "--remote-time",
-  "--location",
-  "--user-agent", HOMEBREW_USER_AGENT_CURL
-].freeze
+HOMEBREW_USER_AGENT_FAKE_SAFARI = "Mozilla/5.0 (#{ENV["HOMEBREW_SYSTEM"]}; #{ENV["HOMEBREW_PROCESSOR"]} #{ENV["HOMEBREW_OS_VERSION"]}) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12".freeze
 
 require "tap_constants"
 
diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb
index 1de4ce1f0c..8379686158 100644
--- a/Library/Homebrew/keg.rb
+++ b/Library/Homebrew/keg.rb
@@ -87,11 +87,23 @@ class Keg
     mime-info pixmaps sounds postgresql
   ].freeze
 
-  # Will return some kegs, and some dependencies, if they're present.
+  # Given an array of kegs, this method will try to find some other kegs
+  # that depend on them.
+  #
+  # If it does, it returns:
+  # - some kegs in the passed array that have installed dependents
+  # - some installed dependents of those kegs.
+  #
+  # If it doesn't, it returns nil.
+  #
+  # Note that nil will be returned if the only installed dependents
+  # in the passed kegs are other kegs in the array.
+  #
   # For efficiency, we don't bother trying to get complete data.
   def self.find_some_installed_dependents(kegs)
     # First, check in the tabs of installed Formulae.
     kegs.each do |keg|
+      # Don't include dependencies of kegs that were in the given array.
       dependents = keg.installed_dependents - kegs
       dependents.map! { |d| "#{d.name} #{d.version}" }
       return [keg], dependents if dependents.any?
@@ -105,11 +117,27 @@ class Keg
     #
     # This happens after the initial dependency check because it's sloooow.
     remaining_formulae = Formula.installed.select do |f|
-      f.installed_kegs.any? { |k| Tab.for_keg(k).runtime_dependencies.nil? }
+      installed_kegs = f.installed_kegs
+
+      # Don't include dependencies of kegs that were in the given array.
+      next false if (installed_kegs - kegs).empty?
+
+      installed_kegs.any? { |k| Tab.for_keg(k).runtime_dependencies.nil? }
     end
 
     keg_names = kegs.map(&:name)
-    kegs_by_source = kegs.group_by { |k| [k.name, Tab.for_keg(k).tap] }
+    kegs_by_source = kegs.group_by do |keg|
+      begin
+        # First, attempt to resolve the keg to a formula
+        # to get up-to-date name and tap information.
+        f = keg.to_formula
+        [f.name, f.tap]
+      rescue FormulaUnavailableError
+        # If the formula for the keg can't be found,
+        # fall back to the information in the tab.
+        [keg.name, Tab.for_keg(keg).tap]
+      end
+    end
 
     remaining_formulae.each do |dependent|
       required = dependent.missing_dependencies(hide: keg_names)
@@ -119,7 +147,7 @@ class Keg
         next unless f_kegs
 
         f_kegs.sort_by(&:version).last
-      end
+      end.compact
 
       next unless required_kegs.any?
 
@@ -139,10 +167,21 @@ class Keg
     raise NotAKegError, "#{path} is not inside a keg"
   end
 
+  def self.all
+    Formula.racks.flat_map(&:subdirs).map { |d| new(d) }
+  end
+
   attr_reader :path, :name, :linked_keg_record, :opt_record
   protected :path
 
+  extend Forwardable
+
+  def_delegators :path,
+    :to_s, :hash, :abv, :disk_usage, :file_count, :directory?, :exist?, :/,
+    :join, :rename, :find
+
   def initialize(path)
+    path = path.resolved_path if path.to_s.start_with?("#{HOMEBREW_PREFIX}/opt/")
     raise "#{path} is not a valid keg" unless path.parent.parent.realpath == HOMEBREW_CELLAR.realpath
     raise "#{path} is not a directory" unless path.directory?
     @path = path
@@ -151,19 +190,11 @@ class Keg
     @opt_record = HOMEBREW_PREFIX/"opt/#{name}"
   end
 
-  def to_s
-    path.to_s
-  end
-
   def rack
     path.parent
   end
 
-  if Pathname.method_defined?(:to_path)
-    alias to_path to_s
-  else
-    alias to_str to_s
-  end
+  alias to_path to_s
 
   def inspect
     "#<#{self.class.name}:#{path}>"
@@ -174,30 +205,6 @@ class Keg
   end
   alias eql? ==
 
-  def hash
-    path.hash
-  end
-
-  def abv
-    path.abv
-  end
-
-  def disk_usage
-    path.disk_usage
-  end
-
-  def file_count
-    path.file_count
-  end
-
-  def directory?
-    path.directory?
-  end
-
-  def exist?
-    path.exist?
-  end
-
   def empty_installation?
     Pathname.glob("#{path}/**/*") do |file|
       next if file.directory?
@@ -210,18 +217,6 @@ class Keg
     true
   end
 
-  def /(other)
-    path / other
-  end
-
-  def join(*args)
-    path.join(*args)
-  end
-
-  def rename(*args)
-    path.rename(*args)
-  end
-
   def linked?
     linked_keg_record.symlink? &&
       linked_keg_record.directory? &&
@@ -334,10 +329,6 @@ class Keg
     Pathname.glob("#{app_prefix}/{,libexec/}*.app")
   end
 
-  def app_installed?
-    !apps.empty?
-  end
-
   def elisp_installed?
     return false unless (path/"share/emacs/site-lisp"/name).exist?
     (path/"share/emacs/site-lisp"/name).children.any? { |f| %w[.el .elc].include? f.extname }
@@ -353,22 +344,24 @@ class Keg
   end
 
   def installed_dependents
-    Formula.installed.flat_map(&:installed_kegs).select do |keg|
+    return [] unless optlinked?
+    tap = Tab.for_keg(self).source["tap"]
+    Keg.all.select do |keg|
       tab = Tab.for_keg(keg)
-      next if tab.runtime_dependencies.nil? # no dependency information saved.
+      next if tab.runtime_dependencies.nil?
       tab.runtime_dependencies.any? do |dep|
         # Resolve formula rather than directly comparing names
         # in case of conflicts between formulae from different taps.
-        dep_formula = Formulary.factory(dep["full_name"])
-        dep_formula == to_formula && dep["version"] == version.to_s
+        begin
+          dep_formula = Formulary.factory(dep["full_name"])
+          dep_formula == to_formula
+        rescue FormulaUnavailableError
+          next "#{tap}/#{name}" == dep["full_name"]
+        end
       end
     end
   end
 
-  def find(*args, &block)
-    path.find(*args, &block)
-  end
-
   def oldname_opt_record
     @oldname_opt_record ||= if (opt_dir = HOMEBREW_PREFIX/"opt").directory?
       opt_dir.subdirs.detect do |dir|
@@ -559,7 +552,7 @@ class Keg
 
       if src.symlink? || src.file?
         Find.prune if File.basename(src) == ".DS_Store"
-        Find.prune if src.realpath == dst
+        Find.prune if src.resolved_path == dst
         # Don't link pyc or pyo files because Python overwrites these
         # cached object files and next time brew wants to link, the
         # file is in the way.
diff --git a/Library/Homebrew/manpages/brew-cask.1.md b/Library/Homebrew/manpages/brew-cask.1.md
index feab9f76e6..a2c9c8c165 100644
--- a/Library/Homebrew/manpages/brew-cask.1.md
+++ b/Library/Homebrew/manpages/brew-cask.1.md
@@ -104,9 +104,6 @@ names, and other aspects of this manual are still subject to change.
     Uninstall the given Cask. With `--force`, uninstall even if the Cask
     does not appear to be present.
 
-  * `update`:
-    For convenience. `brew cask update` is a synonym for `brew update`.
-
   * `zap`  [  ... ]:
     Unconditionally remove _all_ files associated with the given Cask.
 
@@ -123,6 +120,13 @@ names, and other aspects of this manual are still subject to change.
 
     **`zap` may remove files which are shared between applications.**
 
+## INTERNAL COMMANDS
+
+  * `_appcast_checkpoint` [--calculate] [  ... |  ... ]:
+    Given a `token`, returns the current appcast checkpoint, or calculates
+    the appcast checkpoint if the `--calculate` flag is specified.  
+    Given a `URL`, calculates the appcast checkpoint for it.
+
 ## OPTIONS
 
 To make these options persistent, see the ENVIRONMENT section, below.
diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb
index 7412d0a69d..a7f099e9da 100644
--- a/Library/Homebrew/manpages/brew.1.md.erb
+++ b/Library/Homebrew/manpages/brew.1.md.erb
@@ -31,7 +31,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
   * `install` :
     Install .
 
-  * `remove` :
+  * `uninstall` :
     Uninstall .
 
   * `update`:
@@ -76,7 +76,7 @@ scripts that reside somewhere in the `PATH`, named `brew-` or
 to create your own commands without modifying Homebrew's internals.
 
 Instructions for creating your own commands can be found in the docs:
-
+
 
 ## SPECIFYING FORMULAE
 
@@ -197,7 +197,7 @@ can take several different forms:
     *Default:* the number of available CPU cores.
 
   * `HOMEBREW_NO_ANALYTICS`:
-    If set, Homebrew will not send analytics. See: 
+    If set, Homebrew will not send analytics. See: 
 
   * `HOMEBREW_NO_AUTO_UPDATE`:
     If set, Homebrew will not auto-update before running `brew install`,
diff --git a/Library/Homebrew/official_taps.rb b/Library/Homebrew/official_taps.rb
index a220c92396..f2afea6140 100644
--- a/Library/Homebrew/official_taps.rb
+++ b/Library/Homebrew/official_taps.rb
@@ -1,18 +1,15 @@
 OFFICIAL_TAPS = %w[
   apache
   completions
-  devel-only
   dupes
   emacs
   fuse
   games
-  gui
   nginx
   php
   python
   science
   tex
-  versions
   x11
 ].freeze
 
diff --git a/Library/Homebrew/os.rb b/Library/Homebrew/os.rb
index f6fe1eb811..dae8434070 100644
--- a/Library/Homebrew/os.rb
+++ b/Library/Homebrew/os.rb
@@ -15,7 +15,7 @@ module OS
     require "os/mac"
     # Don't tell people to report issues on unsupported versions of macOS.
     if !OS::Mac.prerelease? && !OS::Mac.outdated_release?
-      ISSUES_URL = "https://git.io/brew-troubleshooting".freeze
+      ISSUES_URL = "http://docs.brew.sh/Troubleshooting.html".freeze
     end
     PATH_OPEN = "/usr/bin/open".freeze
     # compatibility
diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb
index b2f0515a0a..9468a6c1e7 100644
--- a/Library/Homebrew/os/mac.rb
+++ b/Library/Homebrew/os/mac.rb
@@ -152,13 +152,13 @@ module OS
     end
 
     STANDARD_COMPILERS = {
-      "2.0"   => { gcc_40_build: 4061 },
-      "2.5"   => { gcc_40_build: 5370 },
-      "3.1.4" => { gcc_40_build: 5493, gcc_42_build: 5577 },
-      "3.2.6" => { gcc_40_build: 5494, gcc_42_build: 5666, clang: "1.7", clang_build: 77 },
-      "4.0"   => { gcc_40_build: 5494, gcc_42_build: 5666, clang: "2.0", clang_build: 137 },
-      "4.0.1" => { gcc_40_build: 5494, gcc_42_build: 5666, clang: "2.0", clang_build: 137 },
-      "4.0.2" => { gcc_40_build: 5494, gcc_42_build: 5666, clang: "2.0", clang_build: 137 },
+      "2.0"   => { gcc_4_0_build: 4061 },
+      "2.5"   => { gcc_4_0_build: 5370 },
+      "3.1.4" => { gcc_4_0_build: 5493, gcc_4_2_build: 5577 },
+      "3.2.6" => { gcc_4_0_build: 5494, gcc_4_2_build: 5666, clang: "1.7", clang_build: 77 },
+      "4.0"   => { gcc_4_0_build: 5494, gcc_4_2_build: 5666, clang: "2.0", clang_build: 137 },
+      "4.0.1" => { gcc_4_0_build: 5494, gcc_4_2_build: 5666, clang: "2.0", clang_build: 137 },
+      "4.0.2" => { gcc_4_0_build: 5494, gcc_4_2_build: 5666, clang: "2.0", clang_build: 137 },
       "4.2"   => { clang: "3.0", clang_build: 211 },
       "4.3"   => { clang: "3.1", clang_build: 318 },
       "4.3.1" => { clang: "3.1", clang_build: 318 },
diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb
index 8e51fc6b6d..aa4504a179 100644
--- a/Library/Homebrew/os/mac/xcode.rb
+++ b/Library/Homebrew/os/mac/xcode.rb
@@ -3,8 +3,9 @@ module OS
     module Xcode
       module_function
 
-      V4_BUNDLE_ID = "com.apple.dt.Xcode".freeze
-      V3_BUNDLE_ID = "com.apple.Xcode".freeze
+      DEFAULT_BUNDLE_PATH = Pathname.new("/Applications/Xcode.app").freeze
+      BUNDLE_ID = "com.apple.dt.Xcode".freeze
+      OLD_BUNDLE_ID = "com.apple.Xcode".freeze
 
       def latest_version
         case MacOS.version
@@ -51,9 +52,9 @@ module OS
           begin
             dir = MacOS.active_developer_dir
 
-            if dir.empty? || dir == CLT::MAVERICKS_PKG_PATH || !File.directory?(dir)
+            if dir.empty? || dir == CLT::PKG_PATH || !File.directory?(dir)
               path = bundle_path
-              path.join("Contents", "Developer") if path
+              path/"Contents/Developer" if path
             else
               # Use cleanpath to avoid pathological trailing slash
               Pathname.new(dir).cleanpath
@@ -67,11 +68,14 @@ module OS
         Pathname.new("#{prefix}/Toolchains/XcodeDefault.xctoolchain")
       end
 
-      # Ask Spotlight where Xcode is. If the user didn't install the
-      # helper tools and installed Xcode in a non-conventional place, this
-      # is our only option. See: https://superuser.com/questions/390757
       def bundle_path
-        MacOS.app_with_bundle_id(V4_BUNDLE_ID, V3_BUNDLE_ID)
+        # Use the default location if it exists.
+        return DEFAULT_BUNDLE_PATH if DEFAULT_BUNDLE_PATH.exist?
+
+        # Ask Spotlight where Xcode is. If the user didn't install the
+        # helper tools and installed Xcode in a non-conventional place, this
+        # is our only option. See: https://superuser.com/questions/390757
+        MacOS.app_with_bundle_id(BUNDLE_ID, OLD_BUNDLE_ID)
       end
 
       def installed?
@@ -182,7 +186,7 @@ module OS
       FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI".freeze
       MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables".freeze
       MAVERICKS_NEW_PKG_ID = "com.apple.pkg.CLTools_Base".freeze # obsolete
-      MAVERICKS_PKG_PATH = "/Library/Developer/CommandLineTools".freeze
+      PKG_PATH = "/Library/Developer/CommandLineTools".freeze
 
       # Returns true even if outdated tools are installed, e.g.
       # tools from Xcode 4.x on 10.9
@@ -222,7 +226,7 @@ module OS
       def minimum_version
         case MacOS.version
         when "10.12" then "8.0.0"
-        else "4.0.0"
+        else "1.0.0"
         end
       end
 
@@ -237,7 +241,7 @@ module OS
         return false if MacOS.version < :lion
 
         if MacOS.version >= :mavericks
-          version = Utils.popen_read("#{MAVERICKS_PKG_PATH}/usr/bin/clang --version")
+          version = Utils.popen_read("#{PKG_PATH}/usr/bin/clang --version")
         else
           version = Utils.popen_read("/usr/bin/clang --version")
         end
@@ -261,7 +265,7 @@ module OS
 
         [MAVERICKS_PKG_ID, MAVERICKS_NEW_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID].find do |id|
           if MacOS.version >= :mavericks
-            next unless File.exist?("#{MAVERICKS_PKG_PATH}/usr/bin/clang")
+            next unless File.exist?("#{PKG_PATH}/usr/bin/clang")
           end
           version = MacOS.pkgutil_info(id)[/version: (.+)$/, 1]
           return version if version
diff --git a/Library/Homebrew/os/mac/xquartz.rb b/Library/Homebrew/os/mac/xquartz.rb
index 674e50c503..b82772faf7 100644
--- a/Library/Homebrew/os/mac/xquartz.rb
+++ b/Library/Homebrew/os/mac/xquartz.rb
@@ -5,6 +5,8 @@ module OS
     module XQuartz
       module_function
 
+      # TODO: confirm this path when you have internet
+      DEFAULT_BUNDLE_PATH = Pathname.new("Applications/Utilities/XQuartz.app").freeze
       FORGE_BUNDLE_ID = "org.macosforge.xquartz.X11".freeze
       APPLE_BUNDLE_ID = "org.x.X11".freeze
       FORGE_PKG_ID = "org.macosforge.xquartz.pkg".freeze
@@ -56,6 +58,11 @@ module OS
       end
 
       def bundle_path
+        # Use the default location if it exists.
+        return DEFAULT_BUNDLE_PATH if DEFAULT_BUNDLE_PATH.exist?
+
+        # Ask Spotlight where XQuartz is. If the user didn't install XQuartz
+        # in the conventional place, this is our only option.
         MacOS.app_with_bundle_id(FORGE_BUNDLE_ID, APPLE_BUNDLE_ID)
       end
 
diff --git a/Library/Homebrew/requirement.rb b/Library/Homebrew/requirement.rb
index fe1a3c020f..49108ca75a 100644
--- a/Library/Homebrew/requirement.rb
+++ b/Library/Homebrew/requirement.rb
@@ -15,6 +15,7 @@ class Requirement
     @default_formula = self.class.default_formula
     @cask ||= self.class.cask
     @download ||= self.class.download
+    @formula = nil
     tags.each do |tag|
       next unless tag.is_a? Hash
       @cask ||= tag[:cask]
@@ -56,7 +57,14 @@ class Requirement
   def satisfied?
     result = self.class.satisfy.yielder { |p| instance_eval(&p) }
     @satisfied_result = result
-    result ? true : false
+    return false unless result
+
+    if parent = satisfied_result_parent
+      parent.to_s =~ %r{(#{Regexp.escape(HOMEBREW_CELLAR)}|#{Regexp.escape(HOMEBREW_PREFIX)}/opt)/([\w+-.@]+)}
+      @formula = $2
+    end
+
+    true
   end
 
   # Overriding #fatal? is deprecated.
@@ -69,6 +77,11 @@ class Requirement
     self.class.default_formula || false
   end
 
+  def satisfied_result_parent
+    return unless @satisfied_result.is_a?(Pathname)
+    @satisfied_result.resolved_path.parent
+  end
+
   # Overriding #modify_build_environment is deprecated.
   # Pass a block to the env DSL method instead.
   # Note: #satisfied? should be called before invoking this method
@@ -81,11 +94,8 @@ class Requirement
     #   satisfy { which("executable") }
     # work, even under superenv where "executable" wouldn't normally be on the
     # PATH.
-    # This is undocumented magic and it should be removed, but we need to add
-    # a way to declare path-based requirements that work with superenv first.
-    return unless @satisfied_result.is_a?(Pathname)
-    parent = @satisfied_result.parent
-
+    parent = satisfied_result_parent
+    return unless parent
     return if ENV["PATH"].split(File::PATH_SEPARATOR).include?(parent.to_s)
     ENV.append_path("PATH", parent)
   end
@@ -111,13 +121,15 @@ class Requirement
     "#<#{self.class.name}: #{name.inspect} #{tags.inspect}>"
   end
 
+  def formula
+    @formula || self.class.default_formula
+  end
+
   def to_dependency
-    f = self.class.default_formula
-    raise "No default formula defined for #{inspect}" if f.nil?
-    if f =~ HOMEBREW_TAP_FORMULA_REGEX
-      TapDependency.new(f, tags, method(:modify_build_environment), name)
-    else
-      Dependency.new(f, tags, method(:modify_build_environment), name)
+    if formula =~ HOMEBREW_TAP_FORMULA_REGEX
+      TapDependency.new(formula, tags, method(:modify_build_environment), name)
+    elsif formula
+      Dependency.new(formula, tags, method(:modify_build_environment), name)
     end
   end
 
diff --git a/Library/Homebrew/requirements/perl_requirement.rb b/Library/Homebrew/requirements/perl_requirement.rb
index 06e36ac0d6..70eb2a36c5 100644
--- a/Library/Homebrew/requirements/perl_requirement.rb
+++ b/Library/Homebrew/requirements/perl_requirement.rb
@@ -10,7 +10,7 @@ class PerlRequirement < Requirement
 
   satisfy(build_env: false) do
     which_all("perl").detect do |perl|
-      perl_version = Utils.popen_read(perl, "--version")[/\(v(\d+\.\d+)(?:\.\d+)?\)/, 1]
+      perl_version = Utils.popen_read(perl, "--version")[/v(\d+\.\d+)(?:\.\d+)?/, 1]
       next unless perl_version
       Version.create(perl_version.to_s) >= Version.create(@version)
     end
diff --git a/Library/Homebrew/system_config.rb b/Library/Homebrew/system_config.rb
index 9c7a8d1b01..043f609193 100644
--- a/Library/Homebrew/system_config.rb
+++ b/Library/Homebrew/system_config.rb
@@ -6,12 +6,12 @@ require "development_tools"
 
 class SystemConfig
   class << self
-    def gcc_42
-      @gcc_42 ||= DevelopmentTools.gcc_42_build_version if DevelopmentTools.installed?
+    def gcc_4_2
+      @gcc_4_2 ||= DevelopmentTools.gcc_4_2_build_version if DevelopmentTools.installed?
     end
 
-    def gcc_40
-      @gcc_40 ||= DevelopmentTools.gcc_40_build_version if DevelopmentTools.installed?
+    def gcc_4_0
+      @gcc_4_0 ||= DevelopmentTools.gcc_4_0_build_version if DevelopmentTools.installed?
     end
 
     def clang
@@ -143,8 +143,8 @@ class SystemConfig
       f.puts "HOMEBREW_BOTTLE_DOMAIN: #{BottleSpecification::DEFAULT_DOMAIN}"
       f.puts hardware if hardware
       f.puts "Homebrew Ruby: #{describe_homebrew_ruby}"
-      f.puts "GCC-4.0: build #{gcc_40}" unless gcc_40.null?
-      f.puts "GCC-4.2: build #{gcc_42}" unless gcc_42.null?
+      f.puts "GCC-4.0: build #{gcc_4_0}" unless gcc_4_0.null?
+      f.puts "GCC-4.2: build #{gcc_4_2}" unless gcc_4_2.null?
       f.puts "Clang: #{clang.null? ? "N/A" : "#{clang} build #{clang_build}"}"
       f.puts "Git: #{describe_git}"
       f.puts "Perl: #{describe_perl}"
diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb
index 40626bad1e..fd59539dfd 100644
--- a/Library/Homebrew/tab.rb
+++ b/Library/Homebrew/tab.rb
@@ -25,6 +25,8 @@ class Tab < OpenStruct
       "unused_options" => build.unused_options.as_flags,
       "tabfile" => formula.prefix.join(FILENAME),
       "built_as_bottle" => build.bottle?,
+      "installed_as_dependency" => false,
+      "installed_on_request" => true,
       "poured_from_bottle" => false,
       "time" => Time.now.to_i,
       "source_modified_time" => formula.source_modified_time.to_i,
@@ -168,9 +170,12 @@ class Tab < OpenStruct
 
   def self.empty
     attributes = {
+      "homebrew_version" => HOMEBREW_VERSION,
       "used_options" => [],
       "unused_options" => [],
       "built_as_bottle" => false,
+      "installed_as_dependency" => false,
+      "installed_on_request" => true,
       "poured_from_bottle" => false,
       "time" => nil,
       "source_modified_time" => 0,
@@ -242,6 +247,17 @@ class Tab < OpenStruct
     super || DevelopmentTools.default_compiler
   end
 
+  def parsed_homebrew_version
+    return Version::NULL if homebrew_version.nil?
+    Version.new(homebrew_version)
+  end
+
+  def runtime_dependencies
+    # Homebrew versions prior to 1.1.6 generated incorrect runtime dependency
+    # lists.
+    super unless parsed_homebrew_version < "1.1.6"
+  end
+
   def cxxstdlib
     # Older tabs won't have these values, so provide sensible defaults
     lib = stdlib.to_sym if stdlib
@@ -301,6 +317,8 @@ class Tab < OpenStruct
       "unused_options" => unused_options.as_flags,
       "built_as_bottle" => built_as_bottle,
       "poured_from_bottle" => poured_from_bottle,
+      "installed_as_dependency" => installed_as_dependency,
+      "installed_on_request" => installed_on_request,
       "changed_files" => changed_files && changed_files.map(&:to_s),
       "time" => time,
       "source_modified_time" => source_modified_time.to_i,
diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb
index 68b21ac604..4b59f23446 100644
--- a/Library/Homebrew/tap.rb
+++ b/Library/Homebrew/tap.rb
@@ -292,7 +292,11 @@ class Tap
 
   # path to the directory of all {Formula} files for this {Tap}.
   def formula_dir
-    @formula_dir ||= [path/"Formula", path/"HomebrewFormula", path].detect(&:directory?)
+    @formula_dir ||= potential_formula_dirs.detect(&:directory?)
+  end
+
+  def potential_formula_dirs
+    @potential_formula_dirs ||= [path/"Formula", path/"HomebrewFormula", path].freeze
   end
 
   # path to the directory of all {Cask} files for this {Tap}.
diff --git a/Library/Homebrew/test/ARGV_test.rb b/Library/Homebrew/test/ARGV_test.rb
index 6805e0c620..e93d09c394 100644
--- a/Library/Homebrew/test/ARGV_test.rb
+++ b/Library/Homebrew/test/ARGV_test.rb
@@ -3,6 +3,7 @@ require "extend/ARGV"
 
 class ArgvExtensionTests < Homebrew::TestCase
   def setup
+    super
     @argv = [].extend(HomebrewArgvExtension)
   end
 
@@ -21,8 +22,6 @@ class ArgvExtensionTests < Homebrew::TestCase
     keg.mkpath
     @argv << "mxcl"
     assert_equal 1, @argv.kegs.length
-  ensure
-    keg.parent.rmtree
   end
 
   def test_argv_named
diff --git a/Library/Homebrew/test/ENV_test.rb b/Library/Homebrew/test/ENV_test.rb
index 6c0e68a9e3..cbfd01e251 100644
--- a/Library/Homebrew/test/ENV_test.rb
+++ b/Library/Homebrew/test/ENV_test.rb
@@ -31,6 +31,7 @@ end
 
 module SharedEnvTests
   def setup
+    super
     @env = {}.extend(EnvActivation)
   end
 
@@ -133,7 +134,7 @@ module SharedEnvTests
   end
 
   def test_switching_compilers_updates_compiler
-    [:clang, :gcc, :gcc_4_0].each do |compiler|
+    [:clang, :gcc_4_2, :gcc_4_0].each do |compiler|
       @env.send(compiler)
       assert_equal compiler, @env.compiler
     end
diff --git a/Library/Homebrew/test/audit_test.rb b/Library/Homebrew/test/audit_test.rb
index 2725f906e3..60cf276106 100644
--- a/Library/Homebrew/test/audit_test.rb
+++ b/Library/Homebrew/test/audit_test.rb
@@ -6,13 +6,10 @@ require "dev-cmd/audit"
 
 class FormulaTextTests < Homebrew::TestCase
   def setup
+    super
     @dir = mktmpdir
   end
 
-  def teardown
-    FileUtils.rm_rf @dir
-  end
-
   def formula_text(name, body = nil, options = {})
     path = Pathname.new "#{@dir}/#{name}.rb"
     path.open("w") do |f|
@@ -58,13 +55,10 @@ end
 
 class FormulaAuditorTests < Homebrew::TestCase
   def setup
+    super
     @dir = mktmpdir
   end
 
-  def teardown
-    FileUtils.rm_rf @dir
-  end
-
   def formula_auditor(name, text, options = {})
     path = Pathname.new "#{@dir}/#{name}.rb"
     path.open("w") do |f|
@@ -249,7 +243,7 @@ class FormulaAuditorTests < Homebrew::TestCase
     needs_compat
     require "compat/formula_specialties"
 
-    ARGV.stubs(:homebrew_developer?).returns false
+    ENV.delete("HOMEBREW_DEVELOPER")
     fa = shutup do
       formula_auditor "foo", <<-EOS.undent
         class Foo < GithubGistFormula
@@ -266,7 +260,7 @@ class FormulaAuditorTests < Homebrew::TestCase
     needs_compat
     require "compat/formula_specialties"
 
-    ARGV.stubs(:homebrew_developer?).returns false
+    ENV.delete("HOMEBREW_DEVELOPER")
     fa = formula_auditor "foo", <<-EOS.undent
       class Foo < ScriptFileFormula
         url "http://example.com/foo-1.0.tgz"
@@ -281,7 +275,7 @@ class FormulaAuditorTests < Homebrew::TestCase
     needs_compat
     require "compat/formula_specialties"
 
-    ARGV.stubs(:homebrew_developer?).returns false
+    ENV.delete("HOMEBREW_DEVELOPER")
     fa = formula_auditor "foo", <<-EOS.undent
       class Foo < AmazonWebServicesFormula
         url "http://example.com/foo-1.0.tgz"
@@ -367,13 +361,10 @@ class FormulaAuditorTests < Homebrew::TestCase
       end
     EOS
 
-    original_value = ENV["HOMEBREW_NO_GITHUB_API"]
     ENV["HOMEBREW_NO_GITHUB_API"] = "1"
 
     fa.audit_github_repository
     assert_equal [], fa.problems
-  ensure
-    ENV["HOMEBREW_NO_GITHUB_API"] = original_value
   end
 
   def test_audit_caveats
@@ -429,8 +420,8 @@ class FormulaAuditorTests < Homebrew::TestCase
 
     fa.audit_homepage
     assert_equal ["The homepage should start with http or https " \
-      "(URL is #{fa.formula.homepage}).", "The homepage is not reachable " \
-      "(curl exit code #{$?.exitstatus})"], fa.problems
+      "(URL is #{fa.formula.homepage}).", "The homepage #{fa.formula.homepage} is not reachable " \
+      "(HTTP status code 000)"], fa.problems
 
     formula_homepages = {
       "bar" => "http://www.freedesktop.org/wiki/bar",
diff --git a/Library/Homebrew/test/bottle_collector_test.rb b/Library/Homebrew/test/bottle_collector_test.rb
index d75e29ec86..5879da92c0 100644
--- a/Library/Homebrew/test/bottle_collector_test.rb
+++ b/Library/Homebrew/test/bottle_collector_test.rb
@@ -3,6 +3,7 @@ require "utils/bottles"
 
 class BottleCollectorTests < Homebrew::TestCase
   def setup
+    super
     @collector = Utils::Bottles::Collector.new
   end
 
diff --git a/Library/Homebrew/test/bottle_hooks_test.rb b/Library/Homebrew/test/bottle_hooks_test.rb
index 3535d80efd..fd890192fb 100644
--- a/Library/Homebrew/test/bottle_hooks_test.rb
+++ b/Library/Homebrew/test/bottle_hooks_test.rb
@@ -17,6 +17,7 @@ class BottleHookTests < Homebrew::TestCase
   end
 
   def setup
+    super
     @fi = FormulaInstaller.new FormulaDouble.new
   end
 
@@ -43,5 +44,6 @@ class BottleHookTests < Homebrew::TestCase
 
   def teardown
     Homebrew::Hooks::Bottles.reset_hooks
+    super
   end
 end
diff --git a/Library/Homebrew/test/build_environment_test.rb b/Library/Homebrew/test/build_environment_test.rb
index 73a1c95f73..54b9cb2b17 100644
--- a/Library/Homebrew/test/build_environment_test.rb
+++ b/Library/Homebrew/test/build_environment_test.rb
@@ -3,6 +3,7 @@ require "build_environment"
 
 class BuildEnvironmentTests < Homebrew::TestCase
   def setup
+    super
     @env = BuildEnvironment.new
   end
 
diff --git a/Library/Homebrew/test/build_options_test.rb b/Library/Homebrew/test/build_options_test.rb
index e460d25ccb..05e7ccd947 100644
--- a/Library/Homebrew/test/build_options_test.rb
+++ b/Library/Homebrew/test/build_options_test.rb
@@ -4,6 +4,7 @@ require "options"
 
 class BuildOptionsTests < Homebrew::TestCase
   def setup
+    super
     args = Options.create(%w[--with-foo --with-bar --without-qux])
     opts = Options.create(%w[--with-foo --with-bar --without-baz --without-qux])
     @build = BuildOptions.new(args, opts)
diff --git a/Library/Homebrew/test/caveats_test.rb b/Library/Homebrew/test/caveats_test.rb
index 9eaac57927..3a582b907f 100644
--- a/Library/Homebrew/test/caveats_test.rb
+++ b/Library/Homebrew/test/caveats_test.rb
@@ -4,6 +4,7 @@ require "caveats"
 
 class CaveatsTests < Homebrew::TestCase
   def setup
+    super
     @f = formula { url "foo-1.0" }
     @c = Caveats.new @f
   end
diff --git a/Library/Homebrew/test/checksum_verification_test.rb b/Library/Homebrew/test/checksum_verification_test.rb
index 9017b528d0..4c674edd29 100644
--- a/Library/Homebrew/test/checksum_verification_test.rb
+++ b/Library/Homebrew/test/checksum_verification_test.rb
@@ -17,10 +17,6 @@ class ChecksumVerificationTests < Homebrew::TestCase
     end
   end
 
-  def teardown
-    @_f.clear_cache
-  end
-
   def test_good_sha256
     formula do
       sha256 TESTBALL_SHA256
diff --git a/Library/Homebrew/test/cleaner_test.rb b/Library/Homebrew/test/cleaner_test.rb
index ac108421c8..05a91b90b4 100644
--- a/Library/Homebrew/test/cleaner_test.rb
+++ b/Library/Homebrew/test/cleaner_test.rb
@@ -6,14 +6,11 @@ class CleanerTests < Homebrew::TestCase
   include FileUtils
 
   def setup
+    super
     @f = formula("cleaner_test") { url "foo-1.0" }
     @f.prefix.mkpath
   end
 
-  def teardown
-    @f.rack.rmtree if @f.rack.exist?
-  end
-
   def test_clean_file
     @f.bin.mkpath
     @f.lib.mkpath
diff --git a/Library/Homebrew/test/cleanup_test.rb b/Library/Homebrew/test/cleanup_test.rb
index bb8e1cdc61..8a292933aa 100644
--- a/Library/Homebrew/test/cleanup_test.rb
+++ b/Library/Homebrew/test/cleanup_test.rb
@@ -14,14 +14,14 @@ end
 
 class CleanupTests < Homebrew::TestCase
   def setup
+    super
     @ds_store = Pathname.new "#{HOMEBREW_PREFIX}/Library/.DS_Store"
     FileUtils.touch @ds_store
   end
 
   def teardown
     FileUtils.rm_f @ds_store
-    ARGV.delete "--dry-run"
-    ARGV.delete "--prune=all"
+    super
   end
 
   def test_cleanup
@@ -55,9 +55,6 @@ class CleanupTests < Homebrew::TestCase
     refute_predicate f1, :installed?
     refute_predicate f2, :installed?
     assert_predicate f3, :installed?
-  ensure
-    [f1, f2, f3].each(&:clear_cache)
-    f3.rack.rmtree
   end
 
   def test_cleanup_logs
diff --git a/Library/Homebrew/test/commands_test.rb b/Library/Homebrew/test/commands_test.rb
index d44d2da0e7..5f5dc95865 100644
--- a/Library/Homebrew/test/commands_test.rb
+++ b/Library/Homebrew/test/commands_test.rb
@@ -13,6 +13,7 @@ end
 
 class CommandsTests < Homebrew::TestCase
   def setup
+    super
     @cmds = [
       # internal commands
       HOMEBREW_LIBRARY_PATH/"cmd/rbcmd.rb",
@@ -28,6 +29,7 @@ class CommandsTests < Homebrew::TestCase
 
   def teardown
     @cmds.each(&:unlink)
+    super
   end
 
   def test_internal_commands
@@ -45,8 +47,6 @@ class CommandsTests < Homebrew::TestCase
   end
 
   def test_external_commands
-    env = ENV.to_hash
-
     mktmpdir do |dir|
       %w[brew-t1 brew-t2.rb brew-t3.py].each do |file|
         path = "#{dir}/#{file}"
@@ -65,8 +65,6 @@ class CommandsTests < Homebrew::TestCase
         "Executable files with a non Ruby extension shoudn't be included"
       refute cmds.include?("t4"), "Non-executable files shouldn't be included"
     end
-  ensure
-    ENV.replace(env)
   end
 
   def test_internal_command_path
diff --git a/Library/Homebrew/test/compiler_selector_test.rb b/Library/Homebrew/test/compiler_selector_test.rb
index b1591bdbec..aa1a6f97ec 100644
--- a/Library/Homebrew/test/compiler_selector_test.rb
+++ b/Library/Homebrew/test/compiler_selector_test.rb
@@ -31,6 +31,7 @@ class CompilerSelectorTests < Homebrew::TestCase
   end
 
   def setup
+    super
     @f  = Double.new
     @cc = :clang
     @versions = CompilerVersions.new
diff --git a/Library/Homebrew/test/dependencies_test.rb b/Library/Homebrew/test/dependencies_test.rb
index db3b782265..c5444fcbcc 100644
--- a/Library/Homebrew/test/dependencies_test.rb
+++ b/Library/Homebrew/test/dependencies_test.rb
@@ -5,6 +5,7 @@ require "requirements"
 
 class DependenciesTests < Homebrew::TestCase
   def setup
+    super
     @deps = Dependencies.new
   end
 
@@ -89,6 +90,7 @@ end
 
 class RequirementsTests < Homebrew::TestCase
   def setup
+    super
     @reqs = Requirements.new
   end
 
diff --git a/Library/Homebrew/test/dependency_collector_test.rb b/Library/Homebrew/test/dependency_collector_test.rb
index 1c7f70118b..c63d046370 100644
--- a/Library/Homebrew/test/dependency_collector_test.rb
+++ b/Library/Homebrew/test/dependency_collector_test.rb
@@ -11,11 +11,13 @@ class DependencyCollectorTests < Homebrew::TestCase
   end
 
   def setup
+    super
     @d = DependencyCollector.new
   end
 
   def teardown
     DependencyCollector.clear_cache
+    super
   end
 
   def test_dependency_creation
diff --git a/Library/Homebrew/test/dependency_expansion_test.rb b/Library/Homebrew/test/dependency_expansion_test.rb
index 9d6de35e2f..de743ce035 100644
--- a/Library/Homebrew/test/dependency_expansion_test.rb
+++ b/Library/Homebrew/test/dependency_expansion_test.rb
@@ -9,6 +9,7 @@ class DependencyExpansionTests < Homebrew::TestCase
   end
 
   def setup
+    super
     @foo = build_dep(:foo)
     @bar = build_dep(:bar)
     @baz = build_dep(:baz)
diff --git a/Library/Homebrew/test/dependency_test.rb b/Library/Homebrew/test/dependency_test.rb
index 65255995ec..404f26d79c 100644
--- a/Library/Homebrew/test/dependency_test.rb
+++ b/Library/Homebrew/test/dependency_test.rb
@@ -3,6 +3,7 @@ require "dependency"
 
 class DependableTests < Homebrew::TestCase
   def setup
+    super
     @tags = ["foo", "bar", :build]
     @dep = Struct.new(:tags).new(@tags).extend(Dependable)
   end
@@ -118,6 +119,11 @@ class DependencyTests < Homebrew::TestCase
 end
 
 class TapDependencyTests < Homebrew::TestCase
+  def test_tap
+    dep = TapDependency.new("foo/bar/dog")
+    assert_equal Tap.new("foo", "bar"), dep.tap
+  end
+
   def test_option_names
     dep = TapDependency.new("foo/bar/dog")
     assert_equal %w[dog], dep.option_names
diff --git a/Library/Homebrew/test/descriptions_test.rb b/Library/Homebrew/test/descriptions_test.rb
index de38fdbd13..baeeb7b192 100644
--- a/Library/Homebrew/test/descriptions_test.rb
+++ b/Library/Homebrew/test/descriptions_test.rb
@@ -3,6 +3,8 @@ require "descriptions"
 
 class DescriptionsTest < Homebrew::TestCase
   def setup
+    super
+
     @descriptions_hash = {}
     @descriptions = Descriptions.new(@descriptions_hash)
 
@@ -12,6 +14,7 @@ class DescriptionsTest < Homebrew::TestCase
 
   def teardown
     $stdout = @old_stdout
+    super
   end
 
   def test_single_core_formula
diff --git a/Library/Homebrew/test/diagnostic_test.rb b/Library/Homebrew/test/diagnostic_test.rb
index c9bb524b0d..7a1fb25f79 100644
--- a/Library/Homebrew/test/diagnostic_test.rb
+++ b/Library/Homebrew/test/diagnostic_test.rb
@@ -5,14 +5,10 @@ require "diagnostic"
 
 class DiagnosticChecksTest < Homebrew::TestCase
   def setup
-    @env = ENV.to_hash
+    super
     @checks = Homebrew::Diagnostic::Checks.new
   end
 
-  def teardown
-    ENV.replace(@env)
-  end
-
   def test_inject_file_list
     assert_equal "foo:\n",
       @checks.inject_file_list([], "foo:\n")
@@ -103,8 +99,6 @@ class DiagnosticChecksTest < Homebrew::TestCase
 
     assert_match "/usr/bin occurs before #{HOMEBREW_PREFIX}/bin",
       @checks.check_user_path_1
-  ensure
-    bin.rmtree
   end
 
   def test_check_user_path_bin
diff --git a/Library/Homebrew/test/download_strategies_test.rb b/Library/Homebrew/test/download_strategies_test.rb
index 87218fb12b..40236b420a 100644
--- a/Library/Homebrew/test/download_strategies_test.rb
+++ b/Library/Homebrew/test/download_strategies_test.rb
@@ -2,11 +2,12 @@ require "testing_env"
 require "download_strategy"
 
 class ResourceDouble
-  attr_reader :url, :specs, :version
+  attr_reader :url, :specs, :version, :mirrors
 
   def initialize(url = "http://example.com/foo.tar.gz", specs = {})
     @url = url
     @specs = specs
+    @mirrors = []
   end
 end
 
@@ -14,6 +15,7 @@ class AbstractDownloadStrategyTests < Homebrew::TestCase
   include FileUtils
 
   def setup
+    super
     @name = "foo"
     @resource = ResourceDouble.new
     @strategy = AbstractDownloadStrategy.new(@name, @resource)
@@ -60,10 +62,86 @@ class VCSDownloadStrategyTests < Homebrew::TestCase
   end
 end
 
+class GitHubPrivateRepositoryDownloadStrategyTests < Homebrew::TestCase
+  def setup
+    super
+    resource = ResourceDouble.new("https://github.com/owner/repo/archive/1.1.5.tar.gz")
+    ENV["HOMEBREW_GITHUB_API_TOKEN"] = "token"
+    GitHub.stubs(:repository).returns {}
+    @strategy = GitHubPrivateRepositoryDownloadStrategy.new("foo", resource)
+  end
+
+  def test_set_github_token
+    assert_equal "token", @strategy.instance_variable_get(:@github_token)
+  end
+
+  def test_parse_url_pattern
+    assert_equal "owner", @strategy.instance_variable_get(:@owner)
+    assert_equal "repo", @strategy.instance_variable_get(:@repo)
+    assert_equal "archive/1.1.5.tar.gz", @strategy.instance_variable_get(:@filepath)
+  end
+
+  def test_download_url
+    expected = "https://token@github.com/owner/repo/archive/1.1.5.tar.gz"
+    assert_equal expected, @strategy.download_url
+  end
+end
+
+class GitHubPrivateRepositoryReleaseDownloadStrategyTests < Homebrew::TestCase
+  def setup
+    super
+    resource = ResourceDouble.new("https://github.com/owner/repo/releases/download/tag/foo_v0.1.0_darwin_amd64.tar.gz")
+    ENV["HOMEBREW_GITHUB_API_TOKEN"] = "token"
+    GitHub.stubs(:repository).returns {}
+    @strategy = GitHubPrivateRepositoryReleaseDownloadStrategy.new("foo", resource)
+  end
+
+  def test_parse_url_pattern
+    assert_equal "owner", @strategy.instance_variable_get(:@owner)
+    assert_equal "repo", @strategy.instance_variable_get(:@repo)
+    assert_equal "tag", @strategy.instance_variable_get(:@tag)
+    assert_equal "foo_v0.1.0_darwin_amd64.tar.gz", @strategy.instance_variable_get(:@filename)
+  end
+
+  def test_download_url
+    @strategy.stubs(:resolve_asset_id).returns(456)
+    expected = "https://token@api.github.com/repos/owner/repo/releases/assets/456"
+    assert_equal expected, @strategy.download_url
+  end
+
+  def test_resolve_asset_id
+    release_metadata = {
+      "assets" => [
+        {
+          "id" => 123,
+          "name" => "foo_v0.1.0_linux_amd64.tar.gz",
+        },
+        {
+          "id" => 456,
+          "name" => "foo_v0.1.0_darwin_amd64.tar.gz",
+        },
+      ],
+    }
+    @strategy.stubs(:fetch_release_metadata).returns(release_metadata)
+    assert_equal 456, @strategy.send(:resolve_asset_id)
+  end
+
+  def test_fetch_release_metadata
+    expected_release_url = "https://api.github.com/repos/owner/repo/releases/tags/tag"
+    github_mock = MiniTest::Mock.new
+    github_mock.expect :call, {}, [expected_release_url]
+    GitHub.stub :open, github_mock do
+      @strategy.send(:fetch_release_metadata)
+    end
+    github_mock.verify
+  end
+end
+
 class GitDownloadStrategyTests < Homebrew::TestCase
   include FileUtils
 
   def setup
+    super
     resource = ResourceDouble.new("https://github.com/homebrew/foo")
     @commit_id = 1
     @strategy = GitDownloadStrategy.new("baz", resource)
@@ -71,10 +149,6 @@ class GitDownloadStrategyTests < Homebrew::TestCase
     mkpath @cached_location
   end
 
-  def teardown
-    rmtree @cached_location
-  end
-
   def git_commit_all
     shutup do
       system "git", "add", "--all"
@@ -83,28 +157,14 @@ class GitDownloadStrategyTests < Homebrew::TestCase
     end
   end
 
-  def using_git_env
-    initial_env = ENV.to_hash
-    %w[AUTHOR COMMITTER].each do |role|
-      ENV["GIT_#{role}_NAME"] = "brew tests"
-      ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost"
-      ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100"
-    end
-    yield
-  ensure
-    ENV.replace(initial_env)
-  end
-
   def setup_git_repo
-    using_git_env do
-      @cached_location.cd do
-        shutup do
-          system "git", "init"
-          system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo"
-        end
-        touch "README"
-        git_commit_all
+    @cached_location.cd do
+      shutup do
+        system "git", "init"
+        system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo"
       end
+      touch "README"
+      git_commit_all
     end
   end
 
@@ -118,18 +178,16 @@ class GitDownloadStrategyTests < Homebrew::TestCase
 
   def test_source_modified_time
     setup_git_repo
-    assert_equal 1_242_860_651, @strategy.source_modified_time.to_i
+    assert_equal 1_485_115_153, @strategy.source_modified_time.to_i
   end
 
   def test_last_commit
     setup_git_repo
-    using_git_env do
-      @cached_location.cd do
-        touch "LICENSE"
-        git_commit_all
-      end
+    @cached_location.cd do
+      touch "LICENSE"
+      git_commit_all
     end
-    assert_equal "c50c79b", @strategy.last_commit
+    assert_equal "f68266e", @strategy.last_commit
   end
 
   def test_fetch_last_commit
@@ -140,21 +198,19 @@ class GitDownloadStrategyTests < Homebrew::TestCase
     resource.instance_variable_set(:@version, Version.create("HEAD"))
     @strategy = GitDownloadStrategy.new("baz", resource)
 
-    using_git_env do
-      remote_repo.cd do
-        shutup do
-          system "git", "init"
-          system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo"
-        end
-        touch "README"
-        git_commit_all
-        touch "LICENSE"
-        git_commit_all
+    remote_repo.cd do
+      shutup do
+        system "git", "init"
+        system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo"
       end
+      touch "README"
+      git_commit_all
+      touch "LICENSE"
+      git_commit_all
     end
 
     @strategy.shutup!
-    assert_equal "c50c79b", @strategy.fetch_last_commit
+    assert_equal "f68266e", @strategy.fetch_last_commit
   ensure
     remote_repo.rmtree if remote_repo.directory?
   end
@@ -162,6 +218,7 @@ end
 
 class DownloadStrategyDetectorTests < Homebrew::TestCase
   def setup
+    super
     @d = DownloadStrategyDetector.new
   end
 
diff --git a/Library/Homebrew/test/emoji_test.rb b/Library/Homebrew/test/emoji_test.rb
new file mode 100644
index 0000000000..ea68db8f6e
--- /dev/null
+++ b/Library/Homebrew/test/emoji_test.rb
@@ -0,0 +1,11 @@
+require "testing_env"
+require "emoji"
+
+class EmojiTest < Homebrew::TestCase
+  def test_install_badge
+    assert_equal "🍺", Emoji.install_badge
+
+    ENV["HOMEBREW_INSTALL_BADGE"] = "foo"
+    assert_equal "foo", Emoji.install_badge
+  end
+end
diff --git a/Library/Homebrew/test/formula_installer_test.rb b/Library/Homebrew/test/formula_installer_test.rb
index 652548bd78..c99b2de74c 100644
--- a/Library/Homebrew/test/formula_installer_test.rb
+++ b/Library/Homebrew/test/formula_installer_test.rb
@@ -84,13 +84,10 @@ class InstallTests < Homebrew::TestCase
 
     cc_arg = "--cc=clang"
     ARGV << cc_arg
-    begin
-      temporary_install(TestballBottle.new) do |f|
-        tab = Tab.for_formula(f)
-        assert_equal "clang", tab.compiler
-      end
-    ensure
-      ARGV.delete_if { |x| x == cc_arg }
+
+    temporary_install(TestballBottle.new) do |f|
+      tab = Tab.for_formula(f)
+      assert_equal "clang", tab.compiler
     end
   end
 end
@@ -128,11 +125,7 @@ class FormulaInstallerTests < Homebrew::TestCase
     fi = FormulaInstaller.new(dependent)
     assert_raises(CannotInstallFormulaError) { fi.check_install_sanity }
   ensure
-    dependency.unpin
     dependency_keg.unlink
-    dependency_keg.uninstall
-    dependency.clear_cache
-    dep_path.unlink
     Formulary::FORMULAE.delete(dep_path)
   end
 end
diff --git a/Library/Homebrew/test/formula_lock_test.rb b/Library/Homebrew/test/formula_lock_test.rb
index 80ee9dd258..13244555d0 100644
--- a/Library/Homebrew/test/formula_lock_test.rb
+++ b/Library/Homebrew/test/formula_lock_test.rb
@@ -3,13 +3,14 @@ require "formula_lock"
 
 class FormulaLockTests < Homebrew::TestCase
   def setup
+    super
     @lock = FormulaLock.new("foo")
     @lock.lock
   end
 
   def teardown
     @lock.unlock
-    HOMEBREW_LOCK_DIR.children.each(&:unlink)
+    super
   end
 
   def test_locking_file_with_existing_lock_raises_error
diff --git a/Library/Homebrew/test/formula_pin_test.rb b/Library/Homebrew/test/formula_pin_test.rb
index 297d7703e3..7e3c7efa04 100644
--- a/Library/Homebrew/test/formula_pin_test.rb
+++ b/Library/Homebrew/test/formula_pin_test.rb
@@ -21,6 +21,7 @@ class FormulaPinTests < Homebrew::TestCase
   end
 
   def setup
+    super
     @f   = FormulaDouble.new
     @pin = FormulaPin.new(@f)
     @f.rack.mkpath
@@ -47,8 +48,4 @@ class FormulaPinTests < Homebrew::TestCase
     refute_predicate @pin, :pinned?
     refute_predicate HOMEBREW_PINNED_KEGS, :directory?
   end
-
-  def teardown
-    @f.rack.rmtree
-  end
 end
diff --git a/Library/Homebrew/test/formula_test.rb b/Library/Homebrew/test/formula_test.rb
index a6db1b57f2..ecdd1847b9 100644
--- a/Library/Homebrew/test/formula_test.rb
+++ b/Library/Homebrew/test/formula_test.rb
@@ -176,8 +176,6 @@ class FormulaTests < Homebrew::TestCase
     prefix.mkpath
     FileUtils.touch prefix+Tab::FILENAME
     assert_predicate f, :any_version_installed?
-  ensure
-    f.rack.rmtree
   end
 
   def test_migration_needed
@@ -203,9 +201,6 @@ class FormulaTests < Homebrew::TestCase
     newname_prefix.mkpath
 
     refute_predicate f, :migration_needed?
-  ensure
-    oldname_prefix.parent.rmtree
-    newname_prefix.parent.rmtree
   end
 
   def test_installed?
@@ -240,8 +235,6 @@ class FormulaTests < Homebrew::TestCase
     prefix = HOMEBREW_CELLAR+f.name+f.head.version
     prefix.mkpath
     assert_equal prefix, f.installed_prefix
-  ensure
-    f.rack.rmtree
   end
 
   def test_installed_prefix_devel_installed
@@ -255,8 +248,6 @@ class FormulaTests < Homebrew::TestCase
     prefix = HOMEBREW_CELLAR+f.name+f.devel.version
     prefix.mkpath
     assert_equal prefix, f.installed_prefix
-  ensure
-    f.rack.rmtree
   end
 
   def test_installed_prefix_stable_installed
@@ -270,8 +261,6 @@ class FormulaTests < Homebrew::TestCase
     prefix = HOMEBREW_CELLAR+f.name+f.version
     prefix.mkpath
     assert_equal prefix, f.installed_prefix
-  ensure
-    f.rack.rmtree
   end
 
   def test_installed_prefix_outdated_stable_head_installed
@@ -289,8 +278,6 @@ class FormulaTests < Homebrew::TestCase
     tab.write
 
     assert_equal HOMEBREW_CELLAR/"#{f.name}/#{f.version}", f.installed_prefix
-  ensure
-    f.rack.rmtree
   end
 
   def test_installed_prefix_outdated_devel_head_installed
@@ -311,8 +298,6 @@ class FormulaTests < Homebrew::TestCase
     tab.write
 
     assert_equal HOMEBREW_CELLAR/"#{f.name}/#{f.version}", f.installed_prefix
-  ensure
-    f.rack.rmtree
   end
 
   def test_installed_prefix_head
@@ -358,8 +343,6 @@ class FormulaTests < Homebrew::TestCase
 
     prefix = HOMEBREW_CELLAR/"#{f.name}/HEAD-222222_2"
     assert_equal prefix, f.latest_head_prefix
-  ensure
-    f.rack.rmtree
   end
 
   def test_equality
@@ -543,8 +526,6 @@ class FormulaTests < Homebrew::TestCase
   end
 
   def test_update_head_version
-    initial_env = ENV.to_hash
-
     f = formula do
       head "foo", using: :git
     end
@@ -552,12 +533,6 @@ class FormulaTests < Homebrew::TestCase
     cached_location = f.head.downloader.cached_location
     cached_location.mkpath
 
-    %w[AUTHOR COMMITTER].each do |role|
-      ENV["GIT_#{role}_NAME"] = "brew tests"
-      ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost"
-      ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100"
-    end
-
     cached_location.cd do
       FileUtils.touch "LICENSE"
       shutup do
@@ -569,9 +544,6 @@ class FormulaTests < Homebrew::TestCase
 
     f.update_head_version
     assert_equal Version.create("HEAD-5658946"), f.head.version
-  ensure
-    ENV.replace(initial_env)
-    cached_location.rmtree
   end
 
   def test_legacy_options
@@ -651,12 +623,80 @@ class FormulaTests < Homebrew::TestCase
 
     f4 = formula("f4") do
       url "f4-1.0"
-      depends_on "f3"
+      depends_on "f1"
+    end
+    stub_formula_loader f4
+
+    f5 = formula("f5") do
+      url "f5-1.0"
+      depends_on "f3" => :build
+      depends_on "f4"
     end
 
-    assert_equal %w[f3], f4.deps.map(&:name)
-    assert_equal %w[f1 f2 f3], f4.recursive_dependencies.map(&:name)
-    assert_equal %w[f2 f3], f4.runtime_dependencies.map(&:name)
+    assert_equal %w[f3 f4], f5.deps.map(&:name)
+    assert_equal %w[f1 f2 f3 f4], f5.recursive_dependencies.map(&:name)
+    assert_equal %w[f1 f4], f5.runtime_dependencies.map(&:name)
+  end
+
+  def test_runtime_dependencies_with_optional_deps_from_tap
+    tap_loader = mock
+    tap_loader.stubs(:get_formula).raises(RuntimeError, "tried resolving tap formula")
+    Formulary.stubs(:loader_for).with("foo/bar/f1", from: nil).returns(tap_loader)
+
+    stub_formula_loader formula("f2") { url "f2-1.0" }, "baz/qux/f2"
+
+    f3 = formula("f3") do
+      url "f3-1.0"
+      depends_on "foo/bar/f1" => :optional
+      depends_on "baz/qux/f2"
+    end
+
+    # f1 shouldn't be loaded by default.
+    # If it is, an exception will be raised.
+    assert_equal %w[baz/qux/f2], f3.runtime_dependencies.map(&:name)
+
+    # If --with-f1, f1 should be loaded.
+    stub_formula_loader formula("f1") { url "f1-1.0" }, "foo/bar/f1"
+    f3.build = BuildOptions.new(Options.create(%w[--with-f1]), f3.options)
+    assert_equal %w[foo/bar/f1 baz/qux/f2], f3.runtime_dependencies.map(&:name)
+  end
+
+  def test_requirements
+    f1 = formula("f1") do
+      url "f1-1"
+
+      depends_on :python
+      depends_on x11: :recommended
+      depends_on xcode: ["1.0", :optional]
+    end
+    stub_formula_loader f1
+
+    python = PythonRequirement.new
+    x11 = X11Requirement.new("x11", [:recommended])
+    xcode = XcodeRequirement.new(["1.0", :optional])
+
+    # Default block should filter out deps that aren't being used
+    assert_equal Set[python, x11], Set.new(f1.recursive_requirements)
+
+    f1.build = BuildOptions.new(["--with-xcode", "--without-x11"], f1.options)
+    assert_equal Set[python, xcode], Set.new(f1.recursive_requirements)
+    f1.build = f1.stable.build
+
+    f2 = formula("f2") do
+      url "f2-1"
+      depends_on "f1"
+    end
+
+    assert_equal Set[python, x11], Set.new(f2.recursive_requirements)
+
+    # Empty block should allow all requirements
+    assert_equal Set[python, x11, xcode], Set.new(f2.recursive_requirements {})
+
+    # Requirements can be pruned
+    requirements = f2.recursive_requirements do |_dependent, requirement|
+      Requirement.prune if requirement.is_a?(PythonRequirement)
+    end
+    assert_equal Set[x11, xcode], Set.new(requirements)
   end
 
   def test_to_hash
@@ -703,9 +743,6 @@ class FormulaTests < Homebrew::TestCase
 
     assert_equal f3.installed_kegs.sort_by(&:version)[0..1],
                  f3.eligible_kegs_for_cleanup.sort_by(&:version)
-  ensure
-    [f1, f2, f3].each(&:clear_cache)
-    f3.rack.rmtree
   end
 
   def test_eligible_kegs_for_cleanup_keg_pinned
@@ -727,10 +764,6 @@ class FormulaTests < Homebrew::TestCase
     assert_predicate f3, :installed?
 
     assert_equal [Keg.new(f2.prefix)], shutup { f3.eligible_kegs_for_cleanup }
-  ensure
-    f1.unpin
-    [f1, f2, f3].each(&:clear_cache)
-    f3.rack.rmtree
   end
 
   def test_eligible_kegs_for_cleanup_head_installed
@@ -753,8 +786,6 @@ class FormulaTests < Homebrew::TestCase
 
     eligible_kegs = f.installed_kegs - [Keg.new(f.prefix("HEAD-111111_1"))]
     assert_equal eligible_kegs, f.eligible_kegs_for_cleanup
-  ensure
-    f.rack.rmtree
   end
 
   def test_pour_bottle
@@ -806,6 +837,8 @@ class AliasChangeTests < Homebrew::TestCase
   end
 
   def setup
+    super
+
     alias_name = "bar"
     @alias_path = "#{CoreTap.instance.alias_dir}/#{alias_name}"
 
@@ -874,6 +907,8 @@ class OutdatedVersionsTests < Homebrew::TestCase
   attr_reader :f, :old_formula, :new_formula
 
   def setup
+    super
+
     @f = formula do
       url "foo"
       version "1.20"
@@ -889,11 +924,6 @@ class OutdatedVersionsTests < Homebrew::TestCase
     @old_alias_target_prefix = HOMEBREW_CELLAR/"#{old_formula.name}/1.0"
   end
 
-  def teardown
-    formulae = [@f, @old_formula, @new_formula]
-    formulae.map(&:rack).select(&:exist?).each(&:rmtree)
-  end
-
   def alias_path
     "#{@f.tap.alias_dir}/bar"
   end
@@ -1058,13 +1088,12 @@ class OutdatedVersionsTests < Homebrew::TestCase
     outdated_stable_prefix = HOMEBREW_CELLAR.join("testball/1.0")
     head_prefix_a = HOMEBREW_CELLAR.join("testball/HEAD")
     head_prefix_b = HOMEBREW_CELLAR.join("testball/HEAD-aaaaaaa_1")
-    head_prefix_c = HOMEBREW_CELLAR.join("testball/HEAD-5658946")
+    head_prefix_c = HOMEBREW_CELLAR.join("testball/HEAD-18a7103")
 
     setup_tab_for_prefix(outdated_stable_prefix)
     tab_a = setup_tab_for_prefix(head_prefix_a, versions: { "stable" => "1.0" })
     setup_tab_for_prefix(head_prefix_b)
 
-    initial_env = ENV.to_hash
     testball_repo = HOMEBREW_PREFIX.join("testball_repo")
     testball_repo.mkdir
 
@@ -1074,12 +1103,6 @@ class OutdatedVersionsTests < Homebrew::TestCase
       head "file://#{testball_repo}", using: :git
     end
 
-    %w[AUTHOR COMMITTER].each do |role|
-      ENV["GIT_#{role}_NAME"] = "brew tests"
-      ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost"
-      ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100"
-    end
-
     testball_repo.cd do
       FileUtils.touch "LICENSE"
       shutup do
@@ -1104,13 +1127,7 @@ class OutdatedVersionsTests < Homebrew::TestCase
     reset_outdated_kegs
     assert_predicate f.outdated_kegs(fetch_head: true), :empty?
   ensure
-    ENV.replace(initial_env)
     testball_repo.rmtree if testball_repo.exist?
-    outdated_stable_prefix.rmtree if outdated_stable_prefix.exist?
-    head_prefix_b.rmtree if head_prefix.exist?
-    head_prefix_c.rmtree if head_prefix_c.exist?
-    FileUtils.rm_rf HOMEBREW_CACHE/"testball--git"
-    FileUtils.rm_rf HOMEBREW_CELLAR/"testball"
   end
 
   def test_outdated_kegs_version_scheme_changed
@@ -1124,8 +1141,6 @@ class OutdatedVersionsTests < Homebrew::TestCase
     setup_tab_for_prefix(prefix, versions: { "stable" => "0.1" })
 
     refute_predicate f.outdated_kegs, :empty?
-  ensure
-    prefix.rmtree
   end
 
   def test_outdated_kegs_mixed_version_schemes
@@ -1153,8 +1168,6 @@ class OutdatedVersionsTests < Homebrew::TestCase
     prefix_d = HOMEBREW_CELLAR.join("testball/20141011")
     setup_tab_for_prefix(prefix_d, versions: { "stable" => "20141009", "version_scheme" => 3 })
     assert_predicate f.outdated_kegs, :empty?
-  ensure
-    f.rack.rmtree
   end
 
   def test_outdated_kegs_head_with_version_scheme
@@ -1174,7 +1187,5 @@ class OutdatedVersionsTests < Homebrew::TestCase
 
     setup_tab_for_prefix(head_prefix, versions: { "stable" => "1.0", "version_scheme" => 2 })
     assert_predicate f.outdated_kegs, :empty?
-  ensure
-    head_prefix.rmtree
   end
 end
diff --git a/Library/Homebrew/test/formulary_test.rb b/Library/Homebrew/test/formulary_test.rb
index 3d88c84077..ea7ecf8d05 100644
--- a/Library/Homebrew/test/formulary_test.rb
+++ b/Library/Homebrew/test/formulary_test.rb
@@ -16,6 +16,7 @@ end
 
 class FormularyFactoryTest < Homebrew::TestCase
   def setup
+    super
     @name = "testball_bottle"
     @path = CoreTap.new.formula_dir/"#{@name}.rb"
     @bottle_dir = Pathname.new("#{TEST_FIXTURE_DIR}/bottles")
@@ -39,10 +40,6 @@ class FormularyFactoryTest < Homebrew::TestCase
     EOS
   end
 
-  def teardown
-    @path.unlink
-  end
-
   def test_factory
     assert_kind_of Formula, Formulary.factory(@name)
   end
@@ -61,8 +58,6 @@ class FormularyFactoryTest < Homebrew::TestCase
     path.write "class Wrong#{Formulary.class_s(name)} < Formula\nend\n"
 
     assert_raises(FormulaClassUnavailableError) { Formulary.factory(name) }
-  ensure
-    path.unlink
   end
 
   def test_factory_from_path
@@ -90,8 +85,6 @@ class FormularyFactoryTest < Homebrew::TestCase
     result = Formulary.factory("foo")
     assert_kind_of Formula, result
     assert_equal alias_path.to_s, result.alias_path
-  ensure
-    alias_dir.rmtree
   end
 
   def test_factory_from_rack_and_from_keg
@@ -107,9 +100,6 @@ class FormularyFactoryTest < Homebrew::TestCase
     assert_kind_of Tab, f.build
   ensure
     keg.unlink
-    keg.uninstall
-    formula.clear_cache
-    formula.bottle.clear_cache
   end
 
   def test_load_from_contents
@@ -121,13 +111,12 @@ class FormularyFactoryTest < Homebrew::TestCase
     (HOMEBREW_CELLAR/@name).mkpath
     assert_equal HOMEBREW_CELLAR/@name, Formulary.to_rack(@name)
     assert_raises(TapFormulaUnavailableError) { Formulary.to_rack("a/b/#{@name}") }
-  ensure
-    FileUtils.rm_rf HOMEBREW_CELLAR/@name
   end
 end
 
 class FormularyTapFactoryTest < Homebrew::TestCase
   def setup
+    super
     @name = "foo"
     @tap = Tap.new "homebrew", "foo"
     @path = @tap.path/"#{@name}.rb"
@@ -139,10 +128,6 @@ class FormularyTapFactoryTest < Homebrew::TestCase
     @path.write @code
   end
 
-  def teardown
-    @tap.path.rmtree
-  end
-
   def test_factory_tap_formula
     assert_kind_of Formula, Formulary.factory(@name)
   end
@@ -173,6 +158,7 @@ end
 
 class FormularyTapPriorityTest < Homebrew::TestCase
   def setup
+    super
     @name = "foo"
     @core_path = CoreTap.new.formula_dir/"#{@name}.rb"
     @tap = Tap.new "homebrew", "foo"
@@ -186,11 +172,6 @@ class FormularyTapPriorityTest < Homebrew::TestCase
     @tap_path.write code
   end
 
-  def teardown
-    @core_path.unlink
-    @tap.path.rmtree
-  end
-
   def test_find_with_priority_core_formula
     formula = Formulary.find_with_priority(@name)
     assert_kind_of Formula, formula
diff --git a/Library/Homebrew/test/gpg2_requirement_test.rb b/Library/Homebrew/test/gpg2_requirement_test.rb
index fa7fc9ea41..3297c28512 100644
--- a/Library/Homebrew/test/gpg2_requirement_test.rb
+++ b/Library/Homebrew/test/gpg2_requirement_test.rb
@@ -4,6 +4,7 @@ require "fileutils"
 
 class GPG2RequirementTests < Homebrew::TestCase
   def setup
+    super
     @dir = Pathname.new(mktmpdir)
     (@dir/"bin/gpg").write <<-EOS.undent
       #!/bin/bash
@@ -14,11 +15,11 @@ class GPG2RequirementTests < Homebrew::TestCase
 
   def teardown
     FileUtils.rm_rf @dir
+    super
   end
 
   def test_satisfied
-    with_environment("PATH" => @dir/"bin") do
-      assert_predicate GPG2Requirement.new, :satisfied?
-    end
+    ENV["PATH"] = @dir/"bin"
+    assert_predicate GPG2Requirement.new, :satisfied?
   end
 end
diff --git a/Library/Homebrew/test/gpg_test.rb b/Library/Homebrew/test/gpg_test.rb
index 0374bdab4b..ea43725491 100644
--- a/Library/Homebrew/test/gpg_test.rb
+++ b/Library/Homebrew/test/gpg_test.rb
@@ -3,18 +3,16 @@ require "gpg"
 
 class GpgTest < Homebrew::TestCase
   def setup
+    super
     skip "GPG Unavailable" unless Gpg.available?
     @dir = Pathname.new(mktmpdir)
   end
 
   def test_create_test_key
     Dir.chdir(@dir) do
-      with_environment("HOME" => @dir) do
-        shutup { Gpg.create_test_key(@dir) }
-        assert_predicate @dir/".gnupg/secring.gpg", :exist?
-      end
+      ENV["HOME"] = @dir
+      shutup { Gpg.create_test_key(@dir) }
+      assert_predicate @dir/".gnupg/secring.gpg", :exist?
     end
-  ensure
-    @dir.rmtree
   end
 end
diff --git a/Library/Homebrew/test/hardware_test.rb b/Library/Homebrew/test/hardware_test.rb
index 2bea5387d5..69f881a60d 100644
--- a/Library/Homebrew/test/hardware_test.rb
+++ b/Library/Homebrew/test/hardware_test.rb
@@ -8,7 +8,7 @@ class HardwareTests < Homebrew::TestCase
 
   if Hardware::CPU.intel?
     def test_hardware_intel_family
-      families = [:core, :core2, :penryn, :nehalem, :arrandale, :sandybridge, :ivybridge, :haswell, :broadwell, :skylake, :dunno]
+      families = [:core, :core2, :penryn, :nehalem, :arrandale, :sandybridge, :ivybridge, :haswell, :broadwell, :skylake, :kabylake, :dunno]
       assert_includes families, Hardware::CPU.family
     end
   end
diff --git a/Library/Homebrew/test/install_test.rb b/Library/Homebrew/test/install_test.rb
index e047c00303..da6c1863f5 100644
--- a/Library/Homebrew/test/install_test.rb
+++ b/Library/Homebrew/test/install_test.rb
@@ -73,13 +73,6 @@ class IntegrationCommandTestInstall < IntegrationCommandTestCase
   end
 
   def test_install_head_installed
-    initial_env = ENV.to_hash
-    %w[AUTHOR COMMITTER].each do |role|
-      ENV["GIT_#{role}_NAME"] = "brew tests"
-      ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost"
-      ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100"
-    end
-
     repo_path = HOMEBREW_CACHE.join("repo")
     repo_path.join("bin").mkpath
 
@@ -105,15 +98,11 @@ class IntegrationCommandTestInstall < IntegrationCommandTestCase
     # Ignore dependencies, because we'll try to resolve requirements in build.rb
     # and there will be the git requirement, but we cannot instantiate git
     # formula since we only have testball1 formula.
-    assert_match "#{HOMEBREW_CELLAR}/testball1/HEAD-2ccdf4f", cmd("install", "testball1", "--HEAD", "--ignore-dependencies")
-    assert_match "testball1-HEAD-2ccdf4f already installed",
+    assert_match "#{HOMEBREW_CELLAR}/testball1/HEAD-d5eb689", cmd("install", "testball1", "--HEAD", "--ignore-dependencies")
+    assert_match "testball1-HEAD-d5eb689 already installed",
       cmd("install", "testball1", "--HEAD", "--ignore-dependencies")
-    assert_match "#{HOMEBREW_CELLAR}/testball1/HEAD-2ccdf4f", cmd("unlink", "testball1")
+    assert_match "#{HOMEBREW_CELLAR}/testball1/HEAD-d5eb689", cmd("unlink", "testball1")
     assert_match "#{HOMEBREW_CELLAR}/testball1/1.0", cmd("install", "testball1")
-
-  ensure
-    ENV.replace(initial_env)
-    repo_path.rmtree
   end
 
   def test_install_with_invalid_option
diff --git a/Library/Homebrew/test/keg_test.rb b/Library/Homebrew/test/keg_test.rb
index 2c91027e5b..bd42320383 100644
--- a/Library/Homebrew/test/keg_test.rb
+++ b/Library/Homebrew/test/keg_test.rb
@@ -2,7 +2,7 @@ require "testing_env"
 require "keg"
 require "stringio"
 
-class LinkTests < Homebrew::TestCase
+class LinkTestCase < Homebrew::TestCase
   include FileUtils
 
   def setup_test_keg(name, version)
@@ -20,6 +20,8 @@ class LinkTests < Homebrew::TestCase
   end
 
   def setup
+    super
+
     @keg = setup_test_keg("foo", "1.0")
     @dst = HOMEBREW_PREFIX.join("bin", "helloworld")
     @nonexistent = Pathname.new("/some/nonexistent/path")
@@ -34,15 +36,17 @@ class LinkTests < Homebrew::TestCase
   end
 
   def teardown
-    @kegs.each do |keg|
-      keg.unlink
-      keg.uninstall
-    end
-
+    @kegs.each(&:unlink)
     $stdout = @old_stdout
-
-    rmtree HOMEBREW_PREFIX/"bin"
     rmtree HOMEBREW_PREFIX/"lib"
+    super
+  end
+end
+
+class LinkTests < LinkTestCase
+  def test_all
+    Formula.clear_racks_cache
+    assert_equal [@keg], Keg.all
   end
 
   def test_empty_installation
@@ -294,8 +298,6 @@ class LinkTests < Homebrew::TestCase
     assert_equal 2, lib.children.length
   ensure
     a.unlink
-    a.uninstall
-    b.uninstall
   end
 
   def test_removes_broken_symlinks_that_conflict_with_directories
@@ -311,11 +313,10 @@ class LinkTests < Homebrew::TestCase
     keg.link
   ensure
     keg.unlink
-    keg.uninstall
   end
 end
 
-class InstalledDependantsTests < LinkTests
+class InstalledDependantsTests < LinkTestCase
   def stub_formula_name(name)
     f = formula(name) { url "foo-1.0" }
     stub_formula_loader f
@@ -333,6 +334,7 @@ class InstalledDependantsTests < LinkTests
   def setup
     super
     @dependent = setup_test_keg("bar", "1.0")
+    @keg.link
   end
 
   def alter_tab(keg = @dependent)
@@ -341,24 +343,55 @@ class InstalledDependantsTests < LinkTests
     tab.write
   end
 
-  def dependencies(deps)
+  # 1.1.6 is the earliest version of Homebrew that generates correct runtime
+  # dependency lists in tabs.
+  def dependencies(deps, homebrew_version: "1.1.6")
     alter_tab do |tab|
+      tab.homebrew_version = homebrew_version
       tab.tabfile = @dependent.join("INSTALL_RECEIPT.json")
       tab.runtime_dependencies = deps
     end
   end
 
+  def unreliable_dependencies(deps)
+    # 1.1.5 is (hopefully!) the last version of Homebrew that generates
+    # incorrect runtime dependency lists in tabs.
+    dependencies(deps, homebrew_version: "1.1.5")
+  end
+
   # Test with a keg whose formula isn't known.
   # This can happen if e.g. a formula is installed
   # from a file path or URL.
   def test_unknown_formula
     Formulary.unstub(:loader_for)
-    dependencies []
-    alter_tab { |t| t.source["path"] = nil }
-    assert_empty @keg.installed_dependents
+    alter_tab(@keg) do |t|
+      t.source["tap"] = "some/tap"
+      t.source["path"] = nil
+    end
+
+    dependencies [{ "full_name" => "some/tap/foo", "version" => "1.0" }]
+    assert_equal [@dependent], @keg.installed_dependents
+    assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg])
+
+    dependencies nil
+    # It doesn't make sense for a keg with no formula to have any dependents,
+    # so that can't really be tested.
     assert_nil Keg.find_some_installed_dependents([@keg])
   end
 
+  def test_a_dependency_with_no_tap_in_tab
+    @tap_dep = setup_test_keg("baz", "1.0")
+
+    alter_tab(@keg) { |t| t.source["tap"] = nil }
+
+    dependencies nil
+    Formula["bar"].class.depends_on "foo"
+    Formula["bar"].class.depends_on "baz"
+
+    result = Keg.find_some_installed_dependents([@keg, @tap_dep])
+    assert_equal [[@keg, @tap_dep], ["bar"]], result
+  end
+
   def test_no_dependencies_anywhere
     dependencies nil
     assert_empty @keg.installed_dependents
@@ -372,6 +405,27 @@ class InstalledDependantsTests < LinkTests
     assert_equal [[@keg], ["bar"]], Keg.find_some_installed_dependents([@keg])
   end
 
+  def test_uninstalling_dependent_and_dependency
+    dependencies nil
+    Formula["bar"].class.depends_on "foo"
+    assert_empty @keg.installed_dependents
+    assert_nil Keg.find_some_installed_dependents([@keg, @dependent])
+  end
+
+  def test_renamed_dependency
+    dependencies nil
+
+    stub_formula_loader Formula["foo"], "homebrew/core/foo-old"
+    renamed_path = HOMEBREW_CELLAR/"foo-old"
+    (HOMEBREW_CELLAR/"foo").rename(renamed_path)
+    renamed_keg = Keg.new(renamed_path.join("1.0"))
+
+    Formula["bar"].class.depends_on "foo"
+
+    result = Keg.find_some_installed_dependents([renamed_keg])
+    assert_equal [[renamed_keg], ["bar"]], result
+  end
+
   def test_empty_dependencies_in_tab
     dependencies []
     assert_empty @keg.installed_dependents
@@ -380,8 +434,8 @@ class InstalledDependantsTests < LinkTests
 
   def test_same_name_different_version_in_tab
     dependencies [{ "full_name" => "foo", "version" => "1.1" }]
-    assert_empty @keg.installed_dependents
-    assert_nil Keg.find_some_installed_dependents([@keg])
+    assert_equal [@dependent], @keg.installed_dependents
+    assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg])
   end
 
   def test_different_name_same_version_in_tab
@@ -396,4 +450,26 @@ class InstalledDependantsTests < LinkTests
     assert_equal [@dependent], @keg.installed_dependents
     assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg])
   end
+
+  def test_fallback_for_old_versions
+    unreliable_dependencies [{ "full_name" => "baz", "version" => "1.0" }]
+    Formula["bar"].class.depends_on "foo"
+    assert_empty @keg.installed_dependents
+    assert_equal [[@keg], ["bar"]], Keg.find_some_installed_dependents([@keg])
+  end
+
+  def test_nonoptlinked
+    @keg.remove_opt_record
+    dependencies [{ "full_name" => "foo", "version" => "1.0" }]
+    assert_empty @keg.installed_dependents
+    assert_nil Keg.find_some_installed_dependents([@keg])
+  end
+
+  def test_keg_only
+    @keg.unlink
+    Formula["foo"].class.keg_only "a good reason"
+    dependencies [{ "full_name" => "foo", "version" => "1.1" }] # different version
+    assert_equal [@dependent], @keg.installed_dependents
+    assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg])
+  end
 end
diff --git a/Library/Homebrew/test/language_python_test.rb b/Library/Homebrew/test/language_python_test.rb
index d1e3867f73..aa0a7d51dc 100644
--- a/Library/Homebrew/test/language_python_test.rb
+++ b/Library/Homebrew/test/language_python_test.rb
@@ -4,6 +4,7 @@ require "resource"
 
 class LanguagePythonTests < Homebrew::TestCase
   def setup
+    super
     @dir = Pathname.new(mktmpdir)
     resource = stub("resource", stage: true)
     formula_bin = @dir/"formula_bin"
@@ -14,10 +15,6 @@ class LanguagePythonTests < Homebrew::TestCase
     @venv = Language::Python::Virtualenv::Virtualenv.new(@formula, @dir, "python")
   end
 
-  def teardown
-    FileUtils.rm_rf @dir
-  end
-
   def test_virtualenv_creation
     @formula.expects(:resource).with("homebrew-virtualenv").returns(
       mock("resource", stage: true)
diff --git a/Library/Homebrew/test/migrator_test.rb b/Library/Homebrew/test/migrator_test.rb
index 8a2b6ad63e..012ea12bb0 100644
--- a/Library/Homebrew/test/migrator_test.rb
+++ b/Library/Homebrew/test/migrator_test.rb
@@ -10,6 +10,7 @@ end
 
 class MigratorErrorsTests < Homebrew::TestCase
   def setup
+    super
     @new_f = Testball.new("newname")
     @new_f.oldname = "oldname"
     @old_f = Testball.new("oldname")
@@ -31,8 +32,6 @@ class MigratorErrorsTests < Homebrew::TestCase
     tab.source["tap"] = "homebrew/core"
     tab.write
     assert_raises(Migrator::MigratorDifferentTapsError) { Migrator.new(@new_f) }
-  ensure
-    keg.parent.rmtree
   end
 end
 
@@ -40,6 +39,8 @@ class MigratorTests < Homebrew::TestCase
   include FileUtils
 
   def setup
+    super
+
     @new_f = Testball.new("newname")
     @new_f.oldname = "oldname"
 
@@ -69,30 +70,16 @@ class MigratorTests < Homebrew::TestCase
   end
 
   def teardown
-    @old_pin.unlink if @old_pin.symlink?
-
-    if @old_keg_record.parent.symlink?
-      @old_keg_record.parent.unlink
-    elsif @old_keg_record.directory?
+    if !@old_keg_record.parent.symlink? && @old_keg_record.directory?
       @keg.unlink
-      @keg.uninstall
     end
 
     if @new_keg_record.directory?
       new_keg = Keg.new(@new_keg_record)
       new_keg.unlink
-      new_keg.uninstall
     end
 
-    @old_keg_record.parent.rmtree if @old_keg_record.parent.directory?
-    @new_keg_record.parent.rmtree if @new_keg_record.parent.directory?
-
-    rmtree HOMEBREW_PREFIX/"bin"
-    rmtree HOMEBREW_PREFIX/"opt" if (HOMEBREW_PREFIX/"opt").directory?
-    # What to do with pin?
-    @new_f.unpin
-
-    HOMEBREW_LOCK_DIR.children.each(&:unlink)
+    super
   end
 
   def test_move_cellar
diff --git a/Library/Homebrew/test/options_test.rb b/Library/Homebrew/test/options_test.rb
index e7189a6042..f38ec44154 100644
--- a/Library/Homebrew/test/options_test.rb
+++ b/Library/Homebrew/test/options_test.rb
@@ -15,6 +15,7 @@ end
 
 class OptionTests < Homebrew::TestCase
   def setup
+    super
     @option = Option.new("foo")
   end
 
@@ -43,6 +44,7 @@ end
 
 class DeprecatedOptionTests < Homebrew::TestCase
   def setup
+    super
     @deprecated_option = DeprecatedOption.new("foo", "bar")
   end
 
@@ -68,6 +70,7 @@ end
 
 class OptionsTests < Homebrew::TestCase
   def setup
+    super
     @options = Options.new
   end
 
diff --git a/Library/Homebrew/test/os/mac/bottle_collector_test.rb b/Library/Homebrew/test/os/mac/bottle_collector_test.rb
index 2f88050aed..e9ae9b7537 100644
--- a/Library/Homebrew/test/os/mac/bottle_collector_test.rb
+++ b/Library/Homebrew/test/os/mac/bottle_collector_test.rb
@@ -3,6 +3,7 @@ require "utils/bottles"
 
 class OSMacBottleCollectorTests < Homebrew::TestCase
   def setup
+    super
     @collector = Utils::Bottles::Collector.new
   end
 
diff --git a/Library/Homebrew/test/os/mac/dependency_collector_test.rb b/Library/Homebrew/test/os/mac/dependency_collector_test.rb
index 4fdf3ebe42..1033df9ab5 100644
--- a/Library/Homebrew/test/os/mac/dependency_collector_test.rb
+++ b/Library/Homebrew/test/os/mac/dependency_collector_test.rb
@@ -7,11 +7,13 @@ class OSMacDependencyCollectorTests < Homebrew::TestCase
   end
 
   def setup
+    super
     @d = DependencyCollector.new
   end
 
   def teardown
     DependencyCollector.clear_cache
+    super
   end
 
   def test_tar_needs_xz_dependency
diff --git a/Library/Homebrew/test/os/mac/diagnostic_test.rb b/Library/Homebrew/test/os/mac/diagnostic_test.rb
index 655aa1d46b..704235b01c 100644
--- a/Library/Homebrew/test/os/mac/diagnostic_test.rb
+++ b/Library/Homebrew/test/os/mac/diagnostic_test.rb
@@ -5,14 +5,10 @@ require "diagnostic"
 
 class OSMacDiagnosticChecksTest < Homebrew::TestCase
   def setup
-    @env = ENV.to_hash
+    super
     @checks = Homebrew::Diagnostic::Checks.new
   end
 
-  def teardown
-    ENV.replace(@env)
-  end
-
   def test_check_for_other_package_managers
     MacOS.stubs(:macports_or_fink).returns ["fink"]
     assert_match "You have MacPorts or Fink installed:",
@@ -20,7 +16,7 @@ class OSMacDiagnosticChecksTest < Homebrew::TestCase
   end
 
   def test_check_for_unsupported_macos
-    ARGV.stubs(:homebrew_developer?).returns false
+    ENV.delete("HOMEBREW_DEVELOPER")
     OS::Mac.stubs(:prerelease?).returns true
     assert_match "We do not provide support for this pre-release version.",
       @checks.check_for_unsupported_macos
diff --git a/Library/Homebrew/test/os/mac/keg_test.rb b/Library/Homebrew/test/os/mac/keg_test.rb
index e79cbc9217..d1103415de 100644
--- a/Library/Homebrew/test/os/mac/keg_test.rb
+++ b/Library/Homebrew/test/os/mac/keg_test.rb
@@ -6,6 +6,8 @@ class OSMacLinkTests < Homebrew::TestCase
   include FileUtils
 
   def setup
+    super
+
     keg = HOMEBREW_CELLAR.join("foo", "1.0")
     keg.join("bin").mkpath
 
@@ -28,12 +30,12 @@ class OSMacLinkTests < Homebrew::TestCase
 
   def teardown
     @keg.unlink
-    @keg.uninstall
 
     $stdout = @old_stdout
 
-    rmtree HOMEBREW_PREFIX/"bin"
     rmtree HOMEBREW_PREFIX/"lib"
+
+    super
   end
 
   def test_mach_o_files_skips_hardlinks
@@ -48,7 +50,6 @@ class OSMacLinkTests < Homebrew::TestCase
     assert_equal 1, keg.mach_o_files.size
   ensure
     keg.unlink
-    keg.uninstall
   end
 
   def test_mach_o_files_isnt_confused_by_symlinks
@@ -64,6 +65,5 @@ class OSMacLinkTests < Homebrew::TestCase
     assert_equal 1, keg.mach_o_files.size
   ensure
     keg.unlink
-    keg.uninstall
   end
 end
diff --git a/Library/Homebrew/test/os/mac/mach_test.rb b/Library/Homebrew/test/os/mac/mach_test.rb
index a42f7316b1..ed0424be65 100644
--- a/Library/Homebrew/test/os/mac/mach_test.rb
+++ b/Library/Homebrew/test/os/mac/mach_test.rb
@@ -109,6 +109,7 @@ end
 
 class ArchitectureListExtensionTests < MachOPathnameTests
   def setup
+    super
     @archs = [:i386, :x86_64, :ppc7400, :ppc64].extend(ArchitectureListExtension)
   end
 
@@ -157,11 +158,13 @@ class TextExecutableTests < Homebrew::TestCase
   attr_reader :pn
 
   def setup
+    super
     @pn = HOMEBREW_PREFIX.join("an_executable")
   end
 
   def teardown
     HOMEBREW_PREFIX.join("an_executable").unlink
+    super
   end
 
   def test_simple_shebang
diff --git a/Library/Homebrew/test/os/mac/version_test.rb b/Library/Homebrew/test/os/mac/version_test.rb
index f702c7097a..ba42176917 100644
--- a/Library/Homebrew/test/os/mac/version_test.rb
+++ b/Library/Homebrew/test/os/mac/version_test.rb
@@ -4,6 +4,7 @@ require "os/mac/version"
 
 class OSMacVersionTests < Homebrew::TestCase
   def setup
+    super
     @v = MacOS::Version.new("10.7")
   end
 
diff --git a/Library/Homebrew/test/patch_test.rb b/Library/Homebrew/test/patch_test.rb
index 62624720e8..f5a61398aa 100644
--- a/Library/Homebrew/test/patch_test.rb
+++ b/Library/Homebrew/test/patch_test.rb
@@ -111,6 +111,7 @@ end
 
 class ExternalPatchTests < Homebrew::TestCase
   def setup
+    super
     @p = ExternalPatch.new(:p1) { url "file:///my.patch" }
   end
 
diff --git a/Library/Homebrew/test/patching_test.rb b/Library/Homebrew/test/patching_test.rb
index ac14c8e1e7..3dacc0818b 100644
--- a/Library/Homebrew/test/patching_test.rb
+++ b/Library/Homebrew/test/patching_test.rb
@@ -20,11 +20,6 @@ class PatchingTests < Homebrew::TestCase
     end
   end
 
-  def teardown
-    @_f.clear_cache
-    @_f.patchlist.each { |p| p.clear_cache if p.external? }
-  end
-
   def assert_patched(formula)
     shutup do
       formula.brew do
diff --git a/Library/Homebrew/test/pathname_test.rb b/Library/Homebrew/test/pathname_test.rb
index 2f6360719b..b48a26fbd3 100644
--- a/Library/Homebrew/test/pathname_test.rb
+++ b/Library/Homebrew/test/pathname_test.rb
@@ -7,16 +7,12 @@ module PathnameTestExtension
   include FileUtils
 
   def setup
+    super
     @src  = Pathname.new(mktmpdir)
     @dst  = Pathname.new(mktmpdir)
     @file = @src/"foo"
     @dir  = @src/"bar"
   end
-
-  def teardown
-    rmtree(@src)
-    rmtree(@dst)
-  end
 end
 
 class PathnameTests < Homebrew::TestCase
diff --git a/Library/Homebrew/test/resource_test.rb b/Library/Homebrew/test/resource_test.rb
index c1b526cb2c..d982a7c337 100644
--- a/Library/Homebrew/test/resource_test.rb
+++ b/Library/Homebrew/test/resource_test.rb
@@ -3,6 +3,7 @@ require "resource"
 
 class ResourceTests < Homebrew::TestCase
   def setup
+    super
     @resource = Resource.new("test")
   end
 
diff --git a/Library/Homebrew/test/sandbox_test.rb b/Library/Homebrew/test/sandbox_test.rb
index 2a062cb10f..a633defce2 100644
--- a/Library/Homebrew/test/sandbox_test.rb
+++ b/Library/Homebrew/test/sandbox_test.rb
@@ -3,26 +3,23 @@ require "sandbox"
 
 class SandboxTest < Homebrew::TestCase
   def setup
+    super
     skip "sandbox not implemented" unless Sandbox.available?
     @sandbox = Sandbox.new
     @dir = Pathname.new(mktmpdir)
     @file = @dir/"foo"
   end
 
-  def teardown
-    @dir.rmtree
-  end
-
   def test_formula?
     f = formula { url "foo-1.0" }
     f2 = formula { url "bar-1.0" }
     f2.stubs(:tap).returns(Tap.fetch("test/tap"))
 
-    ARGV.stubs(:sandbox?).returns true
+    ENV["HOMEBREW_SANDBOX"] = "1"
     assert Sandbox.formula?(f),
       "Formulae should be sandboxed if --sandbox was passed."
 
-    ARGV.stubs(:sandbox?).returns false
+    ENV.delete("HOMEBREW_SANDBOX")
     assert Sandbox.formula?(f),
       "Formulae should be sandboxed if in a sandboxed tap."
     refute Sandbox.formula?(f2),
@@ -30,7 +27,7 @@ class SandboxTest < Homebrew::TestCase
   end
 
   def test_test?
-    ARGV.stubs(:no_sandbox?).returns false
+    ENV.delete("HOMEBREW_NO_SANDBOX")
     assert Sandbox.test?,
       "Tests should be sandboxed unless --no-sandbox was passed."
   end
@@ -50,7 +47,7 @@ class SandboxTest < Homebrew::TestCase
 
   def test_complains_on_failure
     Utils.expects(popen_read: "foo")
-    ARGV.stubs(verbose?: true)
+    ENV["HOMEBREW_VERBOSE"] = "1"
     out, _err = capture_io do
       assert_raises(ErrorDuringExecution) { @sandbox.exec "false" }
     end
@@ -64,7 +61,7 @@ class SandboxTest < Homebrew::TestCase
       bar
     EOS
     Utils.expects(popen_read: with_bogus_error)
-    ARGV.stubs(verbose?: true)
+    ENV["HOMEBREW_VERBOSE"] = "1"
     out, _err = capture_io do
       assert_raises(ErrorDuringExecution) { @sandbox.exec "false" }
     end
diff --git a/Library/Homebrew/test/shell_test.rb b/Library/Homebrew/test/shell_test.rb
index 877acb5c8b..a32d098638 100644
--- a/Library/Homebrew/test/shell_test.rb
+++ b/Library/Homebrew/test/shell_test.rb
@@ -37,7 +37,6 @@ class ShellSmokeTest < Homebrew::TestCase
   end
 
   def prepend_path_shell(shell, path, fragment)
-    original_shell = ENV["SHELL"]
     ENV["SHELL"] = shell
 
     prepend_message = Utils::Shell.prepend_path_in_shell_profile(path)
@@ -45,8 +44,6 @@ class ShellSmokeTest < Homebrew::TestCase
       prepend_message.start_with?(fragment),
       "#{shell}: expected #{prepend_message} to match #{fragment}"
     )
-
-    ENV["SHELL"] = original_shell
   end
 
   def test_prepend_path_in_shell_profile
diff --git a/Library/Homebrew/test/software_spec_test.rb b/Library/Homebrew/test/software_spec_test.rb
index d9226f8c34..026265a4a1 100644
--- a/Library/Homebrew/test/software_spec_test.rb
+++ b/Library/Homebrew/test/software_spec_test.rb
@@ -3,6 +3,7 @@ require "software_spec"
 
 class SoftwareSpecTests < Homebrew::TestCase
   def setup
+    super
     @spec = SoftwareSpec.new
   end
 
@@ -136,6 +137,7 @@ end
 
 class HeadSoftwareSpecTests < Homebrew::TestCase
   def setup
+    super
     @spec = HeadSoftwareSpec.new
   end
 
@@ -150,6 +152,7 @@ end
 
 class BottleSpecificationTests < Homebrew::TestCase
   def setup
+    super
     @spec = BottleSpecification.new
   end
 
diff --git a/Library/Homebrew/test/stdlib_test.rb b/Library/Homebrew/test/stdlib_test.rb
index ee53e7c8cd..f193ae71e9 100644
--- a/Library/Homebrew/test/stdlib_test.rb
+++ b/Library/Homebrew/test/stdlib_test.rb
@@ -4,9 +4,11 @@ require "cxxstdlib"
 
 class CxxStdlibTests < Homebrew::TestCase
   def setup
+    super
     @clang = CxxStdlib.create(:libstdcxx, :clang)
     @gcc   = CxxStdlib.create(:libstdcxx, :gcc)
-    @gcc4  = CxxStdlib.create(:libstdcxx, :gcc_4_0)
+    @gcc40 = CxxStdlib.create(:libstdcxx, :gcc_4_0)
+    @gcc42 = CxxStdlib.create(:libstdcxx, :gcc_4_2)
     @gcc48 = CxxStdlib.create(:libstdcxx, "gcc-4.8")
     @gcc49 = CxxStdlib.create(:libstdcxx, "gcc-4.9")
     @lcxx  = CxxStdlib.create(:libcxx, :clang)
@@ -15,7 +17,7 @@ class CxxStdlibTests < Homebrew::TestCase
 
   def test_apple_libstdcxx_intercompatibility
     assert @clang.compatible_with?(@gcc)
-    assert @clang.compatible_with?(@gcc4)
+    assert @clang.compatible_with?(@gcc42)
   end
 
   def test_compatibility_same_compilers_and_type
@@ -42,7 +44,7 @@ class CxxStdlibTests < Homebrew::TestCase
   def test_apple_compiler_reporting
     assert_predicate @clang, :apple_compiler?
     assert_predicate @gcc, :apple_compiler?
-    assert_predicate @gcc4, :apple_compiler?
+    assert_predicate @gcc42, :apple_compiler?
     refute_predicate @gcc48, :apple_compiler?
   end
 
diff --git a/Library/Homebrew/test/support/fixtures/receipt.json b/Library/Homebrew/test/support/fixtures/receipt.json
index b20626bbe2..a57d6d80d2 100644
--- a/Library/Homebrew/test/support/fixtures/receipt.json
+++ b/Library/Homebrew/test/support/fixtures/receipt.json
@@ -1,4 +1,5 @@
 {
+  "homebrew_version": "1.1.6",
   "used_options": [
     "--with-foo",
     "--without-bar"
diff --git a/Library/Homebrew/test/support/helper/env.rb b/Library/Homebrew/test/support/helper/env.rb
deleted file mode 100644
index 904a1d4c71..0000000000
--- a/Library/Homebrew/test/support/helper/env.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-module Test
-  module Helper
-    module Env
-      def with_environment(partial_env)
-        old = ENV.to_hash
-        ENV.update partial_env
-        begin
-          yield
-        ensure
-          ENV.replace old
-        end
-      end
-    end
-  end
-end
diff --git a/Library/Homebrew/test/support/helper/integration_command_test_case.rb b/Library/Homebrew/test/support/helper/integration_command_test_case.rb
index b79fdd6e0d..a36b566916 100644
--- a/Library/Homebrew/test/support/helper/integration_command_test_case.rb
+++ b/Library/Homebrew/test/support/helper/integration_command_test_case.rb
@@ -6,40 +6,12 @@ require "test/support/helper/test_case"
 
 class IntegrationCommandTestCase < Homebrew::TestCase
   def setup
+    super
     @cmd_id_index = 0 # Assign unique IDs to invocations of `cmd_output`.
     (HOMEBREW_PREFIX/"bin").mkpath
     FileUtils.touch HOMEBREW_PREFIX/"bin/brew"
   end
 
-  def teardown
-    coretap = CoreTap.new
-    paths_to_delete = [
-      HOMEBREW_LINKED_KEGS,
-      HOMEBREW_PINNED_KEGS,
-      HOMEBREW_CELLAR.children,
-      HOMEBREW_CACHE.children,
-      HOMEBREW_LOCK_DIR.children,
-      HOMEBREW_LOGS.children,
-      HOMEBREW_TEMP.children,
-      HOMEBREW_PREFIX/".git",
-      HOMEBREW_PREFIX/"bin",
-      HOMEBREW_PREFIX/"share",
-      HOMEBREW_PREFIX/"opt",
-      HOMEBREW_PREFIX/"Caskroom",
-      HOMEBREW_LIBRARY/"Taps/caskroom",
-      HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle",
-      HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo",
-      HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services",
-      HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-shallow",
-      HOMEBREW_REPOSITORY/".git",
-      coretap.path/".git",
-      coretap.alias_dir,
-      coretap.formula_dir.children,
-      coretap.path/"formula_renames.json",
-    ].flatten
-    FileUtils.rm_rf paths_to_delete
-  end
-
   def needs_test_cmd_taps
     return if ENV["HOMEBREW_TEST_OFFICIAL_CMD_TAPS"]
     skip "HOMEBREW_TEST_OFFICIAL_CMD_TAPS is not set"
@@ -106,16 +78,20 @@ class IntegrationCommandTestCase < Homebrew::TestCase
   def cmd(*args)
     output = cmd_output(*args)
     status = $?.exitstatus
-    puts "\n'brew #{args.join " "}' output: #{output}" if status.nonzero?
-    assert_equal 0, status
+    assert_equal 0, status, <<-EOS.undent
+      `brew #{args.join " "}` exited with non-zero status!
+      #{output}
+    EOS
     output
   end
 
   def cmd_fail(*args)
     output = cmd_output(*args)
     status = $?.exitstatus
-    $stderr.puts "\n'brew #{args.join " "}'" if status.zero?
-    refute_equal 0, status
+    refute_equal 0, status, <<-EOS.undent
+      `brew #{args.join " "}` exited with zero status!
+      #{output}
+    EOS
     output
   end
 
diff --git a/Library/Homebrew/test/support/helper/lifecycle_enforcer.rb b/Library/Homebrew/test/support/helper/lifecycle_enforcer.rb
new file mode 100644
index 0000000000..413f8b11e7
--- /dev/null
+++ b/Library/Homebrew/test/support/helper/lifecycle_enforcer.rb
@@ -0,0 +1,22 @@
+module Test
+  module Helper
+    module LifecycleEnforcer
+      def setup
+        @__setup_called = true
+        super
+      end
+
+      def teardown
+        @__teardown_called = true
+        super
+      end
+
+      def after_teardown
+        assert @__setup_called, "Expected setup to call `super` but didn't"
+        assert @__teardown_called, "Expected teardown to call `super` but didn't"
+
+        super
+      end
+    end
+  end
+end
diff --git a/Library/Homebrew/test/support/helper/test_case.rb b/Library/Homebrew/test/support/helper/test_case.rb
index 60c91e7bb3..ab97ef7589 100644
--- a/Library/Homebrew/test/support/helper/test_case.rb
+++ b/Library/Homebrew/test/support/helper/test_case.rb
@@ -1,17 +1,60 @@
 module Homebrew
   class TestCase < ::Minitest::Test
-    require "test/support/helper/env"
     require "test/support/helper/fs_leak_logger"
+    require "test/support/helper/lifecycle_enforcer"
     require "test/support/helper/shutup"
     require "test/support/helper/version_assertions"
-    include Test::Helper::Env
     include Test::Helper::FSLeakLogger
+    include Test::Helper::LifecycleEnforcer
     include Test::Helper::Shutup
     include Test::Helper::VersionAssertions
 
     TEST_SHA1   = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef".freeze
     TEST_SHA256 = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".freeze
 
+    def setup
+      super
+
+      @__argv = ARGV.dup
+      @__env = ENV.to_hash # dup doesn't work on ENV
+    end
+
+    def teardown
+      ARGV.replace(@__argv)
+      ENV.replace(@__env)
+
+      Tab.clear_cache
+
+      coretap = CoreTap.new
+      paths_to_delete = [
+        HOMEBREW_LINKED_KEGS,
+        HOMEBREW_PINNED_KEGS,
+        HOMEBREW_CELLAR.children,
+        HOMEBREW_CACHE.children,
+        HOMEBREW_LOCK_DIR.children,
+        HOMEBREW_LOGS.children,
+        HOMEBREW_TEMP.children,
+        HOMEBREW_PREFIX/".git",
+        HOMEBREW_PREFIX/"bin",
+        HOMEBREW_PREFIX/"share",
+        HOMEBREW_PREFIX/"opt",
+        HOMEBREW_PREFIX/"Caskroom",
+        HOMEBREW_LIBRARY/"Taps/caskroom",
+        HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle",
+        HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo",
+        HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services",
+        HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-shallow",
+        HOMEBREW_REPOSITORY/".git",
+        coretap.path/".git",
+        coretap.alias_dir,
+        coretap.formula_dir.children,
+        coretap.path/"formula_renames.json",
+      ].flatten
+      FileUtils.rm_rf paths_to_delete
+
+      super
+    end
+
     def formula(name = "formula_name", path = Formulary.core_path(name), spec = :stable, alias_path: nil, &block)
       @_f = Class.new(Formula, &block).new(name, path, spec, alias_path: alias_path)
     end
diff --git a/Library/Homebrew/test/tab_test.rb b/Library/Homebrew/test/tab_test.rb
index 5d83b5907f..f6f55348d1 100644
--- a/Library/Homebrew/test/tab_test.rb
+++ b/Library/Homebrew/test/tab_test.rb
@@ -4,6 +4,8 @@ require "formula"
 
 class TabTests < Homebrew::TestCase
   def setup
+    super
+
     @used = Options.create(%w[--with-foo --without-bar])
     @unused = Options.create(%w[--with-baz --without-qux])
 
@@ -32,6 +34,8 @@ class TabTests < Homebrew::TestCase
 
   def test_defaults
     tab = Tab.empty
+
+    assert_equal HOMEBREW_VERSION, tab.homebrew_version
     assert_empty tab.unused_options
     assert_empty tab.used_options
     assert_nil tab.changed_files
@@ -69,6 +73,49 @@ class TabTests < Homebrew::TestCase
     assert_predicate tab, :universal?
   end
 
+  def test_parsed_homebrew_version
+    tab = Tab.new
+    assert_same Version::NULL, tab.parsed_homebrew_version
+
+    tab = Tab.new(homebrew_version: "1.2.3")
+    assert_equal "1.2.3", tab.parsed_homebrew_version
+    assert tab.parsed_homebrew_version < "1.2.3-1-g12789abdf"
+    assert_kind_of Version, tab.parsed_homebrew_version
+
+    tab.homebrew_version = "1.2.4-567-g12789abdf"
+    assert tab.parsed_homebrew_version > "1.2.4"
+    assert tab.parsed_homebrew_version > "1.2.4-566-g21789abdf"
+    assert tab.parsed_homebrew_version < "1.2.4-568-g01789abdf"
+
+    tab = Tab.new(homebrew_version: "2.0.0-134-gabcdefabc-dirty")
+    assert tab.parsed_homebrew_version > "2.0.0"
+    assert tab.parsed_homebrew_version > "2.0.0-133-g21789abdf"
+    assert tab.parsed_homebrew_version < "2.0.0-135-g01789abdf"
+  end
+
+  def test_runtime_dependencies
+    tab = Tab.new
+    assert_nil tab.runtime_dependencies
+
+    tab.homebrew_version = "1.1.6"
+    assert_nil tab.runtime_dependencies
+
+    tab.runtime_dependencies = []
+    refute_nil tab.runtime_dependencies
+
+    tab.homebrew_version = "1.1.5"
+    assert_nil tab.runtime_dependencies
+
+    tab.homebrew_version = "1.1.7"
+    refute_nil tab.runtime_dependencies
+
+    tab.homebrew_version = "1.1.10"
+    refute_nil tab.runtime_dependencies
+
+    tab.runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }]
+    refute_nil tab.runtime_dependencies
+  end
+
   def test_cxxstdlib
     assert_equal :clang, @tab.cxxstdlib.compiler
     assert_equal :libcxx, @tab.cxxstdlib.type
@@ -215,16 +262,13 @@ end
 
 class TabLoadingTests < Homebrew::TestCase
   def setup
+    super
     @f = formula { url "foo-1.0" }
     @f.prefix.mkpath
     @path = @f.prefix.join(Tab::FILENAME)
     @path.write TEST_FIXTURE_DIR.join("receipt.json").read
   end
 
-  def teardown
-    @f.rack.rmtree
-  end
-
   def test_for_keg
     tab = Tab.for_keg(@f.prefix)
     assert_equal @path, tab.tabfile
diff --git a/Library/Homebrew/test/tap_test.rb b/Library/Homebrew/test/tap_test.rb
index b950cd1666..578326cea8 100644
--- a/Library/Homebrew/test/tap_test.rb
+++ b/Library/Homebrew/test/tap_test.rb
@@ -16,7 +16,7 @@ class IntegrationCommandTestTap < IntegrationCommandTestCase
     end
 
     assert_match "homebrew/foo", cmd("tap")
-    assert_match "homebrew/versions", cmd("tap", "--list-official")
+    assert_match "homebrew/science", cmd("tap", "--list-official")
     assert_match "2 taps", cmd("tap-info")
     assert_match "https://github.com/Homebrew/homebrew-foo", cmd("tap-info", "homebrew/foo")
     assert_match "https://github.com/Homebrew/homebrew-foo", cmd("tap-info", "--json=v1", "--installed")
@@ -34,6 +34,7 @@ class TapTest < Homebrew::TestCase
   include FileUtils
 
   def setup
+    super
     @path = Tap::TAP_DIRECTORY/"homebrew/homebrew-foo"
     @path.mkpath
     @tap = Tap.new("Homebrew", "foo")
@@ -65,13 +66,6 @@ class TapTest < Homebrew::TestCase
   end
 
   def setup_git_repo
-    env = ENV.to_hash
-    %w[AUTHOR COMMITTER].each do |role|
-      ENV["GIT_#{role}_NAME"] = "brew tests"
-      ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost"
-      ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100"
-    end
-
     @path.cd do
       shutup do
         system "git", "init"
@@ -80,12 +74,6 @@ class TapTest < Homebrew::TestCase
         system "git", "commit", "-m", "init"
       end
     end
-  ensure
-    ENV.replace(env)
-  end
-
-  def teardown
-    @path.rmtree
   end
 
   def test_fetch
@@ -162,17 +150,15 @@ class TapTest < Homebrew::TestCase
     assert_raises(TapUnavailableError) { Tap.new("Homebrew", "bar").remote }
     refute_predicate @tap, :custom_remote?
 
-    version_tap = Tap.new("Homebrew", "versions")
-    version_tap.path.mkpath
-    version_tap.path.cd do
+    services_tap = Tap.new("Homebrew", "services")
+    services_tap.path.mkpath
+    services_tap.path.cd do
       shutup do
         system "git", "init"
-        system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-versions"
+        system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-services"
       end
     end
-    refute_predicate version_tap, :private?
-  ensure
-    version_tap.path.rmtree if version_tap
+    refute_predicate services_tap, :private?
   end
 
   def test_remote_not_git_repo
@@ -189,10 +175,10 @@ class TapTest < Homebrew::TestCase
     touch @path/"README"
     setup_git_repo
 
-    assert_equal "e1893a6bd191ba895c71b652ff8376a6114c7fa7", @tap.git_head
-    assert_equal "e189", @tap.git_short_head
-    assert_match "years ago", @tap.git_last_commit
-    assert_equal "2009-05-21", @tap.git_last_commit_date
+    assert_equal "0453e16c8e3fac73104da50927a86221ca0740c2", @tap.git_head
+    assert_equal "0453", @tap.git_short_head
+    assert_match(/\A\d+ .+ ago\Z/, @tap.git_last_commit)
+    assert_equal "2017-01-22", @tap.git_last_commit_date
   end
 
   def test_private_remote
@@ -256,8 +242,6 @@ class TapTest < Homebrew::TestCase
     refute_predicate tap, :installed?
     refute_predicate HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1", :exist?
     refute_predicate HOMEBREW_PREFIX/"share/man/man1", :exist?
-  ensure
-    (HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
   end
 
   def test_pin_and_unpin
@@ -285,6 +269,7 @@ class CoreTapTest < Homebrew::TestCase
   include FileUtils
 
   def setup
+    super
     @repo = CoreTap.new
   end
 
@@ -322,8 +307,5 @@ class CoreTapTest < Homebrew::TestCase
     assert_equal ["bar"], @repo.aliases
     assert_equal @repo.alias_table, "bar" => "foo"
     assert_equal @repo.alias_reverse_table, "foo" => ["bar"]
-  ensure
-    @formula_file.unlink
-    @repo.alias_dir.rmtree
   end
 end
diff --git a/Library/Homebrew/test/uninstall_test.rb b/Library/Homebrew/test/uninstall_test.rb
index 5c53988f24..2f8bf4fffc 100644
--- a/Library/Homebrew/test/uninstall_test.rb
+++ b/Library/Homebrew/test/uninstall_test.rb
@@ -3,15 +3,21 @@ require "cmd/uninstall"
 
 class UninstallTests < Homebrew::TestCase
   def setup
+    super
+
     @dependency = formula("dependency") { url "f-1" }
     @dependent = formula("dependent") do
       url "f-1"
       depends_on "dependency"
     end
 
-    [@dependency, @dependent].each { |f| f.installed_prefix.mkpath }
+    [@dependency, @dependent].each do |f|
+      f.installed_prefix.mkpath
+      Keg.new(f.installed_prefix).optlink
+    end
 
     tab = Tab.empty
+    tab.homebrew_version = "1.1.6"
     tab.tabfile = @dependent.installed_prefix/Tab::FILENAME
     tab.runtime_dependencies = [
       { "full_name" => "dependency", "version" => "1" },
@@ -24,7 +30,7 @@ class UninstallTests < Homebrew::TestCase
 
   def teardown
     Homebrew.failed = false
-    [@dependency, @dependent].each { |f| f.rack.rmtree }
+    super
   end
 
   def handle_unsatisfied_dependents
@@ -52,8 +58,6 @@ class UninstallTests < Homebrew::TestCase
       assert_empty handle_unsatisfied_dependents
       refute_predicate Homebrew, :failed?
     end
-  ensure
-    ARGV.delete("--ignore-dependencies")
   end
 end
 
diff --git a/Library/Homebrew/test/update_report_test.rb b/Library/Homebrew/test/update_report_test.rb
index 6b6cec6ce0..32c3e36d0a 100644
--- a/Library/Homebrew/test/update_report_test.rb
+++ b/Library/Homebrew/test/update_report_test.rb
@@ -24,6 +24,7 @@ class ReportTests < Homebrew::TestCase
   end
 
   def setup
+    super
     @tap = CoreTap.new
     @reporter = ReporterMock.new(@tap)
     @hub = ReporterHub.new
diff --git a/Library/Homebrew/test/utils_test.rb b/Library/Homebrew/test/utils_test.rb
index 146f57b495..1f2fb7b55f 100644
--- a/Library/Homebrew/test/utils_test.rb
+++ b/Library/Homebrew/test/utils_test.rb
@@ -5,13 +5,12 @@ require "utils/shell"
 
 class UtilTests < Homebrew::TestCase
   def setup
+    super
     @dir = Pathname.new(mktmpdir)
-    @env = ENV.to_hash
   end
 
-  def teardown
-    @dir.rmtree
-    ENV.replace @env
+  def esc(code)
+    /(\e\[\d+m)*\e\[#{code}m/
   end
 
   def test_ofail
@@ -27,11 +26,29 @@ class UtilTests < Homebrew::TestCase
   end
 
   def test_pretty_installed
+    $stdout.stubs(:tty?).returns true
+    ENV.delete("HOMEBREW_NO_EMOJI")
+    tty_with_emoji_output = /\A#{esc 1}foo #{esc 32}✔#{esc 0}\Z/
+    assert_match tty_with_emoji_output, pretty_installed("foo")
+
+    ENV["HOMEBREW_NO_EMOJI"] = "1"
+    tty_no_emoji_output = /\A#{esc 1}foo \(installed\)#{esc 0}\Z/
+    assert_match tty_no_emoji_output, pretty_installed("foo")
+
     $stdout.stubs(:tty?).returns false
     assert_equal "foo", pretty_installed("foo")
   end
 
   def test_pretty_uninstalled
+    $stdout.stubs(:tty?).returns true
+    ENV.delete("HOMEBREW_NO_EMOJI")
+    tty_with_emoji_output = /\A#{esc 1}foo #{esc 31}✘#{esc 0}\Z/
+    assert_match tty_with_emoji_output, pretty_uninstalled("foo")
+
+    ENV["HOMEBREW_NO_EMOJI"] = "1"
+    tty_no_emoji_output = /\A#{esc 1}foo \(uninstalled\)#{esc 0}\Z/
+    assert_match tty_no_emoji_output, pretty_uninstalled("foo")
+
     $stdout.stubs(:tty?).returns false
     assert_equal "foo", pretty_uninstalled("foo")
   end
@@ -212,11 +229,11 @@ class UtilTests < Homebrew::TestCase
   end
 
   def test_odeprecated
-    ARGV.stubs(:homebrew_developer?).returns false
+    ENV.delete("HOMEBREW_DEVELOPER")
     e = assert_raises(MethodDeprecatedError) do
       odeprecated("method", "replacement",
         caller: ["#{HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core/"],
-        die: true)
+        disable: true)
     end
     assert_match "method", e.message
     assert_match "replacement", e.message
diff --git a/Library/Homebrew/test/versions_test.rb b/Library/Homebrew/test/versions_test.rb
index a6e922178f..b6814b1d19 100644
--- a/Library/Homebrew/test/versions_test.rb
+++ b/Library/Homebrew/test/versions_test.rb
@@ -185,8 +185,6 @@ class VersionParsingTests < Homebrew::TestCase
     d = HOMEBREW_CELLAR/"foo-0.1.9"
     d.mkpath
     assert_equal version("0.1.9"), d.version
-  ensure
-    d.unlink
   end
 
   def test_no_version
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index 4ad97c7d48..70d2787d97 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -11,6 +11,7 @@ require "utils/hash"
 require "utils/inreplace"
 require "utils/popen"
 require "utils/tty"
+require "time"
 
 def ohai(title, *sput)
   title = Tty.truncate(title) if $stdout.tty? && !ARGV.verbose?
@@ -44,24 +45,32 @@ def odie(error)
   exit 1
 end
 
-def odeprecated(method, replacement = nil, options = {})
-  verb = if options[:die]
-    "disabled"
-  else
-    "deprecated"
-  end
-
+def odeprecated(method, replacement = nil, disable: false, disable_on: nil, caller: send(:caller))
   replacement_message = if replacement
     "Use #{replacement} instead."
   else
     "There is no replacement."
   end
 
+  unless disable_on.nil?
+    if disable_on > Time.now
+      will_be_disabled_message = " and will be disabled on #{disable_on.strftime("%Y-%m-%d")}"
+    else
+      disable = true
+    end
+  end
+
+  verb = if disable
+    "disabled"
+  else
+    "deprecated#{will_be_disabled_message}"
+  end
+
   # Try to show the most relevant location in message, i.e. (if applicable):
   # - Location in a formula.
   # - Location outside of 'compat/'.
   # - Location of caller of deprecated method (if all else fails).
-  backtrace = options.fetch(:caller, caller)
+  backtrace = caller
   tap_message = nil
   caller_message = backtrace.detect do |line|
     next unless line =~ %r{^#{Regexp.escape HOMEBREW_LIBRARY}/Taps/([^/]+/[^/]+)/}
@@ -80,7 +89,7 @@ def odeprecated(method, replacement = nil, options = {})
     #{caller_message}#{tap_message}
   EOS
 
-  if ARGV.homebrew_developer? || options[:die] ||
+  if ARGV.homebrew_developer? || disable ||
      Homebrew.raise_deprecation_exceptions?
     raise MethodDeprecatedError, message
   else
@@ -89,7 +98,7 @@ def odeprecated(method, replacement = nil, options = {})
 end
 
 def odisabled(method, replacement = nil, options = {})
-  options = { die: true, caller: caller }.merge(options)
+  options = { disable: true, caller: caller }.merge(options)
   odeprecated(method, replacement, options)
 end
 
@@ -97,7 +106,7 @@ def pretty_installed(f)
   if !$stdout.tty?
     f.to_s
   elsif Emoji.enabled?
-    "#{Tty.bold}#{f} #{Formatter.success(Emoji.tick)}#{Tty.reset}"
+    "#{Tty.bold}#{f} #{Formatter.success("✔")}#{Tty.reset}"
   else
     Formatter.success("#{Tty.bold}#{f} (installed)#{Tty.reset}")
   end
@@ -107,7 +116,7 @@ def pretty_uninstalled(f)
   if !$stdout.tty?
     f.to_s
   elsif Emoji.enabled?
-    "#{Tty.bold}#{f} #{Formatter.error(Emoji.cross)}#{Tty.reset}"
+    "#{Tty.bold}#{f} #{Formatter.error("✘")}#{Tty.reset}"
   else
     Formatter.error("#{Tty.bold}#{f} (uninstalled)#{Tty.reset}")
   end
diff --git a/Library/Homebrew/utils/analytics.rb b/Library/Homebrew/utils/analytics.rb
index cc7ad54d27..7dd54d3f14 100644
--- a/Library/Homebrew/utils/analytics.rb
+++ b/Library/Homebrew/utils/analytics.rb
@@ -35,7 +35,7 @@ module Utils
         end
 
         # Send analytics. Don't send or store any personally identifiable information.
-        # https://github.com/Homebrew/brew/blob/master/docs/Analytics.md
+        # http://docs.brew.sh/Analytics.html
         # https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide
         # https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
         if ENV["HOMEBREW_ANALYTICS_DEBUG"]
diff --git a/Library/Homebrew/utils/analytics.sh b/Library/Homebrew/utils/analytics.sh
index 0f188fe9b1..35f91eabc0 100644
--- a/Library/Homebrew/utils/analytics.sh
+++ b/Library/Homebrew/utils/analytics.sh
@@ -107,7 +107,7 @@ report-analytics-screenview-command() {
   )
 
   # Send analytics. Don't send or store any personally identifiable information.
-  # https://github.com/Homebrew/brew/blob/master/docs/Analytics.md
+  # http://docs.brew.sh/Analytics.html
   # https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide#screenView
   # https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
   if [[ -z "$HOMEBREW_ANALYTICS_DEBUG" ]]
diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb
index 00c3a591cd..5a40ae8469 100644
--- a/Library/Homebrew/utils/curl.rb
+++ b/Library/Homebrew/utils/curl.rb
@@ -1,27 +1,41 @@
 require "pathname"
 require "open3"
 
-def curl_args(extra_args = [])
+def curl_args(options = {})
   curl = Pathname.new ENV["HOMEBREW_CURL"]
   curl = Pathname.new "/usr/bin/curl" unless curl.exist?
   raise "#{curl} is not executable" unless curl.exist? && curl.executable?
 
-  flags = HOMEBREW_CURL_ARGS
-  flags -= ["--progress-bar"] if ARGV.verbose?
+  args = [
+    curl.to_s,
+    "--remote-time",
+    "--location",
+  ]
 
-  args = [curl.to_s] + flags + extra_args
-  args << "--verbose" if ENV["HOMEBREW_CURL_VERBOSE"]
-  args << "--silent" if !$stdout.tty? || ENV["TRAVIS"]
+  case options[:user_agent]
+  when :browser
+    args << "--user-agent" << HOMEBREW_USER_AGENT_FAKE_SAFARI
+  else
+    args << "--user-agent" << HOMEBREW_USER_AGENT_CURL
+  end
+
+  unless options[:show_output]
+    args << "--progress-bar" unless ARGV.verbose?
+    args << "--verbose" if ENV["HOMEBREW_CURL_VERBOSE"]
+    args << "--fail"
+    args << "--silent" if !$stdout.tty? || ENV["TRAVIS"]
+  end
+
+  args += options[:extra_args] if options[:extra_args]
   args
 end
 
 def curl(*args)
-  safe_system(*curl_args(args))
+  safe_system(*curl_args(extra_args: args))
 end
 
 def curl_output(*args)
-  curl_args = curl_args(args)
-  curl_args -= ["--fail", "--silent"]
+  curl_args = curl_args(extra_args: args, show_output: true)
   Open3.popen3(*curl_args) do |_, stdout, stderr, wait_thread|
     [stdout.read, stderr.read, wait_thread.value]
   end
diff --git a/Library/Homebrew/utils/inreplace.rb b/Library/Homebrew/utils/inreplace.rb
index c7557ab41d..b4c219f064 100644
--- a/Library/Homebrew/utils/inreplace.rb
+++ b/Library/Homebrew/utils/inreplace.rb
@@ -1,9 +1,10 @@
 module Utils
   class InreplaceError < RuntimeError
     def initialize(errors)
-      super errors.inject("inreplace failed\n") do |s, (path, errs)|
+      formatted_errors = errors.inject("inreplace failed\n") do |s, (path, errs)|
         s << "#{path}:\n" << errs.map { |e| "  #{e}\n" }.join
       end
+      super formatted_errors
     end
   end
 
diff --git a/README.md b/README.md
index 8e3efd1fdb..940b49878f 100644
--- a/README.md
+++ b/README.md
@@ -13,12 +13,12 @@ cd "$(brew --repo)" && git fetch && git reset --hard origin/master && brew updat
 3. Or use `brew search --desc ` to browse packages from the command line.
 
 ## More Documentation
-`brew help`, `man brew` or check [our documentation](https://github.com/Homebrew/brew/tree/master/docs#readme).
+`brew help`, `man brew` or check [our documentation](https://brew.sh/brew/).
 
 ## Troubleshooting
 First, please run `brew update` and `brew doctor`.
 
-Second, read the [Troubleshooting Checklist](https://github.com/Homebrew/brew/blob/master/docs/Troubleshooting.md#troubleshooting).
+Second, read the [Troubleshooting Checklist](http://docs.brew.sh/Troubleshooting.html).
 
 **If you don't read these it will take us far longer to help you with your problem.**
 
@@ -27,7 +27,7 @@ We'd love you to contribute to Homebrew. First, please read our [Contribution Gu
 
 We explicitly welcome contributions from people who have never contributed to open-source before: we were all beginners once! We can help build on a partially working pull request with the aim of getting it merged. We are also actively seeking to diversify our contributors and especially welcome contributions from women from all backgrounds and people of colour.
 
-A good starting point for contributing is running `brew audit` (or `brew audit --strict`) with some of the packages you use (e.g. `brew audit wget` if you use `wget`) and then read through the warnings, try to fix them until `brew audit` shows no results and [submit a pull request](https://github.com/Homebrew/brew/blob/master/docs/How-To-Open-a-Homebrew-Pull-Request-(and-get-it-merged).md). If no formulae you use have warnings you can run `brew audit` without arguments to have it run on all packages and pick one. Good luck!
+A good starting point for contributing is running `brew audit` (or `brew audit --strict`) with some of the packages you use (e.g. `brew audit wget` if you use `wget`) and then read through the warnings, try to fix them until `brew audit` shows no results and [submit a pull request](http://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request.html). If no formulae you use have warnings you can run `brew audit` without arguments to have it run on all packages and pick one. Good luck!
 
 ## Security
 Please report security issues to security@brew.sh.
@@ -40,9 +40,14 @@ This is our PGP key which is valid until May 24, 2017.
 ## Who Are You?
 Homebrew's lead maintainer is [Mike McQuaid](https://github.com/mikemcquaid).
 
-Homebrew's current maintainers are [Misty De Meo](https://github.com/mistydemeo), [Andrew Janke](https://github.com/apjanke), [Xu Cheng](https://github.com/xu-cheng), [Tomasz Pajor](https://github.com/nijikon), [Josh Hagins](https://github.com/jawshooah), [Baptiste Fontaine](https://github.com/bfontaine), [Markus Reiter](https://github.com/reitermarkus), [ilovezfs](https://github.com/ilovezfs), [Martin Afanasjew](https://github.com/UniqMartin), [Tom Schoonjans](https://github.com/tschoonj), [Uladzislau Shablinski](https://github.com/vladshablinsky), [Tim Smith](https://github.com/tdsmith) and [Alex Dunn](https://github.com/dunn).
+Homebrew's current maintainers are [Misty De Meo](https://github.com/mistydemeo), [Andrew Janke](https://github.com/apjanke), [Xu Cheng](https://github.com/xu-cheng), [Tomasz Pajor](https://github.com/nijikon), [Josh Hagins](https://github.com/jawshooah), [Baptiste Fontaine](https://github.com/bfontaine), [Markus Reiter](https://github.com/reitermarkus), [ilovezfs](https://github.com/ilovezfs), [Tom Schoonjans](https://github.com/tschoonj), [Uladzislau Shablinski](https://github.com/vladshablinsky), [Tim Smith](https://github.com/tdsmith) and [Alex Dunn](https://github.com/dunn).
 
-Former maintainers with significant contributions include [Dominyk Tiller](https://github.com/DomT4), [Brett Koonce](https://github.com/asparagui), [Jack Nagel](https://github.com/jacknagel), [Adam Vandenberg](https://github.com/adamv) and Homebrew's creator: [Max Howell](https://github.com/mxcl).
+Former maintainers with significant contributions include [Martin Afanasjew](https://github.com/UniqMartin), [Dominyk Tiller](https://github.com/DomT4), [Brett Koonce](https://github.com/asparagui), [Jack Nagel](https://github.com/jacknagel), [Adam Vandenberg](https://github.com/adamv) and Homebrew's creator: [Max Howell](https://github.com/mxcl).
+
+## Community
+- [discourse.brew.sh (forum)](http://discourse.brew.sh)
+- [freenode.net\#machomebrew (IRC)](irc://irc.freenode.net/#machomebrew)
+- [@MacHomebrew (Twitter)](https://twitter.com/MacHomebrew)
 
 ## License
 Code is under the [BSD 2-clause "Simplified" License](https://github.com/Homebrew/brew/tree/master/LICENSE.txt).
@@ -56,7 +61,7 @@ Please consider a regular donation through Patreon:
 [![Donate with Patreon](https://img.shields.io/badge/patreon-donate-green.svg)](https://www.patreon.com/homebrew)
 
 ## Sponsors
-Our CI infrastructure was paid for by [our Kickstarter supporters](https://github.com/Homebrew/brew/blob/master/docs/Kickstarter-Supporters.md).
+Our CI infrastructure was paid for by [our Kickstarter supporters](http://docs.brew.sh/Kickstarter-Supporters.html).
 
 Our CI infrastructure is hosted by [The Positive Internet Company](http://www.positive-internet.com).
 
diff --git a/completions/zsh/_brew_cask b/completions/zsh/_brew_cask
index bb64a2e32b..1e493fc2a6 100644
--- a/completions/zsh/_brew_cask
+++ b/completions/zsh/_brew_cask
@@ -43,7 +43,6 @@ __brew_cask_commands() {
     'search:searches all known Casks'
     'style:checks Cask style using RuboCop'
     'uninstall:uninstalls the given Cask'
-    "update:a synonym for 'brew update'"
     'zap:zaps all files associated with the given Cask'
   )
   _describe -t commands "brew cask command" commands
diff --git a/docs/.ruby-version b/docs/.ruby-version
new file mode 100644
index 0000000000..bec3a35ee8
--- /dev/null
+++ b/docs/.ruby-version
@@ -0,0 +1 @@
+system
diff --git a/docs/Acceptable-Formulae.md b/docs/Acceptable-Formulae.md
index b827403d8a..9f4fb45dba 100644
--- a/docs/Acceptable-Formulae.md
+++ b/docs/Acceptable-Formulae.md
@@ -1,4 +1,5 @@
 # Acceptable Formulae
+
 Some formulae should not go in
 [homebrew/core](https://github.com/Homebrew/homebrew-core). But there are
 additional [Interesting Taps & Forks](Interesting-Taps-&-Forks.md) and anyone can start their
@@ -29,16 +30,16 @@ There are exceptions:
 
 #### Examples
 
-  Formula         | Reason
-  ---             | ---
-  ruby, python, perl    | People want newer versions
-  bash            | macOS's bash is stuck at 3.2 because newer versions are licensed under GPLv3
-  zsh             | This was a mistake, but it’s too late to remove it
-  emacs, vim      | [Too popular to move to dupes](https://github.com/Homebrew/homebrew/pull/21594#issuecomment-21968819)
-  subversion      | Originally added for 10.5, but people want the latest version
-  libcurl         | Some formulae require a newer version than macOS provides
-  openssl         | macOS's openssl is deprecated & outdated.
-  libxml2         | Historically, macOS's libxml2 has been buggy
+| Formula            | Reason                                                                                                |
+|--------------------|-------------------------------------------------------------------------------------------------------|
+| ruby, python, perl | People want newer versions                                                                            |
+| bash               | macOS's bash is stuck at 3.2 because newer versions are licensed under GPLv3                          |
+| zsh                | This was a mistake, but it’s too late to remove it                                                    |
+| emacs, vim         | [Too popular to move to dupes](https://github.com/Homebrew/homebrew/pull/21594#issuecomment-21968819) |
+| subversion         | Originally added for 10.5, but people want the latest version                                         |
+| libcurl            | Some formulae require a newer version than macOS provides                                             |
+| openssl            | macOS's openssl is deprecated & outdated.                                                             |
+| libxml2            | Historically, macOS's libxml2 has been buggy                                                          |
 
 We also maintain [a tap](https://github.com/Homebrew/homebrew-dupes) that
 contains many duplicates not otherwise found in Homebrew.
@@ -67,12 +68,8 @@ Formulae in the core repository must have a stable version tagged by
 the upstream project. Tarballs are preferred to git checkouts, and
 tarballs should include the version in the filename whenever possible.
 
-Software that only provides a development/beta, tagged version should be put in
-[homebrew/devel-only](https://github.com/Homebrew/homebrew-devel-only).
 We don’t accept software without a tagged version because they regularly break
-due to upstream changes; we can’t provide [bottles](Bottles.md) for them; and
-we don’t have an automatic update mechanism for `head-only` formulae which
-makes them very quickly outdated.
+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
@@ -84,7 +81,8 @@ useful to people. Just install the stuff! Having to faff around with
 foo-ruby foo-perl etc. sucks.
 
 ### Niche (or self-submitted) Stuff
-The software in question must be
+The software in question must be:
+
 * maintained (e.g. upstream is still making new releases)
 * known
 * stable (e.g. not declared "unstable" or "beta" by upstream)
diff --git a/docs/Analytics.md b/docs/Analytics.md
index 83386b3eea..b4e73f75df 100644
--- a/docs/Analytics.md
+++ b/docs/Analytics.md
@@ -1,4 +1,5 @@
-# Homebrew's Anonymous Aggregate User Behaviour Analytics
+# Anonymous Aggregate User Behaviour Analytics
+
 Homebrew has begun gathering anonymous aggregate user behaviour analytics and reporting these to Google Analytics. You will be notified the first time you run `brew update` or install Homebrew.
 
 ## Why?
@@ -41,7 +42,7 @@ Homebrew's analytics are sent throughout Homebrew's execution to Google Analytic
 Homebrew's analytics are accessible to Homebrew's current maintainers. Contact @mikemcquaid if you are a maintainer and need access.
 
 ## How?
-The code is viewable in https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils/analytics.rb and https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils/analytics.sh. They are done in a separate background process and fail fast to avoid delaying any execution. They will fail immediately and silently if you have no network connection.
+The code is viewable in [analytics.rb](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils/analytics.rb) and [analytics.sh](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils/analytics.sh). They are done in a separate background process and fail fast to avoid delaying any execution. They will fail immediately and silently if you have no network connection.
 
 ## Opting out
 Homebrew analytics helps us maintainers and leaving it on is appreciated. However, if you want to opt out of Homebrew's analytics, you can set this variable in your environment:
diff --git a/docs/Bottles.md b/docs/Bottles.md
index 196b36e1fb..2752ebe032 100644
--- a/docs/Bottles.md
+++ b/docs/Bottles.md
@@ -1,23 +1,25 @@
-# Bottles
-Bottles are Homebrew's binary packages. They are produced by installing a formula with `brew install --build-bottle $FORMULA` and then bottling it with `brew bottle $FORMULA`. This outputs the bottle DSL which should be inserted into the formula file.
+# Bottles (binary packages)
 
-## Bottle Usage
+Bottles are produced by installing a formula with `brew install --build-bottle $FORMULA` and then bottling it with `brew bottle $FORMULA`. This outputs the bottle DSL which should be inserted into the formula file.
+
+## Usage
 If a bottle is available and usable it will be downloaded and poured automatically when you `brew install `. If you wish to disable this you can do it by specifying `--build-from-source`.
 
 Bottles will not be used if the user requests it (see above), if the formula requests it (with `pour_bottle?`), if any options are specified on installation (bottles are all compiled with default options), if the bottle is not up to date (e.g. lacking a checksum) or the bottle's `cellar` is not `:any` or equal to the current `HOMEBREW_CELLAR`.
 
-## Bottle Creation
+## Creation
 Bottles are created using the [Brew Test Bot](Brew-Test-Bot.md). This happens mostly when people submit pull requests to Homebrew and the `bottle do` block is updated by maintainers when they `brew pull --bottle` the contents of a pull request. For the Homebrew organisations' taps they are uploaded to and downloaded from [Bintray](https://bintray.com/homebrew).
 
 By default, bottles will be built for the oldest CPU supported by the OS/architecture you're building for. (That's Core 2 for 64-bit OSs, Core for 32-bit.) This ensures that bottles are compatible with all computers you might distribute them to. If you *really* want your bottles to be optimized for something else, you can pass the `--bottle-arch=` option to build for another architecture - for example, `brew install foo --bottle-arch=penryn`. Just remember that if you build for a newer architecture some of your users might get binaries they can't run and that would be sad!
 
-## Bottle Format
+## Format
 Bottles are simple gzipped tarballs of compiled binaries. Any metadata is stored in a formula's bottle DSL and in the bottle filename (i.e. MacOS version, revision).
 
 ## Bottle DSL (Domain Specific Language)
 Bottles have a DSL to be used in formulae which is contained in the `bottle do ... end` block.
 
 A simple (and typical) example:
+
 ```ruby
 bottle do
   sha256 "4921af80137af9cc3d38fd17c9120da882448a090b0a8a3a19af3199b415bfca" => :sierra
@@ -27,6 +29,7 @@ end
 ```
 
 A full example:
+
 ```ruby
 bottle do
   root_url "https://example.com"
@@ -39,33 +42,34 @@ bottle do
 end
 ```
 
-### `root_url`
+### Root URL (`root_url`)
 Optionally contains the URL root used to calculate bottle URLs.
 By default this is omitted and the Homebrew default bottle URL root is used. This may be useful for taps which wish to provide bottles for their formulae or to cater for a non-default `HOMEBREW_CELLAR`.
 
-### `cellar`
+### Cellar (`cellar`)
 Optionally contains the value of `HOMEBREW_CELLAR` in which the bottles were built.
 Most compiled software contains references to its compiled location so cannot be simply relocated anywhere on disk. If this value is `:any` or `:any_skip_relocation` this means that the bottle can be safely installed in any Cellar as it did not contain any references to its installation Cellar. This can be omitted if a bottle is compiled (as all default Homebrew ones are) for the default `HOMEBREW_CELLAR` of `/usr/local/Cellar`
 
-### `prefix`
+### Prefix (`prefix`)
 Optionally contains the value of `HOMEBREW_PREFIX` in which the bottles were built.
 See description of `cellar`. When `cellar` is `:any` or `:any_skip_relocation` prefix should be omitted.
 
-### `rebuild`
+### Rebuild version (`rebuild`)
 Optionally contains the rebuild version of the bottle.
 Sometimes bottles may need be updated without bumping the version of the formula e.g. a new patch was applied. In that case the rebuild will have a value of 1 or more.
 
-### `sha256`
+### Checksum (`sha256`)
 Contains the SHA-256 of bottle for a particular version of macOS.
 
 ## Formula DSL
 Additionally there is a method available in the formula DSL.
 
-### `pour_bottle?`
+### Pour Bottle (`pour_bottle?`)
 Optionally returns a boolean to decide whether a bottle should be used for this formula.
 For example a bottle may break if another formula has been compiled with non-default options so this method could check for that case and return `false`.
 
 A full example:
+
 ```ruby
 pour_bottle? do
   reason "The bottle needs the Xcode CLT to be installed."
diff --git a/docs/Brew-Test-Bot-For-Core-Contributors.md b/docs/Brew-Test-Bot-For-Core-Contributors.md
index 8e264ea7e9..f4c9a0ec6e 100644
--- a/docs/Brew-Test-Bot-For-Core-Contributors.md
+++ b/docs/Brew-Test-Bot-For-Core-Contributors.md
@@ -1,10 +1,11 @@
 # Brew Test Bot For Core Contributors
+
 If a build has run and passed on `brew test-bot` then it can be used to quickly bottle formulae.
 
 There are two types of Jenkins jobs you will interact with:
 
 ## [Homebrew Pull Requests](https://bot.brew.sh/job/Homebrew%20Core%20Pull%20Requests/)
-This job automatically builds any pull requests submitted to Homebrew/homebrew-core. On success or failure it updates the pull request status (see more details on the [main Brew Test Bot wiki page](Brew-Test-Bot.md)). On a successful build it automatically uploads bottles.
+This job automatically builds any pull requests submitted to Homebrew/homebrew-core. On success or failure it updates the pull request status (see more details on the [main Brew Test Bot documentation page](Brew-Test-Bot.md)). On a successful build it automatically uploads bottles.
 
 ## [Homebrew Testing](https://bot.brew.sh/job/Homebrew%20Testing/)
 This job is manually triggered to run [`brew test-bot`](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/test-bot.rb) with user-specified parameters. On a successful build it automatically uploads bottles.
diff --git a/docs/Brew-Test-Bot.md b/docs/Brew-Test-Bot.md
index 0a5f76bda9..db39327fac 100644
--- a/docs/Brew-Test-Bot.md
+++ b/docs/Brew-Test-Bot.md
@@ -1,4 +1,5 @@
 # Brew Test Bot
+
 `brew test-bot` is the name for the automated review and testing system funded
 by [our Kickstarter in 2013](https://www.kickstarter.com/projects/homebrew/brew-test-bot).
 
diff --git a/docs/C++-Standard-Libraries.md b/docs/C++-Standard-Libraries.md
index 0bb987def7..c1725f2020 100644
--- a/docs/C++-Standard-Libraries.md
+++ b/docs/C++-Standard-Libraries.md
@@ -1,4 +1,5 @@
 # C++ Standard Libraries
+
 There are two C++ standard libraries supported by Apple compilers.
 
 The default for 10.8 and earlier is **libstdc++**, supported by Apple GCC
diff --git a/docs/CNAME b/docs/CNAME
new file mode 100644
index 0000000000..01a3ad9d8c
--- /dev/null
+++ b/docs/CNAME
@@ -0,0 +1 @@
+docs.brew.sh
diff --git a/docs/Checksum_Deprecation.md b/docs/Checksum_Deprecation.md
index 62985848bd..3ef0d41ecf 100644
--- a/docs/Checksum_Deprecation.md
+++ b/docs/Checksum_Deprecation.md
@@ -1,4 +1,4 @@
-# Checksum Deprecation
+# MD5 and SHA-1 Deprecation
 
 During early 2015 Homebrew started the process of deprecating _SHA1_ for package
 integrity verification. Since then every formulae under the Homebrew organisation
diff --git a/docs/Common-Issues.md b/docs/Common-Issues.md
index 14f2836c41..8da622ab42 100644
--- a/docs/Common-Issues.md
+++ b/docs/Common-Issues.md
@@ -1,4 +1,5 @@
 # Common Issues
+
 This is a list of commonly encountered problems, known issues, and their solutions.
 
 ### `brew` complains about absence of "Command Line Tools"
diff --git a/docs/Custom-GCC-and-cross-compilers.md b/docs/Custom-GCC-and-cross-compilers.md
index 1d662c1587..08a8b2b194 100644
--- a/docs/Custom-GCC-and-cross-compilers.md
+++ b/docs/Custom-GCC-and-cross-compilers.md
@@ -1,4 +1,5 @@
-# Custom GCC and cross compilers
+# Custom GCC and Cross Compilers
+
 Homebrew depends on having an up-to-date version of Xcode because it comes with
 specific versions of build tools e.g. `clang`.
 
@@ -15,7 +16,6 @@ GCC or cross-compiler suite, please link it in here.
 
 * Homebrew provides a `gcc` formula for use with Xcode 4.2+ or when needing
 C++11 support on earlier versions.
-* [Homebrew-versions](https://github.com/homebrew/homebrew-versions) provides an
-up to date GCC duplicates e.g. `brew install homebrew/versions/gcc48`
+* Homebrew provides older GCC formulae e.g. `gcc@4.8` and `gcc@6`
 * [RISC-V](https://github.com/riscv/homebrew-riscv) provides the RISC-V
 toolchain including binutils and gcc.
diff --git a/docs/External-Commands.md b/docs/External-Commands.md
index 8fe6932b05..59622bd3ab 100644
--- a/docs/External-Commands.md
+++ b/docs/External-Commands.md
@@ -1,4 +1,5 @@
 # External Commands
+
 Homebrew, like Git, supports *external commands*. This lets you create new commands that can be run like:
 
 ```shell
@@ -7,78 +8,56 @@ $ brew mycommand --option1 --option3 formula
 
 without modifying Homebrew's internals.
 
-## COMMAND TYPES
+## Command Types
 External commands come in two flavors: Ruby commands and shell scripts.
 
 In both cases, the command file should be executable (`chmod +x`) and live somewhere in `$PATH`.
 
-### RUBY COMMANDS
+### Ruby Commands
 An external command `extcmd` implemented as a Ruby command should be named `brew-extcmd.rb`. The command is executed by doing a `require` on the full pathname. As the command is `require`d, it has full access to the Homebrew "environment", i.e. all global variables and modules that any internal command has access to.
 
 The command may `Kernel.exit` with a status code if it needs to; if it doesn't explicitly exit then Homebrew will return 0.
 
-### SHELL SCRIPTS
+### Shell Scripts
 A shell script for an command named `extcmd` should be named `brew-extcmd`. This file will be run via `exec` with some Homebrew variables set as environmental variables, and passed any additional command-line arguments.
 
-
-  
-    
-    
-	
-  
-    
-		
-	
-  
-    
-		
-  
-  
-    
-		
-	
-  
-    
-		
-	
-  
-    
-		
-  
-
VariableDescription
HOMEBREW_CACHEWhere Homebrew caches downloaded tarballs to, by default ~/Library/Caches/Homebrew.
HOMEBREW_CELLARThe location of the Homebrew Cellar, where software is staged. This will be $HOMEBREW_PREFIX/Cellar if that directory exists, or $HOMEBREW_REPOSITORY/Cellar otherwise.
HOMEBREW_LIBRARY_PATHThe directory containing Homebrew’s own application code.
HOMEBREW_PREFIXWhere Homebrew installs software. This is always the grandparent directory of the `brew` executable, /usr/local by default.
HOMEBREW_REPOSITORYIf installed from a Git clone, the repo directory (i.e., where Homebrew’s .git directory lives).
+| Variable | Description | +|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| HOMEBREW_CACHE | Where Homebrew caches downloaded tarballs to, by default ~/Library/Caches/Homebrew. | +| HOMEBREW_CELLAR | The location of the Homebrew Cellar, where software is staged. This will be $HOMEBREW_PREFIX/Cellar if that directory exists, or $HOMEBREW_REPOSITORY/Cellar otherwise. | +| HOMEBREW_LIBRARY_PATH | The directory containing Homebrew’s own application code. | +| HOMEBREW_PREFIX | Where Homebrew installs software. This is always the grandparent directory of the `brew` executable, /usr/local by default. | +| HOMEBREW_REPOSITORY | If installed from a Git clone, the repo directory (i.e., where Homebrew’s .git directory lives). | + Note that the script itself can use any suitable shebang (`#!`) line, so an external “shell script” can be written for sh, bash, Ruby, or anything else. -## USER-SUBMITTED COMMANDS +## User-submitted Commands These commands have been contributed by Homebrew users but are not included in the main Homebrew repository, nor are they installed by the installer script. You can install them manually, as outlined above. ->*NOTE:* They are largely untested, and as always, be careful about running untested code on your machine. +Note they are largely untested, and as always, be careful about running untested code on your machine. ### brew-livecheck -> Check if there is a new upstream version of a formula. -> -> See the [`README`](https://github.com/youtux/homebrew-livecheck/blob/master/README.md) for more info and usage. -> -> Install using: -> ``` -> $ brew tap youtux/livecheck -> ``` +Check if there is a new upstream version of a formula. +See the [`README`](https://github.com/youtux/homebrew-livecheck/blob/master/README.md) for more info and usage. + +Install using: +```sh +brew tap youtux/livecheck +``` ### brew-gem ->Install any gem package into a self-contained Homebrew cellar location: -> ->*Note:* This can also be installed with `brew install brew-gem`. +Install any gem package into a self-contained Homebrew cellar location: [https://github.com/sportngin/brew-gem](https://github.com/sportngin/brew-gem). + +Note this can also be installed with `brew install brew-gem`. ### brew-growl ->Get Growl notifications for Homebrew https://github.com/secondplanet/brew-growl +Get Growl notifications for Homebrew https://github.com/secondplanet/brew-growl ### brew-services ->Simple support to start formulae using launchctl, has out of the box support for any formula which defines `startup_plist` (e.g. mysql, postgres, redis u.v.m.): [https://github.com/Homebrew/homebrew-services](https://github.com/Homebrew/homebrew-services) +Simple support to start formulae using launchctl, has out of the box support for any formula which defines `startup_plist` (e.g. mysql, postgres, redis u.v.m.): [https://github.com/Homebrew/homebrew-services](https://github.com/Homebrew/homebrew-services) -> Install using: -> ``` - $ brew tap homebrew/services -> ``` - -## SEE ALSO -Homebrew Docs: +Install using: +```sh +brew tap homebrew/services +``` diff --git a/docs/FAQ.md b/docs/FAQ.md index b9cbcd2259..7a32cf9262 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -1,5 +1,6 @@ # FAQ -### How do I update my local packages? + +## How do I update my local packages? First update the formulae and Homebrew itself: brew update @@ -18,7 +19,7 @@ Or upgrade a specific formula with: -### How do I stop certain formulae from being updated? +## How do I stop certain formulae from being updated? To stop something from being updated/upgraded: brew pin $FORMULA @@ -27,7 +28,7 @@ To allow that formulae to update again: brew unpin $FORMULA -### How do I uninstall old versions of a formula? +## How do I uninstall old versions of a formula? By default, Homebrew does not uninstall old versions of a formula, so over time you will accumulate old versions. To remove them, simply use: @@ -43,7 +44,7 @@ to see what would be cleaned up: -### How do I uninstall Homebrew? +## How do I uninstall Homebrew? To uninstall Homebrew, paste the command below in a terminal prompt. ```bash @@ -54,7 +55,7 @@ and run `./uninstall --help` to view more uninstall options. -### How do I uninstall a formula? +## How do I uninstall a formula? If you do not uninstall all of the versions that Homebrew has installed, Homebrew will continue to attempt to install the newest version it knows about when you do (`brew upgrade --all`). This can be surprising. @@ -64,13 +65,13 @@ To remove a formula entirely, you may do Be careful as this is a destructive operation. -### Where does stuff get downloaded? +## Where does stuff get downloaded? brew --cache Which is usually: `~/Library/Caches/Homebrew` -### My Mac `.app`s don’t find `/usr/local/bin` utilities! +## My Mac `.app`s don’t find `/usr/local/bin` utilities! GUI apps on macOS don’t have `/usr/local/bin` in their `PATH` by default. If you’re on Mountain Lion, you can fix this by running `launchctl setenv PATH "/usr/local/bin:$PATH"`. [More details @@ -79,10 +80,10 @@ including how to set this across reboots. If you’re pre-Mountain Lion, [here’s an official alternative](https://developer.apple.com/legacy/library/qa/qa1067/_index.html). -### How do I contribute to Homebrew? +## How do I contribute to Homebrew? Read [CONTRIBUTING.md](/CONTRIBUTING.md). -### Why do you compile everything? +## Why do you compile everything? Homebrew provides pre-compiled versions for many formulae. These pre-compiled versions are referred to as **bottles** and are available at: @@ -107,7 +108,7 @@ your profile. We aim to bottle everything. -### How do I get a formula from someone else’s branch? +## How do I get a formula from someone else’s branch? brew install hub brew update @@ -122,7 +123,7 @@ Or: `brew pull https://github.com/Homebrew/homebrew-core/pull/1234` -### Why does Homebrew prefer I install to `/usr/local`? +## Why does Homebrew prefer I install to `/usr/local`? 1. **It’s easier**
`/usr/local/bin` is already in your @@ -142,7 +143,7 @@ brews then save yourself a bunch of hassle and install to It is not always straightforward to tell `gem` to look in non-standard directories for headers and libraries. If you choose `/usr/local`, many things will "just work". -### Why does Homebrew say sudo is bad? +## Why does Homebrew say sudo is bad? **tl;dr** Sudo is dangerous, and you installed TextMate.app without sudo anyway. @@ -168,17 +169,17 @@ not. So is it that important to `chown root wget`? If you need to run Homebrew in a multi-user environment, consider creating a separate user account especially for use of Homebrew. -### Why isn’t a particular command documented? +## Why isn’t a particular command documented? If it’s not in `man brew`, it’s probably an external command. These are documented [here](External-Commands.md). -### Why haven’t you pulled my pull request? +## Why haven’t you pulled my pull request? If it’s been a while, bump it with a “bump” comment. Sometimes we miss requests and there are plenty of them. Maybe we were thinking on something. It will encourage consideration. In the meantime if you could rebase the pull request so that it can be cherry-picked more easily we will love you for a long time. -### Can I edit formulae myself? +## Can I edit formulae myself? Yes! It’s easy! Just `brew edit $FORMULA`. You don’t have to submit modifications back to *Homebrew/homebrew-core*, just edit the formula as you personally need it and `brew install`. As a bonus `brew update` will merge your changes with upstream so you can still keep the formula up-to-date **with** your personal modifications! -### Can I make new formulae? +## Can I make new formulae? Yes! It’s easy! Just `brew create URL` Homebrew will then open the formula in `$EDITOR` so you can edit it, but it probably already installs; try it: `brew install $FORMULA`. If you come up with any issues, @@ -188,7 +189,7 @@ which drops you into a debugging shell. If you want your new formula to be part of *homebrew/core* or want to learn more about writing formulae, then please read the [Formula Cookbook](Formula-Cookbook.md). -### Can I install my own stuff to `/usr/local`? +## Can I install my own stuff to `/usr/local`? Yes, brew is designed to not get in your way so you can use it how you like. @@ -211,40 +212,25 @@ $ brew link foo Linking /usr/local/Cellar/foo/0.1… 17 symlinks created ``` -### Where was a formula deleted? -Use `brew log $FORMULA` to find out! +## Why was a formula deleted? +Use `brew log $FORMULA` to find out! Likely because it had unresolved issues or +our analytics identified it was not widely used. -Sometimes formulae are moved to specialized repositories. These are the -likely candidates: - -* [homebrew/dupes](https://github.com/Homebrew/homebrew-dupes) -* [homebrew/games](https://github.com/Homebrew/homebrew-games) -* [homebrew/versions](https://github.com/Homebrew/homebrew-versions) - -You can use `brew tap` to access these formulae: - -```bash -brew tap homebrew/games -brew install … -``` - -Note that brew search still finds formula in taps. - -### Homebrew is a poor name, it is generic, why was it chosen? +## Homebrew is a poor name, it is generic, why was it chosen? @mxcl was too concerned with the beer theme and didn’t consider that the project may actually prove popular. By the time he realized it was too late. However, today, the first google hit for “homebrew” is not beer related ;-) -### What does *keg-only* mean? +## What does *keg-only* mean? It means the formula is installed only into the Cellar; it is not linked into `/usr/local`. This means most tools will not find it. We don’t do this for stupid reasons. You can still link in the formula if you need to with `brew link`. -### How can I specify different configure arguments for a formula? +## How can I specify different configure arguments for a formula? `brew edit $FORMULA` and edit the formula. Currently there is no other way to do this. -### Is there a glossary of terms around? +## Is there a glossary of terms around? All your terminology needs can be [found here](Formula-Cookbook.md#homebrew-terminology). diff --git a/docs/Formula-Cookbook.md b/docs/Formula-Cookbook.md index 6657b97668..bb3ad33dcf 100644 --- a/docs/Formula-Cookbook.md +++ b/docs/Formula-Cookbook.md @@ -1,5 +1,6 @@ # Formula Cookbook -A formula is a package definition written in Ruby. It can be created with `brew create $URL`, installed with `brew install $FORMULA`, and debugged with `brew install --debug --verbose $FORMULA`. Formulae use the [Formula API](http://www.rubydoc.info/github/Homebrew/brew/master/Formula) which provides various Homebrew-specific helpers. + +A formula is a package definition written in Ruby. It can be created with `brew create $URL` where `$URL` is a zip or tarball, installed with `brew install $FORMULA`, and debugged with `brew install --debug --verbose $FORMULA`. Formulae use the [Formula API](http://www.rubydoc.info/github/Homebrew/brew/master/Formula) which provides various Homebrew-specific helpers. ## Homebrew Terminology @@ -9,11 +10,11 @@ A formula is a package definition written in Ruby. It can be created with `brew | **Keg** | The installation prefix of a **Formula** | `/usr/local/Cellar/foo/0.1` | | **opt prefix** | A symlink to the active version of a **Keg** | `/usr/local/opt/foo ` | | **Cellar** | All **Kegs** are installed here | `/usr/local/Cellar` | -| **Tap** | An optional Git repository of **Formulae** and/or commands | `/usr/local/Homebrew/Library/Taps/homebrew/homebrew-versions` | +| **Tap** | A Git repository of **Formulae** and/or commands | `/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core` | | **Bottle** | Pre-built **Keg** used instead of building from source | `qt-4.8.4.mavericks.bottle.tar.gz` | | **Cask** | An [extension of homebrew](https://github.com/caskroom/homebrew-cask) to install macOS native apps | `/Applications/MacDown.app/Contents/SharedSupport/bin/macdown` | | **Brew Bundle**| An [extension of homebrew](https://github.com/Homebrew/homebrew-bundle) to describe dependencies | `brew 'myservice', restart_service: true` | - + ## An Introduction Homebrew uses Git for downloading updates and contributing to the project. @@ -33,7 +34,7 @@ Before submitting a new formula make sure your package: * isn't in another official [Homebrew tap](https://github.com/Homebrew) * isn't already waiting to be merged (check the [issue tracker](https://github.com/Homebrew/homebrew-core/pulls)) * is still supported by upstream (i.e. doesn't require extensive patching) -* has a stable, tagged version (i.e. not just a GitHub repository with no versions). See [Interesting-Taps-&-Forks](Interesting-Taps-&-Forks.md) for where pre-release versions belong. +* has a stable, tagged version (i.e. not just a GitHub repository with no versions). * passes all `brew audit --new-formula $FORMULA` tests. Before submitting a new formula make sure you read over our [contribution guidelines](https://github.com/Homebrew/brew/blob/master/CONTRIBUTING.md). @@ -352,7 +353,7 @@ If you have already forked Homebrew on GitHub, then you can manually push (just git push https://github.com/myname/homebrew-core/ ``` -Now, please [open a pull request](https://github.com/Homebrew/brew/blob/master/docs/How-To-Open-a-Homebrew-Pull-Request-(and-get-it-merged).md#how-to-open-a-homebrew-pull-request-and-get-it-merged) for your changes. +Now, please [open a pull request](http://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request.html) for your changes. * One formula per commit; one commit per formula * Keep merge commits out of the pull request diff --git a/docs/Gemfile b/docs/Gemfile new file mode 100644 index 0000000000..fac2f802d4 --- /dev/null +++ b/docs/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +gem "github-pages", group: :jekyll_plugins + +# Nokogiri >=1.7 requires Ruby >=2.1 +gem "nokogiri", "<1.7" diff --git a/docs/Gems,-Eggs-and-Perl-Modules.md b/docs/Gems,-Eggs-and-Perl-Modules.md index dfbdc224f0..770d770f62 100644 --- a/docs/Gems,-Eggs-and-Perl-Modules.md +++ b/docs/Gems,-Eggs-and-Perl-Modules.md @@ -1,4 +1,5 @@ # Gems, Eggs and Perl Modules + On a fresh macOS installation there are three empty directories for add-ons available to all users: diff --git a/docs/Homebrew-and-Python.md b/docs/Homebrew-and-Python.md index 2500b85921..e2f59c322e 100644 --- a/docs/Homebrew-and-Python.md +++ b/docs/Homebrew-and-Python.md @@ -1,5 +1,4 @@ -# Homebrew and Python -## Overview +# Python This page describes how Python is handled in Homebrew for users. See [Python for Formula Authors](Python-for-Formula-Authors.md) for advice on writing formulae to install packages written in Python. @@ -11,14 +10,12 @@ Homebrew provides formulae to brew a more up-to-date Python 2.7.x (and 3.x). ## Python 2.x or Python 3.x - Homebrew provides a formula for Python 2.7.x and one for Python 3.x. They don't conflict, so they can both be installed. The executable `python` will always point to the 2.x and `python3` to the 3.x version. ([Wondering which one to choose?](https://wiki.python.org/moin/Python2orPython3)) ## Setuptools, Pip, etc. - The Python formulae install [`pip`](http://www.pip-installer.org) and [Setuptools](https://pypi.python.org/pypi/setuptools). Setuptools can be updated via Pip, without having to re-brew Python: @@ -30,7 +27,6 @@ Similarly, Pip can be used to upgrade itself via: pip install --upgrade pip ### Note on `pip install --user` - The normal `pip install --user` is disabled for brewed Python. This is because of a bug in distutils, because Homebrew writes a `distutils.cfg` which sets the package `prefix`. A possible workaround (which puts executable scripts in `~/Library/Python/./bin`) is: @@ -38,7 +34,6 @@ A possible workaround (which puts executable scripts in `~/Library/Python/. ## `site-packages` and the `PYTHONPATH` - The `site-packages` is a directory that contains Python modules (especially bindings installed by other formulae). Homebrew creates it here: $(brew --prefix)/lib/pythonX.Y/site-packages @@ -53,11 +48,9 @@ Python 2.7 also searches for modules in: Homebrew's `site-packages` directory is first created if (1) any Homebrew formula with Python bindings are installed, or (2) upon `brew install python`. ### Why here? - 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`). @@ -65,12 +58,10 @@ Homebrew builds bindings against the first `python` (and `python-config`) in you **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`). ## Policy for non-brewed Python bindings - These should be installed via `pip install `. To discover, you can use `pip search` or . (**Note:** System Python does not provide `pip`. Follow the instructions at https://pip.readthedocs.org/en/stable/installing/#install-pip to install it for your system Python if you would like it.) ## Brewed Python modules - For brewed Python, modules installed with `pip` or `python setup.py install` will be installed to `$(brew --prefix)/lib/pythonX.Y/site-packages` directory (explained above). Executable python scripts will be in `$(brew --prefix)/bin`. The system Python may not know which compiler flags to set in order to build bindings for software installed in Homebrew so you may need to: @@ -79,7 +70,6 @@ The system Python may not know which compiler flags to set in order to build bin ## Virtualenv - **WARNING:** When you `brew install` formulae that provide Python bindings, you should **not be in an active virtual environment**. Activate the virtualenv *after* you've brewed, or brew in a fresh Terminal window. @@ -88,5 +78,4 @@ Homebrew will still install Python modules into Homebrew's `site-packages` and * Virtualenv has a 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 depend on the special :python target are bottled against the Homebrew Python and require it to be installed. You can avoid installing Homebrew's Python by building these formulae with `--build-from-source`. diff --git a/docs/How-To-Open-a-Homebrew-Pull-Request-(and-get-it-merged).md b/docs/How-To-Open-a-Homebrew-Pull-Request.md similarity index 96% rename from docs/How-To-Open-a-Homebrew-Pull-Request-(and-get-it-merged).md rename to docs/How-To-Open-a-Homebrew-Pull-Request.md index a3497abcaf..ef6091e2c9 100644 --- a/docs/How-To-Open-a-Homebrew-Pull-Request-(and-get-it-merged).md +++ b/docs/How-To-Open-a-Homebrew-Pull-Request.md @@ -4,6 +4,9 @@ The following commands are used by Homebrew contributors to set up a fork of Hom Depending on the change you want to make, you need to send the pull request to the appropriate one of Homebrew's main repositories. If you want to submit a change to Homebrew core code (the `brew` implementation), you should open the pull request on [Homebrew/brew](https://github.com/Homebrew/brew). If you want to submit a change for a formula, you should open the pull request on [the `homebrew/core` tap](https://github.com/Homebrew/homebrew-core) or another [official tap](https://github.com/Homebrew), based on the formula type. +## Submit a new version of an existing formula +1. Use `brew bump-formula-pr` to do everything (i.e. forking, committing, pushing) with a single command. Run `brew bump-formula-pr --help` to learn more. + ## Set up your own fork of the Homebrew repository ### Core `brew` code related pull request diff --git a/docs/How-to-Create-and-Maintain-a-Tap.md b/docs/How-to-Create-and-Maintain-a-Tap.md index ff7de80299..5c8f3a8c42 100644 --- a/docs/How-to-Create-and-Maintain-a-Tap.md +++ b/docs/How-to-Create-and-Maintain-a-Tap.md @@ -1,4 +1,5 @@ # How to Create and Maintain a Tap + Taps are external sources of Homebrew formulae and/or external commands. They can be created by anyone to provide their own formulae and/or external commands to any Homebrew user. diff --git a/docs/Installation.md b/docs/Installation.md index 15ea71b088..dbe8b9917a 100644 --- a/docs/Installation.md +++ b/docs/Installation.md @@ -1,9 +1,10 @@ # Installation + The suggested and easiest way to install Homebrew is on the [homepage](http://brew.sh). The standard script installs Homebrew to `/usr/local` so that -[you don’t need sudo](FAQ.md#why-does-homebrew-say-sudo-is-bad-) when you +[you don’t need sudo](FAQ.md) when you `brew install`. It is a careful script, it can be run even if you have stuff installed to `/usr/local` already. It tells you exactly what it will do before it does it too. And you have to confirm everything it will do before it starts. @@ -12,11 +13,12 @@ it does it too. And you have to confirm everything it will do before it starts. * An Intel CPU [1](#1) * OS X 10.10 or higher [2](#2) * Command Line Tools (CLT) for Xcode: `xcode-select --install`, - https://developer.apple.com/downloads or + [developer.apple.com/downloads](https://developer.apple.com/downloads) or [Xcode](https://itunes.apple.com/us/app/xcode/id497799835) [3](#3) * A Bourne-compatible shell for installation (e.g. bash or zsh) [4](#4) ## Alternative Installs + ### Untar anywhere Just extract (or `git clone`) Homebrew wherever you want. Just avoid: diff --git a/docs/Interesting-Taps-&-Forks.md b/docs/Interesting-Taps-&-Forks.md index d23277b15c..a5c6094412 100644 --- a/docs/Interesting-Taps-&-Forks.md +++ b/docs/Interesting-Taps-&-Forks.md @@ -1,4 +1,5 @@ # Interesting Taps & Forks + A Tap is homebrew-speak for a git repository containing extra formulae. Homebrew has the capability to add (and remove) multiple taps to your local installation with the `brew tap` and `brew untap` command. Type `man brew` in your Terminal. The main repository https://github.com/Homebrew/homebrew-core, often called `homebrew/core`, is always built-in. @@ -12,16 +13,12 @@ Homebrew has the capability to add (and remove) multiple taps to your local inst * [homebrew/completions](https://github.com/Homebrew/homebrew-completions): Shell completion formulae. -* [homebrew/devel-only](https://github.com/Homebrew/homebrew-devel-only): A tap for brews that only have pre-release/development versions. - * [homebrew/dupes](https://github.com/Homebrew/homebrew-dupes): Need GDB or a newer Tk? System duplicates go here. * [homebrew/emacs](https://github.com/Homebrew/homebrew-emacs): A tap for Emacs packages. * [homebrew/games](https://github.com/Homebrew/homebrew-games): Game or gaming-emulation related formulae. -* [homebrew/head-only](https://github.com/Homebrew/homebrew-head-only): A tap for brews that only have unstable, unreleased versions. This tap is **deprecated** and doesn’t accept new formulae. - * [homebrew/nginx](https://github.com/Homebrew/homebrew-nginx): Feature rich Nginx tap for modules. * [homebrew/php](https://github.com/Homebrew/homebrew-php): Repository for php-related formulae. @@ -32,8 +29,6 @@ Homebrew has the capability to add (and remove) multiple taps to your local inst * [homebrew/services](https://github.com/Homebrew/homebrew-services): A tool to start Homebrew formulae's plists with `launchctl`. -* [homebrew/versions](https://github.com/Homebrew/homebrew-versions): Need e.g. older or newer versions of Postgresql? Older versions of GCC? - * [homebrew/x11](https://github.com/Homebrew/homebrew-x11): Formulae with hard X11 dependencies. `brew search` looks in these main taps as well as in [homebrew/core](https://github.com/Homebrew/homebrew-core). So don't worry about missing stuff. We will add other taps to the search as they become well maintained and popular. @@ -60,4 +55,4 @@ You can be added as a maintainer for one of the Homebrew organization taps and a ## Technical Details -Your taps are git repositories located at `$(brew --prefix)/Library/Taps`. +Your taps are git repositories located at `$(brew --repository)/Library/Taps`. diff --git a/docs/Kickstarter-Supporters.md b/docs/Kickstarter-Supporters.md index ae9556390f..3f39b435c0 100644 --- a/docs/Kickstarter-Supporters.md +++ b/docs/Kickstarter-Supporters.md @@ -1,4 +1,5 @@ # Kickstarter Supporters + This file contains a list of the awesome people who gave £5 or more to [our Kickstarter](https://www.kickstarter.com/projects/homebrew/brew-test-bot). diff --git a/docs/Maintainer-Guidelines.md b/docs/Maintainer-Guidelines.md index d83118642a..fdb7e88f9c 100644 --- a/docs/Maintainer-Guidelines.md +++ b/docs/Maintainer-Guidelines.md @@ -1,4 +1,5 @@ # Maintainer Guidelines + **This guide is for maintainers.** These special people have **write access** to Homebrew’s repository and help merge the contributions of others. You may find what is written here interesting, but it’s diff --git a/docs/Maintainers-Avoiding-Burnout.md b/docs/Maintainers-Avoiding-Burnout.md index f3ba3e346c..99353d946b 100644 --- a/docs/Maintainers-Avoiding-Burnout.md +++ b/docs/Maintainers-Avoiding-Burnout.md @@ -1,4 +1,5 @@ # Maintainers: Avoiding Burnout + **This guide is for maintainers.** These special people have **write access** to Homebrew’s repository and help merge the contributions of others. You may find what is written here interesting, but it’s diff --git a/docs/Migrating-A-Formula-To-A-Tap.md b/docs/Migrating-A-Formula-To-A-Tap.md index 7bc984f84a..ba55770563 100644 --- a/docs/Migrating-A-Formula-To-A-Tap.md +++ b/docs/Migrating-A-Formula-To-A-Tap.md @@ -1,4 +1,5 @@ # Migrating A Formula To A Tap + There are times when we may wish to migrate a formula from one tap into another tap. To do this: 1. Create a pull request to the new tap adding the formula file as-is from the original tap. Fix any test failures that may occur due to the stricter requirements for new formulae than existing formula (e.g. `brew audit --strict` must pass for that formula). diff --git a/docs/New-Maintainer-Checklist.md b/docs/New-Maintainer-Checklist.md index 8745f9b91e..29c2d4ece3 100644 --- a/docs/New-Maintainer-Checklist.md +++ b/docs/New-Maintainer-Checklist.md @@ -1,4 +1,5 @@ # New Maintainer Checklist + **This is a guide used by existing maintainers to invite new maintainers. You might find it interesting but there's nothing here users should have to know.** So, there's someone who has been making consistently high-quality contributions to Homebrew for a long time and shown themselves able to make slightly more advanced contributions than just e.g. formula updates? Let's invite them to be a maintainer! @@ -18,10 +19,10 @@ A few requests: non-trivial (e.g. not a test or audit improvement or version bump) changes to formulae code and don't merge them unless you get at least one approval and passing tests. -- use `brew pull` for formulae changes that require new bottles or change - multiple formulae and let it auto-close issues wherever possible (it may - take ~5m). When this isn't necessary use GitHub's "Merge pull request" - button in "create a merge commit" mode for Homebrew/brew or "squash and +- use `brew pull` for formulae changes that require new bottles or change + multiple formulae and let it auto-close issues wherever possible (it may + take ~5m). When this isn't necessary use GitHub's "Merge pull request" + button in "create a merge commit" mode for Homebrew/brew or "squash and merge" for a single formulae change. If in doubt, check with e.g. GitX that you've not accidentally added merge commits - still create your branches on your fork rather than in the main repository @@ -38,14 +39,14 @@ Thanks for all your work so far! If they accept, follow a few steps to get them set up: -- [x] Invite them to the [**@Homebrew/maintainers** team](https://github.com/orgs/Homebrew/teams/maintainers) to give them write access to all repositories (but don't make them owners yet). They will need to enable [GitHub's Two Factor Authentication](https://help.github.com/articles/about-two-factor-authentication/). -- [x] Ask them to sign in to [Bintray](https://bintray.com) using their GitHub account and they should auto-sync to [Bintray's Homebrew organisation](https://bintray.com/homebrew/organization/edit/members) as a member so they can publish new bottles -- [x] Add them to the [Jenkins' GitHub Authorization Settings admin user names](https://bot.brew.sh/configureSecurity/) so they can adjust settings and restart jobs -- [x] Add them to the [Jenkins' GitHub Pull Request Builder admin list](https://bot.brew.sh/configure) to enable `@BrewTestBot test this please` for them -- [x] Invite them to the [`homebrew-dev` private maintainers mailing list](https://groups.google.com/forum/#!managemembers/homebrew-dev/invite) -- [x] Invite them to the [`machomebrew` private maintainers Slack](https://machomebrew.slack.com/admin/invites) -- [x] Invite them to the [`homebrew` private maintainers 1Password](https://homebrew.1password.com/signin) -- [x] Add them to [Homebrew's README](https://github.com/Homebrew/brew/edit/master/README.md) +- Invite them to the [**@Homebrew/maintainers** team](https://github.com/orgs/Homebrew/teams/maintainers) to give them write access to all repositories (but don't make them owners yet). They will need to enable [GitHub's Two Factor Authentication](https://help.github.com/articles/about-two-factor-authentication/). +- Ask them to sign in to [Bintray](https://bintray.com) using their GitHub account and they should auto-sync to [Bintray's Homebrew organisation](https://bintray.com/homebrew/organization/edit/members) as a member so they can publish new bottles +- Add them to the [Jenkins' GitHub Authorization Settings admin user names](https://bot.brew.sh/configureSecurity/) so they can adjust settings and restart jobs +- Add them to the [Jenkins' GitHub Pull Request Builder admin list](https://bot.brew.sh/configure) to enable `@BrewTestBot test this please` for them +- Invite them to the [`homebrew-dev` private maintainers mailing list](https://groups.google.com/forum/#!managemembers/homebrew-dev/invite) +- Invite them to the [`machomebrew` private maintainers Slack](https://machomebrew.slack.com/admin/invites) +- Invite them to the [`homebrew` private maintainers 1Password](https://homebrew.1password.com/signin) +- Add them to [Homebrew's README](https://github.com/Homebrew/brew/edit/master/README.md) After a few weeks/months with no problems consider making them [owners on the Homebrew GitHub organisation](https://github.com/orgs/Homebrew/people). diff --git a/docs/Python-for-Formula-Authors.md b/docs/Python-for-Formula-Authors.md index 716a3b3595..93830a6c7b 100644 --- a/docs/Python-for-Formula-Authors.md +++ b/docs/Python-for-Formula-Authors.md @@ -45,6 +45,7 @@ If you submit a formula with this syntax to core, you may be asked to rewrite it ## Python declarations 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 ``` @@ -159,6 +160,7 @@ Bindings should follow the same advice for Python module dependencies as librari ## Installing bindings If the bindings are installed by invoking a `setup.py`, do something like: + ```ruby cd "source/python" do system "python", *Language::Python.setup_install_args(prefix) diff --git a/docs/Querying-Brew.md b/docs/Querying-Brew.md index 84a2ba4ebd..6d37cb588d 100644 --- a/docs/Querying-Brew.md +++ b/docs/Querying-Brew.md @@ -1,4 +1,5 @@ -# Querying Brew +# Querying `brew` + _In this document we will be using [jq](https://stedolan.github.io/jq/) to parse JSON, available from Homebrew using `brew install jq`._ ## Overview diff --git a/docs/README.md b/docs/README.md index ac9dbcd79d..ec75647330 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,34 +1,44 @@ -# README -Homebrew installs the stuff you need that Apple didn’t. +# Documentation -- [Install Homebrew](Installation.md) +## Users +- [Troubleshooting](Troubleshooting.md) +- [Installation](Installation.md) - [Frequently Asked Questions](FAQ.md) +- [Common Issues](Common-Issues.md) + - [Tips and Tricks](Tips-N'-Tricks.md) -- [Gems, Eggs and Perl Modules](Gems,-Eggs-and-Perl-Modules.md) -- [Homebrew and Python](Homebrew-and-Python.md) +- [Bottles (binary packages)](Bottles.md) +- [Taps (third-party repositories)](brew-tap.md) +- [Interesting Taps and Forks](Interesting-Taps-&-Forks.md) +- [Anonymous Aggregate User Behaviour Analytics](Analytics.md) -Please note: Homebrew generally works well, but when it doesn’t we’d hope you -report the bug. +- [Querying `brew`](Querying-Brew.md) +- [C++ Standard Libraries](C++-Standard-Libraries.md) +- [MD5 and SHA-1 Deprecation](Checksum_Deprecation.md) +- [Custom GCC and Cross Compilers](Custom-GCC-and-cross-compilers.md) +- [External Commands](External-Commands.md) +- [Ruby Gems, Python Eggs and Perl Modules](Gems,-Eggs-and-Perl-Modules.md) +- [Python](Homebrew-and-Python.md) +- [How To Build Software Outside Homebrew With Homebrew `keg_only` dependencies](How-to-build-software-outside-Homebrew-with-Homebrew-keg-only-dependencies.md) +- [Xcode](Xcode.md) +- [Kickstarter Supporters](Kickstarter-Supporters.md) -## Troubleshooting -First, please run `brew update` (twice) and `brew doctor`. +## Contributors +- [How To Open A Pull Request (and get it merged)](How-To-Open-a-Homebrew-Pull-Request.md) +- [Formula Cookbook](Formula-Cookbook.md) +- [Acceptable Formulae](Acceptable-Formulae.md) +- [Formulae Versions](Versions.md) +- [Node for Formula Authors](Node-for-Formula-Authors.md) +- [Python for Formula Authors](Python-for-Formula-Authors.md) +- [Migrating A Formula To A Tap](Migrating-A-Formula-To-A-Tap.md) +- [Rename A Formula](Rename-A-Formula.md) +- [How To Create (And Maintain) A Tap](How-to-Create-and-Maintain-a-Tap.md) +- [Brew Test Bot](Brew-Test-Bot.md) +- [Prose Style Guidelines](Prose-Style-Guidelines.md) -Second, please read the [Troubleshooting Checklist](Troubleshooting.md). - -**If you don’t follow these steps it will take us far longer to help you with -your problem.** - -However! Fixing build issues is easier than you think: try -`brew edit $FORMULA` and see how you fare. - -## Contributing -Read [CONTRIBUTING.md](/CONTRIBUTING.md). - -### Community Forums -- [@MacHomebrew](https://twitter.com/MacHomebrew) -- [homebrew-discuss@googlegroups.com](mailto:homebrew-discuss@googlegroups.com) ([archive](https://groups.google.com/forum/#!forum/homebrew-discuss)) - subscribe by sending a mail to [homebrew-discuss+subscribe@googlegroups.com](mailto:homebrew-discuss+subscribe@googlegroups.com) -- [freenode.net\#machomebrew](irc://irc.freenode.net/#machomebrew) - -## Supporters -[A list of the awesome people who gave £5 or more to our -Kickstarter](./Kickstarter-Supporters.md). +## Maintainers +- [New Maintainer Checklist](New-Maintainer-Checklist.md) +- [Maintainers Avoiding Burnout](Maintainers-Avoiding-Burnout.md) +- [Maintainer Guidelines](Maintainer-Guidelines.md) +- [Brew Test Bot For Maintainers](Brew-Test-Bot-For-Core-Contributors.md) +- [Common Issues for Maintainers](Common-Issues-for-Core-Contributors.md) diff --git a/docs/Tips-N'-Tricks.md b/docs/Tips-N'-Tricks.md index fc532c0199..8f67c9ca84 100644 --- a/docs/Tips-N'-Tricks.md +++ b/docs/Tips-N'-Tricks.md @@ -1,24 +1,19 @@ -# Tips N' Tricks +# Tips and Tricks ## Installing previous versions of formulae -The preferred and supported method of installing specific versions of -formulae is to use the -[homebrew/versions](https://github.com/Homebrew/homebrew-versions) -tap. If the version you’re looking for isn’t available, consider [opening a -pull request](https://github.com/Homebrew/brew/blob/master/docs/How-To-Open-a-Homebrew-Pull-Request-(and-get-it-merged).md)! +The supported method of installing specific versions of +some formulae is to see if there is a versions formula like e.g. `gcc@6` available. If the version you’re looking for isn’t available, consider [opening a pull request](How-To-Open-a-Homebrew-Pull-Request.md)! ### Installing directly from pull-requests - -You can browse pull requests https://github.com/Homebrew/homebrew-core/pulls -and install through the direct link. For example Python 3.3.0 pull request https://github.com/Homebrew/homebrew/pull/15199 +You can [browse pull requests](https://github.com/Homebrew/homebrew-core/pulls) +and install through the direct link. For example Python 3.3.0 pull request [Homebrew/homebrew#15199](https://github.com/Homebrew/homebrew/pull/15199) ```sh brew install https://raw.github.com/dsr/homebrew/9b22d42f50fcbc5e52c764448b3ac002bc153bd7/Library/Formula/python3.rb ``` ## Quickly remove something from /usr/local - ```sh brew unlink $FORMULA ``` @@ -28,7 +23,6 @@ This can be useful if a package can't build against the version of something you And of course, you can simply `brew link $FORMULA` again afterwards! ## Activate a previously installed version of a formula - ```sh brew info $FORMULA brew switch $FORMULA $VERSION @@ -37,21 +31,18 @@ brew switch $FORMULA $VERSION Use `brew info $FORMULA` to check what versions are installed but not currently activated, then `brew switch $FORMULA $VERSION` to activate the desired version. This can be useful if you would like to switch between versions of a formula. ## Install into Homebrew without formulae - ```sh ./configure --prefix=/usr/local/Cellar/foo/1.2 && make && make install && brew link foo ``` ## Pre-downloading a file for a formula - Sometimes it's faster to download a file via means other than those strategies that are available as part of Homebrew. For example, Erlang provides a torrent that'll let you download at 4–5× the normal HTTP method. Download the file and drop it in `~/Library/Caches/Homebrew`, but -watch the file name. Homebrew downloads files as {{ formula -name }}-{{ version }}. In the case of Erlang, this requires +watch the file name. Homebrew downloads files as ${FORMULA_NAME}-${VERSION}. In the case of Erlang, this requires renaming the file from otp_src_R13B03 to erlang-R13B03. @@ -62,7 +53,6 @@ run `mv the_tarball $(brew --cache -s $FORMULA)`. You can also pre-cache the download by using the command `brew fetch formula` which also displays the SHA256 value. This can be useful for updating formulae to new versions. ## Using Homebrew behind a proxy - Behind the scenes, Homebrew uses several commands for downloading files (e.g. curl, git, svn). Many of these tools can download via a proxy. It's a common (though not universal) convention for these command-line tools to observe getting the proxy parameters from environment variables (e.g. `http_proxy`). Unfortunately, most tools are inconsistent in their use of these environment parameters (e.g. curl supports `http_proxy`, `HTTPS_PROXY`, `FTP_PROXY`, `GOPHER_PROXY`, `ALL_PROXY`, `NO_PROXY`). Luckily, for the majority of cases setting `http_proxy` is enough. @@ -74,13 +64,11 @@ http_proxy=http://: brew install $FORMULA ``` ### Proxy Authentication - ```sh http_proxy=http://:@: brew install $FORMULA ``` ## Installing stuff without the Xcode-CLT - ```sh $ brew sh # or: eval $(brew --env) $ gem install ronn # or c-programs @@ -89,13 +77,11 @@ $ gem install ronn # or c-programs This imports the brew environment into your existing shell, gem will pick up the environment variables and be able to build. As a bonus brew's automatically determined optimization flags are set. ## Install only a formula's dependencies (not the formula) - ```sh brew install --only-dependencies $FORMULA ``` ## Interactive Homebrew Shell - ```sh $ brew irb 1.8.7 :001 > Formula.factory("ace").methods - Object.methods @@ -104,7 +90,6 @@ $ brew irb ``` ## Hiding the beer mug emoji when finishing a build - ```sh export HOMEBREW_NO_EMOJI=1 ``` @@ -127,12 +112,10 @@ In Sublime Text 2/3, you can use Package Control to install which adds highlighting for inline patches. ### Vim - [brew.vim](https://github.com/xu-cheng/brew.vim) adds highlighting to inline patches in Vim. ### Emacs - [homebrew-mode](https://github.com/dunn/homebrew-mode) provides syntax highlighting for inline patches as well as a number of helper functions for editing formula files. @@ -141,7 +124,6 @@ for editing formula files. for emacs shell-mode and eshell-mode. ### Atom - [language-homebrew-formula](https://atom.io/packages/language-homebrew-formula) adds highlighting and diff support (with the [language-diff](https://atom.io/packages/language-diff) plugin). diff --git a/docs/Versions.md b/docs/Versions.md new file mode 100644 index 0000000000..bd3ef8a5f8 --- /dev/null +++ b/docs/Versions.md @@ -0,0 +1,16 @@ +# Versions + +Now that [Homebrew/versions](https://github.com/homebrew/homebrew-versions) has been deprecated [Homebrew/core](https://github.com/homebrew/homebrew-core) supports multiple versions of formulae with a new naming format. + +In [Homebrew/versions](https://github.com/homebrew/homebrew-versions) the formula for GCC 6 was named `gcc6.rb` and began `class Gcc6 < Formula`. In [Homebrew/core](https://github.com/homebrew/homebrew-core) this same formula is named `gcc@6.rb` and begins `class GccAT6 < Formula`. + +## Acceptable Versioned Formulae +Homebrew's versions are not intended to be used for any old versions you personally require for your project; formulae submitted should be expected to be used by a large number of people and still supported by their upstream projects. + +Versioned formulae we include must meet the following standards: + +* Versioned formulae should differ in major/minor (not patch) versions from the current stable release. This is because patch versions indicate bug or security updates and we want to ensure you apply security updates. +* Formulae that depend on versioned formulae must not depend on the same formulae at two different versions twice in their recursive dependencies. For example, if you depend on `openssl@1.0` and `foo`, and `foo` depends on `openssl` then you must instead use `openssl`. +* Versioned formulae should only be linkable at the same time as their non-versioned counterpart if the upstream project provides support for e.g. suffixed binaries. If this is not possible, use `keg_only :versioned_formula` to allow users to have multiple versions installed at once. + +You should create your own [tap](https://github.com/Homebrew/brew/blob/master/docs/How-to-Create-and-Maintain-a-Tap.md) for formulae you or your organisation wishes to control the versioning of or those that do not meet the above standards. diff --git a/docs/Xcode.md b/docs/Xcode.md index 7697a9c550..025cee9d7f 100644 --- a/docs/Xcode.md +++ b/docs/Xcode.md @@ -1,71 +1,71 @@ # Xcode + ## Supported Xcode Versions Homebrew supports and recommends the latest Xcode and/or Command Line Tools available for your platform: - macOS | Xcode | Command Line Tools - ----- | ----- | ---------------------------- - 10.6 | 3.2.6 | N/A - 10.7 | 4.6.3 | April 2013 - 10.8 | 5.1.1 | April 2014 - 10.9 | 6.2 | 6.2 - 10.10 | 7.2.1 | 7.2 - 10.11 | 8.0 | 7.3 - 10.12 | 8.0 | 8.0 - +| macOS | Xcode | Command Line Tools | +|-------|-------|--------------------| +| 10.6 | 3.2.6 | N/A | +| 10.7 | 4.6.3 | April 2013 | +| 10.8 | 5.1.1 | April 2014 | +| 10.9 | 6.2 | 6.2 | +| 10.10 | 7.2.1 | 7.2 | +| 10.11 | 8.0 | 7.3 | +| 10.12 | 8.0 | 8.0 | ## Compiler Version Database - Xcode | GCC 4.0 | GCC 4.2 | LLVM-GCC 4.2 | LLVM | Clang | LLVM (SVN) - --------- | ----------- | ----------- | ---------------- | ----------- | --------------- | ---------- - 2.5.0 | 5370 | — | — | — | — | — - 3.1.4 | 5493 | 5577 | 5555 | 2064.3 | — | — - 3.2.0 | 5493 | 5646 | 5646 | 2118 | — | — - 3.2.1 | 5493 | 5646 | 5646 | 2206 | — | — - 3.2.2 | 5493 | 5659 | 5646 | 2207.5 | 1.0.2 | — - 3.2.3 | 5494 | 5664 | 5658 | 2326.10 | 1.5 (60) | — - 3.2.4 | 5494 | 5664 | 5658 | 2326.10 | 1.5 (60) | — - 3.2.5 | 5494 | 5664 | 5658 | 2333.4 | 1.6 (70) | — - 3.2.6 | 5494 | 5666 | 5658 | 2335.6 | 1.7 (77) | 2.9 - 4.0.0 | 5494 | 5666 | 5658 | 2335.9 | 2.0 (137) | 2.9 - 4.0.2 | 5494 | 5666 | 5658 | 2335.9 | 2.0 (137) | 2.9 - 4.1.0 | — | 5666 | 5658 | 2335.15.00 | 2.1 (163.7.1) | 3.0 - 4.2.0 | — | — | 5658 | 2336.1.00 | 3.0 (211.10.1) | 3.0 - 4.3.0 | — | — | 5658 | 2336.9.00 | 3.1 (318.0.45) | 3.1 - 4.3.1 | — | — | 5658 | 2336.9.00 | 3.1 (318.0.54) | 3.1 - 4.3.2 | — | — | 5658 | 2336.9.00 | 3.1 (318.0.58) | 3.1 - 4.3.3 | — | — | 5658 | 2336.9.00 | 3.1 (318.0.61) | 3.1 - 4.4.0 | — | — | 5658 | 2336.11.00 | 4.0 (421.0.57) | 3.1 - 4.4.1 | — | — | 5658 | 2336.11.00 | 4.0 (421.0.60) | 3.1 - 4.5.0 | — | — | 5658 | 2336.11.00 | 4.1 (421.11.65) | 3.1 - 4.5.1 | — | — | 5658 | 2336.11.00 | 4.1 (421.11.66) | 3.1 - 4.5.2 | — | — | 5658 | 2336.11.00 | 4.1 (421.11.66) | 3.1 - 4.6.0 | — | — | 5658 | 2336.11.00 | 4.2 (425.0.24) | 3.2 - 4.6.1 | — | — | 5658 | 2336.11.00 | 4.2 (425.0.27) | 3.2 - 4.6.2 | — | — | 5658 | 2336.11.00 | 4.2 (425.0.28) | 3.2 - 4.6.3 | — | — | 5658 | 2336.11.00 | 4.2 (425.0.28) | 3.2 - 5.0.0 | — | — | — | — | 5.0 (500.2.76) | 3.3 - 5.0.1 | — | — | — | — | 5.0 (500.2.78) | 3.3 - 5.0.1 | — | — | — | — | 5.0 (500.2.79) | 3.3 - 5.1 | — | — | — | — | 5.1 (503.0.38) | 3.4 - 5.1.1 | — | — | — | — | 5.1 (503.0.40) | 3.4 - 6.0 | — | — | — | — | 6.0 (600.0.51) | 3.5 - 6.0.1 | — | — | — | — | 6.0 (600.0.51) | 3.5 - 6.1 | — | — | — | — | 6.0 (600.0.54) | 3.5 - 6.2 | — | — | — | — | 6.0 (600.0.57) | 3.5 - 6.3 | — | — | — | — | 6.1 (602.0.49) | 3.6 - 6.3.1 | — | — | — | — | 6.1 (602.0.49) | 3.6 - 6.3.2 | — | — | — | — | 6.1 (602.0.53) | 3.6 - 6.4 | — | — | — | — | 6.1 (602.0.53) | 3.6 - 7.0 | — | — | — | — | 7.0 (700.0.72) | - - 7.0.1 | — | — | — | — | 7.0 (700.0.72) | - - 7.1 | — | — | — | — | 7.0 (700.1.76) | - - 7.1.1 | — | — | — | — | 7.0 (700.1.76) | - - 7.2 | — | — | — | — | 7.0 (700.1.81) | - - 7.2.1 | — | — | — | — | 7.0 (700.1.81) | - - 7.3 | — | — | — | — | 7.3 (703.0.29) | - - 7.3.1 | — | — | — | — | 7.3 (703.0.31) | - - 8.0 | — | — | — | — | 8.0 (800.0.38) | - + | Xcode | GCC 4.0 | GCC 4.2 | LLVM-GCC 4.2 | LLVM | Clang | LLVM (SVN) | + |-------|---------|---------|--------------|------------|-----------------|------------| + | 2.5.0 | 5370 | — | — | — | — | — | + | 3.1.4 | 5493 | 5577 | 5555 | 2064.3 | — | — | + | 3.2.0 | 5493 | 5646 | 5646 | 2118 | — | — | + | 3.2.1 | 5493 | 5646 | 5646 | 2206 | — | — | + | 3.2.2 | 5493 | 5659 | 5646 | 2207.5 | 1.0.2 | — | + | 3.2.3 | 5494 | 5664 | 5658 | 2326.10 | 1.5 (60) | — | + | 3.2.4 | 5494 | 5664 | 5658 | 2326.10 | 1.5 (60) | — | + | 3.2.5 | 5494 | 5664 | 5658 | 2333.4 | 1.6 (70) | — | + | 3.2.6 | 5494 | 5666 | 5658 | 2335.6 | 1.7 (77) | 2.9 | + | 4.0.0 | 5494 | 5666 | 5658 | 2335.9 | 2.0 (137) | 2.9 | + | 4.0.2 | 5494 | 5666 | 5658 | 2335.9 | 2.0 (137) | 2.9 | + | 4.1.0 | — | 5666 | 5658 | 2335.15.00 | 2.1 (163.7.1) | 3.0 | + | 4.2.0 | — | — | 5658 | 2336.1.00 | 3.0 (211.10.1) | 3.0 | + | 4.3.0 | — | — | 5658 | 2336.9.00 | 3.1 (318.0.45) | 3.1 | + | 4.3.1 | — | — | 5658 | 2336.9.00 | 3.1 (318.0.54) | 3.1 | + | 4.3.2 | — | — | 5658 | 2336.9.00 | 3.1 (318.0.58) | 3.1 | + | 4.3.3 | — | — | 5658 | 2336.9.00 | 3.1 (318.0.61) | 3.1 | + | 4.4.0 | — | — | 5658 | 2336.11.00 | 4.0 (421.0.57) | 3.1 | + | 4.4.1 | — | — | 5658 | 2336.11.00 | 4.0 (421.0.60) | 3.1 | + | 4.5.0 | — | — | 5658 | 2336.11.00 | 4.1 (421.11.65) | 3.1 | + | 4.5.1 | — | — | 5658 | 2336.11.00 | 4.1 (421.11.66) | 3.1 | + | 4.5.2 | — | — | 5658 | 2336.11.00 | 4.1 (421.11.66) | 3.1 | + | 4.6.0 | — | — | 5658 | 2336.11.00 | 4.2 (425.0.24) | 3.2 | + | 4.6.1 | — | — | 5658 | 2336.11.00 | 4.2 (425.0.27) | 3.2 | + | 4.6.2 | — | — | 5658 | 2336.11.00 | 4.2 (425.0.28) | 3.2 | + | 4.6.3 | — | — | 5658 | 2336.11.00 | 4.2 (425.0.28) | 3.2 | + | 5.0.0 | — | — | — | — | 5.0 (500.2.76) | 3.3 | + | 5.0.1 | — | — | — | — | 5.0 (500.2.78) | 3.3 | + | 5.0.1 | — | — | — | — | 5.0 (500.2.79) | 3.3 | + | 5.1 | — | — | — | — | 5.1 (503.0.38) | 3.4 | + | 5.1.1 | — | — | — | — | 5.1 (503.0.40) | 3.4 | + | 6.0 | — | — | — | — | 6.0 (600.0.51) | 3.5 | + | 6.0.1 | — | — | — | — | 6.0 (600.0.51) | 3.5 | + | 6.1 | — | — | — | — | 6.0 (600.0.54) | 3.5 | + | 6.2 | — | — | — | — | 6.0 (600.0.57) | 3.5 | + | 6.3 | — | — | — | — | 6.1 (602.0.49) | 3.6 | + | 6.3.1 | — | — | — | — | 6.1 (602.0.49) | 3.6 | + | 6.3.2 | — | — | — | — | 6.1 (602.0.53) | 3.6 | + | 6.4 | — | — | — | — | 6.1 (602.0.53) | 3.6 | + | 7.0 | — | — | — | — | 7.0 (700.0.72) | - | + | 7.0.1 | — | — | — | — | 7.0 (700.0.72) | - | + | 7.1 | — | — | — | — | 7.0 (700.1.76) | - | + | 7.1.1 | — | — | — | — | 7.0 (700.1.76) | - | + | 7.2 | — | — | — | — | 7.0 (700.1.81) | - | + | 7.2.1 | — | — | — | — | 7.0 (700.1.81) | - | + | 7.3 | — | — | — | — | 7.3 (703.0.29) | - | + | 7.3.1 | — | — | — | — | 7.3 (703.0.31) | - | + | 8.0 | — | — | — | — | 8.0 (800.0.38) | - | ## References to Xcode and compiler versions in code When a new Xcode release is made, the following things need to be diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000000..687739b4ad --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,2 @@ +theme: jekyll-theme-cayman +exclude: [bin, vendor, CNAME, Gemfile, Gemfile.lock] diff --git a/docs/brew-tap.md b/docs/brew-tap.md index 624a83f33b..15f8c79364 100644 --- a/docs/brew-tap.md +++ b/docs/brew-tap.md @@ -1,10 +1,10 @@ -# brew tap +# Taps (third-party repositories) `brew tap` adds more repos to the list of formulae that `brew` tracks, updates, and installs from. By default, `tap` assumes that the repos come from GitHub, but the command isn't limited to any one location. -## The command +## The command (`brew tap`) * `brew tap` without arguments lists the currently tapped repositories. For example: diff --git a/docs/brew.1.html b/docs/brew.1.html index 7b7251faf7..2e036eb558 100644 --- a/docs/brew.1.html +++ b/docs/brew.1.html @@ -22,7 +22,7 @@ didn't include with macOS.

install formula

Install formula.

-
remove formula

Uninstall formula.

+
uninstall formula

Uninstall formula.

update

Fetch the newest version of Homebrew from GitHub using git(1).

list

List all installed formulae.

search text|/text/

Perform a substring search of formula names for text. If text is @@ -36,7 +36,7 @@ If no search term is given, all locally available formulae are listed.

analytics [state]

Display anonymous user behaviour analytics state. -Read more at https://git.io/brew-analytics.

+Read more at http://docs.brew.sh/Analytics.html.

analytics (on|off)

Turn on/off Homebrew's analytics.

analytics regenerate-uuid

Regenerate UUID used in Homebrew's analytics.

cat formula

Display the source to formula.

@@ -127,8 +127,9 @@ checksum of a previously cached version no longer matches.

If --build-from-source is passed, download the source rather than a bottle.

-

If --force-bottle is passed, download a bottle if it exists for the current -version of macOS, even if it would not be used during installation.

+

If --force-bottle is passed, download a bottle if it exists for the +current or newest version of macOS, even if it would not be used during +installation.

gist-logs [--new-issue|-n] formula

Upload logs for a failed build of formula to a new Gist.

formula is usually the name of the formula to install, but it can be specified @@ -151,7 +152,7 @@ for version is v1.

information on all installed formulae.

See the docs for examples of using the JSON: -https://github.com/Homebrew/brew/blob/master/docs/Querying-Brew.md

+http://docs.brew.sh/Querying-Brew.html

install [--debug] [--env=std|super] [--ignore-dependencies] [--only-dependencies] [--cc=compiler] [--build-from-source] [--devel|--HEAD] [--keep-tmp] formula

Install formula.

formula is usually the name of the formula to install, but it can be specified @@ -185,16 +186,17 @@ from bottles if they are available.

passed, then both formula and the dependencies installed as part of this process are built from source even if bottles are available.

+

If --force-bottle is passed, install from a bottle if it exists for the +current or newest version of macOS, even if it would not normally be used +for installation.

+

If --devel is passed, and formula defines it, install the development version.

If --HEAD is passed, and formula defines it, install the HEAD version, aka master, trunk, unstable.

If --keep-tmp is passed, the temporary files created during installation -are not deleted.

- -

To install a newer version of HEAD use -brew rm <foo> && brew install --HEAD <foo>.

+are not deleted.

install --interactive [--git] formula

Download and patch formula, then open a shell. This allows the user to run ./configure --help and otherwise determine how to turn the software package into a Homebrew formula.

@@ -218,7 +220,12 @@ actually link or delete any files.

If --force is passed, Homebrew will allow keg-only formulae to be linked.

linkapps [--local] [formulae]

Find installed formulae that provide .app-style macOS apps and symlink them -into /Applications, allowing for easier access.

+into /Applications, allowing for easier access (deprecated).

+ +

Unfortunately brew linkapps cannot behave nicely with e.g. Spotlight using +either aliases or symlinks and Homebrew formulae do not build "proper" .app +bundles that can be relocated. Instead, please consider using brew cask and +migrate formulae using .apps to casks.

If no formulae are provided, all of them will have their apps symlinked.

@@ -347,7 +354,7 @@ for version is v1.

Pass --installed to get information on installed taps.

See the docs for examples of using the JSON: -https://github.com/Homebrew/brew/blob/master/docs/Querying-Brew.md

+http://docs.brew.sh/Querying-Brew.html

tap-pin tap

Pin tap, prioritizing its formulae over core when formula names are supplied by the user. See also tap-unpin.

tap-unpin tap

Unpin tap so its formulae are no longer prioritized. See also tap-pin.

@@ -364,7 +371,12 @@ for temporarily disabling a formula:

If --dry-run or -n is passed, Homebrew will list all files which would be unlinked, but will not actually unlink or delete any files.

-
unlinkapps [--local] [--dry-run] [formulae]

Remove symlinks created by brew linkapps from /Applications.

+
unlinkapps [--local] [--dry-run] [formulae]

Remove symlinks created by brew linkapps from /Applications (deprecated).

+ +

Unfortunately brew linkapps cannot behave nicely with e.g. Spotlight using +either aliases or symlinks and Homebrew formulae do not build "proper" .app +bundles that can be relocated. Instead, please consider using brew cask and +migrate formulae using .apps to casks.

If no formulae are provided, all linked apps will be removed.

@@ -504,7 +516,7 @@ message.

url-and-sha256 style specification into a tag-and-revision style specification, nor vice versa. It must use whichever style specification the preexisting formula already uses.

-
create URL [--autotools|--cmake] [--no-fetch] [--set-name name] [--set-version version] [--tap user/repo]

Generate a formula for the downloadable file at URL and open it in the editor. +

create URL [--autotools|--cmake|--meson] [--no-fetch] [--set-name name] [--set-version version] [--tap user/repo]

Generate a formula for the downloadable file at URL and open it in the editor. Homebrew will attempt to automatically derive the formula name and version, but if it fails, you'll have to make your own template. The wget formula serves as a simple example. For the complete API have a look at

@@ -512,7 +524,8 @@ formula serves as a simple example. For the complete API have a look at

http://www.rubydoc.info/github/Homebrew/brew/master/Formula

If --autotools is passed, create a basic template for an Autotools-style build. -If --cmake is passed, create a basic template for a CMake-style build.

+If --cmake is passed, create a basic template for a CMake-style build. +If --meson is passed, create a basic template for a Meson-style build.

If --no-fetch is passed, Homebrew will not download URL to the cache and will thus not add the SHA256 to the formula for you.

@@ -635,7 +648,7 @@ scripts that reside somewhere in the PATH, named brew- to create your own commands without modifying Homebrew's internals.

Instructions for creating your own commands can be found in the docs: -https://github.com/Homebrew/brew/blob/master/docs/External-Commands.md

+http://docs.brew.sh/External-Commands.html

SPECIFYING FORMULAE

@@ -714,7 +727,7 @@ Homebrew uses the GitHub API for features such as brew search.

the number of parallel jobs to run when building with make(1).

Default: the number of available CPU cores.

-
HOMEBREW_NO_ANALYTICS

If set, Homebrew will not send analytics. See: https://github.com/Homebrew/brew/blob/master/docs/Analytics.md#analytics

+
HOMEBREW_NO_ANALYTICS

If set, Homebrew will not send analytics. See: http://docs.brew.sh/Analytics.html

HOMEBREW_NO_AUTO_UPDATE

If set, Homebrew will not auto-update before running brew install, brew upgrade or brew tap.

HOMEBREW_NO_EMOJI

If set, Homebrew will not print the HOMEBREW_INSTALL_BADGE on a @@ -774,9 +787,9 @@ your shell profile, or you can use it before a brew command:

Homebrew's lead maintainer is Mike McQuaid.

-

Homebrew's current maintainers are Misty De Meo, Andrew Janke, Xu Cheng, Tomasz Pajor, Josh Hagins, Baptiste Fontaine, Markus Reiter, ilovezfs, Martin Afanasjew, Tom Schoonjans, Uladzislau Shablinski, Tim Smith and Alex Dunn.

+

Homebrew's current maintainers are Misty De Meo, Andrew Janke, Xu Cheng, Tomasz Pajor, Josh Hagins, Baptiste Fontaine, Markus Reiter, ilovezfs, Tom Schoonjans, Uladzislau Shablinski, Tim Smith and Alex Dunn.

-

Former maintainers with significant contributions include Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew's creator: Max Howell.

+

Former maintainers with significant contributions include Martin Afanasjew, Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew's creator: Max Howell.

BUGS

diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1 index a14c7521ab..9b217fed54 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" "November 2016" "Homebrew" "brew-cask" +.TH "BREW\-CASK" "1" "January 2017" "Homebrew" "brew-cask" . .SH "NAME" \fBbrew\-cask\fR \- a friendly binary installer for macOS @@ -89,9 +89,6 @@ If \fItoken\fR is given, summarize the staged files associated with the given Ca \fBuninstall\fR or \fBrm\fR or \fBremove\fR [\-\-force] \fItoken\fR [ \fItoken\fR \.\.\. ]: Uninstall the given Cask\. With \fB\-\-force\fR, uninstall even if the Cask does not appear to be present\. . .IP "\(bu" 4 -\fBupdate\fR: For convenience\. \fBbrew cask update\fR is a synonym for \fBbrew update\fR\. -. -.IP "\(bu" 4 \fBzap\fR \fItoken\fR [ \fItoken\fR \.\.\. ]: Unconditionally remove \fIall\fR files associated with the given Cask\. . .IP @@ -108,6 +105,15 @@ If the Cask definition contains a \fBzap\fR stanza, performs additional \fBzap\f . .IP "" 0 . +.SH "INTERNAL COMMANDS" +. +.TP +\fB_appcast_checkpoint\fR [\-\-calculate] [ \fItoken\fR \.\.\. | \fIURL\fR \.\.\. ] +Given a \fBtoken\fR, returns the current appcast checkpoint, or calculates the appcast checkpoint if the \fB\-\-calculate\fR flag is specified\. +. +.br +Given a \fBURL\fR, calculates the appcast checkpoint for it\. +. .SH "OPTIONS" To make these options persistent, see the ENVIRONMENT section, below\. . diff --git a/manpages/brew.1 b/manpages/brew.1 index f51468a7f0..f122337fbf 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" "November 2016" "Homebrew" "brew" +.TH "BREW" "1" "January 2017" "Homebrew" "brew" . .SH "NAME" \fBbrew\fR \- The missing package manager for macOS @@ -26,7 +26,7 @@ With \fB\-\-verbose\fR or \fB\-v\fR, many commands print extra debugging informa Install \fIformula\fR\. . .TP -\fBremove\fR \fIformula\fR +\fBuninstall\fR \fIformula\fR Uninstall \fIformula\fR\. . .TP @@ -45,7 +45,7 @@ Perform a substring search of formula names for \fItext\fR\. If \fItext\fR is su . .TP \fBanalytics\fR [\fBstate\fR] -Display anonymous user behaviour analytics state\. Read more at \fIhttps://git\.io/brew\-analytics\fR\. +Display anonymous user behaviour analytics state\. Read more at \fIhttp://docs\.brew\.sh/Analytics\.html\fR\. . .TP \fBanalytics\fR (\fBon\fR|\fBoff\fR) @@ -171,7 +171,7 @@ If \fB\-\-deps\fR is passed, also download dependencies for any listed \fIformul If \fB\-\-build\-from\-source\fR is passed, download the source rather than a bottle\. . .IP -If \fB\-\-force\-bottle\fR is passed, download a bottle if it exists for the current version of macOS, even if it would not be used during installation\. +If \fB\-\-force\-bottle\fR is passed, download a bottle if it exists for the current or newest version of macOS, even if it would not be used during installation\. . .TP \fBgist\-logs\fR [\fB\-\-new\-issue\fR|\fB\-n\fR] \fIformula\fR @@ -213,7 +213,7 @@ Print a JSON representation of \fIformulae\fR\. Currently the only accepted valu Pass \fB\-\-all\fR to get information on all formulae, or \fB\-\-installed\fR to get information on all installed formulae\. . .IP -See the docs for examples of using the JSON: \fIhttps://github\.com/Homebrew/brew/blob/master/docs/Querying\-Brew\.md\fR +See the docs for examples of using the JSON: \fIhttp://docs\.brew\.sh/Querying\-Brew\.html\fR . .TP \fBinstall\fR [\fB\-\-debug\fR] [\fB\-\-env=\fR\fIstd\fR|\fIsuper\fR] [\fB\-\-ignore\-dependencies\fR] [\fB\-\-only\-dependencies\fR] [\fB\-\-cc=\fR\fIcompiler\fR] [\fB\-\-build\-from\-source\fR] [\fB\-\-devel\fR|\fB\-\-HEAD\fR] [\fB\-\-keep\-tmp\fR] \fIformula\fR @@ -247,6 +247,9 @@ If \fB\-\-build\-from\-source\fR or \fB\-s\fR is passed, compile the specified \ If \fBHOMEBREW_BUILD_FROM_SOURCE\fR is set, regardless of whether \fB\-\-build\-from\-source\fR was passed, then both \fIformula\fR and the dependencies installed as part of this process are built from source even if bottles are available\. . .IP +If \fB\-\-force\-bottle\fR is passed, install from a bottle if it exists for the current or newest version of macOS, even if it would not normally be used for installation\. +. +.IP If \fB\-\-devel\fR is passed, and \fIformula\fR defines it, install the development version\. . .IP @@ -255,9 +258,6 @@ If \fB\-\-HEAD\fR is passed, and \fIformula\fR defines it, install the HEAD vers .IP If \fB\-\-keep\-tmp\fR is passed, the temporary files created during installation are not deleted\. . -.IP -To install a newer version of HEAD use \fBbrew rm && brew install \-\-HEAD \fR\. -. .TP \fBinstall\fR \fB\-\-interactive\fR [\fB\-\-git\fR] \fIformula\fR Download and patch \fIformula\fR, then open a shell\. This allows the user to run \fB\./configure \-\-help\fR and otherwise determine how to turn the software package into a Homebrew formula\. @@ -291,7 +291,10 @@ If \fB\-\-force\fR is passed, Homebrew will allow keg\-only formulae to be linke . .TP \fBlinkapps\fR [\fB\-\-local\fR] [\fIformulae\fR] -Find installed formulae that provide \fB\.app\fR\-style macOS apps and symlink them into \fB/Applications\fR, allowing for easier access\. +Find installed formulae that provide \fB\.app\fR\-style macOS apps and symlink them into \fB/Applications\fR, allowing for easier access (deprecated)\. +. +.IP +Unfortunately \fBbrew linkapps\fR cannot behave nicely with e\.g\. Spotlight using either aliases or symlinks and Homebrew formulae do not build "proper" \fB\.app\fR bundles that can be relocated\. Instead, please consider using \fBbrew cask\fR and migrate formulae using \fB\.app\fRs to casks\. . .IP If no \fIformulae\fR are provided, all of them will have their apps symlinked\. @@ -476,7 +479,7 @@ Print a JSON representation of \fItaps\fR\. Currently the only accepted value fo Pass \fB\-\-installed\fR to get information on installed taps\. . .IP -See the docs for examples of using the JSON: \fIhttps://github\.com/Homebrew/brew/blob/master/docs/Querying\-Brew\.md\fR +See the docs for examples of using the JSON: \fIhttp://docs\.brew\.sh/Querying\-Brew\.html\fR . .TP \fBtap\-pin\fR \fItap\fR @@ -505,7 +508,10 @@ If \fB\-\-dry\-run\fR or \fB\-n\fR is passed, Homebrew will list all files which . .TP \fBunlinkapps\fR [\fB\-\-local\fR] [\fB\-\-dry\-run\fR] [\fIformulae\fR] -Remove symlinks created by \fBbrew linkapps\fR from \fB/Applications\fR\. +Remove symlinks created by \fBbrew linkapps\fR from \fB/Applications\fR (deprecated)\. +. +.IP +Unfortunately \fBbrew linkapps\fR cannot behave nicely with e\.g\. Spotlight using either aliases or symlinks and Homebrew formulae do not build "proper" \fB\.app\fR bundles that can be relocated\. Instead, please consider using \fBbrew cask\fR and migrate formulae using \fB\.app\fRs to casks\. . .IP If no \fIformulae\fR are provided, all linked apps will be removed\. @@ -695,14 +701,14 @@ If \fB\-\-message=\fR\fImessage\fR is passed, append \fImessage\fR to the defaul Note that this command cannot be used to transition a formula from a url\-and\-sha256 style specification into a tag\-and\-revision style specification, nor vice versa\. It must use whichever style specification the preexisting formula already uses\. . .TP -\fBcreate\fR \fIURL\fR [\fB\-\-autotools\fR|\fB\-\-cmake\fR] [\fB\-\-no\-fetch\fR] [\fB\-\-set\-name\fR \fIname\fR] [\fB\-\-set\-version\fR \fIversion\fR] [\fB\-\-tap\fR \fIuser\fR\fB/\fR\fIrepo\fR] +\fBcreate\fR \fIURL\fR [\fB\-\-autotools\fR|\fB\-\-cmake\fR|\fB\-\-meson\fR] [\fB\-\-no\-fetch\fR] [\fB\-\-set\-name\fR \fIname\fR] [\fB\-\-set\-version\fR \fIversion\fR] [\fB\-\-tap\fR \fIuser\fR\fB/\fR\fIrepo\fR] Generate a formula for the downloadable file at \fIURL\fR and open it in the editor\. Homebrew will attempt to automatically derive the formula name and version, but if it fails, you\'ll have to make your own template\. The \fBwget\fR formula serves as a simple example\. For the complete API have a look at . .IP \fIhttp://www\.rubydoc\.info/github/Homebrew/brew/master/Formula\fR . .IP -If \fB\-\-autotools\fR is passed, create a basic template for an Autotools\-style build\. If \fB\-\-cmake\fR is passed, create a basic template for a CMake\-style build\. +If \fB\-\-autotools\fR is passed, create a basic template for an Autotools\-style build\. If \fB\-\-cmake\fR is passed, create a basic template for a CMake\-style build\. If \fB\-\-meson\fR is passed, create a basic template for a Meson\-style build\. . .IP If \fB\-\-no\-fetch\fR is passed, Homebrew will not download \fIURL\fR to the cache and will thus not add the SHA256 to the formula for you\. @@ -835,7 +841,7 @@ Integrates Homebrew formulae with macOS\'s \fBlaunchctl\fR manager: \fIhttps://g Homebrew, like \fBgit\fR(1), supports external commands\. These are executable scripts that reside somewhere in the \fBPATH\fR, named \fBbrew\-\fR\fIcmdname\fR or \fBbrew\-\fR\fIcmdname\fR\fB\.rb\fR, which can be invoked like \fBbrew\fR \fIcmdname\fR\. This allows you to create your own commands without modifying Homebrew\'s internals\. . .P -Instructions for creating your own commands can be found in the docs: \fIhttps://github\.com/Homebrew/brew/blob/master/docs/External\-Commands\.md\fR +Instructions for creating your own commands can be found in the docs: \fIhttp://docs\.brew\.sh/External\-Commands\.html\fR . .SH "SPECIFYING FORMULAE" Many Homebrew commands accept one or more \fIformula\fR arguments\. These arguments can take several different forms: @@ -954,7 +960,7 @@ If set, instructs Homebrew to use the value of \fBHOMEBREW_MAKE_JOBS\fR as the n . .TP \fBHOMEBREW_NO_ANALYTICS\fR -If set, Homebrew will not send analytics\. See: \fIhttps://github\.com/Homebrew/brew/blob/master/docs/Analytics\.md#analytics\fR +If set, Homebrew will not send analytics\. See: \fIhttp://docs\.brew\.sh/Analytics\.html\fR . .TP \fBHOMEBREW_NO_AUTO_UPDATE\fR @@ -1043,10 +1049,10 @@ Homebrew Documentation: \fIhttps://github\.com/Homebrew/brew/blob/master/docs/\f Homebrew\'s lead maintainer is Mike McQuaid\. . .P -Homebrew\'s current maintainers are Misty De Meo, Andrew Janke, Xu Cheng, Tomasz Pajor, Josh Hagins, Baptiste Fontaine, Markus Reiter, ilovezfs, Martin Afanasjew, Tom Schoonjans, Uladzislau Shablinski, Tim Smith and Alex Dunn\. +Homebrew\'s current maintainers are Misty De Meo, Andrew Janke, Xu Cheng, Tomasz Pajor, Josh Hagins, Baptiste Fontaine, Markus Reiter, ilovezfs, Tom Schoonjans, Uladzislau Shablinski, Tim Smith and Alex Dunn\. . .P -Former maintainers with significant contributions include Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew\'s creator: Max Howell\. +Former maintainers with significant contributions include Martin Afanasjew, Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew\'s creator: Max Howell\. . .SH "BUGS" See our issues on GitHub: