aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike McQuaid2016-04-25 17:57:51 +0100
committerMike McQuaid2016-05-08 16:51:22 +0100
commit931e292bf12b8e05f6586ac7721255b35f04a389 (patch)
tree0ba3a1b81851de032c2e30a1f3fd3b2f6e3dc573
parentddb576b582ddc801ac702566bacbc2f231fc86af (diff)
downloadbrew-931e292bf12b8e05f6586ac7721255b35f04a389.tar.bz2
Make bottle code cross-platform.
-rw-r--r--Library/Homebrew/bottles.rb141
-rw-r--r--Library/Homebrew/cleanup.rb4
-rw-r--r--Library/Homebrew/cmd/bottle.rb8
-rw-r--r--Library/Homebrew/cmd/pull.rb5
-rw-r--r--Library/Homebrew/cmd/test-bot.rb8
-rw-r--r--Library/Homebrew/extend/os/bottles.rb5
-rw-r--r--Library/Homebrew/extend/os/mac/utils/bottles.rb59
-rw-r--r--Library/Homebrew/formula.rb2
-rw-r--r--Library/Homebrew/formula_installer.rb2
-rw-r--r--Library/Homebrew/formulary.rb4
-rw-r--r--Library/Homebrew/software_spec.rb10
-rw-r--r--Library/Homebrew/test/test_bottle_collector.rb4
-rw-r--r--Library/Homebrew/test/test_bottle_tag.rb24
-rw-r--r--Library/Homebrew/test/test_formulary.rb6
-rw-r--r--Library/Homebrew/test/testball_bottle.rb2
-rw-r--r--Library/Homebrew/utils/bottles.rb104
-rw-r--r--Library/brew.sh2
17 files changed, 209 insertions, 181 deletions
diff --git a/Library/Homebrew/bottles.rb b/Library/Homebrew/bottles.rb
deleted file mode 100644
index b18fde477..000000000
--- a/Library/Homebrew/bottles.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-require "tab"
-require "extend/ARGV"
-
-def built_as_bottle?(f)
- return false unless f.installed?
- tab = Tab.for_keg(f.installed_prefix)
- tab.built_as_bottle
-end
-
-def bottle_file_outdated?(f, file)
- filename = file.basename.to_s
- return unless f.bottle && filename.match(Pathname::BOTTLE_EXTNAME_RX)
-
- bottle_ext = filename[bottle_native_regex, 1]
- bottle_url_ext = f.bottle.url[bottle_native_regex, 1]
-
- bottle_ext && bottle_url_ext && bottle_ext != bottle_url_ext
-end
-
-def bottle_native_regex
- /(\.#{bottle_tag}\.bottle\.(\d+\.)?tar\.gz)$/o
-end
-
-def bottle_tag
- if MacOS.version >= :lion
- MacOS.cat
- elsif MacOS.version == :snow_leopard
- Hardware::CPU.is_64_bit? ? :snow_leopard : :snow_leopard_32
- else
- # Return, e.g., :tiger_g3, :leopard_g5_64, :leopard_64 (which is Intel)
- if Hardware::CPU.type == :ppc
- tag = "#{MacOS.cat}_#{Hardware::CPU.family}".to_sym
- else
- tag = MacOS.cat
- end
- MacOS.prefer_64_bit? ? "#{tag}_64".to_sym : tag
- end
-end
-
-def bottle_receipt_path(bottle_file)
- Utils.popen_read("/usr/bin/tar", "-tzf", bottle_file, "*/*/INSTALL_RECEIPT.json").chomp
-end
-
-def bottle_resolve_formula_names(bottle_file)
- receipt_file_path = bottle_receipt_path bottle_file
- receipt_file = Utils.popen_read("tar", "-xOzf", bottle_file, receipt_file_path)
- name = receipt_file_path.split("/").first
- tap = Tab.from_file_content(receipt_file, "#{bottle_file}/#{receipt_file_path}").tap
-
- if tap.nil? || tap.core_tap?
- full_name = name
- else
- full_name = "#{tap}/#{name}"
- end
-
- [name, full_name]
-end
-
-def bottle_resolve_version(bottle_file)
- PkgVersion.parse bottle_receipt_path(bottle_file).split("/")[1]
-end
-
-class Bintray
- def self.package(formula_name)
- formula_name.to_s.tr("+", "x")
- end
-
- def self.repository(tap = nil)
- if tap.nil? || tap.core_tap?
- "bottles"
- else
- "bottles-#{tap.repo}"
- end
- end
-end
-
-class BottleCollector
- def initialize
- @checksums = {}
- end
-
- def fetch_checksum_for(tag)
- tag = find_matching_tag(tag)
- return self[tag], tag if tag
- end
-
- def keys
- @checksums.keys
- end
-
- def [](key)
- @checksums[key]
- end
-
- def []=(key, value)
- @checksums[key] = value
- end
-
- def key?(key)
- @checksums.key?(key)
- end
-
- private
-
- def find_matching_tag(tag)
- if key?(tag)
- tag
- else
- find_altivec_tag(tag) || find_or_later_tag(tag)
- end
- end
-
- # This allows generic Altivec PPC bottles to be supported in some
- # formulae, while also allowing specific bottles in others; e.g.,
- # sometimes a formula has just :tiger_altivec, other times it has
- # :tiger_g4, :tiger_g5, etc.
- def find_altivec_tag(tag)
- if tag.to_s =~ /(\w+)_(g4|g4e|g5)$/
- altivec_tag = "#{$1}_altivec".to_sym
- altivec_tag if key?(altivec_tag)
- end
- end
-
- # Allows a bottle tag to specify a specific OS or later,
- # so the same bottle can target multiple OSs.
- # Not used in core, used in taps.
- def find_or_later_tag(tag)
- begin
- tag_version = MacOS::Version.from_symbol(tag)
- rescue ArgumentError
- return
- end
-
- keys.find do |key|
- 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
- end
- end
- end
-end
diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb
index 2dba60bb9..88d276bf4 100644
--- a/Library/Homebrew/cleanup.rb
+++ b/Library/Homebrew/cleanup.rb
@@ -1,4 +1,4 @@
-require "bottles"
+require "utils/bottles"
require "formula"
require "thread"
@@ -67,7 +67,7 @@ module Homebrew
file = path
if Pathname::BOTTLE_EXTNAME_RX === file.to_s
- version = bottle_resolve_version(file) rescue file.version
+ version = Utils::Bottles.resolve_version(file) rescue file.version
else
version = file.version
end
diff --git a/Library/Homebrew/cmd/bottle.rb b/Library/Homebrew/cmd/bottle.rb
index 59e122f41..2f8f7f615 100644
--- a/Library/Homebrew/cmd/bottle.rb
+++ b/Library/Homebrew/cmd/bottle.rb
@@ -1,5 +1,5 @@
require "formula"
-require "bottles"
+require "utils/bottles"
require "tab"
require "keg"
require "formula_versions"
@@ -155,7 +155,7 @@ module Homebrew
return
end
- unless built_as_bottle? f
+ unless Utils::Bottles::built_as? f
return ofail "Formula not installed with '--build-bottle': #{f.full_name}"
end
@@ -175,7 +175,7 @@ module Homebrew
bottle_revision = bottle_revisions.any? ? bottle_revisions.max.to_i + 1 : 0
end
- filename = Bottle::Filename.create(f, bottle_tag, bottle_revision)
+ filename = Bottle::Filename.create(f, Utils::Bottles.tag, bottle_revision)
bottle_path = Pathname.pwd/filename
tar_filename = filename.to_s.sub(/.gz$/, "")
@@ -281,7 +281,7 @@ module Homebrew
bottle.prefix prefix
end
bottle.revision bottle_revision
- bottle.sha256 bottle_path.sha256 => bottle_tag
+ bottle.sha256 bottle_path.sha256 => Utils::Bottles.tag
old_spec = f.bottle_specification
if ARGV.include?("--keep-old") && !old_spec.checksums.empty?
diff --git a/Library/Homebrew/cmd/pull.rb b/Library/Homebrew/cmd/pull.rb
index 6f7136cf8..654461edb 100644
--- a/Library/Homebrew/cmd/pull.rb
+++ b/Library/Homebrew/cmd/pull.rb
@@ -32,7 +32,6 @@ require "utils/json"
require "formula"
require "formulary"
require "tap"
-require "bottles"
require "version"
require "pkg_version"
@@ -402,8 +401,8 @@ module Homebrew
# Publishes the current bottle files for a given formula to Bintray
def publish_bottle_file_on_bintray(f, creds)
- repo = Bintray.repository(f.tap)
- package = Bintray.package(f.name)
+ repo = Utils::Bottles::Bintray.repository(f.tap)
+ package = Utils::Bottles::Bintray.package(f.name)
info = FormulaInfoFromJson.lookup(f.name)
if info.nil?
raise "Failed publishing bottle: failed reading formula info for #{f.full_name}"
diff --git a/Library/Homebrew/cmd/test-bot.rb b/Library/Homebrew/cmd/test-bot.rb
index 13b5bd55c..a01467036 100644
--- a/Library/Homebrew/cmd/test-bot.rb
+++ b/Library/Homebrew/cmd/test-bot.rb
@@ -576,7 +576,7 @@ module Homebrew
bottle_step = steps.last
if bottle_step.passed? && bottle_step.has_output?
bottle_filename =
- bottle_step.output.gsub(/.*(\.\/\S+#{bottle_native_regex}).*/m, '\1')
+ bottle_step.output.gsub(/.*(\.\/\S+#{Utils::Bottles::native_regex}).*/m, '\1')
bottle_rb_filename = bottle_filename.gsub(/\.(\d+\.)?tar\.gz$/, ".rb")
bottle_merge_args = ["--merge", "--write", "--no-commit", bottle_rb_filename]
bottle_merge_args << "--keep-old" if ARGV.include? "--keep-old"
@@ -824,15 +824,15 @@ module Homebrew
remote = "git@github.com:BrewTestBot/homebrew-#{tap.repo}.git"
tag = pr ? "pr-#{pr}" : "testing-#{number}"
- bintray_repo = Bintray.repository(tap)
+ bintray_repo = Utils::Bottles::Bintray.repository(tap)
bintray_repo_url = "https://api.bintray.com/packages/homebrew/#{bintray_repo}"
formula_packaged = {}
Dir.glob("*.bottle*.tar.gz") do |filename|
- formula_name, canonical_formula_name = bottle_resolve_formula_names filename
+ formula_name, canonical_formula_name = Utils::Bottles.resolve_formula_names filename
formula = Formulary.factory canonical_formula_name
version = formula.pkg_version
- bintray_package = Bintray.package formula_name
+ bintray_package = Utils::Bottles::Bintray.package formula_name
if system "curl", "-I", "--silent", "--fail", "--output", "/dev/null",
"#{BottleSpecification::DEFAULT_DOMAIN}/#{bintray_repo}/#{filename}"
diff --git a/Library/Homebrew/extend/os/bottles.rb b/Library/Homebrew/extend/os/bottles.rb
new file mode 100644
index 000000000..aff9300de
--- /dev/null
+++ b/Library/Homebrew/extend/os/bottles.rb
@@ -0,0 +1,5 @@
+require "utils/bottles"
+
+if OS.mac?
+ require "extend/os/mac/utils/bottles"
+end
diff --git a/Library/Homebrew/extend/os/mac/utils/bottles.rb b/Library/Homebrew/extend/os/mac/utils/bottles.rb
new file mode 100644
index 000000000..6b83ad6c4
--- /dev/null
+++ b/Library/Homebrew/extend/os/mac/utils/bottles.rb
@@ -0,0 +1,59 @@
+module Utils
+ class Bottles
+ class << self
+ def tag
+ if MacOS.version >= :lion
+ MacOS.cat
+ elsif MacOS.version == :snow_leopard
+ Hardware::CPU.is_64_bit? ? :snow_leopard : :snow_leopard_32
+ else
+ # Return, e.g., :tiger_g3, :leopard_g5_64, :leopard_64 (which is Intel)
+ if Hardware::CPU.type == :ppc
+ tag = "#{MacOS.cat}_#{Hardware::CPU.family}".to_sym
+ else
+ tag = MacOS.cat
+ end
+ MacOS.prefer_64_bit? ? "#{tag}_64".to_sym : tag
+ end
+ end
+ end
+
+ class Collector
+ private
+
+ alias_method :original_find_matching_tag, :find_matching_tag
+ def find_matching_tag(tag)
+ original_find_matching_tag(tag) || find_altivec_tag(tag) || find_or_later_tag(tag)
+ end
+
+ # This allows generic Altivec PPC bottles to be supported in some
+ # formulae, while also allowing specific bottles in others; e.g.,
+ # sometimes a formula has just :tiger_altivec, other times it has
+ # :tiger_g4, :tiger_g5, etc.
+ def find_altivec_tag(tag)
+ if tag.to_s =~ /(\w+)_(g4|g4e|g5)$/
+ altivec_tag = "#{$1}_altivec".to_sym
+ altivec_tag if key?(altivec_tag)
+ end
+ end
+
+ # Allows a bottle tag to specify a specific OS or later,
+ # so the same bottle can target multiple OSs.
+ # Not used in core, used in taps.
+ def find_or_later_tag(tag)
+ begin
+ tag_version = MacOS::Version.from_symbol(tag)
+ rescue ArgumentError
+ return
+ end
+
+ keys.find do |key|
+ 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
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index a25a78f44..b8889225e 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -2,7 +2,7 @@ require "formula_support"
require "formula_lock"
require "formula_pin"
require "hardware"
-require "bottles"
+require "utils/bottles"
require "build_environment"
require "build_options"
require "formulary"
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index 4b8dcf202..00678935d 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -3,7 +3,7 @@ require "exceptions"
require "formula"
require "keg"
require "tab"
-require "bottles"
+require "utils/bottles"
require "caveats"
require "cleaner"
require "formula_cellar_checks"
diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb
index 28e79c68f..1d31995c1 100644
--- a/Library/Homebrew/formulary.rb
+++ b/Library/Homebrew/formulary.rb
@@ -92,7 +92,7 @@ class Formulary
class BottleLoader < FormulaLoader
def initialize(bottle_name)
@bottle_filename = Pathname(bottle_name).realpath
- name, full_name = bottle_resolve_formula_names @bottle_filename
+ name, full_name = Utils::Bottles.resolve_formula_names @bottle_filename
super name, Formulary.path(full_name)
end
@@ -100,7 +100,7 @@ class Formulary
formula = super
formula.local_bottle_path = @bottle_filename
formula_version = formula.pkg_version
- bottle_version = bottle_resolve_version(@bottle_filename)
+ bottle_version = Utils::Bottles.resolve_version(@bottle_filename)
unless formula_version == bottle_version
raise BottleVersionMismatchError.new(@bottle_filename, bottle_version, formula, formula_version)
end
diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb
index 6477dfd56..52885772c 100644
--- a/Library/Homebrew/software_spec.rb
+++ b/Library/Homebrew/software_spec.rb
@@ -5,7 +5,7 @@ require "version"
require "options"
require "build_options"
require "dependency_collector"
-require "bottles"
+require "utils/bottles"
require "patch"
require "compilers"
@@ -80,7 +80,7 @@ class SoftwareSpec
end
def bottled?
- bottle_specification.tag?(bottle_tag) && \
+ bottle_specification.tag?(Utils::Bottles.tag) && \
(bottle_specification.compatible_cellar? || ARGV.force_bottle?)
end
@@ -254,7 +254,7 @@ class Bottle
@resource.owner = formula
@spec = spec
- checksum, tag = spec.checksum_for(bottle_tag)
+ checksum, tag = spec.checksum_for(Utils::Bottles.tag)
filename = Filename.create(formula, tag, spec.revision)
@resource.url(build_url(spec.root_url, filename))
@@ -299,12 +299,12 @@ class BottleSpecification
@revision = 0
@prefix = DEFAULT_PREFIX
@cellar = DEFAULT_CELLAR
- @collector = BottleCollector.new
+ @collector = Utils::Bottles::Collector.new
end
def root_url(var = nil)
if var.nil?
- @root_url ||= "#{DEFAULT_DOMAIN}/#{Bintray.repository(tap)}"
+ @root_url ||= "#{DEFAULT_DOMAIN}/#{Utils::Bottles::Bintray.repository(tap)}"
else
@root_url = var
end
diff --git a/Library/Homebrew/test/test_bottle_collector.rb b/Library/Homebrew/test/test_bottle_collector.rb
index 2621d1272..fa356cb93 100644
--- a/Library/Homebrew/test/test_bottle_collector.rb
+++ b/Library/Homebrew/test/test_bottle_collector.rb
@@ -1,9 +1,9 @@
require "testing_env"
-require "bottles"
+require "utils/bottles"
class BottleCollectorTests < Homebrew::TestCase
def setup
- @collector = BottleCollector.new
+ @collector = Utils::Bottles::Collector.new
end
def checksum_for(tag)
diff --git a/Library/Homebrew/test/test_bottle_tag.rb b/Library/Homebrew/test/test_bottle_tag.rb
index 2bcbbf26d..174c7d14e 100644
--- a/Library/Homebrew/test/test_bottle_tag.rb
+++ b/Library/Homebrew/test/test_bottle_tag.rb
@@ -1,5 +1,5 @@
require "testing_env"
-require "bottles"
+require "utils/bottles"
class BottleTagTests < Homebrew::TestCase
def test_tag_tiger_ppc
@@ -7,14 +7,14 @@ class BottleTagTests < Homebrew::TestCase
Hardware::CPU.stubs(:type).returns(:ppc)
Hardware::CPU.stubs(:family).returns(:foo)
MacOS.stubs(:prefer_64_bit?).returns(false)
- assert_equal :tiger_foo, bottle_tag
+ assert_equal :tiger_foo, Utils::Bottles.tag
end
def test_tag_tiger_intel
MacOS.stubs(:version).returns(MacOS::Version.new("10.4"))
Hardware::CPU.stubs(:type).returns(:intel)
MacOS.stubs(:prefer_64_bit?).returns(false)
- assert_equal :tiger, bottle_tag
+ assert_equal :tiger, Utils::Bottles.tag
end
def test_tag_tiger_ppc_64
@@ -22,7 +22,7 @@ class BottleTagTests < Homebrew::TestCase
Hardware::CPU.stubs(:type).returns(:ppc)
Hardware::CPU.stubs(:family).returns(:g5)
MacOS.stubs(:prefer_64_bit?).returns(true)
- assert_equal :tiger_g5_64, bottle_tag
+ assert_equal :tiger_g5_64, Utils::Bottles.tag
end
# Note that this will probably never be used
@@ -30,14 +30,14 @@ class BottleTagTests < Homebrew::TestCase
MacOS.stubs(:version).returns(MacOS::Version.new("10.4"))
Hardware::CPU.stubs(:type).returns(:intel)
MacOS.stubs(:prefer_64_bit?).returns(true)
- assert_equal :tiger_64, bottle_tag
+ assert_equal :tiger_64, Utils::Bottles.tag
end
def test_tag_leopard_intel
MacOS.stubs(:version).returns(MacOS::Version.new("10.5"))
Hardware::CPU.stubs(:type).returns(:intel)
MacOS.stubs(:prefer_64_bit?).returns(false)
- assert_equal :leopard, bottle_tag
+ assert_equal :leopard, Utils::Bottles.tag
end
def test_tag_leopard_ppc_64
@@ -45,35 +45,35 @@ class BottleTagTests < Homebrew::TestCase
Hardware::CPU.stubs(:type).returns(:ppc)
Hardware::CPU.stubs(:family).returns(:g5)
MacOS.stubs(:prefer_64_bit?).returns(true)
- assert_equal :leopard_g5_64, bottle_tag
+ assert_equal :leopard_g5_64, Utils::Bottles.tag
end
def test_tag_leopard_intel_64
MacOS.stubs(:version).returns(MacOS::Version.new("10.5"))
Hardware::CPU.stubs(:type).returns(:intel)
MacOS.stubs(:prefer_64_bit?).returns(true)
- assert_equal :leopard_64, bottle_tag
+ assert_equal :leopard_64, Utils::Bottles.tag
end
def test_tag_snow_leopard_32
MacOS.stubs(:version).returns(MacOS::Version.new("10.6"))
Hardware::CPU.stubs(:is_64_bit?).returns(false)
- assert_equal :snow_leopard_32, bottle_tag
+ assert_equal :snow_leopard_32, Utils::Bottles.tag
end
def test_tag_snow_leopard_64
MacOS.stubs(:version).returns(MacOS::Version.new("10.6"))
Hardware::CPU.stubs(:is_64_bit?).returns(true)
- assert_equal :snow_leopard, bottle_tag
+ assert_equal :snow_leopard, Utils::Bottles.tag
end
def test_tag_lion
MacOS.stubs(:version).returns(MacOS::Version.new("10.7"))
- assert_equal :lion, bottle_tag
+ assert_equal :lion, Utils::Bottles.tag
end
def test_tag_mountain_lion
MacOS.stubs(:version).returns(MacOS::Version.new("10.8"))
- assert_equal :mountain_lion, bottle_tag
+ assert_equal :mountain_lion, Utils::Bottles.tag
end
end
diff --git a/Library/Homebrew/test/test_formulary.rb b/Library/Homebrew/test/test_formulary.rb
index ec18ee053..593e08cfa 100644
--- a/Library/Homebrew/test/test_formulary.rb
+++ b/Library/Homebrew/test/test_formulary.rb
@@ -1,7 +1,7 @@
require "testing_env"
require "formula"
require "formula_installer"
-require "bottles"
+require "utils/bottles"
class FormularyTest < Homebrew::TestCase
def test_class_naming
@@ -18,7 +18,7 @@ class FormularyFactoryTest < Homebrew::TestCase
@name = "testball_bottle"
@path = CoreTap.new.formula_dir/"#{@name}.rb"
@bottle_dir = Pathname.new("#{File.expand_path("..", __FILE__)}/bottles")
- @bottle = @bottle_dir/"testball_bottle-0.1.#{bottle_tag}.bottle.tar.gz"
+ @bottle = @bottle_dir/"testball_bottle-0.1.#{Utils::Bottles.tag}.bottle.tar.gz"
@path.write <<-EOS.undent
class #{Formulary.class_s(@name)} < Formula
url "file://#{File.expand_path("..", __FILE__)}/tarballs/testball-0.1.tbz"
@@ -27,7 +27,7 @@ class FormularyFactoryTest < Homebrew::TestCase
bottle do
cellar :any_skip_relocation
root_url "file://#{@bottle_dir}"
- sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :#{bottle_tag}
+ sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :#{Utils::Bottles.tag}
end
def install
diff --git a/Library/Homebrew/test/testball_bottle.rb b/Library/Homebrew/test/testball_bottle.rb
index 31e98364e..5aa582fa8 100644
--- a/Library/Homebrew/test/testball_bottle.rb
+++ b/Library/Homebrew/test/testball_bottle.rb
@@ -6,7 +6,7 @@ class TestballBottle < Formula
stable.bottle do
cellar :any_skip_relocation
root_url "file://#{File.expand_path("..", __FILE__)}/bottles"
- sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => bottle_tag
+ sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => Utils::Bottles.tag
end
cxxstdlib_check :skip
end
diff --git a/Library/Homebrew/utils/bottles.rb b/Library/Homebrew/utils/bottles.rb
new file mode 100644
index 000000000..6a05a7aeb
--- /dev/null
+++ b/Library/Homebrew/utils/bottles.rb
@@ -0,0 +1,104 @@
+require "tab"
+require "extend/ARGV"
+
+module Utils
+ class Bottles
+ class << self
+ def tag
+ @bottle_tag ||= "#{ENV["HOMEBREW_SYSTEM"]}-#{ENV["HOMEBREW_PROCESSOR"]}".downcase.to_sym
+ end
+
+ def built_as?(f)
+ return false unless f.installed?
+ tab = Tab.for_keg(f.installed_prefix)
+ tab.built_as_bottle
+ end
+
+ def file_outdated?(f, file)
+ filename = file.basename.to_s
+ return unless f.bottle && filename.match(Pathname::BOTTLE_EXTNAME_RX)
+
+ bottle_ext = filename[native_regex, 1]
+ bottle_url_ext = f.bottle.url[native_regex, 1]
+
+ bottle_ext && bottle_url_ext && bottle_ext != bottle_url_ext
+ end
+
+ def native_regex
+ /(\.#{Regexp.escape(tag)}\.bottle\.(\d+\.)?tar\.gz)$/o
+ end
+
+ def receipt_path(bottle_file)
+ Utils.popen_read("/usr/bin/tar", "-tzf", bottle_file, "*/*/INSTALL_RECEIPT.json").chomp
+ end
+
+ def resolve_formula_names(bottle_file)
+ receipt_file_path = receipt_path bottle_file
+ receipt_file = Utils.popen_read("tar", "-xOzf", bottle_file, receipt_file_path)
+ name = receipt_file_path.split("/").first
+ tap = Tab.from_file_content(receipt_file, "#{bottle_file}/#{receipt_file_path}").tap
+
+ if tap.nil? || tap.core_tap?
+ full_name = name
+ else
+ full_name = "#{tap}/#{name}"
+ end
+
+ [name, full_name]
+ end
+
+ def resolve_version(bottle_file)
+ PkgVersion.parse receipt_path(bottle_file).split("/")[1]
+ end
+ end
+
+ class Bintray
+ def self.package(formula_name)
+ formula_name.to_s.tr("+", "x")
+ end
+
+ def self.repository(tap = nil)
+ if tap.nil? || tap.core_tap?
+ "bottles"
+ else
+ "bottles-#{tap.repo}"
+ end
+ end
+ end
+
+ class Collector
+ def initialize
+ @checksums = {}
+ end
+
+ def fetch_checksum_for(tag)
+ tag = find_matching_tag(tag)
+ return self[tag], tag if tag
+ end
+
+ def keys
+ @checksums.keys
+ end
+
+ def [](key)
+ @checksums[key]
+ end
+
+ def []=(key, value)
+ @checksums[key] = value
+ end
+
+ def key?(key)
+ @checksums.key?(key)
+ end
+
+ private
+
+ def find_matching_tag(tag)
+ tag if key?(tag)
+ end
+ end
+ end
+end
+
+require "extend/os/bottles"
diff --git a/Library/brew.sh b/Library/brew.sh
index 76cb2f9e9..5589bcc68 100644
--- a/Library/brew.sh
+++ b/Library/brew.sh
@@ -118,7 +118,9 @@ export HOMEBREW_LIBRARY
export HOMEBREW_VERSION
export HOMEBREW_CELLAR
export HOMEBREW_RUBY_PATH
+export HOMEBREW_SYSTEM
export HOMEBREW_CURL
+export HOMEBREW_PROCESSOR
export HOMEBREW_PRODUCT
export HOMEBREW_OS_VERSION
export HOMEBREW_OSX_VERSION