diff --git a/Library/Homebrew/cask/lib/hbc/cask_loader.rb b/Library/Homebrew/cask/lib/hbc/cask_loader.rb new file mode 100644 index 0000000000..3875b30df2 --- /dev/null +++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb @@ -0,0 +1,54 @@ +module Hbc + class CaskLoader + def self.load_from_file(path) + raise CaskError, "File '#{path}' does not exist" unless path.exist? + raise CaskError, "File '#{path}' is not readable" unless path.readable? + raise CaskError, "File '#{path}' is not a plain file" unless path.file? + + token = path.basename(".rb").to_s + content = IO.read(path).force_encoding("UTF-8") + + new(token, content, path).load + end + + def self.load_from_string(token, content) + new(token, content).load + end + + def load + instance_eval(@content, __FILE__, __LINE__) + rescue CaskError, StandardError, ScriptError => e + e.message.concat(" while loading '#{@token}'") + e.message.concat(" from '#{@path}'") unless @path.nil? + raise e, e.message + end + + private + + def initialize(token, content, path = nil) + @token = token + @content = content + @path = path unless path.nil? + end + + def cask(header_token, &block) + @klass = Cask + build_cask(header_token, &block) + end + + def test_cask(header_token, &block) + @klass = TestCask + build_cask(header_token, &block) + end + + def build_cask(header_token, &block) + raise CaskTokenDoesNotMatchError.new(@token, header_token) unless @token == header_token + + if @path.nil? + @klass.new(@token, &block) + else + @klass.new(@token, sourcefile_path: @path, &block) + end + end + end +end diff --git a/Library/Homebrew/cask/lib/hbc/locations.rb b/Library/Homebrew/cask/lib/hbc/locations.rb index 32c95413cd..c763b974b4 100644 --- a/Library/Homebrew/cask/lib/hbc/locations.rb +++ b/Library/Homebrew/cask/lib/hbc/locations.rb @@ -131,21 +131,32 @@ module Hbc end def path(query) - query = query.sub(%r{\.rb$}i, "") - token_with_tap = if query.include?("/") - query + query_path = Pathname.new(query) + + if query_path.exist? || query_path.absolute? + return query_path + end + + query_without_extension = query.sub(%r{\.rb$}i, "") + + token_with_tap = if query =~ %r{\A[^/]+/[^/]+/[^/]+\Z} + query_without_extension else - all_tokens.detect do |tap_and_token| - tap_and_token.split("/")[2] == query - end + all_tokens.detect { |tap_and_token| + tap_and_token.split("/")[2] == query_without_extension + } end if token_with_tap user, repo, token = token_with_tap.split("/") - Tap.fetch(user, repo).cask_dir.join("#{token}.rb") + tap = Tap.fetch(user, repo) else - default_tap.cask_dir.join("#{query}.rb") + token = query_without_extension + tap = Hbc.default_tap end + + return query_path if tap.cask_dir.nil? + tap.cask_dir.join("#{token}.rb") end def tcc_db diff --git a/Library/Homebrew/cask/lib/hbc/qualified_token.rb b/Library/Homebrew/cask/lib/hbc/qualified_token.rb index b9329eeb73..adf22b533e 100644 --- a/Library/Homebrew/cask/lib/hbc/qualified_token.rb +++ b/Library/Homebrew/cask/lib/hbc/qualified_token.rb @@ -13,7 +13,7 @@ module Hbc TAP_REGEX = %r{#{USER_REGEX}[/\-]#{REPO_REGEX}} - QUALIFIED_TOKEN_REGEX ||= %r{#{TAP_REGEX}/#{TOKEN_REGEX}} + QUALIFIED_TOKEN_REGEX = %r{#{TAP_REGEX}/#{TOKEN_REGEX}} def self.parse(arg) return nil unless arg.is_a?(String) && arg.downcase =~ %r{^#{QUALIFIED_TOKEN_REGEX}$} diff --git a/Library/Homebrew/cask/lib/hbc/source/path_base.rb b/Library/Homebrew/cask/lib/hbc/source/path_base.rb index 5725380ec5..7d68e518b4 100644 --- a/Library/Homebrew/cask/lib/hbc/source/path_base.rb +++ b/Library/Homebrew/cask/lib/hbc/source/path_base.rb @@ -1,4 +1,5 @@ require "rubygems" +require "hbc/cask_loader" module Hbc module Source @@ -6,67 +7,22 @@ module Hbc # derived classes must define method self.me? def self.path_for_query(query) - query_string = query.to_s - Pathname.new(query_string.end_with?(".rb") ? query_string : query_string + ".rb") + Pathname.new(query).sub(%r{(\.rb)?$}, ".rb") end attr_reader :path def initialize(path) - @path = Pathname(path).expand_path + @path = Pathname.new(path).expand_path end def load - raise CaskError, "File '#{path}' does not exist" unless path.exist? - raise CaskError, "File '#{path}' is not readable" unless path.readable? - raise CaskError, "File '#{path}' is not a plain file" unless path.file? - load_cask + CaskLoader.load_from_file(@path) end def to_s # stringify to fully-resolved location - path.to_s - end - - private - - def load_cask - instance_eval(cask_contents, __FILE__, __LINE__) - rescue CaskError, StandardError, ScriptError => e - # bug: e.message.concat doesn't work with CaskError exceptions - raise e, e.message.concat(" while loading '#{path}'") - end - - def cask_contents - File.open(path, "rb") do |handle| - contents = handle.read - if defined?(Encoding) - contents.force_encoding("UTF-8") - else - contents - end - end - end - - def cask(header_token, &block) - build_cask(Cask, header_token, &block) - end - - def test_cask(header_token, &block) - build_cask(TestCask, header_token, &block) - end - - def build_cask(cask_class, header_token, &block) - if header_token.is_a?(Hash) - # Cask file is using old `cask :v1 => 'token'` syntax - header_token = header_token.values.first - end - raise CaskTokenDoesNotMatchError.new(cask_token, header_token) unless cask_token == header_token - cask_class.new(cask_token, sourcefile_path: path, &block) - end - - def cask_token - path.basename.to_s.sub(%r{\.rb}, "") + @path.to_s end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/tapped.rb b/Library/Homebrew/cask/lib/hbc/source/tapped.rb index 6716e3a351..c1f5f95bca 100644 --- a/Library/Homebrew/cask/lib/hbc/source/tapped.rb +++ b/Library/Homebrew/cask/lib/hbc/source/tapped.rb @@ -2,21 +2,7 @@ module Hbc module Source class Tapped def self.me?(query) - path_for_query(query).exist? - end - - def self.path_for_query(query) - # Repeating Hbc.all_tokens is very slow for operations such as - # brew cask list, but memoizing the value might cause breakage - # elsewhere, given that installation and tap status is permitted - # to change during the course of an invocation. - token_with_tap = Hbc.all_tokens.find { |t| t.split("/").last == query.sub(%r{\.rb$}i, "") } - if token_with_tap - user, repo, token = token_with_tap.split("/") - Tap.fetch(user, repo).cask_dir.join("#{token}.rb") - else - Hbc.default_tap.cask_dir.join(query.sub(%r{(\.rb)?$}i, ".rb")) - end + Hbc.path(query).exist? end attr_reader :token @@ -26,13 +12,12 @@ module Hbc end def load - path = self.class.path_for_query(token) - PathSlashOptional.new(path).load + PathSlashOptional.new(Hbc.path(token)).load end def to_s # stringify to fully-resolved location - self.class.path_for_query(token).expand_path.to_s + Hbc.path(token).expand_path.to_s end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb b/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb index 52191f279a..2db6ddbca5 100644 --- a/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb +++ b/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb @@ -6,7 +6,7 @@ module Hbc def self.me?(query) return if (tap = tap_for_query(query)).nil? - tap.installed? && path_for_query(query).exist? + tap.installed? && Hbc.path(query).exist? end def self.tap_for_query(query) @@ -16,11 +16,6 @@ module Hbc user, repo = qualified_token[0..1] Tap.fetch(user, repo) end - - def self.path_for_query(query) - user, repo, token = QualifiedToken.parse(query) - Tap.fetch(user, repo).cask_dir.join(token.sub(%r{(\.rb)?$}i, ".rb")) - end end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb b/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb index 6041605d8c..698cc46ce6 100644 --- a/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb +++ b/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb @@ -7,7 +7,7 @@ module Hbc return if (tap = tap_for_query(query)).nil? tap.install - tap.installed? && path_for_query(query).exist? + tap.installed? && Hbc.path(query).exist? end end end diff --git a/Library/Homebrew/compat.rb b/Library/Homebrew/compat.rb index 69b45683a0..db0ece584a 100644 --- a/Library/Homebrew/compat.rb +++ b/Library/Homebrew/compat.rb @@ -1,5 +1,6 @@ require "compat/fails_with_llvm" require "compat/tap" +require "compat/hbc" require "compat/formula" require "compat/formula_specialties" require "compat/global" diff --git a/Library/Homebrew/compat/hbc.rb b/Library/Homebrew/compat/hbc.rb new file mode 100644 index 0000000000..a1d1414a59 --- /dev/null +++ b/Library/Homebrew/compat/hbc.rb @@ -0,0 +1 @@ +require "compat/hbc/cask_loader" diff --git a/Library/Homebrew/compat/hbc/cask_loader.rb b/Library/Homebrew/compat/hbc/cask_loader.rb new file mode 100644 index 0000000000..e7f3a4aac2 --- /dev/null +++ b/Library/Homebrew/compat/hbc/cask_loader.rb @@ -0,0 +1,18 @@ +module CaskLoaderCompatibilityLayer + private + + def build_cask(header_token, &block) + if header_token.is_a?(Hash) && header_token.key?(:v1) + odeprecated %q("cask :v1 => 'token'"), %q("cask 'token'") + header_token = header_token[:v1] + end + + super(header_token, &block) + end +end + +module Hbc + class CaskLoader + prepend CaskLoaderCompatibilityLayer + end +end