Skip to content

Commit

Permalink
create shared examples all listeners should behave like
Browse files Browse the repository at this point in the history
  • Loading branch information
niklas committed May 15, 2011
1 parent 9c44f89 commit bc740d7
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 289 deletions.
22 changes: 21 additions & 1 deletion lib/guard/listener.rb
Expand Up @@ -24,11 +24,22 @@ def self.select_and_init
end

def initialize(directory=Dir.pwd)
@directory = directory
@directory = directory.to_s
@sha1_checksums_hash = {}
update_last_event
end

def start
watch directory
end

def stop
end

def on_change(&callback)
@callback = callback
end

def update_last_event
@last_event = Time.now
end
Expand All @@ -38,6 +49,15 @@ def modified_files(dirs, options = {})
files.map! { |file| file.gsub("#{directory}/", '') }
end

def worker
raise NotImplementedError, "should respond to #watch"
end

# register a directory to watch. must be implemented by the subclasses
def watch(directory)
raise NotImplementedError, "do whatever you want here, given the directory as only argument"
end

private

def potentially_modified_files(dirs, options = {})
Expand Down
25 changes: 16 additions & 9 deletions lib/guard/listeners/darwin.rb
Expand Up @@ -2,25 +2,23 @@ module Guard
class Darwin < Listener
attr_reader :fsevent

def initialize
def initialize(*)
super
@fsevent = FSEvent.new
end

def on_change(&callback)
@fsevent.watch directory do |modified_dirs|
files = modified_files(modified_dirs)
update_last_event
callback.call(files)
end
def worker
@fsevent
end

def start
@fsevent.run
super
fsevent.run
end

def stop
@fsevent.stop
super
fsevent.stop
end

def self.usable?
Expand All @@ -36,5 +34,14 @@ def self.usable?
false
end

private
def watch(directory)
worker.watch directory do |modified_dirs|
files = modified_files(modified_dirs)
update_last_event
callback.call(files)
end
end

end
end
27 changes: 16 additions & 11 deletions lib/guard/listeners/linux.rb
Expand Up @@ -2,7 +2,7 @@ module Guard
class Linux < Listener
attr_reader :inotify, :files, :latency, :callback

def initialize
def initialize(*)
super

@inotify = INotify::Notifier.new
Expand All @@ -12,24 +12,16 @@ def initialize

def start
@stop = false
super
watch_change unless watch_change?
end

def stop
super
@stop = true
sleep latency
end

def on_change(&callback)
@callback = callback
inotify.watch(directory, :recursive, :modify, :create, :delete, :move) do |event|
unless event.name == "" # Event on root directory
@files << event.absolute_name
end
end
rescue Interrupt
end

def self.usable?
require 'rb-inotify'
if !defined?(INotify::VERSION) || Gem::Version.new(INotify::VERSION.join('.')) < Gem::Version.new('0.5.1')
Expand All @@ -49,6 +41,19 @@ def watch_change?

private

def worker
@inotify
end

def watch(directory)
worker.watch(directory, :recursive, :modify, :create, :delete, :move) do |event|
unless event.name == "" # Event on root directory
@files << event.absolute_name
end
end
rescue Interrupt
end

def watch_change
@watch_change = true
until @stop
Expand Down
13 changes: 8 additions & 5 deletions lib/guard/listeners/polling.rb
Expand Up @@ -2,21 +2,19 @@ module Guard
class Polling < Listener
attr_reader :callback, :latency

def initialize
def initialize(*)
super
@latency = 1.5
end

def on_change(&callback)
@callback = callback
end

def start
@stop = false
super
watch_change
end

def stop
super
@stop = true
end

Expand All @@ -33,5 +31,10 @@ def watch_change
end
end

# we have no real worker here
# FIXME: cannot watch muliple directories, but is not needed in guard (yet?)
def watch(directory)
end

end
end
26 changes: 17 additions & 9 deletions lib/guard/listeners/windows.rb
Expand Up @@ -7,20 +7,13 @@ def initialize
@fchange = FChange::Notifier.new
end

def on_change(&callback)
@fchange.watch(directory, :all_events, :recursive) do |event|
paths = [File.expand_path(event.watcher.path) + '/']
files = modified_files(paths, {:all => true})
update_last_event
callback.call(files)
end
end

def start
super
@fchange.run
end

def stop
super
@fchange.stop
end

Expand All @@ -32,5 +25,20 @@ def self.usable?
false
end

private

def worker
@fchange
end

def watch(directory)
worker.watch(directory, :all_events, :recursive) do |event|
paths = [File.expand_path(event.watcher.path) + '/']
files = modified_files(paths, {:all => true})
update_last_event
callback.call(files)
end
end

end
end
35 changes: 35 additions & 0 deletions spec/guard/listener_spec.rb
Expand Up @@ -91,4 +91,39 @@
end
end

describe "working directory" do

context "unspecified" do
subject { described_class.new }
it "defaults to Dir.pwd" do
subject.directory.should == Dir.pwd
end
it "can be not changed" do
subject.should_not respond_to(:directory=)
end
end

context "specified as first argument to ::new" do
before :each do
@wd = @fixture_path.join("folder1")
end
subject { described_class.new @wd }
it "can be inspected" do
subject.directory.should == @wd.to_s
end
it "can be not changed" do
subject.should_not respond_to(:directory=)
end

it "will be used to watch" do
subject.should_receive(:watch).with(@wd.to_s)
@listener = subject # indeed.
start
stop
end
end

end


end
56 changes: 2 additions & 54 deletions spec/guard/listeners/darwin_spec.rb
Expand Up @@ -15,61 +15,9 @@
subject.should be_usable
end

describe "#on_change" do
before(:each) do
@results = []
@listener = Guard::Darwin.new
@listener.on_change do |files|
@results += files
end
end
it_should_behave_like "a listener that reacts to #on_change"
it_should_behave_like "a listener scoped to a specific directory"

it "catches a 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 a single 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 multiple file updates" 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 1
@listener.update_last_event
Thread.new { @listener.start }
sleep 1
end

def stop
sleep 1
@listener.stop
sleep 1
end

end

0 comments on commit bc740d7

Please sign in to comment.