lib/rspactor/runner.rb in mislav-rspactor-0.3.2 vs lib/rspactor/runner.rb in mislav-rspactor-0.3.3
- old
+ new
@@ -1,55 +1,98 @@
require 'rspactor'
module RSpactor
class Runner
- def self.load
- dotfile = File.join(ENV['HOME'], '.rspactor')
- Kernel.load dotfile if File.exists?(dotfile)
-
- dir = Dir.pwd
- @inspector = Inspector.new(dir)
- @interactor = Interactor.new
-
+ def self.start(options = {})
+ new(Dir.pwd, options).start
+ end
+
+ attr_reader :dir, :options, :inspector, :interactor
+
+ def initialize(dir, options = {})
+ @dir = dir
+ @options = options
+ read_git_head
+ end
+
+ def start
+ load_dotfile
puts "** RSpactor is now watching at '#{dir}'"
-
- aborted = initial_spec_run_abort
+ start_interactor
+ start_listener
+ end
+
+ def start_interactor
+ @interactor = Interactor.new
+ aborted = @interactor.wait_for_enter_key("** Hit <enter> to skip initial spec run", 3)
@interactor.start_termination_handler
run_all_specs unless aborted
+ end
+
+ def start_listener
+ @inspector = Inspector.new(dir)
Listener.new(Inspector::EXTENSIONS) do |files|
- files_to_spec = []
- files.each do |file|
- spec_files = @inspector.determine_spec_files(file)
- unless spec_files.empty?
- puts spec_files.join("\n")
- files_to_spec.concat spec_files
- end
- end
- run_spec_command(files_to_spec)
+ spec_changed_files(files) unless git_head_changed?
end.run(dir)
end
-
- def self.initial_spec_run_abort
- @interactor.wait_for_enter_key("** Hit <enter> to skip initial spec run", 3)
+
+ def load_dotfile
+ dotfile = File.join(ENV['HOME'], '.rspactor')
+ if File.exists?(dotfile)
+ begin
+ Kernel.load dotfile
+ rescue => e
+ $stderr.puts "Error while loading #{dotfile}: #{e}"
+ end
+ end
end
- def self.run_all_specs
+ def run_all_specs
run_spec_command('spec')
end
- def self.run_spec_command(paths)
+ def run_spec_command(paths)
paths = Array(paths)
- return if paths.empty?
- run_command [ruby_opts, spec_runner, paths, spec_opts].flatten.join(' ')
+ if paths.empty?
+ @last_run_failed = nil
+ else
+ cmd = [ruby_opts, spec_runner, paths, spec_opts].flatten.join(' ')
+ @last_run_failed = run_command(cmd)
+ end
end
+
+ def last_run_failed?
+ @last_run_failed == false
+ end
+
+ protected
- def self.run_command(cmd)
+ def run_command(cmd)
system(cmd)
+ $?.success?
end
+
+ def spec_changed_files(files)
+ files_to_spec = files.inject([]) do |all, file|
+ all.concat inspector.determine_spec_files(file)
+ end
+ unless files_to_spec.empty?
+ puts files_to_spec.join("\n")
+
+ previous_run_failed = last_run_failed?
+ run_spec_command(files_to_spec)
+
+ if options[:retry_failed] and previous_run_failed and not last_run_failed?
+ run_all_specs
+ end
+ end
+ end
+
+ private
- def self.spec_opts
+ def spec_opts
if File.exist?('spec/spec.opts')
opts = File.read('spec/spec.opts').gsub("\n", ' ')
else
opts = "--color"
end
@@ -59,24 +102,36 @@
opts << ' -f progress' unless opts.scan(/\s(?:-f|--format)\b/).length > 1
opts
end
- def self.formatter_opts
+ def formatter_opts
"-r #{File.dirname(__FILE__)}/../rspec_growler.rb -f RSpecGrowler:STDOUT"
end
- def self.spec_runner
+ def spec_runner
if File.exist?("script/spec")
"script/spec"
else
"spec"
end
end
- def self.ruby_opts
+ def ruby_opts
other = ENV['RUBYOPT'] ? " #{ENV['RUBYOPT']}" : ''
+ other << ' -rcoral' if options[:coral]
%(RUBYOPT='-Ilib:spec#{other}')
+ end
+
+ def git_head_changed?
+ old_git_head = @git_head
+ read_git_head
+ @git_head and old_git_head and @git_head != old_git_head
+ end
+
+ def read_git_head
+ git_head_file = File.join(dir, '.git', 'HEAD')
+ @git_head = File.exists?(git_head_file) && File.read(git_head_file)
end
end
end
# backward compatibility
\ No newline at end of file