Compare commits

..

1 Commits

Author SHA1 Message Date
John Bintz 36d24c0c14 update maintainer message, thanks to @ranmocy for taking over 2013-01-22 10:24:11 -05:00
5 changed files with 55 additions and 88 deletions

View File

@ -1,4 +1,4 @@
_I'm currently looking for a new maintainer for this project._ _This fork is no longer maintained. Visit [https://github.com/ranmocy/guard-rails](https://github.com/ranmocy/guard-rails) for the current official fork._
[![Build Status](http://travis-ci.org/johnbintz/guard-rails.png)](http://travis-ci.org/johnbintz/guard-rails) [![Build Status](http://travis-ci.org/johnbintz/guard-rails.png)](http://travis-ci.org/johnbintz/guard-rails)

View File

@ -20,8 +20,6 @@ Gem::Specification.new do |s|
s.require_paths = ["lib"] s.require_paths = ["lib"]
s.add_dependency 'guard', '>= 0.2.2' s.add_dependency 'guard', '>= 0.2.2'
s.add_dependency 'childprocess'
s.add_dependency 'sys-proctable'
s.add_development_dependency 'rspec', '~> 2.6.0' s.add_development_dependency 'rspec', '~> 2.6.0'
s.add_development_dependency 'mocha' s.add_development_dependency 'mocha'

View File

@ -1,10 +1,9 @@
require 'fileutils' require 'fileutils'
require 'timeout'
require 'childprocess'
require 'sys/proctable'
module Guard module Guard
class RailsRunner class RailsRunner
MAX_WAIT_COUNT = 10
attr_reader :options attr_reader :options
def initialize(options) def initialize(options)
@ -13,19 +12,14 @@ module Guard
def start def start
kill_unmanaged_pid! if options[:force_run] kill_unmanaged_pid! if options[:force_run]
process = run_rails_command! run_rails_command!
rails_started = wait_for_rails wait_for_pid
File.open(pid_file, "w") {|file| file.write process.pid} if rails_started
rails_started
end end
def stop def stop
if has_pid? if File.file?(pid_file)
unless windows? system %{kill -SIGINT #{File.read(pid_file).strip}}
Process.kill Signal.list["INT"], pid rescue nil wait_for_no_pid if $?.exitstatus == 0
else
kill_all_child_processes
end
FileUtils.rm pid_file, :force => true FileUtils.rm pid_file, :force => true
end end
end end
@ -42,15 +36,11 @@ module Guard
'--pid', pid_file '--pid', pid_file
] ]
rails_options << '-d' if options[:daemon] && !windows? rails_options << '-d' if options[:daemon]
rails_options << '-u' if options[:debugger] rails_options << '-u' if options[:debugger]
rails_options << options[:server] if options[:server] rails_options << options[:server] if options[:server]
cmd = [] %{sh -c 'cd #{Dir.pwd} && RAILS_ENV=#{options[:environment]} rails s #{rails_options.join(' ')} &'}
if windows?
cmd << 'cmd' << '/C'
end
cmd << "rails server #{rails_options.join(' ')}"
end end
def pid_file def pid_file
@ -61,78 +51,56 @@ module Guard
File.file?(pid_file) ? File.read(pid_file).to_i : nil File.file?(pid_file) ? File.read(pid_file).to_i : nil
end end
private def sleep_time
options[:timeout].to_f / MAX_WAIT_COUNT.to_f
end
private
def run_rails_command! def run_rails_command!
process = ChildProcess.build *build_rails_command system build_rails_command
process.environment["RAILS_ENV"] = options[:environment]
process.io.inherit!
process.start
process
end end
def has_pid? def has_pid?
File.file?(pid_file) File.file?(pid_file)
end end
def wait_for_pid_action
sleep sleep_time
end
def kill_unmanaged_pid! def kill_unmanaged_pid!
if pid = unmanaged_pid if pid = unmanaged_pid
Process.kill Signal.list["KILL"], pid system %{kill -KILL #{pid}}
FileUtils.rm pid_file if has_pid? FileUtils.rm pid_file
wait_for_no_pid
end end
end end
def unmanaged_pid def unmanaged_pid
unless windows? %x{lsof -n -i TCP:#{options[:port]}}.each_line { |line|
%x{lsof -n -i TCP:#{options[:port]}}.each_line { |line| if line["*:#{options[:port]} "]
if line["*:#{options[:port]} "] return line.split("\s")[1]
return line.split("\s")[1] end
end }
}
else
%x{netstat -ano}.each_line { |line|
protocol, local_address, _, state, pid = line.strip.split(/\s+/)
return pid.to_i if protocol == "TCP" &&
state == "LISTENING" &&
local_address =~ /:#{options[:port]}$/
}
end
nil nil
end end
private private
def wait_for_pid
def wait_for_rails wait_for_pid_loop
Timeout.timeout(options[:timeout]) {sleep 1 until rails_running?}
true
rescue Timeout::Error
false
end end
def rails_running? def wait_for_no_pid
return false unless has_pid? wait_for_pid_loop(false)
TCPSocket.new('127.0.0.1', options[:port]).close
true
rescue Errno::ECONNREFUSED
false
end end
def windows? def wait_for_pid_loop(check_for_existince = true)
RUBY_PLATFORM =~ /mswin|msys|mingw/ count = 0
end while !(check_for_existince ? has_pid? : !has_pid?) && count < MAX_WAIT_COUNT
wait_for_pid_action
def kill_all_child_processes count += 1
all_pids_for(pid).each do |pid|
Process.kill Signal.list["KILL"], pid rescue nil
end end
end !(count == MAX_WAIT_COUNT)
def all_pids_for(parent_pid)
pids = [parent_pid]
Sys::ProcTable.ps do |process|
pids += all_pids_for(process.pid) if process.ppid == parent_pid
end
pids
end end
end end
end end

View File

@ -36,15 +36,15 @@ describe Guard::RailsRunner do
describe '#build_rails_command' do describe '#build_rails_command' do
context 'no daemon' do context 'no daemon' do
it "should not have a daemon switch" do it "should not have a daemon switch" do
runner.build_rails_command.last.should_not match(%r{ -d}) runner.build_rails_command.should_not match(%r{ -d})
end end
end end
context 'daemon', :unless => RUBY_PLATFORM =~ /mswin|msys|mingw/ do context 'daemon' do
let(:options) { default_options.merge(:daemon => true) } let(:options) { default_options.merge(:daemon => true) }
it "should have a daemon switch" do it "should have a daemon switch" do
runner.build_rails_command.last.should match(%r{ -d}) runner.build_rails_command.should match(%r{ -d})
end end
end end
@ -52,7 +52,7 @@ describe Guard::RailsRunner do
let(:options) { default_options.merge(:debugger => true) } let(:options) { default_options.merge(:debugger => true) }
it "should have a debugger switch" do it "should have a debugger switch" do
runner.build_rails_command.last.should match(%r{ -u}) runner.build_rails_command.should match(%r{ -u})
end end
end end
@ -60,29 +60,24 @@ describe Guard::RailsRunner do
let(:options) { default_options.merge(:server => 'thin') } let(:options) { default_options.merge(:server => 'thin') }
it "should have the server name" do it "should have the server name" do
runner.build_rails_command.last.should match(%r{thin}) runner.build_rails_command.should match(%r{thin})
end end
end end
end end
describe '#start' do describe '#start' do
include FakeFS::SpecHelpers
let(:kill_expectation) { runner.expects(:kill_unmanaged_pid!) } let(:kill_expectation) { runner.expects(:kill_unmanaged_pid!) }
let(:pid_stub) { runner.stubs(:has_pid?) } let(:pid_stub) { runner.stubs(:has_pid?) }
before do before do
FileUtils.mkdir_p File.split(runner.pid_file).first runner.expects(:run_rails_command!).once
process = mock('process')
process.stubs(:pid).returns(123)
runner.expects(:run_rails_command!).once.returns(process)
end end
context 'do not force run' do context 'do not force run' do
before do before do
pid_stub.returns(true) pid_stub.returns(true)
kill_expectation.never kill_expectation.never
runner.stubs(:rails_running?).once.returns(true) runner.expects(:wait_for_pid_action).never
end end
it "should act properly" do it "should act properly" do
@ -96,7 +91,7 @@ describe Guard::RailsRunner do
before do before do
pid_stub.returns(true) pid_stub.returns(true)
kill_expectation.once kill_expectation.once
runner.stubs(:rails_running?).once.returns(true) runner.expects(:wait_for_pid_action).never
end end
it "should act properly" do it "should act properly" do
@ -105,12 +100,10 @@ describe Guard::RailsRunner do
end end
context "don't write the pid" do context "don't write the pid" do
let(:options) { default_options.merge(:timeout => 0.1) }
before do before do
pid_stub.returns(false) pid_stub.returns(false)
kill_expectation.never kill_expectation.never
runner.stubs(:rails_running?).once.returns(false) runner.expects(:wait_for_pid_action).times(Guard::RailsRunner::MAX_WAIT_COUNT)
end end
it "should act properly" do it "should act properly" do
@ -119,4 +112,12 @@ describe Guard::RailsRunner do
end end
end end
describe '#sleep_time' do
let(:timeout) { 30 }
let(:options) { default_options.merge(:timeout => timeout) }
it "should adjust the sleep time as necessary" do
runner.sleep_time.should == (timeout.to_f / Guard::RailsRunner::MAX_WAIT_COUNT.to_f)
end
end
end end

View File

@ -1,4 +1,4 @@
require 'mocha_standalone' require 'mocha'
RSpec.configure do |c| RSpec.configure do |c|
c.mock_with :mocha c.mock_with :mocha