listen 0.4.2 → 0.4.3
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 +14 -0
- data/README.md +5 -2
- data/lib/listen/adapter.rb +9 -1
- data/lib/listen/adapters/linux.rb +18 -7
- data/lib/listen/directory_record.rb +45 -16
- data/lib/listen/listener.rb +16 -1
- data/lib/listen/version.rb +1 -1
- metadata +39 -16
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## 0.4.3 - June 6, 2012
|
2
|
+
|
3
|
+
### Bug fixes
|
4
|
+
|
5
|
+
- [#24](https://github.com/guard/listen/issues/24): Fail gracefully when the inotify limit is not enough for Listen to function. (reported by [@daemonza][], fixed by [@Maher4Ever][])
|
6
|
+
- [#32](https://github.com/guard/listen/issues/32): Fix a crash when trying to calculate the checksum of unreadable files. (reported by [@nex3][], fixed by [@Maher4Ever][])
|
7
|
+
|
8
|
+
### Improvements
|
9
|
+
|
10
|
+
- Add `#relative_paths` method to listeners. ([@Maher4Ever][])
|
11
|
+
- Add `#started?` query-method to adapters. ([@Maher4Ever][])
|
12
|
+
- Dynamically detect the mtime precision used on a system. ([@Maher4Ever][] with help from [@nex3][])
|
13
|
+
|
1
14
|
## 0.4.2 - May 1, 2012
|
2
15
|
|
3
16
|
### Bug fixes
|
@@ -88,3 +101,4 @@
|
|
88
101
|
[@akerbos]: https://github.com/akerbos
|
89
102
|
[@fny]: https://github.com/fny
|
90
103
|
[@cobychapple]: https://github.com/cobychapple
|
104
|
+
[@nex3]: https://github.com/nex3
|
data/README.md
CHANGED
@@ -32,12 +32,12 @@ Feel free to give your feeback via [Listen issues](https://github.com/guard/list
|
|
32
32
|
|
33
33
|
``` ruby
|
34
34
|
# Listen to a single directory.
|
35
|
-
Listen.to('dir/path/to/listen', filter
|
35
|
+
Listen.to('dir/path/to/listen', :filter => /\.rb$/, :ignore => %r{ignored/path/}) do |modified, added, removed|
|
36
36
|
# ...
|
37
37
|
end
|
38
38
|
|
39
39
|
# Listen to multiple directories.
|
40
|
-
Listen.to('dir/to/awesome_app', 'dir/to/other_app', filter
|
40
|
+
Listen.to('dir/to/awesome_app', 'dir/to/other_app', :filter => /\.rb$/, :latency => 0.1) do |modified, added, removed|
|
41
41
|
# ...
|
42
42
|
end
|
43
43
|
```
|
@@ -193,6 +193,9 @@ These options can be set through `Listen.to` params or via methods (see the "Obj
|
|
193
193
|
:latency => 0.5 # Set the delay (**in seconds**) between checking for changes
|
194
194
|
# default: 0.1 sec (1.0 sec for polling)
|
195
195
|
|
196
|
+
:relative_paths => true # Enable the use of relative paths in the callback.
|
197
|
+
# default: false
|
198
|
+
|
196
199
|
:force_polling => true # Force the use of the polling adapter
|
197
200
|
# default: none
|
198
201
|
|
data/lib/listen/adapter.rb
CHANGED
@@ -83,6 +83,14 @@ module Listen
|
|
83
83
|
@turnstile.signal # ensure no thread is blocked
|
84
84
|
end
|
85
85
|
|
86
|
+
# Returns whether the adapter is statred or not
|
87
|
+
#
|
88
|
+
# @return [Boolean] whether the adapter is started or not
|
89
|
+
#
|
90
|
+
def started?
|
91
|
+
@stop.nil? ? false : !@stop
|
92
|
+
end
|
93
|
+
|
86
94
|
# Blocks the main thread until the poll thread
|
87
95
|
# calls the callback.
|
88
96
|
#
|
@@ -129,7 +137,7 @@ module Listen
|
|
129
137
|
ensure
|
130
138
|
Thread.kill(t) if t
|
131
139
|
FileUtils.rm(test_file) if File.exists?(test_file)
|
132
|
-
adapter.stop
|
140
|
+
adapter.stop if adapter && adapter.started?
|
133
141
|
end
|
134
142
|
|
135
143
|
private
|
@@ -1,22 +1,33 @@
|
|
1
1
|
module Listen
|
2
2
|
module Adapters
|
3
3
|
|
4
|
-
# Watched INotify EVENTS
|
5
|
-
#
|
6
|
-
# @see http://www.tin.org/bin/man.cgi?section=7&topic=inotify
|
7
|
-
# @see https://github.com/nex3/rb-inotify/blob/master/lib/rb-inotify/notifier.rb#L99-L177
|
8
|
-
#
|
9
|
-
EVENTS = %w[recursive attrib close modify move create delete delete_self move_self]
|
10
|
-
|
11
4
|
# Listener implementation for Linux `inotify`.
|
12
5
|
#
|
13
6
|
class Linux < Adapter
|
14
7
|
|
8
|
+
# Watched inotify events
|
9
|
+
#
|
10
|
+
# @see http://www.tin.org/bin/man.cgi?section=7&topic=inotify
|
11
|
+
# @see https://github.com/nex3/rb-inotify/blob/master/lib/rb-inotify/notifier.rb#L99-L177
|
12
|
+
#
|
13
|
+
EVENTS = %w[recursive attrib close modify move create delete delete_self move_self]
|
14
|
+
|
15
|
+
# The message to show when the limit of inotify watchers is not enough
|
16
|
+
#
|
17
|
+
INOTIFY_LIMIT_MESSAGE = <<-EOS.gsub(/^\s*/, '')
|
18
|
+
Listen error: unable to monitor directories for changes.
|
19
|
+
|
20
|
+
Please head to https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers
|
21
|
+
for information on how to solve this issue.
|
22
|
+
EOS
|
23
|
+
|
15
24
|
# Initializes the Adapter. See {Listen::Adapter#initialize} for more info.
|
16
25
|
#
|
17
26
|
def initialize(directories, options = {}, &callback)
|
18
27
|
super
|
19
28
|
@worker = init_worker
|
29
|
+
rescue Errno::ENOSPC
|
30
|
+
abort(INOTIFY_LIMIT_MESSAGE)
|
20
31
|
end
|
21
32
|
|
22
33
|
# Starts the adapter.
|
@@ -15,6 +15,15 @@ module Listen
|
|
15
15
|
|
16
16
|
DEFAULT_IGNORED_EXTENSIONS = %w[.DS_Store]
|
17
17
|
|
18
|
+
# Defines the used precision based on the type of mtime returned by the
|
19
|
+
# system (whether its in milliseconds or just seconds)
|
20
|
+
#
|
21
|
+
HIGH_PRECISION_SUPPORTED = File.mtime(__FILE__).to_f.to_s[-2..-1] != '.0'
|
22
|
+
|
23
|
+
# Data structure used to save meta data about a path
|
24
|
+
#
|
25
|
+
MetaData = Struct.new(:type, :mtime)
|
26
|
+
|
18
27
|
# Class methods
|
19
28
|
#
|
20
29
|
class << self
|
@@ -71,7 +80,7 @@ module Listen
|
|
71
80
|
# Adds ignoring patterns to the record.
|
72
81
|
#
|
73
82
|
# @example Ignore some paths
|
74
|
-
# ignore
|
83
|
+
# ignore %r{^ignored/path/}, /man/
|
75
84
|
#
|
76
85
|
# @param [Regexp] regexp a pattern for ignoring paths
|
77
86
|
#
|
@@ -86,8 +95,6 @@ module Listen
|
|
86
95
|
#
|
87
96
|
# @param [Regexp] regexp a pattern for filtering paths
|
88
97
|
#
|
89
|
-
# @return [Listen::Listener] the listener itself
|
90
|
-
#
|
91
98
|
def filter(*regexps)
|
92
99
|
@filtering_patterns.merge(regexps)
|
93
100
|
end
|
@@ -123,7 +130,6 @@ module Listen
|
|
123
130
|
def build
|
124
131
|
@paths = Hash.new { |h, k| h[k] = Hash.new }
|
125
132
|
important_paths { |path| insert_path(path) }
|
126
|
-
@updated_at = Time.now.to_f
|
127
133
|
end
|
128
134
|
|
129
135
|
# Detects changes in the passed directories, updates
|
@@ -139,12 +145,13 @@ module Listen
|
|
139
145
|
def fetch_changes(directories, options = {})
|
140
146
|
@changes = { :modified => [], :added => [], :removed => [] }
|
141
147
|
directories = directories.sort_by { |el| el.length }.reverse # diff sub-dir first
|
148
|
+
|
142
149
|
directories.each do |directory|
|
143
150
|
next unless directory[@directory] # Path is or inside directory
|
144
151
|
detect_modifications_and_removals(directory, options)
|
145
152
|
detect_additions(directory, options)
|
146
153
|
end
|
147
|
-
|
154
|
+
|
148
155
|
@changes
|
149
156
|
end
|
150
157
|
|
@@ -173,10 +180,10 @@ module Listen
|
|
173
180
|
# @option options [Boolean] relative_paths whether or not to use relative paths for changes
|
174
181
|
#
|
175
182
|
def detect_modifications_and_removals(directory, options = {})
|
176
|
-
@paths[directory].each do |basename,
|
183
|
+
@paths[directory].each do |basename, meta_data|
|
177
184
|
path = File.join(directory, basename)
|
178
185
|
|
179
|
-
case type
|
186
|
+
case meta_data.type
|
180
187
|
when 'Dir'
|
181
188
|
if File.directory?(path)
|
182
189
|
detect_modifications_and_removals(path, options) if options[:recursive]
|
@@ -187,8 +194,15 @@ module Listen
|
|
187
194
|
end
|
188
195
|
when 'File'
|
189
196
|
if File.exist?(path)
|
190
|
-
new_mtime =
|
191
|
-
|
197
|
+
new_mtime = mtime_of(path)
|
198
|
+
|
199
|
+
# First check if we are in the same second (to update checksums)
|
200
|
+
# before checking the time difference
|
201
|
+
if (meta_data.mtime.to_i == new_mtime.to_i && content_modified?(path)) || meta_data.mtime < new_mtime
|
202
|
+
# Update the meta data of the files
|
203
|
+
meta_data.mtime = new_mtime
|
204
|
+
@paths[directory][basename] = meta_data
|
205
|
+
|
192
206
|
@changes[:modified] << (options[:relative_paths] ? relative_to_base(path) : path)
|
193
207
|
end
|
194
208
|
else
|
@@ -238,12 +252,14 @@ module Listen
|
|
238
252
|
#
|
239
253
|
def content_modified?(path)
|
240
254
|
sha1_checksum = Digest::SHA1.file(path).to_s
|
241
|
-
if @sha1_checksums[path]
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
255
|
+
return false if @sha1_checksums[path] == sha1_checksum
|
256
|
+
|
257
|
+
had_no_checksum = @sha1_checksums[path].nil?
|
258
|
+
@sha1_checksums[path] = sha1_checksum
|
259
|
+
|
260
|
+
had_no_checksum ? false : true
|
261
|
+
rescue Errno::EACCES # unreadble file
|
262
|
+
false
|
247
263
|
end
|
248
264
|
|
249
265
|
# Traverses the base directory looking for paths that should
|
@@ -274,7 +290,10 @@ module Listen
|
|
274
290
|
# @param [String] path the path to insert in @paths.
|
275
291
|
#
|
276
292
|
def insert_path(path)
|
277
|
-
|
293
|
+
meta_data = MetaData.new
|
294
|
+
meta_data.type = File.directory?(path) ? 'Dir' : 'File'
|
295
|
+
meta_data.mtime = mtime_of(path) unless meta_data.type == 'Dir' # mtimes of dirs are not used yet
|
296
|
+
@paths[File.dirname(path)][File.basename(path)] = meta_data
|
278
297
|
end
|
279
298
|
|
280
299
|
# Returns whether or not a path exists in the paths hash.
|
@@ -286,5 +305,15 @@ module Listen
|
|
286
305
|
def existing_path?(path)
|
287
306
|
@paths[File.dirname(path)][File.basename(path)] != nil
|
288
307
|
end
|
308
|
+
|
309
|
+
# Returns the modification time of a file based on the precision defined by the system
|
310
|
+
#
|
311
|
+
# @param [String] file the file for which the mtime must be returned
|
312
|
+
#
|
313
|
+
# @return [Fixnum, Float] the mtime of the file
|
314
|
+
#
|
315
|
+
def mtime_of(file)
|
316
|
+
File.mtime(file).send(HIGH_PRECISION_SUPPORTED ? :to_f : :to_i)
|
317
|
+
end
|
289
318
|
end
|
290
319
|
end
|
data/lib/listen/listener.rb
CHANGED
@@ -119,7 +119,7 @@ module Listen
|
|
119
119
|
self
|
120
120
|
end
|
121
121
|
|
122
|
-
#
|
122
|
+
# Sets whether the use of the polling adapter
|
123
123
|
# should be forced or not.
|
124
124
|
#
|
125
125
|
# @example Forcing the use of the polling adapter
|
@@ -134,6 +134,21 @@ module Listen
|
|
134
134
|
self
|
135
135
|
end
|
136
136
|
|
137
|
+
# Sets whether the paths in the callback should be
|
138
|
+
# relative or absolute.
|
139
|
+
#
|
140
|
+
# @example Enabling relative paths in the callback
|
141
|
+
# relative_paths true
|
142
|
+
#
|
143
|
+
# @param [Boolean] value whether to enable relative paths in the callback or not
|
144
|
+
#
|
145
|
+
# @return [Listen::Listener] the listener
|
146
|
+
#
|
147
|
+
def relative_paths(value)
|
148
|
+
@use_relative_paths = value
|
149
|
+
self
|
150
|
+
end
|
151
|
+
|
137
152
|
# Defines a custom polling fallback message of disable it.
|
138
153
|
#
|
139
154
|
# @example Disabling the polling fallback message
|
data/lib/listen/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: listen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-06-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rb-fsevent
|
17
|
-
requirement:
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,15 @@ dependencies:
|
|
22
22
|
version: 0.9.1
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements:
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 0.9.1
|
26
31
|
- !ruby/object:Gem::Dependency
|
27
32
|
name: rb-inotify
|
28
|
-
requirement:
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
29
34
|
none: false
|
30
35
|
requirements:
|
31
36
|
- - ~>
|
@@ -33,10 +38,15 @@ dependencies:
|
|
33
38
|
version: 0.8.8
|
34
39
|
type: :runtime
|
35
40
|
prerelease: false
|
36
|
-
version_requirements:
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.8.8
|
37
47
|
- !ruby/object:Gem::Dependency
|
38
48
|
name: rb-fchange
|
39
|
-
requirement:
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
40
50
|
none: false
|
41
51
|
requirements:
|
42
52
|
- - ~>
|
@@ -44,10 +54,15 @@ dependencies:
|
|
44
54
|
version: 0.0.5
|
45
55
|
type: :runtime
|
46
56
|
prerelease: false
|
47
|
-
version_requirements:
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.0.5
|
48
63
|
- !ruby/object:Gem::Dependency
|
49
64
|
name: bundler
|
50
|
-
requirement:
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
51
66
|
none: false
|
52
67
|
requirements:
|
53
68
|
- - ! '>='
|
@@ -55,7 +70,12 @@ dependencies:
|
|
55
70
|
version: '0'
|
56
71
|
type: :development
|
57
72
|
prerelease: false
|
58
|
-
version_requirements:
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
59
79
|
description: The Listen gem listens to file modifications and notifies you about the
|
60
80
|
changes. Works everywhere!
|
61
81
|
email:
|
@@ -66,16 +86,16 @@ extensions: []
|
|
66
86
|
extra_rdoc_files: []
|
67
87
|
files:
|
68
88
|
- lib/listen.rb
|
89
|
+
- lib/listen/version.rb
|
90
|
+
- lib/listen/adapter.rb
|
69
91
|
- lib/listen/multi_listener.rb
|
70
|
-
- lib/listen/directory_record.rb
|
71
92
|
- lib/listen/listener.rb
|
72
|
-
- lib/listen/
|
73
|
-
- lib/listen/
|
93
|
+
- lib/listen/turnstile.rb
|
94
|
+
- lib/listen/directory_record.rb
|
74
95
|
- lib/listen/adapters/polling.rb
|
75
96
|
- lib/listen/adapters/darwin.rb
|
97
|
+
- lib/listen/adapters/linux.rb
|
76
98
|
- lib/listen/adapters/windows.rb
|
77
|
-
- lib/listen/adapter.rb
|
78
|
-
- lib/listen/turnstile.rb
|
79
99
|
- CHANGELOG.md
|
80
100
|
- LICENSE
|
81
101
|
- README.md
|
@@ -91,6 +111,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
111
|
- - ! '>='
|
92
112
|
- !ruby/object:Gem::Version
|
93
113
|
version: '0'
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
hash: -692640991
|
94
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
118
|
none: false
|
96
119
|
requirements:
|
@@ -99,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
122
|
version: 1.3.6
|
100
123
|
requirements: []
|
101
124
|
rubyforge_project: listen
|
102
|
-
rubygems_version: 1.8.
|
125
|
+
rubygems_version: 1.8.24
|
103
126
|
signing_key:
|
104
127
|
specification_version: 3
|
105
128
|
summary: Listen to file modifications
|