diff options
| author | Adam Vandenberg | 2010-07-04 14:17:03 -0700 |
|---|---|---|
| committer | Adam Vandenberg | 2010-08-07 18:08:51 -0700 |
| commit | 8ce3c26a59a69217e679bb514393a1fba7ddd239 (patch) | |
| tree | 8a549698e500ed48ef580876f8d602e0560aecae /Library | |
| parent | f5b6fbb846b6f4e29ddd14450660a95da8257787 (diff) | |
| download | homebrew-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.rb | 160 |
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 |
