From e00a0219ddcbe95394fb7cbaaa24be0968e815de Mon Sep 17 00:00:00 2001 From: Yossef Mendelssohn Date: Sun, 29 Jun 2008 22:29:11 -0500 Subject: [PATCH] Modifying Stream#update_last_event to consider mode. The mtime mode is the default, and the only thing to do is the same old behavior of storing the last event time. The cache mode involves more work, going through each path and storing a File::Stat object for each file. --- lib/fsevents/stream.rb | 15 ++++++-- spec/stream_spec.rb | 78 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 86 insertions(+), 7 deletions(-) diff --git a/lib/fsevents/stream.rb b/lib/fsevents/stream.rb index 089bdb6..de5b136 100644 --- a/lib/fsevents/stream.rb +++ b/lib/fsevents/stream.rb @@ -2,7 +2,7 @@ module FSEvents class Stream - attr_reader :stream, :mode, :last_event + attr_reader :stream, :mode, :last_event, :dirs attr_reader :allocator, :context, :paths, :since, :latency, :flags, :callback class StreamError < StandardError; end @@ -18,6 +18,7 @@ def initialize(*paths, &callback) @mode = options[:mode] || :mtime raise ArgumentError, "Mode '#{mode}' unknown" unless MODES.include?(@mode) + @dirs = {} paths = Dir.pwd if paths.empty? @@ -58,7 +59,17 @@ def start end def update_last_event - @last_event = Time.now + case mode + when :mtime + @last_event = Time.now + when :cache + paths.each do |path| + dirs[path] = {} + Dir["#{path}/*"].each do |file| + dirs[path][file] = File::Stat.new(file) + end + end + end end def startup diff --git a/spec/stream_spec.rb b/spec/stream_spec.rb index 024bb1f..fb7d67d 100644 --- a/spec/stream_spec.rb +++ b/spec/stream_spec.rb @@ -419,11 +419,79 @@ end describe 'updating its last event' do - it 'should store the last event time' do - now = Time.now - Time.stubs(:now).returns(now) - @stream.update_last_event - @stream.last_event.should == now + describe 'when mode is mtime' do + before :each do + @stream.stubs(:mode).returns(:mtime) + end + + it 'should store the last event time' do + now = Time.now + Time.stubs(:now).returns(now) + @stream.update_last_event + @stream.last_event.should == now + end + end + + describe 'when mode is cache' do + before :each do + @stream.stubs(:mode).returns(:cache) + @files = Array.new(5) { |i| stub("file #{i+1}") } + @stats = Array.new(5) { |i| stub("file #{i+1} stat") } + + @files.zip(@stats).each do |file, stat| + File::Stat.stubs(:new).with(file).returns(stat) + end + + Dir.stubs(:[]).returns(@files) + end + + it 'should get the contents of its path' do + Dir.expects(:[]).with("#{@path}/*").returns([]) + @stream.update_last_event + end + + it 'should get stat objects for the path contents' do + @files.zip(@stats).each do |file, stat| + File::Stat.expects(:new).with(file).returns(stat) + end + @stream.update_last_event + end + + it 'should cache the stat objects' do + @stream.update_last_event + + @files.zip(@stats).each do |file, stat| + @stream.dirs[@path][file].should == stat + end + end + + it 'should update already-existent cache entries' do + file = @files[3] + val = @stats[3] + @stream.dirs[@path] = { file => 'some other val' } + + @stream.update_last_event + @stream.dirs[@path][file].should == val + end + + it 'should remove non-needed cache entries' do + file = 'some other file' + @stream.dirs[@path] = { file => 'some val' } + + @stream.update_last_event + @stream.dirs[@path].should_not have_key(file) + end + + it 'should handle multiple paths' do + other_path = '/other/path' + paths = [@path, other_path] + @stream.stubs(:paths).returns(paths) + + paths.each do |path| + Dir.expects(:[]).with("#{path}/*").returns([]) + end + @stream.update_last_event + end end end