listen 2.2.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c1becf59266f1a4dfdae77c1fe433948ddf3906b
4
- data.tar.gz: d76d3ef28a4c8ac95661b21c6bbf604ecab56869
3
+ metadata.gz: e8644cb90075a5b296441b6e04044258dc64c738
4
+ data.tar.gz: 09212d8aafd577ab7ce6181b99798d43d69d6f44
5
5
  SHA512:
6
- metadata.gz: 6cd16d944719dac5cda7bfae7254b47cbd77c2e32083305ebecaeb115d200ef246fc5366a923d413424549bc875891075f200fb4e0a6a3bfcac850bf642f80db
7
- data.tar.gz: 9119e9c3995d0b74d668132722971926bbd10dda5a76d223fe828c234461dcb036185de06a72408b24f8fef9599cacdddfdb532db071a90c8b3c941cab4d54bb
6
+ metadata.gz: a016d2f3551965258853b077f249f1b19d5f6f3bccce6707f5f9aba4be054faf18a08f2c9f491fb6fd8afeda25fd4481fb041c90489739ce34bd7e5bdeef0c06
7
+ data.tar.gz: 0448bb8714d6ad0209a7db76ef3ceef29075d8e464f3d26d3e8bb5830173423b48b2c665c6eb7b0ff69881b1e976e750da57fbc2f6950b2dc4a7433f981149d2
data/Guardfile CHANGED
@@ -1,4 +1,4 @@
1
- guard :rspec, bundler: false do
1
+ guard :rspec do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
3
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
4
  watch(%r{^spec/support/*}) { 'spec' }
data/README.md CHANGED
@@ -7,7 +7,7 @@ The Listen gem listens to file modifications and notifies you about the changes.
7
7
  ## Features
8
8
 
9
9
  * Supports watching multiple directories from a single listener.
10
- * OS-specific adapters on MRI for Mac OS X 10.6+, Linux, *BSD and Windows, [more info](#listen-adapters) bellow.
10
+ * OS-specific adapters on MRI for Mac OS X 10.6+, Linux, *BSD and Windows, [more info](#listen-adapters) below.
11
11
  * Detects file modification, addition and removal.
12
12
  * Allows supplying regexp-patterns to ignore paths for better results.
13
13
  * File content checksum comparison for modifications made under the same second (OS X only).
@@ -48,7 +48,7 @@ sleep
48
48
 
49
49
  ### Pause / unpause / stop
50
50
 
51
- Listener can also be easily paused/unpaused:
51
+ Listeners can also be easily paused/unpaused:
52
52
 
53
53
  ``` ruby
54
54
  listener = Listen.to('dir/path/to/listen') { |modified, added, removed| # ... }
@@ -62,18 +62,31 @@ listener.stop # stop completely the listener
62
62
 
63
63
  ### Ignore / ignore!
64
64
 
65
- Liste ignore some folder and extensions by default (See DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in Listen::Silencer), you can add ignoring patterns with the `ignore` option/method or overwrite default with `ignore!` option/method.
65
+ Listen ignores some directories and extensions by default (See DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in Listen::Silencer), you can add ignoring patterns with the `ignore` option/method or overwrite default with `ignore!` option/method.
66
66
 
67
67
  ``` ruby
68
68
  listener = Listen.to('dir/path/to/listen', ignore: /\.txt/) { |modified, added, removed| # ... }
69
69
  listener.start
70
- listener.ignore! /\.pkg/ # overwrite all patterns and only ignore pkg extension.
71
- listener.ignore /\.rb/ # ignore rb extension in addition of pkg.
70
+ listener.ignore! /\.pkg/ # overwrite all patterns and only ignore pkg extension.
71
+ listener.ignore /\.rb/ # ignore rb extension in addition of pkg.
72
72
  sleep
73
73
  ```
74
74
 
75
75
  Note: Ignoring regexp patterns are evaluated against relative paths.
76
76
 
77
+ ### Only
78
+
79
+ Listen catches all files (less the ignored once) by default, if you want to only listen to a specific type of file (ie: just rb extension) you should use the `only` option/method.
80
+
81
+ ``` ruby
82
+ listener = Listen.to('dir/path/to/listen', only: /\.rb$/) { |modified, added, removed| # ... }
83
+ listener.start
84
+ listener.only /_spec\.rb$/ # overwrite all existing only patterns.
85
+ sleep
86
+ ```
87
+
88
+ Note: Only regexp patterns are evaluated only against relative **file** paths.
89
+
77
90
  ## Changes callback
78
91
 
79
92
  Changes to the listened-to directories gets reported back to the user in a callback.
@@ -113,6 +126,9 @@ ignore: [%r{/foo/bar}, /\.pid$/, /\.coffee$/] # Ignore a list of paths
113
126
 
114
127
  ignore!: %r{/foo/bar} # Same as ignore options, but overwrite default ignored paths.
115
128
 
129
+ only: %r{.rb$} # Only listen to specific files
130
+ # default: none
131
+
116
132
  latency: 0.5 # Set the delay (**in seconds**) between checking for changes
117
133
  # default: 0.25 sec (1.0 sec for polling)
118
134
 
@@ -138,15 +154,15 @@ These adapters are fast as they use some system-calls to implement the notifying
138
154
  There is also a polling adapter which is a cross-platform adapter and it will
139
155
  work on any system. This adapter is slower than the rest of the adapters.
140
156
 
141
- Darwin and Linux adapter are dependencies of the Listen gem so they work out of the box. For other adapters a specific gem need to be added to your Gemfile, please read bellow.
157
+ The Darwin and Linux adapters are dependencies of the Listen gem so they work out of the box. For other adapters a specific gem will have to be added to your Gemfile, please read below.
142
158
 
143
- The Listen gem choose the good adapter (if present) automatically. If you
144
- want to force the use of the polling adapter use the `:force_polling` option
159
+ The Listen gem will choose the best adapter automatically, if present. If you
160
+ want to force the use of the polling adapter, use the `:force_polling` option
145
161
  while initializing the listener.
146
162
 
147
163
  ### On Windows
148
164
 
149
- If your are on Windows you can try to use the [`wdm`](https://github.com/Maher4Ever/wdm) instead of polling.
165
+ If your are on Windows, you can try to use the [`wdm`](https://github.com/Maher4Ever/wdm) instead of polling.
150
166
  Please add the following to your Gemfile:
151
167
 
152
168
  ```ruby
@@ -166,11 +182,11 @@ gem 'rb-kqueue', '>= 0.2' if RbConfig::CONFIG['target_os'] =~ /freebsd/i
166
182
 
167
183
  ### Issues
168
184
 
169
- Sometimes OS-specific adapter doesn't work, :'(
185
+ Sometimes OS-specific adapters don't work. :'(
170
186
  Here are some things you could try to avoid forcing polling.
171
187
 
172
- * [Update your Dropbox client](http://www.dropbox.com/downloading) (if used).
173
- * Move or rename the listened folder.
188
+ * [Update your Dropbox client](http://www.dropbox.com/downloading), if you have Dropbox installed.
189
+ * Move or rename the listened directory.
174
190
  * Update/reboot your OS.
175
191
  * Increase latency.
176
192
 
@@ -10,14 +10,7 @@ module Listen
10
10
  OPTIMIZED_ADAPTERS = %w[Darwin Linux BSD Windows]
11
11
  POLLING_FALLBACK_MESSAGE = "Listen will be polling for changes. Learn more at https://github.com/guard/listen#polling-fallback."
12
12
 
13
- def self.new(listener)
14
- adapter_class = _select(listener.options)
15
- adapter_class.new(listener)
16
- end
17
-
18
- private
19
-
20
- def self._select(options)
13
+ def self.select(options = {})
21
14
  return Polling if options[:force_polling]
22
15
  return _usable_adapter_class if _usable_adapter_class
23
16
 
@@ -25,6 +18,8 @@ module Listen
25
18
  Polling
26
19
  end
27
20
 
21
+ private
22
+
28
23
  def self._usable_adapter_class
29
24
  adapters = OPTIMIZED_ADAPTERS.map { |adapter| Adapter.const_get(adapter) }
30
25
  adapters.detect { |adapter| adapter.send(:usable?) }
@@ -32,7 +32,8 @@ module Listen
32
32
  end
33
33
 
34
34
  def _notify_change(path, options)
35
- Actor[:listen_change_pool].async.change(path, options) if listener.listen?
35
+ sleep 0.01 until listener.registry[:change_pool]
36
+ listener.registry[:change_pool].async.change(path, options) if listener.listen?
36
37
  end
37
38
  end
38
39
 
@@ -52,7 +52,7 @@ module Listen
52
52
 
53
53
  def _worker_callback
54
54
  lambda do |event|
55
- _notify_change(_event_path(event), type: 'file', change: _change(event.flags))
55
+ _notify_change(_event_path(event), type: 'File', change: _change(event.flags))
56
56
 
57
57
  # If it is a directory, and it has a write flag, it means a
58
58
  # file has been added so find out which and deal with it.
@@ -56,7 +56,7 @@ module Listen
56
56
  if _dir_event?(event)
57
57
  _notify_change(_event_path(event), type: 'Dir')
58
58
  else
59
- _notify_change(_event_path(event), type: 'file', change: _change(event.flags))
59
+ _notify_change(_event_path(event), type: 'File', change: _change(event.flags))
60
60
  end
61
61
  end
62
62
  end
@@ -43,7 +43,7 @@ module Listen
43
43
 
44
44
  def _worker_callback
45
45
  lambda do |change|
46
- _notify_change(_path(change.path), type: 'file', change: _change(change.type))
46
+ _notify_change(_path(change.path), type: 'File', change: _change(change.type))
47
47
  end
48
48
  end
49
49
 
data/lib/listen/change.rb CHANGED
@@ -12,7 +12,8 @@ module Listen
12
12
  end
13
13
 
14
14
  def change(path, options)
15
- return if _silencer.silenced?(path)
15
+ return if _silencer.silenced?(path, options[:type])
16
+
16
17
  if change = options[:change]
17
18
  _notify_listener(change, path)
18
19
  else
@@ -23,14 +24,14 @@ module Listen
23
24
  private
24
25
 
25
26
  def _file_change(path, options)
26
- change = File.new(path).change
27
+ change = File.new(listener, path).change
27
28
  if change && listener.listen? && !options[:silence]
28
29
  _notify_listener(change, path)
29
30
  end
30
31
  end
31
32
 
32
33
  def _dir_change(path, options)
33
- Directory.new(path, options).scan
34
+ Directory.new(listener, path, options).scan
34
35
  end
35
36
 
36
37
  def _notify_listener(change, path)
@@ -38,7 +39,7 @@ module Listen
38
39
  end
39
40
 
40
41
  def _silencer
41
- Celluloid::Actor[:listen_silencer]
42
+ listener.registry[:silencer]
42
43
  end
43
44
 
44
45
  end
@@ -1,8 +1,9 @@
1
1
  module Listen
2
2
  class Directory
3
- attr_accessor :path, :options
3
+ attr_accessor :listener, :path, :options
4
4
 
5
- def initialize(path, options = {})
5
+ def initialize(listener, path, options = {})
6
+ @listener = listener
6
7
  @path = path
7
8
  @options = options
8
9
  end
@@ -11,7 +12,8 @@ module Listen
11
12
  _update_record
12
13
  _all_entries.each do |entry_path, data|
13
14
  case data[:type]
14
- when 'File' then _async_change(entry_path, options.merge(type: 'File'))
15
+ when 'File'
16
+ _async_change(entry_path, options.merge(type: 'File'))
15
17
  when 'Dir'
16
18
  _async_change(entry_path, options.merge(type: 'Dir')) if _recursive_scan?(entry_path)
17
19
  end
@@ -34,6 +36,7 @@ module Listen
34
36
 
35
37
  def _entries
36
38
  return {} unless ::Dir.exists?(path)
39
+
37
40
  entries = ::Dir.entries(path) - %w[. ..]
38
41
  entries = entries.map { |entry| [entry, type: _entry_type(entry)] }
39
42
  Hash[*entries.flatten]
@@ -54,11 +57,11 @@ module Listen
54
57
  end
55
58
 
56
59
  def _record
57
- Celluloid::Actor[:listen_record]
60
+ listener.registry[:record]
58
61
  end
59
62
 
60
63
  def _change_pool
61
- Celluloid::Actor[:listen_change_pool]
64
+ listener.registry[:change_pool]
62
65
  end
63
66
 
64
67
  def _recursive_scan?(path)
data/lib/listen/file.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  module Listen
2
2
  class File
3
- attr_accessor :path, :data
3
+ attr_accessor :listener, :path, :data
4
4
 
5
- def initialize(path)
5
+ def initialize(listener, path)
6
+ @listener = listener
6
7
  @path = path
7
8
  @data = { type: 'File' }
8
9
  end
@@ -78,7 +79,7 @@ module Listen
78
79
  end
79
80
 
80
81
  def _record
81
- Celluloid::Actor[:listen_record]
82
+ listener.registry[:record]
82
83
  end
83
84
 
84
85
  def _mtime
@@ -7,6 +7,7 @@ require 'listen/silencer'
7
7
  module Listen
8
8
  class Listener
9
9
  attr_accessor :options, :directories, :paused, :changes, :block, :thread
10
+ attr_accessor :registry, :supervisor
10
11
 
11
12
  RELATIVE_PATHS_WITH_MULTIPLE_DIRECTORIES_WARNING_MESSAGE = "The relative_paths option doesn't work when listening to multiple diretories."
12
13
 
@@ -25,6 +26,8 @@ module Listen
25
26
  @directories = args.flatten.map { |path| Pathname.new(path).realpath }
26
27
  @changes = []
27
28
  @block = block
29
+ @registry = Celluloid::Registry.new
30
+ @supervisor = Celluloid::SupervisionGroup.run!(@registry)
28
31
  _init_debug
29
32
  end
30
33
 
@@ -36,7 +39,7 @@ module Listen
36
39
  _signals_trap
37
40
  _init_actors
38
41
  unpause
39
- Celluloid::Actor[:listen_adapter].async.start
42
+ registry[:adapter].async.start
40
43
  @thread = Thread.new { _wait_for_changes }
41
44
  end
42
45
 
@@ -56,7 +59,7 @@ module Listen
56
59
  # Unpauses listening callback
57
60
  #
58
61
  def unpause
59
- Celluloid::Actor[:listen_record].build
62
+ registry[:record].build
60
63
  @paused = false
61
64
  end
62
65
 
@@ -78,21 +81,30 @@ module Listen
78
81
 
79
82
  # Adds ignore patterns to the existing one (See DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in Listen::Silencer)
80
83
  #
81
- # @param [Regexp, Hash<Regexp>] new ignoring patterns.
84
+ # @param [Regexp, Array<Regexp>] new ignoring patterns.
82
85
  #
83
86
  def ignore(regexps)
84
87
  @options[:ignore] = [options[:ignore], regexps]
85
- Celluloid::Actor[:listen_silencer] = Silencer.new(self)
88
+ registry[:silencer] = Silencer.new(self)
86
89
  end
87
90
 
88
91
  # Overwrites ignore patterns (See DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in Listen::Silencer)
89
92
  #
90
- # @param [Regexp, Hash<Regexp>] new ignoring patterns.
93
+ # @param [Regexp, Array<Regexp>] new ignoring patterns.
91
94
  #
92
95
  def ignore!(regexps)
93
96
  @options.delete(:ignore)
94
97
  @options[:ignore!] = regexps
95
- Celluloid::Actor[:listen_silencer] = Silencer.new(self)
98
+ registry[:silencer] = Silencer.new(self)
99
+ end
100
+
101
+ # Sets only patterns, to listen only to specific regexps
102
+ #
103
+ # @param [Regexp, Array<Regexp>] new ignoring patterns.
104
+ #
105
+ def only(regexps)
106
+ @options[:only] = regexps
107
+ registry[:silencer] = Silencer.new(self)
96
108
  end
97
109
 
98
110
  private
@@ -114,10 +126,12 @@ module Listen
114
126
  end
115
127
 
116
128
  def _init_actors
117
- Celluloid::Actor[:listen_silencer] = Silencer.new(self)
118
- Celluloid::Actor[:listen_change_pool] = Change.pool(args: self)
119
- Celluloid::Actor[:listen_adapter] = Adapter.new(self)
120
- Celluloid::Actor[:listen_record] = Record.new(self)
129
+ supervisor.add(Silencer, as: :silencer, args: self)
130
+ supervisor.add(Record, as: :record, args: self)
131
+ supervisor.pool(Change, as: :change_pool, args: self)
132
+
133
+ adapter_class = Adapter.select(options)
134
+ supervisor.add(adapter_class, as: :adapter, args: self)
121
135
  end
122
136
 
123
137
  def _signals_trap
@@ -138,8 +152,7 @@ module Listen
138
152
  sleep options[:wait_for_delay]
139
153
  end
140
154
 
141
- _terminate_actors
142
- exit
155
+ supervisor.finalize
143
156
  rescue => ex
144
157
  Kernel.warn "[Listen warning]: Change block raised an exception: #{$!}"
145
158
  Kernel.warn "Backtrace:\n\t#{ex.backtrace.join("\n\t")}"
@@ -153,12 +166,5 @@ module Listen
153
166
  end
154
167
  changes.each { |_, v| v.uniq! }
155
168
  end
156
-
157
- def _terminate_actors
158
- Celluloid::Actor[:listen_adapter].terminate
159
- Celluloid::Actor[:listen_silencer].terminate
160
- Celluloid::Actor[:listen_change_pool].terminate
161
- Celluloid::Actor[:listen_record].terminate
162
- end
163
169
  end
164
170
  end
data/lib/listen/record.rb CHANGED
@@ -28,7 +28,7 @@ module Listen
28
28
  def build
29
29
  @paths = _init_paths
30
30
  listener.directories.each do |path|
31
- Actor[:listen_change_pool].change(path, type: 'Dir', recursive: true, silence: true)
31
+ listener.registry[:change_pool].change(path, type: 'Dir', recursive: true, silence: true)
32
32
  end
33
33
  end
34
34
 
@@ -8,28 +8,41 @@ module Listen
8
8
  # The default list of files that get ignored.
9
9
  DEFAULT_IGNORED_EXTENSIONS = %w[.DS_Store .tmp]
10
10
 
11
- attr_accessor :listener, :patterns
11
+ attr_accessor :listener, :only_patterns, :ignore_patterns
12
12
 
13
13
  def initialize(listener)
14
14
  @listener = listener
15
- _init_patterns
15
+ _init_only_patterns
16
+ _init_ignore_patterns
16
17
  end
17
18
 
18
- def silenced?(path)
19
- patterns.any? { |pattern| _relative_path(path) =~ pattern }
19
+ def silenced?(path, type = 'Unknown')
20
+ silenced = false
21
+
22
+ if only_patterns && type == 'File'
23
+ silenced = !only_patterns.any? { |pattern| _relative_path(path) =~ pattern }
24
+ end
25
+
26
+ silenced ||= ignore_patterns.any? { |pattern| _relative_path(path) =~ pattern }
20
27
  end
21
28
 
22
29
  private
23
30
 
24
- def _init_patterns
25
- @patterns = []
26
- @patterns << _default_patterns unless listener.options[:ignore!]
27
- @patterns << listener.options[:ignore] << listener.options[:ignore!]
28
- @patterns.compact!
29
- @patterns.flatten!
31
+ def _init_only_patterns
32
+ if listener.options[:only]
33
+ @only_patterns = Array(listener.options[:only])
34
+ end
35
+ end
36
+
37
+ def _init_ignore_patterns
38
+ @ignore_patterns = []
39
+ @ignore_patterns << _default_ignore_patterns unless listener.options[:ignore!]
40
+ @ignore_patterns << listener.options[:ignore] << listener.options[:ignore!]
41
+ @ignore_patterns.compact!
42
+ @ignore_patterns.flatten!
30
43
  end
31
44
 
32
- def _default_patterns
45
+ def _default_ignore_patterns
33
46
  [_default_ignored_directories_patterns, _default_ignored_extensions_patterns]
34
47
  end
35
48
 
@@ -1,3 +1,3 @@
1
1
  module Listen
2
- VERSION = '2.2.0'
2
+ VERSION = '2.3.1'
3
3
  end
@@ -13,13 +13,7 @@ describe "Listen" do
13
13
  @listener = setup_listener(options, callback)
14
14
  @listener.start
15
15
  }
16
- after {
17
- begin
18
- listener.stop
19
- rescue SystemExit
20
- # ignore the SystemExit error from the thread
21
- end
22
- }
16
+ after { listener.stop }
23
17
 
24
18
  context "with one listen dir" do
25
19
  let(:paths) { Pathname.new(Dir.pwd) }
@@ -158,6 +152,17 @@ describe "Listen" do
158
152
  end
159
153
  end
160
154
 
155
+ context "default ignored dir with file in listen dir" do
156
+ around { |example| mkdir_p '.bundle'; touch '.bundle/file.rb'; example.run }
157
+ let(:options) { { force_polling: polling, latency: 0.1 } }
158
+
159
+ it "doesn't listen to file touch" do
160
+ expect(listen {
161
+ touch '.bundle/file.rb'
162
+ }).to eq({ modified: [], added: [], removed: [] })
163
+ end
164
+ end
165
+
161
166
  context "ignored dir with file in listen dir" do
162
167
  around { |example| mkdir_p 'ignored_dir'; touch 'ignored_dir/file.rb'; example.run }
163
168
  let(:options) { { force_polling: polling, latency: 0.1, ignore: /ignored_dir/ } }
@@ -180,6 +185,29 @@ describe "Listen" do
180
185
  end
181
186
  end
182
187
 
188
+ context "with only option" do
189
+ let(:options) { { force_polling: polling, latency: 0.1, only: /\.rb$/ } }
190
+
191
+ it "listens only to file touch matching with only patterns" do
192
+ expect(listen {
193
+ touch 'file.rb'
194
+ touch 'file.txt'
195
+ }).to eq({ modified: [], added: ['file.rb'], removed: [] })
196
+ end
197
+ end
198
+
199
+ context "with ignore and only option" do
200
+ let(:options) { { force_polling: polling, latency: 0.1, ignore: /bar\.rb$/, only: /\.rb$/ } }
201
+
202
+ it "listens only to file touch matching with only patterns" do
203
+ expect(listen {
204
+ touch 'file.rb'
205
+ touch 'bar.rb'
206
+ touch 'file.txt'
207
+ }).to eq({ modified: [], added: ['file.rb'], removed: [] })
208
+ end
209
+ end
210
+
183
211
  describe "#ignore" do
184
212
  around { |example| touch 'file.rb'; example.run }
185
213
  let(:options) { { force_polling: polling, latency: 0.1, ignore: /\.rb$/ } }
@@ -2,7 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter::Base do
4
4
  let(:adapter) { described_class.new(listener) }
5
- let(:listener) { double(Listen::Listener, options: {}) }
5
+ let(:registry) { double(Celluloid::Registry) }
6
+ let(:listener) { double(Listen::Listener, registry: registry, options: {}) }
6
7
 
7
8
  describe "#_latency" do
8
9
  it "returns default_latency with listener actor latency not present" do
@@ -20,7 +21,7 @@ describe Listen::Adapter::Base do
20
21
  let(:change_pool_async) { double('ChangePoolAsync') }
21
22
  before {
22
23
  change_pool.stub(:async) { change_pool_async }
23
- Celluloid::Actor.stub(:[]).with(:listen_change_pool) { change_pool }
24
+ registry.stub(:[]).with(:change_pool) { change_pool }
24
25
  }
25
26
 
26
27
  context "listener listen" do
@@ -1,13 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter::Polling do
4
- let(:listener) { double(Listen::Listener, options: {}, listen?: true) }
4
+ let(:registry) { double(Celluloid::Registry) }
5
+ let(:listener) { double(Listen::Listener, registry: registry, options: {}, listen?: true) }
5
6
  let(:adapter) { described_class.new(listener) }
6
7
  let(:change_pool) { double(Listen::Change, terminate: true) }
7
8
  let(:change_pool_async) { double('ChangePoolAsync') }
8
9
  before {
9
10
  change_pool.stub(:async) { change_pool_async }
10
- Celluloid::Actor.stub(:[]).with(:listen_change_pool) { change_pool }
11
+ registry.stub(:[]).with(:change_pool) { change_pool }
11
12
  }
12
13
 
13
14
  describe ".usable?" do
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter do
4
- let(:adapter) { Listen::Adapter.new(listener) }
5
4
  let(:listener) { double(Listen::Listener, options: {}) }
6
5
  before {
7
6
  Listen::Adapter::BSD.stub(:usable?) { false }
@@ -10,58 +9,57 @@ describe Listen::Adapter do
10
9
  Listen::Adapter::Windows.stub(:usable?) { false }
11
10
  }
12
11
 
13
- describe ".new" do
12
+ describe ".select" do
14
13
  it "returns Polling adapter if forced" do
15
- listener.stub(:options) { { force_polling: true } }
16
- expect(adapter).to be_kind_of Listen::Adapter::Polling
14
+ klass = Listen::Adapter.select(force_polling: true)
15
+ expect(klass).to eq Listen::Adapter::Polling
17
16
  end
18
17
 
19
18
  it "returns BSD adapter when usable" do
20
19
  Listen::Adapter::BSD.stub(:usable?) { true }
21
- expect(Listen::Adapter::BSD).to receive(:new)
22
- adapter
20
+ klass = Listen::Adapter.select
21
+ expect(klass).to eq Listen::Adapter::BSD
23
22
  end
24
23
 
25
24
  it "returns Darwin adapter when usable" do
26
25
  Listen::Adapter::Darwin.stub(:usable?) { true }
27
- expect(Listen::Adapter::Darwin).to receive(:new)
28
- adapter
26
+ klass = Listen::Adapter.select
27
+ expect(klass).to eq Listen::Adapter::Darwin
29
28
  end
30
29
 
31
30
  it "returns Linux adapter when usable" do
32
31
  Listen::Adapter::Linux.stub(:usable?) { true }
33
- expect(Listen::Adapter::Linux).to receive(:new)
34
- adapter
32
+ klass = Listen::Adapter.select
33
+ expect(klass).to eq Listen::Adapter::Linux
35
34
  end
36
35
 
37
36
  it "returns Windows adapter when usable" do
38
37
  Listen::Adapter::Windows.stub(:usable?) { true }
39
- expect(Listen::Adapter::Windows).to receive(:new)
40
- adapter
38
+ klass = Listen::Adapter.select
39
+ expect(klass).to eq Listen::Adapter::Windows
41
40
  end
42
41
 
43
42
  context "no usable adapters" do
44
43
  before { Kernel.stub(:warn) }
45
44
 
46
45
  it "returns Polling adapter" do
47
- expect(adapter).to be_kind_of Listen::Adapter::Polling
46
+ klass = Listen::Adapter.select(force_polling: true)
47
+ expect(klass).to eq Listen::Adapter::Polling
48
48
  end
49
49
 
50
50
  it "warns polling fallback with default message" do
51
51
  expect(Kernel).to receive(:warn).with("[Listen warning]:\n #{described_class::POLLING_FALLBACK_MESSAGE}")
52
- adapter
52
+ Listen::Adapter.select
53
53
  end
54
54
 
55
55
  it "doesn't warn if polling_fallback_message is false" do
56
- listener.stub(:options) { { polling_fallback_message: false } }
57
56
  expect(Kernel).to_not receive(:warn)
58
- adapter
57
+ Listen::Adapter.select(polling_fallback_message: false)
59
58
  end
60
59
 
61
60
  it "warns polling fallback with custom message if set" do
62
- listener.stub(:options) { { polling_fallback_message: 'custom fallback message' } }
63
61
  expect(Kernel).to receive(:warn).with("[Listen warning]:\n custom fallback message")
64
- adapter
62
+ Listen::Adapter.select(polling_fallback_message: 'custom fallback message')
65
63
  end
66
64
  end
67
65
  end
@@ -2,15 +2,16 @@ require 'spec_helper'
2
2
 
3
3
  describe Listen::Change do
4
4
  let(:change) { Listen::Change.new(listener) }
5
- let(:listener) { double(Listen::Listener, options: {}) }
5
+ let(:registry) { double(Celluloid::Registry) }
6
+ let(:listener) { double(Listen::Listener, registry: registry, options: {}) }
6
7
  let(:listener_changes) { double("listener_changes") }
7
8
  before {
8
9
  listener.stub(:changes) { listener_changes }
9
10
  }
10
11
 
11
12
  describe "#change" do
12
- let(:silencer) { double(Listen::Silencer, silenced?: false) }
13
- before { Celluloid::Actor.stub(:[]).with(:listen_silencer) { silencer } }
13
+ let(:silencer) { double('Listen::Silencer', silenced?: false) }
14
+ before { registry.stub(:[]).with(:silencer) { silencer } }
14
15
 
15
16
  context "file path" do
16
17
  context "with known change" do
@@ -20,25 +21,28 @@ describe Listen::Change do
20
21
  end
21
22
 
22
23
  it "doesn't notify to listener if path is silenced" do
23
- expect(silencer).to receive(:silenced?).with('file_path') { true }
24
+ # expect(silencer).to receive(:silenced?).with('file_path', 'File').and_return(true)
25
+ expect(silencer).to receive(:silenced?).and_return(true)
24
26
  expect(listener_changes).to_not receive(:<<)
27
+
25
28
  change.change('file_path', type: 'File', change: :modified)
26
29
  end
27
30
  end
28
31
 
29
32
  context "with unknown change" do
30
- let(:file) { double(Listen::File) }
33
+ let(:file) { double('Listen::File') }
31
34
  before { Listen::File.stub(:new) { file } }
32
35
 
33
36
  it "calls Listen::File#change" do
34
- expect(Listen::File).to receive(:new).with('file_path') { file }
37
+ expect(Listen::File).to receive(:new).with(listener, 'file_path') { file }
35
38
  expect(file).to receive(:change)
36
39
  change.change('file_path', type: 'File')
37
40
  end
38
41
 
39
42
  it "doesn't call Listen::File#change if path is silenced" do
40
- expect(silencer).to receive(:silenced?).with('file_path') { true }
43
+ expect(silencer).to receive(:silenced?).with('file_path', 'File').and_return(true)
41
44
  expect(Listen::File).to_not receive(:new)
45
+
42
46
  change.change('file_path', type: 'File')
43
47
  end
44
48
 
@@ -88,7 +92,7 @@ describe Listen::Change do
88
92
  before { Listen::Directory.stub(:new) { dir } }
89
93
 
90
94
  it "calls Listen::Directory#scan" do
91
- expect(Listen::Directory).to receive(:new).with('dir_path', dir_options) { dir }
95
+ expect(Listen::Directory).to receive(:new).with(listener, 'dir_path', dir_options) { dir }
92
96
  expect(dir).to receive(:scan)
93
97
  change.change('dir_path', dir_options)
94
98
  end
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Directory do
4
+ let(:registry) { double(Celluloid::Registry) }
5
+ let(:listener) { double(Listen::Listener, registry: registry, options: {}) }
4
6
  let(:record) { double(Listen::Record, async: double(set_path: true, unset_path: true)) }
5
7
  let(:change_pool) { double(Listen::Change) }
6
8
  let(:change_pool_async) { double('ChangePoolAsync') }
@@ -8,8 +10,8 @@ describe Listen::Directory do
8
10
  around { |example| fixtures { |path| example.run } }
9
11
  before {
10
12
  change_pool.stub(:async) { change_pool_async }
11
- Celluloid::Actor.stub(:[]).with(:listen_record) { record }
12
- Celluloid::Actor.stub(:[]).with(:listen_change_pool) { change_pool }
13
+ registry.stub(:[]).with(:record) { record }
14
+ registry.stub(:[]).with(:change_pool) { change_pool }
13
15
  }
14
16
 
15
17
  describe "#scan" do
@@ -18,7 +20,7 @@ describe Listen::Directory do
18
20
  let(:other_file_path) { dir_path.join('other_file.rb') }
19
21
  let(:inside_dir_path) { dir_path.join('inside_dir') }
20
22
  let(:other_inside_dir_path) { dir_path.join('other_inside_dir') }
21
- let(:dir) { Listen::Directory.new(dir_path, options) }
23
+ let(:dir) { Listen::Directory.new(listener, dir_path, options) }
22
24
 
23
25
  context "with recursive off" do
24
26
  let(:options) { { recursive: false } }
@@ -1,14 +1,16 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::File do
4
+ let(:registry) { double(Celluloid::Registry) }
5
+ let(:listener) { double(Listen::Listener, registry: registry, options: {}) }
4
6
  let(:record) { double(Listen::Record, async: double(set_path: true, unset_path: true)) }
5
7
  let(:path) { Pathname.new(Dir.pwd) }
6
8
  around { |example| fixtures { |path| example.run } }
7
- before { Celluloid::Actor.stub(:[]).with(:listen_record) { record } }
9
+ before { registry.stub(:[]).with(:record) { record } }
8
10
 
9
11
  describe "#change" do
10
12
  let(:file_path) { path.join('file.rb') }
11
- let(:file) { Listen::File.new(file_path) }
13
+ let(:file) { Listen::File.new(listener, file_path) }
12
14
  let(:expected_data) {
13
15
  if darwin?
14
16
  { type: 'File', mtime: kind_of(Float), mode: kind_of(Integer), md5: kind_of(String) }
@@ -3,16 +3,21 @@ require 'spec_helper'
3
3
  describe Listen::Listener do
4
4
  let(:listener) { Listen::Listener.new(options) }
5
5
  let(:options) { {} }
6
+ let(:registry) { double(Celluloid::Registry, :[]= => true) }
7
+ let(:supervisor) { double(Celluloid::SupervisionGroup, add: true, pool: true) }
6
8
  let(:record) { double(Listen::Record, terminate: true, build: true) }
7
9
  let(:silencer) { double(Listen::Silencer, terminate: true) }
8
10
  let(:adapter) { double(Listen::Adapter::Base) }
9
11
  let(:change_pool) { double(Listen::Change, terminate: true) }
10
12
  let(:change_pool_async) { double('ChangePoolAsync') }
11
13
  before {
12
- Celluloid::Actor.stub(:[]).with(:listen_silencer) { silencer }
13
- Celluloid::Actor.stub(:[]).with(:listen_adapter) { adapter }
14
- Celluloid::Actor.stub(:[]).with(:listen_record) { record }
15
- Celluloid::Actor.stub(:[]).with(:listen_change_pool) { change_pool }
14
+ Celluloid::Registry.stub(:new) { registry }
15
+ Celluloid::SupervisionGroup.stub(:run!) { supervisor }
16
+ registry.stub(:[]).with(:silencer) { silencer }
17
+ registry.stub(:[]).with(:adapter) { adapter }
18
+ registry.stub(:[]).with(:record) { record }
19
+ registry.stub(:[]).with(:change_pool) { change_pool }
20
+
16
21
  }
17
22
 
18
23
  describe "initialize" do
@@ -55,12 +60,6 @@ describe Listen::Listener do
55
60
 
56
61
  describe "#start" do
57
62
  before {
58
- Listen::Silencer.stub(:new)
59
- Listen::Change.stub(:pool)
60
- Listen::Adapter.stub(:new)
61
- Listen::Record.stub(:new)
62
- Celluloid::Actor.stub(:[]=)
63
- Celluloid.stub(:cores) { 1 }
64
63
  adapter.stub_chain(:async, :start)
65
64
  }
66
65
 
@@ -70,26 +69,23 @@ describe Listen::Listener do
70
69
  end
71
70
 
72
71
  it "registers silencer" do
73
- expect(Listen::Silencer).to receive(:new).with(listener) { silencer }
74
- expect(Celluloid::Actor).to receive(:[]=).with(:listen_silencer, silencer)
72
+ expect(supervisor).to receive(:add).with(Listen::Silencer, as: :silencer, args: listener)
75
73
  listener.start
76
74
  end
77
75
 
78
- it "registers change_pool" do
79
- expect(Listen::Change).to receive(:pool).with(args: listener) { change_pool }
80
- expect(Celluloid::Actor).to receive(:[]=).with(:listen_change_pool, change_pool)
76
+ it "supervises change_pool" do
77
+ expect(supervisor).to receive(:pool).with(Listen::Change, as: :change_pool, args: listener)
81
78
  listener.start
82
79
  end
83
80
 
84
- it "registers adaper" do
85
- expect(Listen::Adapter).to receive(:new).with(listener) { adapter }
86
- expect(Celluloid::Actor).to receive(:[]=).with(:listen_adapter, adapter)
81
+ it "supervises adaper" do
82
+ Listen::Adapter.stub(:select) { Listen::Adapter::Polling }
83
+ expect(supervisor).to receive(:add).with(Listen::Adapter::Polling, as: :adapter, args: listener)
87
84
  listener.start
88
85
  end
89
86
 
90
- it "registers record" do
91
- expect(Listen::Record).to receive(:new).with(listener) { record }
92
- expect(Celluloid::Actor).to receive(:[]=).with(:listen_record, record)
87
+ it "supervises record" do
88
+ expect(supervisor).to receive(:add).with(Listen::Record, as: :record, args: listener)
93
89
  listener.start
94
90
  end
95
91
 
@@ -191,9 +187,9 @@ describe Listen::Listener do
191
187
  let(:new_silencer) { double(Listen::Silencer) }
192
188
  before { Celluloid::Actor.stub(:[]=) }
193
189
 
194
- it "resets silencer actor with new pattern" do
190
+ it "resets silencer actor" do
195
191
  expect(Listen::Silencer).to receive(:new).with(listener) { new_silencer }
196
- expect(Celluloid::Actor).to receive(:[]=).with(:listen_silencer, new_silencer)
192
+ expect(registry).to receive(:[]=).with(:silencer, new_silencer)
197
193
  listener.ignore(/foo/)
198
194
  end
199
195
 
@@ -222,9 +218,9 @@ describe Listen::Listener do
222
218
  let(:new_silencer) { double(Listen::Silencer) }
223
219
  before { Celluloid::Actor.stub(:[]=) }
224
220
 
225
- it "resets silencer actor with new pattern" do
221
+ it "resets silencer actor" do
226
222
  expect(Listen::Silencer).to receive(:new).with(listener) { new_silencer }
227
- expect(Celluloid::Actor).to receive(:[]=).with(:listen_silencer, new_silencer)
223
+ expect(registry).to receive(:[]=).with(:silencer, new_silencer)
228
224
  listener.ignore!(/foo/)
229
225
  expect(listener.options).to include(ignore!: /foo/)
230
226
  end
@@ -250,4 +246,25 @@ describe Listen::Listener do
250
246
  end
251
247
  end
252
248
 
249
+ describe "#only" do
250
+ let(:new_silencer) { double(Listen::Silencer) }
251
+ before { Celluloid::Actor.stub(:[]=) }
252
+
253
+ it "resets silencer actor" do
254
+ expect(Listen::Silencer).to receive(:new).with(listener) { new_silencer }
255
+ expect(registry).to receive(:[]=).with(:silencer, new_silencer)
256
+ listener.only(/foo/)
257
+ end
258
+
259
+ context "with existing only options" do
260
+ let(:options) { { only: /bar/ } }
261
+
262
+ it "overwrites existing ignore options" do
263
+ expect(Listen::Silencer).to receive(:new).with(listener)
264
+ listener.only([/foo/])
265
+ expect(listener.options).to include(only: [/foo/])
266
+ end
267
+ end
268
+ end
269
+
253
270
  end
@@ -1,7 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Record do
4
- let(:listener) { double(Listen::Listener, options: {}) }
4
+ let(:registry) { double(Celluloid::Registry) }
5
+ let(:listener) { double(Listen::Listener, registry: registry, options: {}) }
5
6
  let(:record) { Listen::Record.new(listener) }
6
7
  let(:path) { '/dir/path/file.rb' }
7
8
  let(:data) { { type: 'File' } }
@@ -74,7 +75,7 @@ describe Listen::Record do
74
75
  let(:change_pool) { double(Listen::Change, terminate: true) }
75
76
  before {
76
77
  change_pool.stub(:change)
77
- Celluloid::Actor.stub(:[]).with(:listen_change_pool) { change_pool }
78
+ registry.stub(:[]).with(:change_pool) { change_pool }
78
79
  listener.stub(:directories) { directories }
79
80
  }
80
81
 
@@ -49,26 +49,28 @@ describe Listen::Silencer do
49
49
  end
50
50
  end
51
51
 
52
- context "with ignore options" do
53
- let(:options) { { ignore: [%r{^foo/bar}, /\.pid$/] } }
52
+ context 'with ignore options (regexp)' do
53
+ let(:options) { { ignore: /\.pid$/ } }
54
54
 
55
- it "silences custom ignored directory" do
56
- path = pwd.join('foo', 'bar')
57
- expect(silencer.silenced?(path)).to be_true
55
+ it "silences path matching custom ignore regex" do
56
+ expect(silencer.silenced?(pwd.join('foo.pid'))).to be_true
58
57
  end
58
+ end
59
+
60
+ context 'with ignore options (array)' do
61
+ let(:options) { { ignore: [%r{^foo/bar}, /\.pid$/] } }
59
62
 
60
- it "silences custom ignored extension" do
61
- path = pwd.join('foo.pid')
62
- expect(silencer.silenced?(path)).to be_true
63
+ it "silences paths matching custom ignore regexes" do
64
+ expect(silencer.silenced?(pwd.join('foo/bar/baz'))).to be_true
65
+ expect(silencer.silenced?(pwd.join('foo.pid'))).to be_true
63
66
  end
64
67
  end
65
68
 
66
69
  context "with ignore! options" do
67
- let(:options) { { ignore!: %r{foo/bar} } }
70
+ let(:options) { { ignore!: /\.pid$/ } }
68
71
 
69
72
  it "silences custom ignored directory" do
70
- path = pwd.join('foo', 'bar')
71
- expect(silencer.silenced?(path)).to be_true
73
+ expect(silencer.silenced?(pwd.join('foo.pid'))).to be_true
72
74
  end
73
75
 
74
76
  it "doesn't silence default ignored directory" do
@@ -77,6 +79,73 @@ describe Listen::Silencer do
77
79
  end
78
80
  end
79
81
 
82
+ context "with only options (regexp)" do
83
+ let(:options) { { only: %r{foo} } }
84
+
85
+ it "do not take only regex in account if type is Unknown" do
86
+ path = pwd.join('baz')
87
+ expect(silencer.silenced?(path)).to be_false
88
+ end
89
+
90
+ it "do not silence path matches only regex if type is File" do
91
+ path = pwd.join('foo')
92
+ expect(silencer.silenced?(path, 'File')).to be_false
93
+ end
94
+
95
+ it "silences other directory" do
96
+ path = pwd.join('bar')
97
+ expect(silencer.silenced?(path, 'File')).to be_true
98
+ end
99
+ end
100
+
101
+ context "with only options (array)" do
102
+ let(:options) { { only: [%r{^foo/}, %r{\.txt$}] } }
103
+
104
+ it "do not take only regex in account if type is Unknown" do
105
+ expect(silencer.silenced?(pwd.join('baz'))).to be_false
106
+ end
107
+
108
+ it "doesn't silence good directory" do
109
+ expect(silencer.silenced?(pwd.join('foo/bar.rb'), 'File')).to be_false
110
+ end
111
+
112
+ it "doesn't silence good file" do
113
+ expect(silencer.silenced?(pwd.join('bar.txt'), 'File')).to be_false
114
+ end
115
+
116
+ it "silences other directory" do
117
+ expect(silencer.silenced?(pwd.join('bar/baz.rb'), 'File')).to be_true
118
+ end
119
+
120
+ it "silences other file" do
121
+ expect(silencer.silenced?(pwd.join('bar.rb'), 'File')).to be_true
122
+ end
123
+ end
124
+
125
+ context 'with ignore and only options' do
126
+ let(:options) { { only: /\.pid$/, ignore: %r{^bar} } }
127
+
128
+ it "do not take only regex in account if type is Unknown" do
129
+ expect(silencer.silenced?(pwd.join('baz'))).to be_false
130
+ end
131
+
132
+ it "do not take only regex in account if type is Unknown but silences if ignore regex matches path" do
133
+ expect(silencer.silenced?(pwd.join('bar'))).to be_true
134
+ end
135
+
136
+ it 'silences path not matching custom only regex' do
137
+ expect(silencer.silenced?(pwd.join('foo.rb'), 'File')).to be_true
138
+ end
139
+
140
+ it 'silences path matching custom ignore regex' do
141
+ expect(silencer.silenced?(pwd.join('bar.pid', 'File'))).to be_true
142
+ end
143
+
144
+ it 'do not silence path matching custom only regex and not matching custom ignore regex' do
145
+ expect(silencer.silenced?(pwd.join('foo.pid', 'File'))).to be_false
146
+ end
147
+ end
148
+
80
149
  it "doesn't silence normal path" do
81
150
  path = pwd.join('some_dir', 'some_file.rb')
82
151
  expect(silencer.silenced?(path)).to be_false
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: listen
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thibaud Guillaume-Gentil
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-29 00:00:00.000000000 Z
11
+ date: 2013-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: celluloid
@@ -181,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
181
  version: '0'
182
182
  requirements: []
183
183
  rubyforge_project:
184
- rubygems_version: 2.1.9
184
+ rubygems_version: 2.0.14
185
185
  signing_key:
186
186
  specification_version: 4
187
187
  summary: Listen to file modifications
@@ -205,3 +205,4 @@ test_files:
205
205
  - spec/support/acceptance_helper.rb
206
206
  - spec/support/fixtures_helper.rb
207
207
  - spec/support/platform_helper.rb
208
+ has_rdoc: