listen 2.7.4 → 2.7.5
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 +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
|