diff options
| author | Max Howell | 2009-06-04 19:21:19 +0100 |
|---|---|---|
| committer | Max Howell | 2009-06-04 19:36:58 +0100 |
| commit | e91aeafc82edb2b79af67e342009cd019cd1ede5 (patch) | |
| tree | 2c12888da095f544f650787ad447aa2edb94d8c1 /bin | |
| parent | 84ad47bc3c8029847e5c41ab4646a6b9455b370a (diff) | |
| download | homebrew-e91aeafc82edb2b79af67e342009cd019cd1ede5.tar.bz2 | |
Created /Library moved brew tool to /bin
Moved Forumla and Cellar/homebrew into Library.
This way the homebrew core files are more sensibly placed, Cellar is
more internally consistent and only generated. And Homebrew is ready for
use straight out of the tarball.
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 |
