listen 2.2.0 → 2.3.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 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: