Skip to content

Commit

Permalink
Support watching of individual files.
Browse files Browse the repository at this point in the history
  • Loading branch information
nex3 authored and ttilley committed Jan 16, 2010
1 parent 6825f27 commit ddfd09d
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 84 deletions.
13 changes: 3 additions & 10 deletions lib/fssm.rb
Expand Up @@ -12,15 +12,7 @@ def dbg(msg=nil)

def monitor(*args, &block)
monitor = FSSM::Monitor.new
context = args.empty? ? monitor : monitor.path(*args)

if block_given?
if block.arity == 1
block.call(context)
else
context.instance_eval(&block)
end
end
FSSM::Support.use_block(args.empty? ? monitor : monitor.path(*args), block)

monitor.run
end
Expand All @@ -33,7 +25,8 @@ def monitor(*args, &block)
require 'fssm/support'
require 'fssm/tree'
require 'fssm/path'
require 'fssm/state'
require 'fssm/state/directory'
require 'fssm/state/file'
require 'fssm/monitor'

require "fssm/backends/#{FSSM::Support.backend.downcase}"
Expand Down
9 changes: 4 additions & 5 deletions lib/fssm/backends/fsevents.rb
Expand Up @@ -7,18 +7,17 @@ def initialize
@fsevents = []
end

def add_path(path, preload=true)
handler = FSSM::State.new(path)
@handlers["#{path}"] = handler
def add_handler(handler, preload=true)
@handlers[handler.path.to_s] = handler

fsevent = Rucola::FSEvents.new("#{path}", {:latency => 0.5}) do |events|
fsevent = Rucola::FSEvents.new(handler.path.to_s, {:latency => 0.5}) do |events|
events.each do |event|
handler.refresh(event.path)
end
end

fsevent.create_stream
handler.refresh(path.to_pathname, true) if preload
handler.refresh(nil, true) if preload
fsevent.start
@fsevents << fsevent
end
Expand Down
8 changes: 3 additions & 5 deletions lib/fssm/backends/inotify.rb
Expand Up @@ -4,14 +4,12 @@ def initialize
@notifier = INotify::Notifier.new
end

def add_path(path, preload=true)
handler = FSSM::State.new(path)

@notifier.watch(path.to_s, :all_events) do |event|
def add_handler(path, preload=true)
@notifier.watch(handler.path.to_s, :all_events) do |event|
handler.refresh(event.name)
end

handler.refresh(path.to_pathname, true) if preload
handler.refresh(nil, true) if preload
end

def run
Expand Down
5 changes: 2 additions & 3 deletions lib/fssm/backends/polling.rb
Expand Up @@ -5,9 +5,8 @@ def initialize(options={})
@latency = options[:latency] || 1.5
end

def add_path(path, preload=true)
handler = FSSM::State.new(path)
handler.refresh(path.to_pathname, true) if preload
def add_handler(handler, preload=true)
handler.refresh(nil, true) if preload
@handlers << handler
end

Expand Down
17 changes: 9 additions & 8 deletions lib/fssm/monitor.rb
Expand Up @@ -6,16 +6,17 @@ def initialize(options={})

def path(*args, &block)
path = FSSM::Path.new(*args)
FSSM::Support.use_block(path, block)

if block_given?
if block.arity == 1
block.call(path)
else
path.instance_eval(&block)
end
end
@backend.add_handler(FSSM::State::Directory.new(path))
path
end

def file(*args, &block)
path = FSSM::Path.new(*args)
FSSM::Support.use_block(path, block)

@backend.add_path(path)
@backend.add_handler(FSSM::State::File.new(path))
path
end

Expand Down
53 changes: 0 additions & 53 deletions lib/fssm/state.rb

This file was deleted.

57 changes: 57 additions & 0 deletions lib/fssm/state/directory.rb
@@ -0,0 +1,57 @@
module FSSM::State
class Directory
attr_reader :path

def initialize(path)
@path = path
@cache = FSSM::Tree::Cache.new
end

def refresh(base=nil, skip_callbacks=false)
previous, current = recache(base || @path.to_pathname)

unless skip_callbacks
deleted(previous, current)
created(previous, current)
modified(previous, current)
end
end

private

def created(previous, current)
(current.keys - previous.keys).each {|created| @path.create(created)}
end

def deleted(previous, current)
(previous.keys - current.keys).each {|deleted| @path.delete(deleted)}
end

def modified(previous, current)
(current.keys & previous.keys).each do |file|
@path.update(file) if (current[file] <=> previous[file]) != 0
end
end

def recache(base)
base = FSSM::Pathname.for(base)
previous = @cache.files
snapshot(base)
current = @cache.files
[previous, current]
end

def snapshot(base)
base = FSSM::Pathname.for(base)
@cache.unset(base)
@path.glob.each {|glob| add_glob(base, glob)}
end

def add_glob(base, glob)
FSSM::Pathname.glob(base.join(glob).to_s).each do |fn|
@cache.set(fn)
end
end

end
end
24 changes: 24 additions & 0 deletions lib/fssm/state/file.rb
@@ -0,0 +1,24 @@
module FSSM::State
class File
attr_reader :path

def initialize(path)
@path = path
end

def refresh(base=nil, skip_callbacks=false)
base ||= @path.to_pathname
used_to_exist, @exists = @exists, base.exists?
# this handles bad symlinks without failing. why handle bad symlinks at
# all? well, we could still be interested in their creation and deletion.
old_mtime, @mtime = @mtime, base.symlink? ? Time.at(0) : base.mtime if @exists

unless skip_callbacks
@path.delete(@path.to_s) if used_to_exist && !@exists
@path.create(@path.to_s) if !used_to_exist && @exists
@path.update(@path.to_s) if used_to_exist && @exists && old_mtime != @mtime
end
end

end
end
9 changes: 9 additions & 0 deletions lib/fssm/support.rb
Expand Up @@ -48,5 +48,14 @@ def rb_inotify?
end
end

def use_block(context, block)
return if block.nil?
if block.arity == 1
block.call(context)
else
context.instance_eval(&block)
end
end

end
end

0 comments on commit ddfd09d

Please sign in to comment.