brew/Library/Homebrew/resource.rb

184 lines
3.9 KiB
Ruby
Raw Normal View History

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.
class Resource
include FileUtils
attr_reader :mirrors, :specs, :using, :source_modified_time
2015-01-12 00:37:24 -05:00
attr_writer :version
attr_accessor :download_strategy, :checksum
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
attr_accessor :name, :owner
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
def initialize(name = nil, &block)
@name = name
@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?
end
def downloader
download_strategy.new(download_name, Download.new(self))
end
# 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.tr("/", "-")
end
2013-09-17 21:25:40 -05:00
def download_name
name.nil? ? owner.name : "#{owner.name}--#{escaped_name}"
2013-09-17 21:25:40 -05:00
end
def cached_download
downloader.cached_location
end
def clear_cache
downloader.clear_cache
end
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
verify_download_integrity(fetch)
unpack(target, &block)
end
# 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 unpack(target = nil)
mktemp(download_name) do
downloader.stage
@source_modified_time = downloader.source_modified_time
if block_given?
yield self
elsif target
target = Pathname.new(target) unless target.is_a? Pathname
target.install Dir["*"]
end
end
end
Partial = Struct.new(:resource, :files)
def files(*files)
Partial.new(self, files)
end
def fetch
HOMEBREW_CACHE.mkpath
2014-10-10 20:30:29 -05:00
begin
downloader.fetch
rescue ErrorDuringExecution, CurlDownloadStrategyError => e
raise DownloadError.new(self, e)
end
cached_download
end
def verify_download_integrity(fn)
if fn.file?
ohai "Verifying #{fn.basename} checksum" if ARGV.verbose?
fn.verify_checksum(checksum)
end
2013-09-17 21:25:38 -05:00
rescue ChecksumMissingError
opoo "Cannot verify integrity of #{fn.basename}"
puts "A checksum was not provided for this resource"
puts "For your reference the SHA256 is: #{fn.sha256}"
2013-09-17 21:25:38 -05:00
end
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 = {})
2013-09-17 21:25:38 -05:00
return @url if val.nil?
@url = val
@specs.merge!(specs)
@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)
2013-09-17 21:25:38 -05:00
@version ||= detect_version(val)
end
def mirror(val)
2013-09-17 21:25:38 -05:00
mirrors << val
end
private
def detect_version(val)
return if val.nil? && url.nil?
2013-09-17 21:25:38 -05:00
case val
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
end
class Go < Resource
def stage(target)
super(target/name)
end
end
class Patch < Resource
attr_reader :patch_files
def initialize(&block)
@patch_files = []
super "patch", &block
end
def apply(*paths)
paths.flatten!
@patch_files.concat(paths)
@patch_files.uniq!
end
end
end