listen 0.1.0 → 0.2.0

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.
data/CHANGELOG.md CHANGED
@@ -1,7 +1,15 @@
1
1
  ## Master
2
2
 
3
+ - Add checksum comparaison support for detecting consecutive file modifications made during the same second. ([@thibaudgg][])
4
+ - Add rb-fchange support. ([@thibaudgg][])
5
+ - Add rb-inotify support. ([@thibaudgg][] with [@Maher4Ever][] help)
6
+ - Add rb-fsevent support. ([@thibaudgg][])
7
+ - Add non-recursive diff with multiple directories support. ([@thibaudgg][])
8
+ - Ignore .DS_Store by default. ([@thibaudgg][])
9
+
3
10
  ## 0.1.0 - January 28, 2012
4
11
 
5
- - First version with only a polling adapter and basic features set. ([@thibaudgg][])
12
+ - First version with only a polling adapter and basic features set (ignore & filter). ([@thibaudgg][])
6
13
 
7
- [@thibaudgg]: https://github.com/thibaudgg
14
+ [@thibaudgg]: https://github.com/thibaudgg
15
+ [@Maher4Ever]: https://github.com/Maher4Ever
data/README.md CHANGED
@@ -1,63 +1,99 @@
1
1
  # Listen [![Build Status](https://secure.travis-ci.org/guard/listen.png?branch=master)](http://travis-ci.org/guard/listen)
2
2
 
3
- Work in progress...
3
+ **Work in progress...**
4
4
 
5
5
  The Listen gem listens to file modifications and notifies you about the changes.
6
6
 
