listen 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -1
- data/LICENSE +1 -1
- data/README.md +91 -24
- data/lib/listen.rb +2 -0
- data/lib/listen/adapter.rb +90 -10
- data/lib/listen/adapters/darwin.rb +4 -5
- data/lib/listen/adapters/linux.rb +9 -13
- data/lib/listen/adapters/polling.rb +8 -6
- data/lib/listen/adapters/windows.rb +6 -8
- data/lib/listen/listener.rb +67 -12
- data/lib/listen/version.rb +1 -1
- metadata +11 -13
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
##
|
1
|
+
## 0.3.0 - February 21, 2012
|
2
|
+
|
3
|
+
- Add automatic fallback to polling if system adapter doesn't work (like a DropBox folder). ([@thibaudgg][])
|
4
|
+
- Add latency and force_polling options. ([@Maher4Ever][])
|
5
|
+
|
6
|
+
## 0.2.0 - February 13, 2012
|
2
7
|
|
3
8
|
- Add checksum comparaison support for detecting consecutive file modifications made during the same second. ([@thibaudgg][])
|
4
9
|
- Add rb-fchange support. ([@thibaudgg][])
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,20 +1,16 @@
|
|
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...**
|
4
|
-
|
5
3
|
The Listen gem listens to file modifications and notifies you about the changes.
|
6
4
|
|
7
|
-
##
|
5
|
+
## Features
|
8
6
|
|
9
|
-
|
10
|
-
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
- Dropbox detection with polling fallback (if needed)
|
17
|
-
- Improve API (if needed)
|
7
|
+
* Works everywhere!
|
8
|
+
* OS-specific adapters for Mac OS X 10.6+, Linux and Windows.
|
9
|
+
* Automatic fallback to polling if OS-specific adapter doesn't work.
|
10
|
+
* Detects files modification, addidation and removal.
|
11
|
+
* Checksum comparaison for modifications made under the same second.
|
12
|
+
* Tested on all Ruby environments via [travis-ci](http://travis-ci.org/guard/listen).
|
13
|
+
* Threadable.
|
18
14
|
|
19
15
|
## Install
|
20
16
|
|
@@ -27,14 +23,12 @@ gem install listen
|
|
27
23
|
There are two ways you can use Listen.
|
28
24
|
|
29
25
|
1. call `Listen.to` with a path params, and define callbacks in a block.
|
30
|
-
|
26
|
+
2. create a `listener` object usable in an (ARel style) chainable way.
|
31
27
|
|
32
28
|
Feel free to give your feeback via [Listen issues](https://github.com/guard/listener/issues)
|
33
29
|
|
34
30
|
### Block API
|
35
31
|
|
36
|
-
#### One dir
|
37
|
-
|
38
32
|
``` ruby
|
39
33
|
Listen.to('dir/path/to/listen', filter: /.*\.rb/, ignore: '/ignored/path') do |modified, added, removed|
|
40
34
|
# ...
|
@@ -47,6 +41,9 @@ end
|
|
47
41
|
listener = Listen.to('dir/path/to/listen')
|
48
42
|
listener = listener.ignore('/ignored/path')
|
49
43
|
listener = listener.filter(/.*\.rb/)
|
44
|
+
listener = listener.latency(0.5)
|
45
|
+
listener = listener.force_polling(true)
|
46
|
+
listener = listener.polling_fallback_message(false)
|
50
47
|
listener = listener.change(&callback)
|
51
48
|
listener.start # enter the run loop
|
52
49
|
listener.stop
|
@@ -55,7 +52,14 @@ listener.stop
|
|
55
52
|
#### Chainable
|
56
53
|
|
57
54
|
``` ruby
|
58
|
-
Listen.to('dir/path/to/listen')
|
55
|
+
Listen.to('dir/path/to/listen')
|
56
|
+
.ignore('/ignored/path')
|
57
|
+
.filter(/.*\.rb/)
|
58
|
+
.latency(0.5)
|
59
|
+
.force_polling(true)
|
60
|
+
.polling_fallback_message('custom message')
|
61
|
+
.change(&callback)
|
62
|
+
.start # enter the run loop
|
59
63
|
```
|
60
64
|
|
61
65
|
#### Multiple listeners support available via Thread
|
@@ -74,20 +78,83 @@ Thread.new { scripts.start } # enter the run loop
|
|
74
78
|
These options can be set through `Listen.to` params or via methods (see the "Object" API)
|
75
79
|
|
76
80
|
```ruby
|
77
|
-
:filter => /.*\.rb/, /.*\.coffee/
|
78
|
-
|
81
|
+
:filter => /.*\.rb/, /.*\.coffee/ # Filter files to listen to via a regexps list.
|
82
|
+
# default: none
|
83
|
+
|
84
|
+
:ignore => 'path1', 'path2' # Ignore a list of paths (root directory or sub-dir)
|
85
|
+
# default: '.bundle', '.git', '.DS_Store', 'log', 'tmp', 'vendor'
|
79
86
|
|
80
|
-
:
|
81
|
-
|
87
|
+
:latency => 0.5 # Set the delay (**in seconds**) between checking for changes
|
88
|
+
# default: 0.1 sec (1.0 sec for polling)
|
89
|
+
|
90
|
+
:force_polling => true # Force the use of the polling adapter
|
91
|
+
# default: none
|
92
|
+
|
93
|
+
:polling_fallback_message => 'custom message' # Set a custom polling fallback message (or disable it with `false`)
|
94
|
+
# default: "WARNING: Listen fallen back to polling, learn more at https://github.com/guard/listen#fallback."
|
82
95
|
```
|
83
96
|
|
97
|
+
## Listen adapters
|
98
|
+
|
99
|
+
The Listen gem has a set of adapters to notify it when there are changes.
|
100
|
+
There are 3 OS-specific adapters to support Mac, Linux and Windows. These adapters are fast
|
101
|
+
as they use some system-calls to implement the notifying function.
|
102
|
+
|
103
|
+
There is also a polling adapter which is a cross-platform adapter and it will
|
104
|
+
work on any system. This adapter is unfortunately slower than the rest of the adapters.
|
105
|
+
|
106
|
+
The Listen gem will choose the best and working adapter for your machine automatically. If you
|
107
|
+
want to force the use of the polling adapter, either use the `:force_polling` option
|
108
|
+
while initializing the listener or call the `force_polling` method on your listener
|
109
|
+
before starting it.
|
110
|
+
|
111
|
+
<a name="fallback"/>
|
112
|
+
### Polling fallback
|
113
|
+
|
114
|
+
When the OS-specific adapter doesn't work the Listen gem automatically falls back to the polling adapter.
|
115
|
+
Here some things to try to avoiding this fallback:
|
116
|
+
|
117
|
+
* [Update your Dropbox client](http://www.dropbox.com/downloading) (if used).
|
118
|
+
* Move or rename the listened folder.
|
119
|
+
* Update/reboot your OS.
|
120
|
+
|
121
|
+
If it still falling back, feel free to [open an issue](https://github.com/guard/listen/issues/new) (and be sure to give all details).
|
122
|
+
|
123
|
+
## Development [![Dependency Status](https://gemnasium.com/guard/listen.png?branch=master)](https://gemnasium.com/guard/listen)
|
124
|
+
|
125
|
+
* Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/listen/master/frames).
|
126
|
+
* Source hosted at [GitHub](https://github.com/guard/listen).
|
127
|
+
|
128
|
+
Pull requests are very welcome! Please try to follow these simple rules if applicable:
|
129
|
+
|
130
|
+
* Please create a topic branch for every separate change you make.
|
131
|
+
* Make sure your patches are well tested. All specs run with `rake spec:portability` must pass.
|
132
|
+
* Update the [Yard](http://yardoc.org/) documentation.
|
133
|
+
* Update the README.
|
134
|
+
* Update the CHANGELOG for noteworthy changes.
|
135
|
+
* Please **do not change** the version number.
|
136
|
+
|
137
|
+
For questions please join us in our [Google group](http://groups.google.com/group/guard-dev) or on
|
138
|
+
`#guard` (irc.freenode.net).
|
139
|
+
|
84
140
|
## Acknowledgment
|
85
141
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
142
|
+
* [Michael Kessler (netzpirat)][] for having written the [initial specs](https://github.com/guard/listen/commit/1e457b13b1bb8a25d2240428ce5ed488bafbed1f).
|
143
|
+
* [Travis Tilley (ttilley)][] for this awesome work on [fssm][] & [rb-fsevent][].
|
144
|
+
* [Nathan Weizenbaum (nex3)][] for [rb-inotify][], a thorough inotify wrapper.
|
145
|
+
* [stereobooster][] for [rb-fchange][], windows support wouldn't exist without him.
|
146
|
+
* [Yehuda Katz (wycats)][] for [vigilo][], that has been a great source of inspiration.
|
147
|
+
|
148
|
+
## Author
|
149
|
+
|
150
|
+
[Thibaud Guillaume-Gentil][] ([@thibaudgg](http://twitter.com/thibaudgg))
|
151
|
+
|
152
|
+
## Contributors
|
153
|
+
|
154
|
+
[https://github.com/guard/listen/contributors](https://github.com/guard/listen/contributors)
|
90
155
|
|
156
|
+
[Thibaud Guillaume-Gentil]: https://github.com/thibaudgg
|
157
|
+
[Michael Kessler (netzpirat)]: https://github.com/netzpirat
|
91
158
|
[Travis Tilley (ttilley)]: https://github.com/ttilley
|
92
159
|
[fssm]: https://github.com/ttilley/fssm
|
93
160
|
[rb-fsevent]: https://github.com/thibaudgg/rb-fsevent
|
data/lib/listen.rb
CHANGED
@@ -8,6 +8,8 @@ module Listen
|
|
8
8
|
# @param [Hash] options the listen options
|
9
9
|
# @option options [String] ignore a list of paths to ignore
|
10
10
|
# @option options [Regexp] filter a list of regexps file filters
|
11
|
+
# @option options [Float] latency the delay between checking for changes in seconds
|
12
|
+
# @option options [Boolean] polling whether to force or disable the polling adapter
|
11
13
|
#
|
12
14
|
# @yield [modified, added, removed] the changed files
|
13
15
|
# @yieldparam [Array<String>] modified the list of modified files
|
data/lib/listen/adapter.rb
CHANGED
@@ -4,35 +4,115 @@ module Listen
|
|
4
4
|
class Adapter
|
5
5
|
attr_accessor :latency
|
6
6
|
|
7
|
+
# The default delay between checking for changes.
|
8
|
+
DEFAULT_LATENCY = 0.1
|
9
|
+
# The default warning message when falling back to polling adapter.
|
10
|
+
POLLING_FALLBACK_MESSAGE = "WARNING: Listen fallen back to polling, learn more at https://github.com/guard/listen#fallback."
|
11
|
+
|
7
12
|
# Select the appropriate adapter implementation for the
|
8
13
|
# current OS and initializes it.
|
9
14
|
#
|
15
|
+
# @param [String, Pathname] directory the directory to watch
|
16
|
+
# @param [Hash] options the adapter options
|
17
|
+
# @option options [Boolean] force_polling to force polling or not
|
18
|
+
# @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
|
19
|
+
# @option options [Float] latency the delay between checking for changes in seconds
|
20
|
+
#
|
21
|
+
# @yield [changed_dirs, options] callback Callback called when a change happens
|
22
|
+
# @yieldparam [Array<String>] changed_dirs the changed directories
|
23
|
+
# @yieldparam [Hash] options callback options (like :recursive => true)
|
24
|
+
#
|
10
25
|
# @return [Listen::Adapter] the chosen adapter
|
11
26
|
#
|
12
|
-
def self.select_and_initialize(
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
Adapters::
|
17
|
-
elsif Adapters::
|
18
|
-
Adapters::
|
27
|
+
def self.select_and_initialize(directory, options = {}, &callback)
|
28
|
+
return Adapters::Polling.new(directory, options, &callback) if options.delete(:force_polling)
|
29
|
+
|
30
|
+
if Adapters::Darwin.usable_and_work?(directory, options)
|
31
|
+
Adapters::Darwin.new(directory, options, &callback)
|
32
|
+
elsif Adapters::Linux.usable_and_work?(directory, options)
|
33
|
+
Adapters::Linux.new(directory, options, &callback)
|
34
|
+
elsif Adapters::Windows.usable_and_work?(directory, options)
|
35
|
+
Adapters::Windows.new(directory, options, &callback)
|
19
36
|
else
|
20
|
-
|
37
|
+
unless options[:polling_fallback_message] == false
|
38
|
+
Kernel.warn(options[:polling_fallback_message] || POLLING_FALLBACK_MESSAGE)
|
39
|
+
end
|
40
|
+
Adapters::Polling.new(directory, options, &callback)
|
21
41
|
end
|
22
42
|
end
|
23
43
|
|
24
|
-
|
25
|
-
|
44
|
+
# Initialize the adapter.
|
45
|
+
#
|
46
|
+
# @param [String, Pathname] directory the directory to watch
|
47
|
+
# @param [Hash] options the adapter options
|
48
|
+
# @option options [Float] latency the delay between checking for changes in seconds
|
49
|
+
#
|
50
|
+
# @yield [changed_dirs, options] callback Callback called when a change happens
|
51
|
+
# @yieldparam [Array<String>] changed_dirs the changed directories
|
52
|
+
# @yieldparam [Hash] options callback options (like :recursive => true)
|
53
|
+
#
|
54
|
+
# @return [Listen::Adapter] the adapter
|
55
|
+
#
|
56
|
+
def initialize(directory, options = {}, &callback)
|
57
|
+
@directory = directory
|
58
|
+
@callback = callback
|
59
|
+
@latency ||= DEFAULT_LATENCY
|
60
|
+
@latency = options[:latency] if options[:latency]
|
26
61
|
end
|
27
62
|
|
28
63
|
# Start the adapter.
|
29
64
|
#
|
30
65
|
def start
|
66
|
+
@stop = false
|
31
67
|
end
|
32
68
|
|
33
69
|
# Stop the adapter.
|
34
70
|
#
|
35
71
|
def stop
|
72
|
+
@stop = true
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
# Check if the adapter is usable and works on the current OS.
|
78
|
+
#
|
79
|
+
# @param [String, Pathname] directory the directory to watch
|
80
|
+
# @param [Hash] options the adapter options
|
81
|
+
# @option options [Float] latency the delay between checking for changes in seconds
|
82
|
+
#
|
83
|
+
# @return [Boolean] whether usable and work or not
|
84
|
+
#
|
85
|
+
def self.usable_and_work?(directory, options = {})
|
86
|
+
usable? && work?(directory, options)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Check if the adapter is really working on the current OS by actually testing it.
|
90
|
+
# This test take some time depending the adapter latency (max latency + 0.2 seconds).
|
91
|
+
#
|
92
|
+
# @param [String, Pathname] directory the directory to watch
|
93
|
+
# @param [Hash] options the adapter options
|
94
|
+
# @option options [Float] latency the delay between checking for changes in seconds
|
95
|
+
#
|
96
|
+
# @return [Boolean] whether work or not
|
97
|
+
#
|
98
|
+
def self.work?(directory, options = {})
|
99
|
+
@work = nil
|
100
|
+
Thread.new do
|
101
|
+
begin
|
102
|
+
callback = lambda { |changed_dirs, options| @work = true }
|
103
|
+
adapter = self.new(directory, options, &callback)
|
104
|
+
thread = Thread.new { adapter.start }
|
105
|
+
sleep 0.1 # wait for the adapter starts
|
106
|
+
FileUtils.touch "#{directory}/.listen_test"
|
107
|
+
sleep adapter.latency + 0.1 # wait for callback
|
108
|
+
@work ||= false
|
109
|
+
Thread.kill(thread)
|
110
|
+
ensure
|
111
|
+
FileUtils.rm "#{directory}/.listen_test"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
sleep 0.01 while @work.nil?
|
115
|
+
@work
|
36
116
|
end
|
37
117
|
|
38
118
|
end
|
@@ -5,11 +5,10 @@ module Listen
|
|
5
5
|
#
|
6
6
|
class Darwin < Adapter
|
7
7
|
|
8
|
-
# Initialize the Adapter.
|
8
|
+
# Initialize the Adapter. See {Listen::Adapter#initialize} for more info.
|
9
9
|
#
|
10
|
-
def initialize(
|
10
|
+
def initialize(directory, options = {}, &callback)
|
11
11
|
super
|
12
|
-
@latency ||= 0.1
|
13
12
|
init_worker
|
14
13
|
end
|
15
14
|
|
@@ -46,9 +45,9 @@ module Listen
|
|
46
45
|
#
|
47
46
|
def init_worker
|
48
47
|
@worker = FSEvent.new
|
49
|
-
@worker.watch(@
|
48
|
+
@worker.watch(@directory, :latency => @latency) do |changed_dirs|
|
50
49
|
changed_dirs.map! { |path| path.sub /\/$/, '' }
|
51
|
-
@
|
50
|
+
@callback.call(changed_dirs, {})
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
@@ -9,16 +9,15 @@ module Listen
|
|
9
9
|
# @see https://github.com/nex3/rb-inotify/blob/master/lib/rb-inotify/notifier.rb#L99-L177
|
10
10
|
#
|
11
11
|
EVENTS = %w[recursive attrib close modify move create delete delete_self move_self]
|
12
|
-
|
12
|
+
|
13
13
|
# Listener implementation for Linux `inotify`.
|
14
14
|
#
|
15
15
|
class Linux < Adapter
|
16
16
|
|
17
|
-
# Initialize the Adapter.
|
17
|
+
# Initialize the Adapter. See {Listen::Adapter#initialize} for more info.
|
18
18
|
#
|
19
|
-
def initialize(
|
19
|
+
def initialize(directory, options = {}, &callback)
|
20
20
|
super
|
21
|
-
@latency ||= 0.1
|
22
21
|
@changed_dirs = Set.new
|
23
22
|
init_worker
|
24
23
|
end
|
@@ -28,7 +27,6 @@ module Listen
|
|
28
27
|
def start
|
29
28
|
super
|
30
29
|
Thread.new { @worker.run }
|
31
|
-
@stop = false
|
32
30
|
poll_changed_dirs
|
33
31
|
end
|
34
32
|
|
@@ -36,7 +34,6 @@ module Listen
|
|
36
34
|
#
|
37
35
|
def stop
|
38
36
|
super
|
39
|
-
@stop = true
|
40
37
|
@worker.stop
|
41
38
|
end
|
42
39
|
|
@@ -54,28 +51,27 @@ module Listen
|
|
54
51
|
end
|
55
52
|
|
56
53
|
private
|
57
|
-
|
58
|
-
#
|
54
|
+
|
55
|
+
# Initialize INotify worker and set watch callback block.
|
59
56
|
#
|
60
57
|
def init_worker
|
61
58
|
@worker = INotify::Notifier.new
|
62
|
-
@worker.watch(@
|
59
|
+
@worker.watch(@directory, *EVENTS.map(&:to_sym)) do |event|
|
63
60
|
unless event.name == "" # Event on root directory
|
64
61
|
@changed_dirs << File.dirname(event.absolute_name)
|
65
62
|
end
|
66
63
|
end
|
67
64
|
end
|
68
|
-
|
65
|
+
|
69
66
|
# Polling around @changed_dirs presence.
|
70
67
|
#
|
71
68
|
def poll_changed_dirs
|
72
69
|
until @stop
|
73
70
|
sleep(@latency)
|
74
|
-
|
75
71
|
next if @changed_dirs.empty?
|
76
72
|
changed_dirs = @changed_dirs.to_a
|
77
|
-
@changed_dirs.clear
|
78
|
-
@
|
73
|
+
@changed_dirs.clear
|
74
|
+
@callback.call(changed_dirs, {})
|
79
75
|
end
|
80
76
|
end
|
81
77
|
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module Listen
|
2
2
|
module Adapters
|
3
3
|
|
4
|
+
# The default delay between checking for changes.
|
5
|
+
DEFAULT_POLLING_LATENCY = 1.0
|
6
|
+
|
4
7
|
# Polling Adapter that works cross-platform and
|
5
8
|
# has no dependencies. This is the adapter that
|
6
9
|
# uses the most CPU processing power and has higher
|
@@ -8,18 +11,17 @@ module Listen
|
|
8
11
|
#
|
9
12
|
class Polling < Adapter
|
10
13
|
|
11
|
-
# Initialize the Adapter.
|
14
|
+
# Initialize the Adapter. See {Listen::Adapter#initialize} for more info.
|
12
15
|
#
|
13
|
-
def initialize(
|
16
|
+
def initialize(directory, options = {}, &callback)
|
17
|
+
@latency ||= DEFAULT_POLLING_LATENCY
|
14
18
|
super
|
15
|
-
@latency ||= 1.0
|
16
19
|
end
|
17
20
|
|
18
21
|
# Start the adapter.
|
19
22
|
#
|
20
23
|
def start
|
21
24
|
super
|
22
|
-
@stop = false
|
23
25
|
poll
|
24
26
|
end
|
25
27
|
|
@@ -27,7 +29,6 @@ module Listen
|
|
27
29
|
#
|
28
30
|
def stop
|
29
31
|
super
|
30
|
-
@stop = true
|
31
32
|
end
|
32
33
|
|
33
34
|
private
|
@@ -37,10 +38,11 @@ module Listen
|
|
37
38
|
def poll
|
38
39
|
until @stop
|
39
40
|
start = Time.now.to_f
|
40
|
-
@
|
41
|
+
@callback.call([@directory], :recursive => true)
|
41
42
|
nap_time = @latency - (Time.now.to_f - start)
|
42
43
|
sleep(nap_time) if nap_time > 0
|
43
44
|
end
|
45
|
+
rescue Interrupt
|
44
46
|
end
|
45
47
|
|
46
48
|
end
|
@@ -7,11 +7,10 @@ module Listen
|
|
7
7
|
#
|
8
8
|
class Windows < Adapter
|
9
9
|
|
10
|
-
# Initialize the Adapter.
|
10
|
+
# Initialize the Adapter. See {Listen::Adapter#initialize} for more info.
|
11
11
|
#
|
12
|
-
def initialize(
|
12
|
+
def initialize(directory, options = {}, &callback)
|
13
13
|
super
|
14
|
-
@latency ||= 0.1
|
15
14
|
@changed_dirs = Set.new
|
16
15
|
init_worker
|
17
16
|
end
|
@@ -21,7 +20,6 @@ module Listen
|
|
21
20
|
def start
|
22
21
|
super
|
23
22
|
Thread.new { @worker.run }
|
24
|
-
@stop = false
|
25
23
|
poll_changed_dirs
|
26
24
|
end
|
27
25
|
|
@@ -51,21 +49,21 @@ module Listen
|
|
51
49
|
#
|
52
50
|
def init_worker
|
53
51
|
@worker = FChange::Notifier.new
|
54
|
-
@worker.watch(@
|
52
|
+
@worker.watch(@directory, :all_events, :recursive) do |event|
|
55
53
|
@changed_dirs << File.expand_path(event.watcher.path)
|
56
54
|
end
|
57
55
|
end
|
58
|
-
|
56
|
+
|
59
57
|
# Polling around @changed_dirs presence.
|
60
58
|
#
|
61
59
|
def poll_changed_dirs
|
62
60
|
until @stop
|
63
61
|
sleep(@latency)
|
64
|
-
|
62
|
+
|
65
63
|
next if @changed_dirs.empty?
|
66
64
|
changed_dirs = @changed_dirs.to_a
|
67
65
|
@changed_dirs.clear
|
68
|
-
@
|
66
|
+
@callback.call(changed_dirs, :recursive => true)
|
69
67
|
end
|
70
68
|
end
|
71
69
|
|
data/lib/listen/listener.rb
CHANGED
@@ -9,17 +9,20 @@ require 'listen/adapters/windows'
|
|
9
9
|
|
10
10
|
module Listen
|
11
11
|
class Listener
|
12
|
-
attr_accessor :directory, :ignored_paths, :file_filters, :sha1_checksums, :paths
|
12
|
+
attr_accessor :directory, :ignored_paths, :file_filters, :sha1_checksums, :paths
|
13
13
|
|
14
14
|
# Default paths that gets ignored by the listener
|
15
15
|
DEFAULT_IGNORED_PATHS = %w[.bundle .git .DS_Store log tmp vendor]
|
16
16
|
|
17
17
|
# Initialize the file listener.
|
18
18
|
#
|
19
|
-
# @param [String, Pathname]
|
19
|
+
# @param [String, Pathname] directory the directory to watch
|
20
20
|
# @param [Hash] options the listen options
|
21
21
|
# @option options [String] ignore a list of paths to ignore
|
22
22
|
# @option options [Regexp] filter a list of regexps file filters
|
23
|
+
# @option options [Float] latency the delay between checking for changes in seconds
|
24
|
+
# @option options [Boolean] force_polling whether to force the polling adapter or not
|
25
|
+
# @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
|
23
26
|
#
|
24
27
|
# @yield [modified, added, removed] the changed files
|
25
28
|
# @yieldparam [Array<String>] modified the list of modified files
|
@@ -28,23 +31,24 @@ module Listen
|
|
28
31
|
#
|
29
32
|
# @return [Listen::Listener] the file listener
|
30
33
|
#
|
31
|
-
def initialize(
|
32
|
-
@directory =
|
34
|
+
def initialize(directory, options = {}, &block)
|
35
|
+
@directory = directory
|
33
36
|
@ignored_paths = DEFAULT_IGNORED_PATHS
|
34
37
|
@file_filters = []
|
35
38
|
@sha1_checksums = {}
|
36
39
|
@block = block
|
37
|
-
if
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
@adapter = Adapter.select_and_initialize(self)
|
40
|
+
@ignored_paths += Array(options.delete(:ignore)) if options[:ignore]
|
41
|
+
@file_filters += Array(options.delete(:filter)) if options[:filter]
|
42
|
+
|
43
|
+
@adapter_options = options
|
42
44
|
end
|
43
45
|
|
44
|
-
# Initialize the @paths and start the adapter.
|
46
|
+
# Initialize the adapter and the @paths concurrently and start the adapter.
|
45
47
|
#
|
46
48
|
def start
|
49
|
+
Thread.new { @adapter = initialize_adapter }
|
47
50
|
init_paths
|
51
|
+
sleep 0.01 while @adapter.nil?
|
48
52
|
@adapter.start
|
49
53
|
end
|
50
54
|
|
@@ -82,9 +86,53 @@ module Listen
|
|
82
86
|
self
|
83
87
|
end
|
84
88
|
|
89
|
+
# Sets the latency for the adapter. This is a helper method
|
90
|
+
# to simplify changing the latency directly from the listener.
|
91
|
+
#
|
92
|
+
# @example Wait 0.5 seconds each time before checking changes
|
93
|
+
# latency 0.5
|
94
|
+
#
|
95
|
+
# @param [Float] seconds the amount of delay, in seconds
|
96
|
+
#
|
97
|
+
# @return [Listen::Listener] the listener itself
|
98
|
+
#
|
99
|
+
def latency(seconds)
|
100
|
+
@adapter_options[:latency] = seconds
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
# Defines whether the use of the polling adapter
|
105
|
+
# should be forced or not.
|
106
|
+
#
|
107
|
+
# @example Forcing the use of the polling adapter
|
108
|
+
# force_polling true
|
109
|
+
#
|
110
|
+
# @param [Boolean] value wheather to force the polling adapter or not
|
111
|
+
#
|
112
|
+
# @return [Listen::Listener] the listener itself
|
113
|
+
#
|
114
|
+
def force_polling(value)
|
115
|
+
@adapter_options[:force_polling] = value
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
# Defines a custom polling fallback message of disable it.
|
120
|
+
#
|
121
|
+
# @example Disabling the polling fallback message
|
122
|
+
# polling_fallback_message false
|
123
|
+
#
|
124
|
+
# @param [String, Boolean] value to change polling fallback message or remove it
|
125
|
+
#
|
126
|
+
# @return [Listen::Listener] the listener itself
|
127
|
+
#
|
128
|
+
def polling_fallback_message(value)
|
129
|
+
@adapter_options[:polling_fallback_message] = value
|
130
|
+
self
|
131
|
+
end
|
132
|
+
|
85
133
|
# Set change callback block to the listener.
|
86
134
|
#
|
87
|
-
# @example
|
135
|
+
# @example Assign a callback to be called on changes
|
88
136
|
# callback = lambda { |modified, added, removed| ... }
|
89
137
|
# change &callback
|
90
138
|
#
|
@@ -136,6 +184,13 @@ module Listen
|
|
136
184
|
|
137
185
|
private
|
138
186
|
|
187
|
+
# Initialize adapter with the listener callback and the @adapter_options
|
188
|
+
#
|
189
|
+
def initialize_adapter
|
190
|
+
callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
|
191
|
+
Adapter.select_and_initialize(@directory, @adapter_options, &callback)
|
192
|
+
end
|
193
|
+
|
139
194
|
# Research all existing paths (directories & files) filtered and without ignored directories paths.
|
140
195
|
#
|
141
196
|
# @yield [path] the existing path
|
@@ -183,7 +238,7 @@ module Listen
|
|
183
238
|
def detect_modifications_and_removals(directory, options = {})
|
184
239
|
@paths[directory].each do |basename, type|
|
185
240
|
path = File.join(directory, basename)
|
186
|
-
|
241
|
+
|
187
242
|
case type
|
188
243
|
when 'Dir'
|
189
244
|
if File.directory?(path)
|
data/lib/listen/version.rb
CHANGED
metadata
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: listen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Thibaud Guillaume-Gentil
|
9
|
-
- Michael Kessler
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-21 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: rb-fsevent
|
17
|
-
requirement: &
|
16
|
+
requirement: &70190939404480 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ~>
|
@@ -22,10 +21,10 @@ dependencies:
|
|
22
21
|
version: 0.9.0
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements: *
|
24
|
+
version_requirements: *70190939404480
|
26
25
|
- !ruby/object:Gem::Dependency
|
27
26
|
name: rb-inotify
|
28
|
-
requirement: &
|
27
|
+
requirement: &70190939403840 !ruby/object:Gem::Requirement
|
29
28
|
none: false
|
30
29
|
requirements:
|
31
30
|
- - ~>
|
@@ -33,10 +32,10 @@ dependencies:
|
|
33
32
|
version: 0.8.8
|
34
33
|
type: :runtime
|
35
34
|
prerelease: false
|
36
|
-
version_requirements: *
|
35
|
+
version_requirements: *70190939403840
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
37
|
name: rb-fchange
|
39
|
-
requirement: &
|
38
|
+
requirement: &70190939403220 !ruby/object:Gem::Requirement
|
40
39
|
none: false
|
41
40
|
requirements:
|
42
41
|
- - ~>
|
@@ -44,10 +43,10 @@ dependencies:
|
|
44
43
|
version: 0.0.5
|
45
44
|
type: :runtime
|
46
45
|
prerelease: false
|
47
|
-
version_requirements: *
|
46
|
+
version_requirements: *70190939403220
|
48
47
|
- !ruby/object:Gem::Dependency
|
49
48
|
name: bundler
|
50
|
-
requirement: &
|
49
|
+
requirement: &70190939402680 !ruby/object:Gem::Requirement
|
51
50
|
none: false
|
52
51
|
requirements:
|
53
52
|
- - ! '>='
|
@@ -55,12 +54,11 @@ dependencies:
|
|
55
54
|
version: '0'
|
56
55
|
type: :development
|
57
56
|
prerelease: false
|
58
|
-
version_requirements: *
|
57
|
+
version_requirements: *70190939402680
|
59
58
|
description: The Listen gem listens to file modifications and notifies you about the
|
60
59
|
changes. Works everywhere!
|
61
60
|
email:
|
62
61
|
- thibaud@thibaud.me
|
63
|
-
- michi@netzpiraten.ch
|
64
62
|
executables: []
|
65
63
|
extensions: []
|
66
64
|
extra_rdoc_files: []
|
@@ -96,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
94
|
version: 1.3.6
|
97
95
|
requirements: []
|
98
96
|
rubyforge_project: listen
|
99
|
-
rubygems_version: 1.8.
|
97
|
+
rubygems_version: 1.8.16
|
100
98
|
signing_key:
|
101
99
|
specification_version: 3
|
102
100
|
summary: Listen to file modifications
|