filewatcher 1.0.0 → 2.0.0.beta2
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.
- checksums.yaml +5 -5
- data/lib/filewatcher.rb +57 -63
- data/lib/filewatcher/cycles.rb +21 -12
- data/lib/filewatcher/snapshot.rb +65 -0
- data/lib/filewatcher/snapshots.rb +56 -0
- data/lib/filewatcher/spec_helper.rb +66 -0
- data/lib/filewatcher/spec_helper/watch_run.rb +76 -0
- data/lib/filewatcher/version.rb +1 -3
- data/spec/filewatcher/snapshot_spec.rb +67 -0
- data/spec/filewatcher/version_spec.rb +9 -0
- data/spec/filewatcher_spec.rb +289 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/spec_helper/ruby_watch_run.rb +82 -0
- metadata +90 -49
- data/bin/banner.txt +0 -17
- data/bin/filewatcher +0 -105
- data/lib/filewatcher/env.rb +0 -29
- data/lib/filewatcher/runner.rb +0 -33
- data/test/dumpers/env_dumper.rb +0 -10
- data/test/dumpers/watched_dumper.rb +0 -5
- data/test/filewatcher/test_env.rb +0 -70
- data/test/filewatcher/test_runner.rb +0 -75
- data/test/filewatcher/test_version.rb +0 -13
- data/test/helper.rb +0 -134
- data/test/test_filewatcher.rb +0 -305
@@ -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,134 +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, :filewatcher, :thread, :watched, :processed
|
16
|
-
|
17
|
-
def initialize(
|
18
|
-
filename: 'tmp_file.txt',
|
19
|
-
directory: false,
|
20
|
-
every: false,
|
21
|
-
filewatcher: Filewatcher.new(
|
22
|
-
File.join(TMP_DIR, '**', '*'), interval: 0.1, every: every
|
23
|
-
),
|
24
|
-
action: :update
|
25
|
-
)
|
26
|
-
@filename =
|
27
|
-
filename.start_with?('/', '~') ? filename : File.join(TMP_DIR, filename)
|
28
|
-
@directory = directory
|
29
|
-
@filewatcher = filewatcher
|
30
|
-
@action = action
|
31
|
-
end
|
32
|
-
|
33
|
-
def start
|
34
|
-
File.write(@filename, 'content1') unless @action == :create
|
35
|
-
|
36
|
-
@thread = thread_initialize
|
37
|
-
sleep 3 # thread needs a chance to start
|
38
|
-
end
|
39
|
-
|
40
|
-
def run
|
41
|
-
start
|
42
|
-
|
43
|
-
make_changes
|
44
|
-
# Some OS, filesystems and Ruby interpretators
|
45
|
-
# doesn't catch milliseconds of `File.mtime`
|
46
|
-
sleep 3
|
47
|
-
|
48
|
-
stop
|
49
|
-
end
|
50
|
-
|
51
|
-
def stop
|
52
|
-
FileUtils.rm_r(@filename) if File.exist?(@filename)
|
53
|
-
@thread.exit
|
54
|
-
sleep 3
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def thread_initialize
|
60
|
-
@watched ||= 0
|
61
|
-
Thread.new(
|
62
|
-
@filewatcher, @processed = []
|
63
|
-
) do |filewatcher, processed|
|
64
|
-
filewatcher.watch do |filename, event|
|
65
|
-
increment_watched
|
66
|
-
processed.push([filename, event])
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def increment_watched
|
72
|
-
@watched += 1
|
73
|
-
end
|
74
|
-
|
75
|
-
def make_changes
|
76
|
-
return FileUtils.remove(@filename) if @action == :delete
|
77
|
-
return FileUtils.mkdir_p(@filename) if @directory
|
78
|
-
File.write(@filename, 'content2')
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
class ShellWatchRun
|
83
|
-
EXECUTABLE = "#{'ruby ' if Gem.win_platform?}" \
|
84
|
-
"#{File.realpath File.join(__dir__, '..', 'bin', 'filewatcher')}".freeze
|
85
|
-
|
86
|
-
attr_reader :output
|
87
|
-
|
88
|
-
def initialize(
|
89
|
-
options: '',
|
90
|
-
dumper: :watched,
|
91
|
-
output: File.join(WatchRun::TMP_DIR, 'env')
|
92
|
-
)
|
93
|
-
@options = options
|
94
|
-
@dumper = dumper
|
95
|
-
@output = output
|
96
|
-
end
|
97
|
-
|
98
|
-
def start
|
99
|
-
@pid = spawn(
|
100
|
-
"#{EXECUTABLE} #{@options} \"#{WatchRun::TMP_DIR}/foo*\"" \
|
101
|
-
" \"ruby #{File.join(__dir__, 'dumpers', "#{@dumper}_dumper.rb")}\""
|
102
|
-
)
|
103
|
-
Process.detach(@pid)
|
104
|
-
sleep 12
|
105
|
-
end
|
106
|
-
|
107
|
-
def run
|
108
|
-
start
|
109
|
-
|
110
|
-
make_changes
|
111
|
-
|
112
|
-
stop
|
113
|
-
end
|
114
|
-
|
115
|
-
def stop
|
116
|
-
Process.kill('KILL', @pid)
|
117
|
-
sleep 6
|
118
|
-
end
|
119
|
-
|
120
|
-
private
|
121
|
-
|
122
|
-
def make_changes
|
123
|
-
FileUtils.touch "#{WatchRun::TMP_DIR}/foo.txt"
|
124
|
-
sleep 12
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
custom_matcher :include_all_files do |obj, elements|
|
129
|
-
elements.all? { |element| obj.include? File.expand_path(element) }
|
130
|
-
end
|
131
|
-
|
132
|
-
def dump_to_env_file(content)
|
133
|
-
File.write File.join(WatchRun::TMP_DIR, 'env'), content
|
134
|
-
end
|
data/test/test_filewatcher.rb
DELETED
@@ -1,305 +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
|
-
end
|
14
|
-
|
15
|
-
describe '#initialize' do
|
16
|
-
it 'should exclude selected file patterns' do
|
17
|
-
wr = WatchRun.new(
|
18
|
-
filewatcher: Filewatcher.new(
|
19
|
-
File.expand_path('test/tmp/**/*'),
|
20
|
-
exclude: File.expand_path('test/tmp/**/*.txt')
|
21
|
-
)
|
22
|
-
)
|
23
|
-
|
24
|
-
wr.run
|
25
|
-
|
26
|
-
wr.processed.should.be.empty
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'should handle absolute paths with globs' do
|
30
|
-
wr = WatchRun.new(
|
31
|
-
filewatcher: Filewatcher.new(
|
32
|
-
File.expand_path('test/tmp/**/*')
|
33
|
-
)
|
34
|
-
)
|
35
|
-
|
36
|
-
wr.run
|
37
|
-
|
38
|
-
wr.processed.should.equal(
|
39
|
-
[[wr.filename, :updated]]
|
40
|
-
)
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'should handle globs' do
|
44
|
-
wr = WatchRun.new(
|
45
|
-
filewatcher: Filewatcher.new('test/tmp/**/*')
|
46
|
-
)
|
47
|
-
|
48
|
-
wr.run
|
49
|
-
|
50
|
-
wr.processed.should.equal(
|
51
|
-
[[wr.filename, :updated]]
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'should handle explicit relative paths with globs' do
|
56
|
-
wr = WatchRun.new(
|
57
|
-
filewatcher: Filewatcher.new('./test/tmp/**/*')
|
58
|
-
)
|
59
|
-
|
60
|
-
wr.run
|
61
|
-
|
62
|
-
wr.processed.should.equal(
|
63
|
-
[[wr.filename, :updated]]
|
64
|
-
)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'should handle explicit relative paths' do
|
68
|
-
wr = WatchRun.new(
|
69
|
-
filewatcher: Filewatcher.new('./test/tmp')
|
70
|
-
)
|
71
|
-
|
72
|
-
wr.run
|
73
|
-
|
74
|
-
wr.processed.should.equal(
|
75
|
-
[[wr.filename, :updated]]
|
76
|
-
)
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'should handle tilde expansion' do
|
80
|
-
filename = File.expand_path('~/file_watcher_1.txt')
|
81
|
-
|
82
|
-
wr = WatchRun.new(
|
83
|
-
filename: filename,
|
84
|
-
filewatcher: Filewatcher.new('~/file_watcher_1.txt')
|
85
|
-
)
|
86
|
-
|
87
|
-
wr.run
|
88
|
-
|
89
|
-
wr.processed.should.equal(
|
90
|
-
[[filename, :updated]]
|
91
|
-
)
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'should immediately run with corresponding option' do
|
95
|
-
wr = WatchRun.new(
|
96
|
-
filewatcher: Filewatcher.new('**/*', immediate: true)
|
97
|
-
)
|
98
|
-
|
99
|
-
wr.start
|
100
|
-
wr.stop
|
101
|
-
|
102
|
-
wr.processed.should.equal [['', '']]
|
103
|
-
wr.watched.should.be > 0
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'should not be executed without immediate option and changes' do
|
107
|
-
wr = WatchRun.new(
|
108
|
-
filewatcher: Filewatcher.new('**/*', immediate: false)
|
109
|
-
)
|
110
|
-
|
111
|
-
wr.start
|
112
|
-
wr.stop
|
113
|
-
|
114
|
-
wr.processed.should.be.empty
|
115
|
-
wr.watched.should.equal 0
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe '#watch' do
|
120
|
-
it 'should detect file deletions' do
|
121
|
-
wr = WatchRun.new(action: :delete)
|
122
|
-
|
123
|
-
wr.run
|
124
|
-
|
125
|
-
wr.processed.should.equal(
|
126
|
-
[[wr.filename, :deleted]]
|
127
|
-
)
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'should detect file additions' do
|
131
|
-
wr = WatchRun.new(action: :create)
|
132
|
-
|
133
|
-
wr.run
|
134
|
-
|
135
|
-
wr.processed.should.equal(
|
136
|
-
[[wr.filename, :created]]
|
137
|
-
)
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'should detect file updates' do
|
141
|
-
wr = WatchRun.new(action: :update)
|
142
|
-
|
143
|
-
wr.run
|
144
|
-
|
145
|
-
wr.processed.should.equal(
|
146
|
-
[[wr.filename, :updated]]
|
147
|
-
)
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'should detect new files in subfolders' do
|
151
|
-
FileUtils.mkdir_p subfolder = File.expand_path('test/tmp/new_sub_folder')
|
152
|
-
|
153
|
-
wr = WatchRun.new(
|
154
|
-
filename: File.join(subfolder, 'file.txt'),
|
155
|
-
action: :create,
|
156
|
-
every: true
|
157
|
-
)
|
158
|
-
wr.run
|
159
|
-
wr.processed.should.equal(
|
160
|
-
[
|
161
|
-
[subfolder, :updated],
|
162
|
-
[wr.filename, :created]
|
163
|
-
]
|
164
|
-
)
|
165
|
-
end
|
166
|
-
|
167
|
-
it 'should detect new subfolders' do
|
168
|
-
subfolder = 'new_sub_folder'
|
169
|
-
|
170
|
-
wr = WatchRun.new(
|
171
|
-
filename: subfolder,
|
172
|
-
directory: true,
|
173
|
-
action: :create
|
174
|
-
)
|
175
|
-
|
176
|
-
wr.run
|
177
|
-
|
178
|
-
wr.processed.should.equal(
|
179
|
-
[[wr.filename, :created]]
|
180
|
-
)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
describe '#stop' do
|
185
|
-
it 'should work' do
|
186
|
-
wr = WatchRun.new
|
187
|
-
|
188
|
-
wr.start
|
189
|
-
|
190
|
-
wr.filewatcher.stop
|
191
|
-
|
192
|
-
# Proves thread successfully joined
|
193
|
-
wr.thread.join.should.equal wr.thread
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
describe '#pause, #resume' do
|
198
|
-
it 'should work' do
|
199
|
-
wr = WatchRun.new(action: :create, every: true)
|
200
|
-
|
201
|
-
wr.start
|
202
|
-
|
203
|
-
wr.filewatcher.pause
|
204
|
-
|
205
|
-
(1..4).each do |n|
|
206
|
-
File.write("test/tmp/file#{n}.txt", "content#{n}")
|
207
|
-
end
|
208
|
-
sleep 0.2 # Give filewatcher time to respond
|
209
|
-
|
210
|
-
# update block should not have been called
|
211
|
-
wr.processed.should.be.empty
|
212
|
-
|
213
|
-
wr.filewatcher.resume
|
214
|
-
sleep 0.2 # Give filewatcher time to respond
|
215
|
-
|
216
|
-
# update block still should not have been called
|
217
|
-
wr.processed.should.be.empty
|
218
|
-
|
219
|
-
added_files = (5..7).to_a.map do |n|
|
220
|
-
File.write(file = "test/tmp/file#{n}.txt", "content#{n}")
|
221
|
-
file
|
222
|
-
end
|
223
|
-
sleep 0.2 # Give filewatcher time to respond
|
224
|
-
|
225
|
-
wr.filewatcher.stop
|
226
|
-
wr.stop
|
227
|
-
wr.processed.map(&:first).should include_all_files(added_files)
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
describe '#finalize' do
|
232
|
-
it 'should process all remaining changes' do
|
233
|
-
wr = WatchRun.new(action: :create, every: true)
|
234
|
-
|
235
|
-
wr.start
|
236
|
-
|
237
|
-
wr.filewatcher.stop
|
238
|
-
wr.thread.join
|
239
|
-
|
240
|
-
added_files = (1..4).to_a.map do |n|
|
241
|
-
File.write(file = "test/tmp/file#{n}.txt", "content#{n}")
|
242
|
-
file
|
243
|
-
end
|
244
|
-
|
245
|
-
wr.filewatcher.finalize
|
246
|
-
|
247
|
-
wr.processed.map(&:first).should include_all_files(added_files)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
describe 'executable' do
|
252
|
-
tmp_dir = WatchRun::TMP_DIR
|
253
|
-
|
254
|
-
it 'should run' do
|
255
|
-
null_output = Gem.win_platform? ? 'NUL' : '/dev/null'
|
256
|
-
system("#{ShellWatchRun::EXECUTABLE} > #{null_output}")
|
257
|
-
.should.be.true
|
258
|
-
end
|
259
|
-
|
260
|
-
it 'should set correct ENV variables' do
|
261
|
-
swr = ShellWatchRun.new(
|
262
|
-
dumper: :env
|
263
|
-
)
|
264
|
-
|
265
|
-
swr.run
|
266
|
-
|
267
|
-
File.read(swr.output)
|
268
|
-
.should.equal(
|
269
|
-
%W[
|
270
|
-
#{tmp_dir}/foo.txt
|
271
|
-
foo.txt
|
272
|
-
created
|
273
|
-
#{tmp_dir}
|
274
|
-
#{tmp_dir}/foo.txt
|
275
|
-
test/tmp/foo.txt
|
276
|
-
].join(', ')
|
277
|
-
)
|
278
|
-
end
|
279
|
-
|
280
|
-
it 'should be executed immediately with corresponding option' do
|
281
|
-
swr = ShellWatchRun.new(
|
282
|
-
options: '--immediate',
|
283
|
-
dumper: :watched
|
284
|
-
)
|
285
|
-
|
286
|
-
swr.start
|
287
|
-
swr.stop
|
288
|
-
|
289
|
-
File.exist?(swr.output).should.be.true
|
290
|
-
File.read(swr.output).should.equal 'watched'
|
291
|
-
end
|
292
|
-
|
293
|
-
it 'should not be executed without immediate option and changes' do
|
294
|
-
swr = ShellWatchRun.new(
|
295
|
-
options: '',
|
296
|
-
dumper: :watched
|
297
|
-
)
|
298
|
-
|
299
|
-
swr.start
|
300
|
-
swr.stop
|
301
|
-
|
302
|
-
File.exist?(swr.output).should.be.false
|
303
|
-
end
|
304
|
-
end
|
305
|
-
end
|