| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | require "download_strategy" | 
					
						
							|  |  |  | require "checksum" | 
					
						
							|  |  |  | require "version" | 
					
						
							| 
									
										
										
										
											2016-04-22 16:54:09 -04:00
										 |  |  | require "forwardable" | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-14 19:00:06 +08:00
										 |  |  |   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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01: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 | 
					
						
							| 
									
										
										
										
											2015-08-06 15:45:52 +08:00
										 |  |  |     name.tr("/", "-") | 
					
						
							| 
									
										
										
										
											2014-06-02 21:53:53 -07:00
										 |  |  |   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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-10 22:53:56 -04:00
										 |  |  |   # Verifies download and unpacks it | 
					
						
							|  |  |  |   # The block may call `|resource,staging| staging.retain!` to retain the staging | 
					
						
							|  |  |  |   # directory. Subclasses that override stage should implement the tmp | 
					
						
							|  |  |  |   # dir using FileUtils.mktemp so that works with all subtypes. | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01: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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-10 22:53:56 -04:00
										 |  |  |   # If a target is given, unpack there; else unpack to a temp folder. | 
					
						
							| 
									
										
										
										
											2016-04-22 16:54:09 -04:00
										 |  |  |   # If block is given, yield to that block with |stage|, where stage | 
					
						
							|  |  |  |   # is a ResourceStagingContext. | 
					
						
							| 
									
										
										
										
											2016-04-10 22:53:56 -04:00
										 |  |  |   # A target or a block must be given, but not both. | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def unpack(target = nil) | 
					
						
							| 
									
										
										
										
											2016-04-10 22:53:56 -04:00
										 |  |  |     mktemp(download_name) do |staging| | 
					
						
							| 
									
										
										
										
											2014-12-14 17:59:35 -05:00
										 |  |  |       downloader.stage | 
					
						
							| 
									
										
										
										
											2016-01-14 19:00:06 +08:00
										 |  |  |       @source_modified_time = downloader.source_modified_time | 
					
						
							| 
									
										
										
										
											2014-12-14 17:59:35 -05:00
										 |  |  |       if block_given? | 
					
						
							| 
									
										
										
										
											2016-04-22 16:54:09 -04:00
										 |  |  |         yield ResourceStageContext.new(self, staging) | 
					
						
							| 
									
										
										
										
											2014-12-14 17:59:35 -05:00
										 |  |  |       elsif target | 
					
						
							|  |  |  |         target = Pathname.new(target) unless target.is_a? Pathname | 
					
						
							| 
									
										
										
										
											2016-06-07 10:57:25 -07:00
										 |  |  |         target.install Pathname.pwd.children | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   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" | 
					
						
							| 
									
										
										
										
											2015-02-24 23:25:57 +00:00
										 |  |  |     puts "For your reference the SHA256 is: #{fn.sha256}" | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |   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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def url(val = nil, specs = {}) | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |     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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def version(val = nil) | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |     @version ||= detect_version(val) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def mirror(val) | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     def stage(target) | 
					
						
							| 
									
										
										
										
											2014-06-02 23:32:42 -07:00
										 |  |  |       super(target/name) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-01-25 08:21:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   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 | 
					
						
							| 
									
										
										
										
											2013-08-06 19:52:58 -07:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2016-04-22 16:54:09 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | # The context in which a Resource.stage() occurs. Supports access to both | 
					
						
							|  |  |  | # the Resource and associated Mktemp in a single block argument. The interface | 
					
						
							|  |  |  | # is back-compatible with Resource itself as used in that context. | 
					
						
							|  |  |  | class ResourceStageContext | 
					
						
							|  |  |  |   extend Forwardable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # The Resource that is being staged | 
					
						
							|  |  |  |   attr_reader :resource | 
					
						
							|  |  |  |   # The Mktemp in which @resource is staged | 
					
						
							|  |  |  |   attr_reader :staging | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def_delegators :@resource, :version, :url, :mirrors, :specs, :using, :source_modified_time | 
					
						
							|  |  |  |   def_delegators :@staging, :retain! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def initialize(resource, staging) | 
					
						
							|  |  |  |     @resource = resource | 
					
						
							|  |  |  |     @staging = staging | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def to_s | 
					
						
							|  |  |  |     "<#{self.class}: resource=#{resource} staging=#{staging}>" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |