<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -2,12 +2,20 @@ require 'fileutils'
 include FileUtils
 
 require 'rubygems'
-%w[rake hoe newgem rubigen].each do |req_gem|
+required = %w[rake hoe newgem rubigen]
+class &lt;&lt; required
+  def to_sentence
+    &quot;#{self[0...-1].join(', ')}, and #{self[-1]}&quot;
+  end
+end
+required.each do |gem_name|
   begin
-    require req_gem
-  rescue LoadError
-    puts &quot;This Rakefile requires the '#{req_gem}' RubyGem.&quot;
-    puts &quot;Installation: gem install #{req_gem} -y&quot;
+    require gem_name
+  rescue LoadError =&gt; e
+    puts &quot;[!] In order to run this Rakefile you need the following gems: #{required.to_sentence}&quot;
+    puts
+    puts &quot;    Couldn't load: `#{gem_name}' (#{e.message})&quot;
+    puts &quot;    Please install the required gem: gem install #{gem_name}&quot;
     exit
   end
 end</diff>
      <filename>config/requirements.rb</filename>
    </modified>
    <modified>
      <diff>@@ -33,39 +33,61 @@ module Rucola
     attr_accessor :latency
     attr_accessor :flags
     
-    class &lt;&lt; self
-      # Initializes a new FSEvents `watchdog` object,
-      # creates, starts and then returns the stream.
-      #
-      # Pass it a block which will be used as a callback.
-      # The block will receive an array of FSEvent objects.
-      #
-      #   fsevents = Rucola::FSEvents.start_watching('/some/path') do |events|
-      #     events.each do |event|
-      #       p event
-      #     end
-      #   end
-      #   p fsevents
-      def start_watching(*paths, &amp;block)
-        fsevents = new(paths.flatten, &amp;block)
-        fsevents.create_stream
-        fsevents.start
-        fsevents
-      end
+    # 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(&quot;#{event.files.inspect} were changed.&quot;) }
+    #   end
+    #   
+    #   Rucola::FSEvents.start_watching('/var/log/system.log', '/var/log/secure.log', :since =&gt; last_id, :latency =&gt; 5) do
+    #     Growl.notify(&quot;Something was added to your log files!&quot;)
+    #   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(&quot;Volume changes: #{event.files.to_sentence}&quot;) }
+    #   end
+    #   fsevents.stop
+    def self.start_watching(*params, &amp;block)
+      fsevents = new(*params, &amp;block)
+      fsevents.create_stream
+      fsevents.start
+      fsevents
     end
     
-    # Creates a new FSEvents `watchdog` object.
-    # Pass it an array of paths and a block with your callback. Options allow you to specify in more detail how
-    # the events watcher should behave.
+    # 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(&quot;Someone touched the password file!&quot;) }
+    #   fsevents.create_stream
+    #   fsevents.start
+    #
+    #   fsevents = FSEvents.new('/home/upload', :since =&gt; UploadWatcher.last_event_id) do |events|
+    #     events.each do |event|
+    #       UploadWatcher.last_event_id = event.id
+    #       event.files.each do |file|
+    #         UploadWatcher.logfile.append(&quot;#{file} was changed&quot;)
+    #       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 &quot;beginning of time&quot; 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)
     #
-    # For the rest of the options read the Cocoa documentation.
-    def initialize(paths, options={}, &amp;block)
+    # Please refer to the Cocoa documentation for the rest of the options.
+    def initialize(*params, &amp;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, &quot;The specified path (#{path}) does not exist.&quot; unless File.exist?(path) }
       
       @allocator = options[:allocator] || OSX::KCFAllocatorDefault
@@ -75,7 +97,6 @@ module Rucola
       @flags     = options[:flags]     || 0
       @stream    = options[:stream]    || nil
       
-      @paths = paths
       @user_callback = block
       @callback = Proc.new do |stream, client_callback_info, number_of_events, paths_pointer, event_flags, event_ids|
         paths_pointer.regard_as('*')</diff>
      <filename>lib/rucola/fsevents.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,7 +21,7 @@ module DependenciesSpecHelper
   end
   
   def copied_deps_path(file = '')
-    File.join(TMP_PATH, 'copied_dependencies', file)
+    File.join(Tmp.path, 'copied_dependencies', file)
   end
   
   def stubbed_equal_required_files
@@ -32,6 +32,7 @@ module DependenciesSpecHelper
 end
 
 describe &quot;Dependencies::Dependency&quot; do
+  include Tmp
   include DependenciesSpecHelper
   
   before do</diff>
      <filename>test/test_dependencies.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,26 +3,32 @@ require 'rucola/fsevents'
 
 describe &quot;FSEvents initialization&quot; do
   before do
-    @path = File.dirname(__FILE__)
-    @paths = [@path]
+    @paths = %w(first-directory second-directory).map { |dn| File.join(Tmp.path, dn) }
+    @paths.each { |path| FileUtils.mkdir_p(path) }
   end
 
   it &quot;should raise an ArgumentError if a non existing path is specified&quot; do
-    lambda { Rucola::FSEvents.new('/non/existing/path') {|events| 'nothing' } }.should.raise ArgumentError
+    lambda { Rucola::FSEvents.new('/non/existing/path') { |events| nil } }.should.raise ArgumentError
   end
   
   it &quot;should raise an ArgumentError if no block was passed&quot; do
-    lambda { Rucola::FSEvents.new(@paths) }.should.raise ArgumentError
+    lambda { Rucola::FSEvents.new(*@paths) }.should.raise ArgumentError
   end
   
   it &quot;should take at minimum an array of paths and a block&quot; do
-    fsevents = Rucola::FSEvents.new(@paths) { |events| 'nothing' }
+    fsevents = Rucola::FSEvents.new(*@paths) { |events| nil }
     fsevents.should.be.an.instance_of Rucola::FSEvents
-    fsevents.paths.first.should.be @path
+    fsevents.paths.should == @paths
+  end
+  
+  it &quot;should take a list of paths instead of multiple path arguments&quot; do
+    fsevents = Rucola::FSEvents.new(@paths) { |events| nil }
+    fsevents.should.be.an.instance_of Rucola::FSEvents
+    fsevents.paths.should == @paths
   end
   
   it &quot;should have some default values&quot; do
-    fsevents = Rucola::FSEvents.new(@paths) { |events| 'nothing' }
+    fsevents = Rucola::FSEvents.new(*@paths) { |events| nil }
     fsevents.allocator.should.be OSX::KCFAllocatorDefault
     fsevents.context.should.be nil
     fsevents.since.should.be OSX::KFSEventStreamEventIdSinceNow
@@ -33,28 +39,28 @@ describe &quot;FSEvents initialization&quot; do
 
   it &quot;should be possible to create and start a stream with one call&quot; do
     fsevents = mock('FSEvents')
-    Rucola::FSEvents.expects(:new).with(@paths).returns(fsevents)
+    Rucola::FSEvents.expects(:new).with(*@paths).returns(fsevents)
     fsevents.expects(:create_stream)
     fsevents.expects(:start)
     
-    result = Rucola::FSEvents.start_watching(@path) {|events| 'nothing' }
+    result = Rucola::FSEvents.start_watching(*@paths) {|events| nil }
     result.should.be(fsevents)
   end
   
   it &quot;should accept options to tweak event parameters&quot; do
-    fsevents = Rucola::FSEvents.new(@paths,
-      :latency =&gt; 5.2,
-      :since =&gt; 24051980
-    ) { |events| 'nothing' }
+    fsevents = Rucola::FSEvents.new(*(@paths+[{ :latency =&gt; 5.2, :since =&gt; 24051980 }])) { |events| nil }
+    fsevents.paths.should == @paths
     fsevents.since.should.be 24051980
     fsevents.latency.should == 5.2
   end
 end
 
 describe &quot;FSEvents when setting up the stream&quot; do
+  include Tmp
+  
   before do
-    @path = File.dirname(__FILE__)
-    @paths = [@path]
+    @paths = %w(first-directory second-directory).map { |dn| File.join(Tmp.path, dn) }
+    @paths.each { |path| FileUtils.mkdir_p(path) }
     @fsevents = Rucola::FSEvents.new(@paths) { |events| 'nothing' }
   end
   
@@ -90,63 +96,46 @@ describe &quot;FSEvents when setting up the stream&quot; do
   end
 end
 
-describe &quot;FSEvents when started the stream&quot; do
-  before do
-    @paths = [TMP_PATH]
-  end
-  
-  def touch_file
-    sleep 0.25
-    `touch #{@paths.first}/test.txt`
-    sleep 1.5
-    `rm #{@paths.first}/test.txt`
-  end
+describe &quot;FSEvents with a running stream&quot; do
+  include Tmp
   
-  def start(fsevents)
+  it &quot;should run the specified block on events in the directory&quot; do
+    waiter = :waiting
+    
+    Thread.new { OSX.CFRunLoopRun }
+    fsevents = Rucola::FSEvents.new(Tmp.path) do |events|
+      waiter = :done
+    end
     fsevents.create_stream
     fsevents.start
-    Thread.new { OSX.CFRunLoopRun }
-  end
-  
-  xit &quot;should run the user specified block when one of the paths that was specified is modified&quot; do
-    some_mock = mock
-    some_mock.expects(:call!)
     
-    fsevents = Rucola::FSEvents.new(@paths) do |events|
-      some_mock.call!
-      
-      events.length.should == 1
-      event = events.first
-      event.should.be.an.instance_of Rucola::FSEvents::FSEvent
-      event.path.should == @paths.first
+    new_file = File.join(Tmp.path, 'a-new-file')
+    FileUtils.touch(new_file)
+    File.should.exist(new_file)
+    
+    # Busy wait for the block to run
+    started = Time.now
+    while waiter == :waiting &amp;&amp; (Time.now - started) &lt; 60
+      sleep 0.1
     end
-    p fsevents
-    start(fsevents)
-    touch_file
+    waiter.should == :done
     fsevents.stop
   end
-end
+end unless ENV['QUICK_RUN']
 
 describe &quot;FSEvent&quot; do
+  include Tmp
+  
   before do
-    @tmp_path = TMP_PATH
-    @new_file, @old_file = &quot;#{@tmp_path}/new_file&quot;, &quot;#{@tmp_path}/old_file&quot;
-
-    `touch #{@old_file}`
-    sleep 1
-    `touch #{@new_file}`
-  end
-
-  after do
-    `rm #{@old_file}`
-    `rm #{@new_file}`
+    @files = %w(first-file second-file).map { |fn| File.join(Tmp.path, fn) }
+    @files.each { |fn| FileUtils.touch(fn) }
   end
   
   it &quot;should return an array of file entries in the path that the event occurred in, sorted by modification time (first element = last mod.)&quot; do
-    Rucola::FSEvents::FSEvent.new(nil, 666, @tmp_path).files.should == [@new_file, @old_file]
+    Rucola::FSEvents::FSEvent.new(nil, nil, Tmp.path).files.should == @files.reverse
   end
   
   it &quot;should return the last modified file&quot; do
-    Rucola::FSEvents::FSEvent.new(nil, 999, @tmp_path).last_modified_file.should == @new_file
+    Rucola::FSEvents::FSEvent.new(nil, nil, Tmp.path).last_modified_file.should == @files.last
   end
 end
\ No newline at end of file</diff>
      <filename>test/test_fsevents.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,7 +15,6 @@ $TESTING = true
 require 'pathname'
 RUBYCOCOA_ROOT = Pathname.new(File.expand_path(File.dirname(__FILE__)))
 RUBYCOCOA_ENV = 'test'
-TMP_PATH = File.expand_path('../../tmp/', __FILE__)
 
 require 'rucola/rucola_support'
 require 'rucola/test_helper'
@@ -40,3 +39,25 @@ module Test::Spec::Rucola
 end
 Test::Spec::Should.send(:include, Test::Spec::Rucola::ShouldChange)
 Test::Spec::ShouldNot.send(:include, Test::Spec::Rucola::ShouldNotChange)
+
+require 'tmpdir'
+require 'fileutils'
+
+module Tmp
+  def self.included(base)
+    base.send(:before) { Tmp.setup }
+    base.send(:after)  { Tmp.teardown }
+  end
+  
+  def self.setup
+    FileUtils.mkdir_p(path)
+  end
+  
+  def self.teardown
+    FileUtils.rm_rf(path)
+  end
+  
+  def self.path
+    File.join(Dir.tmpdir, 'rucola')
+  end
+end</diff>
      <filename>test/test_helper.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>94ba749c5dd272ccda39830d2d882e288e14cea7</id>
    </parent>
  </parents>
  <author>
    <name>Manfred Stienstra</name>
    <email>manfred@fngtps.com</email>
  </author>
  <url>http://github.com/alloy/rucola/commit/cafb2d80144de4988c996f5dd27827752962bec8</url>
  <id>cafb2d80144de4988c996f5dd27827752962bec8</id>
  <committed-date>2008-12-06T06:25:13-08:00</committed-date>
  <authored-date>2008-12-06T06:25:13-08:00</authored-date>
  <message>Small changes to the FSEvents API.

- FSEvents.start_watching now takes options, just like initialize.
- FSEvents.start_watching and FSEvents.new take either a list of paths or a list of arguments of paths:

  FSEvents.new('/first/path', '/second/path', :latency =&gt; 1.0)
  FSEvents.new(['/first/path', '/second/path'], :latency =&gt; 1.0)

- Change config/requirements.rb slightly to give nicer output and explain a bit more about the dependencies.
- Added a Tmp module to the tests so tests which use a temporary directory get clean automatically.</message>
  <tree>af07520368ce067d2fb73164d5c7af9f08071011</tree>
  <committer>
    <name>Manfred Stienstra</name>
    <email>manfred@fngtps.com</email>
  </committer>
</commit>
