feather_watch 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c365a117cc400f3b83860aabf245dbdd24a87d0e
4
- data.tar.gz: e37efc790a575ed9c9beb2f2699d6e4eff745fbd
3
+ metadata.gz: 30971c259a7028609aabaf9d2ef3a859fe14083c
4
+ data.tar.gz: dddb2c7ab3a28d0382a152ab857531757f2551a1
5
5
  SHA512:
6
- metadata.gz: 54894b9dc54e207f0afc675e75ceddcfb036bfa502d55bbef66fdfcc25b647e5ab85e86807c9a6783d04f8aeaea2868cf61ee4994043ebcbef77372b767f144d
7
- data.tar.gz: 5ccbdba157e5c9cab6cfd23e4033a837259975a81e1cefa0cf6e6900f1543e637f822f90db76cbe0bf8b15bb8b6309521350953484406650548bcec5b0484ef0
6
+ metadata.gz: 1dd10630dfbf7b1de3dec9592a4327ec5a097cbb93786256b5a44796427c67002aa7881a030296dbc4edafd09dc7bc32cbf02103b422425267ba105cc090173d
7
+ data.tar.gz: cec18243d9533413f85b28691b0f1745ba7fbf41fd09cca1ea1ac3e6956e9720481efa34c6083eb61de8c1340a47ec521bafad79f28c207ca488a1f30e608df5
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Light weight, cross platform, file system watcher.
4
4
 
5
5
 
6
- ### Should work windows, but not yet tested becase I do not have access to a windows machine now. If you do, I would love for you to run the specs and see if it works :)
6
+ (!) Should work on windows, but I have not yet tested it because I do not have access to a windows machine right now. If you do, I would love for you to run the specs and see if it works :)
7
7
 
