listen 2.8.4 → 2.8.5

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -11
  3. data/lib/listen/adapter/base.rb +8 -4
  4. data/lib/listen/adapter/bsd.rb +8 -25
  5. data/lib/listen/adapter/tcp.rb +2 -1
  6. data/lib/listen/internals/logging.rb +12 -8
  7. data/lib/listen/listener.rb +1 -1
  8. data/lib/listen/version.rb +1 -1
  9. metadata +4 -121
  10. data/.gitignore +0 -28
  11. data/.hound.yml +0 -3
  12. data/.rspec +0 -2
  13. data/.rubocop.yml +0 -20
  14. data/.rubocop_todo.yml +0 -33
  15. data/.travis.yml +0 -15
  16. data/.yardopts +0 -11
  17. data/Gemfile +0 -48
  18. data/Guardfile +0 -16
  19. data/Rakefile +0 -151
  20. data/TROUBLESHOOTING.md +0 -139
  21. data/listen.gemspec +0 -33
  22. data/spec/acceptance/listen_spec.rb +0 -230
  23. data/spec/acceptance/tcp_spec.rb +0 -139
  24. data/spec/lib/listen/adapter/base_spec.rb +0 -31
  25. data/spec/lib/listen/adapter/bsd_spec.rb +0 -14
  26. data/spec/lib/listen/adapter/darwin_spec.rb +0 -145
  27. data/spec/lib/listen/adapter/linux_spec.rb +0 -93
  28. data/spec/lib/listen/adapter/polling_spec.rb +0 -48
  29. data/spec/lib/listen/adapter/tcp_spec.rb +0 -129
  30. data/spec/lib/listen/adapter/windows_spec.rb +0 -14
  31. data/spec/lib/listen/adapter_spec.rb +0 -75
  32. data/spec/lib/listen/change_spec.rb +0 -104
  33. data/spec/lib/listen/directory_spec.rb +0 -180
  34. data/spec/lib/listen/file_spec.rb +0 -252
  35. data/spec/lib/listen/listener_spec.rb +0 -482
  36. data/spec/lib/listen/record_spec.rb +0 -377
  37. data/spec/lib/listen/silencer_spec.rb +0 -100
  38. data/spec/lib/listen/tcp/broadcaster_spec.rb +0 -124
  39. data/spec/lib/listen/tcp/listener_spec.rb +0 -104
  40. data/spec/lib/listen/tcp/message_spec.rb +0 -138
  41. data/spec/lib/listen_spec.rb +0 -52
  42. data/spec/spec_helper.rb +0 -52
  43. data/spec/support/acceptance_helper.rb +0 -275
  44. data/spec/support/fixtures_helper.rb +0 -30
  45. data/spec/support/platform_helper.rb +0 -15
  46. data/vendor/hound/config/style_guides/ruby.yml +0 -259
