From 94e04ec7e0c16e533be91b5769af1c84e0045a40 Mon Sep 17 00:00:00 2001 From: slavic Date: Sat, 30 Apr 2011 13:38:57 +0300 Subject: [PATCH] add support for Windows using rb-fchange. Specs fail because of k32WaitForMultipleObjects blocks all threads --- Gemfile | 1 + lib/guard/listener.rb | 7 +++ lib/guard/listeners/windows.rb | 35 ++++++++++++ spec/guard/listener_spec.rb | 6 +-- spec/guard/listeners/windows_spec.rb | 79 ++++++++++++++++++++++++++++ spec/support/platform_helper.rb | 4 ++ 6 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 lib/guard/listeners/windows.rb create mode 100644 spec/guard/listeners/windows_spec.rb diff --git a/Gemfile b/Gemfile index 180543c..8b676d9 100644 --- a/Gemfile +++ b/Gemfile @@ -14,4 +14,5 @@ if Config::CONFIG['target_os'] =~ /linux/i end if Config::CONFIG['target_os'] =~ /mswin|mingw/i gem 'win32console' + gem 'rb-fchange', :git => 'git://github.com/stereobooster/rb-fchange.git' end diff --git a/lib/guard/listener.rb b/lib/guard/listener.rb index 3675489..0021c6b 100644 --- a/lib/guard/listener.rb +++ b/lib/guard/listener.rb @@ -4,6 +4,7 @@ module Guard autoload :Darwin, 'guard/listeners/darwin' autoload :Linux, 'guard/listeners/linux' + autoload :Windows, 'guard/listeners/windows' autoload :Polling, 'guard/listeners/polling' class Listener @@ -14,6 +15,8 @@ module Guard Darwin.new elsif linux? && Linux.usable? Linux.new + elsif windows? && Windows.usable? + Windows.new else UI.info "Using polling (Please help us to support your system better than that.)" Polling.new @@ -54,6 +57,10 @@ module Guard Config::CONFIG['target_os'] =~ /linux/i end + def self.windows? + Config::CONFIG['target_os'] =~ /mswin|mingw/i + end + end end diff --git a/lib/guard/listeners/windows.rb b/lib/guard/listeners/windows.rb new file mode 100644 index 0000000..7fd5299 --- /dev/null +++ b/lib/guard/listeners/windows.rb @@ -0,0 +1,35 @@ +module Guard + class Windows < Listener + attr_reader :fchange + + def initialize + super + @fchange = FChange::Notifier.new + end + + def on_change(&callback) + @fchange.watch Dir.pwd, :all_events do |event| + files = modified_files([event.watcher.path]) + update_last_event + callback.call(files) + end + end + + def start + @fchange.run + end + + def stop + @fchange.stop + end + + def self.usable? + require 'rb-fchange' + true + rescue LoadError + UI.info "Please install rb-fchange gem for Windows file events support" + false + end + + end +end diff --git a/spec/guard/listener_spec.rb b/spec/guard/listener_spec.rb index dfbface..a5454aa 100644 --- a/spec/guard/listener_spec.rb +++ b/spec/guard/listener_spec.rb @@ -14,10 +14,10 @@ describe Guard::Listener do subject.select_and_init end - it "uses polling listener on Windows" do + it "uses windows listener on Windows" do Config::CONFIG['target_os'] = 'win32' - Guard::Polling.stub(:usable?).and_return(true) - Guard::Polling.should_receive(:new) + Guard::Windows.stub(:usable?).and_return(true) + Guard::Windows.should_receive(:new) subject.select_and_init end diff --git a/spec/guard/listeners/windows_spec.rb b/spec/guard/listeners/windows_spec.rb new file mode 100644 index 0000000..d161b1f --- /dev/null +++ b/spec/guard/listeners/windows_spec.rb @@ -0,0 +1,79 @@ +require 'spec_helper' +require 'guard/listeners/windows' + +describe Guard::Windows do + subject { Guard::Windows } + + if linux? + it "isn't usable on linux" do + subject.should_not be_usable + end + end + + if mac? + it "isn't usable on Mac" do + subject.should_not be_usable + end + end + + if windows? + it "is usable on Windows 2000 and later" do + subject.should be_usable + end + + describe "#on_change" do + before(:each) do + @results = [] + @listener = Guard::Windows.new + @listener.on_change do |files| + @results += files + end + end + + it "catches new file" do + file = @fixture_path.join("newfile.rb") + File.exists?(file).should be_false + start + FileUtils.touch file + stop + File.delete file + @results.should == ['spec/fixtures/newfile.rb'] + end + + it "catches file update" do + file = @fixture_path.join("folder1/file1.txt") + File.exists?(file).should be_true + start + FileUtils.touch file + stop + @results.should == ['spec/fixtures/folder1/file1.txt'] + end + + it "catches files update" do + file1 = @fixture_path.join("folder1/file1.txt") + file2 = @fixture_path.join("folder1/folder2/file2.txt") + File.exists?(file1).should be_true + File.exists?(file2).should be_true + start + FileUtils.touch file1 + FileUtils.touch file2 + stop + @results.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt'] + end + end + end + +private + + def start + sleep 0.6 + Thread.new { @listener.start } + sleep 0.6 + end + + def stop + sleep 0.6 + @listener.stop + end + +end diff --git a/spec/support/platform_helper.rb b/spec/support/platform_helper.rb index 2b8bfb5..c1acf10 100644 --- a/spec/support/platform_helper.rb +++ b/spec/support/platform_helper.rb @@ -4,4 +4,8 @@ end def linux? Config::CONFIG['target_os'] =~ /linux/i +end + +def windows? + Config::CONFIG['target_os'] =~ /mswin|mingw/i end \ No newline at end of file