listen 3.2.1 → 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 +4 -4
- data/README.md +7 -6
- data/lib/listen.rb +15 -20
- 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 +10 -12
- 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 +4 -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 +24 -23
- 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 +2 -0
- 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 +2 -0
- data/lib/listen/silencer/controller.rb +2 -0
- data/lib/listen/thread.rb +47 -0
- data/lib/listen/version.rb +3 -1
- metadata +9 -25
- data/lib/listen/internals/thread_pool.rb +0 -29
data/lib/listen/listener.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'English'
|
2
4
|
|
3
5
|
require 'listen/version'
|
@@ -19,7 +21,6 @@ require 'listen/listener/config'
|
|
19
21
|
|
20
22
|
module Listen
|
21
23
|
class Listener
|
22
|
-
# TODO: move the state machine's methods private
|
23
24
|
include Listen::FSM
|
24
25
|
|
25
26
|
# Initializes the directories listener.
|
@@ -38,7 +39,7 @@ module Listen
|
|
38
39
|
@config = Config.new(options)
|
39
40
|
|
40
41
|
eq_config = Event::Queue::Config.new(@config.relative?)
|
41
|
-
queue = Event::Queue.new(eq_config)
|
42
|
+
queue = Event::Queue.new(eq_config)
|
42
43
|
|
43
44
|
silencer = Silencer.new
|
44
45
|
rules = @config.silencer_rules
|
@@ -57,41 +58,42 @@ module Listen
|
|
57
58
|
|
58
59
|
@processor = Event::Loop.new(pconfig)
|
59
60
|
|
60
|
-
|
61
|
+
initialize_fsm
|
61
62
|
end
|
62
63
|
|
63
|
-
|
64
|
+
start_state :initializing
|
64
65
|
|
65
66
|
state :initializing, to: [:backend_started, :stopped]
|
66
67
|
|
67
|
-
state :backend_started, to: [:
|
68
|
-
backend.start
|
69
|
-
end
|
70
|
-
|
71
|
-
state :frontend_ready, to: [:processing_events, :stopped] do
|
72
|
-
processor.setup
|
68
|
+
state :backend_started, to: [:processing_events, :stopped] do
|
69
|
+
@backend.start
|
73
70
|
end
|
74
71
|
|
75
72
|
state :processing_events, to: [:paused, :stopped] do
|
76
|
-
processor.
|
73
|
+
@processor.start
|
77
74
|
end
|
78
75
|
|
79
76
|
state :paused, to: [:processing_events, :stopped] do
|
80
|
-
processor.pause
|
77
|
+
@processor.pause
|
81
78
|
end
|
82
79
|
|
83
80
|
state :stopped, to: [:backend_started] do
|
84
|
-
backend.stop #
|
85
|
-
processor.
|
81
|
+
@backend.stop # halt events ASAP
|
82
|
+
@processor.stop
|
86
83
|
end
|
87
84
|
|
88
85
|
# Starts processing events and starts adapters
|
89
86
|
# or resumes invoking callbacks if paused
|
90
87
|
def start
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
88
|
+
case state
|
89
|
+
when :initializing
|
90
|
+
transition :backend_started
|
91
|
+
transition :processing_events
|
92
|
+
when :paused
|
93
|
+
transition :processing_events
|
94
|
+
else
|
95
|
+
raise ArgumentError, "cannot start from state #{state.inspect}"
|
96
|
+
end
|
95
97
|
end
|
96
98
|
|
97
99
|
# Stops both listening for events and processing them
|
@@ -113,6 +115,10 @@ module Listen
|
|
113
115
|
state == :paused
|
114
116
|
end
|
115
117
|
|
118
|
+
def stopped?
|
119
|
+
state == :stopped
|
120
|
+
end
|
121
|
+
|
116
122
|
def ignore(regexps)
|
117
123
|
@silencer_controller.append_ignores(regexps)
|
118
124
|
end
|
@@ -124,10 +130,5 @@ module Listen
|
|
124
130
|
def only(regexps)
|
125
131
|
@silencer_controller.replace_with_only(regexps)
|
126
132
|
end
|
127
|
-
|
128
|
-
private
|
129
|
-
|
130
|
-
attr_reader :processor
|
131
|
-
attr_reader :backend
|
132
133
|
end
|
133
134
|
end
|
data/lib/listen/logger.rb
CHANGED
@@ -1,32 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Listen
|
2
|
-
|
3
|
-
@logger ||= nil
|
4
|
-
end
|
4
|
+
@logger = nil
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
# Listen.logger will always be present.
|
7
|
+
# If you don't want logging, set Listen.logger = ::Logger.new('/dev/null', level: ::Logger::UNKNOWN)
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_writer :logger
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
debugging = ENV['LISTEN_GEM_DEBUGGING']
|
13
|
-
logger.level =
|
14
|
-
case debugging.to_s
|
15
|
-
when /2/
|
16
|
-
::Logger::DEBUG
|
17
|
-
when /true|yes|1/i
|
18
|
-
::Logger::INFO
|
19
|
-
else
|
20
|
-
::Logger::ERROR
|
21
|
-
end
|
12
|
+
def logger
|
13
|
+
@logger ||= default_logger
|
22
14
|
end
|
23
|
-
end
|
24
15
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
16
|
+
private
|
17
|
+
|
18
|
+
def default_logger
|
19
|
+
level = case ENV['LISTEN_GEM_DEBUGGING'].to_s
|
20
|
+
when /debug|2/i
|
21
|
+
::Logger::DEBUG
|
22
|
+
when /info|true|yes|1/i
|
23
|
+
::Logger::INFO
|
24
|
+
when /warn/i
|
25
|
+
::Logger::WARN
|
26
|
+
when /fatal/i
|
27
|
+
::Logger::FATAL
|
28
|
+
else
|
29
|
+
::Logger::ERROR
|
30
|
+
end
|
31
|
+
|
32
|
+
::Logger.new(STDERR, level: level)
|
30
33
|
end
|
31
34
|
end
|
32
35
|
end
|
data/lib/listen/options.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Listen
|
2
4
|
class Options
|
3
5
|
def initialize(opts, defaults)
|
@@ -10,7 +12,7 @@ module Listen
|
|
10
12
|
return if given_options.empty?
|
11
13
|
|
12
14
|
msg = "Unknown options: #{given_options.inspect}"
|
13
|
-
Listen
|
15
|
+
Listen.logger.warn msg
|
14
16
|
fail msg
|
15
17
|
end
|
16
18
|
|
data/lib/listen/record.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'thread'
|
2
4
|
require 'listen/record/entry'
|
3
5
|
require 'listen/record/symlink_detector'
|
@@ -45,8 +47,7 @@ module Listen
|
|
45
47
|
if [nil, '', '.'].include? rel_path.to_s
|
46
48
|
tree
|
47
49
|
else
|
48
|
-
|
49
|
-
tree[rel_path.to_s]
|
50
|
+
_sub_tree(rel_path)
|
50
51
|
end
|
51
52
|
|
52
53
|
result = {}
|
@@ -57,6 +58,19 @@ module Listen
|
|
57
58
|
result
|
58
59
|
end
|
59
60
|
|
61
|
+
def _sub_tree(rel_path)
|
62
|
+
tree.each_with_object({}) do |(path, meta), result|
|
63
|
+
next unless path.start_with?(rel_path)
|
64
|
+
|
65
|
+
if path == rel_path
|
66
|
+
result.merge!(meta)
|
67
|
+
else
|
68
|
+
sub_path = path.sub(%r{\A#{rel_path}/?}, '')
|
69
|
+
result[sub_path] = meta
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
60
74
|
def build
|
61
75
|
@tree = _auto_hash
|
62
76
|
# TODO: test with a file name given
|
data/lib/listen/record/entry.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Listen
|
2
4
|
# @private api
|
3
5
|
class Record
|
@@ -22,7 +24,7 @@ module Listen
|
|
22
24
|
|
23
25
|
def meta
|
24
26
|
lstat = ::File.lstat(sys_path)
|
25
|
-
{ mtime: lstat.mtime.to_f, mode: lstat.mode }
|
27
|
+
{ mtime: lstat.mtime.to_f, mode: lstat.mode, size: lstat.size }
|
26
28
|
end
|
27
29
|
|
28
30
|
# record hash is e.g.
|
data/lib/listen/silencer.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
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
|
+
def new(name)
|
13
|
+
thread_name = "listen-#{name}"
|
14
|
+
|
15
|
+
caller_stack = caller
|
16
|
+
::Thread.new do
|
17
|
+
begin
|
18
|
+
yield
|
19
|
+
rescue Exception => ex
|
20
|
+
_log_exception(ex, thread_name, caller_stack)
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end.tap do |thread|
|
24
|
+
thread.name = thread_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def _log_exception(ex, thread_name, caller_stack)
|
31
|
+
complete_backtrace = [*ex.backtrace, "--- Thread.new ---", *caller_stack]
|
32
|
+
message = "Exception rescued in #{thread_name}:\n#{_exception_with_causes(ex)}\n#{complete_backtrace * "\n"}"
|
33
|
+
Listen.logger.error(message)
|
34
|
+
end
|
35
|
+
|
36
|
+
def _exception_with_causes(ex)
|
37
|
+
result = +"#{ex.class}: #{ex}"
|
38
|
+
if ex.cause
|
39
|
+
result << "\n"
|
40
|
+
result << "--- Caused by: ---\n"
|
41
|
+
result << _exception_with_causes(ex.cause)
|
42
|
+
end
|
43
|
+
result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/listen/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: listen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2
|
4
|
+
version: 3.3.0.pre.2
|
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: 2020-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rb-fsevent
|
@@ -50,22 +50,8 @@ dependencies:
|
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: 0.9.10
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: bundler
|
55
|
-
requirement: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - ">="
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: '0'
|
60
|
-
type: :development
|
61
|
-
prerelease: false
|
62
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
requirements:
|
64
|
-
- - ">="
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: '0'
|
67
53
|
description: The Listen gem listens to file modifications and notifies you about the
|
68
|
-
|
54
|
+
changegem. Works everywhere!
|
69
55
|
email: thibaud@thibaud.gg
|
70
56
|
executables:
|
71
57
|
- listen
|
@@ -96,7 +82,6 @@ files:
|
|
96
82
|
- lib/listen/event/queue.rb
|
97
83
|
- lib/listen/file.rb
|
98
84
|
- lib/listen/fsm.rb
|
99
|
-
- lib/listen/internals/thread_pool.rb
|
100
85
|
- lib/listen/listener.rb
|
101
86
|
- lib/listen/listener/config.rb
|
102
87
|
- lib/listen/logger.rb
|
@@ -107,30 +92,29 @@ files:
|
|
107
92
|
- lib/listen/record/symlink_detector.rb
|
108
93
|
- lib/listen/silencer.rb
|
109
94
|
- lib/listen/silencer/controller.rb
|
95
|
+
- lib/listen/thread.rb
|
110
96
|
- lib/listen/version.rb
|
111
97
|
homepage: https://github.com/guard/listen
|
112
98
|
licenses:
|
113
99
|
- MIT
|
114
|
-
metadata:
|
100
|
+
metadata:
|
101
|
+
allowed_push_host: https://rubygems.org
|
115
102
|
post_install_message:
|
116
103
|
rdoc_options: []
|
117
104
|
require_paths:
|
118
105
|
- lib
|
119
106
|
required_ruby_version: !ruby/object:Gem::Requirement
|
120
107
|
requirements:
|
121
|
-
- - "~>"
|
122
|
-
- !ruby/object:Gem::Version
|
123
|
-
version: '2.2'
|
124
108
|
- - ">="
|
125
109
|
- !ruby/object:Gem::Version
|
126
110
|
version: 2.2.7
|
127
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
112
|
requirements:
|
129
|
-
- - "
|
113
|
+
- - ">"
|
130
114
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
115
|
+
version: 1.3.1
|
132
116
|
requirements: []
|
133
|
-
rubygems_version: 3.0.
|
117
|
+
rubygems_version: 3.0.1
|
134
118
|
signing_key:
|
135
119
|
specification_version: 4
|
136
120
|
summary: Listen to file modifications
|
@@ -1,29 +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
|
-
# You can't kill a read on a descriptor in JRuby, so let's just
|
17
|
-
# ignore running threads (listen rb-inotify waiting for disk activity
|
18
|
-
# before closing) pray threads die faster than they are created...
|
19
|
-
limit = RUBY_ENGINE == 'jruby' ? [1] : []
|
20
|
-
|
21
|
-
killed << @threads.pop.kill until @threads.empty?
|
22
|
-
until killed.empty?
|
23
|
-
th = killed.pop
|
24
|
-
th.join(*limit) unless th[:listen_blocking_read_thread]
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|