Class: Rucola::FSEvents

Inherits:
Object
  • Object
show all
Defined in:
lib/fssm/backends/rubycocoa/fsevents.rb

Defined Under Namespace

Classes: FSEvent, StreamError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*params, &block) ⇒ FSEvents

Creates a new FSEvents ‘watchdog` object. You can specify a list of paths to watch and options to control the behaviour of the watchdog. The block you pass serves as a callback when an event is generated on one of the specified paths.

fsevents = FSEvents.new('/etc/passwd') { Mailer.send_mail("Someone touched the password file!") }
fsevents.create_stream
fsevents.start

fsevents = FSEvents.new('/home/upload', :since => UploadWatcher.last_event_id) do |events|
  events.each do |event|
    UploadWatcher.last_event_id = event.id
    event.files.each do |file|
      UploadWatcher.logfile.append("#{file} was changed")
    end
  end
end

*:since: The service will report events that have happened after the supplied event ID. Never use 0 because that

will cause every fsevent since the "beginning of time" to be reported. Use OSX::KFSEventStreamEventIdSinceNow
if you want to receive events that have happened after this call. (Default: OSX::KFSEventStreamEventIdSinceNow).
You can find the ID's passed with :since in the events passed to your block.

*:latency: Number of seconds to wait until an FSEvent is reported, this allows the service to bundle events. (Default: 0.0)

Please refer to the Cocoa documentation for the rest of the options.

Raises:

  • (ArgumentError)


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 87

def initialize(*params, &block)
  raise ArgumentError, 'No callback block was specified.' unless block_given?

  options = params.last.kind_of?(Hash) ? params.pop : {}
  @paths  = params.flatten

  paths.each { |path| raise ArgumentError, "The specified path (#{path}) does not exist." unless File.exist?(path) }

  @allocator     = options[:allocator] || OSX::KCFAllocatorDefault
  @context       = options[:context] || nil
  @since         = options[:since] || OSX::KFSEventStreamEventIdSinceNow
  @latency       = options[:latency] || 0.0
  @flags         = options[:flags] || 0
  @stream        = options[:stream] || nil

  @user_callback = block
  @callback      = Proc.new do |stream, client_callback_info, number_of_events, paths_pointer, event_flags, event_ids|
    paths_pointer.regard_as('*')
    events = []
    number_of_events.times { |i| events << Rucola::FSEvents::FSEvent.new(self, event_ids[i], paths_pointer[i]) }
    @user_callback.call(events)
  end
end

Instance Attribute Details

#allocatorObject

Returns the value of attribute allocator.



32
33
34
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 32

def allocator
  @allocator
end

#contextObject

Returns the value of attribute context.



33
34
35
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 33

def context
  @context
end

#flagsObject

Returns the value of attribute flags.



36
37
38
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 36

def flags
  @flags
end

#latencyObject

Returns the value of attribute latency.



35
36
37
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 35

def latency
  @latency
end

#pathsObject (readonly)

Returns the value of attribute paths.



29
30
31
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 29

def paths
  @paths
end

#sinceObject

Returns the value of attribute since.



34
35
36
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 34

def since
  @since
end

#streamObject (readonly)

Returns the value of attribute stream.



30
31
32
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 30

def stream
  @stream
end

Class Method Details

.start_watching(*params, &block) ⇒ Object

Initializes a new FSEvents ‘watchdog` object and starts watching the directories you specify for events. The block is used as a handler for events, which are passed as the block’s argument. This method is the easiest way to start watching some directories if you don’t care about the details of setting up the event stream.

Rucola::FSEvents.start_watching('/tmp') do |events|
  events.each { |event| log.debug("#{event.files.inspect} were changed.") }
end

Rucola::FSEvents.start_watching('/var/log/system.log', '/var/log/secure.log', :since => last_id, :latency => 5) do
  Growl.notify("Something was added to your log files!")
end

Note that the method also returns the FSEvents object. This enables you to control the event stream if you want to.

fsevents = Rucola::FSEvents.start_watching('/Volumes') do |events|
  events.each { |event| Growl.notify("Volume changes: #{event.files.to_sentence}") }
end
fsevents.stop


56
57
58
59
60
61
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 56

def self.start_watching(*params, &block)
  fsevents = new(*params, &block)
  fsevents.create_stream
  fsevents.start
  fsevents
end

Instance Method Details

#create_streamObject

Create the stream. Raises a Rucola::FSEvents::StreamError if the stream could not be created.

Raises:



113
114
115
116
117
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 113

def create_stream
  @stream = OSX.FSEventStreamCreate(@allocator, @callback, @context, @paths, @since, @latency, @flags)
  raise(StreamError, 'Unable to create FSEvents stream.') unless @stream
  OSX.FSEventStreamScheduleWithRunLoop(@stream, OSX.CFRunLoopGetCurrent, OSX::KCFRunLoopDefaultMode)
end

#startObject

Start the stream. Raises a Rucola::FSEvents::StreamError if the stream could not be started.

Raises:



121
122
123
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 121

def start
  raise(StreamError, 'Unable to start FSEvents stream.') unless OSX.FSEventStreamStart(@stream)
end

#stopObject

Stop the stream. You can resume it by calling ‘start` again.



127
128
129
# File 'lib/fssm/backends/rubycocoa/fsevents.rb', line 127

def stop
  OSX.FSEventStreamStop(@stream)
end