Permalink
Fetching contributors…
Cannot retrieve contributors at this time
152 lines (128 sloc) 4.98 KB
require 'socket'
module Guard
class Spork
class Runner
attr_accessor :options
attr_reader :spork_instances
def initialize(options={})
options[:wait] ||= 30 # seconds
options[:retry_delay] ||= 2 * options[:wait] # seconds
options[:test_unit_port] ||= 8988
options[:cucumber_port] ||= 8990
options[:rspec_port] ||= 8989
options[:minitest_port] ||= 8988
options[:rspec_env] ||= {}
options[:test_unit_env] ||= {}
options[:cucumber_env] ||= {}
options[:minitest_env] ||= {}
options[:minitest] ||= false
options[:aggressive_kill] = true unless options[:aggressive_kill] == false
options[:foreman] ||= false
options[:quiet] ||= false
@options = options
initialize_spork_instances
end
def launch_sporks(action, type = nil)
instances = find_instances(type)
Compat::UI.info "#{action.capitalize}ing Spork for #{instances.join(', ')}", :reset => true
if options[:notify_on_start]
Notifier.notify "#{action.capitalize}ing #{instances.join(', ')}", :title => "Spork", :image => :success
end
instances.each(&:start)
verify_launches(action, instances)
end
def kill_sporks(type = nil)
alive = find_instances(type).select(&:alive?)
Compat::UI.debug "Killing Spork servers with PID: #{alive.map(&:pid).join(', ')}"
alive.each(&:stop)
end
def kill_global_sporks
if options[:aggressive_kill]
kill_pids self.class.spork_instance_class.spork_pids
end
end
def self.windows?
ENV['OS'] == 'Windows_NT'
end
private
def initialize_spork_instances
@spork_instances = []
[:rspec, :cucumber, :test_unit, :minitest].each do |type|
port, env = options[:"#{type}_port"], options[:"#{type}_env"]
spork_instances << self.class.spork_instance_class.new(type, port, env, :bundler => should_use?(:bundler), :foreman => should_use?(:foreman), :quiet => should_use?(:quiet)) if should_use?(type)
end
end
def self.spork_instance_class
windows? ? SporkWindowsInstance : SporkInstance
end
def kill_pids(pids)
Compat::UI.debug "Killing Spork servers with PID: #{pids.join(', ')}"
pids.each { |pid| ::Process.kill("KILL", pid) rescue nil }
end
def find_instances(type = nil)
if type.nil?
spork_instances
else
spork_instances.select { |instance| instance.type == type }
end
end
def verify_launches(action, instances)
start_time = Time.now
names = instances.join(', ')
if wait_for_launch(instances, options[:wait])
Compat::UI.info "Spork server for #{names} successfully #{action}ed", :reset => true
Compat::UI.notify "#{names} successfully #{action}ed", :title => "Spork", :image => :success
else
Compat::UI.error "Could not #{action} Spork server for #{names} after #{options[:wait]} seconds. I will continue waiting for a further #{options[:retry_delay]} seconds."
Compat::UI.notify "#{names} NOT #{action}ed. Continuing to wait for #{options[:retry_delay]} seconds.", :title => "Spork", :image => :failed
if wait_for_launch(instances, options[:retry_delay])
total_time = Time.now - start_time
UI.info "Spork server for #{names} eventually #{action}ed after #{total_time.to_i} seconds. Consider adjusting your :wait option beyond this time.", :reset => true
Notifier.notify "#{names} eventually #{action}ed after #{total_time.to_i} seconds", :title => "Spork", :image => :success
else
Compat::UI.error "Could not #{action} Spork server for #{names}. Make sure you can use it manually first."
Compat::UI.notify "#{names} NOT #{action}ed", :title => "Spork", :image => :failed
throw :task_has_failed
end
end
end
def wait_for_launch(instances, wait)
not_running = instances.dup
wait_or_loop(wait) do
sleep 1
not_running.delete_if { |instance| instance.running? }
return true if not_running.empty?
end
end
def should_use?(what)
options[what].nil? ? send("detect_#{what}") : options[what]
end
def wait_or_loop(wait)
if wait
wait.times { yield }
else
loop { yield }
end
false
end
def detect_bundler
File.exist?("Gemfile")
end
def detect_test_unit
File.exist?("test/test_helper.rb")
end
def detect_rspec
File.exist?("spec") && (options[:minitest].nil? || !options[:minitest])
end
def detect_minitest
false
end
def detect_cucumber
File.exist?("features")
end
def detect_foreman
File.exist?("Procfile")
end
end
end
end