2013-03-02 17:42:21 -06:00
|
|
|
# encoding: UTF-8
|
2013-02-19 14:27:17 -06:00
|
|
|
|
2013-07-27 02:07:29 -07:00
|
|
|
require 'cxxstdlib'
|
2010-11-09 12:57:41 +00:00
|
|
|
require 'exceptions'
|
2009-10-26 18:13:38 +00:00
|
|
|
require 'formula'
|
2011-08-23 23:30:52 +01:00
|
|
|
require 'keg'
|
2011-09-22 20:07:39 -07:00
|
|
|
require 'tab'
|
2012-03-07 21:30:03 -05:00
|
|
|
require 'bottles'
|
2013-01-01 17:26:50 +00:00
|
|
|
require 'caveats'
|
2013-06-23 12:48:45 -07:00
|
|
|
require 'cleaner'
|
2013-07-15 19:28:10 -07:00
|
|
|
require 'formula_cellar_checks'
|
2013-10-05 20:32:05 +01:00
|
|
|
require 'install_renamed'
|
2014-02-28 15:58:20 -06:00
|
|
|
require 'cmd/tap'
|
2014-03-31 13:15:07 -05:00
|
|
|
require 'hooks/bottles'
|
2009-10-26 18:13:38 +00:00
|
|
|
|
|
|
|
class FormulaInstaller
|
2013-07-15 19:28:10 -07:00
|
|
|
include FormulaCellarChecks
|
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
def self.mode_attr_accessor(*names)
|
|
|
|
attr_accessor(*names)
|
|
|
|
names.each { |name| define_method("#{name}?") { !!send(name) }}
|
|
|
|
end
|
|
|
|
|
2013-02-17 22:52:39 -06:00
|
|
|
attr_reader :f
|
2014-03-13 10:11:00 -05:00
|
|
|
attr_accessor :options
|
|
|
|
mode_attr_accessor :show_summary_heading, :show_header
|
|
|
|
mode_attr_accessor :build_from_source, :build_bottle, :force_bottle
|
2014-03-13 10:11:00 -05:00
|
|
|
mode_attr_accessor :ignore_deps, :only_deps, :interactive
|
2014-03-13 10:11:00 -05:00
|
|
|
mode_attr_accessor :verbose, :debug
|
2009-10-26 18:13:38 +00:00
|
|
|
|
2013-01-23 00:26:27 -06:00
|
|
|
def initialize ff
|
2011-08-23 23:30:52 +01:00
|
|
|
@f = ff
|
2012-08-22 19:49:17 -05:00
|
|
|
@show_header = false
|
2014-03-04 14:06:25 -06:00
|
|
|
@ignore_deps = false
|
|
|
|
@only_deps = false
|
2014-03-08 22:28:50 -06:00
|
|
|
@build_from_source = false
|
|
|
|
@build_bottle = false
|
2014-03-10 14:56:02 -05:00
|
|
|
@force_bottle = false
|
2014-03-13 10:11:00 -05:00
|
|
|
@interactive = false
|
2014-03-13 10:11:00 -05:00
|
|
|
@verbose = false
|
2014-03-13 10:11:00 -05:00
|
|
|
@debug = false
|
2013-01-23 00:26:28 -06:00
|
|
|
@options = Options.new
|
2012-03-07 11:16:27 +00:00
|
|
|
|
2013-01-13 15:39:50 -06:00
|
|
|
@@attempted ||= Set.new
|
|
|
|
|
2013-12-12 15:42:31 -06:00
|
|
|
@poured_bottle = false
|
|
|
|
@pour_failed = false
|
2012-03-07 11:16:27 +00:00
|
|
|
end
|
|
|
|
|
2013-09-18 12:36:43 +01:00
|
|
|
def pour_bottle? install_bottle_options={:warn=>false}
|
2014-03-31 13:15:07 -05:00
|
|
|
return true if Homebrew::Hooks::Bottles.formula_has_bottle?(f)
|
|
|
|
|
2013-11-14 15:25:56 -05:00
|
|
|
return false if @pour_failed
|
2014-03-13 10:11:00 -05:00
|
|
|
return true if force_bottle? && f.bottle
|
2014-03-19 22:45:56 -05:00
|
|
|
return false if build_from_source? || build_bottle? || interactive?
|
2014-03-10 14:56:02 -05:00
|
|
|
return false unless options.empty?
|
|
|
|
|
|
|
|
return true if f.local_bottle_path
|
|
|
|
return false unless f.bottle && f.pour_bottle?
|
|
|
|
|
|
|
|
unless f.bottle.compatible_cellar?
|
|
|
|
if install_bottle_options[:warn]
|
2014-09-14 11:18:55 -05:00
|
|
|
opoo "Building source; cellar of #{f.name}'s bottle is #{f.bottle.cellar}"
|
2014-03-10 14:56:02 -05:00
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
def install_bottle_for_dep?(dep, build)
|
2014-03-13 10:11:00 -05:00
|
|
|
return false if build_from_source?
|
2014-03-10 14:56:02 -05:00
|
|
|
return false unless dep.bottle && dep.pour_bottle?
|
|
|
|
return false unless build.used_options.empty?
|
|
|
|
return false unless dep.bottle.compatible_cellar?
|
|
|
|
return true
|
2013-01-23 00:26:27 -06:00
|
|
|
end
|
|
|
|
|
2014-03-04 14:06:25 -06:00
|
|
|
def prelude
|
2014-03-13 10:11:00 -05:00
|
|
|
verify_deps_exist unless ignore_deps?
|
2014-03-04 14:06:25 -06:00
|
|
|
lock
|
|
|
|
check_install_sanity
|
|
|
|
end
|
|
|
|
|
2014-02-28 11:16:55 -06:00
|
|
|
def verify_deps_exist
|
2014-06-17 00:04:21 -05:00
|
|
|
begin
|
|
|
|
f.recursive_dependencies.map(&:to_formula)
|
|
|
|
rescue TapFormulaUnavailableError => e
|
|
|
|
if Homebrew.install_tap(e.user, e.repo)
|
|
|
|
retry
|
|
|
|
else
|
|
|
|
raise
|
|
|
|
end
|
|
|
|
end
|
2014-02-28 11:16:55 -06:00
|
|
|
rescue FormulaUnavailableError => e
|
|
|
|
e.dependent = f.name
|
|
|
|
raise
|
|
|
|
end
|
|
|
|
|
2012-03-07 11:16:27 +00:00
|
|
|
def check_install_sanity
|
2013-01-08 19:54:32 -06:00
|
|
|
raise FormulaInstallationAlreadyAttemptedError, f if @@attempted.include? f
|
|
|
|
|
2012-03-07 11:16:27 +00:00
|
|
|
if f.installed?
|
2014-09-14 11:18:55 -05:00
|
|
|
msg = "#{f.name}-#{f.installed_version} already installed"
|
2013-09-07 11:08:51 -05:00
|
|
|
msg << ", it's just not linked" unless f.linked_keg.symlink? or f.keg_only?
|
2013-04-03 18:26:40 -05:00
|
|
|
raise FormulaAlreadyInstalledError, msg
|
2012-03-07 11:16:27 +00:00
|
|
|
end
|
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
unless ignore_deps?
|
2013-01-23 00:26:29 -06:00
|
|
|
unlinked_deps = f.recursive_dependencies.map(&:to_formula).select do |dep|
|
2012-08-19 17:36:10 -04:00
|
|
|
dep.installed? and not dep.keg_only? and not dep.linked_keg.directory?
|
2012-03-15 12:32:03 +00:00
|
|
|
end
|
2012-08-19 17:36:10 -04:00
|
|
|
raise CannotInstallFormulaError,
|
2014-09-14 11:18:55 -05:00
|
|
|
"You must `brew link #{unlinked_deps*' '}' before #{f.name} can be installed" unless unlinked_deps.empty?
|
2012-08-19 17:36:10 -04:00
|
|
|
end
|
2009-10-26 18:13:38 +00:00
|
|
|
end
|
|
|
|
|
2013-10-05 20:32:05 +01:00
|
|
|
def build_bottle_preinstall
|
|
|
|
@etc_var_glob ||= "#{HOMEBREW_PREFIX}/{etc,var}/**/*"
|
|
|
|
@etc_var_preinstall = Dir[@etc_var_glob]
|
|
|
|
end
|
|
|
|
|
|
|
|
def build_bottle_postinstall
|
|
|
|
@etc_var_postinstall = Dir[@etc_var_glob]
|
|
|
|
(@etc_var_postinstall - @etc_var_preinstall).each do |file|
|
|
|
|
Pathname.new(file).cp_path_sub(HOMEBREW_PREFIX, f.bottle_prefix)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-08-23 23:30:52 +01:00
|
|
|
def install
|
2012-03-07 11:16:27 +00:00
|
|
|
# not in initialize so upgrade can unlink the active keg before calling this
|
|
|
|
# function but after instantiating this class so that it can avoid having to
|
|
|
|
# relink the active keg if possible (because it is slow).
|
|
|
|
if f.linked_keg.directory?
|
|
|
|
# some other version is already installed *and* linked
|
|
|
|
raise CannotInstallFormulaError, <<-EOS.undent
|
2014-09-14 11:18:55 -05:00
|
|
|
#{f.name}-#{f.linked_keg.resolved_path.basename} already installed
|
|
|
|
To install this version, first `brew unlink #{f.name}'
|
2012-03-07 11:16:27 +00:00
|
|
|
EOS
|
|
|
|
end
|
2011-03-09 21:01:23 -08:00
|
|
|
|
2013-06-09 13:44:59 -05:00
|
|
|
check_conflicts
|
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
compute_and_install_dependencies unless ignore_deps?
|
2010-01-13 09:00:24 +00:00
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
return if only_deps?
|
2013-12-16 16:37:59 -08:00
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
if build_bottle? && (arch = ARGV.bottle_arch) && !Hardware::CPU.optimization_flags.include?(arch)
|
2013-08-25 14:57:26 -07:00
|
|
|
raise "Unrecognized architecture for --bottle-arch: #{arch}"
|
|
|
|
end
|
|
|
|
|
2014-09-14 11:18:55 -05:00
|
|
|
oh1 "Installing #{Tty.green}#{f.name}#{Tty.reset}" if show_header?
|
2011-08-23 23:30:52 +01:00
|
|
|
|
2013-01-13 15:39:50 -06:00
|
|
|
@@attempted << f
|
|
|
|
|
2013-02-18 07:28:06 +00:00
|
|
|
begin
|
2013-09-18 12:36:43 +01:00
|
|
|
if pour_bottle? :warn => true
|
2013-02-18 07:28:06 +00:00
|
|
|
pour
|
2013-03-11 18:56:26 +00:00
|
|
|
@poured_bottle = true
|
2013-10-23 22:25:02 -07:00
|
|
|
|
2014-08-22 22:18:03 -05:00
|
|
|
CxxStdlib.check_compatibility(
|
|
|
|
f, f.recursive_dependencies,
|
|
|
|
Keg.new(f.prefix), MacOS.default_compiler
|
|
|
|
)
|
2013-10-23 22:25:02 -07:00
|
|
|
|
2013-03-15 00:28:18 +00:00
|
|
|
tab = Tab.for_keg f.prefix
|
|
|
|
tab.poured_from_bottle = true
|
|
|
|
tab.write
|
2013-02-18 07:28:06 +00:00
|
|
|
end
|
2014-02-02 21:28:56 +00:00
|
|
|
rescue => e
|
|
|
|
raise e if ARGV.homebrew_developer?
|
2013-11-14 15:25:56 -05:00
|
|
|
@pour_failed = true
|
2014-02-02 21:28:56 +00:00
|
|
|
onoe e.message
|
2013-02-18 07:28:06 +00:00
|
|
|
opoo "Bottle installation failed: building from source."
|
|
|
|
end
|
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
build_bottle_preinstall if build_bottle?
|
2013-10-05 20:32:05 +01:00
|
|
|
|
2013-03-11 18:56:26 +00:00
|
|
|
unless @poured_bottle
|
2014-03-13 10:11:00 -05:00
|
|
|
compute_and_install_dependencies if @pour_failed and not ignore_deps?
|
2011-08-23 23:30:52 +01:00
|
|
|
build
|
|
|
|
clean
|
2010-02-09 11:30:16 -08:00
|
|
|
end
|
2011-08-23 23:30:52 +01:00
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
build_bottle_postinstall if build_bottle?
|
2013-10-05 20:32:05 +01:00
|
|
|
|
2012-08-10 16:04:56 -04:00
|
|
|
opoo "Nothing was installed to #{f.prefix}" unless f.installed?
|
2010-02-09 11:30:16 -08:00
|
|
|
end
|
|
|
|
|
2013-06-08 15:14:01 -05:00
|
|
|
# HACK: If readline is present in the dependency tree, it will clash
|
|
|
|
# with the stdlib's Readline module when the debugger is loaded
|
|
|
|
def perform_readline_hack
|
2014-03-25 01:36:12 -05:00
|
|
|
if (f.recursive_dependencies.any? { |d| d.name == "readline" } || f.name == "readline") && debug?
|
2013-06-08 15:14:01 -05:00
|
|
|
ENV['HOMEBREW_NO_READLINE'] = '1'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-09 13:44:59 -05:00
|
|
|
def check_conflicts
|
|
|
|
return if ARGV.force?
|
|
|
|
|
|
|
|
conflicts = f.conflicts.reject do |c|
|
2014-06-22 15:00:15 -05:00
|
|
|
keg = Formulary.factory(c.name).prefix
|
2013-06-09 13:44:59 -05:00
|
|
|
not keg.directory? && Keg.new(keg).linked?
|
|
|
|
end
|
|
|
|
|
|
|
|
raise FormulaConflictError.new(f, conflicts) unless conflicts.empty?
|
|
|
|
end
|
|
|
|
|
2013-12-02 12:44:28 -06:00
|
|
|
def compute_and_install_dependencies
|
|
|
|
perform_readline_hack
|
2013-12-09 14:36:10 -06:00
|
|
|
|
2013-12-09 14:36:10 -06:00
|
|
|
req_map, req_deps = expand_requirements
|
|
|
|
|
|
|
|
check_requirements(req_map)
|
|
|
|
|
2014-08-13 20:34:11 -05:00
|
|
|
deps = expand_dependencies(req_deps + f.deps)
|
2013-12-09 14:36:10 -06:00
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
if deps.empty? and only_deps?
|
2014-09-14 11:18:55 -05:00
|
|
|
puts "All dependencies for #{f.name} are satisfied."
|
2013-12-19 16:36:49 -06:00
|
|
|
else
|
|
|
|
install_dependencies(deps)
|
|
|
|
end
|
2013-12-02 12:44:28 -06:00
|
|
|
end
|
|
|
|
|
2013-12-09 14:36:10 -06:00
|
|
|
def check_requirements(req_map)
|
|
|
|
fatals = []
|
|
|
|
|
|
|
|
req_map.each_pair do |dependent, reqs|
|
|
|
|
reqs.each do |req|
|
|
|
|
puts "#{dependent}: #{req.message}"
|
|
|
|
fatals << req if req.fatal?
|
2013-01-27 23:57:34 -06:00
|
|
|
end
|
2013-01-23 00:26:24 -06:00
|
|
|
end
|
|
|
|
|
2014-09-14 01:10:20 -05:00
|
|
|
raise UnsatisfiedRequirements.new(fatals) unless fatals.empty?
|
2013-01-23 00:26:24 -06:00
|
|
|
end
|
|
|
|
|
2014-08-11 15:32:19 +01:00
|
|
|
def install_requirement_default_formula?(req, build)
|
2014-07-06 17:22:56 +01:00
|
|
|
return false unless req.default_formula?
|
2014-08-11 20:15:25 +01:00
|
|
|
return false if build.without?(req) && (req.recommended? || req.optional?)
|
2014-07-06 17:22:56 +01:00
|
|
|
return true unless req.satisfied?
|
|
|
|
pour_bottle? || build_bottle?
|
|
|
|
end
|
|
|
|
|
2013-12-09 14:36:10 -06:00
|
|
|
def expand_requirements
|
|
|
|
unsatisfied_reqs = Hash.new { |h, k| h[k] = [] }
|
|
|
|
deps = []
|
|
|
|
formulae = [f]
|
|
|
|
|
|
|
|
while f = formulae.pop
|
|
|
|
|
2014-06-19 21:35:47 -05:00
|
|
|
f.recursive_requirements do |dependent, req|
|
|
|
|
build = effective_build_options_for(dependent)
|
|
|
|
|
|
|
|
if (req.optional? || req.recommended?) && build.without?(req)
|
|
|
|
Requirement.prune
|
2014-09-16 22:32:18 -05:00
|
|
|
elsif req.build? && dependent == self.f && pour_bottle?
|
2014-06-19 21:35:47 -05:00
|
|
|
Requirement.prune
|
2014-09-16 22:32:18 -05:00
|
|
|
elsif req.build? && dependent != self.f && install_bottle_for_dep?(dependent, build)
|
2014-06-19 21:35:47 -05:00
|
|
|
Requirement.prune
|
2014-08-11 15:32:19 +01:00
|
|
|
elsif install_requirement_default_formula?(req, build)
|
2014-06-19 21:35:47 -05:00
|
|
|
dep = req.to_dependency
|
|
|
|
deps.unshift(dep)
|
|
|
|
formulae.unshift(dep.to_formula)
|
|
|
|
Requirement.prune
|
2014-08-10 16:41:30 +01:00
|
|
|
elsif req.satisfied?
|
2014-07-06 17:22:56 +01:00
|
|
|
Requirement.prune
|
2014-06-19 21:35:47 -05:00
|
|
|
else
|
|
|
|
unsatisfied_reqs[dependent] << req
|
2013-12-09 14:36:10 -06:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return unsatisfied_reqs, deps
|
|
|
|
end
|
|
|
|
|
2013-12-09 14:36:10 -06:00
|
|
|
def expand_dependencies(deps)
|
2014-02-27 14:22:43 -06:00
|
|
|
inherited_options = {}
|
|
|
|
|
2014-06-19 21:35:47 -05:00
|
|
|
expanded_deps = Dependency.expand(f, deps) do |dependent, dep|
|
2014-08-24 16:14:16 -05:00
|
|
|
options = inherited_options[dep.name] = inherited_options_for(dep)
|
2014-06-19 21:35:47 -05:00
|
|
|
build = effective_build_options_for(
|
|
|
|
dependent,
|
|
|
|
inherited_options.fetch(dependent.name, [])
|
|
|
|
)
|
|
|
|
|
|
|
|
if (dep.optional? || dep.recommended?) && build.without?(dep)
|
|
|
|
Dependency.prune
|
|
|
|
elsif dep.build? && dependent == f && pour_bottle?
|
|
|
|
Dependency.prune
|
|
|
|
elsif dep.build? && dependent != f && install_bottle_for_dep?(dependent, build)
|
|
|
|
Dependency.prune
|
|
|
|
elsif dep.satisfied?(options)
|
|
|
|
Dependency.skip
|
2013-06-03 22:50:11 -05:00
|
|
|
end
|
2013-01-23 00:26:25 -06:00
|
|
|
end
|
2014-02-27 14:22:43 -06:00
|
|
|
|
2014-08-24 16:14:16 -05:00
|
|
|
expanded_deps.map { |dep| [dep, inherited_options[dep.name]] }
|
2014-02-27 14:22:43 -06:00
|
|
|
end
|
|
|
|
|
2014-04-05 10:40:04 -05:00
|
|
|
def effective_build_options_for(dependent, inherited_options=[])
|
2014-08-11 17:48:30 -05:00
|
|
|
args = dependent.build.used_options
|
|
|
|
args |= dependent == f ? options : inherited_options
|
2014-08-24 14:46:34 -05:00
|
|
|
args |= Tab.for_formula(dependent).used_options
|
2014-08-11 17:48:30 -05:00
|
|
|
BuildOptions.new(args, dependent.options)
|
2014-03-02 14:02:18 -06:00
|
|
|
end
|
|
|
|
|
2014-03-02 14:02:17 -06:00
|
|
|
def inherited_options_for(dep)
|
2014-04-04 10:12:09 -05:00
|
|
|
inherited_options = Options.new
|
2014-07-31 19:37:39 -05:00
|
|
|
u = Option.new("universal")
|
2014-08-16 01:33:41 -05:00
|
|
|
if (options.include?(u) || f.require_universal_deps?) && !dep.build? && dep.to_formula.option_defined?(u)
|
2014-07-31 19:37:39 -05:00
|
|
|
inherited_options << u
|
2014-03-01 18:54:00 -06:00
|
|
|
end
|
2014-04-04 10:12:09 -05:00
|
|
|
inherited_options
|
2013-01-23 00:26:25 -06:00
|
|
|
end
|
|
|
|
|
2013-12-09 14:36:10 -06:00
|
|
|
def install_dependencies(deps)
|
|
|
|
if deps.length > 1
|
2014-09-14 11:18:55 -05:00
|
|
|
oh1 "Installing dependencies for #{f.name}: #{Tty.green}#{deps.map(&:first)*", "}#{Tty.reset}"
|
2013-10-16 15:34:43 -05:00
|
|
|
end
|
|
|
|
|
2014-06-19 21:35:47 -05:00
|
|
|
deps.each { |dep, options| install_dependency(dep, options) }
|
2014-02-27 14:22:42 -06:00
|
|
|
|
2013-12-09 14:36:10 -06:00
|
|
|
@show_header = true unless deps.empty?
|
2013-01-23 00:26:25 -06:00
|
|
|
end
|
|
|
|
|
2014-03-13 19:10:49 -05:00
|
|
|
class DependencyInstaller < FormulaInstaller
|
|
|
|
def initialize ff
|
|
|
|
super
|
|
|
|
@ignore_deps = true
|
|
|
|
end
|
|
|
|
|
|
|
|
def sanitized_ARGV_options
|
|
|
|
args = super
|
|
|
|
args.delete "--ignore-dependencies"
|
|
|
|
args
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-02-27 14:22:43 -06:00
|
|
|
def install_dependency(dep, inherited_options)
|
2014-02-27 14:22:42 -06:00
|
|
|
df = dep.to_formula
|
2014-04-05 10:48:54 -05:00
|
|
|
tab = Tab.for_formula(df)
|
2013-01-23 00:26:27 -06:00
|
|
|
|
2014-04-05 10:48:54 -05:00
|
|
|
if df.linked_keg.directory?
|
2014-04-05 12:17:19 -05:00
|
|
|
linked_keg = Keg.new(df.linked_keg.resolved_path)
|
2014-04-05 10:48:54 -05:00
|
|
|
linked_keg.unlink
|
|
|
|
end
|
|
|
|
|
|
|
|
if df.installed?
|
|
|
|
installed_keg = Keg.new(df.prefix)
|
|
|
|
tmp_keg = Pathname.new("#{installed_keg}.tmp")
|
|
|
|
installed_keg.rename(tmp_keg)
|
|
|
|
end
|
2012-03-07 13:48:04 +00:00
|
|
|
|
2014-03-13 19:10:49 -05:00
|
|
|
fi = DependencyInstaller.new(df)
|
2014-04-05 10:48:54 -05:00
|
|
|
fi.options |= tab.used_options
|
2014-03-13 10:11:00 -05:00
|
|
|
fi.options |= dep.options
|
|
|
|
fi.options |= inherited_options
|
|
|
|
fi.build_from_source = build_from_source?
|
|
|
|
fi.verbose = verbose? unless verbose == :quieter
|
|
|
|
fi.debug = debug?
|
2014-03-04 14:06:25 -06:00
|
|
|
fi.prelude
|
2014-09-14 11:18:55 -05:00
|
|
|
oh1 "Installing #{f.name} dependency: #{Tty.green}#{dep.name}#{Tty.reset}"
|
2011-11-26 21:03:46 -08:00
|
|
|
fi.install
|
|
|
|
fi.caveats
|
|
|
|
fi.finish
|
2014-04-05 10:48:54 -05:00
|
|
|
rescue Exception
|
2014-04-05 10:48:54 -05:00
|
|
|
ignore_interrupts do
|
|
|
|
tmp_keg.rename(installed_keg) if tmp_keg && !installed_keg.directory?
|
|
|
|
linked_keg.link if linked_keg
|
|
|
|
end
|
2014-04-05 10:48:54 -05:00
|
|
|
raise
|
|
|
|
else
|
2014-04-05 10:48:54 -05:00
|
|
|
ignore_interrupts { tmp_keg.rmtree if tmp_keg && tmp_keg.directory? }
|
2011-11-26 21:03:46 -08:00
|
|
|
end
|
|
|
|
|
2011-08-23 23:30:52 +01:00
|
|
|
def caveats
|
2014-03-13 10:11:00 -05:00
|
|
|
return if only_deps?
|
2013-12-16 16:37:59 -08:00
|
|
|
|
2013-09-07 11:08:51 -05:00
|
|
|
if ARGV.homebrew_developer? and not f.keg_only?
|
2012-12-31 17:51:57 +00:00
|
|
|
audit_bin
|
|
|
|
audit_sbin
|
|
|
|
audit_lib
|
2013-07-15 19:03:08 -07:00
|
|
|
audit_man
|
|
|
|
audit_info
|
2011-08-23 23:30:52 +01:00
|
|
|
end
|
2012-07-18 03:22:00 -05:00
|
|
|
|
2013-01-12 13:08:29 -06:00
|
|
|
c = Caveats.new(f)
|
|
|
|
|
|
|
|
unless c.empty?
|
|
|
|
@show_summary_heading = true
|
|
|
|
ohai 'Caveats', c.caveats
|
|
|
|
end
|
2011-08-23 23:30:52 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def finish
|
2014-03-13 10:11:00 -05:00
|
|
|
return if only_deps?
|
2013-12-16 16:37:59 -08:00
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
ohai 'Finishing up' if verbose?
|
2011-08-23 23:30:52 +01:00
|
|
|
|
2013-06-30 11:16:53 -07:00
|
|
|
install_plist
|
|
|
|
|
2014-07-24 19:39:09 -05:00
|
|
|
keg = Keg.new(f.prefix)
|
2014-07-24 19:39:09 -05:00
|
|
|
link(keg)
|
2014-07-24 19:39:09 -05:00
|
|
|
fix_install_names(keg) if OS.mac?
|
2011-08-23 23:30:52 +01:00
|
|
|
|
2013-12-05 10:09:14 -06:00
|
|
|
post_install
|
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
ohai "Summary" if verbose? or show_summary_heading?
|
2013-12-12 15:42:31 -06:00
|
|
|
puts summary
|
2013-06-11 15:35:30 -05:00
|
|
|
ensure
|
2013-01-23 00:26:25 -06:00
|
|
|
unlock if hold_locks?
|
2009-10-26 18:13:38 +00:00
|
|
|
end
|
2010-07-20 21:03:25 -07:00
|
|
|
|
2013-12-12 15:42:31 -06:00
|
|
|
def emoji
|
|
|
|
ENV['HOMEBREW_INSTALL_BADGE'] || "\xf0\x9f\x8d\xba"
|
|
|
|
end
|
|
|
|
|
|
|
|
def summary
|
|
|
|
s = ""
|
|
|
|
s << "#{emoji} " if MacOS.version >= :lion and not ENV['HOMEBREW_NO_EMOJI']
|
|
|
|
s << "#{f.prefix}: #{f.prefix.abv}"
|
|
|
|
s << ", built in #{pretty_duration build_time}" if build_time
|
|
|
|
s
|
|
|
|
end
|
|
|
|
|
2011-08-23 23:30:52 +01:00
|
|
|
def build_time
|
2014-03-13 14:16:15 -05:00
|
|
|
@build_time ||= Time.now - @start_time if @start_time && !interactive?
|
2011-08-23 23:30:52 +01:00
|
|
|
end
|
2009-10-26 18:13:38 +00:00
|
|
|
|
2014-03-08 16:54:19 -06:00
|
|
|
def sanitized_ARGV_options
|
2014-03-13 10:10:59 -05:00
|
|
|
args = []
|
2014-03-13 19:10:41 -05:00
|
|
|
args << "--ignore-dependencies" if ignore_deps?
|
2014-03-13 10:10:59 -05:00
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
if build_bottle?
|
2014-03-13 10:10:59 -05:00
|
|
|
args << "--build-bottle"
|
|
|
|
args << "--bottle-arch=#{ARGV.bottle_arch}" if ARGV.bottle_arch
|
|
|
|
end
|
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
if interactive?
|
2014-03-13 10:10:59 -05:00
|
|
|
args << "--interactive"
|
2014-03-13 10:11:00 -05:00
|
|
|
args << "--git" if interactive == :git
|
2014-03-13 10:10:59 -05:00
|
|
|
end
|
|
|
|
|
2014-03-13 10:11:00 -05:00
|
|
|
args << "--verbose" if verbose?
|
2014-03-13 10:11:00 -05:00
|
|
|
args << "--debug" if debug?
|
2014-03-13 10:10:59 -05:00
|
|
|
args << "--cc=#{ARGV.cc}" if ARGV.cc
|
|
|
|
args << "--env=#{ARGV.env}" if ARGV.env
|
2014-06-19 21:35:47 -05:00
|
|
|
|
|
|
|
case f.active_spec
|
|
|
|
when f.head then args << "--HEAD"
|
|
|
|
when f.devel then args << "--devel"
|
|
|
|
end
|
2014-04-26 19:09:49 -05:00
|
|
|
|
2014-08-10 22:24:25 -05:00
|
|
|
f.options.each do |opt|
|
2014-04-26 19:09:49 -05:00
|
|
|
name = opt.name[/\A(.+)=\z$/, 1]
|
|
|
|
value = ARGV.value(name)
|
|
|
|
args << "--#{name}=#{value}" if name && value
|
|
|
|
end
|
|
|
|
|
2014-03-08 16:54:19 -06:00
|
|
|
args
|
|
|
|
end
|
|
|
|
|
2013-01-23 00:26:28 -06:00
|
|
|
def build_argv
|
2014-08-26 15:48:16 -05:00
|
|
|
sanitized_ARGV_options + options.as_flags
|
2013-01-23 00:26:28 -06:00
|
|
|
end
|
|
|
|
|
2011-08-23 23:30:52 +01:00
|
|
|
def build
|
2014-09-14 11:18:55 -05:00
|
|
|
FileUtils.rm Dir["#{HOMEBREW_LOGS}/#{f.name}/*"]
|
2012-09-11 20:59:59 -04:00
|
|
|
|
2011-08-23 23:30:52 +01:00
|
|
|
@start_time = Time.now
|
2009-10-26 18:13:38 +00:00
|
|
|
|
|
|
|
# 1. formulae can modify ENV, so we must ensure that each
|
2010-11-09 12:57:41 +00:00
|
|
|
# installation has a pristine ENV when it starts, forking now is
|
2009-10-26 18:13:38 +00:00
|
|
|
# the easiest way to do this
|
|
|
|
read, write = IO.pipe
|
|
|
|
# I'm guessing this is not a good way to do this, but I'm no UNIX guru
|
|
|
|
ENV['HOMEBREW_ERROR_PIPE'] = write.to_i.to_s
|
|
|
|
|
2013-04-05 17:42:53 -05:00
|
|
|
args = %W[
|
|
|
|
nice #{RUBY_PATH}
|
|
|
|
-W0
|
2014-07-29 16:59:02 -05:00
|
|
|
-I #{HOMEBREW_LIBRARY_PATH}
|
2013-04-05 17:42:53 -05:00
|
|
|
--
|
2014-08-26 22:06:43 -05:00
|
|
|
#{HOMEBREW_LIBRARY_PATH}/build.rb
|
2013-04-05 17:42:53 -05:00
|
|
|
#{f.path}
|
|
|
|
].concat(build_argv)
|
|
|
|
|
|
|
|
# Ruby 2.0+ sets close-on-exec on all file descriptors except for
|
|
|
|
# 0, 1, and 2 by default, so we have to specify that we want the pipe
|
|
|
|
# to remain open in the child process.
|
|
|
|
args << { write => write } if RUBY_VERSION >= "2.0"
|
|
|
|
|
2014-03-29 10:23:43 -05:00
|
|
|
pid = fork do
|
2010-11-09 12:57:41 +00:00
|
|
|
begin
|
|
|
|
read.close
|
2013-04-05 17:42:53 -05:00
|
|
|
exec(*args)
|
2010-11-09 12:57:41 +00:00
|
|
|
rescue Exception => e
|
|
|
|
Marshal.dump(e, write)
|
2009-10-26 18:13:38 +00:00
|
|
|
write.close
|
2010-11-09 12:57:41 +00:00
|
|
|
exit! 1
|
2009-10-26 18:13:38 +00:00
|
|
|
end
|
|
|
|
end
|
2010-11-09 12:57:41 +00:00
|
|
|
|
2014-03-29 10:23:43 -05:00
|
|
|
ignore_interrupts(:quietly) do # the child will receive the interrupt and marshal it back
|
2010-11-09 12:57:41 +00:00
|
|
|
write.close
|
2014-08-08 17:31:13 -05:00
|
|
|
thr = Thread.new { read.read }
|
2014-03-29 10:23:43 -05:00
|
|
|
Process.wait(pid)
|
2014-08-08 17:31:13 -05:00
|
|
|
data = thr.value
|
2013-09-07 22:17:52 -05:00
|
|
|
read.close
|
2010-11-09 12:57:41 +00:00
|
|
|
raise Marshal.load(data) unless data.nil? or data.empty?
|
2012-08-22 15:50:27 -04:00
|
|
|
raise Interrupt if $?.exitstatus == 130
|
2010-11-09 12:57:41 +00:00
|
|
|
raise "Suspicious installation failure" unless $?.success?
|
2012-08-10 16:04:56 -04:00
|
|
|
end
|
|
|
|
|
2012-09-11 20:59:59 -04:00
|
|
|
raise "Empty installation" if Dir["#{f.prefix}/*"].empty?
|
|
|
|
|
2013-02-17 22:54:27 -06:00
|
|
|
rescue Exception
|
2012-08-10 16:04:56 -04:00
|
|
|
ignore_interrupts do
|
|
|
|
# any exceptions must leave us with nothing installed
|
2012-09-11 20:59:59 -04:00
|
|
|
f.prefix.rmtree if f.prefix.directory?
|
2012-08-10 16:04:56 -04:00
|
|
|
f.rack.rmdir_if_possible
|
2010-11-09 12:57:41 +00:00
|
|
|
end
|
2012-08-10 16:04:56 -04:00
|
|
|
raise
|
2009-10-26 18:13:38 +00:00
|
|
|
end
|
2011-08-23 23:30:52 +01:00
|
|
|
|
2014-07-24 19:39:09 -05:00
|
|
|
def link(keg)
|
2014-07-24 19:39:09 -05:00
|
|
|
if f.keg_only?
|
|
|
|
begin
|
|
|
|
keg.optlink
|
2014-07-24 19:39:09 -05:00
|
|
|
rescue Keg::LinkError => e
|
|
|
|
onoe "Failed to create #{f.opt_prefix}"
|
2014-09-14 11:18:55 -05:00
|
|
|
puts "Things that depend on #{f.name} will probably not build."
|
2014-07-24 19:39:09 -05:00
|
|
|
puts e
|
2014-07-24 19:39:09 -05:00
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2014-06-27 16:20:17 -05:00
|
|
|
if keg.linked?
|
2012-02-21 11:40:06 +00:00
|
|
|
opoo "This keg was marked linked already, continuing anyway"
|
2014-06-27 16:20:17 -05:00
|
|
|
keg.remove_linked_keg_record
|
2012-02-21 11:40:06 +00:00
|
|
|
end
|
|
|
|
|
2012-08-22 15:50:27 -04:00
|
|
|
begin
|
|
|
|
keg.link
|
2014-06-27 16:10:42 -05:00
|
|
|
rescue Keg::ConflictError => e
|
2012-08-22 15:50:27 -04:00
|
|
|
onoe "The `brew link` step did not complete successfully"
|
|
|
|
puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}"
|
2014-06-27 16:10:42 -05:00
|
|
|
puts e
|
2013-06-23 16:32:31 -07:00
|
|
|
puts
|
|
|
|
puts "Possible conflicting files are:"
|
|
|
|
mode = OpenStruct.new(:dry_run => true, :overwrite => true)
|
|
|
|
keg.link(mode)
|
2012-08-22 15:50:27 -04:00
|
|
|
@show_summary_heading = true
|
2014-06-27 16:10:42 -05:00
|
|
|
rescue Keg::LinkError => e
|
|
|
|
onoe "The `brew link` step did not complete successfully"
|
|
|
|
puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}"
|
|
|
|
puts e
|
|
|
|
puts
|
|
|
|
puts "You can try again using:"
|
|
|
|
puts " brew link #{f.name}"
|
|
|
|
@show_summary_heading = true
|
2014-04-21 09:40:24 -05:00
|
|
|
rescue Exception => e
|
|
|
|
onoe "An unexpected error occurred during the `brew link` step"
|
|
|
|
puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}"
|
|
|
|
puts e
|
|
|
|
puts e.backtrace if debug?
|
|
|
|
@show_summary_heading = true
|
|
|
|
ignore_interrupts { keg.unlink }
|
|
|
|
raise
|
2012-08-22 15:50:27 -04:00
|
|
|
end
|
2011-08-23 23:30:52 +01:00
|
|
|
end
|
|
|
|
|
2012-09-11 20:57:41 -04:00
|
|
|
def install_plist
|
2012-11-25 15:06:41 +00:00
|
|
|
return unless f.plist
|
2014-03-25 23:45:23 -05:00
|
|
|
f.plist_path.atomic_write(f.plist)
|
2012-11-25 15:06:41 +00:00
|
|
|
f.plist_path.chmod 0644
|
2014-03-25 23:45:49 -05:00
|
|
|
rescue Exception => e
|
|
|
|
onoe "Failed to install plist file"
|
|
|
|
ohai e, e.backtrace if debug?
|
2012-09-11 20:57:41 -04:00
|
|
|
end
|
|
|
|
|
2014-07-24 19:39:09 -05:00
|
|
|
def fix_install_names(keg)
|
2013-12-04 22:37:57 -06:00
|
|
|
keg.fix_install_names(:keg_only => f.keg_only?)
|
|
|
|
|
2013-12-04 22:37:58 -06:00
|
|
|
if @poured_bottle
|
2013-12-04 22:37:57 -06:00
|
|
|
keg.relocate_install_names Keg::PREFIX_PLACEHOLDER, HOMEBREW_PREFIX.to_s,
|
|
|
|
Keg::CELLAR_PLACEHOLDER, HOMEBREW_CELLAR.to_s, :keg_only => f.keg_only?
|
2013-03-11 18:56:26 +00:00
|
|
|
end
|
2011-08-23 23:30:52 +01:00
|
|
|
rescue Exception => e
|
|
|
|
onoe "Failed to fix install names"
|
|
|
|
puts "The formula built, but you may encounter issues using it or linking other"
|
|
|
|
puts "formula against it."
|
2014-03-13 10:11:00 -05:00
|
|
|
ohai e, e.backtrace if debug?
|
2011-08-23 23:30:52 +01:00
|
|
|
@show_summary_heading = true
|
|
|
|
end
|
|
|
|
|
|
|
|
def clean
|
2014-03-13 10:11:00 -05:00
|
|
|
ohai "Cleaning" if verbose?
|
2014-02-23 11:07:37 -08:00
|
|
|
Cleaner.new(f).clean
|
2011-08-23 23:30:52 +01:00
|
|
|
rescue Exception => e
|
|
|
|
opoo "The cleaning step did not complete successfully"
|
|
|
|
puts "Still, the installation was successful, so we will link it into your prefix"
|
2014-03-13 10:11:00 -05:00
|
|
|
ohai e, e.backtrace if debug?
|
2011-08-23 23:30:52 +01:00
|
|
|
@show_summary_heading = true
|
|
|
|
end
|
|
|
|
|
2013-12-05 10:09:14 -06:00
|
|
|
def post_install
|
|
|
|
f.post_install
|
|
|
|
rescue Exception => e
|
|
|
|
opoo "The post-install step did not complete successfully"
|
|
|
|
puts "You can try again using `brew postinstall #{f.name}`"
|
2014-03-13 10:11:00 -05:00
|
|
|
ohai e, e.backtrace if debug?
|
2013-12-05 10:09:14 -06:00
|
|
|
@show_summary_heading = true
|
|
|
|
end
|
|
|
|
|
2011-08-24 01:13:15 +01:00
|
|
|
def pour
|
2014-03-31 13:15:07 -05:00
|
|
|
if Homebrew::Hooks::Bottles.formula_has_bottle?(f)
|
|
|
|
return if Homebrew::Hooks::Bottles.pour_formula_bottle(f)
|
|
|
|
end
|
|
|
|
|
2013-09-25 18:51:30 -05:00
|
|
|
if f.local_bottle_path
|
|
|
|
downloader = LocalBottleDownloadStrategy.new(f)
|
2013-06-08 16:41:23 +01:00
|
|
|
else
|
2014-07-22 19:11:09 -05:00
|
|
|
downloader = f.bottle
|
|
|
|
downloader.verify_download_integrity(downloader.fetch)
|
2013-06-08 16:41:23 +01:00
|
|
|
end
|
2011-08-24 01:13:15 +01:00
|
|
|
HOMEBREW_CELLAR.cd do
|
|
|
|
downloader.stage
|
|
|
|
end
|
2013-10-05 20:32:05 +01:00
|
|
|
|
2014-05-31 23:53:46 -05:00
|
|
|
Pathname.glob("#{f.bottle_prefix}/{etc,var}/**/*") do |path|
|
2013-10-05 20:32:05 +01:00
|
|
|
path.extend(InstallRenamed)
|
|
|
|
path.cp_path_sub(f.bottle_prefix, HOMEBREW_PREFIX)
|
|
|
|
end
|
|
|
|
FileUtils.rm_rf f.bottle_prefix
|
2011-08-24 01:13:15 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
## checks
|
|
|
|
|
2013-07-15 19:28:10 -07:00
|
|
|
def print_check_output warning_and_description
|
|
|
|
return unless warning_and_description
|
|
|
|
warning, description = *warning_and_description
|
|
|
|
opoo warning
|
|
|
|
puts description
|
|
|
|
@show_summary_heading = true
|
2012-02-26 16:33:44 -08:00
|
|
|
end
|
|
|
|
|
2013-07-15 19:03:08 -07:00
|
|
|
def audit_bin
|
2013-07-15 19:28:10 -07:00
|
|
|
print_check_output(check_PATH(f.bin)) unless f.keg_only?
|
|
|
|
print_check_output(check_non_executables(f.bin))
|
2013-11-10 12:51:24 -08:00
|
|
|
print_check_output(check_generic_executables(f.bin))
|
2013-07-15 19:03:08 -07:00
|
|
|
end
|
|
|
|
|
2012-02-26 16:33:44 -08:00
|
|
|
def audit_sbin
|
2013-07-15 19:28:10 -07:00
|
|
|
print_check_output(check_PATH(f.sbin)) unless f.keg_only?
|
|
|
|
print_check_output(check_non_executables(f.sbin))
|
2013-11-10 12:51:24 -08:00
|
|
|
print_check_output(check_generic_executables(f.sbin))
|
2012-02-19 19:09:38 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
def audit_lib
|
2013-07-15 19:28:10 -07:00
|
|
|
print_check_output(check_jars)
|
|
|
|
print_check_output(check_non_libraries)
|
2012-02-19 19:09:38 -08:00
|
|
|
end
|
2013-01-23 00:26:25 -06:00
|
|
|
|
2013-07-15 19:03:08 -07:00
|
|
|
def audit_man
|
2013-07-15 19:28:10 -07:00
|
|
|
print_check_output(check_manpages)
|
2013-07-15 19:03:08 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def audit_info
|
2013-07-15 19:28:10 -07:00
|
|
|
print_check_output(check_infopages)
|
2013-07-15 19:03:08 -07:00
|
|
|
end
|
|
|
|
|
2013-01-23 00:26:25 -06:00
|
|
|
private
|
|
|
|
|
|
|
|
def hold_locks?
|
|
|
|
@hold_locks || false
|
|
|
|
end
|
|
|
|
|
|
|
|
def lock
|
|
|
|
if (@@locked ||= []).empty?
|
2013-01-23 00:26:29 -06:00
|
|
|
f.recursive_dependencies.each do |dep|
|
|
|
|
@@locked << dep.to_formula
|
2014-03-13 10:11:00 -05:00
|
|
|
end unless ignore_deps?
|
2013-01-23 00:26:25 -06:00
|
|
|
@@locked.unshift(f)
|
2014-05-20 22:50:13 -05:00
|
|
|
@@locked.uniq!
|
2013-01-23 00:26:25 -06:00
|
|
|
@@locked.each(&:lock)
|
|
|
|
@hold_locks = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def unlock
|
|
|
|
if hold_locks?
|
|
|
|
@@locked.each(&:unlock)
|
|
|
|
@@locked.clear
|
|
|
|
@hold_locks = false
|
|
|
|
end
|
|
|
|
end
|
2011-08-23 23:30:52 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
class Formula
|
2011-09-01 10:06:28 -07:00
|
|
|
def keg_only_text
|
2014-02-09 18:45:02 -08:00
|
|
|
s = "This formula is keg-only, which means it was not symlinked into #{HOMEBREW_PREFIX}."
|
2012-08-10 16:34:20 -04:00
|
|
|
s << "\n\n#{keg_only_reason.to_s}"
|
|
|
|
if lib.directory? or include.directory?
|
|
|
|
s <<
|
|
|
|
<<-EOS.undent_________________________________________________________72
|
2011-08-23 23:30:52 +01:00
|
|
|
|
|
|
|
|
2012-08-10 16:34:20 -04:00
|
|
|
Generally there are no consequences of this for you. If you build your
|
|
|
|
own software and it requires this formula, you'll need to add to your
|
|
|
|
build variables:
|
2011-08-23 23:30:52 +01:00
|
|
|
|
2012-08-10 16:34:20 -04:00
|
|
|
EOS
|
2014-06-30 20:23:56 -05:00
|
|
|
s << " LDFLAGS: -L#{opt_lib}\n" if lib.directory?
|
|
|
|
s << " CPPFLAGS: -I#{opt_include}\n" if include.directory?
|
2012-08-10 16:34:20 -04:00
|
|
|
end
|
|
|
|
s << "\n"
|
2011-08-23 23:30:52 +01:00
|
|
|
end
|
2009-10-26 18:13:38 +00:00
|
|
|
end
|