Misty De Meo 3657393017 Move stdlib tracking postinstall
This moves stdlib tracking after the install completes, which allows
the tracking to have access to the actual stdlib in use.

This unfortunately means that builds can error out *after* a build,
resulting in wasted time; however, it reduces false positives, and the
overall user experience is still likely to be better this way.
2013-10-26 21:54:29 -07:00

137 lines
3.4 KiB
Ruby

require 'cxxstdlib'
require 'ostruct'
require 'options'
require 'utils/json'
# Inherit from OpenStruct to gain a generic initialization method that takes a
# hash and creates an attribute for each key and value. `Tab.new` probably
# should not be called directly, instead use one of the class methods like
# `Tab.create`.
class Tab < OpenStruct
FILENAME = 'INSTALL_RECEIPT.json'
def self.create f, compiler, stdlib, args
f.build.args = args
sha = HOMEBREW_REPOSITORY.cd do
`git rev-parse --verify -q HEAD 2>/dev/null`.chuzzle
end
Tab.new :used_options => f.build.used_options,
:unused_options => f.build.unused_options,
:tabfile => f.prefix.join(FILENAME),
:built_as_bottle => !!ARGV.build_bottle?,
:poured_from_bottle => false,
:tapped_from => f.tap,
:time => Time.now.to_i, # to_s would be better but Ruby has no from_s function :P
:HEAD => sha,
:compiler => compiler,
:stdlib => stdlib
end
def self.from_file path
tab = Tab.new Utils::JSON.load(File.read(path))
tab.tabfile = path
tab
end
def self.for_keg keg
path = keg.join(FILENAME)
if path.exist?
self.from_file(path)
else
self.dummy_tab
end
end
def self.for_name name
for_formula(Formula.factory(name))
end
def self.for_formula f
path = [f.opt_prefix, f.linked_keg].map{ |pn| pn.join(FILENAME) }.find{ |pn| pn.exist? }
# Legacy kegs may lack a receipt. If it doesn't exist, fake one
if path.nil? then self.dummy_tab(f) else self.from_file(path) end
end
def self.dummy_tab f=nil
Tab.new :used_options => [],
:unused_options => (f.build.as_flags rescue []),
:built_as_bottle => false,
:poured_from_bottle => false,
:tapped_from => "",
:time => nil,
:HEAD => nil,
:compiler => :clang
end
def with? name
if options.include? "with-#{name}"
used_options.include? "with-#{name}"
elsif options.include? "without-#{name}"
not used_options.include? "without-#{name}"
else
false
end
end
def include? opt
used_options.include? opt
end
def universal?
used_options.include? "universal"
end
def used_options
Options.coerce(super)
end
def unused_options
Options.coerce(super)
end
def options
used_options + unused_options
end
def cxxstdlib
# Older tabs won't have these values, so provide sensible defaults
lib = stdlib.to_sym if stdlib
cc = compiler || MacOS.default_compiler
CxxStdlib.new(lib, cc.to_sym)
end
def to_json
Utils::JSON.dump({
:used_options => used_options.map(&:to_s),
:unused_options => unused_options.map(&:to_s),
:built_as_bottle => built_as_bottle,
:poured_from_bottle => poured_from_bottle,
:tapped_from => tapped_from,
:time => time,
:HEAD => send("HEAD"),
:stdlib => (stdlib.to_s if stdlib),
:compiler => (compiler.to_s if compiler)})
end
def write
tabfile.write to_json
end
def to_s
s = []
case poured_from_bottle
when true then s << "Poured from bottle"
when false then s << "Built from source"
end
unless used_options.empty?
s << "Installed" if s.empty?
s << "with:"
s << used_options.to_a.join(", ")
end
s.join(" ")
end
end