Clean up and improve build-error output and logs
All logs are now stored from each command executed in Formula.install. Error output is truncated to five lines in an attempt to not overwhelm the user and to encourage users to read the error output and report the bug properly. Maybe we can get that figure up from 70% to 90%.
This commit is contained in:
parent
1100818100
commit
a217b03952
@ -168,9 +168,10 @@ class Cmd
|
|||||||
dels = @args - args
|
dels = @args - args
|
||||||
adds = args - @args
|
adds = args - @args
|
||||||
dups = dels & args
|
dups = dels & args
|
||||||
puts "brew: Superenv removed: #{dels*' '}" unless dels.empty?
|
|
||||||
puts "brew: Superenv deduped: #{dels}" unless dups.empty?
|
STDERR.puts "brew: superenv removed: #{dels*' '}" unless dels.empty?
|
||||||
puts "brew: Superenv added: #{adds*' '}" unless adds.empty?
|
STDERR.puts "brew: superenv deduped: #{dels}" unless dups.empty?
|
||||||
|
STDERR.puts "brew: superenv added: #{adds*' '}" unless adds.empty?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -128,7 +128,6 @@ def install f
|
|||||||
end
|
end
|
||||||
|
|
||||||
interactive_shell f
|
interactive_shell f
|
||||||
nil
|
|
||||||
else
|
else
|
||||||
f.prefix.mkpath
|
f.prefix.mkpath
|
||||||
f.install
|
f.install
|
||||||
|
|||||||
@ -95,54 +95,13 @@ class BuildError < Homebrew::InstallationError
|
|||||||
end
|
end
|
||||||
|
|
||||||
def dump
|
def dump
|
||||||
e = self
|
logs = "#{ENV['HOME']}/Library/Logs/Homebrew/#{formula}/"
|
||||||
|
|
||||||
require 'cmd/--config'
|
|
||||||
require 'cmd/--env'
|
|
||||||
|
|
||||||
e.backtrace[1] =~ %r{Library/Formula/(.+)\.rb:(\d+)}
|
|
||||||
formula_name = $1
|
|
||||||
error_line = $2
|
|
||||||
|
|
||||||
path = HOMEBREW_REPOSITORY/"Library/Formula/#{formula_name}.rb"
|
|
||||||
if path.symlink? and path.realpath.to_s =~ %r{^#{HOMEBREW_REPOSITORY}/Library/Taps/(\w+)-(\w+)/}
|
|
||||||
repo = "#$1/homebrew-#$2"
|
|
||||||
repo_path = path.realpath.relative_path_from(HOMEBREW_REPOSITORY/"Library/Taps/#$1-#$2").parent.to_s
|
|
||||||
issues_url = "https://github.com/#$1/homebrew-#$2/issues/new"
|
|
||||||
else
|
|
||||||
repo = "mxcl/master"
|
|
||||||
repo_path = "Library/Formula"
|
|
||||||
issues_url = ISSUES_URL
|
|
||||||
end
|
|
||||||
|
|
||||||
if ARGV.verbose?
|
|
||||||
ohai "Exit Status: #{e.exit_status}"
|
|
||||||
puts "https://github.com/#{repo}/blob/master/#{repo_path}/#{formula_name}.rb#L#{error_line}"
|
|
||||||
end
|
|
||||||
ohai "Build Environment"
|
|
||||||
Homebrew.dump_build_config
|
|
||||||
puts %["--use-clang" was specified] if ARGV.include? '--use-clang'
|
|
||||||
puts %["--use-llvm" was specified] if ARGV.include? '--use-llvm'
|
|
||||||
puts %["--use-gcc" was specified] if ARGV.include? '--use-gcc'
|
|
||||||
Homebrew.dump_build_env e.env
|
|
||||||
puts
|
puts
|
||||||
onoe "#{e.to_s.strip} (#{formula_name}.rb:#{error_line})"
|
onoe "#{formula.name} did not build"
|
||||||
issues = GitHub.issues_for_formula formula_name
|
puts "Logs: #{logs}" unless Dir["#{logs}/*"].empty?
|
||||||
puts
|
puts "Help: #{Tty.em}https://github.com/mxcl/homebrew/wiki/troubleshooting#{Tty.reset}"
|
||||||
if issues.empty?
|
issues = GitHub.issues_for_formula(formula.name)
|
||||||
puts "This link will help resolve the above errors:"
|
puts *issues.map{ |s| " #{Tty.em}#{s}#{Tty.reset}" } unless issues.empty?
|
||||||
puts " #{Tty.em}#{issues_url}#{Tty.reset}"
|
|
||||||
else
|
|
||||||
puts "These existing issues may help you:", *issues.map{ |s| " #{Tty.em}#{s}#{Tty.reset}" }
|
|
||||||
puts "Otherwise, this may help you fix or report the issue:"
|
|
||||||
puts " #{Tty.em}#{issues_url}#{Tty.reset}"
|
|
||||||
end
|
|
||||||
if e.was_running_configure?
|
|
||||||
puts "We saved the configure log:"
|
|
||||||
puts " ~/Library/Logs/Homebrew/config.log"
|
|
||||||
puts "When you report the issue please paste the build output above and the config.log here:"
|
|
||||||
puts " #{Tty.em}http://gist.github.com/#{Tty.reset}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ module FileUtils extend self
|
|||||||
# /tmp volume to the other volume. So we let the user override the tmp
|
# /tmp volume to the other volume. So we let the user override the tmp
|
||||||
# prefix if they need to.
|
# prefix if they need to.
|
||||||
tmp = ENV['HOMEBREW_TEMP'].chuzzle || '/tmp'
|
tmp = ENV['HOMEBREW_TEMP'].chuzzle || '/tmp'
|
||||||
tempd = `/usr/bin/mktemp -d #{tmp}/brew-#{name}-#{version}-XXXX`.chuzzle
|
tempd = `/usr/bin/mktemp -d #{tmp}/#{name}-XXXX`.chuzzle
|
||||||
raise "Failed to create sandbox" if tempd.nil?
|
raise "Failed to create sandbox" if tempd.nil?
|
||||||
prevd = pwd
|
prevd = pwd
|
||||||
cd tempd
|
cd tempd
|
||||||
|
|||||||
@ -223,25 +223,17 @@ class Formula
|
|||||||
# we allow formulas to do anything they want to the Ruby process
|
# we allow formulas to do anything they want to the Ruby process
|
||||||
# so load any deps before this point! And exit asap afterwards
|
# so load any deps before this point! And exit asap afterwards
|
||||||
yield self
|
yield self
|
||||||
rescue Interrupt, RuntimeError, SystemCallError => e
|
rescue RuntimeError, SystemCallError => e
|
||||||
puts if Interrupt === e # don't print next to the ^C
|
if not ARGV.debug?
|
||||||
unless ARGV.debug?
|
%w(config.log CMakeCache.txt).each do |fn|
|
||||||
%w(config.log CMakeCache.txt).select{|f| File.exist? f}.each do |f|
|
(HOMEBREW_LOGS/name).install(fn) if File.file?(fn)
|
||||||
HOMEBREW_LOGS.install f
|
|
||||||
puts "#{f} was copied to #{HOMEBREW_LOGS}"
|
|
||||||
end
|
end
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
|
|
||||||
onoe e.inspect
|
onoe e.inspect
|
||||||
puts e.backtrace
|
puts e.backtrace unless e.kind_of? BuildError
|
||||||
|
|
||||||
ohai "Rescuing build..."
|
ohai "Rescuing build..."
|
||||||
if (e.was_running_configure? rescue false) and File.exist? 'config.log'
|
|
||||||
puts "It looks like an autotools configure failed."
|
|
||||||
puts "Gist 'config.log' and any error output when reporting an issue."
|
|
||||||
puts
|
|
||||||
end
|
|
||||||
|
|
||||||
puts "When you exit this shell Homebrew will attempt to finalise the installation."
|
puts "When you exit this shell Homebrew will attempt to finalise the installation."
|
||||||
puts "If nothing is installed or the shell exits with a non-zero error code,"
|
puts "If nothing is installed or the shell exits with a non-zero error code,"
|
||||||
puts "Homebrew will abort. The installation prefix is:"
|
puts "Homebrew will abort. The installation prefix is:"
|
||||||
@ -529,23 +521,30 @@ protected
|
|||||||
if ARGV.verbose?
|
if ARGV.verbose?
|
||||||
safe_system cmd, *args
|
safe_system cmd, *args
|
||||||
else
|
else
|
||||||
|
@exec_count ||= 0
|
||||||
|
@exec_count += 1
|
||||||
|
logd = HOMEBREW_LOGS/name
|
||||||
|
logfn = "#{logd}/%02d.%s" % [@exec_count, File.basename(cmd).split(' ').first]
|
||||||
|
mkdir_p(logd)
|
||||||
|
|
||||||
rd, wr = IO.pipe
|
rd, wr = IO.pipe
|
||||||
pid = fork do
|
pid = fork do
|
||||||
|
ENV['VERBOSE'] = '1' # helps with many tool's logging outputs
|
||||||
rd.close
|
rd.close
|
||||||
$stdout.reopen wr
|
$stdout.reopen wr
|
||||||
$stderr.reopen wr
|
$stderr.reopen wr
|
||||||
args.collect!{|arg| arg.to_s}
|
args.collect!{|arg| arg.to_s}
|
||||||
exec(cmd, *args) rescue nil
|
exec(cmd, *args) rescue nil
|
||||||
|
puts "Failed to execute: #{cmd}"
|
||||||
exit! 1 # never gets here unless exec threw or failed
|
exit! 1 # never gets here unless exec threw or failed
|
||||||
end
|
end
|
||||||
wr.close
|
wr.close
|
||||||
out = ''
|
|
||||||
out << rd.read until rd.eof?
|
f = File.open(logfn, 'w')
|
||||||
|
f.write(rd.read) until rd.eof?
|
||||||
|
|
||||||
Process.wait
|
Process.wait
|
||||||
unless $?.success?
|
raise unless $?.success?
|
||||||
puts out
|
|
||||||
raise
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
removed_ENV_variables.each do |key, value|
|
removed_ENV_variables.each do |key, value|
|
||||||
@ -553,7 +552,21 @@ protected
|
|||||||
end if removed_ENV_variables
|
end if removed_ENV_variables
|
||||||
|
|
||||||
rescue
|
rescue
|
||||||
|
if f
|
||||||
|
f.flush
|
||||||
|
Kernel.system "/usr/bin/tail -n 5 #{logfn}"
|
||||||
|
require 'cmd/--config'
|
||||||
|
$f = f
|
||||||
|
def Homebrew.puts(*foo); $f.puts *foo end
|
||||||
|
f.puts
|
||||||
|
Homebrew.dump_build_config
|
||||||
|
class << Homebrew; undef :puts end
|
||||||
|
else
|
||||||
|
puts "No logs recorded :(" unless ARGV.verbose?
|
||||||
|
end
|
||||||
raise BuildError.new(self, cmd, args, $?)
|
raise BuildError.new(self, cmd, args, $?)
|
||||||
|
ensure
|
||||||
|
f.close if f
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
public
|
||||||
|
|||||||
@ -200,6 +200,8 @@ class FormulaInstaller
|
|||||||
end
|
end
|
||||||
|
|
||||||
def build
|
def build
|
||||||
|
FileUtils.rm Dir["#{HOMEBREW_LOGS}/#{f}/*"]
|
||||||
|
|
||||||
@start_time = Time.now
|
@start_time = Time.now
|
||||||
|
|
||||||
# 1. formulae can modify ENV, so we must ensure that each
|
# 1. formulae can modify ENV, so we must ensure that each
|
||||||
@ -236,7 +238,7 @@ class FormulaInstaller
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ignore_interrupts do # the fork will receive the interrupt and marshall it back
|
ignore_interrupts(:quietly) do # the fork will receive the interrupt and marshall it back
|
||||||
write.close
|
write.close
|
||||||
Process.wait
|
Process.wait
|
||||||
data = read.read
|
data = read.read
|
||||||
@ -245,18 +247,14 @@ class FormulaInstaller
|
|||||||
raise "Suspicious installation failure" unless $?.success?
|
raise "Suspicious installation failure" unless $?.success?
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is the installation receipt. The reason this comment is necessary
|
raise "Empty installation" if Dir["#{f.prefix}/*"].empty?
|
||||||
# is because some numpty decided to call the class Tab rather than
|
|
||||||
# the far more appropriate InstallationReceipt :P
|
Tab.for_install(f, args).write # INSTALL_RECEIPT.json
|
||||||
Tab.for_install(f, args).write
|
|
||||||
|
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
ignore_interrupts do
|
ignore_interrupts do
|
||||||
# any exceptions must leave us with nothing installed
|
# any exceptions must leave us with nothing installed
|
||||||
if f.prefix.directory?
|
f.prefix.rmtree if f.prefix.directory?
|
||||||
puts "One sec, just cleaning up..." if e.kind_of? Interrupt
|
|
||||||
f.prefix.rmtree
|
|
||||||
end
|
|
||||||
f.rack.rmdir_if_possible
|
f.rack.rmdir_if_possible
|
||||||
end
|
end
|
||||||
raise
|
raise
|
||||||
|
|||||||
@ -216,8 +216,10 @@ def inreplace path, before=nil, after=nil
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def ignore_interrupts
|
def ignore_interrupts(opt = nil)
|
||||||
std_trap = trap("INT") { puts "One sec, just cleaning up" }
|
std_trap = trap("INT") do
|
||||||
|
puts "One sec, just cleaning up" unless opt = :quietly
|
||||||
|
end
|
||||||
yield
|
yield
|
||||||
ensure
|
ensure
|
||||||
trap("INT", std_trap)
|
trap("INT", std_trap)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user