aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
authorAdam Vandenberg2010-07-04 14:17:03 -0700
committerAdam Vandenberg2010-08-07 18:08:51 -0700
commit8ce3c26a59a69217e679bb514393a1fba7ddd239 (patch)
tree8a549698e500ed48ef580876f8d602e0560aecae /Library
parentf5b6fbb846b6f4e29ddd14450660a95da8257787 (diff)
downloadhomebrew-8ce3c26a59a69217e679bb514393a1fba7ddd239.tar.bz2
"url" now has same features as "head"
Specifically, it can accept all the VCS tag specs that head could, making it more useful for defining stable versions that come from VCS instead of tarballs. A new "SoftwareSpecification" class was added to implement this. This new class holds a "spec" for downloading a software package. It combines the url (or head url) with the "specs" [1] that head has been able to take. This allows both the stable (url) and unstable (head) specification for a software package to co-exist without stomping on each others "specs". [1] "specs" contain instructions on which branch/tag/revision/etc. to use from the source repository URL.
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/formula.rb160
1 files changed, 100 insertions, 60 deletions
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 91320cf9a..4c726eced 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -6,26 +6,81 @@ class FormulaUnavailableError <RuntimeError
@name = name
super "No available formula for #{name}"
end
-
+
attr_reader :name
end
+class SoftwareSpecification
+ attr_reader :url, :specs, :using
+
+ VCS_SYMBOLS = {
+ :bzr, BazaarDownloadStrategy,
+ :curl, CurlDownloadStrategy,
+ :cvs, CVSDownloadStrategy,
+ :git, GitDownloadStrategy,
+ :hg, MercurialDownloadStrategy,
+ :nounzip, NoUnzipCurlDownloadStrategy,
+ :post, CurlPostDownloadStrategy,
+ :svn, SubversionDownloadStrategy,
+ }
+
+ def initialize url, specs=nil
+ raise "No url provided" if url.nil?
+ @url = url
+ unless specs.nil?
+ # Get download strategy hint, if any
+ @using = specs.delete :using
+ # The rest of the specs are for source control
+ @specs = specs
+ end
+ end
+
+ # Returns a suitable DownloadStrategy class that can be
+ # used to retreive this software package.
+ def download_strategy
+ return detect_download_strategy @url if @using.nil?
+
+ # If a class is passed, assume it is a download strategy
+ return @using if @using.kind_of? Class
+
+ detected = VCS_SYMBOLS[@using]
+ raise "Unknown strategy #{@using} was requested." unless detected
+ return detected
+ end
+
+ def detect_version
+ Pathname.new(@url).version
+ end
+end
+
+
# Derive and define at least @url, see Library/Formula for examples
class Formula
include FileUtils
-
+
attr_reader :url, :version, :homepage, :name, :specs, :downloader
# Homebrew determines the name
def initialize name='__UNKNOWN__'
+ set_instance_variable 'homepage'
set_instance_variable 'url'
set_instance_variable 'head'
set_instance_variable 'specs'
+ set_instance_variable 'stable'
+ set_instance_variable 'unstable'
+
if @head and (not @url or ARGV.build_head?)
- @url=@head
- @version='HEAD'
+ @url = @head
+ @version = 'HEAD'
+ @spec_to_use = @unstable
+ else
+ if @stable.nil?
+ @spec_to_use = SoftwareSpecification.new(@url, @specs)
+ else
+ @spec_to_use = @stable
+ end
end
raise "No url provided for formula #{name}" if @url.nil?
@@ -33,16 +88,12 @@ class Formula
validate_variable :name
set_instance_variable 'version'
- @version ||= Pathname.new(@url).version
+ @version ||= @spec_to_use.detect_version
validate_variable :version if @version
-
- set_instance_variable 'homepage'
- CHECKSUM_TYPES.each do |type|
- set_instance_variable type
- end
+ CHECKSUM_TYPES.each { |type| set_instance_variable type }
- @downloader=download_strategy.new url, name, version, specs
+ @downloader=download_strategy.new @spec_to_use.url, name, version, @spec_to_use.specs
end
# if the dir is there, but it's empty we consider it not installed
@@ -52,18 +103,14 @@ class Formula
return false
end
- def prefix
- validate_variable :name
- validate_variable :version
- HOMEBREW_CELLAR+@name+@version
- end
-
def path
self.class.path name
end
- def cached_download
- @downloader.cached_location
+ def prefix
+ validate_variable :name
+ validate_variable :version
+ HOMEBREW_CELLAR+@name+@version
end
def bin; prefix+'bin' end
@@ -77,33 +124,19 @@ class Formula
def include; prefix+'include' end
def share; prefix+'share' end
- # generally we don't want var stuff inside the keg
- def var; HOMEBREW_PREFIX+'var' end
# configuration needs to be preserved past upgrades
def etc; HOMEBREW_PREFIX+'etc' end
-
- # reimplement if we don't autodetect the download strategy you require
- def download_strategy
- if @specs and @url == @head
- vcs = @specs.delete :using
- if vcs != nil
- # If a class is passed, assume it is a download strategy
- return vcs if vcs.kind_of? Class
-
- case vcs
- when :bzr then return BazaarDownloadStrategy
- when :curl then return CurlDownloadStrategy
- when :cvs then return CVSDownloadStrategy
- when :git then return GitDownloadStrategy
- when :hg then return MercurialDownloadStrategy
- when :svn then return SubversionDownloadStrategy
- end
+ # generally we don't want var stuff inside the keg
+ def var; HOMEBREW_PREFIX+'var' end
- raise "Unknown strategy #{vcs} was requested."
- end
- end
+ # Use the @spec_to_use to detect the download strategy.
+ # Can be overriden to force a custom download strategy
+ def download_strategy
+ @spec_to_use.download_strategy
+ end
- detect_download_strategy url
+ def cached_download
+ @downloader.cached_location
end
# tell the user about any caveats regarding this package, return a string
@@ -213,7 +246,7 @@ class Formula
require self.path(name)
end
begin
- klass_name =self.class_s(name)
+ klass_name = self.class_s(name)
klass = eval(klass_name)
rescue NameError
# TODO really this text should be encoded into the exception
@@ -279,15 +312,15 @@ protected
rescue SystemCallError
# usually because exec could not be find the command that was requested
raise
- rescue
+ rescue
raise BuildError.new(cmd, args, $?)
end
private
- # creates a temporary directory then yields, when the block returns it
- # recursively deletes the temporary directory
+ # Create a temporary directory then yield. When the block returns,
+ # recursively delete the temporary directory.
def mktemp
- # I used /tmp rather than mktemp -td because that generates a directory
+ # I used /tmp rather than `mktemp -td` because that generates a directory
# name with exotic characters like + in it, and these break badly written
# scripts that don't escape strings before trying to regexp them :(
@@ -336,18 +369,15 @@ EOF
def stage
HOMEBREW_CACHE.mkpath
+ fetched = @downloader.fetch
+ verify_download_integrity fetched if fetched.kind_of? Pathname
- downloaded_tarball = @downloader.fetch
- if downloaded_tarball.kind_of? Pathname
- verify_download_integrity downloaded_tarball
- end
-
mktemp do
@downloader.stage
yield
end
end
-
+
def patch
return if patches.nil?
@@ -391,7 +421,7 @@ EOF
patch_list << p
end
end
-
+
return if patch_list.empty?
ohai "Downloading patches"
@@ -427,6 +457,8 @@ EOF
end
class << self
+ # The methods below define the formula DSL.
+ attr_reader :stable, :unstable
def self.attr_rw(*attrs)
attrs.each do |attr|
@@ -438,13 +470,21 @@ EOF
end
end
- attr_rw :url, :version, :homepage, :specs, :deps, :external_deps, *CHECKSUM_TYPES
+ attr_rw :version, :homepage, :specs, :deps, :external_deps
+ attr_rw *CHECKSUM_TYPES
def head val=nil, specs=nil
- if specs
- @specs = specs
- end
- val.nil? ? @head : @head = val
+ return @head if val.nil?
+ @unstable = SoftwareSpecification.new(val, specs)
+ @head = val
+ @specs = specs
+ end
+
+ def url val=nil, specs=nil
+ return @url if val.nil?
+ @stable = SoftwareSpecification.new(val, specs)
+ @url = val
+ @specs = specs
end
def depends_on name
@@ -480,7 +520,7 @@ EOF
@skip_clean_paths << p.to_s unless @skip_clean_paths.include? p.to_s
end
end
-
+
def skip_clean_paths
@skip_clean_paths or []
end