7
- Here the API that should be implemented, feel free to give your feeback via [Listen issues](https://github.com/guard/listener/issues)
7
+ ## TODO
8
8
 
9
- ## Block API
9
+ - **DONE** Add polling support
10
+ - **DONE** Add `rb-fsevent` support
11
+ - **DONE** Add `rb-inotify` support
12
+ - **DONE** Add `rb-fchange` support
13
+ - **DONE** Add checksum comparaison support for detecting consecutive file modifications made during the same second. (like Guard)
14
+ - Add latency option
15
+ - Add polling option (true: polling forced, false: polling never used (to skip DropBox polling fallback))
16
+ - Dropbox detection with polling fallback (if needed)
17
+ - Improve API (if needed)
10
18
 
11
- ### One dir
19
+ ## Install
12
20
 
13
- ``` ruby
14
- Listen.to(dir, filter: '**/*', ignore: paths) do |modified, added, removed|
15
- ...
16
- end
21
+ ``` bash
22
+ gem install listen
17
23
  ```
18
24
 
19
- ### Multiple dir
25
+ ## Usage
26
+
27
+ There are two ways you can use Listen.
28
+
29
+ 1. call `Listen.to` with a path params, and define callbacks in a block.
30
+ 3. create a `listener` object usable in an (ARel style) chainable way.
31
+
32
+ Feel free to give your feeback via [Listen issues](https://github.com/guard/listener/issues)
33
+
34
+ ### Block API
35
+
36
+ #### One dir
20
37
 
21
38
  ``` ruby
22
- Listen.to do
23
- path(dir1, filter: '**/*', ignore: paths) do |modified, added, removed|
24
- ...
25
- end
26
- path(dir2, filter: '**/*', ignore: paths) do |modified, added, removed|
27
- ...
28
- end
29
- ....
39
+ Listen.to('dir/path/to/listen', filter: /.*\.rb/, ignore: '/ignored/path') do |modified, added, removed|
40
+ # ...
30
41
  end
31
42
  ```
32
43
 
33
- Question: if dir2 is a child of dir1 both path block will be call if a file inside dir2 is modified right?
34
-
35
- ## "Object" API
44
+ ### "Object" API
36
45
 
37
46
  ``` ruby
38
- listen = Listen.to(dir)
39
- listen.ignore('.git')
40
- listen.filter('*.rb')
41
- listen.modification(&on_modification)
42
- listen.addition(&on_addition)
43
- listen.removal(&on_removal)
44
- listen.start # enter the run loop
45
- listen.stop
47
+ listener = Listen.to('dir/path/to/listen')
48
+ listener = listener.ignore('/ignored/path')
49
+ listener = listener.filter(/.*\.rb/)
50
+ listener = listener.change(&callback)
51
+ listener.start # enter the run loop
52
+ listener.stop
46
53
  ```
47
54
 
48
- ### Chainable
55
+ #### Chainable
49
56
 
50
57
  ``` ruby
51
- Listen.to(dir).ignore('.git').filter('*.rb').modification(&on_modification).addition(&on_addition).removal(&on_removal).start # enter the run loop
58
+ Listen.to('dir/path/to/listen').ignore('/ignored/path').filter(/.*\.rb/).change(&callback).start # enter the run loop
52
59
  ```
53
60
 
54
- ### Multiple dir support available via Thread.
61
+ #### Multiple listeners support available via Thread
55
62
 
56
63
  ``` ruby
57
- listen = Listen.ignore('.git')
58
- styles = listen.to(dir1).filter('*.css').addition(&on_style_addition)
59
- scripts = listen.to(dir2).filter('*.js').addition(&on_script_addition)
64
+ listener = Listen.to(dir1).ignore('/ignored/path/')
65
+ styles = listener.filter(/.*\.css/).change(&style_callback)
66
+ scripts = listener.filter(/.*\.js/).change(&scripts_callback)
60
67
 
61
68
  Thread.new { styles.start } # enter the run loop
62
69
  Thread.new { scripts.start } # enter the run loop
63
- ```
70
+ ```
71
+
72
+ ### Options
73
+
74
+ These options can be set through `Listen.to` params or via methods (see the "Object" API)
75
+
76
+ ```ruby
77
+ :filter => /.*\.rb/, /.*\.coffee/ # Filter files to listen to via a regexps list.
78
+ # default: none
79
+
80
+ :ignore => 'path1', 'path2' # Ignore a list of paths (root directory or sub-dir)
81
+ # default: '.bundle', '.git', '.DS_Store', 'log', 'tmp', 'vendor'
82
+ ```
83
+
84
+ ## Acknowledgment
85
+
86
+ - [Travis Tilley (ttilley)][] for this awesome work on [fssm][] & [rb-fsevent][].
87
+ - [Nathan Weizenbaum (nex3)][] for [rb-inotify][], a thorough inotify wrapper.
88
+ - [stereobooster][] for [rb-fchange][], windows support wouldn't exist without him.
89
+ - [Yehuda Katz (wycats)][] for [vigilo][], that has been a great source of inspiration.
90
+
91
+ [Travis Tilley (ttilley)]: https://github.com/ttilley
92
+ [fssm]: https://github.com/ttilley/fssm
93
+ [rb-fsevent]: https://github.com/thibaudgg/rb-fsevent
94
+ [Nathan Weizenbaum (nex3)]: https://github.com/nex3
95
+ [rb-inotify]: https://github.com/nex3/rb-inotify
96
+ [stereobooster]: https://github.com/stereobooster
97
+ [rb-fchange]: https://github.com/stereobooster/rb-fchange
98
+ [Yehuda Katz (wycats)]: https://github.com/wycats
99
+ [vigilo]: https://github.com/wycats/vigilo
data/lib/listen.rb CHANGED
@@ -21,4 +21,4 @@ module Listen
21
21
  block ? listener.start : listener
22
22
  end
23
23
 
24
- end
24
+ end
@@ -1,5 +1,8 @@
1
+ require 'rbconfig'
2
+
1
3
  module Listen
2
4
  class Adapter
5
+ attr_accessor :latency
3
6
 
4
7
  # Select the appropriate adapter implementation for the
5
8
  # current OS and initializes it.
@@ -7,12 +10,30 @@ module Listen
7
10
  # @return [Listen::Adapter] the chosen adapter
8
11
  #
9
12
  def self.select_and_initialize(listener)
10
- Adapters::Polling.new(listener)
13
+ if Adapters::Darwin.usable?
14
+ Adapters::Darwin.new(listener)
15
+ elsif Adapters::Linux.usable?
16
+ Adapters::Linux.new(listener)
17
+ elsif Adapters::Windows.usable?
18
+ Adapters::Windows.new(listener)
19
+ else
20
+ Adapters::Polling.new(listener)
21
+ end
11
22
  end
12
23
 
13
24
  def initialize(listener)
14
25
  @listener = listener
15
26
  end
16
27
 
28
+ # Start the adapter.
29
+ #
30
+ def start
31
+ end
32
+
33
+ # Stop the adapter.
34
+ #
35
+ def stop
36
+ end
37
+
17
38
  end
18
39
  end
@@ -0,0 +1,58 @@
1
+ module Listen
2
+ module Adapters
3
+
4
+ # Adapter implementation for Mac OS X `FSEvents`.
5
+ #
6
+ class Darwin < Adapter
7
+
8
+ # Initialize the Adapter.
9
+ #
10
+ def initialize(*)
11
+ super
12
+ @latency ||= 0.1
13
+ init_worker
14
+ end
15
+
16
+ # Start the adapter.
17
+ #
18
+ def start
19
+ super
20
+ @worker.run
21
+ end
22
+
23
+ # Stop the adapter.
24
+ #
25
+ def stop
26
+ super
27
+ @worker.stop
28
+ end
29
+
30
+ # Check if the adapter is usable on the current OS.
31
+ #
32
+ # @return [Boolean] whether usable or not
33
+ #
34
+ def self.usable?
35
+ return false unless RbConfig::CONFIG['target_os'] =~ /darwin(1.+)?$/i
36
+
37
+ require 'rb-fsevent'
38
+ true
39
+ rescue LoadError
40
+ false
41
+ end
42
+
43
+ private
44
+
45
+ # Initialiaze FSEvent worker and set watch callback block
46
+ #
47
+ def init_worker
48
+ @worker = FSEvent.new
49
+ @worker.watch(@listener.directory, :latency => @latency) do |changed_dirs|
50
+ changed_dirs.map! { |path| path.sub /\/$/, '' }
51
+ @listener.on_change(changed_dirs)
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,85 @@
1
+ require 'set'
2
+
3
+ module Listen
4
+ module Adapters
5
+
6
+ # Watched INotify EVENTS
7
+ #
8
+ # @see http://www.tin.org/bin/man.cgi?section=7&topic=inotify
9
+ # @see https://github.com/nex3/rb-inotify/blob/master/lib/rb-inotify/notifier.rb#L99-L177
10
+ #
11
+ EVENTS = %w[recursive attrib close modify move create delete delete_self move_self]
12
+
13
+ # Listener implementation for Linux `inotify`.
14
+ #
15
+ class Linux < Adapter
16
+
17
+ # Initialize the Adapter.
18
+ #
19
+ def initialize(*)
20
+ super
21
+ @latency ||= 0.1
22
+ @changed_dirs = Set.new
23
+ init_worker
24
+ end
25
+
26
+ # Start the adapter.
27
+ #
28
+ def start
29
+ super
30
+ Thread.new { @worker.run }
31
+ @stop = false
32
+ poll_changed_dirs
33
+ end
34
+
35
+ # Stop the adapter.
36
+ #
37
+ def stop
38
+ super
39
+ @stop = true
40
+ @worker.stop
41
+ end
42
+
43
+ # Check if the adapter is usable on the current OS.
44
+ #
45
+ # @return [Boolean] whether usable or not
46
+ #
47
+ def self.usable?
48
+ return false unless RbConfig::CONFIG['target_os'] =~ /linux/i
49
+
50
+ require 'rb-inotify'
51
+ true
52
+ rescue LoadError
53
+ false
54
+ end
55
+
56
+ private
57
+
58
+ # Initialiaze INotify worker and set watch callback block.
59
+ #
60
+ def init_worker
61
+ @worker = INotify::Notifier.new
62
+ @worker.watch(@listener.directory, *EVENTS.map(&:to_sym)) do |event|
63
+ unless event.name == "" # Event on root directory
64
+ @changed_dirs << File.dirname(event.absolute_name)
65
+ end
66
+ end
67
+ end
68
+
69
+ # Polling around @changed_dirs presence.
70
+ #
71
+ def poll_changed_dirs
72
+ until @stop
73
+ sleep(@latency)
74
+
75
+ next if @changed_dirs.empty?
76
+ changed_dirs = @changed_dirs.to_a
77
+ @changed_dirs.clear
78
+ @listener.on_change(changed_dirs)
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
@@ -7,18 +7,18 @@ module Listen
7
7
  # file IO that the other implementations.
8
8
  #
9
9
  class Polling < Adapter
10
- attr_accessor :latency
11
-
10
+
12
11
  # Initialize the Adapter.
13
12
  #
14
13
  def initialize(*)
15
14
  super
16
- @latency = 1.0
15
+ @latency ||= 1.0
17
16
  end
18
17
 
19
18
  # Start the adapter.
20
19
  #
21
20
  def start
21
+ super
22
22
  @stop = false
23
23
  poll
24
24
  end
@@ -26,17 +26,18 @@ module Listen
26
26
  # Stop the adapter.
27
27
  #
28
28
  def stop
29
+ super
29
30
  @stop = true
30
31
  end
31
32
 
32
- private
33
+ private
33
34
 
34
35
  # Poll listener directory for file system changes.
35
36
  #
36
37
  def poll
37
38
  until @stop
38
39
  start = Time.now.to_f
39
- @listener.on_change(@listener.directory)
40
+ @listener.on_change([@listener.directory], :recursive => true)
40
41
  nap_time = @latency - (Time.now.to_f - start)
41
42
  sleep(nap_time) if nap_time > 0
42
43
  end
@@ -0,0 +1,75 @@
1
+ require 'set'
2
+
3
+ module Listen
4
+ module Adapters
5
+
6
+ # Adapter implementation for Windows `fchange`.
7
+ #
8
+ class Windows < Adapter
9
+
10
+ # Initialize the Adapter.
11
+ #
12
+ def initialize(*)
13
+ super
14
+ @latency ||= 0.1
15
+ @changed_dirs = Set.new
16
+ init_worker
17
+ end
18
+
19
+ # Start the adapter.
20
+ #
21
+ def start
22
+ super
23
+ Thread.new { @worker.run }
24
+ @stop = false
25
+ poll_changed_dirs
26
+ end
27
+
28
+ # Stop the adapter.
29
+ #
30
+ def stop
31
+ super
32
+ @worker.stop
33
+ end
34
+
35
+ # Check if the adapter is usable on the current OS.
36
+ #
37
+ # @return [Boolean] whether usable or not
38
+ #
39
+ def self.usable?
40
+ return false unless RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
41
+
42
+ require 'rb-fchange'
43
+ true
44
+ rescue LoadError
45
+ false
46
+ end
47
+
48
+ private
49
+
50
+ # Initialiaze FSEvent worker and set watch callback block
51
+ #
52
+ def init_worker
53
+ @worker = FChange::Notifier.new
54
+ @worker.watch(@listener.directory, :all_events, :recursive) do |event|
55
+ @changed_dirs << File.expand_path(event.watcher.path)
56
+ end
57
+ end
58
+
59
+ # Polling around @changed_dirs presence.
60
+ #
61
+ def poll_changed_dirs
62
+ until @stop
63
+ sleep(@latency)
64
+
65
+ next if @changed_dirs.empty?
66
+ changed_dirs = @changed_dirs.to_a
67
+ @changed_dirs.clear
68
+ @listener.on_change(changed_dirs, :recursive => true)
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+ end
@@ -1,13 +1,18 @@
1
1
  require 'find'
2
+ require 'digest/sha1'
3
+
2
4
  require 'listen/adapter'
5
+ require 'listen/adapters/darwin'
6
+ require 'listen/adapters/linux'
3
7
  require 'listen/adapters/polling'
8
+ require 'listen/adapters/windows'
4
9
 
5
10
  module Listen
6
11
  class Listener
7
- attr_accessor :directory, :ignored_paths, :file_filters, :paths
12
+ attr_accessor :directory, :ignored_paths, :file_filters, :sha1_checksums, :paths, :adapter
8
13
 
9
14
  # Default paths that gets ignored by the listener
10
- DEFAULT_IGNORED_PATHS = %w[.bundle .git log tmp vendor]
15
+ DEFAULT_IGNORED_PATHS = %w[.bundle .git .DS_Store log tmp vendor]
11
16
 
12
17
  # Initialize the file listener.
13
18
  #
@@ -24,10 +29,11 @@ module Listen
24
29
  # @return [Listen::Listener] the file listener
25
30
  #
26
31
  def initialize(*args, &block)
27
- @directory = args.first
28
- @ignored_paths = DEFAULT_IGNORED_PATHS
29
- @file_filters = []
30
- @block = block
32
+ @directory = args.first
33
+ @ignored_paths = DEFAULT_IGNORED_PATHS
34
+ @file_filters = []
35
+ @sha1_checksums = {}
36
+ @block = block
31
37
  if args[1]
32
38
  @ignored_paths += Array(args[1][:ignore]) if args[1][:ignore]
33
39
  @file_filters += Array(args[1][:filter]) if args[1][:filter]
@@ -93,31 +99,38 @@ module Listen
93
99
 
94
100
  # Call @block callback when there is a diff in the passed directory.
95
101
  #
96
- # @param [String] directory the directory to diff
102
+ # @param [Array] directories the list of directories to diff
97
103
  #
98
- def on_change(directory)
99
- changes = diff(directory)
100
- unless changes == { :modified => [], :added => [], :removed => [] }
104
+ def on_change(directories, diff_options = {})
105
+ changes = diff(directories, diff_options)
106
+ unless changes.values.all? { |paths| paths.empty? }
101
107
  @block.call(changes[:modified],changes[:added],changes[:removed])
102
108
  end
103
109
  end
104
110
 
105
- # Initialize the @paths double levels Hash with all existing paths.
111
+ # Initialize the @paths double levels Hash with all existing paths and set diffed_at.
106
112
  #
107
113
  def init_paths
108
114
  @paths = Hash.new { |h,k| h[k] = {} }
109
115
  all_existing_paths { |path| insert_path(path) }
116
+ @diffed_at = Time.now.to_i
110
117
  end
111
118
 
112
119
  # Detect changes diff in a directory.
113
120
  #
114
- # @param [String] directory the path to diff
121
+ # @param [Array] directories the list of directories to diff
122
+ # @param [Hash] options
123
+ # @option options [Boolean] recursive scan all sub-direcoties recursively (true when polling)
115
124
  # @return [Hash<Array>] the file changes
116
125
  #
117
- def diff(directory = @directory)
118
- @changes = { :modified => [], :added => [], :removed => [] }
119
- detect_modifications_and_removals(directory)
120
- detect_additions(directory)
126
+ def diff(directories, options = {})
127
+ @changes = { :modified => [], :added => [], :removed => [] }
128
+ directories = directories.sort_by { |el| el.length }.reverse # diff sub-dir first
129
+ directories.each do |directory|
130
+ detect_modifications_and_removals(directory, options)
131
+ detect_additions(directory, options)
132
+ end
133
+ @diffed_at = Time.now.to_i
121
134
  @changes
122
135
  end
123
136
 
@@ -129,62 +142,107 @@ module Listen
129
142
  #
130
143
  def all_existing_paths
131
144
  Find.find(@directory) do |path|
145
+ next if @directory == path
146
+
132
147
  if File.directory?(path)
133
- if @ignored_paths.any? { |ignored_path| path =~ /#{ignored_path}$/ }
148
+ if ignored_path?(path)
134
149
  Find.prune # Don't look any further into this directory.
135
150
  else
136
151
  yield(path)
137
152
  end
138
- elsif @file_filters.empty? || @file_filters.any? { |file_filter| path =~ file_filter }
153
+ elsif !ignored_path?(path) && filtered_file?(path)
139
154
  yield(path)
140
155
  end
141
156
  end
142
157
  end
143
158
 
144
- # Insert a path with its File.stat in @paths.
159
+ # Insert a path with its type (Dir or File) in @paths.
145
160
  #
146
161
  # @param [String] path the path to insert in @paths.
147
162
  #
148
163
  def insert_path(path)
149
- @paths[File.dirname(path)][File.basename(path)] = File.stat(path)
164
+ @paths[File.dirname(path)][File.basename(path)] = File.directory?(path) ? 'Dir' : 'File'
165
+ end
166
+
167
+ # Find is a path exists in @paths.
168
+ #
169
+ # @param [String] path the path to find in @paths.
170
+ # @return [Boolean]
171
+ #
172
+ def existing_path?(path)
173
+ @paths[File.dirname(path)][File.basename(path)] != nil
150
174
  end
151
175
 
152
176
  # Detect modifications and removals recursivly in a directory.
177
+ # Modifications detection are based on mtime first and on checksum when mtime == last diffed_at
153
178
  #
154
179
  # @param [String] directory the path to analyze
180
+ # @param [Hash] options
181
+ # @option options [Boolean] recursive scan all sub-direcoties recursively (when polling)
155
182
  #
156
- def detect_modifications_and_removals(directory)
157
- @paths[directory].each do |basename, stat|
183
+ def detect_modifications_and_removals(directory, options = {})
184
+ @paths[directory].each do |basename, type|
158
185
  path = File.join(directory, basename)
159
-
160
- if stat.directory?
161
- detect_modifications_and_removals(path)
162
- @paths[directory].delete(basename) unless File.directory?(path)
163
- else
186
+
187
+ case type
188
+ when 'Dir'
189
+ if File.directory?(path)
190
+ detect_modifications_and_removals(path, options) if options[:recursive]
191
+ else
192
+ detect_modifications_and_removals(path, :recursive => true)
193
+ @paths[directory].delete(basename)
194
+ @paths.delete("#{directory}/#{basename}")
195
+ end
196
+ when 'File'
164
197
  if File.exist?(path)
165
- new_stat = File.stat(path)
166
- if stat.mtime != new_stat.mtime
198
+ new_mtime = File.mtime(path).to_i
199
+ if @diffed_at < new_mtime || (@diffed_at == new_mtime && content_modified?(path))
167
200
  @changes[:modified] << relative_path(path)
168
- @paths[directory][basename] = new_stat
169
201
  end
170
202
  else
171
203
  @paths[directory].delete(basename)
204
+ @sha1_checksums.delete(path)
172
205
  @changes[:removed] << relative_path(path)
173
206
  end
174
207
  end
175
208
  end
176
209
  end
177
210
 
211
+ # Tests if the file content has been modified by
212
+ # comparing the SHA1 checksum.
213
+ #
214
+ # @param [String] path the file path
215
+ #
216
+ def content_modified?(path)
217
+ sha1_checksum = Digest::SHA1.file(path).to_s
218
+ if @sha1_checksums[path] != sha1_checksum
219
+ @sha1_checksums[path] = sha1_checksum
220
+ true
221
+ else
222
+ false
223
+ end
224
+ end
225
+
178
226
  # Detect additions in a directory.
179
227
  #
180
228
  # @param [String] directory the path to analyze
229
+ # @param [Hash] options
230
+ # @option options [Boolean] recursive scan all sub-direcoties recursively (when polling)
181
231
  #
182
- def detect_additions(directory)
183
- all_existing_paths do |path|
184
- next if @paths[File.dirname(path)][File.basename(path)]
232
+ def detect_additions(directory, options = {})
233
+ Find.find(directory) do |path|
234
+ next if @directory == path
185
235
 
186
- @changes[:added] << relative_path(path) if File.file?(path)
187
- insert_path(path)
236
+ if File.directory?(path)
237
+ if directory != path && (ignored_path?(path) || (!options[:recursive] && existing_path?(path)))
238
+ Find.prune # Don't look any further into this directory.
239
+ else
240
+ insert_path(path)
241
+ end
242
+ elsif !existing_path?(path) && !ignored_path?(path) && filtered_file?(path)
243
+ @changes[:added] << relative_path(path) if File.file?(path)
244
+ insert_path(path)
245
+ end
188
246
  end
189
247
  end
190
248
 
@@ -199,5 +257,23 @@ module Listen
199
257
  path.sub(%r(^#{base_dir}/), '')
200
258
  end
201
259
 
260
+ # Test if a path should be ignored or not.
261
+ #
262
+ # @param [String] path the path to test.
263
+ # @return [Boolean]
264
+ #
265
+ def ignored_path?(path)
266
+ @ignored_paths.any? { |ignored_path| path =~ /#{ignored_path}$/ }
267
+ end
268
+
269
+ # Test if a file path should be filtered or not.
270
+ #
271
+ # @param [String] path the file path to test.
272
+ # @return [Boolean]
273
+ #
274
+ def filtered_file?(path)
275
+ @file_filters.empty? || @file_filters.any? { |file_filter| path =~ file_filter }
276
+ end
277
+
202
278
  end
203
279
  end
@@ -1,3 +1,3 @@
1
1
  module Listen
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,89 +1,53 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: listen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - Travis Tilley
9
- - Yehuda Katz
10
8
  - Thibaud Guillaume-Gentil
11
- - Rémy Coutable
12
9
  - Michael Kessler
13
10
  autorequire:
14
11
  bindir: bin
15
12
  cert_chain: []
16
- date: 2012-01-28 00:00:00.000000000 Z
13
+ date: 2012-02-12 00:00:00.000000000 Z
17
14
  dependencies:
18
15
  - !ruby/object:Gem::Dependency
19
- name: bundler
20
- requirement: &70178027214260 !ruby/object:Gem::Requirement
21
- none: false
22
- requirements:
23
- - - ! '>='
24
- - !ruby/object:Gem::Version
25
- version: '0'
26
- type: :development
27
- prerelease: false
28
- version_requirements: *70178027214260
29
- - !ruby/object:Gem::Dependency
30
- name: guard
31
- requirement: &70178027229800 !ruby/object:Gem::Requirement
16
+ name: rb-fsevent
17
+ requirement: &70294412755220 !ruby/object:Gem::Requirement
32
18
  none: false
33
19
  requirements:
34
20
  - - ~>
35
21
  - !ruby/object:Gem::Version
36
- version: 1.0.0
37
- type: :development
22
+ version: 0.9.0
23
+ type: :runtime
38
24
  prerelease: false
39
- version_requirements: *70178027229800
25
+ version_requirements: *70294412755220
40
26
  - !ruby/object:Gem::Dependency
41
- name: rspec
42
- requirement: &70178027228980 !ruby/object:Gem::Requirement
27
+ name: rb-inotify
28
+ requirement: &70294412770880 !ruby/object:Gem::Requirement
43
29
  none: false
44
30
  requirements:
45
31
  - - ~>
46
32
  - !ruby/object:Gem::Version
47
- version: 2.8.0
48
- type: :development
33
+ version: 0.8.8
34
+ type: :runtime
49
35
  prerelease: false
50
- version_requirements: *70178027228980
36
+ version_requirements: *70294412770880
51
37
  - !ruby/object:Gem::Dependency
52
- name: guard-rspec
53
- requirement: &70178027228220 !ruby/object:Gem::Requirement
38
+ name: rb-fchange
39
+ requirement: &70294412770160 !ruby/object:Gem::Requirement
54
40
  none: false
55
41
  requirements:
56
42
  - - ~>
57
43
  - !ruby/object:Gem::Version
58
- version: 0.6.0
59
- type: :development
44
+ version: 0.0.5
45
+ type: :runtime
60
46
  prerelease: false
61
- version_requirements: *70178027228220
47
+ version_requirements: *70294412770160
62
48
  - !ruby/object:Gem::Dependency
63
- name: yard
64
- requirement: &70178027227420 !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
- type: :development
71
- prerelease: false
72
- version_requirements: *70178027227420
73
- - !ruby/object:Gem::Dependency
74
- name: redcarpet
75
- requirement: &70178027226740 !ruby/object:Gem::Requirement
76
- none: false
77
- requirements:
78
- - - ! '>='
79
- - !ruby/object:Gem::Version
80
- version: '0'
81
- type: :development
82
- prerelease: false
83
- version_requirements: *70178027226740
84
- - !ruby/object:Gem::Dependency
85
- name: pry
86
- requirement: &70178027226280 !ruby/object:Gem::Requirement
49
+ name: bundler
50
+ requirement: &70294412769580 !ruby/object:Gem::Requirement
87
51
  none: false
88
52
  requirements:
89
53
  - - ! '>='
@@ -91,21 +55,21 @@ dependencies:
91
55
  version: '0'
92
56
  type: :development
93
57
  prerelease: false
94
- version_requirements: *70178027226280
58
+ version_requirements: *70294412769580
95
59
  description: The Listen gem listens to file modifications and notifies you about the
96
- changes.
60
+ changes. Works everywhere!
97
61
  email:
98
- - ttilley@gmail.com
99
- - wycats@gmail.com
100
62
  - thibaud@thibaud.me
101
- - rymai@rymai.me
102
63
  - michi@netzpiraten.ch
103
64
  executables: []
104
65
  extensions: []
105
66
  extra_rdoc_files: []
106
67
  files:
107
68
  - lib/listen/adapter.rb
69
+ - lib/listen/adapters/darwin.rb
70
+ - lib/listen/adapters/linux.rb
108
71
  - lib/listen/adapters/polling.rb
72
+ - lib/listen/adapters/windows.rb
109
73
  - lib/listen/listener.rb
110
74
  - lib/listen/version.rb
111
75
  - lib/listen.rb
@@ -124,9 +88,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
88
  - - ! '>='
125
89
  - !ruby/object:Gem::Version
126
90
  version: '0'
127
- segments:
128
- - 0
129
- hash: -4340389000594607932
130
91
  required_rubygems_version: !ruby/object:Gem::Requirement
131
92
  none: false
132
93
  requirements:
@@ -135,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
96
  version: 1.3.6
136
97
  requirements: []
137
98
  rubyforge_project: listen
138
- rubygems_version: 1.8.12
99
+ rubygems_version: 1.8.15
139
100
  signing_key:
140
101
  specification_version: 3
141
102
  summary: Listen to file modifications