Implement Resources

Closes Homebrew/homebrew#20212.
This commit is contained in:
Adam Vandenberg 2013-08-06 19:52:58 -07:00
parent cf751fd013
commit d4cf3ef212
4 changed files with 109 additions and 0 deletions

View File

@ -260,3 +260,24 @@ class ChecksumMismatchError < RuntimeError
super + advice.to_s super + advice.to_s
end end
end end
class ResourceMissingError < ArgumentError
def initialize formula, resource
@formula = formula
@resource = resource
end
def to_s
"Formula #{@formula} does not define resource \"#{@resource}\"."
end
end
class DuplicateResourceError < ArgumentError
def initialize resource
@resource = resource
end
def to_s
"Resource \"#{@resource}\" defined more than once."
end
end

View File

@ -10,6 +10,8 @@ class Pathname
def install *sources def install *sources
sources.each do |src| sources.each do |src|
case src case src
when Resource
src.stage(self)
when Array when Array
if src.empty? if src.empty?
opoo "tried to install empty array to #{self}" opoo "tried to install empty array to #{self}"

View File

@ -1,3 +1,4 @@
require 'resource'
require 'download_strategy' require 'download_strategy'
require 'dependency_collector' require 'dependency_collector'
require 'formula_support' require 'formula_support'
@ -56,6 +57,11 @@ class Formula
end end
@pin = FormulaPin.new(self) @pin = FormulaPin.new(self)
@resources = self.class.resources
@resources.each_value do |r|
r.set_owner name
end
end end
def set_spec(name) def set_spec(name)
@ -91,6 +97,16 @@ class Formula
def version; active_spec.version; end def version; active_spec.version; end
def mirrors; active_spec.mirrors; end def mirrors; active_spec.mirrors; end
def resource(name)
res = @resources[name]
raise ResourceMissingError.new(@name, name) if res.nil?
res
end
def resources
@resources.values
end
# if the dir is there, but it's empty we consider it not installed # if the dir is there, but it's empty we consider it not installed
def installed? def installed?
(dir = installed_prefix).directory? && dir.children.length > 0 (dir = installed_prefix).directory? && dir.children.length > 0
@ -694,6 +710,19 @@ class Formula
@stable.mirror(val) @stable.mirror(val)
end end
# Hold any resources defined by this formula
def resources
@resources ||= Hash.new
end
# Define a named resource using a SoftwareSpec style block
def resource res_name, &block
raise DuplicateResourceError.new(res_name) if resources.has_key?(res_name)
spec = SoftwareSpec.new
spec.instance_eval(&block)
resources[res_name] = Resource.new(res_name, spec)
end
def dependencies def dependencies
@dependencies ||= DependencyCollector.new @dependencies ||= DependencyCollector.new
end end

View File

@ -0,0 +1,57 @@
# A Resource describes a tarball that a formula needs in addition
# to the formula's own download.
class Resource
include FileUtils
# The mktmp mixin expects a name property
# This is the resource name
attr_reader :name
# This is the associated formula name
attr_reader :owner_name
def initialize name, spec
@name = name
@spec = spec
end
# Formula name must be set after the DSL, as we have no access to the
# formula name before initialization of the formula
def set_owner owner
@owner = owner
@downloader = @spec.download_strategy.new("#{owner}--#{name}", @spec)
end
# Download the resource
# If a target is given, unpack there; else unpack to a temp folder
# If block is given, yield to that block
# A target or a block must be given, but not both
def stage(target=nil)
fetched = fetch
verify_download_integrity(fetched) if fetched.file?
mktemp do
@downloader.stage
if block_given?
yield self
else
target.install Dir['*']
end
end
end
def cached_download
@downloader.cached_location
end
# For brew-fetch and others.
def fetch
# Ensure the cache exists
HOMEBREW_CACHE.mkpath
@downloader.fetch
cached_download
end
def verify_download_integrity fn
@spec.verify_download_integrity(fn)
end
end