aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
authorMisty De Meo2015-08-21 11:04:22 -0700
committerMisty De Meo2015-08-21 11:04:22 -0700
commit727239e12f98fafad39aa4f70b37c6d5bf4db1cc (patch)
tree6019e597c18c9ea366e7e45be0a3e6fc19335ae1 /Library
parent1da2855c0b1d884d18944307bdbbe2b64c4dd47d (diff)
parent04a0b2aafe2062701be4028f408d0bee15f3815d (diff)
downloadbrew-727239e12f98fafad39aa4f70b37c6d5bf4db1cc.tar.bz2
Merge bottle install without Xcode branch
Merge branch 'bottle_hooks'
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/cmd/config.rb10
-rw-r--r--Library/Homebrew/cmd/doctor.rb1
-rw-r--r--Library/Homebrew/cmd/install.rb8
-rw-r--r--Library/Homebrew/cmd/reinstall.rb2
-rw-r--r--Library/Homebrew/cmd/upgrade.rb2
-rw-r--r--Library/Homebrew/exceptions.rb94
-rw-r--r--Library/Homebrew/extend/ARGV.rb14
-rw-r--r--Library/Homebrew/extend/ENV/std.rb2
-rw-r--r--Library/Homebrew/extend/ENV/super.rb2
-rw-r--r--Library/Homebrew/formula.rb6
-rw-r--r--Library/Homebrew/formula_installer.rb79
-rw-r--r--Library/Homebrew/keg_relocate.rb4
-rw-r--r--Library/Homebrew/mach.rb4
-rw-r--r--Library/Homebrew/os/mac.rb27
-rw-r--r--Library/Homebrew/os/mac/xcode.rb2
-rw-r--r--Library/Homebrew/requirements/cctools_requirement.rb13
-rw-r--r--Library/Homebrew/software_spec.rb12
l---------Library/Homebrew/test/bottles/testball_bottle-0.1.mavericks.bottle.tar.gz1
l---------Library/Homebrew/test/bottles/testball_bottle-0.1.mountain_lion.bottle.tar.gz1
-rw-r--r--Library/Homebrew/test/bottles/testball_bottle-0.1.yosemite.bottle.tar.gzbin0 -> 1379 bytes
-rw-r--r--Library/Homebrew/test/test_formula_installer_bottle.rb78
-rw-r--r--Library/Homebrew/test/testball_bottle.rb17
22 files changed, 350 insertions, 29 deletions
diff --git a/Library/Homebrew/cmd/config.rb b/Library/Homebrew/cmd/config.rb
index 7627d6e97..74b4f436e 100644
--- a/Library/Homebrew/cmd/config.rb
+++ b/Library/Homebrew/cmd/config.rb
@@ -7,23 +7,23 @@ module Homebrew
end
def llvm
- @llvm ||= MacOS.llvm_build_version
+ @llvm ||= MacOS.llvm_build_version if MacOS.has_apple_developer_tools?
end
def gcc_42
- @gcc_42 ||= MacOS.gcc_42_build_version
+ @gcc_42 ||= MacOS.gcc_42_build_version if MacOS.has_apple_developer_tools?
end
def gcc_40
- @gcc_40 ||= MacOS.gcc_40_build_version
+ @gcc_40 ||= MacOS.gcc_40_build_version if MacOS.has_apple_developer_tools?
end
def clang
- @clang ||= MacOS.clang_version
+ @clang ||= MacOS.clang_version if MacOS.has_apple_developer_tools?
end
def clang_build
- @clang_build ||= MacOS.clang_build_version
+ @clang_build ||= MacOS.clang_build_version if MacOS.has_apple_developer_tools?
end
def xcode
diff --git a/Library/Homebrew/cmd/doctor.rb b/Library/Homebrew/cmd/doctor.rb
index 7ceb88b7e..97e31a8e2 100644
--- a/Library/Homebrew/cmd/doctor.rb
+++ b/Library/Homebrew/cmd/doctor.rb
@@ -258,6 +258,7 @@ class Checks
end
end
+ # TODO: distill down into single method definition a la BuildToolsError
if MacOS.version >= "10.9"
def check_for_installed_developer_tools
unless MacOS::Xcode.installed? || MacOS::CLT.installed? then <<-EOS.undent
diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb
index 19c826d44..47735a23c 100644
--- a/Library/Homebrew/cmd/install.rb
+++ b/Library/Homebrew/cmd/install.rb
@@ -38,6 +38,10 @@ module Homebrew
end
end
+ # if the user's flags will prevent bottle only-installations when no
+ # developer tools are available, we need to stop them early on
+ FormulaInstaller.prevent_build_flags unless MacOS.has_apple_developer_tools?
+
ARGV.formulae.each do |f|
# head-only without --HEAD is an error
if !ARGV.build_head? && f.stable.nil? && f.devel.nil?
@@ -131,10 +135,10 @@ module Homebrew
checks = Checks.new
%w[
check_for_unsupported_osx
+ check_for_bad_install_name_tool
check_for_installed_developer_tools
check_xcode_license_approved
check_for_osx_gcc_installer
- check_for_bad_install_name_tool
].each do |check|
out = checks.send(check)
opoo out unless out.nil?
@@ -161,7 +165,7 @@ module Homebrew
def perform_preinstall_checks
check_ppc
check_writable_install_location
- check_xcode
+ check_xcode if MacOS.has_apple_developer_tools?
check_cellar
end
diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb
index fe5e2e5ec..435c3155f 100644
--- a/Library/Homebrew/cmd/reinstall.rb
+++ b/Library/Homebrew/cmd/reinstall.rb
@@ -2,6 +2,8 @@ require "formula_installer"
module Homebrew
def reinstall
+ FormulaInstaller.prevent_build_flags unless MacOS.has_apple_developer_tools?
+
ARGV.resolved_formulae.each { |f| reinstall_formula(f) }
end
diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb
index 211d081e7..e1b7dd0dc 100644
--- a/Library/Homebrew/cmd/upgrade.rb
+++ b/Library/Homebrew/cmd/upgrade.rb
@@ -3,6 +3,8 @@ require "cmd/outdated"
module Homebrew
def upgrade
+ FormulaInstaller.prevent_build_flags unless MacOS.has_apple_developer_tools?
+
Homebrew.perform_preinstall_checks
if ARGV.named.empty?
diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb
index bae941eed..65675247c 100644
--- a/Library/Homebrew/exceptions.rb
+++ b/Library/Homebrew/exceptions.rb
@@ -257,6 +257,100 @@ class BuildError < RuntimeError
end
end
+# raised by FormulaInstaller.check_dependencies_bottled and
+# FormulaInstaller.install if the formula or its dependencies are not bottled
+# and are being installed on a system without necessary build tools
+class BuildToolsError < RuntimeError
+ def initialize(formulae)
+ if formulae.length > 1
+ formula_text = "formulae"
+ package_text = "binary packages"
+ else
+ formula_text = "formula"
+ package_text = "a binary package"
+ end
+
+ if MacOS.version >= "10.10"
+ xcode_text = <<-EOS.undent
+ To continue, you must install Xcode from the App Store,
+ or the CLT by running:
+ xcode-select --install
+ EOS
+ elsif MacOS.version == "10.9"
+ xcode_text = <<-EOS.undent
+ To continue, you must install Xcode from:
+ https://developer.apple.com/downloads/
+ or the CLT by running:
+ xcode-select --install
+ EOS
+ elsif MacOS.version >= "10.7"
+ xcode_text = <<-EOS.undent
+ To continue, you must install Xcode or the CLT from:
+ https://developer.apple.com/downloads/
+ EOS
+ else
+ xcode_text = <<-EOS.undent
+ To continue, you must install Xcode from:
+ https://developer.apple.com/downloads/
+ EOS
+ end
+
+ super <<-EOS.undent
+ The following #{formula_text}:
+ #{formulae.join(', ')}
+ cannot be installed as a #{package_text} and must be built from source.
+ #{xcode_text}
+ EOS
+ end
+end
+
+# raised by Homebrew.install, Homebrew.reinstall, and Homebrew.upgrade
+# if the user passes any flags/environment that would case a bottle-only
+# installation on a system without build tools to fail
+class BuildFlagsError < RuntimeError
+ def initialize(flags)
+ if flags.length > 1
+ flag_text = "flags"
+ require_text = "require"
+ else
+ flag_text = "flag"
+ require_text = "requires"
+ end
+
+ if MacOS.version >= "10.10"
+ xcode_text = <<-EOS.undent
+ or install Xcode from the App Store, or the CLT by running:
+ xcode-select --install
+ EOS
+ elsif MacOS.version == "10.9"
+ xcode_text = <<-EOS.undent
+ or install Xcode from:
+ https://developer.apple.com/downloads/
+ or the CLT by running:
+ xcode-select --install
+ EOS
+ elsif MacOS.version >= "10.7"
+ xcode_text = <<-EOS.undent
+ or install Xcode or the CLT from:
+ https://developer.apple.com/downloads/
+ EOS
+ else
+ xcode_text = <<-EOS.undent
+ or install Xcode from:
+ https://developer.apple.com/downloads/
+ EOS
+ end
+
+ super <<-EOS.undent
+ The following #{flag_text}:
+ #{flags.join(', ')}
+ #{require_text} building tools, but none are installed.
+ Either remove the #{flag_text} to attempt bottle installation,
+ #{xcode_text}
+ EOS
+ end
+end
+
# raised by CompilerSelector if the formula fails with all of
# the compilers available on the user's system
class CompilerSelectionError < RuntimeError
diff --git a/Library/Homebrew/extend/ARGV.rb b/Library/Homebrew/extend/ARGV.rb
index 9241f02c6..0f78769c5 100644
--- a/Library/Homebrew/extend/ARGV.rb
+++ b/Library/Homebrew/extend/ARGV.rb
@@ -207,6 +207,20 @@ module HomebrewArgvExtension
value "env"
end
+ # If the user passes any flags that trigger building over installing from
+ # a bottle, they are collected here and returned as an Array for checking.
+ def collect_build_flags
+ build_flags = []
+
+ build_flags << '--HEAD' if build_head?
+ build_flags << '--universal' if build_universal?
+ build_flags << '--32-bit' if build_32_bit?
+ build_flags << '--build-bottle' if build_bottle?
+ build_flags << '--build-from-source' if build_from_source?
+
+ build_flags
+ end
+
private
def spec(default = :stable)
diff --git a/Library/Homebrew/extend/ENV/std.rb b/Library/Homebrew/extend/ENV/std.rb
index 6798e6cd3..d05ccf1a3 100644
--- a/Library/Homebrew/extend/ENV/std.rb
+++ b/Library/Homebrew/extend/ENV/std.rb
@@ -29,7 +29,7 @@ module Stdenv
self["PKG_CONFIG_LIBDIR"] = determine_pkg_config_libdir
# make any aclocal stuff installed in Homebrew available
- self["ACLOCAL_PATH"] = "#{HOMEBREW_PREFIX}/share/aclocal" if MacOS::Xcode.provides_autotools?
+ self["ACLOCAL_PATH"] = "#{HOMEBREW_PREFIX}/share/aclocal" if MacOS.has_apple_developer_tools? && MacOS::Xcode.provides_autotools?
self["MAKEFLAGS"] = "-j#{make_jobs}"
diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb
index a59b54a1d..95a8773cd 100644
--- a/Library/Homebrew/extend/ENV/super.rb
+++ b/Library/Homebrew/extend/ENV/super.rb
@@ -23,6 +23,8 @@ module Superenv
end
def self.bin
+ return unless MacOS.has_apple_developer_tools?
+
bin = (HOMEBREW_REPOSITORY/"Library/ENV").subdirs.reject { |d| d.basename.to_s > MacOS::Xcode.version }.max
bin.realpath unless bin.nil?
end
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 8fb220ba8..278cf6595 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -741,7 +741,11 @@ class Formula
end
def file_modified?
- return false unless which("git")
+ git_dir = MacOS.locate("git").dirname.to_s
+
+ # /usr/bin/git is a popup stub when Xcode/CLT aren't installed, so bail out
+ return false if git_dir == "/usr/bin" && !MacOS.has_apple_developer_tools?
+
path.parent.cd do
diff = Utils.popen_read("git", "diff", "origin/master", "--", "#{path}")
!diff.empty? && $?.exitstatus == 0
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index 8b0c1eebc..8c15367a9 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -13,6 +13,7 @@ require "cmd/postinstall"
require "hooks/bottles"
require "debrew"
require "sandbox"
+require "requirements/cctools_requirement"
class FormulaInstaller
include FormulaCellarChecks
@@ -55,6 +56,15 @@ class FormulaInstaller
@pour_failed = false
end
+ # When no build tools are available and build flags are passed through ARGV,
+ # it's necessary to interrupt the user before any sort of installation
+ # can proceed. Only invoked when the user has no developer tools.
+ def self.prevent_build_flags
+ build_flags = ARGV.collect_build_flags
+
+ raise BuildFlagsError.new(build_flags) unless build_flags.empty?
+ end
+
def pour_bottle?(install_bottle_options = { :warn=>false })
return true if Homebrew::Hooks::Bottles.formula_has_bottle?(formula)
@@ -146,7 +156,15 @@ class FormulaInstaller
check_conflicts
- compute_and_install_dependencies unless ignore_deps?
+ if !pour_bottle? && !MacOS.has_apple_developer_tools?
+ raise BuildToolsError.new([formula])
+ end
+
+ if !ignore_deps?
+ deps = compute_dependencies
+ check_dependencies_bottled(deps) if pour_bottle?
+ install_dependencies(deps)
+ end
return if only_deps?
@@ -166,6 +184,7 @@ class FormulaInstaller
if pour_bottle?(:warn => true)
begin
+ install_relocation_tools unless formula.bottle.skip_relocation?
pour
rescue => e
raise if ARGV.homebrew_developer?
@@ -215,18 +234,31 @@ class FormulaInstaller
raise FormulaConflictError.new(formula, conflicts) unless conflicts.empty?
end
- def compute_and_install_dependencies
+ # Compute and collect the dependencies needed by the formula currently
+ # being installed.
+ def compute_dependencies
req_map, req_deps = expand_requirements
-
check_requirements(req_map)
-
deps = expand_dependencies(req_deps + formula.deps)
- if deps.empty? && only_deps?
- puts "All dependencies for #{formula.full_name} are satisfied."
- else
- install_dependencies(deps)
+ deps
+ end
+
+ # Check that each dependency in deps has a bottle available, terminating
+ # abnormally with a BuildToolsError if one or more don't.
+ # Only invoked when the user has no developer tools.
+ def check_dependencies_bottled(deps)
+ unbottled = deps.select do |dep, _|
+ formula = dep.to_formula
+ !formula.pour_bottle? && !MacOS.has_apple_developer_tools?
end
+
+ raise BuildToolsError.new(unbottled) unless unbottled.empty?
+ end
+
+ def compute_and_install_dependencies
+ deps = compute_dependencies
+ install_dependencies(deps)
end
def check_requirements(req_map)
@@ -317,15 +349,29 @@ class FormulaInstaller
end
def install_dependencies(deps)
- if deps.length > 1
- oh1 "Installing dependencies for #{formula.full_name}: #{Tty.green}#{deps.map(&:first)*", "}#{Tty.reset}"
+ if deps.empty? && only_deps?
+ puts "All dependencies for #{formula.full_name} are satisfied."
+ else
+ oh1 "Installing dependencies for #{formula.full_name}: #{Tty.green}#{deps.map(&:first)*", "}#{Tty.reset}" unless deps.empty?
+ deps.each { |dep, options| install_dependency(dep, options) }
end
- deps.each { |dep, options| install_dependency(dep, options) }
-
@show_header = true unless deps.empty?
end
+ # Installs the relocation tools (as provided by the cctools formula) as a hard
+ # dependency for every formula installed from a bottle when the user has no
+ # developer tools. Invoked unless the formula explicitly sets
+ # :any_skip_relocation in its bottle DSL.
+ def install_relocation_tools
+ cctools = CctoolsRequirement.new
+ dependency = cctools.to_dependency
+ formula = dependency.to_formula
+ return if cctools.satisfied? || @@attempted.include?(formula)
+
+ install_dependency(dependency, inherited_options_for(cctools))
+ end
+
class DependencyInstaller < FormulaInstaller
def initialize(*)
super
@@ -397,7 +443,8 @@ class FormulaInstaller
keg = Keg.new(formula.prefix)
link(keg)
- fix_install_names(keg)
+
+ fix_install_names(keg) unless @poured_bottle && formula.bottle.skip_relocation?
if formula.post_install_defined?
if build_bottle?
@@ -633,8 +680,10 @@ class FormulaInstaller
end
keg = Keg.new(formula.prefix)
- keg.relocate_install_names Keg::PREFIX_PLACEHOLDER, HOMEBREW_PREFIX.to_s,
- Keg::CELLAR_PLACEHOLDER, HOMEBREW_CELLAR.to_s, :keg_only => formula.keg_only?
+ unless formula.bottle.skip_relocation?
+ keg.relocate_install_names Keg::PREFIX_PLACEHOLDER, HOMEBREW_PREFIX.to_s,
+ Keg::CELLAR_PLACEHOLDER, HOMEBREW_CELLAR.to_s, :keg_only => formula.keg_only?
+ end
Pathname.glob("#{formula.bottle_prefix}/{etc,var}/**/*") do |path|
path.extend(InstallRenamed)
diff --git a/Library/Homebrew/keg_relocate.rb b/Library/Homebrew/keg_relocate.rb
index eceef192f..05d19db4d 100644
--- a/Library/Homebrew/keg_relocate.rb
+++ b/Library/Homebrew/keg_relocate.rb
@@ -98,8 +98,8 @@ class Keg
end
def install_name_tool(*args)
- tool = MacOS.locate("install_name_tool")
- system(tool, *args) || raise(ErrorDuringExecution.new(tool, args))
+ tool = MacOS.install_name_tool
+ system(tool, *args) or raise ErrorDuringExecution.new(tool, args)
end
# If file is a dylib or bundle itself, look for the dylib named by
diff --git a/Library/Homebrew/mach.rb b/Library/Homebrew/mach.rb
index c15399cbf..f7ca428e6 100644
--- a/Library/Homebrew/mach.rb
+++ b/Library/Homebrew/mach.rb
@@ -154,9 +154,9 @@ module MachO
def parse_otool_L_output
ENV["HOMEBREW_MACH_O_FILE"] = path.expand_path.to_s
- libs = `#{MacOS.locate("otool")} -L "$HOMEBREW_MACH_O_FILE"`.split("\n")
+ libs = `#{MacOS.otool} -L "$HOMEBREW_MACH_O_FILE"`.split("\n")
unless $?.success?
- raise ErrorDuringExecution.new(MacOS.locate("otool"),
+ raise ErrorDuringExecution.new(MacOS.otool,
["-L", ENV["HOMEBREW_MACH_O_FILE"]])
end
diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb
index ffab00b00..c2c909d76 100644
--- a/Library/Homebrew/os/mac.rb
+++ b/Library/Homebrew/os/mac.rb
@@ -36,6 +36,33 @@ module OS
end
end
+ # Locates a (working) copy of install_name_tool, guaranteed to function
+ # whether the user has developer tools installed or not.
+ def install_name_tool
+ if File.executable?(path = "#{HOMEBREW_PREFIX}/opt/cctools/bin/install_name_tool")
+ Pathname.new(path)
+ else
+ locate("install_name_tool")
+ end
+ end
+
+ # Locates a (working) copy of otool, guaranteed to function whether the user
+ # has developer tools installed or not.
+ def otool
+ if File.executable?(path = "#{HOMEBREW_PREFIX}/opt/cctools/bin/otool")
+ Pathname.new(path)
+ else
+ locate("otool")
+ end
+ end
+
+ # Checks if the user has any developer tools installed, either via Xcode
+ # or the CLT. Convenient for guarding against formula builds when building
+ # is impossible.
+ def has_apple_developer_tools?
+ Xcode.installed? || CLT.installed?
+ end
+
def active_developer_dir
@active_developer_dir ||= Utils.popen_read("/usr/bin/xcode-select", "-print-path").strip
end
diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb
index 9b111e4e6..a79814d0d 100644
--- a/Library/Homebrew/os/mac/xcode.rb
+++ b/Library/Homebrew/os/mac/xcode.rb
@@ -76,6 +76,8 @@ module OS
return "0" unless OS.mac?
+ return nil if !MacOS::Xcode.installed? && !MacOS::CLT.installed?
+
%W[#{prefix}/usr/bin/xcodebuild #{which("xcodebuild")}].uniq.each do |path|
if File.file? path
Utils.popen_read(path, "-version") =~ /Xcode (\d(\.\d)*)/
diff --git a/Library/Homebrew/requirements/cctools_requirement.rb b/Library/Homebrew/requirements/cctools_requirement.rb
new file mode 100644
index 000000000..ab7f8cb59
--- /dev/null
+++ b/Library/Homebrew/requirements/cctools_requirement.rb
@@ -0,0 +1,13 @@
+# Represents a general requirement for utilities normally installed by Xcode,
+# the CLT, or provided by the cctools formula. In particular, this requirement
+# allows Homebrew to pull in the cctools formula and use its utilities to
+# perform relocation operations on systems that do not have either Xcode or the
+# CLT installed (but still want to install bottled formulae).
+class CctoolsRequirement < Requirement
+ fatal true
+ default_formula 'cctools'
+
+ satisfy(:build_env => false) do
+ MacOS::Xcode.installed? || MacOS::CLT.installed? || Formula['cctools'].installed?
+ end
+end
diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb
index f7e2ff113..e8148322e 100644
--- a/Library/Homebrew/software_spec.rb
+++ b/Library/Homebrew/software_spec.rb
@@ -245,6 +245,11 @@ class Bottle
@spec.compatible_cellar?
end
+ # Does the bottle need to be relocated?
+ def skip_relocation?
+ @spec.skip_relocation?
+ end
+
def stage
resource.downloader.stage
end
@@ -281,7 +286,12 @@ class BottleSpecification
end
def compatible_cellar?
- cellar == :any || cellar == HOMEBREW_CELLAR.to_s
+ cellar == :any || cellar == :any_skip_relocation || cellar == HOMEBREW_CELLAR.to_s
+ end
+
+ # Does the Bottle this BottleSpecification belongs to need to be relocated?
+ def skip_relocation?
+ cellar == :any_skip_relocation
end
def tag?(tag)
diff --git a/Library/Homebrew/test/bottles/testball_bottle-0.1.mavericks.bottle.tar.gz b/Library/Homebrew/test/bottles/testball_bottle-0.1.mavericks.bottle.tar.gz
new file mode 120000
index 000000000..3e989830b
--- /dev/null
+++ b/Library/Homebrew/test/bottles/testball_bottle-0.1.mavericks.bottle.tar.gz
@@ -0,0 +1 @@
+testball_bottle-0.1.yosemite.bottle.tar.gz \ No newline at end of file
diff --git a/Library/Homebrew/test/bottles/testball_bottle-0.1.mountain_lion.bottle.tar.gz b/Library/Homebrew/test/bottles/testball_bottle-0.1.mountain_lion.bottle.tar.gz
new file mode 120000
index 000000000..3e989830b
--- /dev/null
+++ b/Library/Homebrew/test/bottles/testball_bottle-0.1.mountain_lion.bottle.tar.gz
@@ -0,0 +1 @@
+testball_bottle-0.1.yosemite.bottle.tar.gz \ No newline at end of file
diff --git a/Library/Homebrew/test/bottles/testball_bottle-0.1.yosemite.bottle.tar.gz b/Library/Homebrew/test/bottles/testball_bottle-0.1.yosemite.bottle.tar.gz
new file mode 100644
index 000000000..d88838a94
--- /dev/null
+++ b/Library/Homebrew/test/bottles/testball_bottle-0.1.yosemite.bottle.tar.gz
Binary files differ
diff --git a/Library/Homebrew/test/test_formula_installer_bottle.rb b/Library/Homebrew/test/test_formula_installer_bottle.rb
new file mode 100644
index 000000000..4d2d1676f
--- /dev/null
+++ b/Library/Homebrew/test/test_formula_installer_bottle.rb
@@ -0,0 +1,78 @@
+require "testing_env"
+require "formula"
+require "compat/formula_specialties"
+require "formula_installer"
+require "keg"
+require "testball_bottle"
+require "testball"
+
+class InstallBottleTests < Homebrew::TestCase
+ def temporary_bottle_install(formula)
+ refute_predicate formula, :installed?
+ assert_predicate formula, :bottled?
+ assert_predicate formula, :pour_bottle?
+
+ installer = FormulaInstaller.new(formula)
+
+ shutup { installer.install }
+
+ keg = Keg.new(formula.prefix)
+
+ assert_predicate formula, :installed?
+
+ begin
+ yield formula
+ ensure
+ keg.unlink
+ keg.uninstall
+ formula.clear_cache
+ Dir["#{HOMEBREW_CACHE}/testball_bottle*"].each { |f| File.delete(f) }
+ # there will be log files when sandbox is enable.
+ formula.logs.rmtree if formula.logs.directory?
+ end
+
+ refute_predicate keg, :exist?
+ refute_predicate formula, :installed?
+ end
+
+ def test_a_basic_bottle_install
+ MacOS.stubs(:has_apple_developer_tools?).returns(false)
+
+ temporary_bottle_install(TestballBottle.new) do |f|
+ # Copied directly from test_formula_installer.rb as we expect
+ # the same behavior
+
+ # Test that things made it into the Keg
+ assert_predicate f.bin, :directory?
+
+ assert_predicate f.libexec, :directory?
+
+ refute_predicate f.prefix+"main.c", :exist?
+
+ # Test that things make it into the Cellar
+ keg = Keg.new f.prefix
+ keg.link
+
+ bin = HOMEBREW_PREFIX+"bin"
+ assert_predicate bin, :directory?
+ end
+ end
+
+ def test_build_tools_error
+ MacOS.stubs(:has_apple_developer_tools?).returns(false)
+
+ # Testball doesn't have a bottle block, so use it to test this behavior
+ formula = Testball.new
+
+ refute_predicate formula, :installed?
+ refute_predicate formula, :bottled?
+
+ installer = FormulaInstaller.new(formula)
+
+ assert_raises(BuildToolsError) do
+ installer.install
+ end
+
+ refute_predicate formula, :installed?
+ end
+end
diff --git a/Library/Homebrew/test/testball_bottle.rb b/Library/Homebrew/test/testball_bottle.rb
new file mode 100644
index 000000000..27ffd972a
--- /dev/null
+++ b/Library/Homebrew/test/testball_bottle.rb
@@ -0,0 +1,17 @@
+class TestballBottle < Formula
+ def initialize(name = "testball_bottle", path = Pathname.new(__FILE__).expand_path, spec = :stable)
+ self.class.instance_eval do
+ stable.url "file://#{File.expand_path("..", __FILE__)}/tarballs/testball-0.1.tbz"
+ stable.sha256 "1dfb13ce0f6143fe675b525fc9e168adb2215c5d5965c9f57306bb993170914f"
+ stable.bottle do
+ cellar :any_skip_relocation
+ root_url "file://#{File.expand_path("..", __FILE__)}/bottles"
+ sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :yosemite
+ sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :mavericks
+ sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :mountain_lion
+ end
+ cxxstdlib_check :skip
+ end
+ super
+ end
+end