diff options
| -rw-r--r-- | Library/Homebrew/bottles.rb | 8 | ||||
| -rw-r--r-- | Library/Homebrew/compat/compatibility.rb | 4 | ||||
| -rw-r--r-- | Library/Homebrew/formula.rb | 268 | ||||
| -rw-r--r-- | Library/Homebrew/formula_installer.rb | 6 | ||||
| -rw-r--r-- | Library/Homebrew/formula_specialties.rb | 4 | ||||
| -rw-r--r-- | Library/Homebrew/formula_support.rb | 128 | ||||
| -rw-r--r-- | Library/Homebrew/test/test_formula.rb | 234 | ||||
| -rw-r--r-- | Library/Homebrew/test/testball.rb | 130 | ||||
| -rw-r--r-- | Library/Homebrew/test/testing_env.rb | 5 |
9 files changed, 626 insertions, 161 deletions
diff --git a/Library/Homebrew/bottles.rb b/Library/Homebrew/bottles.rb index d7ed83d23..0164b07dd 100644 --- a/Library/Homebrew/bottles.rb +++ b/Library/Homebrew/bottles.rb @@ -3,8 +3,8 @@ require 'extend/ARGV' def bottle_filename f, bottle_version=nil name = f.name.downcase - version = f.version || f.standard.detect_version - bottle_version = bottle_version || f.bottle_version + version = f.stable.version + bottle_version ||= f.bottle.revision.to_i "#{name}-#{version}#{bottle_native_suffix(bottle_version)}" end @@ -22,7 +22,7 @@ def built_bottle? f end def bottle_current? f - f.bottle_url && f.bottle_sha1 && Pathname.new(f.bottle_url).version == f.version + f.bottle.url && f.bottle.has_checksum? && f.bottle.version == f.stable.version end def bottle_file_outdated? f, file @@ -39,7 +39,7 @@ end def bottle_new_version f return 0 unless bottle_current? f - f.bottle_version + 1 + f.bottle.revision + 1 end def bottle_native_suffix version=nil diff --git a/Library/Homebrew/compat/compatibility.rb b/Library/Homebrew/compat/compatibility.rb index 45222cf82..3f0f23766 100644 --- a/Library/Homebrew/compat/compatibility.rb +++ b/Library/Homebrew/compat/compatibility.rb @@ -91,6 +91,10 @@ class Formula def std_cmake_parameters "-DCMAKE_INSTALL_PREFIX='#{prefix}' -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev" end + + class << self + attr_rw :bottle_sha1 + end end class UnidentifiedFormula < Formula diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 541ee65d8..92509f13f 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -7,13 +7,12 @@ require 'extend/fileutils' require 'patches' require 'compilers' -# Derive and define at least @url, see Library/Formula for examples + class Formula include FileUtils - attr_reader :name, :path, :url, :version, :homepage, :specs, :downloader - attr_reader :standard, :unstable, :head - attr_reader :bottle_version, :bottle_url, :bottle_sha1 + attr_reader :name, :path, :homepage, :downloader + attr_reader :stable, :bottle, :devel, :head, :active_spec # The build folder, usually in /tmp. # Will only be non-nil during the stage method. @@ -21,50 +20,76 @@ class Formula # Homebrew determines the name def initialize name='__UNKNOWN__', path=nil - set_instance_variable 'homepage' - set_instance_variable 'url' - set_instance_variable 'bottle_version' - set_instance_variable 'bottle_url' - set_instance_variable 'bottle_sha1' - set_instance_variable 'head' - set_instance_variable 'specs' - set_instance_variable 'standard' - set_instance_variable 'unstable' - - if @head and (not @url or ARGV.build_head?) - @url = @head - @version = 'HEAD' - @spec_to_use = @unstable - else - if @standard.nil? - @spec_to_use = SoftwareSpecification.new(@url, @specs) - else - @spec_to_use = @standard - end - end + set_instance_variable :homepage + set_instance_variable :stable + set_instance_variable :bottle + set_instance_variable :devel + set_instance_variable :head - raise "No url provided for formula #{name}" if @url.nil? @name = name validate_variable :name - # If we got an explicit path, use that, else determine from the name - @path = path.nil? ? self.class.path(name) : Pathname.new(path) + # Legacy formulae can set specs via class ivars + ensure_specs_set if @stable.nil? + + # If a checksum or version was set in the DSL, but no stable URL + # was defined, make @stable nil and save callers some trouble + @stable = nil if @stable and @stable.url.nil? - # Use a provided version, if any - set_instance_variable 'version' - # Otherwise detect the version from the URL - @version ||= @spec_to_use.detect_version - # Only validate if a version was set; GitHubGistFormula needs to get - # the URL to determine the version + # Ensure the bottle URL is set. If it does not have a checksum, + # then a bottle is not available for the current platform. + if @bottle and @bottle.has_checksum? + @bottle.url ||= bottle_base_url + bottle_filename(self) + else + @bottle = nil + end + + @active_spec = if @head and ARGV.build_head? then @head # --HEAD + elsif @devel and ARGV.build_devel? then @devel # --devel + elsif @bottle and install_bottle?(self) then @bottle # bottle available + elsif @stable.nil? and @head then @head # head-only + else @stable # default + end + + @version = @active_spec.version validate_variable :version if @version - CHECKSUM_TYPES.each { |type| set_instance_variable type } + raise "No url provided for formula #{name}" if @active_spec.url.nil? - @downloader = download_strategy.new @spec_to_use.url, name, version, @spec_to_use.specs + # If we got an explicit path, use that, else determine from the name + @path = path.nil? ? self.class.path(name) : Pathname.new(path) + @downloader = download_strategy.new(@active_spec.url, name, @active_spec.version, @active_spec.specs) + end + + # Derive specs from class ivars + def ensure_specs_set + set_instance_variable :url + set_instance_variable :version + set_instance_variable :md5 + set_instance_variable :sha1 + set_instance_variable :sha256 + + unless @url.nil? + @stable = SoftwareSpec.new + @stable.url(@url) + @stable.version(@version) + @stable.md5(@md5) + @stable.sha1(@sha1) + @stable.sha256(@sha256) + end - @bottle_url ||= bottle_base_url + bottle_filename(self) if @bottle_sha1 + if @head.kind_of? String + url = @head + @head = HeadSoftwareSpec.new + @head.url(url, self.class.instance_variable_get("@specs")) + end end + def url; @active_spec.url; end + def version; @active_spec.version; end + def specs; @active_spec.specs; end + def mirrors; @active_spec.mirrors or []; end + # if the dir is there, but it's empty we consider it not installed def installed? return installed_prefix.children.length > 0 @@ -84,9 +109,18 @@ class Formula end def installed_prefix - head_prefix = HOMEBREW_CELLAR+@name+'HEAD' - if @version == 'HEAD' || head_prefix.directory? + devel_prefix = unless @devel.nil? + HOMEBREW_CELLAR/@name/@devel.version + end + + head_prefix = unless @head.nil? + HOMEBREW_CELLAR/@name/@head.version + end + + if @active_spec == @head || @head and head_prefix.directory? head_prefix + elsif @active_spec == @devel || @devel and devel_prefix.directory? + devel_prefix else prefix end @@ -126,10 +160,10 @@ class Formula def plist_name; 'homebrew.mxcl.'+name end def plist_path; prefix+(plist_name+'.plist') end - # Use the @spec_to_use to detect the download strategy. + # Use the @active_spec to detect the download strategy. # Can be overriden to force a custom download strategy def download_strategy - @spec_to_use.download_strategy + @active_spec.download_strategy end def cached_download @@ -388,8 +422,6 @@ class Formula HOMEBREW_REPOSITORY+"Library/Formula/#{name.downcase}.rb" end - def mirrors; self.class.mirrors or []; end - def deps; self.class.dependencies.deps; end def external_deps; self.class.dependencies.external_deps; end @@ -456,19 +488,17 @@ public # For brew-fetch and others. def fetch - if install_bottle? self - downloader = CurlBottleDownloadStrategy.new bottle_url, name, version, nil - mirror_list = [] - else - downloader = @downloader - # Don't attempt mirrors if this install is not pointed at a "stable" URL. - # This can happen when options like `--HEAD` are invoked. - mirror_list = @spec_to_use == @standard ? mirrors : [] + downloader = @downloader + mirror_list = case @active_spec + when @stable, @devel then @active_spec.mirrors + else [] end # Ensure the cache exists HOMEBREW_CACHE.mkpath + # TODO teach download strategies to take a SoftwareSpec + # object, and move mirror handling into CurlDownloadStrategy begin fetched = downloader.fetch rescue CurlDownloadStrategyError => e @@ -482,34 +512,27 @@ public return fetched, downloader end - # Detect which type of checksum is being used, or nil if none - def checksum_type - CHECKSUM_TYPES.detect { |type| instance_variable_defined?("@#{type}") } - end - # For FormulaInstaller. - def verify_download_integrity fn, *args - require 'digest' - if args.length != 2 - type = checksum_type || :md5 - supplied = instance_variable_get("@#{type}") - # Convert symbol to readable string - type = type.to_s.upcase - else - supplied, type = args - end + def verify_download_integrity fn + # Checksums don't apply to HEAD + return if @active_spec == @head + + type = @active_spec.checksum_type || :md5 + supplied = @active_spec.send(type) + type = type.to_s.upcase + require 'digest' hasher = Digest.const_get(type) hash = fn.incremental_hash(hasher) if supplied and not supplied.empty? - message = <<-EOF -#{type} mismatch -Expected: #{supplied} -Got: #{hash} -Archive: #{fn} -(To retry an incomplete download, remove the file above.) -EOF + message = <<-EOS.undent + #{type} mismatch + Expected: #{supplied} + Got: #{hash} + Archive: #{fn} + (To retry an incomplete download, remove the file above.) + EOS raise message unless supplied.upcase == hash.upcase else opoo "Cannot verify package integrity" @@ -520,8 +543,6 @@ EOF private - CHECKSUM_TYPES=[:md5, :sha1, :sha256].freeze - def stage fetched, downloader = fetch verify_download_integrity fetched if fetched.kind_of? Pathname @@ -571,7 +592,6 @@ private class << self # The methods below define the formula DSL. - attr_reader :standard, :unstable def self.attr_rw(*attrs) attrs.each do |attr| @@ -583,79 +603,61 @@ private end end - attr_rw :version, :homepage, :mirrors, :specs - attr_rw :keg_only_reason, :skip_clean_all, :cc_failures - attr_rw :bottle_version, :bottle_url, :bottle_sha1 - attr_rw(*CHECKSUM_TYPES) + attr_rw :homepage, :keg_only_reason, :skip_clean_all, :cc_failures - def head val=nil, specs=nil - return @head if val.nil? - @unstable = SoftwareSpecification.new(val, specs) - @head = val - @specs = specs + SoftwareSpec::CHECKSUM_TYPES.each do |cksum| + class_eval %Q{ + def #{cksum}(val=nil) + unless val.nil? + @stable ||= SoftwareSpec.new + @stable.#{cksum}(val) + end + return @stable ? @stable.#{cksum} : @#{cksum} + end + } end def url val=nil, specs=nil - return @url if val.nil? - @standard = SoftwareSpecification.new(val, specs) - @url = val - @specs = specs + if val.nil? + return @stable.url if @stable + return @url if @url + end + @stable ||= SoftwareSpec.new + @stable.url(val, specs) end def stable &block - raise "url and md5 must be specified in a block" unless block_given? - instance_eval(&block) unless ARGV.build_devel? or ARGV.build_head? - end - - def devel &block - raise "url and md5 must be specified in a block" unless block_given? - if ARGV.build_devel? - @mirrors = nil # clear out mirrors from the stable release - instance_eval(&block) - end + return @stable unless block_given? + instance_eval(&block) end def bottle url=nil, &block - return unless block_given? - - bottle_block = Class.new do - def self.version version - @version = version - end - - def self.url url - @url = url - end + return @bottle unless block_given? + @bottle ||= Bottle.new + @bottle.instance_eval(&block) + end - def self.sha1 sha1 - case sha1 - when Hash - key, value = sha1.shift - @sha1 = key if value == MacOS.cat - when String - @sha1 = sha1 if MacOS.lion? - end - end + def devel &block + return @devel unless block_given? + @devel ||= SoftwareSpec.new + @devel.instance_eval(&block) + end - def self.data - @version = 0 unless @version - return @version, @url, @sha1 if @sha1 && @url - return @version, nil, @sha1 if @sha1 - end - end + def head val=nil, specs=nil + return @head if val.nil? + @head ||= HeadSoftwareSpec.new + @head.url(val, specs) + end - bottle_block.instance_eval(&block) - @bottle_version, @bottle_url, @bottle_sha1 = bottle_block.data + def version val=nil + return @version if val.nil? + @stable ||= SoftwareSpec.new + @stable.version(val) end def mirror val, specs=nil - @mirrors ||= [] - @mirrors << {:url => val, :specs => specs} - # Added the uniq after some inspection with Pry---seems `mirror` gets - # called three times. The first two times only one copy of the input is - # left in `@mirrors`. On the final call, two copies are present. This - # happens with `@deps` as well. Odd. - @mirrors.uniq! + @stable ||= SoftwareSpec.new + @stable.mirror(val, specs) end def dependencies diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 9d4b3b492..a7fd0d07f 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -29,7 +29,7 @@ class FormulaInstaller end # Building head-only without --HEAD is an error - if not ARGV.build_head? and f.standard.nil? + if not ARGV.build_head? and f.stable.nil? raise CannotInstallFormulaError, <<-EOS.undent #{f} is a head-only formula Install with `brew install --HEAD #{f.name} @@ -37,7 +37,7 @@ class FormulaInstaller end # Building stable-only with --HEAD is an error - if ARGV.build_head? and f.unstable.nil? + if ARGV.build_head? and f.head.nil? raise CannotInstallFormulaError, "No head is defined for #{f.name}" end @@ -261,7 +261,7 @@ class FormulaInstaller def pour fetched, downloader = f.fetch - f.verify_download_integrity fetched, f.bottle_sha1, "SHA1" + f.verify_download_integrity fetched HOMEBREW_CELLAR.cd do downloader.stage end diff --git a/Library/Homebrew/formula_specialties.rb b/Library/Homebrew/formula_specialties.rb index 6cae0887f..4e63440a6 100644 --- a/Library/Homebrew/formula_specialties.rb +++ b/Library/Homebrew/formula_specialties.rb @@ -11,7 +11,9 @@ end class GithubGistFormula < ScriptFileFormula def initialize name='__UNKNOWN__', path=nil super name, path - @version=File.basename(File.dirname(url))[0,6] + @stable.version(File.basename(File.dirname(url))[0,6]) + @version = @active_spec.version + validate_variable :version end end diff --git a/Library/Homebrew/formula_support.rb b/Library/Homebrew/formula_support.rb index 06b25729b..9bd7b6d6b 100644 --- a/Library/Homebrew/formula_support.rb +++ b/Library/Homebrew/formula_support.rb @@ -1,9 +1,9 @@ require 'download_strategy' +class SoftwareSpec + attr_reader :checksum, :mirrors, :specs, :strategy -# Defines a URL and download method for a stable or HEAD build -class SoftwareSpecification - attr_reader :url, :specs, :using + CHECKSUM_TYPES = [:md5, :sha1, :sha256].freeze VCS_SYMBOLS = { :bzr => BazaarDownloadStrategy, @@ -16,34 +16,122 @@ class SoftwareSpecification :svn => SubversionDownloadStrategy, } - def initialize url, specs=nil - raise "No url provided" if url.nil? - @url = url - if specs.nil? - @using = nil - else - # Get download strategy hint, if any - @using = specs.delete :using - # The rest of the specs are for source control - @specs = specs + # Detect which type of checksum is being used, or nil if none + def checksum_type + @checksum_type ||= CHECKSUM_TYPES.detect do |type| + instance_variable_defined?("@#{type}") end end + def has_checksum? + (checksum_type and self.send(checksum_type)) || false + end + + # Was the version defined in the DSL, or detected from the URL? + def explicit_version? + @explicit_version || false + end + # Returns a suitable DownloadStrategy class that can be - # used to retreive this software package. + # used to retrieve this software package. def download_strategy - return detect_download_strategy(@url) if @using.nil? + return detect_download_strategy(@url) if @strategy.nil? # If a class is passed, assume it is a download strategy - return @using if @using.kind_of? Class + return @strategy if @strategy.kind_of? Class - detected = VCS_SYMBOLS[@using] - raise "Unknown strategy #{@using} was requested." unless detected + detected = VCS_SYMBOLS[@strategy] + raise "Unknown strategy #{@strategy} was requested." unless detected return detected end - def detect_version - Pathname.new(@url).version + # The methods that follow are used in the block-form DSL spec methods + CHECKSUM_TYPES.each do |cksum| + class_eval %Q{ + def #{cksum}(val=nil) + val.nil? ? @#{cksum} : @#{cksum} = val + end + } + end + + def url val=nil, specs=nil + return @url if val.nil? + @url = val + if specs.nil? + @strategy = nil + else + @strategy = specs.delete :using + @specs = specs + end + end + + def version val=nil + unless val.nil? + @version = val + @explicit_version = true + end + @version ||= Pathname.new(@url).version + return @version + end + + def mirror val, specs=nil + @mirrors ||= [] + @mirrors << { :url => val, :specs => specs } + end +end + +class HeadSoftwareSpec < SoftwareSpec + def initialize + super + @version = 'HEAD' + @checksum = nil + end + + def verify_download_integrity fn + return + end +end + +class Bottle < SoftwareSpec + attr_writer :url + attr_reader :revision + + def initialize + @revision = 0 + @strategy = CurlBottleDownloadStrategy + end + + # Checksum methods in the DSL's bottle block optionally take + # a Hash, which indicates the platform the checksum applies on. + CHECKSUM_TYPES.each do |cksum| + class_eval %Q{ + def #{cksum}(val=nil) + @#{cksum} ||= Hash.new + case val + when nil + @#{cksum}[MacOS.cat] + when String + @#{cksum}[:lion] = val + when Hash + key, value = val.shift + @#{cksum}[value] = key + end + end + } + end + + def url val=nil + val.nil? ? @url : @url = val + end + + # Used in the bottle DSL to set @revision, but acts as an + # as accessor for @version to preserve the interface + def version val=nil + if val.nil? + return @version ||= Pathname.new(@url).version + else + @revision = val + end end end diff --git a/Library/Homebrew/test/test_formula.rb b/Library/Homebrew/test/test_formula.rb index b49b06757..55b48e3b0 100644 --- a/Library/Homebrew/test/test_formula.rb +++ b/Library/Homebrew/test/test_formula.rb @@ -66,4 +66,238 @@ class FormulaTests < Test::Unit::TestCase assert_equal downloader.url, "file:///#{TEST_FOLDER}/tarballs/testball-0.1.tbz" end end + + def test_formula_specs + f = SpecTestBall.new + + assert_equal 'http://example.com', f.homepage + assert_equal 'file:///foo.com/testball-0.1.tbz', f.url + assert_equal 1, f.mirrors.length + assert_equal '0.1', f.version + assert_equal f.stable, f.active_spec + assert_equal CurlDownloadStrategy, f.download_strategy + assert_instance_of CurlDownloadStrategy, f.downloader + + assert_instance_of SoftwareSpec, f.stable + assert_instance_of Bottle, f.bottle + assert_instance_of SoftwareSpec, f.devel + assert_instance_of HeadSoftwareSpec, f.head + + assert_equal 'file:///foo.com/testball-0.1.tbz', f.stable.url + assert_equal "https://downloads.sf.net/project/machomebrew/Bottles/spectestball-0.1.#{MacOS.cat}.bottle.tar.gz", + f.bottle.url + assert_equal 'file:///foo.com/testball-0.2.tbz', f.devel.url + assert_equal 'https://github.com/mxcl/homebrew.git', f.head.url + + assert_nil f.stable.specs + assert_nil f.bottle.specs + assert_nil f.devel.specs + assert_equal({ :tag => 'foo' }, f.head.specs) + + assert_equal CurlDownloadStrategy, f.stable.download_strategy + assert_equal CurlBottleDownloadStrategy, f.bottle.download_strategy + assert_equal CurlDownloadStrategy, f.devel.download_strategy + assert_equal GitDownloadStrategy, f.head.download_strategy + + assert f.stable.has_checksum? + assert f.bottle.has_checksum? + assert f.devel.has_checksum? + assert !f.head.has_checksum? + assert_equal :sha1, f.stable.checksum_type + assert_equal :sha1, f.bottle.checksum_type + assert_equal :sha256, f.devel.checksum_type + assert_nil f.head.checksum_type + assert_equal case MacOS.cat + when :snowleopard then 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' + when :lion then 'baadf00dbaadf00dbaadf00dbaadf00dbaadf00d' + end, f.bottle.sha1 + assert_match /[0-9a-fA-F]{40}/, f.stable.sha1 + assert_match /[0-9a-fA-F]{64}/, f.devel.sha256 + + assert_nil f.stable.md5 + assert_nil f.stable.sha256 + assert_nil f.bottle.md5 + assert_nil f.bottle.sha256 + assert_nil f.devel.md5 + assert_nil f.devel.sha1 + + assert_equal 1, f.stable.mirrors.length + assert_nil f.bottle.mirrors + assert_equal 1, f.devel.mirrors.length + assert_nil f.head.mirrors + + assert !f.stable.explicit_version? + assert !f.bottle.explicit_version? + assert !f.devel.explicit_version? + assert_equal '0.1', f.stable.version + assert_equal '0.1', f.bottle.version + assert_equal '0.2', f.devel.version + assert_equal 'HEAD', f.head.version + assert_equal 0, f.bottle.revision + end + + def test_ancient_formula_specs + f = AncientSpecTestBall.new + + assert_equal 'http://example.com', f.homepage + assert_equal 'file:///foo.com/testball-0.1.tbz', f.url + assert_equal '0.1', f.version + assert_equal f.stable, f.active_spec + assert_equal CurlDownloadStrategy, f.download_strategy + assert_instance_of CurlDownloadStrategy, f.downloader + + assert_instance_of SoftwareSpec, f.stable + assert_instance_of HeadSoftwareSpec, f.head + + assert_equal 'file:///foo.com/testball-0.1.tbz', f.stable.url + assert_equal 'https://github.com/mxcl/homebrew.git', f.head.url + + assert_nil f.stable.specs + assert_equal({ :tag => 'foo' }, f.head.specs) + + assert f.stable.has_checksum? + assert !f.head.has_checksum? + assert_equal :md5, f.stable.checksum_type + assert_nil f.head.checksum_type + assert_match /[0-9a-fA-F]{32}/, f.stable.md5 + + assert !f.stable.explicit_version? + assert_equal '0.1', f.stable.version + assert_equal 'HEAD', f.head.version + end + + def test_devel_active_spec + ARGV.push '--devel' + f = SpecTestBall.new + assert_equal f.devel, f.active_spec + assert_equal '0.2', f.version + assert_equal 'file:///foo.com/testball-0.2.tbz', f.url + assert_equal CurlDownloadStrategy, f.download_strategy + assert_instance_of CurlDownloadStrategy, f.downloader + ARGV.delete '--devel' + end + + def test_head_active_spec + ARGV.push '--HEAD' + f = SpecTestBall.new + assert_equal f.head, f.active_spec + assert_equal 'HEAD', f.version + assert_equal 'https://github.com/mxcl/homebrew.git', f.url + assert_equal GitDownloadStrategy, f.download_strategy + assert_instance_of GitDownloadStrategy, f.downloader + ARGV.delete '--HEAD' + end + + def test_explicit_version_spec + f = ExplicitVersionSpecTestBall.new + assert_equal '0.3', f.version + assert_equal '0.3', f.stable.version + assert_equal '0.4', f.devel.version + assert f.stable.explicit_version? + assert f.devel.explicit_version? + end + + def test_old_bottle_specs + f = OldBottleSpecTestBall.new + + case MacOS.cat + when :lion + assert_instance_of Bottle, f.bottle + assert_equal CurlBottleDownloadStrategy, f.bottle.download_strategy + assert_nil f.bottle.specs + assert_nil f.bottle.mirrors + + assert_equal 'file:///foo.com/testball-0.1-bottle.tar.gz', f.bottle.url + + assert f.bottle.has_checksum? + assert_equal :sha1, f.bottle.checksum_type + assert_equal 'baadf00dbaadf00dbaadf00dbaadf00dbaadf00d', f.bottle.sha1 + assert_nil f.bottle.md5 + assert_nil f.bottle.sha256 + + assert !f.bottle.explicit_version? + assert_equal 0, f.bottle.revision + assert_equal '0.1', f.bottle.version + else + assert_nil f.bottle + end + end + + def test_ancient_bottle_specs + f = AncientBottleSpecTestBall.new + assert_nil f.bottle + end + + def test_head_only_specs + f = HeadOnlySpecTestBall.new + + assert_not_nil f.head + assert_nil f.stable + assert_nil f.bottle + assert_nil f.devel + + assert_equal f.head, f.active_spec + assert_equal 'HEAD', f.version + assert !f.head.has_checksum? + assert_equal 'https://github.com/mxcl/homebrew.git', f.url + assert_equal GitDownloadStrategy, f.download_strategy + assert_instance_of GitDownloadStrategy, f.downloader + assert_instance_of HeadSoftwareSpec, f.head + end + + def test_incomplete_stable_specs + f = IncompleteStableSpecTestBall.new + + assert_not_nil f.head + assert_nil f.stable + assert_nil f.bottle + assert_nil f.devel + + assert_equal f.head, f.active_spec + assert_equal 'HEAD', f.version + assert !f.head.has_checksum? + assert_equal 'https://github.com/mxcl/homebrew.git', f.url + assert_equal GitDownloadStrategy, f.download_strategy + assert_instance_of GitDownloadStrategy, f.downloader + assert_instance_of HeadSoftwareSpec, f.head + end + + def test_head_only_with_version_specs + f = IncompleteStableSpecTestBall.new + + assert_not_nil f.head + assert_nil f.stable + assert_nil f.bottle + assert_nil f.devel + + assert_equal f.head, f.active_spec + assert_equal 'HEAD', f.version + assert !f.head.has_checksum? + assert_equal 'https://github.com/mxcl/homebrew.git', f.url + assert_equal GitDownloadStrategy, f.download_strategy + assert_instance_of GitDownloadStrategy, f.downloader + assert_instance_of HeadSoftwareSpec, f.head + end + + def test_explicit_strategy_specs + f = ExplicitStrategySpecTestBall.new + + assert_not_nil f.stable + assert_not_nil f.devel + assert_not_nil f.head + + assert_equal f.stable, f.active_spec + + assert !f.stable.has_checksum? + assert !f.devel.has_checksum? + assert !f.head.has_checksum? + + assert_equal MercurialDownloadStrategy, f.stable.download_strategy + assert_equal BazaarDownloadStrategy, f.devel.download_strategy + assert_equal SubversionDownloadStrategy, f.head.download_strategy + + assert_equal({ :tag => '0.2' }, f.stable.specs) + assert_equal({ :tag => '0.3' }, f.devel.specs) + assert f.head.specs.empty? + end end diff --git a/Library/Homebrew/test/testball.rb b/Library/Homebrew/test/testball.rb index f440a6ed9..b61eef178 100644 --- a/Library/Homebrew/test/testball.rb +++ b/Library/Homebrew/test/testball.rb @@ -94,3 +94,133 @@ class TestBlockWithoutBuildCompilerFailure < TestCompilerFailures cause "failure" end end + +class SpecTestBall < Formula + homepage 'http://example.com' + url 'file:///foo.com/testball-0.1.tbz' + mirror 'file:///foo.org/testball-0.1.tbz' + sha1 '482e737739d946b7c8cbaf127d9ee9c148b999f5' + + head 'https://github.com/mxcl/homebrew.git', :tag => 'foo' + + devel do + url 'file:///foo.com/testball-0.2.tbz' + mirror 'file:///foo.org/testball-0.2.tbz' + sha256 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' + end + + bottle do + sha1 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' => :snowleopard + sha1 'baadf00dbaadf00dbaadf00dbaadf00dbaadf00d' => :lion + end + + def initialize name=nil + super "spectestball" + end +end + +class AncientSpecTestBall < Formula + @homepage='http://example.com' + @url='file:///foo.com/testball-0.1.tbz' + @md5='060844753f2a3b36ecfc3192d307dab2' + @head='https://github.com/mxcl/homebrew.git' + @specs={ :tag => 'foo' } + + def initialize name=nil + super "ancientspectestball" + end +end + +class ExplicitVersionSpecTestBall < Formula + homepage 'http://example.com' + url 'file:///foo.com/testball-stable.tbz' + sha1 '482e737739d946b7c8cbaf127d9ee9c148b999f5' + version '0.3' + + devel do + url 'file:///foo.com/testball-devel.tbz' + sha1 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' + version '0.4' + end + + bottle do + version '1' + url 'file:///foo.com/test-0.3.lion.bottle.tar.gz' + sha1 'baadf00dbaadf00dbaadf00dbaadf00dbaadf00d' + end + + def initialize name=nil + super "explicitversionspectestball" + end +end + +class OldBottleSpecTestBall < Formula + homepage 'http://example.com' + url 'file:///foo.com/testball-0.1.tbz' + sha1 '482e737739d946b7c8cbaf127d9ee9c148b999f5' + + bottle do + url 'file:///foo.com/testball-0.1-bottle.tar.gz' + sha1 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' + end + + def initialize name=nil + super "oldbottlespectestball" + end +end + +class AncientBottleSpecTestBall < Formula + homepage 'http://example.com' + url 'file:///foo.com/testball-0.1.tbz' + sha1 '482e737739d946b7c8cbaf127d9ee9c148b999f5' + + bottle 'file:///foo.com/testball-0.1-bottle.tar.gz' + bottle_sha1 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' + + def initialize name=nil + super "ancientbottlespectestball" + end +end + +class HeadOnlySpecTestBall < Formula + homepage 'http://example.com' + head 'https://github.com/mxcl/homebrew.git' + + def initialize name=nil + super "headyonlyspectestball" + end +end + +class IncompleteStableSpecTestBall < Formula + homepage 'http://example.com' + head 'https://github.com/mxcl/homebrew.git' + sha1 '482e737739d946b7c8cbaf127d9ee9c148b999f5' + + def initialize name=nil + super "incompletestablespectestball" + end +end + +class HeadOnlyWithVersionSpecTestBall < Formula + homepage 'http://example.com' + head 'https://github.com/mxcl/homebrew.git' + version '0.3' + + def initialize name=nil + super "headonlywithversionspectestball" + end +end + +class ExplicitStrategySpecTestBall < Formula + homepage 'http://example.com' + url 'file:///foo.com/testball-stable', :using => :hg, :tag => '0.2' + head 'file:///foo.com/testball-head', :using => :svn + + devel do + url 'file:///foo.com/testball-devel', :using => :bzr, :tag => '0.3' + end + + def initialize name=nil + super "explicitstrategyspectestball" + end +end diff --git a/Library/Homebrew/test/testing_env.rb b/Library/Homebrew/test/testing_env.rb index a283dbf25..68df4e17e 100644 --- a/Library/Homebrew/test/testing_env.rb +++ b/Library/Homebrew/test/testing_env.rb @@ -52,4 +52,9 @@ def shutup end end +unless ARGV.include? "--no-compat" or ENV['HOMEBREW_NO_COMPAT'] + $:.unshift(File.expand_path("#{ABS__FILE__}/../../compat")) + require 'compatibility' +end + require 'test/unit' # must be after at_exit |
