Newer
Older
class Tty
class <<self
def blue; bold 34; end
def white; bold 39; end
def red; underline 31; end
def yellow; underline 33 ; end
def reset; escape 0; end
private
def color n
escape "0;#{n}"
end
def bold n
escape "1;#{n}"
end
def underline n
escape "4;#{n}"
end
def escape n
"\033[#{n}m" if $stdout.tty?
end
end
end
# args are additional inputs to puts until a nil arg is encountered
title = title.to_s[0, `/usr/bin/tput cols`.strip.to_i-4] unless ARGV.verbose?
puts "#{Tty.blue}==>#{Tty.white} #{title}#{Tty.reset}"
return "2 seconds" if s < 3 # avoids the plural problem ;)
return "#{s.to_i} seconds" if s < 120
return "%.1f minutes" % (s/60)
def interactive_shell f=nil
unless f.nil?
ENV['HOMEBREW_DEBUG_PREFIX'] = f.prefix
ENV['HOMEBREW_DEBUG_INSTALL'] = f.name
end
fork {exec ENV['SHELL'] }
Process.wait
unless $?.success?
puts "Aborting due to non-zero exit status"
exit $?
end
module Homebrew
def self.system cmd, *args
puts "#{cmd} #{args*' '}" if ARGV.verbose?
fork do
yield if block_given?
args.collect!{|arg| arg.to_s}
exec(cmd, *args) rescue nil
exit! 1 # never gets here unless exec failed
end
Process.wait
$?.success?
end
end
# Kernel.system but with exceptions
def safe_system cmd, *args
unless Homebrew.system cmd, *args
args = args.map{ |arg| arg.gsub " ", "\\ " } * " "
raise "Failure while executing: #{cmd} #{args}"
end
end
# prints no output
def quiet_system cmd, *args
Homebrew.system(cmd, *args) do
$stdout.close
$stderr.close
safe_system '/usr/bin/curl', '-f#LA', HOMEBREW_USER_AGENT, *args unless args.empty?
return if items.empty?
if $stdout.tty?
# determine the best width to display for different console sizes
console_width = `/bin/stty size`.chomp.split(" ").last.to_i
console_width = 80 if console_width <= 0
longest = items.sort_by { |item| item.length }.last
optimal_col_width = (console_width.to_f / (longest.length + 2).to_f).floor
cols = optimal_col_width > 1 ? optimal_col_width : 1
IO.popen("/usr/bin/pr -#{cols} -t -w#{console_width}", "w"){|io| io.puts(items) }
editor = ENV['HOMEBREW_EDITOR'] || ENV['EDITOR']
elsif system "/usr/bin/which -s edit"
# BBEdit / TextWrangler
editor='edit'
# we split the editor because especially on mac "mate -w" is common
# but we still want to use the comma-delimited version of exec because then
# we don't have to escape args, and escaping 100% is tricky
# GZips the given path, and returns the gzipped file
def gzip *paths
paths.collect do |path|
system "/usr/bin/gzip", path
Pathname.new(path+".gz")
end
module ArchitectureListExtension
def universal?
self.include? :i386 and self.include? :x86_64
end
end
# Returns array of architectures that the given command or library is built for.
cmd = cmd.to_s # If we were passed a Pathname, turn it into a string.
cmd = `/usr/bin/which #{cmd}` unless Pathname.new(cmd).absolute?
cmd.gsub! ' ', '\\ ' # Escape spaces in the filename.
archs = IO.popen("/usr/bin/file -L #{cmd}").readlines.inject([]) do |archs, line|
case line
when /Mach-O (executable|dynamically linked shared library) ppc/
archs << :ppc7400
when /Mach-O 64-bit (executable|dynamically linked shared library) ppc64/
archs << :ppc64
when /Mach-O (executable|dynamically linked shared library) i386/
archs << :i386
when /Mach-O 64-bit (executable|dynamically linked shared library) x86_64/
archs << :x86_64
else
archs
end
def inreplace path, before=nil, after=nil
f = File.open(path, 'r')
s = f.read
yield s
else
s.gsub!(before, after)
end
f.reopen(path, 'w').write(s)
f.close
end
def ignore_interrupts
std_trap = trap("INT") {}
yield
ensure
trap("INT", std_trap)
end
def nostdout
if ARGV.verbose?
yield
else
begin
require 'stringio'
real_stdout = $stdout
$stdout = StringIO.new
yield
ensure
$stdout = real_stdout
end
end
module MacOS extend self
def gcc_42_build_version
`/usr/bin/gcc-4.2 -v 2>&1` =~ /build (\d{4,})/
if $1
$1.to_i
elsif system "/usr/bin/which gcc"
# Xcode 3.0 didn't come with gcc-4.2
# We can't change the above regex to use gcc because the version numbers
# are different and thus, not useful.
# FIXME I bet you 20 quid this causes a side effect — magic values tend to
401
else
nil
end
end
def gcc_40_build_version
`/usr/bin/gcc-4.0 -v 2>&1` =~ /build (\d{4,})/
if $1
$1.to_i
else
nil
def llvm_build_version
if MACOS_VERSION >= 10.6
xcode_path = `/usr/bin/xcode-select -print-path`.chomp
return nil if xcode_path.empty?
`#{xcode_path}/usr/bin/llvm-gcc -v 2>&1` =~ /LLVM build (\d{4,})/
$1.to_i
end
def x11_installed?
Pathname.new('/usr/X11/lib/libpng.dylib').exist?
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
end
def macports_or_fink_installed?
# See these issues for some history:
# http://github.com/mxcl/homebrew/issues/#issue/13
# http://github.com/mxcl/homebrew/issues/#issue/41
# http://github.com/mxcl/homebrew/issues/#issue/48
%w[port fink].each do |ponk|
path = `/usr/bin/which -s #{ponk}`
return ponk unless path.empty?
end
# we do the above check because macports can be relocated and fink may be
# able to be relocated in the future. This following check is because if
# fink and macports are not in the PATH but are still installed it can
# *still* break the build -- because some build scripts hardcode these paths:
%w[/sw/bin/fink /opt/local/bin/port].each do |ponk|
return ponk if File.exist? ponk
end
# finally, sometimes people make their MacPorts or Fink read-only so they
# can quickly test Homebrew out, but still in theory obey the README's
# advise to rename the root directory. This doesn't work, many build scripts
# error out when they try to read from these now unreadable directories.
%w[/sw /opt/local].each do |path|
path = Pathname.new(path)
return path if path.exist? and not path.readable?
end
false
end
end
module GitHub extend self
def issues_for_formula name
# bit basic as depends on the issue at github having the exact name of the
# formula in it. Which for stuff like objective-caml is unlikely. So we
# really should search for aliases too.
name = f.name if Formula === name
require 'open-uri'
require 'yaml'
issues = []
open "http://github.com/api/v2/yaml/issues/search/mxcl/homebrew/open/#{name}" do |f|
YAML::load(f.read)['issues'].each do |issue|
issues << 'http://github.com/mxcl/homebrew/issues/#issue/%s' % issue['number']
end
end
issues
rescue
[]
end
end