listen 2.0.0 → 2.0.1
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/.gitignore +27 -0
- data/.rspec +2 -0
- data/.travis.yml +17 -0
- data/.yardopts +11 -0
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +16 -0
- data/Guardfile +6 -0
- data/{LICENSE → LICENSE.txt} +2 -0
- data/README.md +4 -2
- data/Rakefile +5 -0
- data/lib/listen/listener.rb +1 -2
- data/lib/listen/version.rb +1 -1
- data/listen.gemspec +30 -0
- data/spec/acceptance/listen_spec.rb +204 -0
- data/spec/lib/listen/adapter/base_spec.rb +44 -0
- data/spec/lib/listen/adapter/bsd_spec.rb +39 -0
- data/spec/lib/listen/adapter/darwin_spec.rb +39 -0
- data/spec/lib/listen/adapter/linux_spec.rb +39 -0
- data/spec/lib/listen/adapter/polling_spec.rb +38 -0
- data/spec/lib/listen/adapter/windows_spec.rb +37 -0
- data/spec/lib/listen/adapter_spec.rb +77 -0
- data/spec/lib/listen/change_spec.rb +97 -0
- data/spec/lib/listen/directory_spec.rb +153 -0
- data/spec/lib/listen/file_spec.rb +112 -0
- data/spec/lib/listen/listener_spec.rb +269 -0
- data/spec/lib/listen/record_spec.rb +92 -0
- data/spec/lib/listen/silencer_spec.rb +62 -0
- data/spec/lib/listen_spec.rb +10 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/support/acceptance_helper.rb +45 -0
- data/spec/support/actor_helper.rb +13 -0
- data/spec/support/fixtures_helper.rb +27 -0
- data/spec/support/platform_helper.rb +15 -0
- metadata +75 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ccc28e54b4f14ddb8662b77011a6ec04807ef0c
|
4
|
+
data.tar.gz: 044317983ad9a14eca7744f2e4542f281079981c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2e2e92218ec8d523114db9100f5fb5bc8eaaf470705fb0b179127bb13bd73992a598ca475f175fc8be7a54c18715ad0433be8e4551da1b4b5717b2175f56974
|
7
|
+
data.tar.gz: a80907bc0bf9366a832223cb4112cd9786ee21d46538dc0e74357f4c7fa7df931a84d3a5906b22640998dae06b0995d0388dba44381bee1c7a80b9a1dc914315
|
data/.gitignore
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
pkg/*
|
2
|
+
doc/*
|
3
|
+
*.gem
|
4
|
+
*.rbc
|
5
|
+
.*.swp
|
6
|
+
*.bak
|
7
|
+
bundle
|
8
|
+
.bundle
|
9
|
+
.yardoc
|
10
|
+
.rbx
|
11
|
+
.rvmrc
|
12
|
+
.vagrant
|
13
|
+
Gemfile.lock
|
14
|
+
spec/.fixtures
|
15
|
+
coverage
|
16
|
+
.ruby-version
|
17
|
+
example*
|
18
|
+
test.txt
|
19
|
+
|
20
|
+
## MAC OS
|
21
|
+
.DS_Store
|
22
|
+
.Trashes
|
23
|
+
.com.apple.timemachine.supported
|
24
|
+
.fseventsd
|
25
|
+
Desktop DB
|
26
|
+
Desktop DF
|
27
|
+
|
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
language: ruby
|
2
|
+
bundler_args: --without tool
|
3
|
+
rvm:
|
4
|
+
- 1.9.3
|
5
|
+
- 2.0.0
|
6
|
+
- jruby-19mode
|
7
|
+
- rbx-19mode
|
8
|
+
matrix:
|
9
|
+
allow_failures:
|
10
|
+
- rvm: jruby-19mode
|
11
|
+
- rvm: rbx-19mode
|
12
|
+
notifications:
|
13
|
+
recipients:
|
14
|
+
- thibaud@thibaud.me
|
15
|
+
- remy@rymai.me
|
16
|
+
- michi@netzpiraten.ch
|
17
|
+
- maher@sallam.me
|
data/.yardopts
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Contribute to Listen
|
2
|
+
===================
|
3
|
+
|
4
|
+
File an issue
|
5
|
+
-------------
|
6
|
+
|
7
|
+
You can report bugs and feature requests to [GitHub Issues](https://github.com/guard/listen/issues).
|
8
|
+
|
9
|
+
**Please don't ask question in the issue tracker**, instead ask them in our
|
10
|
+
[Google group](http://groups.google.com/group/guard-dev) or on `#guard` (irc.freenode.net).
|
11
|
+
|
12
|
+
Try to figure out where the issue belongs to: Is it an issue with Listen itself or with Guard?
|
13
|
+
|
14
|
+
When you file a bug, please try to follow these simple rules if applicable:
|
15
|
+
|
16
|
+
* Make sure you run Listen with `bundle exec` first.
|
17
|
+
* Add your `Guardfile` (if used) and `Gemfile` to the issue.
|
18
|
+
* Make sure that the issue is reproducible with your description.
|
19
|
+
|
20
|
+
**It's most likely that your bug gets resolved faster if you provide as much information as possible!**
|
21
|
+
|
22
|
+
Development
|
23
|
+
-----------
|
24
|
+
|
25
|
+
* Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/listen/master/frames).
|
26
|
+
* Source hosted at [GitHub](https://github.com/guard/listen).
|
27
|
+
|
28
|
+
Pull requests are very welcome! Please try to follow these simple rules if applicable:
|
29
|
+
|
30
|
+
* Please create a topic branch for every separate change you make.
|
31
|
+
* Make sure your patches are well tested. All specs run with `rake spec` must pass.
|
32
|
+
* Update the [Yard](http://yardoc.org/) documentation.
|
33
|
+
* Update the [README](https://github.com/guard/listen/blob/master/README.md).
|
34
|
+
* Update the [CHANGELOG](https://github.com/guard/listen/blob/master/CHANGELOG.md) for noteworthy changes.
|
35
|
+
* Please **do not change** the version number.
|
36
|
+
|
37
|
+
For questions please join us in our [Google group](http://groups.google.com/group/guard-dev) or on
|
38
|
+
`#guard` (irc.freenode.net).
|
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
require 'rbconfig'
|
6
|
+
gem 'wdm', '>= 0.1.0' if RbConfig::CONFIG['target_os'] =~ /mswin|mingw|cygwin/i
|
7
|
+
gem 'rb-kqueue', '>= 0.2' if RbConfig::CONFIG['target_os'] =~ /freebsd/i
|
8
|
+
|
9
|
+
group :tool do
|
10
|
+
gem 'yard', require: false
|
11
|
+
gem 'guard-rspec', require: false
|
12
|
+
end
|
13
|
+
|
14
|
+
group :test do
|
15
|
+
gem 'coveralls', require: false
|
16
|
+
end
|
data/Guardfile
ADDED
data/{LICENSE → LICENSE.txt}
RENAMED
@@ -1,5 +1,7 @@
|
|
1
1
|
Copyright (c) 2013 Thibaud Guillaume-Gentil
|
2
2
|
|
3
|
+
MIT License
|
4
|
+
|
3
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
6
|
a copy of this software and associated documentation files (the
|
5
7
|
"Software"), to deal in the Software without restriction, including
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
# Listen
|
1
|
+
# Listen
|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/listen) [](https://travis-ci.org/guard/listen) [](https://gemnasium.com/guard/listen) [](https://codeclimate.com/github/guard/listen) [](https://coveralls.io/r/guard/listen)
|
2
4
|
|
3
5
|
The Listen gem listens to file modifications and notifies you about the changes.
|
4
6
|
|
@@ -66,7 +68,7 @@ listener.start
|
|
66
68
|
listener.ignore! /\.pkg/ # overwrite all patterns and only ignore pkg extension.
|
67
69
|
listener.ignore /\.rb/ # ignore rb extension in addition of pkg.
|
68
70
|
sleep
|
69
|
-
|
71
|
+
```
|
70
72
|
|
71
73
|
## Changes callback
|
72
74
|
|
data/Rakefile
ADDED
data/lib/listen/listener.rb
CHANGED
@@ -116,9 +116,8 @@ module Listen
|
|
116
116
|
end
|
117
117
|
|
118
118
|
def _init_actors
|
119
|
-
cores = Celluloid.cores || 2
|
120
119
|
Celluloid::Actor[:listen_silencer] = Silencer.new(options)
|
121
|
-
Celluloid::Actor[:listen_change_pool] = Change.pool(
|
120
|
+
Celluloid::Actor[:listen_change_pool] = Change.pool(args: self)
|
122
121
|
Celluloid::Actor[:listen_adapter] = Adapter.new(self)
|
123
122
|
Celluloid::Actor[:listen_record] = Record.new(self)
|
124
123
|
end
|
data/lib/listen/version.rb
CHANGED
data/listen.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'listen/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'listen'
|
8
|
+
s.version = Listen::VERSION
|
9
|
+
s.license = 'MIT'
|
10
|
+
s.author = 'Thibaud Guillaume-Gentil'
|
11
|
+
s.email = 'thibaud@thibaud.me'
|
12
|
+
s.homepage = 'https://github.com/guard/listen'
|
13
|
+
s.summary = 'Listen to file modifications'
|
14
|
+
s.description = 'The Listen gem listens to file modifications and notifies you about the changes. Works everywhere!'
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split($/)
|
17
|
+
s.test_files = s.files.grep(%r{^spec/})
|
18
|
+
s.require_path = 'lib'
|
19
|
+
|
20
|
+
s.required_ruby_version = ">= 1.9.3"
|
21
|
+
|
22
|
+
s.add_dependency 'celluloid', '>= 0.15.2'
|
23
|
+
s.add_dependency 'rb-fsevent', '>= 0.9.3'
|
24
|
+
s.add_dependency 'rb-inotify', '>= 0.9'
|
25
|
+
|
26
|
+
s.add_development_dependency 'bundler', '>= 1.3.5'
|
27
|
+
s.add_development_dependency 'rake'
|
28
|
+
s.add_development_dependency 'rspec'
|
29
|
+
s.add_development_dependency 'rspec-retry'
|
30
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe "Listen" do
|
5
|
+
let(:options) { { } }
|
6
|
+
let(:callback) { ->(modified, added, removed) {
|
7
|
+
add_changes(:modified, modified)
|
8
|
+
add_changes(:added, added)
|
9
|
+
add_changes(:removed, removed)
|
10
|
+
} }
|
11
|
+
let(:listener) { @listener }
|
12
|
+
before {
|
13
|
+
@listener = setup_listener(options, callback)
|
14
|
+
@listener.start
|
15
|
+
}
|
16
|
+
after { listener.stop }
|
17
|
+
|
18
|
+
context "with one listen dir" do
|
19
|
+
let(:paths) { Pathname.new(Dir.pwd) }
|
20
|
+
around { |example| fixtures { |path| example.run } }
|
21
|
+
|
22
|
+
context "with change block raising" do
|
23
|
+
let(:callback) { ->(x,y,z) { raise 'foo' } }
|
24
|
+
|
25
|
+
it "warns the backtrace" do
|
26
|
+
expect(Kernel).to receive(:warn).with("[Listen warning]: Change block raise an execption: foo")
|
27
|
+
expect(Kernel).to receive(:warn).with(/^Backtrace:.*/)
|
28
|
+
listen { touch 'file.rb' }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
[false, true].each do |polling|
|
33
|
+
context "force_polling option to #{polling}" do
|
34
|
+
let(:options) { { force_polling: polling, latency: 0.1 } }
|
35
|
+
|
36
|
+
context "nothing in listen dir" do
|
37
|
+
it "listens to file addition" do
|
38
|
+
expect(listen {
|
39
|
+
touch 'file.rb'
|
40
|
+
}).to eq({ modified: [], added: ['file.rb'], removed: [] })
|
41
|
+
end
|
42
|
+
|
43
|
+
it "listens to multiple files addition" do
|
44
|
+
expect(listen {
|
45
|
+
touch 'file1.rb'
|
46
|
+
touch 'file2.rb'
|
47
|
+
}).to eq({ modified: [], added: ['file1.rb', 'file2.rb'], removed: [] })
|
48
|
+
end
|
49
|
+
|
50
|
+
it "listens to file moved inside" do
|
51
|
+
touch '../file.rb'
|
52
|
+
expect(listen {
|
53
|
+
mv '../file.rb', 'file.rb'
|
54
|
+
}).to eq({ modified: [], added: ['file.rb'], removed: [] })
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "file in listen dir" do
|
59
|
+
around { |example| touch 'file.rb'; example.run }
|
60
|
+
|
61
|
+
it "listens to file touch" do
|
62
|
+
expect(listen {
|
63
|
+
touch 'file.rb'
|
64
|
+
}).to eq({ modified: ['file.rb'], added: [], removed: [] })
|
65
|
+
end
|
66
|
+
|
67
|
+
it "listens to file modification" do
|
68
|
+
expect(listen {
|
69
|
+
open('file.rb', 'w') { |f| f.write('foo') }
|
70
|
+
}).to eq({ modified: ['file.rb'], added: [], removed: [] })
|
71
|
+
end
|
72
|
+
|
73
|
+
it "listens to file modification and wait" do
|
74
|
+
expect(listen {
|
75
|
+
open('file.rb', 'w') { |f| f.write('foo') }
|
76
|
+
sleep 0.5
|
77
|
+
}).to eq({ modified: ['file.rb'], added: [], removed: [] })
|
78
|
+
end
|
79
|
+
|
80
|
+
it "listens to file echo" do
|
81
|
+
expect(listen {
|
82
|
+
`echo foo > #{Dir.pwd}/file.rb`
|
83
|
+
}).to eq({ modified: ['file.rb'], added: [], removed: [] })
|
84
|
+
end
|
85
|
+
|
86
|
+
it "listens to file removal" do
|
87
|
+
expect(listen {
|
88
|
+
rm 'file.rb'
|
89
|
+
}).to eq({ modified: [], added: [], removed: ['file.rb'] })
|
90
|
+
end
|
91
|
+
|
92
|
+
it "listens to file moved out" do
|
93
|
+
expect(listen {
|
94
|
+
mv 'file.rb', '../file.rb'
|
95
|
+
}).to eq({ modified: [], added: [], removed: ['file.rb'] })
|
96
|
+
end
|
97
|
+
|
98
|
+
it "listens to file mode change" do
|
99
|
+
expect(listen {
|
100
|
+
chmod 0777, 'file.rb'
|
101
|
+
}).to eq({ modified: ['file.rb'], added: [], removed: [] })
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "hidden file in listen dir" do
|
106
|
+
around { |example| touch '.hidden'; example.run }
|
107
|
+
|
108
|
+
it "listens to file touch" do
|
109
|
+
expect(listen {
|
110
|
+
touch '.hidden'
|
111
|
+
}).to eq({ modified: ['.hidden'], added: [], removed: [] })
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "dir in listen dir" do
|
116
|
+
around { |example| mkdir_p 'dir'; example.run }
|
117
|
+
|
118
|
+
it "listens to file touch" do
|
119
|
+
expect(listen {
|
120
|
+
touch 'dir/file.rb'
|
121
|
+
}).to eq({ modified: [], added: ['dir/file.rb'], removed: [] })
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "dir with file in listen dir" do
|
126
|
+
around { |example| mkdir_p 'dir'; touch 'dir/file.rb'; example.run }
|
127
|
+
|
128
|
+
it "listens to file move" do
|
129
|
+
expect(listen {
|
130
|
+
mv 'dir/file.rb', 'file.rb'
|
131
|
+
}).to eq({ modified: [], added: ['file.rb'], removed: ['dir/file.rb'] })
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "two dirs with files in listen dir" do
|
136
|
+
around { |example|
|
137
|
+
mkdir_p 'dir1'; touch 'dir1/file1.rb'
|
138
|
+
mkdir_p 'dir2'; touch 'dir2/file2.rb'
|
139
|
+
example.run }
|
140
|
+
|
141
|
+
it "listens to multiple file moves" do
|
142
|
+
expect(listen {
|
143
|
+
mv 'dir1/file1.rb', 'dir2/file1.rb'
|
144
|
+
mv 'dir2/file2.rb', 'dir1/file2.rb'
|
145
|
+
}).to eq({ modified: [], added: ['dir1/file2.rb', 'dir2/file1.rb'], removed: ['dir1/file1.rb', 'dir2/file2.rb'] })
|
146
|
+
end
|
147
|
+
|
148
|
+
it "listens to dir move" do
|
149
|
+
expect(listen {
|
150
|
+
mv 'dir1', 'dir2/'
|
151
|
+
}).to eq({ modified: [], added: ['dir2/dir1/file1.rb'], removed: ['dir1/file1.rb'] })
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "ignored dir with file in listen dir" do
|
156
|
+
around { |example| mkdir_p 'ignored_dir'; touch 'ignored_dir/file.rb'; example.run }
|
157
|
+
let(:options) { { force_polling: polling, latency: 0.1, ignore: /ignored_dir/ } }
|
158
|
+
|
159
|
+
it "doesn't listen to file touch" do
|
160
|
+
expect(listen {
|
161
|
+
touch 'ignored_dir/file.rb'
|
162
|
+
}).to eq({ modified: [], added: [], removed: [] })
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "with ignored file in listen dir" do
|
167
|
+
around { |example| touch 'file.rb'; example.run }
|
168
|
+
let(:options) { { force_polling: polling, latency: 0.1, ignore: /\.rb$/ } }
|
169
|
+
|
170
|
+
it "doesn't listen to file touch" do
|
171
|
+
expect(listen {
|
172
|
+
touch 'file.rb'
|
173
|
+
}).to eq({ modified: [], added: [], removed: [] })
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#ignore" do
|
178
|
+
around { |example| touch 'file.rb'; example.run }
|
179
|
+
let(:options) { { force_polling: polling, latency: 0.1, ignore: /\.rb$/ } }
|
180
|
+
|
181
|
+
it "overwrites existing patterns" do
|
182
|
+
expect(listen {
|
183
|
+
listener.ignore(/\.txt/)
|
184
|
+
touch 'file.rb'
|
185
|
+
touch 'file.txt'
|
186
|
+
}).to eq({ modified: [], added: [], removed: [] })
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "#ignore!" do
|
191
|
+
let(:options) { { force_polling: polling, latency: 0.1, ignore: /\.rb$/ } }
|
192
|
+
|
193
|
+
it "overwrites existing patterns" do
|
194
|
+
expect(listen {
|
195
|
+
listener.ignore!(/\.txt/)
|
196
|
+
touch 'file.rb'
|
197
|
+
touch 'file.txt'
|
198
|
+
}).to eq({ modified: [], added: ['file.rb'], removed: [] })
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen::Adapter::Base do
|
4
|
+
let(:adapter) { described_class.new(listener) }
|
5
|
+
let(:listener) { double(Listen::Listener, options: {}) }
|
6
|
+
|
7
|
+
describe "#_latency" do
|
8
|
+
it "returns default_latency with listener actor latency not present" do
|
9
|
+
expect(adapter.send(:_latency)).to eq Listen::Adapter::Base::DEFAULT_LATENCY
|
10
|
+
end
|
11
|
+
|
12
|
+
it "returns latency from listener actor if present" do
|
13
|
+
listener.stub(:options) { { latency: 1234 } }
|
14
|
+
expect(adapter.send(:_latency)).to eq 1234
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#_notify_change" do
|
19
|
+
let(:change_pool) { double(Listen::Change) }
|
20
|
+
let(:change_pool_async) { double('ChangePoolAsync') }
|
21
|
+
before {
|
22
|
+
change_pool.stub(:async) { change_pool_async }
|
23
|
+
Celluloid::Actor.stub(:[]).with(:listen_change_pool) { change_pool }
|
24
|
+
}
|
25
|
+
|
26
|
+
context "listener listen" do
|
27
|
+
before { listener.stub(:listen?) { true} }
|
28
|
+
|
29
|
+
it "calls change on change_pool asynchronously" do
|
30
|
+
expect(change_pool_async).to receive(:change).with('path', type: 'Dir', recurcise: true)
|
31
|
+
adapter.send(:_notify_change, 'path', type: 'Dir', recurcise: true)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "listener doesn't listen" do
|
36
|
+
before { listener.stub(:listen?) { false } }
|
37
|
+
|
38
|
+
it "calls change on change_pool asynchronously" do
|
39
|
+
expect(change_pool_async).to_not receive(:change)
|
40
|
+
adapter.send(:_notify_change, 'path', type: 'Dir', recurcise: true)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|