paulanthonywilson-osx_watchfolder 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,7 +19,7 @@ Only works on OSX 10.5+ (Leopard), obviously.
19
19
 
20
20
  To run a the method 'run_tests' when a change is detected in a couple of folders:
21
21
 
22
- OsxWatchFolder::FolderWatcher.new ("lib", "test") { run_tests}
22
+ OsxWatchfolder::FolderWatcher.new("lib", "test") { run_tests}.start
23
23
 
24
24
  == REQUIREMENTS:
25
25
 
@@ -2,7 +2,7 @@
2
2
  module OsxWatchfolder
3
3
 
4
4
  # :stopdoc:
5
- VERSION = '1.0.0'
5
+ VERSION = '1.0.1'
6
6
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
7
7
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
8
8
  # :startdoc:
@@ -3,33 +3,38 @@ OSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Framewo
3
3
 
4
4
  module OsxWatchfolder
5
5
 
6
+ # To run a the method 'run_tests' when a change is detected in a couple of folders:
7
+ #
8
+ # folder_watcher = OsxWatchfolder::FolderWatcher.new("lib", "test") { run_tests}
9
+ # folder_wacher.start
10
+ #
6
11
  class FolderWatcher
7
-
8
- attr_accessor :latency, :runloop_interval
12
+
13
+ # directory update notification latency in seconds. Defaults to 1
14
+ attr_accessor :latency
15
+
16
+ # runloop timeout in seconds - on all but the 1st interrupt for the script it will take a maximum of
17
+ # this long for interrupts to be noticed. Defaults to 5
18
+ attr_accessor :runloop_interval
19
+
20
+ # how many times has this been interrupted?
21
+ attr_reader :interrupted_count
9
22
 
10
23
 
11
24
  def stop
25
+ @running = false
12
26
  OSX::CFRunLoopStop(@runloop)
13
27
  end
14
28
 
15
29
  def start
16
30
  raise "May only be started from main thread" unless Thread.current == Thread.main
17
- callback = lambda do |streamRef, clientCallBackInfo, numEvents,eventPaths, eventFlags,eventIds|
18
- @block.call
19
- end
20
- stream = OSX::FSEventStreamCreate(nil,
21
- callback,
22
- nil,
23
- @folders,
24
- OSX::KFSEventStreamEventIdSinceNow,
25
- @latency,
26
- OSX::KFSEventStreamCreateFlagNone)
27
-
28
- @runloop = OSX::CFRunLoopGetCurrent()
29
-
30
- OSX::FSEventStreamScheduleWithRunLoop(stream, @runloop, OSX::KCFRunLoopDefaultMode)
31
- OSX::FSEventStreamStart(stream)
32
- OSX::CFRunLoopRun()
31
+ prepare_stream
32
+ enter_run_loop
33
+ rescue Interrupt
34
+ stop
35
+ @interrupted_count += 1
36
+ ensure
37
+ cleanup_stream
33
38
  end
34
39
 
35
40
 
@@ -38,7 +43,40 @@ module OsxWatchfolder
38
43
  @block = block
39
44
  @running = true
40
45
  @latency = 1
46
+ @runloop_interval = 5
47
+ @interrupted_count = 0
41
48
  end
42
49
 
50
+ private
51
+
52
+
53
+ def enter_run_loop
54
+ @running = true
55
+ OSX::CFRunLoopRunInMode(OSX::KCFRunLoopDefaultMode, @runloop_interval, true) while @running
56
+ end
57
+
58
+ def cleanup_stream
59
+ if (@stream)
60
+ OSX::FSEventStreamStop(@stream)
61
+ OSX::FSEventStreamInvalidate(@stream)
62
+ OSX::FSEventStreamRelease(@stream)
63
+ end
64
+ @stream = nil
65
+ end
66
+
67
+ def prepare_stream
68
+ callback = lambda do |streamRef, clientCallBackInfo, numEvents,eventPaths, eventFlags,eventIds|
69
+ @block.call
70
+ end
71
+ @stream = OSX::FSEventStreamCreate(nil,callback,nil,@folders,OSX::KFSEventStreamEventIdSinceNow, @latency,OSX::KFSEventStreamCreateFlagNone)
72
+
73
+ @runloop = OSX::CFRunLoopGetCurrent()
74
+
75
+ OSX::FSEventStreamScheduleWithRunLoop(@stream, @runloop, OSX::KCFRunLoopDefaultMode)
76
+ OSX::FSEventStreamStart(@stream)
77
+ end
78
+
79
+
80
+
43
81
  end
