homebrew-cask-versions/lib/hbc/source/path_base.rb
Paul Hinze 63d748e14c core: [refactor] separate Hbc::Cask from Hbc
Hbc is the namespace, Hbc::Cask is the object representing a Cask

One step on the path to reducing the surface area of the God-object
we've grown over the years. :)
2015-02-07 16:37:32 -06:00

102 lines
3.3 KiB
Ruby

require 'rubygems'
class Hbc::Source::PathBase
# derived classes must define method self.me?
def self.path_for_query(query)
path_string = "#{query}"
path_string.concat('.rb') unless path_string.match(%r{\.rb\Z}i)
Pathname.new(path_string)
end
attr_reader :path
def initialize(path)
@path = Pathname(path).expand_path
end
def load
raise Hbc::CaskError.new "File '#{path}' does not exist" unless path.exist?
raise Hbc::CaskError.new "File '#{path}' is not readable" unless path.readable?
raise Hbc::CaskError.new "File '#{path}' is not a plain file" unless path.file?
begin
# transitional hack: convert first lines of the new form
#
# cask :v1 => 'google-chrome' do
#
# to the old form
#
# class GoogleChrome < Hbc (class GoogleChrome < Cask)
#
# limitation: does not support Ruby extended quoting such as %Q{}
#
# todo: in the future, this can be pared down to an "eval"
# read Cask
cask_contents = File.open(path, 'rb') do |handle|
contents = handle.read
if defined?(Encoding)
contents.force_encoding('UTF-8')
else
contents
end
end
# munge text
cask_contents.sub!(%r{\A(\s*\#[^\n]*\n)+}, '');
if %r{\A\s*cask\s+:v([\d_]+)(test)?\s+=>\s+([\'\"])(\S+?)\3(?:\s*,\s*|\s+)do\s*\n}.match(cask_contents)
dsl_version_string = $1
is_test = ! $2.nil?
header_token = $4
dsl_version = Gem::Version.new(dsl_version_string.gsub('_','.'))
superclass_name = is_test ? 'Hbc::TestCask' : 'Hbc::Cask'
cask_contents.sub!(%r{\A[^\n]+\n}, "class #{cask_class_name} < #{superclass_name}\n")
# todo the minimum DSL version should be defined globally elsewhere
minimum_dsl_version = Gem::Version.new('1.0')
unless dsl_version >= minimum_dsl_version
raise Hbc::CaskInvalidError.new(cask_token, "Bad header line: 'v#{dsl_version_string}' is less than required minimum version '#{minimum_dsl_version}'")
end
if header_token != cask_token
raise Hbc::CaskInvalidError.new(cask_token, "Bad header line: '#{header_token}' does not match file name")
end
else
raise Hbc::CaskInvalidError.new(cask_token, "Bad header line: parse failed")
end
# simulate "require"
begin
Object.const_get(cask_class_name)
rescue NameError
eval(cask_contents, TOPLEVEL_BINDING)
end
rescue Hbc::CaskError, StandardError, ScriptError => e
# bug: e.message.concat doesn't work with Hbc::CaskError exceptions
e.message.concat(" while loading '#{path}'")
raise e
end
begin
Object.const_get(cask_class_name).new(path)
rescue Hbc::CaskError, StandardError, ScriptError => e
# bug: e.message.concat doesn't work with Hbc::CaskError exceptions
e.message.concat(" while instantiating '#{cask_class_name}' from '#{path}'")
raise e
end
end
def cask_token
path.basename.to_s.sub(/\.rb/, '')
end
def cask_class_name
# todo removeme: prepending KlassPrefix is transitional as we move away from representing Casks as classes
'KlassPrefix'.concat cask_token.split('-').map(&:capitalize).join
end
def to_s
# stringify to fully-resolved location
path.to_s
end
end