listen 2.7.4 → 2.7.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +232 -0
- data/.travis.yml +6 -3
- data/Gemfile +9 -1
- data/Guardfile +6 -1
- data/README.md +17 -4
- data/lib/listen.rb +9 -4
- data/lib/listen/adapter.rb +5 -7
- data/lib/listen/adapter/base.rb +8 -5
- data/lib/listen/adapter/bsd.rb +58 -21
- data/lib/listen/adapter/darwin.rb +2 -4
- data/lib/listen/adapter/linux.rb +20 -10
- data/lib/listen/adapter/polling.rb +0 -2
- data/lib/listen/adapter/tcp.rb +6 -5
- data/lib/listen/adapter/windows.rb +8 -6
- data/lib/listen/change.rb +1 -2
- data/lib/listen/cli.rb +25 -22
- data/lib/listen/directory.rb +8 -6
- data/lib/listen/listener.rb +25 -19
- data/lib/listen/record.rb +4 -2
- data/lib/listen/silencer.rb +55 -25
- data/lib/listen/tcp.rb +9 -0
- data/lib/listen/tcp/broadcaster.rb +0 -2
- data/lib/listen/tcp/listener.rb +13 -8
- data/lib/listen/tcp/message.rb +0 -2
- data/lib/listen/version.rb +1 -1
- data/listen.gemspec +4 -3
- data/spec/acceptance/listen_spec.rb +190 -109
- data/spec/acceptance/tcp_spec.rb +28 -26
- data/spec/lib/listen/adapter/base_spec.rb +14 -12
- data/spec/lib/listen/adapter/bsd_spec.rb +5 -2
- data/spec/lib/listen/adapter/darwin_spec.rb +5 -2
- data/spec/lib/listen/adapter/linux_spec.rb +40 -25
- data/spec/lib/listen/adapter/polling_spec.rb +29 -14
- data/spec/lib/listen/adapter/tcp_spec.rb +24 -6
- data/spec/lib/listen/adapter/windows_spec.rb +5 -2
- data/spec/lib/listen/adapter_spec.rb +20 -17
- data/spec/lib/listen/change_spec.rb +36 -26
- data/spec/lib/listen/directory_spec.rb +128 -71
- data/spec/lib/listen/file_spec.rb +67 -34
- data/spec/lib/listen/listener_spec.rb +135 -105
- data/spec/lib/listen/record_spec.rb +32 -29
- data/spec/lib/listen/silencer_spec.rb +78 -56
- data/spec/lib/listen/tcp/broadcaster_spec.rb +3 -2
- data/spec/lib/listen/tcp/listener_spec.rb +17 -11
- data/spec/lib/listen/tcp/message_spec.rb +1 -1
- data/spec/lib/listen_spec.rb +18 -6
- data/spec/spec_helper.rb +5 -1
- data/spec/support/acceptance_helper.rb +3 -3
- data/spec/support/fixtures_helper.rb +10 -9
- metadata +17 -15
data/lib/listen/directory.rb
CHANGED
@@ -15,7 +15,9 @@ module Listen
|
|
15
15
|
when 'File'
|
16
16
|
_async_change(entry_path, options.merge(type: 'File'))
|
17
17
|
when 'Dir'
|
18
|
-
|
18
|
+
if _recursive_scan?(entry_path)
|
19
|
+
_async_change(entry_path, options.merge(type: 'Dir'))
|
20
|
+
end
|
19
21
|
end
|
20
22
|
end
|
21
23
|
end
|
@@ -23,8 +25,8 @@ module Listen
|
|
23
25
|
private
|
24
26
|
|
25
27
|
def _update_record
|
26
|
-
if ::Dir.
|
27
|
-
_record.async.set_path(path,
|
28
|
+
if ::Dir.exist?(path)
|
29
|
+
_record.async.set_path(path, type: 'Dir')
|
28
30
|
else
|
29
31
|
_record.async.unset_path(path)
|
30
32
|
end
|
@@ -35,9 +37,9 @@ module Listen
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def _entries
|
38
|
-
return {} unless ::Dir.
|
40
|
+
return {} unless ::Dir.exist?(path)
|
39
41
|
|
40
|
-
entries = ::Dir.entries(path) - %w
|
42
|
+
entries = ::Dir.entries(path) - %w(. ..)
|
41
43
|
entries = entries.map { |entry| [entry, type: _entry_type(entry)] }
|
42
44
|
Hash[*entries.flatten]
|
43
45
|
end
|
@@ -65,7 +67,7 @@ module Listen
|
|
65
67
|
end
|
66
68
|
|
67
69
|
def _recursive_scan?(path)
|
68
|
-
!::Dir.
|
70
|
+
!::Dir.exist?(path) || options[:recursive]
|
69
71
|
end
|
70
72
|
|
71
73
|
def _async_change(entry_path, options)
|
data/lib/listen/listener.rb
CHANGED
@@ -3,14 +3,13 @@ require 'listen/adapter'
|
|
3
3
|
require 'listen/change'
|
4
4
|
require 'listen/record'
|
5
5
|
require 'listen/silencer'
|
6
|
+
require 'English'
|
6
7
|
|
7
8
|
module Listen
|
8
9
|
class Listener
|
9
10
|
attr_accessor :options, :directories, :paused, :changes, :block, :stopping
|
10
11
|
attr_accessor :registry, :supervisor
|
11
12
|
|
12
|
-
RELATIVE_PATHS_WITH_MULTIPLE_DIRECTORIES_WARNING_MESSAGE = "The relative_paths option doesn't work when listening to multiple diretories."
|
13
|
-
|
14
13
|
# Initializes the directories listener.
|
15
14
|
#
|
16
15
|
# @param [String] directory the directories to listen to
|
@@ -78,7 +77,10 @@ module Listen
|
|
78
77
|
@paused == false && @stopping == false
|
79
78
|
end
|
80
79
|
|
81
|
-
# Adds ignore patterns to the existing one
|
80
|
+
# Adds ignore patterns to the existing one
|
81
|
+
#
|
82
|
+
# @see DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in
|
83
|
+
# Listen::Silencer)
|
82
84
|
#
|
83
85
|
# @param [Regexp, Array<Regexp>] new ignoring patterns.
|
84
86
|
#
|
@@ -87,7 +89,10 @@ module Listen
|
|
87
89
|
registry[:silencer] = Silencer.new(self)
|
88
90
|
end
|
89
91
|
|
90
|
-
# Overwrites ignore patterns
|
92
|
+
# Overwrites ignore patterns
|
93
|
+
#
|
94
|
+
# @see DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in
|
95
|
+
# Listen::Silencer)
|
91
96
|
#
|
92
97
|
# @param [Regexp, Array<Regexp>] new ignoring patterns.
|
93
98
|
#
|
@@ -118,7 +123,12 @@ module Listen
|
|
118
123
|
|
119
124
|
def _init_debug
|
120
125
|
if options[:debug] || ENV['LISTEN_GEM_DEBUGGING'] =~ /true|1/i
|
121
|
-
|
126
|
+
if RbConfig::CONFIG['host_os'] =~ /bsd|dragonfly/
|
127
|
+
Celluloid.logger.level = Logger::INFO
|
128
|
+
else
|
129
|
+
# BSDs silently fail ;;(
|
130
|
+
Celluloid.logger.level = Logger::DEBUG
|
131
|
+
end
|
122
132
|
else
|
123
133
|
Celluloid.logger.level = Logger::FATAL
|
124
134
|
end
|
@@ -161,21 +171,16 @@ module Listen
|
|
161
171
|
end
|
162
172
|
|
163
173
|
def _smoosh_changes(changes)
|
164
|
-
if
|
174
|
+
if registry[:adapter].class.local_fs?
|
165
175
|
cookies = changes.group_by { |x| x[:cookie] }
|
166
176
|
_squash_changes(_reinterpret_related_changes(cookies))
|
167
177
|
else
|
168
178
|
smooshed = { modified: [], added: [], removed: [] }
|
169
|
-
changes.each { |
|
170
|
-
smooshed.each { |_, v| v.uniq! }
|
171
|
-
smooshed
|
179
|
+
changes.map(&:first).each { |type, path| smooshed[type] << path.to_s }
|
180
|
+
smooshed.tap { |s| s.each { |_, v| v.uniq! } }
|
172
181
|
end
|
173
182
|
end
|
174
183
|
|
175
|
-
def _local_fs?
|
176
|
-
!registry[:adapter].is_a?(Adapter::TCP)
|
177
|
-
end
|
178
|
-
|
179
184
|
def _squash_changes(changes)
|
180
185
|
actions = changes.group_by(&:last).map do |path, action_list|
|
181
186
|
[_logical_action_for(path, action_list.map(&:first)), path.to_s]
|
@@ -194,7 +199,7 @@ module Listen
|
|
194
199
|
actions << :added if actions.delete(:moved_to)
|
195
200
|
actions << :removed if actions.delete(:moved_from)
|
196
201
|
|
197
|
-
modified = actions.
|
202
|
+
modified = actions.detect { |x| x == :modified }
|
198
203
|
_calculate_add_remove_difference(actions, path, modified)
|
199
204
|
end
|
200
205
|
|
@@ -220,14 +225,15 @@ module Listen
|
|
220
225
|
# editor rename() call (e.g. Kate and Sublime)
|
221
226
|
def _reinterpret_related_changes(cookies)
|
222
227
|
table = { moved_to: :added, moved_from: :removed }
|
223
|
-
cookies.map do |
|
228
|
+
cookies.map do |_, changes|
|
224
229
|
file = _detect_possible_editor_save(changes)
|
225
230
|
if file
|
226
231
|
[[:modified, file]]
|
227
232
|
else
|
228
|
-
changes.map(&:first).reject do |
|
233
|
+
not_silenced = changes.map(&:first).reject do |_, path|
|
229
234
|
_silenced?(path)
|
230
|
-
end
|
235
|
+
end
|
236
|
+
not_silenced.map { |type, path| [table.fetch(type, type), path] }
|
231
237
|
end
|
232
238
|
end.flatten(1)
|
233
239
|
end
|
@@ -235,9 +241,9 @@ module Listen
|
|
235
241
|
def _detect_possible_editor_save(changes)
|
236
242
|
return unless changes.size == 2
|
237
243
|
|
238
|
-
from, to = changes.sort { |x,y| x.keys.first <=> y.keys.first }
|
244
|
+
from, to = changes.sort { |x, y| x.keys.first <=> y.keys.first }
|
239
245
|
from, to = from[:moved_from], to[:moved_to]
|
240
|
-
return unless from
|
246
|
+
return unless from && to
|
241
247
|
|
242
248
|
# Expect an ignored moved_from and non-ignored moved_to
|
243
249
|
# to qualify as an "editor modify"
|
data/lib/listen/record.rb
CHANGED
@@ -10,7 +10,8 @@ module Listen
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def set_path(path, data)
|
13
|
-
|
13
|
+
new_data = file_data(path).merge(data)
|
14
|
+
@paths[::File.dirname(path)][::File.basename(path)] = new_data
|
14
15
|
end
|
15
16
|
|
16
17
|
def unset_path(path)
|
@@ -28,7 +29,8 @@ module Listen
|
|
28
29
|
def build
|
29
30
|
@paths = _init_paths
|
30
31
|
listener.directories.each do |path|
|
31
|
-
|
32
|
+
options = { type: 'Dir', recursive: true, silence: true }
|
33
|
+
listener.registry[:change_pool].change(path, options)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
data/lib/listen/silencer.rb
CHANGED
@@ -3,11 +3,33 @@ module Listen
|
|
3
3
|
include Celluloid
|
4
4
|
|
5
5
|
# The default list of directories that get ignored.
|
6
|
-
DEFAULT_IGNORED_DIRECTORIES = %
|
6
|
+
DEFAULT_IGNORED_DIRECTORIES = %r{^(?:
|
7
|
+
\.git
|
8
|
+
| \.svn
|
9
|
+
| \.hg
|
10
|
+
| \.rbx
|
11
|
+
| \.bundle
|
12
|
+
| bundle
|
13
|
+
| vendor/bundle
|
14
|
+
| log
|
15
|
+
| tmp
|
16
|
+
|vendor/ruby
|
17
|
+
)(/|$)}x
|
7
18
|
|
8
19
|
# The default list of files that get ignored.
|
9
|
-
|
10
|
-
|
20
|
+
DEFAULT_IGNORED_EXTENSIONS = %r{(?:
|
21
|
+
# Kate's tmp/swp files
|
22
|
+
\..*\d+\.new
|
23
|
+
| \.kate-swp
|
24
|
+
|
25
|
+
# Gedit tmp files
|
26
|
+
| \.goutputstream-.{6}
|
27
|
+
|
28
|
+
# other files
|
29
|
+
| \.DS_Store
|
30
|
+
| \.tmp
|
31
|
+
| ~
|
32
|
+
)$}x
|
11
33
|
|
12
34
|
attr_accessor :listener, :only_patterns, :ignore_patterns
|
13
35
|
|
@@ -20,11 +42,18 @@ module Listen
|
|
20
42
|
def silenced?(path, type = 'Unknown')
|
21
43
|
silenced = false
|
22
44
|
|
45
|
+
relative_path = _relative_path(path)
|
46
|
+
|
23
47
|
if only_patterns && type == 'File'
|
24
|
-
silenced = !only_patterns.any? { |pattern|
|
48
|
+
silenced = !only_patterns.any? { |pattern| relative_path =~ pattern }
|
25
49
|
end
|
26
50
|
|
27
|
-
silenced
|
51
|
+
silenced || ignore_patterns.any? { |pattern| relative_path =~ pattern }
|
52
|
+
end
|
53
|
+
|
54
|
+
def match(args)
|
55
|
+
path, type = args.first
|
56
|
+
silenced?(path, type)
|
28
57
|
end
|
29
58
|
|
30
59
|
private
|
@@ -36,33 +65,34 @@ module Listen
|
|
36
65
|
end
|
37
66
|
|
38
67
|
def _init_ignore_patterns
|
39
|
-
|
40
|
-
@ignore_patterns << _default_ignore_patterns unless listener.options[:ignore!]
|
41
|
-
@ignore_patterns << listener.options[:ignore] << listener.options[:ignore!]
|
42
|
-
@ignore_patterns.compact!
|
43
|
-
@ignore_patterns.flatten!
|
44
|
-
end
|
68
|
+
options = listener.options
|
45
69
|
|
46
|
-
|
47
|
-
[
|
48
|
-
|
70
|
+
patterns = []
|
71
|
+
unless options[:ignore!]
|
72
|
+
patterns << DEFAULT_IGNORED_DIRECTORIES
|
73
|
+
patterns << DEFAULT_IGNORED_EXTENSIONS
|
74
|
+
end
|
49
75
|
|
50
|
-
|
51
|
-
|
52
|
-
%r{^(?:#{ignored_directories.join('|')})(/|$)}
|
53
|
-
end
|
76
|
+
patterns << options[:ignore]
|
77
|
+
patterns << options[:ignore!]
|
54
78
|
|
55
|
-
|
56
|
-
|
57
|
-
|e| e.is_a?(Regexp) ? e : Regexp.escape(e)
|
58
|
-
end
|
79
|
+
patterns.compact!
|
80
|
+
patterns.flatten!
|
59
81
|
|
60
|
-
|
82
|
+
@ignore_patterns = patterns
|
61
83
|
end
|
62
84
|
|
63
85
|
def _relative_path(path)
|
64
|
-
relative_paths = listener.directories.map
|
65
|
-
|
86
|
+
relative_paths = listener.directories.map do |dir|
|
87
|
+
begin
|
88
|
+
path.relative_path_from(dir).to_s
|
89
|
+
rescue ArgumentError
|
90
|
+
# Windows raises errors across drives, e.g. when 'C:/' and 'E:/dir'
|
91
|
+
# So, here's a Dirty hack to fool the detect() below..
|
92
|
+
'../'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
relative_paths.detect { |rel_path| !rel_path.start_with?('../') }
|
66
96
|
end
|
67
97
|
end
|
68
98
|
end
|
data/lib/listen/tcp.rb
ADDED
data/lib/listen/tcp/listener.rb
CHANGED
@@ -4,7 +4,6 @@ require 'listen/tcp/message'
|
|
4
4
|
module Listen
|
5
5
|
module TCP
|
6
6
|
class Listener < Listen::Listener
|
7
|
-
|
8
7
|
DEFAULT_HOST = 'localhost'
|
9
8
|
|
10
9
|
attr_reader :host, :mode, :port
|
@@ -43,18 +42,24 @@ module Listen
|
|
43
42
|
# Hook to broadcast changes over TCP
|
44
43
|
def block
|
45
44
|
if broadcaster?
|
46
|
-
|
45
|
+
proc do |modified, added, removed|
|
47
46
|
|
48
47
|
# Honour paused and stopped states
|
49
48
|
next if @paused || @stopping
|
50
49
|
|
51
|
-
# Broadcast changes as a hash
|
52
|
-
|
50
|
+
# Broadcast changes as a hash
|
51
|
+
#
|
52
|
+
# @see Listen::Adapter::TCP#handle_message
|
53
|
+
message = Message.new(
|
54
|
+
modified: modified,
|
55
|
+
added: added,
|
56
|
+
removed: removed)
|
57
|
+
|
53
58
|
registry[:broadcaster].async.broadcast(message.payload)
|
54
59
|
|
55
60
|
# Invoke the original callback block
|
56
61
|
@block.call(modified, added, removed) if @block
|
57
|
-
|
62
|
+
end
|
58
63
|
else
|
59
64
|
super
|
60
65
|
end
|
@@ -74,7 +79,8 @@ module Listen
|
|
74
79
|
#
|
75
80
|
def mode=(mode)
|
76
81
|
unless [:broadcaster, :recipient].include? mode
|
77
|
-
|
82
|
+
fail ArgumentError, 'TCP::Listener requires mode to be either'\
|
83
|
+
' :broadcaster or :recipient'
|
78
84
|
end
|
79
85
|
@mode = mode
|
80
86
|
end
|
@@ -85,7 +91,7 @@ module Listen
|
|
85
91
|
#
|
86
92
|
def target=(target)
|
87
93
|
unless target
|
88
|
-
|
94
|
+
fail ArgumentError, 'TCP::Listener requires target to be given'
|
89
95
|
end
|
90
96
|
|
91
97
|
@host = DEFAULT_HOST if recipient?
|
@@ -97,7 +103,6 @@ module Listen
|
|
97
103
|
@port = @port.to_i
|
98
104
|
end
|
99
105
|
end
|
100
|
-
|
101
106
|
end
|
102
107
|
end
|
103
108
|
end
|
data/lib/listen/tcp/message.rb
CHANGED
data/lib/listen/version.rb
CHANGED
data/listen.gemspec
CHANGED
@@ -11,21 +11,22 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.email = 'thibaud@thibaud.gg'
|
12
12
|
s.homepage = 'https://github.com/guard/listen'
|
13
13
|
s.summary = 'Listen to file modifications'
|
14
|
-
s.description = 'The Listen gem listens to file modifications and
|
14
|
+
s.description = 'The Listen gem listens to file modifications and '\
|
15
|
+
'notifies you about the changes. Works everywhere!'
|
15
16
|
|
16
17
|
s.files = `git ls-files`.split($/)
|
17
18
|
s.test_files = s.files.grep(%r{^spec/})
|
18
19
|
s.executable = 'listen'
|
19
20
|
s.require_path = 'lib'
|
20
21
|
|
21
|
-
s.required_ruby_version =
|
22
|
+
s.required_ruby_version = '>= 1.9.3'
|
22
23
|
|
23
24
|
s.add_dependency 'celluloid', '>= 0.15.2'
|
24
|
-
s.add_dependency 'celluloid-io', '>= 0.15.0'
|
25
25
|
s.add_dependency 'rb-fsevent', '>= 0.9.3'
|
26
26
|
s.add_dependency 'rb-inotify', '>= 0.9'
|
27
27
|
|
28
28
|
s.add_development_dependency 'bundler', '>= 1.3.5'
|
29
|
+
s.add_development_dependency 'celluloid-io', '>= 0.15.0'
|
29
30
|
s.add_development_dependency 'rake'
|
30
31
|
s.add_development_dependency 'rspec', '~> 2.14'
|
31
32
|
s.add_development_dependency 'rspec-retry'
|
@@ -1,29 +1,35 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
describe
|
5
|
-
let(:options) { {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
describe 'Listen' do
|
5
|
+
let(:options) { {} }
|
6
|
+
|
7
|
+
let(:callback) do
|
8
|
+
lambda do |modified, added, removed|
|
9
|
+
add_changes(:modified, modified)
|
10
|
+
add_changes(:added, added)
|
11
|
+
add_changes(:removed, removed)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
11
15
|
let(:listener) { @listener }
|
12
|
-
before
|
16
|
+
before do
|
13
17
|
@listener = setup_listener(options, callback)
|
14
18
|
@listener.start
|
15
|
-
|
19
|
+
end
|
20
|
+
|
16
21
|
after { listener.stop }
|
17
22
|
|
18
|
-
context
|
23
|
+
context 'with one listen dir' do
|
19
24
|
let(:paths) { Pathname.new(Dir.pwd) }
|
20
|
-
around { |example| fixtures {
|
25
|
+
around { |example| fixtures { example.run } }
|
21
26
|
|
22
|
-
context
|
23
|
-
let(:callback) { ->(
|
27
|
+
context 'with change block raising' do
|
28
|
+
let(:callback) { ->(_, _, _) { fail 'foo' } }
|
24
29
|
|
25
|
-
it
|
26
|
-
expect(Kernel).to receive(:warn).
|
30
|
+
it 'warns the backtrace' do
|
31
|
+
expect(Kernel).to receive(:warn).
|
32
|
+
with('[Listen warning]: Change block raised an exception: foo')
|
27
33
|
expect(Kernel).to receive(:warn).with(/^Backtrace:.*/)
|
28
34
|
listen { touch 'file.rb' }
|
29
35
|
end
|
@@ -33,203 +39,278 @@ describe "Listen" do
|
|
33
39
|
context "force_polling option to #{polling}" do
|
34
40
|
let(:options) { { force_polling: polling, latency: 0.1 } }
|
35
41
|
|
36
|
-
context
|
37
|
-
it
|
38
|
-
expect(listen
|
42
|
+
context 'nothing in listen dir' do
|
43
|
+
it 'listens to file addition' do
|
44
|
+
expect(listen do
|
39
45
|
touch 'file.rb'
|
40
|
-
|
46
|
+
end).to eq(modified: [], added: ['file.rb'], removed: [])
|
41
47
|
end
|
42
48
|
|
43
|
-
it
|
44
|
-
|
49
|
+
it 'listens to multiple files addition' do
|
50
|
+
result = listen do
|
45
51
|
touch 'file1.rb'
|
46
52
|
touch 'file2.rb'
|
47
|
-
|
53
|
+
end
|
54
|
+
|
55
|
+
expect(result).to eq(modified: [],
|
56
|
+
added: %w(file1.rb file2.rb),
|
57
|
+
removed: [])
|
48
58
|
end
|
49
59
|
|
50
|
-
it
|
60
|
+
it 'listens to file moved inside' do
|
51
61
|
touch '../file.rb'
|
52
|
-
expect(listen
|
62
|
+
expect(listen do
|
53
63
|
mv '../file.rb', 'file.rb'
|
54
|
-
|
64
|
+
end).to eq(modified: [], added: ['file.rb'], removed: [])
|
55
65
|
end
|
56
66
|
end
|
57
67
|
|
58
|
-
context
|
59
|
-
around
|
68
|
+
context 'file in listen dir' do
|
69
|
+
around do |example|
|
70
|
+
touch 'file.rb'
|
71
|
+
example.run
|
72
|
+
end
|
60
73
|
|
61
|
-
it
|
62
|
-
expect(listen
|
74
|
+
it 'listens to file touch' do
|
75
|
+
expect(listen do
|
63
76
|
touch 'file.rb'
|
64
|
-
|
77
|
+
end).to eq(modified: ['file.rb'], added: [], removed: [])
|
65
78
|
end
|
66
79
|
|
67
|
-
it
|
68
|
-
expect(listen
|
80
|
+
it 'listens to file modification' do
|
81
|
+
expect(listen do
|
69
82
|
open('file.rb', 'w') { |f| f.write('foo') }
|
70
|
-
|
83
|
+
end).to eq(modified: ['file.rb'], added: [], removed: [])
|
71
84
|
end
|
72
85
|
|
73
|
-
it
|
74
|
-
expect(listen
|
86
|
+
it 'listens to file modification and wait' do
|
87
|
+
expect(listen do
|
75
88
|
open('file.rb', 'w') { |f| f.write('foo') }
|
76
89
|
sleep 0.5
|
77
|
-
|
90
|
+
end).to eq(modified: ['file.rb'], added: [], removed: [])
|
78
91
|
end
|
79
92
|
|
80
|
-
it
|
81
|
-
expect(listen
|
93
|
+
it 'listens to file echo' do
|
94
|
+
expect(listen do
|
82
95
|
`echo foo > #{Dir.pwd}/file.rb`
|
83
|
-
|
96
|
+
end).to eq(modified: ['file.rb'], added: [], removed: [])
|
84
97
|
end
|
85
98
|
|
86
|
-
it
|
87
|
-
expect(listen
|
99
|
+
it 'listens to file removal' do
|
100
|
+
expect(listen do
|
88
101
|
rm 'file.rb'
|
89
|
-
|
102
|
+
end).to eq(modified: [], added: [], removed: ['file.rb'])
|
90
103
|
end
|
91
104
|
|
92
|
-
it
|
93
|
-
expect(listen
|
105
|
+
it 'listens to file moved out' do
|
106
|
+
expect(listen do
|
94
107
|
mv 'file.rb', '../file.rb'
|
95
|
-
|
108
|
+
end).to eq(modified: [], added: [], removed: ['file.rb'])
|
96
109
|
end
|
97
110
|
|
98
|
-
it
|
99
|
-
expect(listen
|
111
|
+
it 'listens to file mode change' do
|
112
|
+
expect(listen do
|
100
113
|
chmod 0777, 'file.rb'
|
101
|
-
|
114
|
+
end).to eq(modified: ['file.rb'], added: [], removed: [])
|
102
115
|
end
|
103
116
|
end
|
104
117
|
|
105
|
-
context
|
106
|
-
around
|
118
|
+
context 'hidden file in listen dir' do
|
119
|
+
around do |example|
|
120
|
+
touch '.hidden'
|
121
|
+
example.run
|
122
|
+
end
|
107
123
|
|
108
|
-
it
|
109
|
-
expect(listen
|
124
|
+
it 'listens to file touch' do
|
125
|
+
expect(listen do
|
110
126
|
touch '.hidden'
|
111
|
-
|
127
|
+
end).to eq(modified: ['.hidden'], added: [], removed: [])
|
112
128
|
end
|
113
129
|
end
|
114
130
|
|
115
|
-
context
|
116
|
-
around
|
131
|
+
context 'dir in listen dir' do
|
132
|
+
around do |example|
|
133
|
+
mkdir_p 'dir'
|
134
|
+
example.run
|
135
|
+
end
|
117
136
|
|
118
|
-
it
|
119
|
-
expect(listen
|
137
|
+
it 'listens to file touch' do
|
138
|
+
expect(listen do
|
120
139
|
touch 'dir/file.rb'
|
121
|
-
|
140
|
+
end).to eq(modified: [], added: ['dir/file.rb'], removed: [])
|
122
141
|
end
|
123
142
|
end
|
124
143
|
|
125
|
-
context
|
126
|
-
around
|
144
|
+
context 'dir with file in listen dir' do
|
145
|
+
around do |example|
|
146
|
+
mkdir_p 'dir'
|
147
|
+
touch 'dir/file.rb'
|
148
|
+
example.run
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'listens to file move' do
|
152
|
+
expected = { modified: [],
|
153
|
+
added: %w(file.rb),
|
154
|
+
removed: %w(dir/file.rb)
|
155
|
+
}
|
127
156
|
|
128
|
-
|
129
|
-
expect(listen {
|
157
|
+
expect(listen do
|
130
158
|
mv 'dir/file.rb', 'file.rb'
|
131
|
-
|
159
|
+
end).to eq expected
|
132
160
|
end
|
133
161
|
end
|
134
162
|
|
135
|
-
context
|
136
|
-
around
|
137
|
-
mkdir_p 'dir1'
|
138
|
-
|
139
|
-
|
163
|
+
context 'two dirs with files in listen dir' do
|
164
|
+
around do |example|
|
165
|
+
mkdir_p 'dir1'
|
166
|
+
touch 'dir1/file1.rb'
|
167
|
+
mkdir_p 'dir2'
|
168
|
+
touch 'dir2/file2.rb'
|
169
|
+
example.run
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'listens to multiple file moves' do
|
173
|
+
expected = {
|
174
|
+
modified: [],
|
175
|
+
added: ['dir1/file2.rb', 'dir2/file1.rb'],
|
176
|
+
removed: ['dir1/file1.rb', 'dir2/file2.rb']
|
177
|
+
}
|
140
178
|
|
141
|
-
|
142
|
-
expect(listen {
|
179
|
+
expect(listen do
|
143
180
|
mv 'dir1/file1.rb', 'dir2/file1.rb'
|
144
181
|
mv 'dir2/file2.rb', 'dir1/file2.rb'
|
145
|
-
|
182
|
+
end).to eq expected
|
146
183
|
end
|
147
184
|
|
148
|
-
it
|
149
|
-
|
185
|
+
it 'listens to dir move' do
|
186
|
+
expected = { modified: [],
|
187
|
+
added: ['dir2/dir1/file1.rb'],
|
188
|
+
removed: ['dir1/file1.rb'] }
|
189
|
+
|
190
|
+
expect(listen do
|
150
191
|
mv 'dir1', 'dir2/'
|
151
|
-
|
192
|
+
end).to eq expected
|
152
193
|
end
|
153
194
|
end
|
154
195
|
|
155
|
-
context
|
156
|
-
around
|
196
|
+
context 'default ignored dir with file in listen dir' do
|
197
|
+
around do |example|
|
198
|
+
mkdir_p '.bundle'
|
199
|
+
touch '.bundle/file.rb'
|
200
|
+
example.run
|
201
|
+
end
|
202
|
+
|
157
203
|
let(:options) { { force_polling: polling, latency: 0.1 } }
|
158
204
|
|
159
205
|
it "doesn't listen to file touch" do
|
160
|
-
expect(listen
|
206
|
+
expect(listen do
|
161
207
|
touch '.bundle/file.rb'
|
162
|
-
|
208
|
+
end).to eq(modified: [], added: [], removed: [])
|
163
209
|
end
|
164
210
|
end
|
165
211
|
|
166
|
-
context
|
167
|
-
around
|
168
|
-
|
212
|
+
context 'ignored dir with file in listen dir' do
|
213
|
+
around do |example|
|
214
|
+
mkdir_p 'ignored_dir'
|
215
|
+
touch 'ignored_dir/file.rb'
|
216
|
+
example.run
|
217
|
+
end
|
218
|
+
|
219
|
+
let(:options) do
|
220
|
+
{ force_polling: polling,
|
221
|
+
latency: 0.1,
|
222
|
+
ignore: /ignored_dir/ }
|
223
|
+
end
|
169
224
|
|
170
225
|
it "doesn't listen to file touch" do
|
171
|
-
expect(listen
|
226
|
+
expect(listen do
|
172
227
|
touch 'ignored_dir/file.rb'
|
173
|
-
|
228
|
+
end).to eq(modified: [], added: [], removed: [])
|
174
229
|
end
|
175
230
|
end
|
176
231
|
|
177
|
-
context
|
178
|
-
around
|
179
|
-
|
232
|
+
context 'with ignored file in listen dir' do
|
233
|
+
around do |example|
|
234
|
+
touch 'file.rb'
|
235
|
+
example.run
|
236
|
+
end
|
237
|
+
let(:options) do
|
238
|
+
{ force_polling: polling,
|
239
|
+
latency: 0.1,
|
240
|
+
ignore: /\.rb$/ }
|
241
|
+
end
|
180
242
|
|
181
243
|
it "doesn't listen to file touch" do
|
182
|
-
expect(listen
|
244
|
+
expect(listen do
|
183
245
|
touch 'file.rb'
|
184
|
-
|
246
|
+
end).to eq(modified: [], added: [], removed: [])
|
185
247
|
end
|
186
248
|
end
|
187
249
|
|
188
|
-
context
|
189
|
-
let(:options)
|
250
|
+
context 'with only option' do
|
251
|
+
let(:options) do
|
252
|
+
{ force_polling: polling,
|
253
|
+
latency: 0.1,
|
254
|
+
only: /\.rb$/ }
|
255
|
+
end
|
190
256
|
|
191
|
-
it
|
192
|
-
expect(listen
|
257
|
+
it 'listens only to file touch matching with only patterns' do
|
258
|
+
expect(listen do
|
193
259
|
touch 'file.rb'
|
194
260
|
touch 'file.txt'
|
195
|
-
|
261
|
+
end).to eq(modified: [], added: ['file.rb'], removed: [])
|
196
262
|
end
|
197
263
|
end
|
198
264
|
|
199
|
-
context
|
200
|
-
let(:options)
|
265
|
+
context 'with ignore and only option' do
|
266
|
+
let(:options) do
|
267
|
+
{ force_polling: polling,
|
268
|
+
latency: 0.1,
|
269
|
+
ignore: /bar\.rb$/, only: /\.rb$/ }
|
270
|
+
end
|
201
271
|
|
202
|
-
it
|
203
|
-
expect(listen
|
272
|
+
it 'listens only to file touch matching with only patterns' do
|
273
|
+
expect(listen do
|
204
274
|
touch 'file.rb'
|
205
275
|
touch 'bar.rb'
|
206
276
|
touch 'file.txt'
|
207
|
-
|
277
|
+
end).to eq(modified: [], added: ['file.rb'], removed: [])
|
208
278
|
end
|
209
279
|
end
|
210
280
|
|
211
|
-
describe
|
212
|
-
around
|
213
|
-
|
281
|
+
describe '#ignore' do
|
282
|
+
around do |example|
|
283
|
+
touch 'file.rb'
|
284
|
+
example.run
|
285
|
+
end
|
286
|
+
let(:options) do
|
287
|
+
{ force_polling: polling,
|
288
|
+
latency: 0.1,
|
289
|
+
ignore: /\.rb$/ }
|
290
|
+
end
|
214
291
|
|
215
|
-
it
|
216
|
-
expect(listen
|
292
|
+
it 'overwrites existing patterns' do
|
293
|
+
expect(listen do
|
217
294
|
listener.ignore(/\.txt/)
|
218
295
|
touch 'file.rb'
|
219
296
|
touch 'file.txt'
|
220
|
-
|
297
|
+
end).to eq(modified: [], added: [], removed: [])
|
221
298
|
end
|
222
299
|
end
|
223
300
|
|
224
|
-
describe
|
225
|
-
let(:options)
|
301
|
+
describe '#ignore!' do
|
302
|
+
let(:options) do
|
303
|
+
{ force_polling: polling,
|
304
|
+
latency: 0.1,
|
305
|
+
ignore: /\.rb$/ }
|
306
|
+
end
|
226
307
|
|
227
|
-
it
|
228
|
-
expect(listen
|
308
|
+
it 'overwrites existing patterns' do
|
309
|
+
expect(listen do
|
229
310
|
listener.ignore!(/\.txt/)
|
230
311
|
touch 'file.rb'
|
231
312
|
touch 'file.txt'
|
232
|
-
|
313
|
+
end).to eq(modified: [], added: ['file.rb'], removed: [])
|
233
314
|
end
|
234
315
|
end
|
235
316
|
end
|