2013-09-17 21:25:38 -05:00
|
|
|
require 'download_strategy'
|
|
|
|
require 'checksum'
|
|
|
|
require 'version'
|
|
|
|
|
2013-09-17 21:25:38 -05:00
|
|
|
# Resource is the fundamental representation of an external resource. The
|
|
|
|
# primary formula download, along with other declared resources, are instances
|
|
|
|
# of this class.
|
2013-08-06 19:52:58 -07:00
|
|
|
class Resource
|
|
|
|
include FileUtils
|
|
|
|
|
2013-09-17 21:25:38 -05:00
|
|
|
attr_reader :checksum, :mirrors, :specs, :using
|
2014-07-15 13:42:03 -05:00
|
|
|
attr_writer :url, :checksum, :version
|
|
|
|
attr_accessor :download_strategy
|
2013-09-17 21:25:38 -05:00
|
|
|
|
2013-09-17 21:25:38 -05:00
|
|
|
# Formula name must be set after the DSL, as we have no access to the
|
|
|
|
# formula name before initialization of the formula
|
2014-03-13 19:51:23 -05:00
|
|
|
attr_accessor :name, :owner
|
2013-09-17 21:25:38 -05:00
|
|
|
|
2014-12-05 22:11:23 -05:00
|
|
|
class Download
|
|
|
|
def initialize(resource)
|
|
|
|
@resource = resource
|
|
|
|
end
|
|
|
|
|
|
|
|
def url
|
|
|
|
@resource.url
|
|
|
|
end
|
|
|
|
|
|
|
|
def specs
|
|
|
|
@resource.specs
|
|
|
|
end
|
|
|
|
|
|
|
|
def version
|
|
|
|
@resource.version
|
|
|
|
end
|
|
|
|
|
|
|
|
def mirrors
|
|
|
|
@resource.mirrors
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-09-23 21:39:19 -05:00
|
|
|
def initialize name=nil, &block
|
2013-08-06 19:52:58 -07:00
|
|
|
@name = name
|
2013-09-23 21:39:19 -05:00
|
|
|
@url = nil
|
|
|
|
@version = nil
|
2013-09-17 21:25:38 -05:00
|
|
|
@mirrors = []
|
|
|
|
@specs = {}
|
|
|
|
@checksum = nil
|
|
|
|
@using = nil
|
2013-09-17 21:25:39 -05:00
|
|
|
instance_eval(&block) if block_given?
|
2013-08-06 19:52:58 -07:00
|
|
|
end
|
|
|
|
|
2013-09-17 21:25:38 -05:00
|
|
|
def downloader
|
2015-01-06 00:25:04 -05:00
|
|
|
download_strategy.new(download_name, Download.new(self))
|
2013-08-06 19:52:58 -07:00
|
|
|
end
|
|
|
|
|
2014-06-02 21:53:53 -07:00
|
|
|
# Removes /s from resource names; this allows go package names
|
|
|
|
# to be used as resource names without confusing software that
|
|
|
|
# interacts with download_name, e.g. github.com/foo/bar
|
|
|
|
def escaped_name
|
|
|
|
name.gsub("/", '-')
|
|
|
|
end
|
|
|
|
|
2013-09-17 21:25:40 -05:00
|
|
|
def download_name
|
2014-06-02 21:53:53 -07:00
|
|
|
name.nil? ? owner.name : "#{owner.name}--#{escaped_name}"
|
2013-09-17 21:25:40 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def cached_download
|
|
|
|
downloader.cached_location
|
|
|
|
end
|
|
|
|
|
2013-10-31 14:28:49 -05:00
|
|
|
def clear_cache
|
|
|
|
downloader.clear_cache
|
|
|
|
end
|
|
|
|
|
2013-10-30 00:43:10 -05:00
|
|
|
def stage(target=nil, &block)
|
2014-12-13 22:51:21 -05:00
|
|
|
unless target || block
|
|
|
|
raise ArgumentError, "target directory or block is required"
|
|
|
|
end
|
|
|
|
|
2013-10-30 00:43:10 -05:00
|
|
|
verify_download_integrity(fetch)
|
|
|
|
unpack(target, &block)
|
|
|
|
end
|
|
|
|
|
2013-08-06 19:52:58 -07:00
|
|
|
# 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
|
2013-10-30 00:43:10 -05:00
|
|
|
def unpack(target=nil)
|
2014-12-14 17:59:35 -05:00
|
|
|
mktemp(download_name) do
|
|
|
|
downloader.stage
|
|
|
|
if block_given?
|
2013-08-06 19:52:58 -07:00
|
|
|
yield self
|
2014-12-14 17:59:35 -05:00
|
|
|
elsif target
|
|
|
|
target = Pathname.new(target) unless target.is_a? Pathname
|
|
|
|
target.install Dir['*']
|
2013-08-06 19:52:58 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-09-17 21:25:43 -05:00
|
|
|
Partial = Struct.new(:resource, :files)
|
|
|
|
|
|
|
|
def files(*files)
|
|
|
|
Partial.new(self, files)
|
|
|
|
end
|
|
|
|
|
2013-08-06 19:52:58 -07:00
|
|
|
def fetch
|
2014-02-18 15:08:03 -05:00
|
|
|
HOMEBREW_CACHE.mkpath
|
2014-10-10 20:30:29 -05:00
|
|
|
|
|
|
|
begin
|
|
|
|
downloader.fetch
|
|
|
|
rescue ErrorDuringExecution, CurlDownloadStrategyError => e
|
|
|
|
raise DownloadError.new(self, e)
|
|
|
|
end
|
|
|
|
|
2014-02-18 15:08:03 -05:00
|
|
|
cached_download
|
2013-08-06 19:52:58 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def verify_download_integrity fn
|
2014-12-05 18:08:21 -05:00
|
|
|
if fn.file?
|
2013-12-08 21:37:22 +00:00
|
|
|
ohai "Verifying #{fn.basename} checksum" if ARGV.verbose?
|
2013-10-30 00:43:10 -05:00
|
|
|
fn.verify_checksum(checksum)
|
|
|
|
end
|
2013-09-17 21:25:38 -05:00
|
|
|
rescue ChecksumMissingError
|
2013-09-17 21:25:41 -05:00
|
|
|
opoo "Cannot verify integrity of #{fn.basename}"
|
2013-09-17 21:25:38 -05:00
|
|
|
puts "A checksum was not provided for this resource"
|
2013-09-17 21:25:38 -05:00
|
|
|
puts "For your reference the SHA1 is: #{fn.sha1}"
|
|
|
|
end
|
|
|
|
|
2014-05-27 21:02:00 -05:00
|
|
|
Checksum::TYPES.each do |type|
|
|
|
|
define_method(type) { |val| @checksum = Checksum.new(type, val) }
|
2013-09-17 21:25:38 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def url val=nil, specs={}
|
|
|
|
return @url if val.nil?
|
|
|
|
@url = val
|
|
|
|
@specs.merge!(specs)
|
2013-10-11 20:21:41 -05:00
|
|
|
@using = @specs.delete(:using)
|
2014-07-15 13:42:03 -05:00
|
|
|
@download_strategy = DownloadStrategyDetector.detect(url, using)
|
2013-09-17 21:25:38 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def version val=nil
|
|
|
|
@version ||= detect_version(val)
|
|
|
|
end
|
|
|
|
|
|
|
|
def mirror val
|
|
|
|
mirrors << val
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def detect_version(val)
|
2014-12-31 10:37:29 -05:00
|
|
|
return if val.nil? && url.nil?
|
|
|
|
|
2013-09-17 21:25:38 -05:00
|
|
|
case val
|
2014-05-27 21:41:43 -05:00
|
|
|
when nil then Version.detect(url, specs)
|
|
|
|
when String then Version.new(val)
|
|
|
|
when Version then val
|
2013-09-17 21:25:38 -05:00
|
|
|
else
|
|
|
|
raise TypeError, "version '#{val.inspect}' should be a string"
|
|
|
|
end
|
2013-08-06 19:52:58 -07:00
|
|
|
end
|
2014-06-02 23:32:42 -07:00
|
|
|
|
|
|
|
class Go < Resource
|
|
|
|
def stage target
|
|
|
|
super(target/name)
|
|
|
|
end
|
|
|
|
end
|
2013-08-06 19:52:58 -07:00
|
|
|
end
|