filewatcher 1.0.1 → 2.0.0.beta3

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.
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../lib/filewatcher/runner'
4
-
5
- describe Filewatcher::Runner do
6
- before do
7
- @init = proc do |filename|
8
- Filewatcher::Runner.new(filename)
9
- end
10
- end
11
-
12
- describe '#initialize' do
13
- it 'should recieve filename' do
14
- -> { @init.call('file.txt') }
15
- .should.not.raise ArgumentError
16
- end
17
- end
18
-
19
- describe '#command' do
20
- it 'should return correct command for file with .py extension' do
21
- @init.call('file.py').command
22
- .should.equal 'env python file.py'
23
- end
24
-
25
- it 'should return correct command for file with .js extension' do
26
- @init.call('file.js').command
27
- .should.equal 'env node file.js'
28
- end
29
-
30
- it 'should return correct command for file with .rb extension' do
31
- @init.call('file.rb').command
32
- .should.equal 'env ruby file.rb'
33
- end
34
-
35
- it 'should return correct command for file with .pl extension' do
36
- @init.call('file.pl').command
37
- .should.equal 'env perl file.pl'
38
- end
39
-
40
- it 'should return correct command for file with .awk extension' do
41
- @init.call('file.awk').command
42
- .should.equal 'env awk file.awk'
43
- end
44
-
45
- it 'should return correct command for file with .php extension' do
46
- @init.call('file.php').command
47
- .should.equal 'env php file.php'
48
- end
49
-
50
- it 'should return correct command for file with .phtml extension' do
51
- @init.call('file.phtml').command
52
- .should.equal 'env php file.phtml'
53
- end
54
-
55
- it 'should return correct command for file with .php4 extension' do
56
- @init.call('file.php4').command
57
- .should.equal 'env php file.php4'
58
- end
59
-
60
- it 'should return correct command for file with .php3 extension' do
61
- @init.call('file.php3').command
62
- .should.equal 'env php file.php3'
63
- end
64
-
65
- it 'should return correct command for file with .php5 extension' do
66
- @init.call('file.php5').command
67
- .should.equal 'env php file.php5'
68
- end
69
-
70
- it 'should return correct command for file with .phps extension' do
71
- @init.call('file.phps').command
72
- .should.equal 'env php file.phps'
73
- end
74
- end
75
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../lib/filewatcher/version'
4
-
5
- describe Filewatcher::VERSION do
6
- it 'should exist as constant' do
7
- Filewatcher.const_defined?(:VERSION).should.be.true
8
- end
9
-
10
- it 'should be an instance of String' do
11
- Filewatcher::VERSION.class.should.equal String
12
- end
13
- end
data/test/helper.rb DELETED
@@ -1,216 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bacon'
4
- require 'bacon/custom_matchers_messages'
5
-
6
- begin
7
- require 'pry-byebug'
8
- rescue LoadError
9
- nil
10
- end
11
-
12
- class WatchRun
13
- TMP_DIR = File.join(__dir__, 'tmp')
14
-
15
- attr_reader :filename
16
-
17
- def initialize(
18
- filename: 'tmp_file.txt',
19
- directory: false,
20
- action: :update
21
- )
22
- @filename =
23
- filename.start_with?('/', '~') ? filename : File.join(TMP_DIR, filename)
24
- @directory = directory
25
- @action = action
26
- end
27
-
28
- def start
29
- File.write(@filename, 'content1') unless @action == :create
30
- end
31
-
32
- def run
33
- start
34
-
35
- make_changes
36
-
37
- stop
38
- end
39
-
40
- def stop
41
- FileUtils.rm_r(@filename) if File.exist?(@filename)
42
- end
43
-
44
- private
45
-
46
- def make_changes
47
- if @action == :delete
48
- FileUtils.remove(@filename)
49
- elsif @directory
50
- FileUtils.mkdir_p(@filename)
51
- else
52
- File.write(@filename, 'content2')
53
- end
54
- end
55
- end
56
-
57
- class RubyWatchRun < WatchRun
58
- attr_reader :filewatcher, :thread, :watched, :processed
59
-
60
- def initialize(
61
- every: false,
62
- filewatcher: Filewatcher.new(
63
- File.join(TMP_DIR, '**', '*'), interval: 0.1, every: every
64
- ),
65
- **args
66
- )
67
- super(**args)
68
- @filewatcher = filewatcher
69
- end
70
-
71
- def start
72
- super
73
- @thread = thread_initialize
74
- # thread needs a chance to start
75
- wait 3 do
76
- filewatcher.keep_watching
77
- end
78
- end
79
-
80
- def stop
81
- thread.exit
82
-
83
- wait 3 do
84
- thread.stop?
85
- end
86
-
87
- super
88
- end
89
-
90
- private
91
-
92
- def make_changes
93
- super
94
-
95
- # Some OS, filesystems and Ruby interpretators
96
- # doesn't catch milliseconds of `File.mtime`
97
- wait 3 do
98
- processed.any?
99
- end
100
- end
101
-
102
- def thread_initialize
103
- @watched ||= 0
104
- Thread.new(
105
- @filewatcher, @processed = []
106
- ) do |filewatcher, processed|
107
- filewatcher.watch do |filename, event|
108
- increment_watched
109
- processed.push([filename, event])
110
- end
111
- end
112
- end
113
-
114
- def increment_watched
115
- @watched += 1
116
- end
117
-
118
- def wait(seconds)
119
- max_count = seconds / filewatcher.interval
120
- count = 0
121
- while count < max_count && !yield
122
- sleep filewatcher.interval
123
- count += 1
124
- end
125
- end
126
- end
127
-
128
- class ShellWatchRun < WatchRun
129
- EXECUTABLE = "#{'ruby ' if Gem.win_platform?}" \
130
- "#{File.realpath File.join(__dir__, '..', 'bin', 'filewatcher')}".freeze
131
-
132
- SLEEP_MULTIPLIER = RUBY_PLATFORM == 'java' ? 5 : 1
133
-
134
- ENV_FILE = File.join(TMP_DIR, 'env')
135
-
136
- def initialize(
137
- options: {},
138
- dumper: :watched,
139
- **args
140
- )
141
- super(**args)
142
- @options = options
143
- @options[:interval] ||= 0.1
144
- @options_string =
145
- @options.map { |key, value| "--#{key}=#{value}" }.join(' ')
146
- @dumper = dumper
147
- end
148
-
149
- def start
150
- super
151
-
152
- @pid = spawn(
153
- "#{EXECUTABLE} #{@options_string} \"#{@filename}\"" \
154
- " \"ruby #{File.join(__dir__, 'dumpers', "#{@dumper}_dumper.rb")}\"",
155
- pgroup: true
156
- )
157
-
158
- Process.detach(@pid)
159
-
160
- wait 12 do
161
- pid_state == 'S' && (!@options[:immediate] || File.exist?(ENV_FILE))
162
- end
163
-
164
- # a little more time
165
- sleep 1 * SLEEP_MULTIPLIER
166
- end
167
-
168
- def stop
169
- ## Problems: https://github.com/thomasfl/filewatcher/pull/83
170
- ## Solution: https://stackoverflow.com/a/45032252/2630849
171
- Process.kill('TERM', -Process.getpgid(@pid))
172
- Process.waitall
173
-
174
- wait 12 do
175
- pid_state.empty?
176
- end
177
-
178
- # a little more time
179
- sleep 1 * SLEEP_MULTIPLIER
180
-
181
- super
182
- end
183
-
184
- private
185
-
186
- def make_changes
187
- super
188
-
189
- wait 12 do
190
- File.exist?(ENV_FILE)
191
- end
192
- end
193
-
194
- def pid_state
195
- ## For macOS output:
196
- ## https://travis-ci.org/thomasfl/filewatcher/jobs/304433538
197
- `ps -ho state -p #{@pid}`.sub('STAT', '').strip
198
- end
199
-
200
- def wait(seconds)
201
- max_count = seconds / @options[:interval]
202
- count = 0
203
- while count < max_count && !yield
204
- sleep @options[:interval]
205
- count += 1
206
- end
207
- end
208
- end
209
-
210
- custom_matcher :include_all_files do |obj, elements|
211
- elements.all? { |element| obj.include? File.expand_path(element) }
212
- end
213
-
214
- def dump_to_env_file(content)
215
- File.write File.join(ShellWatchRun::ENV_FILE), content
216
- end
@@ -1,340 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'fileutils'
4
- require_relative '../lib/filewatcher'
5
-
6
- describe Filewatcher do
7
- before do
8
- FileUtils.mkdir_p WatchRun::TMP_DIR
9
- end
10
-
11
- after do
12
- FileUtils.rm_r WatchRun::TMP_DIR
13
-
14
- interval = 0.1
15
- wait = 5
16
- count = 0
17
- while File.exist?(WatchRun::TMP_DIR) && count < (wait / interval)
18
- sleep interval
19
- end
20
- end
21
-
22
- describe '#initialize' do
23
- it 'should exclude selected file patterns' do
24
- wr = RubyWatchRun.new(
25
- filewatcher: Filewatcher.new(
26
- File.expand_path('test/tmp/**/*'),
27
- exclude: File.expand_path('test/tmp/**/*.txt')
28
- )
29
- )
30
-
31
- wr.run
32
-
33
- wr.processed.should.be.empty
34
- end
35
-
36
- it 'should handle absolute paths with globs' do
37
- wr = RubyWatchRun.new(
38
- filewatcher: Filewatcher.new(
39
- File.expand_path('test/tmp/**/*')
40
- )
41
- )
42
-
43
- wr.run
44
-
45
- wr.processed.should.equal(
46
- [[wr.filename, :updated]]
47
- )
48
- end
49
-
50
- it 'should handle globs' do
51
- wr = RubyWatchRun.new(
52
- filewatcher: Filewatcher.new('test/tmp/**/*')
53
- )
54
-
55
- wr.run
56
-
57
- wr.processed.should.equal(
58
- [[wr.filename, :updated]]
59
- )
60
- end
61
-
62
- it 'should handle explicit relative paths with globs' do
63
- wr = RubyWatchRun.new(
64
- filewatcher: Filewatcher.new('./test/tmp/**/*')
65
- )
66
-
67
- wr.run
68
-
69
- wr.processed.should.equal(
70
- [[wr.filename, :updated]]
71
- )
72
- end
73
-
74
- it 'should handle explicit relative paths' do
75
- wr = RubyWatchRun.new(
76
- filewatcher: Filewatcher.new('./test/tmp')
77
- )
78
-
79
- wr.run
80
-
81
- wr.processed.should.equal(
82
- [[wr.filename, :updated]]
83
- )
84
- end
85
-
86
- it 'should handle tilde expansion' do
87
- filename = File.expand_path('~/file_watcher_1.txt')
88
-
89
- wr = RubyWatchRun.new(
90
- filename: filename,
91
- filewatcher: Filewatcher.new('~/file_watcher_1.txt')
92
- )
93
-
94
- wr.run
95
-
96
- wr.processed.should.equal(
97
- [[filename, :updated]]
98
- )
99
- end
100
-
101
- it 'should immediately run with corresponding option' do
102
- wr = RubyWatchRun.new(
103
- filewatcher: Filewatcher.new('**/*', immediate: true)
104
- )
105
-
106
- wr.start
107
- wr.stop
108
-
109
- wr.processed.should.equal [['', '']]
110
- wr.watched.should.be > 0
111
- end
112
-
113
- it 'should not be executed without immediate option and changes' do
114
- wr = RubyWatchRun.new(
115
- filewatcher: Filewatcher.new('**/*', immediate: false)
116
- )
117
-
118
- wr.start
119
- wr.stop
120
-
121
- wr.processed.should.be.empty
122
- wr.watched.should.equal 0
123
- end
124
- end
125
-
126
- describe '#watch' do
127
- it 'should detect file deletions' do
128
- wr = RubyWatchRun.new(action: :delete)
129
-
130
- wr.run
131
-
132
- wr.processed.should.equal(
133
- [[wr.filename, :deleted]]
134
- )
135
- end
136
-
137
- it 'should detect file additions' do
138
- wr = RubyWatchRun.new(action: :create)
139
-
140
- wr.run
141
-
142
- wr.processed.should.equal(
143
- [[wr.filename, :created]]
144
- )
145
- end
146
-
147
- it 'should detect file updates' do
148
- wr = RubyWatchRun.new(action: :update)
149
-
150
- wr.run
151
-
152
- wr.processed.should.equal(
153
- [[wr.filename, :updated]]
154
- )
155
- end
156
-
157
- it 'should detect new files in subfolders' do
158
- FileUtils.mkdir_p subfolder = File.expand_path('test/tmp/new_sub_folder')
159
-
160
- wr = RubyWatchRun.new(
161
- filename: File.join(subfolder, 'file.txt'),
162
- action: :create,
163
- every: true
164
- )
165
- wr.run
166
- wr.processed.should.equal(
167
- [
168
- [subfolder, :updated],
169
- [wr.filename, :created]
170
- ]
171
- )
172
- end
173
-
174
- it 'should detect new subfolders' do
175
- subfolder = 'new_sub_folder'
176
-
177
- wr = RubyWatchRun.new(
178
- filename: subfolder,
179
- directory: true,
180
- action: :create
181
- )
182
-
183
- wr.run
184
-
185
- wr.processed.should.equal(
186
- [[wr.filename, :created]]
187
- )
188
- end
189
- end
190
-
191
- describe '#stop' do
192
- it 'should work' do
193
- wr = RubyWatchRun.new
194
-
195
- wr.start
196
-
197
- wr.filewatcher.stop
198
-
199
- # Proves thread successfully joined
200
- wr.thread.join.should.equal wr.thread
201
- end
202
- end
203
-
204
- describe '#pause, #resume' do
205
- it 'should work' do
206
- wr = RubyWatchRun.new(action: :create, every: true)
207
-
208
- wr.start
209
-
210
- wr.filewatcher.pause
211
-
212
- (1..4).each do |n|
213
- File.write("test/tmp/file#{n}.txt", "content#{n}")
214
- end
215
- sleep 0.2 # Give filewatcher time to respond
216
-
217
- # update block should not have been called
218
- wr.processed.should.be.empty
219
-
220
- wr.filewatcher.resume
221
- sleep 0.2 # Give filewatcher time to respond
222
-
223
- # update block still should not have been called
224
- wr.processed.should.be.empty
225
-
226
- added_files = (5..7).to_a.map do |n|
227
- File.write(file = "test/tmp/file#{n}.txt", "content#{n}")
228
- file
229
- end
230
- sleep 0.2 # Give filewatcher time to respond
231
-
232
- wr.filewatcher.stop
233
- wr.stop
234
- wr.processed.map(&:first).should include_all_files(added_files)
235
- end
236
- end
237
-
238
- describe '#finalize' do
239
- it 'should process all remaining changes' do
240
- wr = RubyWatchRun.new(action: :create, every: true)
241
-
242
- wr.start
243
-
244
- wr.filewatcher.stop
245
- wr.thread.join
246
-
247
- added_files = (1..4).to_a.map do |n|
248
- File.write(file = "test/tmp/file#{n}.txt", "content#{n}")
249
- file
250
- end
251
-
252
- wr.filewatcher.finalize
253
-
254
- wr.processed.map(&:first).should include_all_files(added_files)
255
- end
256
- end
257
-
258
- describe 'executable' do
259
- tmp_dir = ShellWatchRun::TMP_DIR
260
-
261
- it 'should run' do
262
- null_output = Gem.win_platform? ? 'NUL' : '/dev/null'
263
- system("#{ShellWatchRun::EXECUTABLE} > #{null_output}")
264
- .should.be.true
265
- end
266
-
267
- it 'should set correct ENV variables for file creation' do
268
- filename = 'foo.txt'
269
-
270
- swr = ShellWatchRun.new(
271
- filename: filename,
272
- action: :create,
273
- dumper: :env
274
- )
275
-
276
- swr.run
277
-
278
- File.read(ShellWatchRun::ENV_FILE)
279
- .should.equal(
280
- %W[
281
- #{tmp_dir}/#{filename}
282
- #{filename}
283
- created
284
- #{tmp_dir}
285
- #{tmp_dir}/#{filename}
286
- test/tmp/#{filename}
287
- ].join(', ')
288
- )
289
- end
290
-
291
- it 'should set correct ENV variables for file deletion' do
292
- filename = 'foo.txt'
293
-
294
- swr = ShellWatchRun.new(
295
- filename: filename,
296
- action: :delete,
297
- dumper: :env
298
- )
299
-
300
- swr.run
301
-
302
- File.read(ShellWatchRun::ENV_FILE)
303
- .should.equal(
304
- %W[
305
- #{tmp_dir}/#{filename}
306
- #{filename}
307
- deleted
308
- #{tmp_dir}
309
- #{tmp_dir}/#{filename}
310
- test/tmp/#{filename}
311
- ].join(', ')
312
- )
313
- end
314
-
315
- it 'should be executed immediately with corresponding option' do
316
- swr = ShellWatchRun.new(
317
- options: { immediate: true },
318
- dumper: :watched
319
- )
320
-
321
- swr.start
322
- swr.stop
323
-
324
- File.exist?(ShellWatchRun::ENV_FILE).should.be.true
325
- File.read(ShellWatchRun::ENV_FILE).should.equal 'watched'
326
- end
327
-
328
- it 'should not be executed without immediate option and changes' do
329
- swr = ShellWatchRun.new(
330
- options: {},
331
- dumper: :watched
332
- )
333
-
334
- swr.start
335
- swr.stop
336
-
337
- File.exist?(ShellWatchRun::ENV_FILE).should.be.false
338
- end
339
- end
340
- end