listen 3.0.2 → 3.8.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.
- checksums.yaml +5 -5
- data/CONTRIBUTING.md +10 -3
- data/README.md +263 -106
- data/bin/listen +3 -4
- data/lib/listen/adapter/base.rb +31 -32
- data/lib/listen/adapter/bsd.rb +9 -8
- data/lib/listen/adapter/config.rb +12 -4
- data/lib/listen/adapter/darwin.rb +53 -29
- data/lib/listen/adapter/linux.rb +21 -15
- data/lib/listen/adapter/polling.rb +9 -6
- data/lib/listen/adapter/windows.rb +19 -22
- data/lib/listen/adapter.rb +25 -25
- data/lib/listen/backend.rb +9 -10
- data/lib/listen/change.rb +18 -27
- data/lib/listen/cli.rb +8 -8
- data/lib/listen/directory.rb +33 -20
- data/lib/listen/error.rb +11 -0
- data/lib/listen/event/config.rb +9 -28
- data/lib/listen/event/loop.rb +47 -68
- data/lib/listen/event/processor.rb +41 -37
- data/lib/listen/event/queue.rb +19 -19
- data/lib/listen/file.rb +23 -8
- data/lib/listen/fsm.rb +74 -72
- data/lib/listen/listener/config.rb +5 -9
- data/lib/listen/listener.rb +27 -23
- data/lib/listen/logger.rb +24 -20
- data/lib/listen/monotonic_time.rb +27 -0
- data/lib/listen/options.rb +11 -8
- data/lib/listen/queue_optimizer.rb +15 -18
- data/lib/listen/record/entry.rb +18 -3
- data/lib/listen/record/symlink_detector.rb +10 -8
- data/lib/listen/record.rb +42 -38
- data/lib/listen/silencer/controller.rb +2 -0
- data/lib/listen/silencer.rb +30 -21
- data/lib/listen/thread.rb +54 -0
- data/lib/listen/version.rb +3 -1
- data/lib/listen.rb +14 -22
- metadata +28 -24
- data/lib/listen/internals/thread_pool.rb +0 -21
@@ -1,23 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'set'
|
4
|
+
require 'listen/error'
|
2
5
|
|
3
6
|
module Listen
|
4
7
|
# @private api
|
5
8
|
class Record
|
6
9
|
class SymlinkDetector
|
7
|
-
|
10
|
+
README_URL = 'https://github.com/guard/listen/blob/master/README.md'
|
8
11
|
|
9
12
|
SYMLINK_LOOP_ERROR = <<-EOS
|
10
13
|
** ERROR: directory is already being watched! **
|
11
14
|
|
12
15
|
Directory: %s
|
13
16
|
|
14
|
-
is already
|
17
|
+
is already being watched through: %s
|
15
18
|
|
16
|
-
MORE INFO: #{
|
19
|
+
MORE INFO: #{README_URL}
|
17
20
|
EOS
|
18
21
|
|
19
|
-
|
20
|
-
end
|
22
|
+
Error = ::Listen::Error # for backward compatibility
|
21
23
|
|
22
24
|
def initialize
|
23
25
|
@real_dirs = Set.new
|
@@ -25,14 +27,14 @@ module Listen
|
|
25
27
|
|
26
28
|
def verify_unwatched!(entry)
|
27
29
|
real_path = entry.real_path
|
28
|
-
@real_dirs.add?(real_path)
|
30
|
+
@real_dirs.add?(real_path) or _fail(entry.sys_path, real_path)
|
29
31
|
end
|
30
32
|
|
31
33
|
private
|
32
34
|
|
33
35
|
def _fail(symlinked, real_path)
|
34
|
-
|
35
|
-
|
36
|
+
warn(format(SYMLINK_LOOP_ERROR, symlinked, real_path))
|
37
|
+
raise ::Listen::Error::SymlinkLoop, 'Failed due to looped symlinks'
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
data/lib/listen/record.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thread'
|
1
4
|
require 'listen/record/entry'
|
2
5
|
require 'listen/record/symlink_detector'
|
3
6
|
|
@@ -7,14 +10,17 @@ module Listen
|
|
7
10
|
# TODO: deprecate
|
8
11
|
|
9
12
|
attr_reader :root
|
10
|
-
|
11
|
-
|
13
|
+
|
14
|
+
def initialize(directory, silencer)
|
15
|
+
reset_tree
|
12
16
|
@root = directory.to_s
|
17
|
+
@silencer = silencer
|
13
18
|
end
|
14
19
|
|
15
20
|
def add_dir(rel_path)
|
16
|
-
|
17
|
-
|
21
|
+
if !empty_dirname?(rel_path.to_s)
|
22
|
+
@tree[rel_path.to_s]
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
26
|
def update_file(rel_path, data)
|
@@ -29,77 +35,75 @@ module Listen
|
|
29
35
|
|
30
36
|
def file_data(rel_path)
|
31
37
|
dirname, basename = Pathname(rel_path).split.map(&:to_s)
|
32
|
-
if
|
33
|
-
tree[basename]
|
34
|
-
tree[basename].dup
|
38
|
+
if empty_dirname?(dirname)
|
39
|
+
@tree[basename].dup
|
35
40
|
else
|
36
|
-
tree[dirname] ||= {}
|
37
|
-
tree[dirname][basename]
|
38
|
-
tree[dirname][basename].dup
|
41
|
+
@tree[dirname][basename] ||= {}
|
42
|
+
@tree[dirname][basename].dup
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
42
46
|
def dir_entries(rel_path)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
47
|
+
rel_path_s = rel_path.to_s
|
48
|
+
subtree = if empty_dirname?(rel_path_s)
|
49
|
+
@tree
|
50
|
+
else
|
51
|
+
@tree[rel_path_s]
|
52
|
+
end
|
50
53
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
54
|
+
subtree.each_with_object({}) do |(key, values), result|
|
55
|
+
# only return data for file entries inside the dir (which will each be sub-hashes)
|
56
|
+
if values.is_a?(Hash)
|
57
|
+
result[key] = values.has_key?(:mtime) ? values : {}
|
58
|
+
end
|
55
59
|
end
|
56
|
-
result
|
57
60
|
end
|
58
61
|
|
59
62
|
def build
|
60
|
-
|
63
|
+
reset_tree
|
61
64
|
# TODO: test with a file name given
|
62
65
|
# TODO: test other permissions
|
63
66
|
# TODO: test with mixed encoding
|
64
67
|
symlink_detector = SymlinkDetector.new
|
65
|
-
remaining = Queue.new
|
68
|
+
remaining = ::Queue.new
|
66
69
|
remaining << Entry.new(root, nil, nil)
|
67
70
|
_fast_build_dir(remaining, symlink_detector) until remaining.empty?
|
68
71
|
end
|
69
72
|
|
70
73
|
private
|
71
74
|
|
72
|
-
def
|
73
|
-
|
75
|
+
def empty_dirname?(dirname)
|
76
|
+
dirname == '.' || dirname == ''
|
74
77
|
end
|
75
78
|
|
76
|
-
def
|
77
|
-
@tree
|
79
|
+
def reset_tree
|
80
|
+
@tree = Hash.new { |h, k| h[k] = {} }
|
78
81
|
end
|
79
82
|
|
80
83
|
def _fast_update_file(dirname, basename, data)
|
81
|
-
if
|
82
|
-
tree[basename] =
|
84
|
+
if empty_dirname?(dirname.to_s)
|
85
|
+
@tree[basename] = @tree[basename].merge(data)
|
83
86
|
else
|
84
|
-
tree[dirname]
|
85
|
-
tree[dirname][basename] = (tree[dirname][basename] || {}).merge(data)
|
87
|
+
@tree[dirname][basename] = (@tree[dirname][basename] || {}).merge(data)
|
86
88
|
end
|
87
89
|
end
|
88
90
|
|
89
91
|
def _fast_unset_path(dirname, basename)
|
90
92
|
# this may need to be reworked to properly remove
|
91
93
|
# entries from a tree, without adding non-existing dirs to the record
|
92
|
-
if
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
tree[dirname].delete(basename)
|
94
|
+
if empty_dirname?(dirname.to_s)
|
95
|
+
if @tree.key?(basename)
|
96
|
+
@tree.delete(basename)
|
97
|
+
end
|
98
|
+
elsif @tree.key?(dirname)
|
99
|
+
@tree[dirname].delete(basename)
|
98
100
|
end
|
99
101
|
end
|
100
102
|
|
101
103
|
def _fast_build_dir(remaining, symlink_detector)
|
102
104
|
entry = remaining.pop
|
105
|
+
return if @silencer.silenced?(entry.record_dir_key, :dir)
|
106
|
+
|
103
107
|
children = entry.children # NOTE: children() implicitly tests if dir
|
104
108
|
symlink_detector.verify_unwatched!(entry)
|
105
109
|
children.each { |child| remaining << child }
|
data/lib/listen/silencer.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Listen
|
2
4
|
class Silencer
|
3
5
|
# The default list of directories that get ignored.
|
4
|
-
|
5
|
-
|
6
|
+
DEFAULT_IGNORED_FILES = %r{\A(?:
|
7
|
+
\.git
|
6
8
|
| \.svn
|
7
9
|
| \.hg
|
8
10
|
| \.rbx
|
@@ -11,11 +13,15 @@ module Listen
|
|
11
13
|
| vendor/bundle
|
12
14
|
| log
|
13
15
|
| tmp
|
14
|
-
|vendor/ruby
|
15
|
-
|
16
|
+
| vendor/ruby
|
17
|
+
|
18
|
+
# emacs temp files
|
19
|
+
| \#.+\#
|
20
|
+
| \.\#.+
|
21
|
+
)(/|\z)}x.freeze
|
16
22
|
|
17
23
|
# The default list of files that get ignored.
|
18
|
-
DEFAULT_IGNORED_EXTENSIONS
|
24
|
+
DEFAULT_IGNORED_EXTENSIONS = %r{(?:
|
19
25
|
# Kate's tmp\/swp files
|
20
26
|
\..*\d+\.new
|
21
27
|
| \.kate-swp
|
@@ -33,7 +39,7 @@ module Listen
|
|
33
39
|
| ^4913
|
34
40
|
|
35
41
|
# Sed temporary files - but without actual words, like 'sedatives'
|
36
|
-
| (
|
42
|
+
| (?:\A
|
37
43
|
sed
|
38
44
|
|
39
45
|
(?:
|
@@ -46,45 +52,48 @@ module Listen
|
|
46
52
|
)
|
47
53
|
)
|
48
54
|
|
55
|
+
# Mutagen sync temporary files
|
56
|
+
| \.mutagen-temporary.*
|
57
|
+
|
49
58
|
# other files
|
50
59
|
| \.DS_Store
|
51
60
|
| \.tmp
|
52
61
|
| ~
|
53
|
-
)
|
62
|
+
)\z}x.freeze
|
54
63
|
|
64
|
+
# TODO: deprecate these mutators; use attr_reader instead
|
55
65
|
attr_accessor :only_patterns, :ignore_patterns
|
56
66
|
|
57
|
-
def initialize
|
58
|
-
configure(
|
67
|
+
def initialize(**options)
|
68
|
+
configure(options)
|
59
69
|
end
|
60
70
|
|
71
|
+
# TODO: deprecate this mutator
|
61
72
|
def configure(options)
|
62
73
|
@only_patterns = options[:only] ? Array(options[:only]) : nil
|
63
74
|
@ignore_patterns = _init_ignores(options[:ignore], options[:ignore!])
|
64
75
|
end
|
65
76
|
|
66
|
-
# Note: relative_path is temporarily expected to be a relative Pathname to
|
67
|
-
# make refactoring easier (ideally, it would take a string)
|
68
|
-
|
69
|
-
# TODO: switch type and path places - and verify
|
70
77
|
def silenced?(relative_path, type)
|
71
|
-
path = relative_path.to_s
|
72
|
-
|
73
|
-
if only_patterns && type == :file
|
74
|
-
return true unless only_patterns.any? { |pattern| path =~ pattern }
|
75
|
-
end
|
78
|
+
path = relative_path.to_s # in case it is a Pathname
|
76
79
|
|
77
|
-
|
80
|
+
_ignore?(path) || (only_patterns && type == :file && !_only?(path))
|
78
81
|
end
|
79
82
|
|
80
83
|
private
|
81
84
|
|
82
|
-
|
85
|
+
def _ignore?(path)
|
86
|
+
ignore_patterns.any? { |pattern| path =~ pattern }
|
87
|
+
end
|
88
|
+
|
89
|
+
def _only?(path)
|
90
|
+
only_patterns.any? { |pattern| path =~ pattern }
|
91
|
+
end
|
83
92
|
|
84
93
|
def _init_ignores(ignores, overrides)
|
85
94
|
patterns = []
|
86
95
|
unless overrides
|
87
|
-
patterns <<
|
96
|
+
patterns << DEFAULT_IGNORED_FILES
|
88
97
|
patterns << DEFAULT_IGNORED_EXTENSIONS
|
89
98
|
end
|
90
99
|
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thread'
|
4
|
+
|
5
|
+
require_relative 'logger'
|
6
|
+
|
7
|
+
module Listen
|
8
|
+
module Thread
|
9
|
+
class << self
|
10
|
+
# Creates a new thread with the given name.
|
11
|
+
# Any exceptions raised by the thread will be logged with the thread name and complete backtrace.
|
12
|
+
# rubocop:disable Style/MultilineBlockChain
|
13
|
+
def new(name, &block)
|
14
|
+
thread_name = "listen-#{name}"
|
15
|
+
caller_stack = caller
|
16
|
+
|
17
|
+
::Thread.new do
|
18
|
+
rescue_and_log(thread_name, caller_stack: caller_stack, &block)
|
19
|
+
end.tap do |thread|
|
20
|
+
thread.name = thread_name
|
21
|
+
end
|
22
|
+
end
|
23
|
+
# rubocop:enable Style/MultilineBlockChain
|
24
|
+
|
25
|
+
def rescue_and_log(method_name, *args, caller_stack: nil)
|
26
|
+
yield(*args)
|
27
|
+
rescue => exception
|
28
|
+
_log_exception(exception, method_name, caller_stack: caller_stack)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def _log_exception(exception, thread_name, caller_stack: nil)
|
34
|
+
complete_backtrace = if caller_stack
|
35
|
+
[*exception.backtrace, "--- Thread.new ---", *caller_stack]
|
36
|
+
else
|
37
|
+
exception.backtrace
|
38
|
+
end
|
39
|
+
message = "Exception rescued in #{thread_name}:\n#{_exception_with_causes(exception)}\n#{complete_backtrace * "\n"}"
|
40
|
+
Listen.logger.error(message)
|
41
|
+
end
|
42
|
+
|
43
|
+
def _exception_with_causes(exception)
|
44
|
+
result = +"#{exception.class}: #{exception}"
|
45
|
+
if exception.cause
|
46
|
+
result << "\n"
|
47
|
+
result << "--- Caused by: ---\n"
|
48
|
+
result << _exception_with_causes(exception.cause)
|
49
|
+
end
|
50
|
+
result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/listen/version.rb
CHANGED
data/lib/listen.rb
CHANGED
@@ -1,23 +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
|
-
# Always set up logging by default first time file is required
|
8
|
-
#
|
9
|
-
# NOTE: If you need to clear the logger completely, do so *after*
|
10
|
-
# requiring this file. If you need to set a custom logger,
|
11
|
-
# require the listen/logger file and set the logger before requiring
|
12
|
-
# this file.
|
13
|
-
Listen.setup_default_logger_if_unset
|
14
|
-
|
15
8
|
# Won't print anything by default because of level - unless you've set
|
16
9
|
# LISTEN_GEM_DEBUGGING or provided your own logger with a high enough level
|
17
|
-
Listen
|
18
|
-
Listen
|
10
|
+
Listen.logger.info "Listen loglevel set to: #{Listen.logger.level}"
|
11
|
+
Listen.logger.info "Listen version: #{Listen::VERSION}"
|
19
12
|
|
20
13
|
module Listen
|
14
|
+
@listeners = Queue.new
|
15
|
+
|
21
16
|
class << self
|
22
17
|
# Listens to file system modifications on a either single directory or
|
23
18
|
# multiple directories.
|
@@ -32,24 +27,21 @@ module Listen
|
|
32
27
|
# @return [Listen::Listener] the listener
|
33
28
|
#
|
34
29
|
def to(*args, &block)
|
35
|
-
@listeners ||= []
|
36
30
|
Listener.new(*args, &block).tap do |listener|
|
37
|
-
@listeners
|
31
|
+
@listeners.enq(WeakRef.new(listener))
|
38
32
|
end
|
39
33
|
end
|
40
34
|
|
41
35
|
# This is used by the `listen` binary to handle Ctrl-C
|
42
36
|
#
|
43
37
|
def stop
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# call stop to halt the main loop
|
50
|
-
listener.stop
|
38
|
+
while (listener = @listeners.deq(true))
|
39
|
+
begin
|
40
|
+
listener.stop
|
41
|
+
rescue WeakRef::RefError
|
42
|
+
end
|
51
43
|
end
|
52
|
-
|
44
|
+
rescue ThreadError
|
53
45
|
end
|
54
46
|
end
|
55
47
|
end
|
metadata
CHANGED
@@ -1,57 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: listen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thibaud Guillaume-Gentil
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rb-fsevent
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.10'
|
17
20
|
- - ">="
|
18
21
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
22
|
+
version: 0.10.3
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.10'
|
24
30
|
- - ">="
|
25
31
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
32
|
+
version: 0.10.3
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: rb-inotify
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
|
-
- - "
|
37
|
+
- - "~>"
|
32
38
|
- !ruby/object:Gem::Version
|
33
39
|
version: '0.9'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.9.10
|
34
43
|
type: :runtime
|
35
44
|
prerelease: false
|
36
45
|
version_requirements: !ruby/object:Gem::Requirement
|
37
46
|
requirements:
|
38
|
-
- - "
|
47
|
+
- - "~>"
|
39
48
|
- !ruby/object:Gem::Version
|
40
49
|
version: '0.9'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: bundler
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 1.3.5
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
50
|
- - ">="
|
53
51
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
52
|
+
version: 0.9.10
|
55
53
|
description: The Listen gem listens to file modifications and notifies you about the
|
56
54
|
changes. Works everywhere!
|
57
55
|
email: thibaud@thibaud.gg
|
@@ -78,16 +76,17 @@ files:
|
|
78
76
|
- lib/listen/change.rb
|
79
77
|
- lib/listen/cli.rb
|
80
78
|
- lib/listen/directory.rb
|
79
|
+
- lib/listen/error.rb
|
81
80
|
- lib/listen/event/config.rb
|
82
81
|
- lib/listen/event/loop.rb
|
83
82
|
- lib/listen/event/processor.rb
|
84
83
|
- lib/listen/event/queue.rb
|
85
84
|
- lib/listen/file.rb
|
86
85
|
- lib/listen/fsm.rb
|
87
|
-
- lib/listen/internals/thread_pool.rb
|
88
86
|
- lib/listen/listener.rb
|
89
87
|
- lib/listen/listener/config.rb
|
90
88
|
- lib/listen/logger.rb
|
89
|
+
- lib/listen/monotonic_time.rb
|
91
90
|
- lib/listen/options.rb
|
92
91
|
- lib/listen/queue_optimizer.rb
|
93
92
|
- lib/listen/record.rb
|
@@ -95,11 +94,18 @@ files:
|
|
95
94
|
- lib/listen/record/symlink_detector.rb
|
96
95
|
- lib/listen/silencer.rb
|
97
96
|
- lib/listen/silencer/controller.rb
|
97
|
+
- lib/listen/thread.rb
|
98
98
|
- lib/listen/version.rb
|
99
99
|
homepage: https://github.com/guard/listen
|
100
100
|
licenses:
|
101
101
|
- MIT
|
102
|
-
metadata:
|
102
|
+
metadata:
|
103
|
+
allowed_push_host: https://rubygems.org
|
104
|
+
bug_tracker_uri: https://github.com/guard/listen/issues
|
105
|
+
changelog_uri: https://github.com/guard/listen/releases
|
106
|
+
documentation_uri: https://www.rubydoc.info/gems/listen/3.8.0
|
107
|
+
homepage_uri: https://github.com/guard/listen
|
108
|
+
source_code_uri: https://github.com/guard/listen/tree/v3.8.0
|
103
109
|
post_install_message:
|
104
110
|
rdoc_options: []
|
105
111
|
require_paths:
|
@@ -108,17 +114,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
114
|
requirements:
|
109
115
|
- - ">="
|
110
116
|
- !ruby/object:Gem::Version
|
111
|
-
version:
|
117
|
+
version: 2.4.0
|
112
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
119
|
requirements:
|
114
120
|
- - ">="
|
115
121
|
- !ruby/object:Gem::Version
|
116
122
|
version: '0'
|
117
123
|
requirements: []
|
118
|
-
|
119
|
-
rubygems_version: 2.4.5
|
124
|
+
rubygems_version: 3.0.1
|
120
125
|
signing_key:
|
121
126
|
specification_version: 4
|
122
127
|
summary: Listen to file modifications
|
123
128
|
test_files: []
|
124
|
-
has_rdoc:
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Listen
|
2
|
-
# @private api
|
3
|
-
module Internals
|
4
|
-
module ThreadPool
|
5
|
-
def self.add(&block)
|
6
|
-
Thread.new { block.call }.tap do |th|
|
7
|
-
(@threads ||= Queue.new) << th
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.stop
|
12
|
-
return unless @threads ||= nil
|
13
|
-
return if @threads.empty? # return to avoid using possibly stubbed Queue
|
14
|
-
|
15
|
-
killed = Queue.new
|
16
|
-
killed << @threads.pop.kill until @threads.empty?
|
17
|
-
killed.pop.join until killed.empty?
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|