cool.io 1.10.1 → 1.11.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 +4 -4
- data/.github/workflows/test.yaml +1 -1
- data/.github/workflows/valgrind.yaml +1 -1
- data/.gitignore +0 -3
- data/CHANGES.md +81 -0
- data/Rakefile +4 -29
- data/cool.io.gemspec +7 -1
- data/examples/dslified_echo_client.rb +1 -0
- data/examples/dslified_echo_server.rb +1 -0
- data/examples/echo_client.rb +3 -3
- data/ext/cool.io/buffer.c +0 -23
- data/ext/cool.io/cool.io.h +0 -16
- data/ext/cool.io/extconf.rb +0 -24
- data/ext/cool.io/iowatcher.c +0 -14
- data/ext/cool.io/stat_watcher.c +14 -8
- data/ext/cool.io/watcher.c +1 -1
- data/ext/libev/ev.c +39 -22
- data/ext/libev/ev_kqueue_stat.c +414 -0
- data/ext/libev/ev_vars.h +4 -0
- data/ext/libev/ev_wrap.h +4 -0
- data/lib/cool.io/version.rb +1 -1
- data/spec/fixtures/kqueue_stat_native.c +333 -0
- data/spec/fixtures/windows_stat_native.c +1 -5
- data/spec/kqueue_stat_native_spec.rb +103 -0
- data/spec/kqueue_stat_watcher_spec.rb +339 -0
- data/spec/stat_watcher_spec.rb +4 -5
- data/spec/timer_watcher_spec.rb +10 -1
- data/spec/windows_stat_native_spec.rb +2 -2
- metadata +14 -19
- data/appveyor.yml +0 -18
- data/examples/google.rb +0 -9
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
|
2
|
+
require 'tmpdir'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'rbconfig'
|
|
5
|
+
require 'timeout'
|
|
6
|
+
|
|
7
|
+
describe 'kqueue notification-backed StatWatcher', :if => RUBY_PLATFORM =~ /darwin/ do
|
|
8
|
+
before do
|
|
9
|
+
@directory = Dir.mktmpdir('coolio-kq-notify-')
|
|
10
|
+
@loop = Coolio::Loop.new
|
|
11
|
+
@watchers = []
|
|
12
|
+
@threads = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
after do
|
|
16
|
+
@threads.each(&:join)
|
|
17
|
+
@watchers.each { |watcher| watcher.detach if watcher.attached? }
|
|
18
|
+
FileUtils.remove_entry(@directory)
|
|
19
|
+
@loop = nil
|
|
20
|
+
@watchers = nil
|
|
21
|
+
GC.start # exercise cleanup of unreachable loops and watchers
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Most tests use a 60-second interval so native notifications must deliver
|
|
25
|
+
# changes before their deadlines. Recovery tests can override the interval.
|
|
26
|
+
def watch(path, interval = 60)
|
|
27
|
+
watcher = Coolio::StatWatcher.new(path, interval)
|
|
28
|
+
watcher.attach(@loop)
|
|
29
|
+
@watchers << watcher
|
|
30
|
+
watcher
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def await_change(watcher, size: nil, exists: nil, timeout: 2, &mutation)
|
|
34
|
+
change = nil
|
|
35
|
+
first_previous = nil
|
|
36
|
+
reactor = @loop
|
|
37
|
+
stopped = false
|
|
38
|
+
stop = -> do
|
|
39
|
+
unless stopped
|
|
40
|
+
stopped = true
|
|
41
|
+
reactor.stop
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
watcher.define_singleton_method(:on_change) do |previous, current|
|
|
45
|
+
first_previous ||= previous
|
|
46
|
+
if (size.nil? || current.size == size) && (exists.nil? || (current.nlink != 0) == exists)
|
|
47
|
+
change = [first_previous, current]
|
|
48
|
+
stop.call
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
deadline = Coolio::TimerWatcher.new(timeout, false)
|
|
52
|
+
deadline.on_timer { stop.call }
|
|
53
|
+
deadline.attach(@loop)
|
|
54
|
+
@threads << Thread.new { sleep 0.1; mutation.call }
|
|
55
|
+
@loop.run
|
|
56
|
+
expect(change).not_to be_nil
|
|
57
|
+
change
|
|
58
|
+
ensure
|
|
59
|
+
deadline.detach if deadline && deadline.attached?
|
|
60
|
+
@threads.each(&:join)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def in_child
|
|
64
|
+
pid = fork do
|
|
65
|
+
begin
|
|
66
|
+
yield
|
|
67
|
+
exit! 0
|
|
68
|
+
rescue Exception => error
|
|
69
|
+
warn error.full_message
|
|
70
|
+
exit! 1
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
begin
|
|
74
|
+
_, status = Timeout.timeout(10) { Process.wait2(pid) }
|
|
75
|
+
rescue Timeout::Error
|
|
76
|
+
Process.kill('KILL', pid)
|
|
77
|
+
Process.wait(pid)
|
|
78
|
+
raise 'forked watcher test timed out'
|
|
79
|
+
end
|
|
80
|
+
expect(status.success?).to eq(true)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'wakes a blocked loop for a file size change without waiting for polling' do
|
|
84
|
+
path = File.join(@directory, 'file')
|
|
85
|
+
File.write(path, 'a')
|
|
86
|
+
previous, current = await_change(watch(path), size: 6) { File.write(path, 'longer') }
|
|
87
|
+
expect(previous.size).to eq(1)
|
|
88
|
+
expect(current.size).to eq(6)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'notifies for a truncation' do
|
|
92
|
+
path = File.join(@directory, 'file')
|
|
93
|
+
File.write(path, 'x' * 40)
|
|
94
|
+
await_change(watch(path), size: 0) { File.truncate(path, 0) }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'notifies for creation, deletion, and recreation of a watched file' do
|
|
98
|
+
directory = File.join(@directory, 'missing')
|
|
99
|
+
path = File.join(directory, 'file')
|
|
100
|
+
watcher = watch(path)
|
|
101
|
+
previous, current = await_change(watcher, size: 7, exists: true) do
|
|
102
|
+
Dir.mkdir(directory)
|
|
103
|
+
File.write(path, 'created')
|
|
104
|
+
end
|
|
105
|
+
expect(previous.nlink).to eq(0)
|
|
106
|
+
expect(current.nlink).not_to eq(0)
|
|
107
|
+
_, current = await_change(watcher, exists: false) { File.delete(path) }
|
|
108
|
+
expect(current.nlink).to eq(0)
|
|
109
|
+
_, current = await_change(watcher, size: 9, exists: true) { File.write(path, 'recreated') }
|
|
110
|
+
expect(current.size).to eq(9)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'notifies when a watched file is renamed away (log rotation)' do
|
|
114
|
+
path = File.join(@directory, 'file')
|
|
115
|
+
File.write(path, 'a')
|
|
116
|
+
_, current = await_change(watch(path)) { File.rename(path, "#{path}.old") }
|
|
117
|
+
expect(current.nlink).to eq(0)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'notifies when a watched file is replaced under the same name' do
|
|
121
|
+
path = File.join(@directory, 'file')
|
|
122
|
+
File.write(path, 'a')
|
|
123
|
+
watcher = watch(path)
|
|
124
|
+
_, current = await_change(watcher, size: 6, exists: true) do
|
|
125
|
+
File.rename(path, "#{path}.old")
|
|
126
|
+
File.write(path, 'longer')
|
|
127
|
+
end
|
|
128
|
+
expect(current.size).to eq(6)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it 'notifies for atomic replacement and subsequent changes' do
|
|
132
|
+
path = File.join(@directory, 'file')
|
|
133
|
+
replacement = File.join(@directory, 'replacement')
|
|
134
|
+
File.write(path, 'a')
|
|
135
|
+
File.write(replacement, 'longer')
|
|
136
|
+
watcher = watch(path)
|
|
137
|
+
await_change(watcher, size: 6) { File.rename(replacement, path) }
|
|
138
|
+
await_change(watcher, size: 7) { File.write(path, 'changed') }
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it 'uses parent hints when a symlink is replaced' do
|
|
142
|
+
path = File.join(@directory, 'link')
|
|
143
|
+
File.symlink('missing', path)
|
|
144
|
+
watcher = watch(path)
|
|
145
|
+
_, current = await_change(watcher, size: 22, exists: true) do
|
|
146
|
+
File.unlink(path)
|
|
147
|
+
File.symlink('another-missing-target', path)
|
|
148
|
+
end
|
|
149
|
+
expect(current.mode & 0o170000).to eq(0o120000)
|
|
150
|
+
expect(current.size).to eq('another-missing-target'.bytesize)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it 'attaches without blocking for a FIFO or a path below it' do
|
|
154
|
+
in_child do
|
|
155
|
+
path = File.join(@directory, 'fifo')
|
|
156
|
+
File.mkfifo(path)
|
|
157
|
+
fifo = watch(path, 0.1)
|
|
158
|
+
watch(File.join(path, 'missing'), 0.1)
|
|
159
|
+
await_change(fifo, exists: false) { File.unlink(path) }
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it 'does not wake a FIFO writer when attaching or retrying registration' do
|
|
164
|
+
in_child do
|
|
165
|
+
path = File.join(@directory, 'fifo')
|
|
166
|
+
File.mkfifo(path)
|
|
167
|
+
reader, ready = IO.pipe
|
|
168
|
+
writer = fork do
|
|
169
|
+
reader.close
|
|
170
|
+
ready.write('ready')
|
|
171
|
+
File.open(path, File::WRONLY) { ready.write('opened') }
|
|
172
|
+
exit! 0
|
|
173
|
+
end
|
|
174
|
+
ready.close
|
|
175
|
+
begin
|
|
176
|
+
expect(reader.read(5)).to eq('ready')
|
|
177
|
+
expect(IO.select([reader], nil, nil, 0.1)).to be_nil
|
|
178
|
+
watch(path, 0.1)
|
|
179
|
+
watch(File.join(path, 'missing'), 0.1)
|
|
180
|
+
deadline = Coolio::TimerWatcher.new(0.35, false)
|
|
181
|
+
deadline.on_timer { @loop.stop }
|
|
182
|
+
deadline.attach(@loop)
|
|
183
|
+
@loop.run
|
|
184
|
+
expect(IO.select([reader], nil, nil, 0)).to be_nil
|
|
185
|
+
ensure
|
|
186
|
+
deadline.detach if deadline && deadline.attached?
|
|
187
|
+
Process.kill('KILL', writer)
|
|
188
|
+
Process.wait(writer)
|
|
189
|
+
reader.close
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it 'continues polling in a child without fork checking' do
|
|
195
|
+
path = File.join(@directory, 'file')
|
|
196
|
+
File.write(path, 'a')
|
|
197
|
+
watcher = watch(path, 0.1)
|
|
198
|
+
in_child do
|
|
199
|
+
await_change(watcher, size: 6) { File.write(path, 'longer') }
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'notifies when a child is added to a watched directory' do
|
|
204
|
+
directory = File.join(@directory, 'sub')
|
|
205
|
+
Dir.mkdir(directory)
|
|
206
|
+
await_change(watch(directory)) { File.write(File.join(directory, 'child'), 'a') }
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it 'notifies for a metadata-only change' do
|
|
210
|
+
path = File.join(@directory, 'file')
|
|
211
|
+
File.write(path, 'a')
|
|
212
|
+
mode = (File.stat(path).mode & 0o777) ^ 0o100
|
|
213
|
+
await_change(watch(path)) { File.chmod(mode, path) }
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it 're-registers when the watched directory itself is recreated' do
|
|
217
|
+
directory = File.join(@directory, 'sub')
|
|
218
|
+
Dir.mkdir(directory)
|
|
219
|
+
watcher = watch(directory)
|
|
220
|
+
await_change(watcher, exists: false) { FileUtils.remove_entry(directory) }
|
|
221
|
+
await_change(watcher, exists: true) { Dir.mkdir(directory) }
|
|
222
|
+
await_change(watcher, timeout: 5) { File.write(File.join(directory, 'child'), 'a' * 6) }
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it 're-registers when a parent of the watched file is recreated under the same name' do
|
|
226
|
+
sub = File.join(@directory, 'sub')
|
|
227
|
+
Dir.mkdir(sub)
|
|
228
|
+
path = File.join(sub, 'file')
|
|
229
|
+
File.write(path, 'a')
|
|
230
|
+
watcher = watch(path)
|
|
231
|
+
await_change(watcher, exists: false) { FileUtils.remove_entry(sub) }
|
|
232
|
+
await_change(watcher, size: 6, exists: true, timeout: 5) do
|
|
233
|
+
Dir.mkdir(sub)
|
|
234
|
+
File.write(path, 'longer')
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it 'transfers notification monitoring to another loop' do
|
|
239
|
+
path = File.join(@directory, 'file')
|
|
240
|
+
File.write(path, 'a')
|
|
241
|
+
watcher = watch(path)
|
|
242
|
+
old_loop = @loop
|
|
243
|
+
@loop = Coolio::Loop.new
|
|
244
|
+
watcher.attach(@loop)
|
|
245
|
+
old_loop.run_nonblock
|
|
246
|
+
_, current = await_change(watcher, size: 6) { File.write(path, 'longer') }
|
|
247
|
+
expect(current.size).to eq(6)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it 'recovers when an ancestor is renamed and the original path is recreated' do
|
|
251
|
+
sub = File.join(@directory, 'sub')
|
|
252
|
+
Dir.mkdir(sub)
|
|
253
|
+
path = File.join(sub, 'file')
|
|
254
|
+
File.write(path, 'a')
|
|
255
|
+
watcher = watch(path, 0)
|
|
256
|
+
|
|
257
|
+
await_change(watcher, size: 6, exists: true, timeout: 8) do
|
|
258
|
+
File.rename(sub, "#{sub}.old")
|
|
259
|
+
Dir.mkdir(sub)
|
|
260
|
+
File.write(path, 'longer')
|
|
261
|
+
end
|
|
262
|
+
# The polling backstop must also transfer native monitoring to the new file.
|
|
263
|
+
await_change(watcher, size: 10) { File.write(path, 'evenlonger') }
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
[false, true].each do |missing|
|
|
267
|
+
it "does not inherit #{missing ? 'parent hint' : 'file'} descriptors across exec" do
|
|
268
|
+
path = File.join(@directory, 'file')
|
|
269
|
+
File.write(path, 'a') unless missing
|
|
270
|
+
target = missing ? @directory : path
|
|
271
|
+
watch(path)
|
|
272
|
+
|
|
273
|
+
script = <<~'RUBY'
|
|
274
|
+
target = File.stat(ARGV.fetch(0))
|
|
275
|
+
leaked = Dir.children('/dev/fd').any? do |fd|
|
|
276
|
+
begin
|
|
277
|
+
stat = IO.for_fd(Integer(fd), autoclose: false).stat
|
|
278
|
+
stat.dev == target.dev && stat.ino == target.ino
|
|
279
|
+
rescue Errno::EBADF, ArgumentError
|
|
280
|
+
false
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
puts leaked
|
|
284
|
+
RUBY
|
|
285
|
+
inherited = IO.popen([RbConfig.ruby, '-e', script, target], close_others: false, &:read)
|
|
286
|
+
expect(inherited.strip).to eq('false')
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
it 'keeps monitoring when another watcher on the same path detaches' do
|
|
291
|
+
path = File.join(@directory, 'file')
|
|
292
|
+
File.write(path, 'a')
|
|
293
|
+
first = watch(path)
|
|
294
|
+
second = watch(path)
|
|
295
|
+
await_change(first, size: 6) { File.write(path, 'b' * 6) }
|
|
296
|
+
first.detach
|
|
297
|
+
await_change(second, size: 7) { File.write(path, 'c' * 7) }
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it 'notifies every watcher of many watched files within one burst' do
|
|
301
|
+
# Exceed the native event batch size without requiring hundreds of fds.
|
|
302
|
+
paths = (1..64).map do |i|
|
|
303
|
+
path = File.join(@directory, "file#{i}")
|
|
304
|
+
File.write(path, 'a')
|
|
305
|
+
watch(path)
|
|
306
|
+
end
|
|
307
|
+
notified = 0
|
|
308
|
+
reactor = @loop
|
|
309
|
+
paths.each do |watcher|
|
|
310
|
+
watcher.define_singleton_method(:on_change) do |_previous, current|
|
|
311
|
+
if current.size == 2
|
|
312
|
+
notified += 1
|
|
313
|
+
reactor.stop if notified == paths.size
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
deadline = Coolio::TimerWatcher.new(5, false)
|
|
318
|
+
deadline.on_timer { @loop.stop }
|
|
319
|
+
deadline.attach(@loop)
|
|
320
|
+
paths.each { |watcher| File.open(watcher.path, 'a') { |file| file.write 'b' } }
|
|
321
|
+
@loop.run
|
|
322
|
+
deadline.detach if deadline.attached?
|
|
323
|
+
expect(notified).to eq(paths.size)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
it 're-registers inherited watchers after fork without changing the parent loop' do
|
|
327
|
+
@loop = Coolio::Loop.new(fork_check: true)
|
|
328
|
+
path = File.join(@directory, 'file')
|
|
329
|
+
File.write(path, 'a')
|
|
330
|
+
watcher = watch(path)
|
|
331
|
+
|
|
332
|
+
in_child do
|
|
333
|
+
await_change(watcher, size: 6) { File.write(path, 'longer') }
|
|
334
|
+
watcher.detach
|
|
335
|
+
end
|
|
336
|
+
await_change(watcher, size: 10) { File.write(path, 'evenlonger') }
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
end
|
data/spec/stat_watcher_spec.rb
CHANGED
|
@@ -19,10 +19,10 @@ class MyStatWatcher < Cool.io::StatWatcher
|
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def run_with_file_change(path, compact: false)
|
|
22
|
+
def run_with_file_change(path, watcher_class: MyStatWatcher, compact: false)
|
|
23
23
|
reactor = Cool.io::Loop.new
|
|
24
24
|
|
|
25
|
-
sw =
|
|
25
|
+
sw = watcher_class.new(path)
|
|
26
26
|
sw.attach(reactor)
|
|
27
27
|
|
|
28
28
|
# libev retains the path pointer passed to ev_stat_init() for the lifetime of
|
|
@@ -155,12 +155,11 @@ describe Cool.io::StatWatcher do
|
|
|
155
155
|
end
|
|
156
156
|
|
|
157
157
|
it "should raise when the handler does not take 2 parameters" do
|
|
158
|
-
|
|
159
|
-
remove_method :on_change
|
|
158
|
+
watcher_class = Class.new(MyStatWatcher) do
|
|
160
159
|
def on_change
|
|
161
160
|
end
|
|
162
161
|
end
|
|
163
|
-
expect {
|
|
162
|
+
expect { run_with_file_change(TEMP_FILE_PATH, watcher_class: watcher_class) }.to raise_error(ArgumentError)
|
|
164
163
|
end
|
|
165
164
|
|
|
166
165
|
end
|
data/spec/timer_watcher_spec.rb
CHANGED
|
@@ -53,7 +53,16 @@ describe Cool.io::TimerWatcher do
|
|
|
53
53
|
expect(nr).to eq(:foo)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
+
it "reports whether it is attached" do
|
|
57
|
+
@watcher = Cool.io::TimerWatcher.new(interval, true)
|
|
58
|
+
expect(@watcher.attached?).to eq(false)
|
|
59
|
+
@watcher.attach(loop)
|
|
60
|
+
expect(@watcher.attached?).to eq(true)
|
|
61
|
+
@watcher.detach
|
|
62
|
+
expect(@watcher.attached?).to eq(false)
|
|
63
|
+
end
|
|
64
|
+
|
|
56
65
|
after :each do
|
|
57
|
-
@watcher.detach if defined?(@watcher)
|
|
66
|
+
@watcher.detach if defined?(@watcher) && @watcher.attached?
|
|
58
67
|
end
|
|
59
68
|
end
|
|
@@ -7,7 +7,7 @@ describe 'Windows stat notification internals', :if => RUBY_PLATFORM =~ /mingw|m
|
|
|
7
7
|
before(:context) do
|
|
8
8
|
@build = Dir.mktmpdir('coolio-stat-native-')
|
|
9
9
|
source = File.expand_path('fixtures/windows_stat_native.c', __dir__)
|
|
10
|
-
|
|
10
|
+
coolio = File.expand_path('../ext/cool.io', __dir__)
|
|
11
11
|
FileUtils.cp(source, @build)
|
|
12
12
|
File.write(File.join(@build, 'extconf.rb'), <<~RUBY)
|
|
13
13
|
begin
|
|
@@ -16,7 +16,7 @@ describe 'Windows stat notification internals', :if => RUBY_PLATFORM =~ /mingw|m
|
|
|
16
16
|
# Other Windows toolchains can provide the compiler through PATH.
|
|
17
17
|
end
|
|
18
18
|
require 'mkmf'
|
|
19
|
-
$INCFLAGS << ' -I"#{
|
|
19
|
+
$INCFLAGS << ' -I"#{coolio}"'
|
|
20
20
|
abort 'ws2_32 is required' unless have_library('ws2_32')
|
|
21
21
|
create_makefile('coolio_stat_native')
|
|
22
22
|
RUBY
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cool.io
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tony Arcieri
|
|
@@ -24,20 +24,6 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1.0'
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: rake-compiler-dock
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - "~>"
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '1.0'
|
|
34
|
-
type: :development
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - "~>"
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '1.0'
|
|
41
27
|
- !ruby/object:Gem::Dependency
|
|
42
28
|
name: rspec
|
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -84,14 +70,12 @@ files:
|
|
|
84
70
|
- LICENSE
|
|
85
71
|
- README.md
|
|
86
72
|
- Rakefile
|
|
87
|
-
- appveyor.yml
|
|
88
73
|
- cool.io.gemspec
|
|
89
74
|
- examples/callbacked_echo_server.rb
|
|
90
75
|
- examples/dslified_echo_client.rb
|
|
91
76
|
- examples/dslified_echo_server.rb
|
|
92
77
|
- examples/echo_client.rb
|
|
93
78
|
- examples/echo_server.rb
|
|
94
|
-
- examples/google.rb
|
|
95
79
|
- ext/cool.io/.gitignore
|
|
96
80
|
- ext/cool.io/buffer.c
|
|
97
81
|
- ext/cool.io/cool.io.h
|
|
@@ -114,6 +98,7 @@ files:
|
|
|
114
98
|
- ext/libev/ev.h
|
|
115
99
|
- ext/libev/ev_epoll.c
|
|
116
100
|
- ext/libev/ev_kqueue.c
|
|
101
|
+
- ext/libev/ev_kqueue_stat.c
|
|
117
102
|
- ext/libev/ev_poll.c
|
|
118
103
|
- ext/libev/ev_port.c
|
|
119
104
|
- ext/libev/ev_select.c
|
|
@@ -144,8 +129,11 @@ files:
|
|
|
144
129
|
- spec/async_watcher_spec.rb
|
|
145
130
|
- spec/detach_race_condition_spec.rb
|
|
146
131
|
- spec/dns_spec.rb
|
|
132
|
+
- spec/fixtures/kqueue_stat_native.c
|
|
147
133
|
- spec/fixtures/windows_stat_native.c
|
|
148
134
|
- spec/iobuffer_spec.rb
|
|
135
|
+
- spec/kqueue_stat_native_spec.rb
|
|
136
|
+
- spec/kqueue_stat_watcher_spec.rb
|
|
149
137
|
- spec/loop_spec.rb
|
|
150
138
|
- spec/spec_helper.rb
|
|
151
139
|
- spec/stat_watcher_spec.rb
|
|
@@ -161,7 +149,11 @@ files:
|
|
|
161
149
|
homepage: https://github.com/socketry/cool.io
|
|
162
150
|
licenses:
|
|
163
151
|
- MIT
|
|
164
|
-
metadata:
|
|
152
|
+
metadata:
|
|
153
|
+
bug_tracker_uri: https://github.com/socketry/cool.io/issues
|
|
154
|
+
changelog_uri: https://github.com/socketry/cool.io/blob/main/CHANGES.md
|
|
155
|
+
source_code_uri: https://github.com/socketry/cool.io.git
|
|
156
|
+
rubygems_mfa_required: 'true'
|
|
165
157
|
rdoc_options: []
|
|
166
158
|
require_paths:
|
|
167
159
|
- lib
|
|
@@ -169,7 +161,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
169
161
|
requirements:
|
|
170
162
|
- - ">="
|
|
171
163
|
- !ruby/object:Gem::Version
|
|
172
|
-
version: '
|
|
164
|
+
version: '3.2'
|
|
173
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
174
166
|
requirements:
|
|
175
167
|
- - ">="
|
|
@@ -183,8 +175,11 @@ test_files:
|
|
|
183
175
|
- spec/async_watcher_spec.rb
|
|
184
176
|
- spec/detach_race_condition_spec.rb
|
|
185
177
|
- spec/dns_spec.rb
|
|
178
|
+
- spec/fixtures/kqueue_stat_native.c
|
|
186
179
|
- spec/fixtures/windows_stat_native.c
|
|
187
180
|
- spec/iobuffer_spec.rb
|
|
181
|
+
- spec/kqueue_stat_native_spec.rb
|
|
182
|
+
- spec/kqueue_stat_watcher_spec.rb
|
|
188
183
|
- spec/loop_spec.rb
|
|
189
184
|
- spec/spec_helper.rb
|
|
190
185
|
- spec/stat_watcher_spec.rb
|
data/appveyor.yml
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
install:
|
|
3
|
-
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
|
4
|
-
- ruby --version
|
|
5
|
-
- gem --version
|
|
6
|
-
- bundle install
|
|
7
|
-
build: off
|
|
8
|
-
test_script:
|
|
9
|
-
- bundle exec rake -rdevkit
|
|
10
|
-
|
|
11
|
-
environment:
|
|
12
|
-
matrix:
|
|
13
|
-
- ruby_version: "200"
|
|
14
|
-
- ruby_version: "200-x64"
|
|
15
|
-
- ruby_version: "21"
|
|
16
|
-
- ruby_version: "21-x64"
|
|
17
|
-
- ruby_version: "22"
|
|
18
|
-
- ruby_version: "22-x64"
|
data/examples/google.rb
DELETED