listen 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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