@@ -1,275 +0,0 @@
1
- {
2
- modification: :modified,
3
- addition: :added,
4
- removal: :removed,
5
- queued_modification: :modified,
6
- queued_addition: :added
7
- }.each do |description, type|
8
-
9
- RSpec::Matchers.define "process_#{description}_of".to_sym do |expected|
10
- match do |actual|
11
- # Use cases:
12
- # 1. reset the changes so they don't have leftovers
13
- # 2. keep the queue if we're testing for existing accumulated changes
14
-
15
- # if were testing the queue (e.g. after unpause), don't reset
16
- check_already_queued = /queued_/ =~ description
17
- reset_queue = !check_already_queued
18
-
19
- actual.listen(reset_queue) do
20
- change_fs(type, expected) unless check_already_queued
21
- end
22
- actual.changes[type].include? expected
23
- end
24
-
25
- failure_message do |actual|
26
- result = actual.changes.inspect
27
- "expected #{result} to include #{description} of #{expected}"
28
- end
29
-
30
- failure_message_when_negated do |actual|
31
- result = actual.changes.inspect
32
- "expected #{result} to not include #{description} of #{expected}"
33
- end
34
- end
35
- end
36
-
37
- def change_fs(type, path)
38
- case type
39
- when :modified
40
- unless File.exist?(path)
41
- fail "Bad test: cannot modify #{path.inspect} (it doesn't exist)"
42
- end
43
-
44
- # wait until full second, because this might be followed by a modification
45
- # event (which otherwise may not be detected every time)
46
- _sleep_until_next_second(Pathname.pwd)
47
-
48
- open(path, 'a') { |f| f.write('foo') }
49
-
50
- # separate it from upcoming modifications"
51
- _sleep_to_separate_events
52
- when :added
53
- if File.exist?(path)
54
- fail "Bad test: cannot add #{path.inspect} (it already exists)"
55
- end
56
-
57
- # wait until full second, because this might be followed by a modification
58
- # event (which otherwise may not be detected every time)
59
- _sleep_until_next_second(Pathname.pwd)
60
-
61
- open(path, 'w') { |f| f.write('foo') }
62
-
63
- # separate it from upcoming modifications"
64
- _sleep_to_separate_events
65
- when :removed
66
- unless File.exist?(path)
67
- fail "Bad test: cannot remove #{path.inspect} (it doesn't exist)"
68
- end
69
- File.unlink(path)
70
- else
71
- fail "bad test: unknown type: #{type.inspect}"
72
- end
73
- end
74
-
75
- # Used by change_fs() above so that the FS change (e.g. file created) happens
76
- # as close to the start of a new second (time) as possible.
77
- #
78
- # E.g. if file is created at 1234567.999 (unix time), it's mtime on some
79
- # filesystems is rounded, so it becomes 1234567.0, but if the change
80
- # notification happens a little while later, e.g. at 1234568.111, now the file
81
- # mtime and the current time in seconds are different (1234567 vs 1234568), and
82
- # so the MD5 test won't kick in (see file.rb) - the file will not be considered
83
- # for content checking (md5), so File.change will consider the file unmodified.
84
- #
85
- # This means, that if a file is added at 1234567.888 (and updated in Record),
86
- # and then its content is modified at 1234567.999, and checking for changes
87
- # happens at 1234568.111, the modification won't be detected.
88
- # (because Record mtime is 1234567.0, current FS mtime from stat() is the
89
- # same, and the checking happens in another second - 1234568).
90
- #
91
- # So basically, adding a file and detecting its later modification should all
92
- # happen within 1 second (which makes testing and debugging difficult).
93
- #
94
- def _sleep_until_next_second(path)
95
- Listen::File.inaccurate_mac_time?(path)
96
-
97
- t = Time.now
98
- diff = t.to_f - t.to_i
99
-
100
- sleep(1.05 - diff)
101
- end
102
-
103
- # Special class to only allow changes within a specific time window
104
-
105
- class TimedChanges
106
- attr_reader :changes
107
-
108
- def initialize
109
- # Set to non-nil, because changes can immediately come after unpausing
110
- # listener in an Rspec 'before()' block
111
- @changes = { modified: [], added: [], removed: [] }
112
- end
113
-
114
- def change_offset
115
- Time.now.to_f - @yield_time
116
- end
117
-
118
- def freeze_offset
119
- result = @freeze_time - @yield_time
120
- # Make an "almost zero" value more readable
121
- result < 1e-4 ? 1e-4 : result
122
- end
123
-
124
- # Allow changes only during specific time wine
125
- def allow_changes(reset_queue = true)
126
- @freeze_time = nil
127
- if reset_queue
128
- # Clear to prepare for collecting new FS events
129
- @changes = { modified: [], added: [], removed: [] }
130
- else
131
- # Since we're testing the queue and the listener callback is adding
132
- # changes to the same hash (e.g. after a pause), copy the existing data
133
- # to a new, unfrozen hash
134
- @changes = @changes.dup if @changes.frozen?
135
- @changes ||= { modified: [], added: [], removed: [] }
136
- end
137
-
138
- @yield_time = Time.now.to_f
139
- yield
140
- # Prevent recording changes after timeout
141
- @changes.freeze
142
- @freeze_time = Time.now.to_f
143
- end
144
- end
145
-
146
- # Conveniently wrap a Listener instance for testing
147
- class ListenerWrapper
148
- attr_reader :listener, :changes
149
- attr_accessor :lag
150
-
151
- def initialize(callback, paths, *args)
152
- # Lag depends mostly on wait_for_delay On Linux desktop, it's 0.06 - 0.11
153
- #
154
- # On Travis it used to be > 0.5, but that was before broadcaster sent
155
- # changes immediately, so 0.2-0.4 might be enough for Travis, but we set it
156
- # to 0.6
157
- #
158
- # The value should be 2-3 x wait_for_delay + time between fs operation and
159
- # notification, which for polling and FSEvent means the configured latency
160
- @lag = 0.6
161
-
162
- @paths = paths
163
-
164
- # Isolate collected changes between tests/listener instances
165
- @timed_changes = TimedChanges.new
166
-
167
- if callback
168
- @listener = Listen.send(*args) do |modified, added, removed|
169
- # Add changes to trigger frozen Hash error, making sure lag is enough
170
- _add_changes(:modified, modified, changes)
171
- _add_changes(:added, added, changes)
172
- _add_changes(:removed, removed, changes)
173
-
174
- unless callback == :track_changes
175
- callback.call(modified, added, removed)
176
- end
177
- end
178
- else
179
- @listener = Listen.send(*args)
180
- end
181
- end
182
-
183
- def changes
184
- @timed_changes.changes
185
- end
186
-
187
- def listen(reset_queue = true)
188
- # Give previous events time to be received, queued and processed
189
- # so they complete and don't interfere
190
- sleep lag
191
-
192
- @timed_changes.allow_changes(reset_queue) do
193
-
194
- yield
195
-
196
- # Polling sleep (default: 1s)
197
- adapter = @listener.sync(:adapter)
198
- sleep(adapter.options.latency) if adapter.is_a?(Listen::Adapter::Polling)
199
-
200
- # Lag should include:
201
- # 0.1s - 0.2s if the test needs Listener queue to be processed
202
- # 0.1s in case the system is busy
203
- # 0.1s - for celluloid overhead and scheduling
204
- sleep lag
205
- end
206
-
207
- # Keep this to detect a lag too small (changes during this sleep
208
- # will trigger "frozen hash" error caught below (and displaying timeout
209
- # details)
210
- sleep 1
211
-
212
- changes
213
- end
214
-
215
- private
216
-
217
- def _add_changes(type, changes, dst)
218
- dst[type] += _relative_path(changes)
219
- dst[type].uniq!
220
- dst[type].sort!
221
-
222
- rescue RuntimeError => e
223
- raise unless e.message == "can't modify frozen Hash"
224
-
225
- # Show how by much the changes missed the timeout
226
- change_offset = @timed_changes.change_offset
227
- freeze_offset = @timed_changes.freeze_offset
228
-
229
- msg = "Changes took #{change_offset}s (allowed lag: #{freeze_offset})s"
230
-
231
- # Use STDERR (workaround for Celluloid, since it catches abort)
232
- STDERR.puts msg
233
- abort(msg)
234
- end
235
-
236
- def _relative_path(changes)
237
- changes.map do |change|
238
- unfrozen_copy = change.dup
239
- [@paths].flatten.each do |path|
240
- sub = path.sub(/\/$/, '').to_s
241
- unfrozen_copy.gsub!(/^#{sub}\//, '')
242
- end
243
- unfrozen_copy
244
- end
245
- end
246
- end
247
-
248
- def setup_listener(options, callback = nil)
249
- ListenerWrapper.new(callback, paths, :to, paths, options)
250
- end
251
-
252
- def setup_recipient(port, callback = nil)
253
- ListenerWrapper.new(callback, paths, :on, port)
254
- end
255
-
256
- def _sleep_to_separate_events
257
- # separate the events or Darwin and Polling
258
- # will detect only the :added event
259
- #
260
- # (This is because both use directory scanning
261
- # through Celluloid tasks, which may not kick in
262
- # time before the next filesystem change)
263
- #
264
- # The minimum for this is the time it takes between a syscall
265
- # changing the filesystem ... and ... an async
266
- # Listen::File.scan to finish comparing the file with the
267
- # Record
268
- #
269
- # This necessary for:
270
- # - Darwin Adapter
271
- # - Polling Adapter
272
- # - Linux Adapter in FSEvent emulation mode
273
- # - maybe Windows adapter (probably not)
274
- sleep 0.4
275
- end
@@ -1,30 +0,0 @@
1
- require 'tmpdir'
2
-
3
- include FileUtils
4
-
5
- # Prepares temporary fixture-directories and
6
- # cleans them afterwards.
7
- #
8
- # @param [Fixnum] number_of_directories the number of fixture-directories to
9
- # make
10
- #
11
- # @yield [path1, path2, ...] the empty fixture-directories
12
- # @yieldparam [String] path the path to a fixture directory
13
- #
14
- def fixtures(number_of_directories = 1)
15
- current_pwd = Dir.pwd
16
- paths = 1.upto(number_of_directories).map { mk_fixture_tmp_dir }
17
-
18
- FileUtils.cd(paths.first) if number_of_directories == 1
19
-
20
- yield(*paths)
21
- ensure
22
- FileUtils.cd current_pwd
23
- paths.map { |p| FileUtils.rm_rf(p) if File.exist?(p) }
24
- end
25
-
26
- def mk_fixture_tmp_dir
27
- timestamp = Time.now.to_f.to_s.sub('.', '') + rand(9999).to_s
28
- path = Pathname.pwd.join('spec', '.fixtures', timestamp).expand_path
29
- path.tap(&:mkpath)
30
- end
@@ -1,15 +0,0 @@
1
- def darwin?
2
- RbConfig::CONFIG['target_os'] =~ /darwin/i
3
- end
4
-
5
- def linux?
6
- RbConfig::CONFIG['target_os'] =~ /linux/i
7
- end
8
-
9
- def bsd?
10
- RbConfig::CONFIG['target_os'] =~ /bsd|dragonfly/i
11
- end
12
-
13
- def windows?
14
- RbConfig::CONFIG['target_os'] =~ /mswin|mingw|cygwin/i
15
- end
@@ -1,259 +0,0 @@
1
- AllCops:
2
- Exclude:
3
- - db/schema.rb
4
-
5
- AccessorMethodName:
6
- Enabled: false
7
-
8
- ActionFilter:
9
- Enabled: false
10
-
11
- Alias:
12
- Enabled: false
13
-
14
- ArrayJoin:
15
- Enabled: false
16
-
17
- AsciiComments:
18
- Enabled: false
19
-
20
- AsciiIdentifiers:
21
- Enabled: false
22
-
23
- Attr:
24
- Enabled: false
25
-
26
- BlockNesting:
27
- Enabled: false
28
-
29
- CaseEquality:
30
- Enabled: false
31
-
32
- CharacterLiteral:
33
- Enabled: false
34
-
35
- ClassAndModuleChildren:
36
- Enabled: false
37
-
38
- ClassLength:
39
- Enabled: false
40
-
41
- ClassVars:
42
- Enabled: false
43
-
44
- Style/CollectionMethods:
45
- PreferredMethods:
46
- find: detect
47
- reduce: inject
48
- collect: map
49
- find_all: select
50
-
51
- ColonMethodCall:
52
- Enabled: false
53
-
54
- CommentAnnotation:
55
- Enabled: false
56
-
57
- CyclomaticComplexity:
58
- Enabled: false
59
-
60
- Delegate:
61
- Enabled: false
62
-
63
- DeprecatedHashMethods:
64
- Enabled: false
65
-
66
- Documentation:
67
- Enabled: false
68
-
69
- DotPosition:
70
- EnforcedStyle: trailing
71
-
72
- DoubleNegation:
73
- Enabled: false
74
-
75
- EachWithObject:
76
- Enabled: false
77
-
78
- EmptyLiteral:
79
- Enabled: false
80
-
81
- Encoding:
82
- Enabled: false
83
-
84
- EvenOdd:
85
- Enabled: false
86
-
87
- FileName:
88
- Enabled: false
89
-
90
- FlipFlop:
91
- Enabled: false
92
-
93
- FormatString:
94
- Enabled: false
95
-
96
- GlobalVars:
97
- Enabled: false
98
-
99
- GuardClause:
100
- Enabled: false
101
-
102
- IfUnlessModifier:
103
- Enabled: false
104
-
105
- IfWithSemicolon:
106
- Enabled: false
107
-
108
- InlineComment:
109
- Enabled: false
110
-
111
- Lambda:
112
- Enabled: false
113
-
114
- LambdaCall:
115
- Enabled: false
116
-
117
- LineEndConcatenation:
118
- Enabled: false
119
-
120
- LineLength:
121
- Max: 80
122
-
123
- MethodLength:
124
- Enabled: false
125
-
126
- ModuleFunction:
127
- Enabled: false
128
-
129
- NegatedIf:
130
- Enabled: false
131
-
132
- NegatedWhile:
133
- Enabled: false
134
-
135
- Next:
136
- Enabled: false
137
-
138
- NilComparison:
139
- Enabled: false
140
-
141
- Not:
142
- Enabled: false
143
-
144
- NumericLiterals:
145
- Enabled: false
146
-
147
- OneLineConditional:
148
- Enabled: false
149
-
150
- OpMethod:
151
- Enabled: false
152
-
153
- ParameterLists:
154
- Enabled: false
155
-
156
- PercentLiteralDelimiters:
157
- Enabled: false
158
-
159
- PerlBackrefs:
160
- Enabled: false
161
-
162
- PredicateName:
163
- NamePrefixBlacklist:
164
- - is_
165
-
166
- Proc:
167
- Enabled: false
168
-
169
- RaiseArgs:
170
- Enabled: false
171
-
172
- RegexpLiteral:
173
- Enabled: false
174
-
175
- SelfAssignment:
176
- Enabled: false
177
-
178
- SingleLineBlockParams:
179
- Enabled: false
180
-
181
- SingleLineMethods:
182
- Enabled: false
183
-
184
- SignalException:
185
- Enabled: false
186
-
187
- SpecialGlobalVars:
188
- Enabled: false
189
-
190
- StringLiterals:
191
- EnforcedStyle: double_quotes
192
-
193
- VariableInterpolation:
194
- Enabled: false
195
-
196
- TrailingComma:
197
- Enabled: false
198
-
199
- TrivialAccessors:
200
- Enabled: false
201
-
202
- VariableInterpolation:
203
- Enabled: false
204
-
205
- WhenThen:
206
- Enabled: false
207
-
208
- WhileUntilModifier:
209
- Enabled: false
210
-
211
- WordArray:
212
- Enabled: false
213
-
214
- # Lint
215
-
216
- AmbiguousOperator:
217
- Enabled: false
218
-
219
- AmbiguousRegexpLiteral:
220
- Enabled: false
221
-
222
- AssignmentInCondition:
223
- Enabled: false
224
-
225
- ConditionPosition:
226
- Enabled: false
227
-
228
- DeprecatedClassMethods:
229
- Enabled: false
230
-
231
- ElseLayout:
232
- Enabled: false
233
-
234
- HandleExceptions:
235
- Enabled: false
236
-
237
- InvalidCharacterLiteral:
238
- Enabled: false
239
-
240
- LiteralInCondition:
241
- Enabled: false
242
-
243
- LiteralInInterpolation:
244
- Enabled: false
245
-
246
- Loop:
247
- Enabled: false
248
-
249
- ParenthesesAsGroupedExpression:
250
- Enabled: false
251
-
252
- RequireParentheses:
253
- Enabled: false
254
-
255
- UnderscorePrefixedVariableName:
256
- Enabled: false
257
-
258
- Void:
259
- Enabled: false