aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
authorAdam Vandenberg2009-08-11 12:20:55 -0700
committerMax Howell2009-08-24 01:03:23 +0100
commit0eaf4bbcd9e4afb8a92a678ee072e8167e841527 (patch)
tree914109b77c2bfe864165521c2af84e26953dc27c /Library
parent65e1419ea977c6ea1f4edd6ebf24f48c84fa0832 (diff)
downloadbrew-0eaf4bbcd9e4afb8a92a678ee072e8167e841527.tar.bz2
Factor out downloading from Formula
This patch adds a ArchiveDownloadStrategy that handles downloading tarbarlls and decompressing them into the staging area ready for brewing. Refactored safe_system and curl into utils.rb Signed-off-by: Max Howell <max@methylblue.com> Modifications to Adam's original patch: I reverted objectification of checksum verification because I couldn't think of any other download validation methods that might be useful to us in the future, so allowing such flexibility had no advantages. If we ever need this to be OO we can add it. But for now less complexity is preferable. I removed the @svnurl class member. Instead download_strategy is autodetected by examining the url. The user can override the download_strategy in case this fails. Thus we already can easily add support for clones of git repositories.
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/formula.rb148
-rw-r--r--Library/Homebrew/pathname+yeast.rb5
-rwxr-xr-xLibrary/Homebrew/unittest.rb26
-rw-r--r--Library/Homebrew/utils.rb14
4 files changed, 119 insertions, 74 deletions
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index c0cb925a2..2b3d3d996 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -16,6 +16,63 @@
# along with Homebrew. If not, see <http://www.gnu.org/licenses/>.
+class AbstractDownloadStrategy
+ def initialize url, name, version
+ @url=url
+ @unique_token="#{name}-#{version}"
+ end
+end
+
+class HttpDownloadStrategy <AbstractDownloadStrategy
+ def fetch
+ ohai "Downloading #{@url}"
+ @dl=HOMEBREW_CACHE+(@unique_token+ext)
+ unless @dl.exist?
+ curl @url, '-o', @dl
+ else
+ puts "File already downloaded and cached"
+ end
+ return @dl # thus performs checksum verification
+ end
+ def stage
+ case `file -b #{@dl}`
+ when /^Zip archive data/
+ safe_system 'unzip', '-qq', @dl
+ chdir
+ when /^(gzip|bzip2) compressed data/
+ # TODO do file -z now to see if it is in fact a tar
+ safe_system 'tar', 'xf', @dl
+ chdir
+ else
+ # we are assuming it is not an archive, use original filename
+ # this behaviour is due to ScriptFileFormula expectations
+ @dl.mv File.basename(@url)
+ end
+ end
+private
+ def chdir
+ entries=Dir['*']
+ case entries.length
+ when 0 then raise "Empty archive"
+ when 1 then Dir.chdir entries.first rescue nil
+ end
+ end
+ def ext
+ # GitHub uses odd URLs for zip files, so check for those
+ rx=%r[http://(www\.)?github\.com/.*/(zip|tar)ball/]
+ if rx.match @url
+ if $2 == 'zip'
+ '.zip'
+ else
+ '.tgz'
+ end
+ else
+ Pathname.new(@url).extname
+ end
+ end
+end
+
+
class ExecutionError <RuntimeError
def initialize cmd, args=[]
super "#{cmd} #{args*' '}"
@@ -40,7 +97,9 @@ class AbstractFormula
@homepage=self.class.homepage unless @homepage
@md5=self.class.md5 unless @md5
@sha1=self.class.sha1 unless @sha1
- raise "@url is nil" if @url.nil?
+ raise if @url.nil?
+ raise if @name =~ /\s/
+ raise if @version =~ /\s/
end
# if the dir is there, but it's empty we consider it not installed
@@ -60,7 +119,7 @@ class AbstractFormula
Formula.path name
end
- attr_reader :url, :version, :url, :homepage, :name
+ attr_reader :url, :version, :homepage, :name
def bin; prefix+'bin' end
def sbin; prefix+'sbin' end
@@ -71,6 +130,15 @@ class AbstractFormula
def info; prefix+'share'+'info' end
def include; prefix+'include' end
+ # reimplement if we don't autodetect the download strategy you require
+ def download_strategy
+ case url
+ when %r[^svn://] then SubversionDownloadStrategy
+ when %r[^git://] then GitDownloadStrategy
+ when %r[^http://(.+?\.)?googlecode\.com/svn] then SubversionDownloadStrategy
+ else HttpDownloadStrategy
+ end
+ end
# tell the user about any caveats regarding this package
def caveats; nil end
# patches are automatically applied after extracting the tarball
@@ -89,19 +157,7 @@ class AbstractFormula
# yields self with current working directory set to the uncompressed tarball
def brew
- ohai "Downloading #{@url}"
- tgz=HOMEBREW_CACHE+File.basename(@url)
- unless tgz.exist?
- HOMEBREW_CACHE.mkpath
- curl @url, '-o', tgz
- else
- puts "File already downloaded and cached"
- end
-
- verify_download_integrity tgz
-
- mktemp do
- Dir.chdir uncompress(tgz)
+ stage do
begin
patch
yield self
@@ -144,8 +200,10 @@ protected
end
private
+ # creates a temporary directory then yields, when the block returns it
+ # recursively deletes the temporary directory
def mktemp
- tmp=Pathname.new `mktemp -dt #{File.basename @url}`.strip
+ tmp=Pathname.new `mktemp -dt #{name}-#{version}`.strip
raise if not tmp.directory? or $? != 0
begin
wd=Dir.pwd
@@ -157,20 +215,6 @@ private
end
end
- # Kernel.system but with exceptions
- def safe_system cmd, *args
- puts "#{cmd} #{args*' '}" if ARGV.verbose?
-
- execd=Kernel.system cmd, *args
- # somehow Ruby doesn't handle the CTRL-C from another process -- WTF!?
- raise Interrupt, cmd if $?.termsig == 2
- raise ExecutionError.new(cmd, args) unless execd and $? == 0
- end
-
- def curl url, *args
- safe_system 'curl', '-f#LA', HOMEBREW_USER_AGENT, url, *args
- end
-
def verify_download_integrity fn
require 'digest'
type='MD5'
@@ -183,7 +227,18 @@ private
else
opoo "Cannot verify package integrity"
puts "The formula did not provide a download checksum"
- puts "For your reference the #{type} is: #{hash}"
+ puts "For your reference the #{type} is: #{hash}"
+ end
+ end
+
+ def stage
+ ds=download_strategy.new url, name, version
+ HOMEBREW_CACHE.mkpath
+ dl=ds.fetch
+ verify_download_integrity dl if dl.kind_of? Pathname
+ mktemp do
+ ds.stage
+ yield
end
end
@@ -216,7 +271,7 @@ private
end
class <<self
- attr_reader :url, :version, :md5, :url, :homepage, :sha1
+ attr_reader :url, :version, :homepage, :md5, :sha1
end
end
@@ -254,30 +309,6 @@ class Formula <AbstractFormula
end
private
- def uncompress_args
- rx=%r[http://(www.)?github.com/.*/(zip|tar)ball/]
- if rx.match @url and $2 == '.zip' or Pathname.new(@url).extname == '.zip'
- %w[unzip -qq]
- else
- %w[tar xf]
- end
- end
-
- def uncompress path
- safe_system *uncompress_args<<path
-
- entries=Dir['*']
- if entries.length == 0
- raise "Empty archive"
- elsif entries.length == 1
- # if one dir enter it as that will be where the build is
- entries.first
- else
- # if there's more than one dir, then this is the build directory already
- Dir.pwd
- end
- end
-
def method_added method
raise 'You cannot override Formula.brew' if method == 'brew'
end
@@ -289,11 +320,8 @@ class ScriptFileFormula <AbstractFormula
super
@name=name
end
- def uncompress path
- path.dirname
- end
def install
- bin.install File.basename(@url)
+ bin.install Dir['*']
end
end
diff --git a/Library/Homebrew/pathname+yeast.rb b/Library/Homebrew/pathname+yeast.rb
index dffbb0244..f0ca0f503 100644
--- a/Library/Homebrew/pathname+yeast.rb
+++ b/Library/Homebrew/pathname+yeast.rb
@@ -22,11 +22,10 @@ class Pathname
def mv dst
FileUtils.mv to_s, dst
end
-
+
def rename newname
- raise unless file?
dst=dirname+newname
- dst.unlink if dst.exist?
+ dst.unlink if dst.exist? and file?
mv dst
end
diff --git a/Library/Homebrew/unittest.rb b/Library/Homebrew/unittest.rb
index 2ffb874ba..f3ea7c930 100755
--- a/Library/Homebrew/unittest.rb
+++ b/Library/Homebrew/unittest.rb
@@ -43,9 +43,9 @@ end
class TestZip <Formula
def initialize
- path=HOMEBREW_CACHE.parent+'test-0.1.zip'
- Kernel.system 'zip', '-0', path, __FILE__
- @url="file://#{path}"
+ zip=HOMEBREW_CACHE.parent+'test-0.1.zip'
+ Kernel.system 'zip', '-0', zip, __FILE__
+ @url="file://#{zip}"
super 'testzip'
end
end
@@ -63,7 +63,6 @@ class TestBallOverrideBrew <Formula
super "foo"
end
def brew
- # We can't override brew
end
end
@@ -78,13 +77,18 @@ class TestScriptFileFormula <ScriptFileFormula
end
def nostdout
- require 'stringio'
- tmpo=$stdout
- tmpe=$stderr
- $stdout=StringIO.new
- yield
-ensure
- $stdout=tmpo
+ if ARGV.include? '-V'
+ yield
+ end
+ begin
+ require 'stringio'
+ tmpo=$stdout
+ tmpe=$stderr
+ $stdout=StringIO.new
+ yield
+ ensure
+ $stdout=tmpo
+ end
end
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index 7c86faf1b..06b9cab21 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -49,3 +49,17 @@ def interactive_shell
Process.wait pid
end
end
+
+# Kernel.system but with exceptions
+def safe_system cmd, *args
+ puts "#{cmd} #{args*' '}" if ARGV.verbose?
+
+ execd=Kernel.system cmd, *args
+ # somehow Ruby doesn't handle the CTRL-C from another process -- WTF!?
+ raise Interrupt, cmd if $?.termsig == 2
+ raise ExecutionError.new(cmd, args) unless execd and $? == 0
+end
+
+def curl url, *args
+ safe_system 'curl', '-f#LA', HOMEBREW_USER_AGENT, url, *args
+end