listen 2.8.4 → 2.8.5

Sign up to get free protection for your applications and to get access to all the features.
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