listen 2.7.11 → 2.7.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound.yml +3 -0
- data/.rubocop.yml +20 -232
- data/.rubocop_todo.yml +33 -0
- data/CONTRIBUTING.md +5 -5
- data/Gemfile +1 -0
- data/Guardfile +12 -9
- data/README.md +15 -29
- data/Rakefile +8 -1
- data/TROUBLESHOOTING.md +139 -0
- data/lib/listen.rb +6 -5
- data/lib/listen/adapter.rb +2 -1
- data/lib/listen/adapter/base.rb +7 -3
- data/lib/listen/adapter/darwin.rb +16 -1
- data/lib/listen/adapter/tcp.rb +8 -5
- data/lib/listen/adapter/windows.rb +6 -6
- data/lib/listen/change.rb +3 -2
- data/lib/listen/cli.rb +1 -3
- data/lib/listen/directory.rb +7 -11
- data/lib/listen/file.rb +35 -41
- data/lib/listen/internals/logging.rb +31 -0
- data/lib/listen/internals/thread_pool.rb +19 -0
- data/lib/listen/listener.rb +14 -14
- data/lib/listen/record.rb +2 -2
- data/lib/listen/silencer.rb +3 -3
- data/lib/listen/tcp/broadcaster.rb +8 -5
- data/lib/listen/version.rb +1 -1
- data/listen.gemspec +2 -2
- data/spec/acceptance/listen_spec.rb +1 -2
- data/spec/acceptance/tcp_spec.rb +4 -1
- data/spec/lib/listen/adapter/darwin_spec.rb +108 -0
- data/spec/lib/listen/adapter/polling_spec.rb +1 -0
- data/spec/lib/listen/file_spec.rb +20 -20
- data/spec/lib/listen/listener_spec.rb +1 -1
- data/spec/lib/listen/record_spec.rb +1 -1
- data/spec/lib/listen/silencer_spec.rb +4 -4
- data/spec/spec_helper.rb +4 -0
- data/spec/support/acceptance_helper.rb +2 -4
- data/vendor/hound/config/style_guides/ruby.yml +259 -0
- metadata +8 -2
data/Rakefile
CHANGED
@@ -2,4 +2,11 @@ require 'bundler/gem_tasks'
|
|
2
2
|
require 'rspec/core/rake_task'
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
|
-
|
5
|
+
|
6
|
+
if ENV["CI"] != "true"
|
7
|
+
require "rubocop/rake_task"
|
8
|
+
RuboCop::RakeTask.new(:rubocop)
|
9
|
+
task default: [:spec, :rubocop]
|
10
|
+
else
|
11
|
+
task default: [:spec]
|
12
|
+
end
|
data/TROUBLESHOOTING.md
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
# Issues and troubleshooting
|
2
|
+
|
3
|
+
## 3 steps before you start diagnosing problems
|
4
|
+
|
5
|
+
These 3 steps will:
|
6
|
+
* help quickly troubleshoot issues caused by obscure problems
|
7
|
+
* help quickly identify the area of the problem (a full list is [below](#known-issues))
|
8
|
+
* help you get familiar with listen's diagnostic mode
|
9
|
+
* help you create relevant output before you submit an issue
|
10
|
+
|
11
|
+
1) For effective troubleshooting set the `LISTEN_GEM_DEBUGGING=1` variable
|
12
|
+
before starting listen.
|
13
|
+
|
14
|
+
2) Verify polling works (see `force_polling` option).
|
15
|
+
|
16
|
+
After starting listen, you should see something like:
|
17
|
+
```
|
18
|
+
INFO -- : Celluloid loglevel set to: 1
|
19
|
+
INFO -- : Record.build(): 0.06773114204406738 seconds
|
20
|
+
```
|
21
|
+
|
22
|
+
(Listen uses [Celluloid](https://github.com/celluloid/celluloid) for logging, so if you don't see anything, `Celluloid.logger` might have been disabled by a different gem, e.g. sidekiq)
|
23
|
+
|
24
|
+
If you don't see the line `Record.build()`:
|
25
|
+
* and there's a lot of disk activity, you may have to wait a few seconds
|
26
|
+
* you may be using an outdated version of Listen
|
27
|
+
* listen may have got stuck on a recursive symlink, see #259
|
28
|
+
|
29
|
+
3) Make changes e.g. `touch foo` or `echo "a" >> foo` (for troubleshooting, avoid using an editor which could generate too many misleading events)
|
30
|
+
|
31
|
+
You should see something like:
|
32
|
+
|
33
|
+
```
|
34
|
+
INFO -- : listen: raw changes: [[:added, "/home/me/foo"]]
|
35
|
+
INFO -- : listen: final changes: {:modified=>[], :added=>["/home/me/foo"], :removed=>[]}
|
36
|
+
```
|
37
|
+
|
38
|
+
"raw changes" contains changes collected during the `:wait_for_delay` and `:latency` intervals, while "final changes" is what listen decided are relevant changes (for better editor support).
|
39
|
+
|
40
|
+
## Adapter-specific diagnostics
|
41
|
+
|
42
|
+
Use the `LISTEN_GEM_DEBUGGING` set to `2` for additional info.
|
43
|
+
|
44
|
+
E.g. you'll get:
|
45
|
+
|
46
|
+
```
|
47
|
+
INFO -- : Celluloid loglevel set to: 0
|
48
|
+
DEBUG -- : Broadcaster: starting tcp server: 127.0.0.1:4000
|
49
|
+
DEBUG -- : Adapter: considering TCP ...
|
50
|
+
DEBUG -- : Adapter: considering polling ...
|
51
|
+
DEBUG -- : Adapter: considering optimized backend...
|
52
|
+
INFO -- : Record.build(): 0.0007264614105224609 seconds
|
53
|
+
DEBUG -- : inotify: foo ([:create])
|
54
|
+
DEBUG -- : raw queue: [:file, #<Pathname:/tmp/x>, "foo", {:change=>:added}]
|
55
|
+
DEBUG -- : added: file:/tmp/x/foo ({:change=>:added})
|
56
|
+
DEBUG -- : inotify: foo ([:attrib])
|
57
|
+
DEBUG -- : raw queue: [:file, #<Pathname:/tmp/x>, "foo", {:change=>:modified}]
|
58
|
+
DEBUG -- : inotify: foo ([:close_write, :close])
|
59
|
+
DEBUG -- : raw queue: [:file, #<Pathname:/tmp/x>, "foo", {:change=>:modified}]
|
60
|
+
DEBUG -- : modified: file:/tmp/x/foo ({:change=>:modified})
|
61
|
+
DEBUG -- : modified: file:/tmp/x/foo ({:change=>:modified})
|
62
|
+
INFO -- : listen: raw changes: [[:added, "/tmp/x/foo"]]
|
63
|
+
INFO -- : listen: final changes: {:modified=>[], :added=>["/tmp/x/foo"], :removed=>[]}
|
64
|
+
DEBUG -- : Callback took 4.410743713378906e-05 seconds
|
65
|
+
```
|
66
|
+
|
67
|
+
This shows:
|
68
|
+
* host port listened to (for forwarding events)
|
69
|
+
* the actual adapter used (here, it's "optimized backend")
|
70
|
+
* the event received (here it's `:create` from rb-inotify)
|
71
|
+
* "raw queue" - events queued for processing (collected during `:latency`)
|
72
|
+
* "Callback took" - how long it took your app to process changes
|
73
|
+
|
74
|
+
#### Known issues
|
75
|
+
|
76
|
+
Here are common issues grouped by area in which they occur:
|
77
|
+
|
78
|
+
1. System/OS
|
79
|
+
* [Update your Dropbox client](http://www.dropbox.com/downloading), if you have Dropbox installed.
|
80
|
+
* old MacOS (< 10.6)
|
81
|
+
* certain old versions of Ruby (try a newer Ruby on Windows for `wdm` and TCP mode to work)
|
82
|
+
* system limits
|
83
|
+
* threads for Celluloid (e.g. Virtual Machine CPU/RAM limitations)
|
84
|
+
* [inotify limits (Linux)](https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers)
|
85
|
+
* system in an inconsistent state or stuck (try rebooting/updating on Windows/Mac - seriously!)
|
86
|
+
* FSEvent bug: (http://feedback.livereload.com/knowledgebase/articles/86239)
|
87
|
+
|
88
|
+
2. Installation/gems/config
|
89
|
+
* not running listen or your app (e.g. guard) with `bundle exec` first
|
90
|
+
* old version of listen
|
91
|
+
* problems with adapter gems (`wdm`, `rb-fsevent`, `rb-inotify`) not installed, not detected properly (Windows) or not in Gemfile (Windows)
|
92
|
+
* Celluloid actors are silently crashing (when no LISTEN_GEM_DEBUGGING variable is present)
|
93
|
+
* see the [Performance](https://github.com/guard/listen/blob/master/README.md#Performance) section in the README
|
94
|
+
|
95
|
+
3. Filesystem
|
96
|
+
* VM shared folders and network folders (NFS, Samba, SSHFS) don't work with optimized backends (workaround: polling, [TCP mode](https://github.com/guard/listen/blob/master/README.md#forwarding-file-events-over-tcp), Vagrant's rsync-auto mode, rsync/unison)
|
97
|
+
* FAT/HFS timestamps have 1-second precision, which can cause polling and rb-fsevent to be very slow on large files (try `LISTEN_GEM_DISABLE_HASHING` variable)
|
98
|
+
* virtual filesystems may not implement event monitoring
|
99
|
+
* restrictive file/folder permissions
|
100
|
+
* watched folders moved/removed while listen was running (try restarting listen and moving/copying watched folder to a new location)
|
101
|
+
|
102
|
+
4. Insufficient latency (for polling and rb-fsevent)
|
103
|
+
* too many files being watched (polling) and not enough threads or CPU power
|
104
|
+
* slow editor save (see below)
|
105
|
+
* slow hard drive
|
106
|
+
* encryption
|
107
|
+
* a combination of factors
|
108
|
+
|
109
|
+
5. Too few or too many callbacks (`:wait_for_delay` option)
|
110
|
+
* complex editor file-save causes events to happen during callback (result: multiple callbacks if wait_for_delay is too small)
|
111
|
+
* too large when using TCP mode (see timestamps in output to debug)
|
112
|
+
* too many changes happening too frequently (use ignore rules to filter them out)
|
113
|
+
|
114
|
+
6. Paths
|
115
|
+
* default ignore rules
|
116
|
+
* encoding-related issues (bad filenames, mounted FS encoding mismatch)
|
117
|
+
* symlinks may cause listen to hang (#259)
|
118
|
+
* symlinks may not work as you expect or work differently for polling vs non-polling
|
119
|
+
* TCP paths don't match with client's current working directory
|
120
|
+
|
121
|
+
7. Editors
|
122
|
+
* "atomic save" in editors may confuse listen (disable it and try again)
|
123
|
+
* listen's default ignore rules may need tweaking
|
124
|
+
* your editor may not be supported yet (see default ignore rules for editors)
|
125
|
+
* use `touch foo` or `echo "a" >> foo` to confirm it's an editor issue
|
126
|
+
* slow terminal/GFX card, slow font, transparency effects in terminal
|
127
|
+
* complex/lengthy editor save (due to e.g. many plugins running during save)
|
128
|
+
* listen has complex rules for detecting atomic file saves (Linux)
|
129
|
+
|
130
|
+
8. TCP (tcp mode) issues
|
131
|
+
* not a recent listen gem (before 2.7.11)
|
132
|
+
* additional network delay and collecting may need a higher `:wait_for_delay` value
|
133
|
+
* changes (added, removed, deleted) not matching actual changes
|
134
|
+
|
135
|
+
If your application keeps using the polling-adapter and you can't figure out why, feel free to [open an issue](https://github.com/guard/listen/issues/new) (and be sure to [give all the details](https://github.com/guard/listen/blob/master/CONTRIBUTING.md)).
|
136
|
+
|
137
|
+
Listen traps SIGINT signal to properly finalize listeners. If you plan
|
138
|
+
on trapping this signal yourself - make sure to call `Listen.stop` in
|
139
|
+
signal handler.
|
data/lib/listen.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'celluloid'
|
2
2
|
require 'listen/listener'
|
3
3
|
|
4
|
+
require 'listen/internals/thread_pool'
|
5
|
+
|
4
6
|
module Listen
|
5
7
|
class << self
|
6
8
|
# Listens to file system modifications on a either single directory or
|
@@ -21,11 +23,9 @@ module Listen
|
|
21
23
|
def to(*args, &block)
|
22
24
|
Celluloid.boot unless Celluloid.running?
|
23
25
|
options = args.last.is_a?(Hash) ? args.last : {}
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
_add_listener(*args, &block)
|
28
|
-
end
|
26
|
+
target = options.delete(:forward_to)
|
27
|
+
args = ([target, :broadcaster] + args) if target
|
28
|
+
_add_listener(*args, &block)
|
29
29
|
end
|
30
30
|
|
31
31
|
# Stop all listeners & Celluloid
|
@@ -36,6 +36,7 @@ module Listen
|
|
36
36
|
# This is used by the `listen` binary to handle Ctrl-C
|
37
37
|
#
|
38
38
|
def stop
|
39
|
+
Internals::ThreadPool.stop
|
39
40
|
@listeners ||= []
|
40
41
|
|
41
42
|
# TODO: should use a mutex for this
|
data/lib/listen/adapter.rb
CHANGED
data/lib/listen/adapter/base.rb
CHANGED
@@ -28,7 +28,7 @@ module Listen
|
|
28
28
|
defaults = self.class.const_get('DEFAULTS')
|
29
29
|
@options = Listen::Options.new(options, defaults)
|
30
30
|
rescue
|
31
|
-
|
31
|
+
_log_exception 'adapter config failed: %s:%s'
|
32
32
|
raise
|
33
33
|
end
|
34
34
|
|
@@ -53,11 +53,11 @@ module Listen
|
|
53
53
|
|
54
54
|
def start
|
55
55
|
configure
|
56
|
-
|
56
|
+
Listen::Internals::ThreadPool.add do
|
57
57
|
begin
|
58
58
|
_run
|
59
59
|
rescue
|
60
|
-
|
60
|
+
_log_exception 'run() in thread failed: %s:%s'
|
61
61
|
raise
|
62
62
|
end
|
63
63
|
end
|
@@ -83,6 +83,10 @@ module Listen
|
|
83
83
|
self.class.send(:_log, *args)
|
84
84
|
end
|
85
85
|
|
86
|
+
def _log_exception(msg)
|
87
|
+
_log :error, format(msg, $ERROR_INFO, $ERROR_POSITION * "\n")
|
88
|
+
end
|
89
|
+
|
86
90
|
def self._log(*args)
|
87
91
|
Celluloid::Logger.send(*args)
|
88
92
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'listen/internals/thread_pool'
|
2
|
+
|
1
3
|
module Listen
|
2
4
|
module Adapter
|
3
5
|
# Adapter implementation for Mac OS X `FSEvents`.
|
@@ -10,6 +12,7 @@ module Listen
|
|
10
12
|
|
11
13
|
private
|
12
14
|
|
15
|
+
# NOTE: each directory gets a DIFFERENT callback!
|
13
16
|
def _configure(dir, &callback)
|
14
17
|
require 'rb-fsevent'
|
15
18
|
opts = { latency: options.latency }
|
@@ -20,8 +23,20 @@ module Listen
|
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
26
|
+
# NOTE: _run is called within a thread, so run every other
|
27
|
+
# worker in it's own thread
|
23
28
|
def _run
|
24
|
-
@workers.pop
|
29
|
+
first = @workers.pop
|
30
|
+
until @workers.empty?
|
31
|
+
Listen::Internals::ThreadPool.add do
|
32
|
+
begin
|
33
|
+
@workers.pop.run
|
34
|
+
rescue
|
35
|
+
_log_exception 'run() in extra thread(s) failed: %s: %s'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
first.run
|
25
40
|
end
|
26
41
|
|
27
42
|
def _process_event(dir, event)
|
data/lib/listen/adapter/tcp.rb
CHANGED
@@ -26,16 +26,18 @@ module Listen
|
|
26
26
|
@buffer = ''
|
27
27
|
async.run
|
28
28
|
rescue Celluloid::Task::TerminatedError
|
29
|
-
_log :debug, "TCP adapter was terminated: #{
|
29
|
+
_log :debug, "TCP adapter was terminated: #{$ERROR_INFO.inspect}"
|
30
30
|
rescue Errno::ECONNREFUSED
|
31
31
|
sleep 1
|
32
32
|
attempts -= 1
|
33
|
-
_log :warn, "TCP.start: #{
|
33
|
+
_log :warn, "TCP.start: #{$ERROR_INFO.inspect}"
|
34
34
|
retry if attempts > 0
|
35
|
-
_log :error,
|
35
|
+
_log :error, format('TCP.start: %s:%s', $ERROR_INFO.inspect,
|
36
|
+
$ERROR_POSITION * "\n")
|
36
37
|
raise
|
37
38
|
rescue
|
38
|
-
_log :error,
|
39
|
+
_log :error, format('TCP.start: %s:%s', $ERROR_INFO.inspect,
|
40
|
+
$ERROR_POSITION * "\n")
|
39
41
|
raise
|
40
42
|
end
|
41
43
|
|
@@ -65,7 +67,8 @@ module Listen
|
|
65
67
|
handle_message(message)
|
66
68
|
end
|
67
69
|
rescue
|
68
|
-
_log :error,
|
70
|
+
_log :error, format('TCP.handle_data crashed: %s:%s', $ERROR_INFO,
|
71
|
+
$ERROR_POSITION * "\n")
|
69
72
|
raise
|
70
73
|
end
|
71
74
|
|
@@ -7,10 +7,7 @@ module Listen
|
|
7
7
|
|
8
8
|
BUNDLER_DECLARE_GEM = <<-EOS.gsub(/^ {6}/, '')
|
9
9
|
Please add the following to your Gemfile to avoid polling for changes:
|
10
|
-
|
11
|
-
if RbConfig::CONFIG['target_os'] =~ /mswin|mingw|cygwin/i
|
12
|
-
gem 'wdm', '>= 0.1.0'
|
13
|
-
end
|
10
|
+
gem 'wdm', '>= 0.1.0' if Gem.win_platform?
|
14
11
|
EOS
|
15
12
|
|
16
13
|
def self.usable?
|
@@ -18,7 +15,9 @@ module Listen
|
|
18
15
|
require 'wdm'
|
19
16
|
true
|
20
17
|
rescue LoadError
|
21
|
-
_log :debug,
|
18
|
+
_log :debug, format('wdm - load failed: %s:%s', $ERROR_INFO,
|
19
|
+
$ERROR_POSITION * "\n")
|
20
|
+
|
22
21
|
Kernel.warn BUNDLER_DECLARE_GEM
|
23
22
|
false
|
24
23
|
end
|
@@ -82,7 +81,8 @@ module Listen
|
|
82
81
|
end
|
83
82
|
rescue
|
84
83
|
details = event.inspect
|
85
|
-
_log :error,
|
84
|
+
_log :error, format('wdm - callback (%): %s:%s', details, $ERROR_INFO,
|
85
|
+
$ERROR_POSITION * "\n")
|
86
86
|
raise
|
87
87
|
end
|
88
88
|
|
data/lib/listen/change.rb
CHANGED
@@ -43,9 +43,10 @@ module Listen
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
rescue Celluloid::Task::TerminatedError
|
46
|
-
_log :debug, "Change#change was terminated: #{
|
46
|
+
_log :debug, "Change#change was terminated: #{$ERROR_INFO.inspect}"
|
47
47
|
rescue RuntimeError
|
48
|
-
_log :error,
|
48
|
+
_log :error, format('Change#change crashed %s:%s', $ERROR_INFO.inspect,
|
49
|
+
$ERROR_POSITION * "\n")
|
49
50
|
raise
|
50
51
|
end
|
51
52
|
|
data/lib/listen/cli.rb
CHANGED
data/lib/listen/directory.rb
CHANGED
@@ -13,16 +13,10 @@ module Listen
|
|
13
13
|
path = dir + rel_path
|
14
14
|
current = Set.new(path.children)
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
else
|
22
|
-
_log(:debug) do
|
23
|
-
"Scanning: #{rel_path}: #{options.inspect}"\
|
24
|
-
" [#{previous.inspect}] -> (#{current.inspect})"
|
25
|
-
end
|
16
|
+
_log(:debug) do
|
17
|
+
format('%s: %s(%s): %s -> %s',
|
18
|
+
(options[:silence] ? 'Recording' : 'Scanning'),
|
19
|
+
rel_path, options.inspect, previous.inspect, current.inspect)
|
26
20
|
end
|
27
21
|
|
28
22
|
current.each do |full_path|
|
@@ -46,7 +40,9 @@ module Listen
|
|
46
40
|
_async_changes(dir, path, queue, previous, options)
|
47
41
|
_change(queue, :file, dir, rel_path, options)
|
48
42
|
rescue
|
49
|
-
_log(:warn)
|
43
|
+
_log(:warn) do
|
44
|
+
format('scan DIED: %s:%s', $ERROR_INFO, $ERROR_POSITION * "\n")
|
45
|
+
end
|
50
46
|
raise
|
51
47
|
end
|
52
48
|
|
data/lib/listen/file.rb
CHANGED
@@ -23,52 +23,46 @@ module Listen
|
|
23
23
|
return :modified
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
# Check if change happened within 1 second (maybe it's even
|
29
|
-
# too much, e.g. 0.3-0.5 could be sufficient).
|
30
|
-
#
|
31
|
-
# With rb-fsevent, there's a (configurable) latency between
|
32
|
-
# when file was changed and when the event was triggered.
|
33
|
-
#
|
34
|
-
# If a file is saved at ???14.998, by the time the event is
|
35
|
-
# actually received by Listen, the time could already be e.g.
|
36
|
-
# ???15.7.
|
37
|
-
#
|
38
|
-
# And since Darwin adapter uses directory scanning, the file
|
39
|
-
# mtime may be the same (e.g. file was changed at ???14.001,
|
40
|
-
# then at ???14.998, but the fstat time would be ???14.0 in
|
41
|
-
# both cases).
|
42
|
-
#
|
43
|
-
# If change happend at ???14.999997, the mtime is 14.0, so for
|
44
|
-
# an mtime=???14.0 we assume it could even be almost ???15.0
|
45
|
-
#
|
46
|
-
# So if Time.now.to_f is ???15.999998 and stat reports mtime
|
47
|
-
# at ???14.0, then event was due to that file'd change when:
|
48
|
-
#
|
49
|
-
# ???15.999997 - ???14.999998 < 1.0s
|
50
|
-
#
|
51
|
-
# So the "2" is "1 + 1" (1s to cover rb-fsevent latency +
|
52
|
-
# 1s maximum difference between real mtime and that recorded
|
53
|
-
# in the file system)
|
54
|
-
#
|
55
|
-
if data[:mtime].to_i + 2 > Time.now.to_f
|
56
|
-
begin
|
57
|
-
md5 = Digest::MD5.file(path).digest
|
58
|
-
record.async.update_file(dir, rel_path, data.merge(md5: md5))
|
59
|
-
:modified if record_data[:md5] && md5 != record_data[:md5]
|
26
|
+
return if /1|true/ =~ ENV['LISTEN_GEM_DISABLE_HASHING']
|
27
|
+
return unless self.inaccurate_mac_time?(lstat)
|
60
28
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
29
|
+
# Check if change happened within 1 second (maybe it's even
|
30
|
+
# too much, e.g. 0.3-0.5 could be sufficient).
|
31
|
+
#
|
32
|
+
# With rb-fsevent, there's a (configurable) latency between
|
33
|
+
# when file was changed and when the event was triggered.
|
34
|
+
#
|
35
|
+
# If a file is saved at ???14.998, by the time the event is
|
36
|
+
# actually received by Listen, the time could already be e.g.
|
37
|
+
# ???15.7.
|
38
|
+
#
|
39
|
+
# And since Darwin adapter uses directory scanning, the file
|
40
|
+
# mtime may be the same (e.g. file was changed at ???14.001,
|
41
|
+
# then at ???14.998, but the fstat time would be ???14.0 in
|
42
|
+
# both cases).
|
43
|
+
#
|
44
|
+
# If change happend at ???14.999997, the mtime is 14.0, so for
|
45
|
+
# an mtime=???14.0 we assume it could even be almost ???15.0
|
46
|
+
#
|
47
|
+
# So if Time.now.to_f is ???15.999998 and stat reports mtime
|
48
|
+
# at ???14.0, then event was due to that file'd change when:
|
49
|
+
#
|
50
|
+
# ???15.999997 - ???14.999998 < 1.0s
|
51
|
+
#
|
52
|
+
# So the "2" is "1 + 1" (1s to cover rb-fsevent latency +
|
53
|
+
# 1s maximum difference between real mtime and that recorded
|
54
|
+
# in the file system)
|
55
|
+
#
|
56
|
+
return if data[:mtime].to_i + 2 <= Time.now.to_f
|
57
|
+
|
58
|
+
md5 = Digest::MD5.file(path).digest
|
59
|
+
record.async.update_file(dir, rel_path, data.merge(md5: md5))
|
60
|
+
:modified if record_data[:md5] && md5 != record_data[:md5]
|
67
61
|
rescue SystemCallError
|
68
62
|
record.async.unset_path(dir, rel_path)
|
69
63
|
:removed
|
70
64
|
rescue
|
71
|
-
Celluloid::Logger.debug "lstat failed for: #{rel_path} (#{
|
65
|
+
Celluloid::Logger.debug "lstat failed for: #{rel_path} (#{$ERROR_INFO})"
|
72
66
|
raise
|
73
67
|
end
|
74
68
|
|