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.
- data/README.rdoc +1 -1
- data/lib/osx_watchfolder.rb +1 -1
- data/lib/osx_watchfolder/folder_watcher.rb +56 -18
- data/osx_watchfolder.gemspec +0 -0
- data/test/test_folder_watch.rb +25 -13
- metadata +1 -2
data/README.rdoc
CHANGED
@@ -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
|
-
|
22
|
+
OsxWatchfolder::FolderWatcher.new("lib", "test") { run_tests}.start
|
23
23
|
|
24
24
|
== REQUIREMENTS:
|
25
25
|
|
data/lib/osx_watchfolder.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
data/osx_watchfolder.gemspec
CHANGED
Binary file
|
data/test/test_folder_watch.rb
CHANGED
@@ -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.
|
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
|