8
8
  [![Build Status](https://travis-ci.org/stephan-nordnes-eriksen/feather_watch.svg?branch=master)](https://travis-ci.org/stephan-nordnes-eriksen/feather_watch)
9
9
 
@@ -40,9 +40,9 @@ Or install it yourself as:
40
40
 
41
41
 
42
42
  # Important Notes!
43
- Events on OSx, also known as darwin, is currenty an approximation as the underlying libraries does not currently support actual events. Thus on OSx, you get `:removed` if the file recieved does not exist by checking File.file?(the_file). If it does exist you get `:modified`. So you will **not** get any `:added` events on OSx.
43
+ Events on OSx, also known as darwin, is current an approximation as the underlying libraries does not currently support actual events. Thus on OSx, you get `:removed` if the file received does not exist by checking File.file?(the_file). If it does exist you get `:modified`. So you will **not** get any `:added` events on OSx.
44
44
 
45
- Feather Watch will recieve very many file events, even for temp files. Care should be taken when handling the events. Make sure to only process what you need. For instance, you should check against temp-files, and skip those events. Example:
45
+ Feather Watch will receive very many file events, even for temp files. Care should be taken when handling the events. Make sure to only process what you need. For instance, you should check against temp-files, and skip those events. Example:
46
46
 
47
47
  #black list approach
48
48
  un_accepted_file_types = ["tmp", "cache", "db"]
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = FeatherWatch::VERSION
9
9
  spec.authors = ["Stephan Nordnes Eriksen"]
10
10
  spec.email = ["stephanruler@gmail.com"]
11
- spec.summary = %q{Barebones, simple, and fast file system watcher}
11
+ spec.summary = %q{Barebones, simple, and fast Ruby file system watcher}
12
12
  spec.description = %q{A barebones file system watcher which uses native file system events for Linux, OSx, and Windows.}
13
13
  spec.homepage = "https://github.com/stephan-nordnes-eriksen/feather_watch"
14
14
  spec.license = "MIT"
@@ -1,7 +1,8 @@
1
1
  module FeatherWatch::Core
2
2
  class DarwinWatcher
3
- def initialize(directories, callback, verbose= false)
3
+ def initialize(directories, callback, verbose= false, silence_exceptions= false)
4
4
  @verbose = verbose
5
+ @silence_exceptions = silence_exceptions
5
6
  puts "Initializing mac watcher" if @verbose
6
7
  @fs_event = FSEvent.new
7
8
  options = { :no_defer => true,
@@ -9,12 +10,21 @@ module FeatherWatch::Core
9
10
 
10
11
  @fs_event.watch directories, options do |changed_files|
11
12
  changed_files.each do |f|
12
- if File.file?(f)
13
- puts "Change on file: #{f}" if @verbose
14
- callback.call({status: :modified, file: f})
15
- else
16
- puts "Removed file: #{f}" if @verbose
17
- callback.call({status: :removed, file: f})
13
+ begin
14
+ if File.file?(f)
15
+ puts "Change on file: #{f}" if @verbose
16
+ callback.call({status: :modified, file: f, event: f})
17
+ else
18
+ puts "Removed file: #{f}" if @verbose
19
+ callback.call({status: :removed, file: f, event: f})
20
+ end
21
+ rescue Exception => e
22
+ unless @silence_exceptions
23
+ STDERR.puts "----------------------------"
24
+ STDERR.puts "Error in Feather Watch callback"
25
+ STDERR.puts "Message: #{e.message}"
26
+ STDERR.puts "backtrace: #{e.backtrace * "\n\t >"}"
27
+ end
18
28
  end
19
29
  end
20
30
  end
@@ -1,33 +1,44 @@
1
1
  module FeatherWatch::Core
2
2
  class LinuxWatcher
3
- def initialize(directories, callback, verbose= false)
3
+ def initialize(directories, callback, verbose= false, silence_exceptions= false)
4
4
  @verbose = verbose
5
+ @silence_exceptions = silence_exceptions
5
6
  puts "Initializing linux watcher" if @verbose
6
7
  @notifiers = []
8
+ directories = [directories] if directories.is_a?(String)
7
9
  directories.each do |dir|
8
10
  notifier = INotify::Notifier.new
9
11
  @notifiers << notifier
10
12
  #Avaliable events: :access, :attrib, :close_write, :close_nowrite, :create, :delete, :delete_self, :ignored, :modify, :move_self, :moved_from, :moved_to, :open
11
- notifier.watch(dir, :create, :attrib, :delete, :close_write, :delete_self, :modify, :move_self, :moved_from, :moved_to) do |event|
13
+ notifier.watch(dir, :recursive, :create, :attrib, :delete, :close_write, :delete_self, :modify, :move_self, :moved_from, :moved_to) do |event|
12
14
  #TODO: This information is probably in the event, but I'm on a mac now, so I can't test it properly
13
15
 
14
- if !([:attrib, :close_write, :modify] & event.flags ).empty?
15
- puts "Change on file: #{event.absolute_name}" if @verbose
16
- callback.call({status: :modified, file: event.absolute_name})
17
- elsif !([:moved_to] & event.flags ).empty?
18
- puts "File added: #{event.absolute_name}" if @verbose
19
- callback.call({status: :added, file: event.absolute_name})
20
- elsif !([:moved_from] & event.flags ).empty?
21
- puts "File removed: #{event.absolute_name}" if @verbose
22
- callback.call({status: :removed, file: event.absolute_name})
23
- elsif !([:create] & event.flags ).empty?
24
- puts "File added: #{event.absolute_name}" if @verbose
25
- callback.call({status: :added, file: event.absolute_name})
26
- elsif !([:delete, :delete_self] & event.flags ).empty?
27
- puts "File removed: #{event.absolute_name}" if @verbose
28
- callback.call({status: :removed, file: event.absolute_name})
29
- else
30
- puts "Unhandled status flags: #{event.flags} for file #{event.absolute_name}" if @verbose
16
+ begin
17
+ if !([:attrib, :close_write, :modify] & event.flags ).empty?
18
+ puts "Change on file: #{event.absolute_name}" if @verbose
19
+ callback.call({status: :modified, file: event.absolute_name, event: event})
20
+ elsif !([:moved_to] & event.flags ).empty?
21
+ puts "File added: #{event.absolute_name}" if @verbose
22
+ callback.call({status: :added, file: event.absolute_name, event: event})
23
+ elsif !([:moved_from] & event.flags ).empty?
24
+ puts "File removed: #{event.absolute_name}" if @verbose
25
+ callback.call({status: :removed, file: event.absolute_name, event: event})
26
+ elsif !([:create] & event.flags ).empty?
27
+ puts "File added: #{event.absolute_name}" if @verbose
28
+ callback.call({status: :added, file: event.absolute_name, event: event})
29
+ elsif !([:delete, :delete_self] & event.flags ).empty?
30
+ puts "File removed: #{event.absolute_name}" if @verbose
31
+ callback.call({status: :removed, file: event.absolute_name, event: event})
32
+ else
33
+ STDERR.puts "Unhandled status flags: #{event.flags} for file #{event.absolute_name}" if @verbose
34
+ end
35
+ rescue Exception => e
36
+ unless @silence_exceptions
37
+ STDERR.puts "----------------------------"
38
+ STDERR.puts "Error in Feather Watch callback"
39
+ STDERR.puts "Message: #{e.message}"
40
+ STDERR.puts "backtrace: #{e.backtrace * "\n\t >"}"
41
+ end
31
42
  end
32
43
  end
33
44
  end
@@ -1,27 +1,38 @@
1
1
  module FeatherWatch::Core
2
2
  class WindowsWatcher
3
- def initialize(directories, callback, verbose= false)
3
+ def initialize(directories, callback, verbose= false, silence_exceptions= false)
4
4
  @verbose = verbose
5
+ @silence_exceptions = silence_exceptions
5
6
  puts "Initializing windows watcher" if @verbose
6
7
  @monitors = []
8
+ directories = [directories] if directories.is_a?(String)
7
9
  directories.each do |dir|
8
10
  monitor = WDM::Monitor.new
9
11
  @monitors << monitor
10
12
  monitor.watch_recursively(dir, :files) do |change|
11
13
  #TODO: Have not tested this. It should work
12
14
 
13
- case change.type
14
- when :added, :renamed_new_file
15
- puts "File added: #{change.path}" if @verbose
16
- callback.call({status: :added, file: change.path})
17
- when :removed, :renamed_old_file
18
- puts "Removed file: #{change.path}" if @verbose
19
- callback.call({status: :removed, file: change.path})
20
- when :modified, :attrib
21
- puts "File modified: #{change.path}" if @verbose
22
- callback.call({status: :modified, file: change.path})
23
- else
24
- puts "Unhandled status type: #{change.type} for file #{change.path}" if @verbose
15
+ begin
16
+ case change.type
17
+ when :added, :renamed_new_file
18
+ puts "File added: #{change.path}" if @verbose
19
+ callback.call({status: :added, file: change.path, event: change})
20
+ when :removed, :renamed_old_file
21
+ puts "Removed file: #{change.path}" if @verbose
22
+ callback.call({status: :removed, file: change.path, event: change})
23
+ when :modified, :attrib
24
+ puts "File modified: #{change.path}" if @verbose
25
+ callback.call({status: :modified, file: change.path, event: change})
26
+ else
27
+ STDERR.puts "Unhandled status type: #{change.type} for file #{change.path}" if @verbose
28
+ end
29
+ rescue Exception => e
30
+ unless @silence_exceptions
31
+ STDERR.puts "----------------------------"
32
+ STDERR.puts "Error in Feather Watch callback"
33
+ STDERR.puts "Message: #{e.message}"
34
+ STDERR.puts "backtrace: #{e.backtrace * "\n\t >"}"
35
+ end
25
36
  end
26
37
  end
27
38
  end
@@ -1,3 +1,3 @@
1
1
  module FeatherWatch
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -12,15 +12,19 @@ module FeatherWatch
12
12
  # FeatherWatch::Watcher.new([File.join(Dir.home, 'Desktop')], lambda{|e| puts "got event with status: #{e[:status]} on file #{e[:file]}"})
13
13
  #
14
14
  # Returns a Watcher object.
15
- def initialize(directories, callback, verbose= false)
15
+ def initialize(directories, callback, verbose= false, silence_exceptions= false)
16
16
  @verbose = verbose
17
17
  dir = directories
18
18
  dir = [directories] if directories.is_a?(String)
19
19
  raise "Unknown datatype for directories. Was: #{dir}" unless dir.is_a?(Array)
20
20
 
21
- @listener = FeatherWatch::Core::DarwinWatcher.new(dir, callback, verbose) if FeatherWatch::OS.mac?
22
- @listener = FeatherWatch::Core::LinuxWatcher.new(dir, callback, verbose) if FeatherWatch::OS.linux?
23
- @listener = FeatherWatch::Core::WindowsWatcher.new(dir, callback, verbose) if FeatherWatch::OS.windows?
21
+ dir.each do |d|
22
+ raise "Not a vaild directory: #{d}" unless File.directory?(d)
23
+ end
24
+
25
+ @listener = FeatherWatch::Core::DarwinWatcher.new(dir, callback, verbose, silence_exceptions) if FeatherWatch::OS.mac?
26
+ @listener = FeatherWatch::Core::LinuxWatcher.new(dir, callback, verbose, silence_exceptions) if FeatherWatch::OS.linux?
27
+ @listener = FeatherWatch::Core::WindowsWatcher.new(dir, callback, verbose, silence_exceptions) if FeatherWatch::OS.windows?
24
28
  end
25
29
 
26
30
  # Public: Starts the watcher.
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ class FSEvent
4
+ end
5
+
6
+ describe FeatherWatch::Core::DarwinWatcher do
7
+ after(:each) do
8
+ FileUtils.rm_rf(File.join(Dir.pwd, "test_folder"))
9
+ end
10
+ describe ".initialize" do
11
+ it "catches exceptions in user callback and print to STDERR" do
12
+ fse_spy = spy("FSEvent spy")
13
+ expect(FSEvent).to receive(:new).and_return(fse_spy)
14
+
15
+ path = File.join(Dir.pwd, "test_folder")
16
+ file_path = File.join(Dir.pwd, "test_folder", "new_file")
17
+ callback_spy = spy("Callback Spy")
18
+ verbose = false
19
+ silence_exceptions = false
20
+
21
+ the_callback = nil
22
+ expect(fse_spy).to receive(:watch) do |watch_paths, options=nil, &block|
23
+ the_callback = block
24
+ expect(watch_paths).to eq(path)
25
+ end
26
+
27
+
28
+ expect(callback_spy).to receive(:call).with({status: :removed ,file: file_path, event: anything}).and_raise("some error")
29
+ expect(STDERR).to receive(:puts).exactly(4).times.with(kind_of(String))
30
+
31
+
32
+ watcher = FeatherWatch::Core::DarwinWatcher.new(path,callback_spy,verbose, silence_exceptions)
33
+ watcher.start
34
+
35
+ expect{the_callback.call([file_path])}.to_not raise_error
36
+
37
+ watcher.stop
38
+ end
39
+ it "executes callback with :removed if file does not exist" do
40
+ fse_spy = spy("FSEvent spy")
41
+ expect(FSEvent).to receive(:new).and_return(fse_spy)
42
+
43
+ path = File.join(Dir.pwd, "test_folder")
44
+ file_path = File.join(Dir.pwd, "test_folder", "new_file")
45
+ callback_spy = spy("Callback Spy")
46
+ verbose = false
47
+ silence_exceptions = true
48
+
49
+ the_callback = nil
50
+ expect(fse_spy).to receive(:watch) do |watch_paths, options=nil, &block|
51
+ the_callback = block
52
+ expect(watch_paths).to eq(path)
53
+ end
54
+
55
+
56
+ expect(callback_spy).to receive(:call).with({status: :removed ,file: file_path, event: anything})
57
+ expect(STDERR).to_not receive(:puts)
58
+
59
+
60
+ watcher = FeatherWatch::Core::DarwinWatcher.new(path,callback_spy,verbose, silence_exceptions)
61
+ watcher.start
62
+
63
+ expect{the_callback.call([file_path])}.to_not raise_error
64
+
65
+ watcher.stop
66
+ end
67
+
68
+ it "executes callback with :modified if file exist" do
69
+ fse_spy = spy("FSEvent spy")
70
+ expect(FSEvent).to receive(:new).and_return(fse_spy)
71
+
72
+ path = File.join(Dir.pwd, "test_folder")
73
+ file_path = File.join(Dir.pwd, "test_folder", "new_file")
74
+ callback_spy = spy("Callback Spy")
75
+ verbose = false
76
+ silence_exceptions = true
77
+
78
+ the_callback = nil
79
+ expect(fse_spy).to receive(:watch) do |watch_paths, options=nil, &block|
80
+ the_callback = block
81
+ expect(watch_paths).to eq(path)
82
+ end
83
+
84
+
85
+ expect(callback_spy).to receive(:call).with({status: :modified ,file: file_path, event: anything})
86
+ expect(STDERR).to_not receive(:puts)
87
+
88
+ FileUtils.mkdir(path)
89
+ FileUtils.touch(file_path)
90
+ sleep 0.1
91
+
92
+ watcher = FeatherWatch::Core::DarwinWatcher.new(path,callback_spy,verbose, silence_exceptions)
93
+ watcher.start
94
+
95
+ expect{the_callback.call([file_path])}.to_not raise_error
96
+
97
+ watcher.stop
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,396 @@
1
+ require 'spec_helper'
2
+
3
+ module INotify
4
+ end
5
+ class INotify::Notifier
6
+ end
7
+
8
+ describe FeatherWatch::Core::LinuxWatcher do
9
+
10
+ let(:path) {File.join(Dir.pwd, "test_folder")}
11
+ let(:file_path) {File.join(Dir.pwd, "test_folder", "new_file")}
12
+
13
+ after(:each) do
14
+ FileUtils.rm_rf(File.join(Dir.pwd, "test_folder"))
15
+ end
16
+ describe ".initialize" do
17
+ it "catches exceptions in user callback and print to STDERR" do
18
+ inotify_spy = spy("inotify spy")
19
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
20
+
21
+ callback_spy = spy("Callback Spy")
22
+ verbose = false
23
+ silence_exceptions = false
24
+
25
+ the_callback = nil
26
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
27
+ the_callback = callback
28
+ expect(watch_path).to eq(path)
29
+ end
30
+
31
+
32
+ expect(callback_spy).to receive(:call).with({status: :removed ,file: file_path, event: anything}).and_raise("some error")
33
+ expect(STDERR).to receive(:puts).exactly(4).times.with(kind_of(String))
34
+
35
+
36
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
37
+ watcher.start
38
+
39
+ event_spy = spy("Event spy")
40
+ allow(event_spy).to receive(:flags).and_return([:delete])
41
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
42
+ expect{the_callback.call(event_spy)}.to_not raise_error
43
+
44
+ watcher.stop
45
+ end
46
+ it "executes callback with :removed if file does not exist" do
47
+ inotify_spy = spy("inotify spy")
48
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
49
+
50
+ callback_spy = spy("Callback Spy")
51
+ verbose = false
52
+ silence_exceptions = true
53
+
54
+ the_callback = nil
55
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
56
+ the_callback = callback
57
+ expect(watch_path).to eq(path)
58
+ end
59
+
60
+
61
+ expect(callback_spy).to receive(:call).with({status: :removed ,file: file_path, event: anything})
62
+ expect(STDERR).to_not receive(:puts)
63
+
64
+
65
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
66
+ watcher.start
67
+
68
+ event_spy = spy("Event spy")
69
+ allow(event_spy).to receive(:flags).and_return([:delete])
70
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
71
+ expect{the_callback.call(event_spy)}.to_not raise_error
72
+
73
+ watcher.stop
74
+ end
75
+
76
+ it "executes callback with :modified if file exist" do
77
+ inotify_spy = spy("inotify spy")
78
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
79
+
80
+ callback_spy = spy("Callback Spy")
81
+ verbose = false
82
+ silence_exceptions = true
83
+
84
+ the_callback = nil
85
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
86
+ the_callback = callback
87
+ expect(watch_path).to eq(path)
88
+ end
89
+
90
+
91
+ expect(callback_spy).to receive(:call).with({status: :added ,file: file_path, event: anything})
92
+ expect(STDERR).to_not receive(:puts)
93
+
94
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
95
+ watcher.start
96
+
97
+ event_spy = spy("Event spy")
98
+ allow(event_spy).to receive(:flags).and_return([:create])
99
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
100
+ expect{the_callback.call(event_spy)}.to_not raise_error
101
+
102
+ watcher.stop
103
+ end
104
+
105
+
106
+
107
+ it "inotify-event with :attrib produces :modified FeatherWatch-event" do
108
+ inotify_spy = spy("inotify spy")
109
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
110
+
111
+ callback_spy = spy("Callback Spy")
112
+ verbose = false
113
+ silence_exceptions = true
114
+
115
+ the_callback = nil
116
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
117
+ the_callback = callback
118
+ expect(watch_path).to eq(path)
119
+ end
120
+
121
+
122
+ expect(callback_spy).to receive(:call).with({status: :modified ,file: file_path, event: anything})
123
+ expect(STDERR).to_not receive(:puts)
124
+
125
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
126
+ watcher.start
127
+
128
+ event_spy = spy("Event spy")
129
+ allow(event_spy).to receive(:flags).and_return([:attrib])
130
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
131
+ the_callback.call(event_spy)
132
+
133
+ watcher.stop
134
+ end
135
+ it "inotify-event with :close_write produces :modified FeatherWatch-event" do
136
+ inotify_spy = spy("inotify spy")
137
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
138
+
139
+ callback_spy = spy("Callback Spy")
140
+ verbose = false
141
+ silence_exceptions = true
142
+
143
+ the_callback = nil
144
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
145
+ the_callback = callback
146
+ expect(watch_path).to eq(path)
147
+ end
148
+
149
+
150
+ expect(callback_spy).to receive(:call).with({status: :modified ,file: file_path, event: anything})
151
+ expect(STDERR).to_not receive(:puts)
152
+
153
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
154
+ watcher.start
155
+
156
+ event_spy = spy("Event spy")
157
+ allow(event_spy).to receive(:flags).and_return([:close_write])
158
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
159
+ the_callback.call(event_spy)
160
+
161
+ watcher.stop
162
+ end
163
+ it "inotify-event with :modify produces :modified FeatherWatch-event" do
164
+ inotify_spy = spy("inotify spy")
165
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
166
+
167
+ callback_spy = spy("Callback Spy")
168
+ verbose = false
169
+ silence_exceptions = true
170
+
171
+ the_callback = nil
172
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
173
+ the_callback = callback
174
+ expect(watch_path).to eq(path)
175
+ end
176
+
177
+
178
+ expect(callback_spy).to receive(:call).with({status: :modified ,file: file_path, event: anything})
179
+ expect(STDERR).to_not receive(:puts)
180
+
181
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
182
+ watcher.start
183
+
184
+ event_spy = spy("Event spy")
185
+ allow(event_spy).to receive(:flags).and_return([:modify])
186
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
187
+ the_callback.call(event_spy)
188
+
189
+ watcher.stop
190
+ end
191
+
192
+
193
+ it "inotify-event with :moved_to produces :added FeatherWatch-event" do
194
+ inotify_spy = spy("inotify spy")
195
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
196
+
197
+ callback_spy = spy("Callback Spy")
198
+ verbose = false
199
+ silence_exceptions = true
200
+
201
+ the_callback = nil
202
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
203
+ the_callback = callback
204
+ expect(watch_path).to eq(path)
205
+ end
206
+
207
+
208
+ expect(callback_spy).to receive(:call).with({status: :added ,file: file_path, event: anything})
209
+ expect(STDERR).to_not receive(:puts)
210
+
211
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
212
+ watcher.start
213
+
214
+ event_spy = spy("Event spy")
215
+ allow(event_spy).to receive(:flags).and_return([:moved_to])
216
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
217
+ the_callback.call(event_spy)
218
+
219
+ watcher.stop
220
+ end
221
+
222
+ it "inotify-event with :moved_from produces :removed FeatherWatch-event" do
223
+ inotify_spy = spy("inotify spy")
224
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
225
+
226
+ callback_spy = spy("Callback Spy")
227
+ verbose = false
228
+ silence_exceptions = true
229
+
230
+ the_callback = nil
231
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
232
+ the_callback = callback
233
+ expect(watch_path).to eq(path)
234
+ end
235
+
236
+
237
+ expect(callback_spy).to receive(:call).with({status: :removed ,file: file_path, event: anything})
238
+ expect(STDERR).to_not receive(:puts)
239
+
240
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
241
+ watcher.start
242
+
243
+ event_spy = spy("Event spy")
244
+ allow(event_spy).to receive(:flags).and_return([:moved_from])
245
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
246
+ the_callback.call(event_spy)
247
+
248
+ watcher.stop
249
+ end
250
+
251
+ it "inotify-event with :create produces :added FeatherWatch-event" do
252
+ inotify_spy = spy("inotify spy")
253
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
254
+
255
+ callback_spy = spy("Callback Spy")
256
+ verbose = false
257
+ silence_exceptions = true
258
+
259
+ the_callback = nil
260
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
261
+ the_callback = callback
262
+ expect(watch_path).to eq(path)
263
+ end
264
+
265
+
266
+ expect(callback_spy).to receive(:call).with({status: :added ,file: file_path, event: anything})
267
+ expect(STDERR).to_not receive(:puts)
268
+
269
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
270
+ watcher.start
271
+
272
+ event_spy = spy("Event spy")
273
+ allow(event_spy).to receive(:flags).and_return([:create])
274
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
275
+ the_callback.call(event_spy)
276
+
277
+ watcher.stop
278
+ end
279
+
280
+ it "inotify-event with :delete produces :removed FeatherWatch-event" do
281
+ inotify_spy = spy("inotify spy")
282
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
283
+
284
+ callback_spy = spy("Callback Spy")
285
+ verbose = false
286
+ silence_exceptions = true
287
+
288
+ the_callback = nil
289
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
290
+ the_callback = callback
291
+ expect(watch_path).to eq(path)
292
+ end
293
+
294
+
295
+ expect(callback_spy).to receive(:call).with({status: :removed ,file: file_path, event: anything})
296
+ expect(STDERR).to_not receive(:puts)
297
+
298
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
299
+ watcher.start
300
+
301
+ event_spy = spy("Event spy")
302
+ allow(event_spy).to receive(:flags).and_return([:delete])
303
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
304
+ the_callback.call(event_spy)
305
+
306
+ watcher.stop
307
+ end
308
+ it "inotify-event with :delete_self produces :removed FeatherWatch-event" do
309
+ inotify_spy = spy("inotify spy")
310
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
311
+
312
+ callback_spy = spy("Callback Spy")
313
+ verbose = false
314
+ silence_exceptions = true
315
+
316
+ the_callback = nil
317
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
318
+ the_callback = callback
319
+ expect(watch_path).to eq(path)
320
+ end
321
+
322
+
323
+ expect(callback_spy).to receive(:call).with({status: :removed ,file: file_path, event: anything})
324
+ expect(STDERR).to_not receive(:puts)
325
+
326
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
327
+ watcher.start
328
+
329
+ event_spy = spy("Event spy")
330
+ allow(event_spy).to receive(:flags).and_return([:delete_self])
331
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
332
+ the_callback.call(event_spy)
333
+
334
+ watcher.stop
335
+ end
336
+
337
+ it "Prints error to STDERR when no event flags and verbose" do
338
+ inotify_spy = spy("inotify spy")
339
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
340
+ allow(STDOUT).to receive(:puts)
341
+
342
+ callback_spy = spy("Callback Spy")
343
+ verbose = true
344
+ silence_exceptions = true
345
+
346
+ the_callback = nil
347
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
348
+ the_callback = callback
349
+ expect(watch_path).to eq(path)
350
+ end
351
+
352
+
353
+ expect(callback_spy).to_not receive(:call)
354
+ expect(STDERR).to receive(:puts).exactly(1).times.with(kind_of(String))
355
+
356
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
357
+ watcher.start
358
+
359
+ event_spy = spy("Event spy")
360
+ allow(event_spy).to receive(:flags).and_return([])
361
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
362
+ the_callback.call(event_spy)
363
+
364
+ watcher.stop
365
+ end
366
+ it "Does not print to STDERR when no event flags and not verbose" do
367
+ inotify_spy = spy("inotify spy")
368
+ expect(INotify::Notifier).to receive(:new).and_return(inotify_spy)
369
+
370
+ callback_spy = spy("Callback Spy")
371
+ verbose = false
372
+ silence_exceptions = true
373
+
374
+ the_callback = nil
375
+ expect(inotify_spy).to receive(:watch) do |watch_path, *flags, &callback|
376
+ the_callback = callback
377
+ expect(watch_path).to eq(path)
378
+ end
379
+
380
+
381
+ expect(callback_spy).to_not receive(:call)
382
+ expect(STDERR).to_not receive(:puts)
383
+
384
+ watcher = FeatherWatch::Core::LinuxWatcher.new(path,callback_spy,verbose, silence_exceptions)
385
+ watcher.start
386
+
387
+ event_spy = spy("Event spy")
388
+ allow(event_spy).to receive(:flags).and_return([])
389
+ allow(event_spy).to receive(:absolute_name).and_return(file_path)
390
+ the_callback.call(event_spy)
391
+
392
+ watcher.stop
393
+ end
394
+ end
395
+
396
+ end