44
82
  end
Binary file
@@ -4,8 +4,8 @@ require 'fileutils'
4
4
  require File.expand_path(File.dirname(__FILE__) + '/../lib/osx_watchfolder')
5
5
 
6
6
  class TestFolderWatch < Test::Unit::TestCase
7
- include FileUtils
8
- include OsxWatchfolder
7
+ include FileUtils
8
+ include OsxWatchfolder
9
9
 
10
10
  def setup
11
11
  @some_folders = [Dir.tmpdir + "/folder_watch_test1", Dir.tmpdir + "/folder_watch_test2"]
@@ -13,11 +13,11 @@ include OsxWatchfolder
13
13
  @some_folders.each {|dir| mkdir dir}
14
14
  @folder_changed = false
15
15
  end
16
-
16
+
17
17
  def teardown
18
18
  @some_folders.each {|dir| rm_rf dir}
19
19
  end
20
-
20
+
21
21
  def test_nothing_happens_if_a_watched_folder_does_not_change
22
22
  in_a_second_yield_and_stop_watcher
23
23
  watch_folders
@@ -29,20 +29,20 @@ include OsxWatchfolder
29
29
  assert_equal @some_folders, FolderWatcher.new(@some_folders).instance_variable_get(:@folders)
30
30
  end
31
31
 
32
-
32
+
33
33
  def test_notified_if_first_watched_folder_changes
34
34
  in_a_second_write_file_and_stop_watcher @some_folders.first + "/somefile"
35
35
  watch_folders
36
36
  assert @folder_changed
37
37
  end
38
-
38
+
39
39
 
40
40
  def test_notified_if_another_watched_folder_changes
41
41
  in_a_second_write_file_and_stop_watcher @some_folders.last + "/somefile"
42
42
  watch_folders
43
43
  assert @folder_changed
44
44
  end
45
-
45
+
46
46
  def test_must_be_started_in_main_thread
47
47
  @testee = FolderWatcher.new(*@some_folders) {}
48
48
  t = Thread.new do
@@ -50,8 +50,20 @@ include OsxWatchfolder
50
50
  end
51
51
  t.join
52
52
  end
53
-
54
-
53
+
54
+ def test_handles_interrupts
55
+ @testee = FolderWatcher.new(*@some_folders) {}
56
+ assert_equal 0, @testee.interrupted_count
57
+ class << @testee
58
+ def enter_run_loop
59
+ raise Interrupt, "stopped!"
60
+ end
61
+ end
62
+ @testee.start
63
+ assert_equal 1, @testee.interrupted_count
64
+ end
65
+
66
+
55
67
  def in_a_second_yield_and_stop_watcher
56
68
  Thread.new do
57
69
  yield if block_given?
@@ -59,19 +71,19 @@ include OsxWatchfolder
59
71
  @testee.stop
60
72
  end
61
73
  end
62
-
74
+
63
75
  def in_a_second_write_file_and_stop_watcher(file)
64
76
  in_a_second_yield_and_stop_watcher do
65
77
  File.open(file, "w"){|f| f.write "hello"}
66
78
  end
67
79
  end
68
-
80
+
69
81
  def watch_folders
70
82
  @testee = FolderWatcher.new(*@some_folders) {@folder_changed = true}
71
83
  @testee.latency = 0.1
72
84
  @testee.runloop_interval = 0.5
73
85
  @testee.start
74
86
  end
75
-
76
-
87
+
88
+
77
89
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paulanthonywilson-osx_watchfolder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Wilson
@@ -38,7 +38,6 @@ files:
38
38
  - Rakefile
39
39
  - lib/osx_watchfolder.rb
40
40
  - lib/osx_watchfolder/folder_watcher.rb
41
- - osx_watchfolder-1.0.0.gem
42
41
  - osx_watchfolder.gemspec
43
42
  - test/test_folder_watch.rb
44
43
  has_rdoc: true