| 
									
										
										
										
											2020-10-10 14:16:11 +02:00
										 |  |  | # typed: false | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 14:01:37 +08:00
										 |  |  | require "cask/cache" | 
					
						
							| 
									
										
										
										
											2018-09-03 19:39:07 +01:00
										 |  |  | require "cask/cask" | 
					
						
							| 
									
										
										
										
											2018-03-07 16:14:55 +00:00
										 |  |  | require "uri" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 08:29:14 +02:00
										 |  |  | module Cask | 
					
						
							| 
									
										
										
										
											2020-08-24 22:50:29 +02:00
										 |  |  |   # Loads a cask from various sources. | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # @api private | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |   module CaskLoader | 
					
						
							| 
									
										
										
										
											2020-08-24 22:50:29 +02:00
										 |  |  |     # Loads a cask from a string. | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |     class FromContentLoader | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |       attr_reader :content | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 15:20:58 +02:00
										 |  |  |       def self.can_load?(ref) | 
					
						
							|  |  |  |         return false unless ref.respond_to?(:to_str) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 15:20:58 +02:00
										 |  |  |         content = ref.to_str | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         token  = /(?:"[^"]*"|'[^']*')/ | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |         curly  = /\(\s*#{token.source}\s*\)\s*\{.*\}/ | 
					
						
							|  |  |  |         do_end = /\s+#{token.source}\s+do(?:\s*;\s*|\s+).*end/ | 
					
						
							| 
									
										
										
										
											2017-10-08 15:20:58 +02:00
										 |  |  |         regex  = /\A\s*cask(?:#{curly.source}|#{do_end.source})\s*\Z/m | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         content.match?(regex) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       def initialize(content) | 
					
						
							| 
									
										
										
										
											2018-02-13 17:23:49 +01:00
										 |  |  |         @content = content.force_encoding("UTF-8") | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |       def load(config:) | 
					
						
							|  |  |  |         @config = config | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 17:23:49 +01:00
										 |  |  |         instance_eval(content, __FILE__, __LINE__) | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-10-08 13:25:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       private | 
					
						
							| 
									
										
										
										
											2016-10-08 13:25:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |       def cask(header_token, **options, &block) | 
					
						
							| 
									
										
										
										
											2021-08-14 16:18:13 -04:00
										 |  |  |         Cask.new(header_token, source: content, **options, config: @config, &block) | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-10-08 13:25:38 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 22:50:29 +02:00
										 |  |  |     # Loads a cask from a path. | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |     class FromPathLoader < FromContentLoader | 
					
						
							|  |  |  |       def self.can_load?(ref) | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |         path = Pathname(ref) | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |         path.extname == ".rb" && path.expand_path.exist? | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       attr_reader :token, :path | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 17:12:32 +01:00
										 |  |  |       def initialize(path) # rubocop:disable Lint/MissingSuper | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |         path = Pathname(path).expand_path | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         @token = path.basename(".rb").to_s | 
					
						
							|  |  |  |         @path = path | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |       def load(config:) | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |         raise CaskUnavailableError.new(token, "'#{path}' does not exist.")  unless path.exist? | 
					
						
							|  |  |  |         raise CaskUnavailableError.new(token, "'#{path}' is not readable.") unless path.readable? | 
					
						
							|  |  |  |         raise CaskUnavailableError.new(token, "'#{path}' is not a file.")   unless path.file? | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |         @content = path.read(encoding: "UTF-8") | 
					
						
							|  |  |  |         @config = config | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-29 11:05:23 +02:00
										 |  |  |         begin | 
					
						
							|  |  |  |           instance_eval(content, path).tap do |cask| | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |             raise CaskUnreadableError.new(token, "'#{path}' does not contain a cask.") unless cask.is_a?(Cask) | 
					
						
							| 
									
										
										
										
											2018-07-29 11:05:23 +02:00
										 |  |  |           end | 
					
						
							|  |  |  |         rescue NameError, ArgumentError, ScriptError => e | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |           error = CaskUnreadableError.new(token, e.message) | 
					
						
							|  |  |  |           error.set_backtrace e.backtrace | 
					
						
							|  |  |  |           raise error | 
					
						
							| 
									
										
										
										
											2018-07-29 11:05:23 +02:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       private | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |       def cask(header_token, **options, &block) | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |         raise CaskTokenMismatchError.new(token, header_token) if token != header_token | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |         super(header_token, **options, sourcefile_path: path, &block) | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-10-08 13:25:38 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 22:50:29 +02:00
										 |  |  |     # Loads a cask from a URI. | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |     class FromURILoader < FromPathLoader | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |       extend T::Sig | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       def self.can_load?(ref) | 
					
						
							| 
									
										
										
										
											2017-10-08 15:20:58 +02:00
										 |  |  |         uri_regex = ::URI::DEFAULT_PARSER.make_regexp | 
					
						
							| 
									
										
										
										
											2020-08-19 17:12:32 +01:00
										 |  |  |         return false unless ref.to_s.match?(Regexp.new("\\A#{uri_regex.source}\\Z", uri_regex.options)) | 
					
						
							| 
									
										
										
										
											2019-11-14 07:38:24 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         uri = URI(ref) | 
					
						
							|  |  |  |         return false unless uri | 
					
						
							|  |  |  |         return false unless uri.path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         true | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 02:00:59 +02:00
										 |  |  |       attr_reader :url | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |       sig { params(url: T.any(URI::Generic, String)).void } | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       def initialize(url) | 
					
						
							| 
									
										
										
										
											2017-06-11 02:00:59 +02:00
										 |  |  |         @url = URI(url) | 
					
						
							| 
									
										
										
										
											2018-06-09 09:42:49 +02:00
										 |  |  |         super Cache.path/File.basename(@url.path) | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |       def load(config:) | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |         path.dirname.mkpath | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         begin | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           ohai "Downloading #{url}" | 
					
						
							| 
									
										
										
										
											2017-08-08 18:10:13 +02:00
										 |  |  |           curl_download url, to: path | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |         rescue ErrorDuringExecution | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |           raise CaskUnavailableError.new(token, "Failed to download #{Formatter.url(url)}.") | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         super | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-10-08 13:25:38 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 22:50:29 +02:00
										 |  |  |     # Loads a cask from a tap path. | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |     class FromTapPathLoader < FromPathLoader | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       def self.can_load?(ref) | 
					
						
							| 
									
										
										
										
											2018-03-29 22:05:02 +02:00
										 |  |  |         super && !Tap.from_path(ref).nil? | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |       attr_reader :tap | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 22:05:02 +02:00
										 |  |  |       def initialize(path) | 
					
						
							|  |  |  |         @tap = Tap.from_path(path) | 
					
						
							|  |  |  |         super(path) | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       private | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def cask(*args, &block) | 
					
						
							|  |  |  |         super(*args, tap: tap, &block) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 22:50:29 +02:00
										 |  |  |     # Loads a cask from a specific tap. | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |     class FromTapLoader < FromTapPathLoader | 
					
						
							|  |  |  |       def self.can_load?(ref) | 
					
						
							|  |  |  |         ref.to_s.match?(HOMEBREW_TAP_CASK_REGEX) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       def initialize(tapped_name) | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |         user, repo, token = tapped_name.split("/", 3) | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |         super Tap.fetch(user, repo).cask_dir/"#{token}.rb" | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-10-08 13:25:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |       def load(config:) | 
					
						
							| 
									
										
										
										
											2021-03-11 21:09:42 +05:30
										 |  |  |         raise TapCaskUnavailableError.new(tap, token) unless tap.installed? | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         super | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 22:50:29 +02:00
										 |  |  |     # Loads a cask from an existing {Cask} instance. | 
					
						
							| 
									
										
										
										
											2017-09-11 08:37:15 +02:00
										 |  |  |     class FromInstanceLoader | 
					
						
							|  |  |  |       def self.can_load?(ref) | 
					
						
							|  |  |  |         ref.is_a?(Cask) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def initialize(cask) | 
					
						
							|  |  |  |         @cask = cask | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |       def load(config:) | 
					
						
							|  |  |  |         @cask | 
					
						
							| 
									
										
										
										
											2017-09-11 08:37:15 +02:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 22:50:29 +02:00
										 |  |  |     # Pseudo-loader which raises an error when trying to load the corresponding cask. | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |     class NullLoader < FromPathLoader | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |       extend T::Sig | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       def self.can_load?(*) | 
					
						
							|  |  |  |         true | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |       sig { params(ref: T.any(String, Pathname)).void } | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       def initialize(ref) | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |         token = File.basename(ref, ".rb") | 
					
						
							|  |  |  |         super CaskLoader.default_path(token) | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |       def load(config:) | 
					
						
							| 
									
										
										
										
											2017-06-28 09:25:14 +02:00
										 |  |  |         raise CaskUnavailableError.new(token, "No Cask with this name exists.") | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def self.path(ref) | 
					
						
							|  |  |  |       self.for(ref).path | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:46:30 +02:00
										 |  |  |     def self.load(ref, config: nil) | 
					
						
							|  |  |  |       self.for(ref).load(config: config) | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def self.for(ref) | 
					
						
							|  |  |  |       [ | 
					
						
							| 
									
										
										
										
											2017-09-11 08:37:15 +02:00
										 |  |  |         FromInstanceLoader, | 
					
						
							| 
									
										
										
										
											2017-10-08 15:20:58 +02:00
										 |  |  |         FromContentLoader, | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |         FromURILoader, | 
					
						
							|  |  |  |         FromTapLoader, | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |         FromTapPathLoader, | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |         FromPathLoader, | 
					
						
							|  |  |  |       ].each do |loader_class| | 
					
						
							|  |  |  |         return loader_class.new(ref) if loader_class.can_load?(ref) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |       return FromTapPathLoader.new(default_path(ref)) if FromTapPathLoader.can_load?(default_path(ref)) | 
					
						
							| 
									
										
										
										
											2016-10-08 13:25:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |       case (possible_tap_casks = tap_paths(ref)).count | 
					
						
							|  |  |  |       when 1
 | 
					
						
							|  |  |  |         return FromTapPathLoader.new(possible_tap_casks.first) | 
					
						
							|  |  |  |       when 2..Float::INFINITY | 
					
						
							|  |  |  |         loaders = possible_tap_casks.map(&FromTapPathLoader.method(:new)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         raise CaskError, <<~EOS | 
					
						
							| 
									
										
										
										
											2017-07-29 16:27:54 +02:00
										 |  |  |           Cask #{ref} exists in multiple taps: | 
					
						
							|  |  |  |           #{loaders.map { |loader| "  #{loader.tap}/#{loader.token}" }.join("\n")} | 
					
						
							|  |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-10-08 13:25:38 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       possible_installed_cask = Cask.new(ref) | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |       return FromPathLoader.new(possible_installed_cask.installed_caskfile) if possible_installed_cask.installed? | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       NullLoader.new(ref) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def self.default_path(token) | 
					
						
							| 
									
										
										
										
											2018-06-09 10:13:28 +02:00
										 |  |  |       Tap.default_cask_tap.cask_dir/"#{token.to_s.downcase}.rb" | 
					
						
							| 
									
										
										
										
											2017-03-12 19:18:41 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def self.tap_paths(token) | 
					
						
							|  |  |  |       Tap.map { |t| t.cask_dir/"#{token.to_s.downcase}.rb" } | 
					
						
							|  |  |  |          .select(&:exist?) | 
					
						
							| 
									
										
										
										
											2016-10-08 13:25:38 +02:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |