listen 3.1.3 → 3.3.0.pre.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CONTRIBUTING.md +8 -1
- data/README.md +29 -11
- data/lib/listen.rb +15 -25
- data/lib/listen/adapter.rb +6 -8
- data/lib/listen/adapter/base.rb +17 -29
- data/lib/listen/adapter/bsd.rb +3 -1
- data/lib/listen/adapter/config.rb +2 -0
- data/lib/listen/adapter/darwin.rb +29 -44
- data/lib/listen/adapter/linux.rb +6 -4
- data/lib/listen/adapter/polling.rb +2 -0
- data/lib/listen/adapter/windows.rb +6 -4
- data/lib/listen/backend.rb +2 -0
- data/lib/listen/change.rb +5 -3
- data/lib/listen/cli.rb +3 -2
- data/lib/listen/directory.rb +10 -2
- data/lib/listen/event/config.rb +8 -18
- data/lib/listen/event/loop.rb +43 -64
- data/lib/listen/event/processor.rb +26 -24
- data/lib/listen/event/queue.rb +4 -5
- data/lib/listen/file.rb +9 -2
- data/lib/listen/fsm.rb +69 -71
- data/lib/listen/listener.rb +25 -24
- data/lib/listen/listener/config.rb +2 -0
- data/lib/listen/logger.rb +27 -24
- data/lib/listen/options.rb +3 -1
- data/lib/listen/queue_optimizer.rb +6 -4
- data/lib/listen/record.rb +16 -2
- data/lib/listen/record/entry.rb +3 -1
- data/lib/listen/record/symlink_detector.rb +2 -0
- data/lib/listen/silencer.rb +5 -0
- data/lib/listen/silencer/controller.rb +2 -0
- data/lib/listen/thread.rb +47 -0
- data/lib/listen/version.rb +3 -1
- metadata +16 -48
- data/lib/listen/internals/thread_pool.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 82d32d20751964de477dd8c2ff8af48cc0c70558b323c1043b37d5bf9183c3ba
|
4
|
+
data.tar.gz: fb40a33b41e0bf52ce30303fc88a7fb1dd35a9d56e2e920fccf598fcd7193c17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14e679e027bb5c100eaf438f10ec96ce5336465366facf7559a19ed6fa23d0c6e89f72eba25fb53a1e689ca08d0572d54399826b3d78d5cb354f2b2c7d105b61
|
7
|
+
data.tar.gz: 4b4f93d99b7519d06a7302152e8d86332edb8a656caef7c1b164596d79c221d539ad0a29481709915070945e46fb1c4661bde3368f0e9c55cd277ffe52bc8b13
|
data/CONTRIBUTING.md
CHANGED
@@ -31,8 +31,15 @@ Pull requests are very welcome! Please try to follow these simple rules if appli
|
|
31
31
|
* Make sure your patches are well tested. All specs run with `rake spec` must pass.
|
32
32
|
* Update the [Yard](http://yardoc.org/) documentation.
|
33
33
|
* Update the [README](https://github.com/guard/listen/blob/master/README.md).
|
34
|
-
* Update the [CHANGELOG](https://github.com/guard/listen/blob/master/CHANGELOG.md) for noteworthy changes.
|
35
34
|
* Please **do not change** the version number.
|
36
35
|
|
36
|
+
The title of your PR will automatically be included in the release notes for the next version of the gem. A maintainer can add one of the following GitHub labels to the PR to automatically categorize it when the release notes are generated:
|
37
|
+
|
38
|
+
- ⚠️ Breaking
|
39
|
+
- ✨ Feature
|
40
|
+
- 🐛 Bug Fix
|
41
|
+
- 📚 Docs
|
42
|
+
- 🏠 Housekeeping
|
43
|
+
|
37
44
|
For questions please join us in our [Google group](http://groups.google.com/group/guard-dev) or on
|
38
45
|
`#guard` (irc.freenode.net).
|
data/README.md
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
-
|
1
|
+
# Listen
|
2
2
|
|
3
|
-
|
3
|
+
The Listen gem listens to file modifications and notifies you about the changes.
|
4
4
|
|
5
5
|
:exclamation: Listen is currently accepting more maintainers. Please [read this](https://github.com/guard/guard/wiki/Maintainers) if you're interested in joining the team.
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
[](https://github.com/guard/listen/actions?workflow=Development)
|
8
|
+
[](http://badge.fury.io/rb/listen)
|
9
|
+
[](https://codeclimate.com/github/guard/listen)
|
10
|
+
[](https://coveralls.io/r/guard/listen)
|
12
11
|
|
13
12
|
## Features
|
14
13
|
|
@@ -31,7 +30,8 @@ The Listen gem listens to file modifications and notifies you about the changes.
|
|
31
30
|
* Specs suite on JRuby and Rubinius aren't reliable on Travis CI, but should work.
|
32
31
|
* Windows and \*BSD adapter aren't continuously and automatically tested.
|
33
32
|
* OSX adapter has some performance limitations ([#342](https://github.com/guard/listen/issues/342)).
|
34
|
-
* Ruby < 2.2.x is no longer supported - upgrade to Ruby 2.2 or 2.3
|
33
|
+
* Ruby < 2.2.x is no longer supported - upgrade to Ruby 2.2 or 2.3.
|
34
|
+
* Listeners do not notify across forked processes, if you wish for multiple processes to receive change notifications you must [listen inside of each process](https://github.com/guard/listen/issues/398#issuecomment-223957952).
|
35
35
|
|
36
36
|
Pull requests or help is very welcome for these.
|
37
37
|
|
@@ -170,7 +170,7 @@ polling_fallback_message: 'custom message' # Set a custom polling fallback
|
|
170
170
|
|
171
171
|
## Debugging
|
172
172
|
|
173
|
-
Setting the environment variable `LISTEN_GEM_DEBUGGING=1` sets up the INFO level logger, while `LISTEN_GEM_DEBUGGING=2` sets up the DEBUG level logger.
|
173
|
+
Setting the environment variable `LISTEN_GEM_DEBUGGING=1` sets up the INFO level logger, while `LISTEN_GEM_DEBUGGING=2` sets up the DEBUG level logger.
|
174
174
|
|
175
175
|
You can also set `Listen.logger` to a custom logger.
|
176
176
|
|
@@ -263,11 +263,29 @@ Pull requests are very welcome! Please try to follow these simple rules if appli
|
|
263
263
|
For questions please join us in our [Google group](http://groups.google.com/group/guard-dev) or on
|
264
264
|
`#guard` (irc.freenode.net).
|
265
265
|
|
266
|
+
## Releasing
|
267
|
+
|
268
|
+
### Prerequisites
|
269
|
+
|
270
|
+
* You must have commit rights to the GitHub repository.
|
271
|
+
* You must have push rights for rubygems.org.
|
272
|
+
|
273
|
+
### How to release
|
274
|
+
|
275
|
+
1. Run `bundle install` to make sure that you have all the gems necessary for testing and releasing.
|
276
|
+
2. **Ensure all tests are passing by running `bundle exec rake`.**
|
277
|
+
3. Determine which would be the correct next version number according to [semver](http://semver.org/).
|
278
|
+
4. Update the version in `./lib/listen/version.rb`.
|
279
|
+
5. Update the version in the Install section of `./README.md` (`gem 'listen', '~> X.Y'`).
|
280
|
+
6. Commit the version in a single commit, the message should be "Preparing vX.Y.Z"
|
281
|
+
7. Run `bundle exec rake release:full`; this will tag, push to GitHub, and publish to rubygems.org.
|
282
|
+
8. Update and publish the release notes on the [GitHub releases page](https://github.com/guard/listen/releases) if necessary
|
283
|
+
|
266
284
|
## Acknowledgments
|
267
285
|
|
268
286
|
* [Michael Kessler (netzpirat)][] for having written the [initial specs](https://github.com/guard/listen/commit/1e457b13b1bb8a25d2240428ce5ed488bafbed1f).
|
269
287
|
* [Travis Tilley (ttilley)][] for this awesome work on [fssm][] & [rb-fsevent][].
|
270
|
-
* [
|
288
|
+
* [Natalie Weizenbaum (nex3)][] for [rb-inotify][], a thorough inotify wrapper.
|
271
289
|
* [Mathieu Arnold (mat813)][] for [rb-kqueue][], a simple kqueue wrapper.
|
272
290
|
* [Maher Sallam][] for [wdm][], windows support wouldn't exist without him.
|
273
291
|
* [Yehuda Katz (wycats)][] for [vigilo][], that has been a great source of inspiration.
|
@@ -287,7 +305,7 @@ For questions please join us in our [Google group](http://groups.google.com/grou
|
|
287
305
|
[fssm]: https://github.com/ttilley/fssm
|
288
306
|
[rb-fsevent]: https://github.com/thibaudgg/rb-fsevent
|
289
307
|
[Mathieu Arnold (mat813)]: https://github.com/mat813
|
290
|
-
[
|
308
|
+
[Natalie Weizenbaum (nex3)]: https://github.com/nex3
|
291
309
|
[rb-inotify]: https://github.com/nex3/rb-inotify
|
292
310
|
[stereobooster]: https://github.com/stereobooster
|
293
311
|
[rb-fchange]: https://github.com/stereobooster/rb-fchange
|
data/lib/listen.rb
CHANGED
@@ -1,28 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'logger'
|
4
|
+
require 'weakref'
|
2
5
|
require 'listen/logger'
|
3
6
|
require 'listen/listener'
|
4
7
|
|
5
|
-
require 'listen/internals/thread_pool'
|
6
|
-
|
7
|
-
# Show warnings about vulnerabilities, bugs and outdated Rubies, since previous
|
8
|
-
# versions aren't tested or officially supported.
|
9
|
-
require 'ruby_dep/warning'
|
10
|
-
RubyDep::Warning.new.show_warnings
|
11
|
-
|
12
|
-
# Always set up logging by default first time file is required
|
13
|
-
#
|
14
|
-
# NOTE: If you need to clear the logger completely, do so *after*
|
15
|
-
# requiring this file. If you need to set a custom logger,
|
16
|
-
# require the listen/logger file and set the logger before requiring
|
17
|
-
# this file.
|
18
|
-
Listen.setup_default_logger_if_unset
|
19
|
-
|
20
8
|
# Won't print anything by default because of level - unless you've set
|
21
9
|
# LISTEN_GEM_DEBUGGING or provided your own logger with a high enough level
|
22
|
-
Listen
|
23
|
-
Listen
|
10
|
+
Listen.logger.info "Listen loglevel set to: #{Listen.logger.level}"
|
11
|
+
Listen.logger.info "Listen version: #{Listen::VERSION}"
|
24
12
|
|
25
13
|
module Listen
|
14
|
+
@listeners = Queue.new
|
15
|
+
|
26
16
|
class << self
|
27
17
|
# Listens to file system modifications on a either single directory or
|
28
18
|
# multiple directories.
|
@@ -37,21 +27,21 @@ module Listen
|
|
37
27
|
# @return [Listen::Listener] the listener
|
38
28
|
#
|
39
29
|
def to(*args, &block)
|
40
|
-
@listeners ||= []
|
41
30
|
Listener.new(*args, &block).tap do |listener|
|
42
|
-
@listeners
|
31
|
+
@listeners.enq(WeakRef.new(listener))
|
43
32
|
end
|
44
33
|
end
|
45
34
|
|
46
35
|
# This is used by the `listen` binary to handle Ctrl-C
|
47
36
|
#
|
48
37
|
def stop
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
38
|
+
while (listener = @listeners.deq(true))
|
39
|
+
begin
|
40
|
+
listener.stop
|
41
|
+
rescue WeakRef::RefError
|
42
|
+
end
|
43
|
+
end
|
44
|
+
rescue ThreadError
|
55
45
|
end
|
56
46
|
end
|
57
47
|
end
|
data/lib/listen/adapter.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'listen/adapter/base'
|
2
4
|
require 'listen/adapter/bsd'
|
3
5
|
require 'listen/adapter/darwin'
|
@@ -13,15 +15,15 @@ module Listen
|
|
13
15
|
|
14
16
|
class << self
|
15
17
|
def select(options = {})
|
16
|
-
|
18
|
+
Listen.logger.debug 'Adapter: considering polling ...'
|
17
19
|
return Polling if options[:force_polling]
|
18
|
-
|
20
|
+
Listen.logger.debug 'Adapter: considering optimized backend...'
|
19
21
|
return _usable_adapter_class if _usable_adapter_class
|
20
|
-
|
22
|
+
Listen.logger.debug 'Adapter: falling back to polling...'
|
21
23
|
_warn_polling_fallback(options)
|
22
24
|
Polling
|
23
25
|
rescue
|
24
|
-
|
26
|
+
Listen.logger.warn format('Adapter: failed: %s:%s', $ERROR_POSITION.inspect,
|
25
27
|
$ERROR_POSITION * "\n")
|
26
28
|
raise
|
27
29
|
end
|
@@ -36,10 +38,6 @@ module Listen
|
|
36
38
|
msg = options.fetch(:polling_fallback_message, POLLING_FALLBACK_MESSAGE)
|
37
39
|
Kernel.warn "[Listen warning]:\n #{msg}" if msg
|
38
40
|
end
|
39
|
-
|
40
|
-
def _log(type, message)
|
41
|
-
Listen::Logger.send(type, message)
|
42
|
-
end
|
43
41
|
end
|
44
42
|
end
|
45
43
|
end
|
data/lib/listen/adapter/base.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'listen/options'
|
2
4
|
require 'listen/record'
|
3
5
|
require 'listen/change'
|
6
|
+
require 'listen/thread'
|
4
7
|
|
5
8
|
module Listen
|
6
9
|
module Adapter
|
@@ -30,7 +33,7 @@ module Listen
|
|
30
33
|
# TODO: it's a separate method as a temporary workaround for tests
|
31
34
|
def configure
|
32
35
|
if @configured
|
33
|
-
|
36
|
+
Listen.logger.warn('Adapter already configured!')
|
34
37
|
return
|
35
38
|
end
|
36
39
|
|
@@ -63,48 +66,39 @@ module Listen
|
|
63
66
|
configure
|
64
67
|
|
65
68
|
if started?
|
66
|
-
|
69
|
+
Listen.logger.warn('Adapter already started!')
|
67
70
|
return
|
68
71
|
end
|
69
72
|
|
70
73
|
@started = true
|
71
74
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
@snapshots.values.each do |snapshot|
|
76
|
-
_timed('Record.build()') { snapshot.record.build }
|
77
|
-
end
|
78
|
-
_run
|
79
|
-
rescue
|
80
|
-
msg = 'run() in thread failed: %s:\n'\
|
81
|
-
' %s\n\ncalled from:\n %s'
|
82
|
-
_log_exception(msg, calling_stack)
|
83
|
-
raise # for unit tests mostly
|
75
|
+
@run_thread = Listen::Thread.new("run_thread") do
|
76
|
+
@snapshots.values.each do |snapshot|
|
77
|
+
_timed('Record.build()') { snapshot.record.build }
|
84
78
|
end
|
79
|
+
_run
|
85
80
|
end
|
86
81
|
end
|
87
82
|
|
88
83
|
def stop
|
89
84
|
_stop
|
90
|
-
|
91
|
-
|
92
|
-
def self.usable?
|
93
|
-
const_get('OS_REGEXP') =~ RbConfig::CONFIG['target_os']
|
85
|
+
config.queue.close # this causes queue.pop to return `nil` to the front-end
|
94
86
|
end
|
95
87
|
|
96
88
|
private
|
97
89
|
|
98
90
|
def _stop
|
91
|
+
@run_thread&.kill
|
92
|
+
@run_thread = nil
|
99
93
|
end
|
100
94
|
|
101
95
|
def _timed(title)
|
102
96
|
start = Time.now.to_f
|
103
97
|
yield
|
104
98
|
diff = Time.now.to_f - start
|
105
|
-
Listen
|
99
|
+
Listen.logger.info format('%s: %.05f seconds', title, diff)
|
106
100
|
rescue
|
107
|
-
Listen
|
101
|
+
Listen.logger.warn "#{title} crashed: #{$ERROR_INFO.inspect}"
|
108
102
|
raise
|
109
103
|
end
|
110
104
|
|
@@ -114,10 +108,6 @@ module Listen
|
|
114
108
|
@snapshots[dir].invalidate(type, rel_path, options)
|
115
109
|
end
|
116
110
|
|
117
|
-
def _log(*args, &block)
|
118
|
-
self.class.send(:_log, *args, &block)
|
119
|
-
end
|
120
|
-
|
121
111
|
def _log_exception(msg, caller_stack)
|
122
112
|
formatted = format(
|
123
113
|
msg,
|
@@ -126,14 +116,12 @@ module Listen
|
|
126
116
|
caller_stack * "\n"
|
127
117
|
)
|
128
118
|
|
129
|
-
|
119
|
+
Listen.logger.error(formatted)
|
130
120
|
end
|
131
121
|
|
132
122
|
class << self
|
133
|
-
|
134
|
-
|
135
|
-
def _log(*args, &block)
|
136
|
-
Listen::Logger.send(*args, &block)
|
123
|
+
def usable?
|
124
|
+
const_get('OS_REGEXP') =~ RbConfig::CONFIG['target_os']
|
137
125
|
end
|
138
126
|
end
|
139
127
|
end
|
data/lib/listen/adapter/bsd.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Listener implementation for BSD's `kqueue`.
|
2
4
|
# @see http://www.freebsd.org/cgi/man.cgi?query=kqueue
|
3
5
|
# @see https://github.com/mat813/rb-kqueue/blob/master/lib/rb-kqueue/queue.rb
|
@@ -94,7 +96,7 @@ module Listen
|
|
94
96
|
def _watch_file(path, queue)
|
95
97
|
queue.watch_file(path, *options.events, &@callback)
|
96
98
|
rescue Errno::ENOENT => e
|
97
|
-
|
99
|
+
Listen.logger.warn "kqueue: watch file failed: #{e.message}"
|
98
100
|
end
|
99
101
|
|
100
102
|
# Quick rubocop workaround
|
@@ -1,12 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'listen/thread'
|
3
4
|
|
4
5
|
module Listen
|
5
6
|
module Adapter
|
6
7
|
# Adapter implementation for Mac OS X `FSEvents`.
|
7
8
|
#
|
8
9
|
class Darwin < Base
|
9
|
-
OS_REGEXP = /darwin(?<major_version>1\d+)/i
|
10
|
+
OS_REGEXP = /darwin(?<major_version>(1|2)\d+)/i
|
10
11
|
|
11
12
|
# The default delay between checking for changes.
|
12
13
|
DEFAULTS = { latency: 0.1 }.freeze
|
@@ -22,11 +23,11 @@ module Listen
|
|
22
23
|
EOS
|
23
24
|
|
24
25
|
def self.usable?
|
25
|
-
require 'rb-fsevent'
|
26
26
|
version = RbConfig::CONFIG['target_os'][OS_REGEXP, :major_version]
|
27
27
|
return false unless version
|
28
28
|
return true if version.to_i >= 13 # darwin13 is OS X 10.9
|
29
29
|
|
30
|
+
require 'rb-fsevent'
|
30
31
|
fsevent_version = Gem::Version.new(FSEvent::VERSION)
|
31
32
|
return true if fsevent_version <= Gem::Version.new('0.9.4')
|
32
33
|
Kernel.warn INCOMPATIBLE_GEM_VERSION
|
@@ -35,57 +36,41 @@ module Listen
|
|
35
36
|
|
36
37
|
private
|
37
38
|
|
38
|
-
# NOTE: each directory gets a DIFFERENT callback!
|
39
39
|
def _configure(dir, &callback)
|
40
|
-
|
41
|
-
|
42
|
-
@workers ||= ::Queue.new
|
43
|
-
@workers << FSEvent.new.tap do |worker|
|
44
|
-
_log :debug, "fsevent: watching: #{dir.to_s.inspect}"
|
45
|
-
worker.watch(dir.to_s, opts, &callback)
|
46
|
-
end
|
40
|
+
@callbacks[dir] = callback
|
47
41
|
end
|
48
42
|
|
49
43
|
def _run
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
44
|
+
require 'rb-fsevent'
|
45
|
+
worker = FSEvent.new
|
46
|
+
dirs_to_watch = @callbacks.keys.map(&:to_s)
|
47
|
+
Listen.logger.info { "fsevent: watching: #{dirs_to_watch.inspect}" }
|
48
|
+
worker.watch(dirs_to_watch, { latency: options.latency }, &method(:_process_changes))
|
49
|
+
@worker_thread = Listen::Thread.new("worker_thread") { worker.run }
|
56
50
|
end
|
57
51
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
new_path = Pathname.new(path.sub(%r{\/$}, ''))
|
62
|
-
_log :debug, "fsevent: #{new_path}"
|
63
|
-
# TODO: does this preserve symlinks?
|
64
|
-
rel_path = new_path.relative_path_from(dir).to_s
|
65
|
-
_queue_change(:dir, dir, rel_path, recursive: true)
|
66
|
-
end
|
67
|
-
end
|
52
|
+
def _process_changes(dirs)
|
53
|
+
dirs.each do |dir|
|
54
|
+
dir = Pathname.new(dir.sub(%r{\/$}, ''))
|
68
55
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
56
|
+
@callbacks.each do |watched_dir, callback|
|
57
|
+
if watched_dir.eql?(dir) || Listen::Directory.ascendant_of?(watched_dir, dir)
|
58
|
+
callback.call(dir)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
75
62
|
end
|
76
63
|
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
64
|
+
def _process_event(dir, path)
|
65
|
+
Listen.logger.debug { "fsevent: processing path: #{path.inspect}" }
|
66
|
+
# TODO: does this preserve symlinks?
|
67
|
+
rel_path = path.relative_path_from(dir).to_s
|
68
|
+
_queue_change(:dir, dir, rel_path, recursive: true)
|
83
69
|
end
|
84
70
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
workers
|
71
|
+
def _stop
|
72
|
+
@worker_thread&.kill
|
73
|
+
super
|
89
74
|
end
|
90
75
|
end
|
91
76
|
end
|