Allow formulae to use __END__
For this to work the "running script" must be the formulae file. Making this so wasn't so hard, there is now an install.rb script which is included with the -r flag to the ruby executable. An at_exit handler calls the install function. Having the install logic in its own file made it feel like there was so much space that I added extra error handling. So there is something to be said for separating functionality out into its own files. Still the error handling sucks, we'll need to marshall the exception back to the bin/brew command. Which is another PITA. Still overall I think this will prove worthwhile. But if it doesn't we'll revert. As a first usage, you can put a diff after __END__ and return DATA from Formula::patches to make Homebrew aware of it.
This commit is contained in:
parent
fd5ed391be
commit
c28bd7b571
@ -144,31 +144,6 @@ def clean f
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def install f
|
|
||||||
f.brew do
|
|
||||||
if ARGV.flag? '--interactive'
|
|
||||||
ohai "Entering interactive mode"
|
|
||||||
puts "Type `exit' to return and finalize the installation"
|
|
||||||
puts "Install to this prefix: #{f.prefix}"
|
|
||||||
interactive_shell
|
|
||||||
nil
|
|
||||||
elsif ARGV.include? '--help'
|
|
||||||
system './configure --help'
|
|
||||||
exit $?
|
|
||||||
else
|
|
||||||
f.prefix.mkpath
|
|
||||||
beginning=Time.now
|
|
||||||
f.install
|
|
||||||
%w[README ChangeLog COPYING LICENSE COPYRIGHT AUTHORS].each do |file|
|
|
||||||
FileUtils.mv "#{file}.txt", file rescue nil
|
|
||||||
f.prefix.install file rescue nil
|
|
||||||
end
|
|
||||||
return Time.now-beginning
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def prune
|
def prune
|
||||||
$n=0
|
$n=0
|
||||||
$d=0
|
$d=0
|
||||||
|
|||||||
@ -114,6 +114,8 @@ class Formula
|
|||||||
# :p1 => 'http://bar.com/patch2',
|
# :p1 => 'http://bar.com/patch2',
|
||||||
# :p2 => ['http://moo.com/patch5', 'http://moo.com/patch6']
|
# :p2 => ['http://moo.com/patch5', 'http://moo.com/patch6']
|
||||||
# }
|
# }
|
||||||
|
# The final option is to return DATA, then put a diff after __END__ and you
|
||||||
|
# can still return a Hash with DATA as the value for a patch level key.
|
||||||
def patches; [] end
|
def patches; [] end
|
||||||
# reimplement and specify dependencies
|
# reimplement and specify dependencies
|
||||||
def deps; end
|
def deps; end
|
||||||
@ -128,6 +130,8 @@ class Formula
|
|||||||
stage do
|
stage do
|
||||||
begin
|
begin
|
||||||
patch
|
patch
|
||||||
|
# we allow formulas to do anything they want to the Ruby process
|
||||||
|
# so load any deps before this point! And exit asap afterwards
|
||||||
yield self
|
yield self
|
||||||
rescue Interrupt, RuntimeError, SystemCallError => e
|
rescue Interrupt, RuntimeError, SystemCallError => e
|
||||||
raise unless ARGV.debug?
|
raise unless ARGV.debug?
|
||||||
@ -158,7 +162,13 @@ class Formula
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.factory name
|
def self.factory name
|
||||||
require self.path(name)
|
path = Pathname.new(name)
|
||||||
|
if path.absolute?
|
||||||
|
require name
|
||||||
|
name = path.stem
|
||||||
|
else
|
||||||
|
require self.path(name)
|
||||||
|
end
|
||||||
return eval(self.class_s(name)).new(name)
|
return eval(self.class_s(name)).new(name)
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
raise FormulaUnavailableError.new(name)
|
raise FormulaUnavailableError.new(name)
|
||||||
@ -242,7 +252,7 @@ private
|
|||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def patch
|
def patch
|
||||||
return if patches.empty?
|
return if patches.empty?
|
||||||
|
|
||||||
@ -258,17 +268,20 @@ private
|
|||||||
n=0
|
n=0
|
||||||
patch_defns.each do |arg, urls|
|
patch_defns.each do |arg, urls|
|
||||||
urls.each do |url|
|
urls.each do |url|
|
||||||
p = {:filename => '%03d-homebrew.patch' % n+=1, :compression => false}
|
p = {:filename => '%03d-homebrew.diff' % n+=1, :compression => false}
|
||||||
|
|
||||||
if url =~ %r[^\w+\://]
|
if defined? DATA and url == DATA
|
||||||
|
pn=Pathname.new p[:filename]
|
||||||
|
pn.write DATA.read
|
||||||
|
elsif url =~ %r[^\w+\://]
|
||||||
out_fn = p[:filename]
|
out_fn = p[:filename]
|
||||||
case url
|
case url
|
||||||
when /\.gz$/
|
when /\.gz$/
|
||||||
p[:compression] = :gzip
|
p[:compression] = :gzip
|
||||||
out_fn << '.gz'
|
out_fn += '.gz'
|
||||||
when /\.bz2$/
|
when /\.bz2$/
|
||||||
p[:compression] = :bzip2
|
p[:compression] = :bzip2
|
||||||
out_fn << '.bz2'
|
out_fn += '.bz2'
|
||||||
end
|
end
|
||||||
p[:curl_args] = [url, '-o', out_fn]
|
p[:curl_args] = [url, '-o', out_fn]
|
||||||
else
|
else
|
||||||
@ -281,9 +294,11 @@ private
|
|||||||
patch_list << p
|
patch_list << p
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return if patch_list.empty?
|
||||||
|
|
||||||
# downloading all at once is much more efficient, espeically for FTP
|
# downloading all at once is much more efficient, espeically for FTP
|
||||||
curl *(patch_list.collect { |p| p[:curl_args] }).flatten
|
curl *(patch_list.collect{|p| p[:curl_args]}.select{|p| p}.flatten)
|
||||||
|
|
||||||
patch_list.each do |p|
|
patch_list.each do |p|
|
||||||
case p[:compression]
|
case p[:compression]
|
||||||
|
|||||||
41
Library/Homebrew/global.rb
Normal file
41
Library/Homebrew/global.rb
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Copyright 2009 Max Howell and other contributors.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
require 'pathname+yeast'
|
||||||
|
require 'ARGV+yeast'
|
||||||
|
require 'utils'
|
||||||
|
require 'hardware'
|
||||||
|
|
||||||
|
if Process.uid == 0
|
||||||
|
# technically this is not the correct place, this cache is for *all users*
|
||||||
|
# so in that case, maybe we should always use it, root or not?
|
||||||
|
HOMEBREW_CACHE=Pathname.new("/Library/Caches/Homebrew")
|
||||||
|
else
|
||||||
|
HOMEBREW_CACHE=Pathname.new("~/Library/Caches/Homebrew").expand_path
|
||||||
|
end
|
||||||
|
|
||||||
|
HOMEBREW_PREFIX=(Pathname.getwd+__FILE__).dirname.parent.parent.cleanpath
|
||||||
|
HOMEBREW_CELLAR=HOMEBREW_PREFIX+'Cellar'
|
||||||
|
HOMEBREW_VERSION='0.4'
|
||||||
|
HOMEBREW_WWW='http://bit.ly/Homebrew'
|
||||||
|
HOMEBREW_USER_AGENT="Homebrew #{HOMEBREW_VERSION} (Ruby #{VERSION}; Mac OS X 10.5 Leopard)"
|
||||||
78
Library/Homebrew/install.rb
Executable file
78
Library/Homebrew/install.rb
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/ruby
|
||||||
|
require 'global'
|
||||||
|
require 'formula'
|
||||||
|
require 'keg'
|
||||||
|
require 'brew.h'
|
||||||
|
|
||||||
|
def install f
|
||||||
|
build_time=nil
|
||||||
|
|
||||||
|
begin
|
||||||
|
f.brew do
|
||||||
|
if ARGV.flag? '--interactive'
|
||||||
|
ohai "Entering interactive mode"
|
||||||
|
puts "Type `exit' to return and finalize the installation"
|
||||||
|
puts "Install to this prefix: #{f.prefix}"
|
||||||
|
interactive_shell
|
||||||
|
nil
|
||||||
|
elsif ARGV.include? '--help'
|
||||||
|
system './configure --help'
|
||||||
|
exit $?
|
||||||
|
else
|
||||||
|
f.prefix.mkpath
|
||||||
|
beginning=Time.now
|
||||||
|
f.install
|
||||||
|
%w[README ChangeLog COPYING LICENSE COPYRIGHT AUTHORS].each do |file|
|
||||||
|
FileUtils.mv "#{file}.txt", file rescue nil
|
||||||
|
f.prefix.install file rescue nil
|
||||||
|
end
|
||||||
|
build_time=Time.now-beginning
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue Exception
|
||||||
|
if f.prefix.directory?
|
||||||
|
f.prefix.rmtree
|
||||||
|
f.prefix.parent.rmdir_if_possible
|
||||||
|
end
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
|
||||||
|
ohai "Caveats", f.caveats, ''
|
||||||
|
ohai 'Finishing up' if ARGV.verbose?
|
||||||
|
|
||||||
|
begin
|
||||||
|
clean f
|
||||||
|
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"
|
||||||
|
ohai e, e.inspect if ARGV.debug?
|
||||||
|
end
|
||||||
|
|
||||||
|
raise "Nothing was installed to #{f.prefix}" unless f.installed?
|
||||||
|
|
||||||
|
begin
|
||||||
|
Keg.new(f.prefix).link
|
||||||
|
rescue Exception
|
||||||
|
onoe "The linking step did not complete successfully"
|
||||||
|
puts "The package built, but is not symlinked into #{HOMEBREW_PREFIX}"
|
||||||
|
puts "You can try again using `brew link #{f.name}'"
|
||||||
|
ohai e, e.inspect if ARGV.debug?
|
||||||
|
ohai "Summary"
|
||||||
|
else
|
||||||
|
ohai "Summary" if ARGV.verbose?
|
||||||
|
end
|
||||||
|
|
||||||
|
print "#{f.prefix}: #{f.prefix.abv}"
|
||||||
|
print ", built in #{pretty_duration build_time}" if build_time
|
||||||
|
puts
|
||||||
|
|
||||||
|
rescue Exception => e
|
||||||
|
#TODO propogate exception back to brew script
|
||||||
|
onoe e
|
||||||
|
puts e.backtrace
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# I like this little at all, but see no alternative seeing as the formula
|
||||||
|
# rb file has to be the running script to allow it to use __END__ and DATA
|
||||||
|
at_exit { install(Formula.factory($0)) }
|
||||||
@ -14,7 +14,7 @@ require 'utils'
|
|||||||
require 'brew.h'
|
require 'brew.h'
|
||||||
require 'hardware.rb'
|
require 'hardware.rb'
|
||||||
|
|
||||||
# these are defined in bin/brew, but we don't want to break our actual
|
# these are defined in global.rb, but we don't want to break our actual
|
||||||
# homebrew tree, and we do want to test everything :)
|
# homebrew tree, and we do want to test everything :)
|
||||||
HOMEBREW_PREFIX=Pathname.new '/tmp/testbrew/prefix'
|
HOMEBREW_PREFIX=Pathname.new '/tmp/testbrew/prefix'
|
||||||
HOMEBREW_CACHE=HOMEBREW_PREFIX.parent+"cache"
|
HOMEBREW_CACHE=HOMEBREW_PREFIX.parent+"cache"
|
||||||
|
|||||||
@ -75,8 +75,8 @@ def safe_system cmd, *args
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def curl url, *args
|
def curl *args
|
||||||
safe_system 'curl', '-f#LA', HOMEBREW_USER_AGENT, url, *args
|
safe_system 'curl', '-f#LA', HOMEBREW_USER_AGENT, *args unless args.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def puts_columns items, cols = 4
|
def puts_columns items, cols = 4
|
||||||
|
|||||||
64
bin/brew
64
bin/brew
@ -1,26 +1,10 @@
|
|||||||
#!/usr/bin/ruby
|
#!/usr/bin/ruby
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
$:.unshift ENV['RUBYLIB']=File.expand_path(__FILE__+'/../../Library/Homebrew')
|
ENV['RUBYLIB']=HOMEBREW_RUBYLIB=File.expand_path(__FILE__+'/../../Library/Homebrew')
|
||||||
require 'pathname+yeast'
|
$:.unshift HOMEBREW_RUBYLIB
|
||||||
require 'ARGV+yeast'
|
require 'global'
|
||||||
require 'utils'
|
|
||||||
require 'hardware'
|
|
||||||
require 'brew.h'
|
require 'brew.h'
|
||||||
|
|
||||||
if Process.uid == 0
|
|
||||||
# technically this is not the correct place, this cache is for *all users*
|
|
||||||
# so in that case, maybe we should always use it, root or not?
|
|
||||||
HOMEBREW_CACHE=Pathname.new("/Library/Caches/Homebrew")
|
|
||||||
else
|
|
||||||
HOMEBREW_CACHE=Pathname.new("~/Library/Caches/Homebrew").expand_path
|
|
||||||
end
|
|
||||||
|
|
||||||
HOMEBREW_PREFIX=(Pathname.getwd+__FILE__).dirname.parent.cleanpath
|
|
||||||
HOMEBREW_CELLAR=HOMEBREW_PREFIX+'Cellar'
|
|
||||||
HOMEBREW_VERSION='0.4'
|
|
||||||
HOMEBREW_WWW='http://bit.ly/Homebrew'
|
|
||||||
HOMEBREW_USER_AGENT="Homebrew #{HOMEBREW_VERSION} (Ruby #{VERSION}; Mac OS X 10.5 Leopard)"
|
|
||||||
|
|
||||||
if %w[/ /usr].include? HOMEBREW_PREFIX.to_s then abort <<-EOS
|
if %w[/ /usr].include? HOMEBREW_PREFIX.to_s then abort <<-EOS
|
||||||
You have placed Homebrew at the prefix: #{HOMEBREW_PREFIX}
|
You have placed Homebrew at the prefix: #{HOMEBREW_PREFIX}
|
||||||
This is not currently supported. Voice your support for this feature at:
|
This is not currently supported. Voice your support for this feature at:
|
||||||
@ -109,11 +93,14 @@ begin
|
|||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
# we need to ensure a pristine ENV for each process or the formula
|
# 1. formulae can modify ENV, so we must ensure that each
|
||||||
# will start with the ENV from the previous build
|
# installation has a pristine ENV when it starts, forking now is
|
||||||
|
# the easiest way to do this
|
||||||
|
# 2. formulae have access to __END__ the only way to allow this is
|
||||||
|
# to make the formula script the executed script
|
||||||
pid=fork
|
pid=fork
|
||||||
if pid.nil?
|
if pid.nil?
|
||||||
exec __FILE__, "install-just-one", f.name, *ARGV.options
|
exec 'ruby', '-r', "#{HOMEBREW_RUBYLIB}/install", f.path, '--', *ARGV.options
|
||||||
else
|
else
|
||||||
Process.wait pid
|
Process.wait pid
|
||||||
end
|
end
|
||||||
@ -122,39 +109,6 @@ begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# this is an internal option, don't expose it to the user
|
|
||||||
when 'install-just-one'
|
|
||||||
require 'keg'
|
|
||||||
|
|
||||||
f=ARGV.formulae.shift
|
|
||||||
|
|
||||||
begin
|
|
||||||
build_time=install f
|
|
||||||
ohai "Caveats", f.caveats, ''
|
|
||||||
ohai 'Finishing up' if ARGV.verbose?
|
|
||||||
clean f
|
|
||||||
raise "Nothing was installed to #{f.prefix}" unless f.installed?
|
|
||||||
rescue Exception
|
|
||||||
if f.prefix.directory?
|
|
||||||
f.prefix.rmtree
|
|
||||||
f.prefix.parent.rmdir_if_possible
|
|
||||||
end
|
|
||||||
raise
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
Keg.new(f.prefix).link
|
|
||||||
rescue Exception
|
|
||||||
onoe "The linking step did not complete successfully"
|
|
||||||
puts "The package built, but is not symlinked into #{HOMEBREW_PREFIX}"
|
|
||||||
puts "You can try again using `brew link #{f.name}'"
|
|
||||||
ohai "Summary" unless ARGV.verbose?
|
|
||||||
end
|
|
||||||
|
|
||||||
ohai "Summary" if ARGV.verbose?
|
|
||||||
print "#{f.prefix}: #{f.prefix.abv}"
|
|
||||||
print ", built in #{pretty_duration build_time}" if build_time
|
|
||||||
puts
|
|
||||||
|
|
||||||
when 'ln', 'link'
|
when 'ln', 'link'
|
||||||
ARGV.kegs.each {|keg| puts "#{keg.link} links created for #{keg}"}
|
ARGV.kegs.each {|keg| puts "#{keg.link} links created for #{keg}"}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user