homebrew-cask-versions/lib/cask/source/path_base.rb
Roland Walker bf99c6b0a3 Store metadata with installed Casks.
Step 2: Snapshot the Cask file used at install-time, using
the previously-merged metadata directory support.

Using a simple filesystem-is-a-database approach, we set up a
`.metadata` directory for each installed Cask in which we can
record any information, starting with a copy of the Cask
definition which was used at install-time.

This should be useful for various cases such as:
- a fallback when the Cask was renamed/removed.  We
  currently cannot recover any uninstall info in that
  scenario
- installation of multiple versions of the same software

There might be a smarter way to discover the source filename
for the Cask through introspection or some deep Ruby voodoo.
All I could come up with was to pass the filename in on the
constructor, which seems perfectly reasonable if voodoo is
not available.  The existing code was taking the title as an
argument to the constructor, which is dispensable.

This PR contains no code to actually make use of the metadata,
but only takes care of the relevant book-keeping: creation,
destruction, as well as organization of metadata according to
software version number and timestamp.
2014-12-10 18:24:43 -05:00

102 lines
3.2 KiB
Ruby

require 'rubygems'
class Cask::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 CaskError.new "File '#{path}' does not exist" unless path.exist?
raise CaskError.new "File '#{path}' is not readable" unless path.readable?
raise 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 < 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 ? 'TestCask' : '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 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 CaskInvalidError.new(cask_token, "Bad header line: '#{header_token}' does not match file name")
end
else
raise 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 CaskError, StandardError, ScriptError => e
# bug: e.message.concat doesn't work with CaskError exceptions
e.message.concat(" while loading '#{path}'")
raise e
end
begin
Object.const_get(cask_class_name).new(path)
rescue CaskError, StandardError, ScriptError => e
# bug: e.message.concat doesn't work with 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