lib/genspec/matchers/base.rb
module GenSpec
module Matchers
class Base
attr_reader :block, :generator, :args, :init_blocks
attr_reader :destination_root
attr_accessor :error
def source_root
generator.source_root
end
def initialize(&block)
@block = block if block_given?
@matched = false
end
def match!
@matched = true
end
def matches?(generator)
@described = generator[:described]
base = nil
base, @described = @described.split(/:/) if @described =~ /:/
@args = generator[:args]
@generator_options = generator[:generator_options]
@shell = GenSpec::Shell.new(generator[:output] || "", generator[:input] || "")
@init_blocks = generator[:init_blocks]
if @described.kind_of?(Class)
@generator = @described
else
if GenSpec.rails?
@generator = Rails::Generators.find_by_namespace(@described.to_s, base)
else
@generator = Thor::Util.find_by_namespace(@described.to_s)
end
end
raise "Could not find generator: #{@described.inspect}" unless @generator
inject_error_handlers!
invoking
invoke
matched?
ensure
complete
end
def matched?
@matched
end
def failure_message
"was supposed to match and didn't"
end
def negative_failure_message
"was supposed to not match and did"
end
protected
# callback fired after matching process is complete, regardless of success, failure
# or error
def complete
end
# callback which fires just before a generator has been invoked.
# Allows matchers to inject whatever hooks they need into the generator.
def invoking
end
# callback which fires just after a generator has run and after error checking has
# been performed, if applicable.
def generated
end
def spec_file_contents(filename)
if @block
content = File.read(filename)
@block.call(content)
end
end
def shell
@shell
end
# Causes errors not to be raised if a generator fails. Useful for testing output,
# rather than results.
def silence_errors!
@errors_silenced = true
end
private
def check_for_errors
# generation is complete - check for errors and re-raise it if it's there
raise error if error && !@errors_silenced
end
def mktmpdir(&block)
tmpdir_args = [ @described.to_s ]
if GenSpec.root
FileUtils.mkdir_p GenSpec.root
tmpdir_args << GenSpec.root
end
Dir.mktmpdir *tmpdir_args, &block
end
def invoke
mktmpdir do |tempdir|
FileUtils.chdir tempdir do
init_blocks.each do |block|
block.call(tempdir)
end
@destination_root = tempdir
defaults = { :shell => @shell, :destination_root => destination_root }
with_captured_io do
@generator.start @args || [], defaults.merge(@generator_options)
end
check_for_errors
generated
end
end
end
def with_captured_io
stdout, stderr, stdin = $stdout, $stderr, $stdin
begin
$stdout, $stderr, $stdin = @shell.output, @shell.output, @shell.input
yield
ensure
$stdout, $stderr, $stdin = stdout, stderr, stdin
end
end
def inject_error_handlers!
interceptor = self
@generator.class_eval do
no_tasks do
def invoke_with_genspec_error_handler(*names, &block)
invoke_without_genspec_error_handler(*names, &block)
rescue Thor::Error => err
# self.class.interceptor.error = err
interceptor.error = err
raise err
end
alias invoke_without_genspec_error_handler invoke
alias invoke invoke_with_genspec_error_handler
end
end
end
end
end
end