diff options
Diffstat (limited to 'bin')
| -rwxr-xr-x | bin/brew | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/bin/brew b/bin/brew new file mode 100755 index 000000000..825872d93 --- /dev/null +++ b/bin/brew @@ -0,0 +1,245 @@ +#!/usr/bin/ruby + +require 'find' +require 'pathname' +$:.unshift Pathname.new(__FILE__).dirname.parent.realpath+'Library'+'Homebrew' +require 'env' + +def prune + n=0 + dirs=Array.new + $root.find do |path| + if path.directory? + name=path.relative_path_from($root).to_s + if name == '.git' or name == 'Cellar' or name == 'Library/Homebrew' or name == 'Library/Formula' + Find.prune + else + dirs<<path + end + elsif path.symlink? + resolved_path=path.dirname+path.readlink + unless resolved_path.exist? + path.unlink + n+=1 + end + end + end + # entries lists '.' and '..' so 2 is minimum basically + dirs.sort.reverse_each do |d| + if d.children.length == 0 + d.rmdir + n+=1 + end + end + return n +end + +def shift_formulae + name=Pathname.new ARGV.shift + + return name if name.directory? and name.parent.realpath == $cellar + return File.basename(name, '.rb') if name.file? and name.extname == '.rb' and name.parent.realpath == $formula + + name=name.to_s + raise "#{name} is an invalid name for a formula" if name.include? '/' + + return name if ($formula+(name+'.rb')).file? + return name if ($cellar+name).directory? + + raise "No formula or keg for #{name} found" +end + +def __class name + #remove invalid characters and camelcase + name.capitalize.gsub(/[-_\s]([a-zA-Z0-9])/) { $1.upcase } +end + +def __rb name + $formula+(name+'.rb') +end + +def __obj name + require "#{__rb name}" + o=eval(__class(name)).new + o.name=name + return o +end + +def rm keg + #TODO if multiple versions don't rm all unless --force + path=$cellar+keg + path.rmtree + puts "#{path} removed (#{prune} files)" +end + +def ln name + keg=$cellar+name + keg=keg.realpath + + if keg.parent.parent == $root + # we are one dir too high + kids=keg.children + raise "#{keg} is empty :(" if kids.length == 0 + raise "There are multiple versions of #{keg.basename} installed please specify one" if kids.length > 1 + keg=keg.children.first + raise "#{keg} is not a directory" unless keg.directory? + elsif keg.parent.parent.parent != $root + raise '#{keg} is not a keg' + end + + # yeah indeed, you have to force anything you need in the main tree into + # these directories :P + # NOTE that not everything needs to be in the main tree + # TODO consider using hardlinks + $n=0 + lnd(keg, 'etc') {nil} + lnd(keg, 'include') {nil} + + lnd(keg, 'lib') do |path| + :mkpath if ['pkgconfig','php'].include? path.to_s + end + + lnd(keg, 'bin') do |path| + if path.extname.to_s == '.app' + # no need to put .app bundles in the path, just use spotlight, or the + # open command + :skip + else + :mkpath + end + end + + lnd(keg, 'share') do |path| + includes=(1..9).collect {|x| "man/man#{x}"} <<'man'<<'doc'<<'locale'<<'info' + :mkpath if includes.include? path.to_s + end + + return $n +end + +def symlink_relative_to from, to + tod=to.dirname + tod.mkpath + Dir.chdir(tod) do + #TODO use ruby function so we get exceptions + `ln -sf "#{from.relative_path_from tod}"` + $n+=1 + end +end + +# symlinks a directory recursively into our FHS tree +def lnd keg, start + start=keg+start + return unless start.directory? + + start.find do |from| + next if from == start + + prune=false + relative_path=from.relative_path_from keg + to=$root+relative_path + + if from.directory? + cmd=yield from.relative_path_from(start) + + if :skip == cmd + Find.prune + elsif :mkpath == cmd + to.mkpath + $n+=1 + else + symlink_relative_to from, to + Find.prune + end + elsif from.file? + symlink_relative_to from, to + end + end +end + +def prefix + # Get the clean path to $prefix/Cellar/homebrew/brew/../../../ + # Don't resolve any symlinks of that final result. + # Rationale: if the user calls /usr/local/bin/brew but that will resolve + # to /Brewery/Cellar/homebrew/brew we should give /usr/local and not + # /Brewery because the user probably has chosen /usr/local as the Homebrew + # to expose to the system. + if File.symlink? __FILE__ + # using pathname as it will handle readlink returning abs or rel paths + d=Pathname.new(__FILE__).dirname + File.expand_path(d+File.readlink(__FILE__)+'../../../') + else + # Dir.pwd resolves the symlink :P #rubysucks + # we use the cwd because __FILE__ can be relative and expand_path + # resolves the symlink for the working directory if fed a relative path + # SIGH + cwd=Pathname.new `pwd`.strip + File.expand_path(cwd+__FILE__+'../../../') + end +end + +def usage + name=File.basename $0 + <<-EOS +Usage: #{name} [abv] [prune] [--prefix] [--cache] +Usage: #{name} [install] [ln] [rm] [info] [list] beverage + EOS +end + +######################################################################### impl +begin + #TODO proper options parsing so --options can go first if necessary + + case ARGV.shift + when 'abv' + `find #{$cellar} -type f | wc -l`.strip+' files, '+`du -hd0 #{$cellar} | cut -d"\t" -f1`.strip + when 'prune' + puts "Pruned #{prune} files" + when '--prefix' + puts prefix + when '--cache' + puts File.expand_path('~/Library/Application Support/Homebrew') + when '-h', '--help', '--usage', '-?' + puts usage + when '-v', '--version' + puts HOMEBREW_VERSION + when 'list' + puts `find #{$cellar+shift_formulae}` + when 'install' + name=shift_formulae + beginning = Time.now + o=__obj(name) + raise "#{o.prefix} already exists!" if o.prefix.exist? + o.brew { o.install } + ohai 'Finishing up' + o.clean + ln name + puts "#{o.prefix}: "+`find #{o.prefix} -type f | wc -l`.strip+ + ' files, '+ + `du -hd0 #{o.prefix} | cut -d"\t" -f1`.strip+ + ", built in #{Time.now - beginning} seconds" + when 'ln' + puts "Created #{ln shift_formulae} links" + when 'rm' + rm shift_formulae + when 'info' + o=__obj shift_formulae + puts "#{o.name} #{o.version}" + puts o.homepage + else + puts usage + end + +rescue StandardError, Interrupt => e + if ARGV.include? '--verbose' or ENV['HOMEBREW_DEBUG'] + raise + elsif e.kind_of? Interrupt + puts # seeimgly a newline is typical + exit 130 + elsif e.kind_of? StandardError and not e.kind_of? NameError + puts "\033[1;31mError\033[0;0m: #{e}" + exit 1 + else + raise + end +end
\ No newline at end of file |
