rbbt-util 5.23.7 → 5.23.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d76b8cd3df1f148aba3f5d8dd7106ec89e78110
4
- data.tar.gz: 27e02877f0fcc8d75d5a1822edfb4fbd13b9f272
3
+ metadata.gz: f8aaf566bf17aad351fdc54c77e2cff349e23daf
4
+ data.tar.gz: 393fc23341ab6ecb7b7a01ae408e8ca2dea2ef9e
5
5
  SHA512:
6
- metadata.gz: 5115c493080b64334eca39ae4f880df24e8ac4e84b6cb635f25bfb02c7159a93d2a9b79175cb08e5e86e1d56f84e0c55976e619b7538ec5012f87e55f275cf7d
7
- data.tar.gz: 7a92cd8e8660ee5793dd90a699570cd4c97b060d795f316e34ab6eb9dd5f92fc9240f82e015924c4c0fed0a8e459c76b0f1398336093abdcd165faa82a639c7e
6
+ metadata.gz: 729e28c3ed2a19f84c0b702b3eb62f94b141e64b1b305caa0ae0388409fbdf34e53110922ad0ee6499b4364f5bdba8e1735b1fc491fe7c2dc137e559c66c1189
7
+ data.tar.gz: 943598ede0e34302e6784b1dc7201165f44ba8dae6e8bed071a828d568bc7d241f1dab49aa3c46c24c4aa77c989d06bb37a483ba4c379d73b789cb8982b2fffe
@@ -197,7 +197,7 @@ module Persist
197
197
  def self.tee_stream_thread(stream, path, type, callback = nil, abort_callback = nil, lockfile = nil)
198
198
  file, out = Misc.tee_stream(stream)
199
199
 
200
- saver_thread = Thread.new(Thread.current) do |parent|
200
+ saver_thread = Thread.new do
201
201
  begin
202
202
  file.threads = []
203
203
  Thread.current["name"] = "file saver: " + path
@@ -209,7 +209,6 @@ module Persist
209
209
  rescue Exception
210
210
  Log.medium "Persist stream thread exception: #{ Log.color :blue, path }"
211
211
  file.abort if file.respond_to? :abort
212
- #parent.raise $!
213
212
  raise $!
214
213
  rescue Exception
215
214
  Log.exception $!
@@ -71,162 +71,200 @@ module TSV
71
71
  def self.traverse_tsv(tsv, options = {}, &block)
72
72
  callback, bar, join = Misc.process_options options, :callback, :bar, :join
73
73
 
74
- if callback
75
- bar.init if bar
76
- tsv.through options[:key_field], options[:fields] do |k,v|
77
- begin
78
- callback.call yield(k,v)
79
- rescue Exception
80
- Log.exception $!
81
- raise $!
82
- ensure
83
- bar.tick if bar
74
+ begin
75
+ error = false
76
+ if callback
77
+ bar.init if bar
78
+ tsv.through options[:key_field], options[:fields] do |k,v|
79
+ begin
80
+ callback.call yield(k,v)
81
+ rescue Exception
82
+ Log.exception $!
83
+ raise $!
84
+ ensure
85
+ bar.tick if bar
86
+ end
84
87
  end
85
- end
86
- else
87
- bar.init if bar
88
- tsv.through options[:key_field], options[:fields] do |k,v|
89
- begin
90
- yield k,v
91
- ensure
92
- bar.tick if bar
88
+ else
89
+ bar.init if bar
90
+ tsv.through options[:key_field], options[:fields] do |k,v|
91
+ begin
92
+ yield k,v
93
+ ensure
94
+ bar.tick if bar
95
+ end
93
96
  end
94
97
  end
95
- end
96
- Log::ProgressBar.remove_bar(bar) if bar
97
- join.call if join
98
+ rescue
99
+ Log.exception $!
100
+ error = true
101
+ raise $!
102
+ ensure
103
+ Log::ProgressBar.remove_bar(bar) if bar
104
+ join.call(error) if join
105
+ end
98
106
  end
99
107
 
100
108
  def self.traverse_hash(hash, options = {}, &block)
101
109
  callback, bar, join = Misc.process_options options, :callback, :bar, :join
102
110
 
103
- if callback
104
- bar.init if bar
105
- hash.each do |k,v|
106
- begin
107
- callback.call yield(k,v)
108
- ensure
109
- bar.tick if bar
111
+ begin
112
+ error = false
113
+ if callback
114
+ bar.init if bar
115
+ hash.each do |k,v|
116
+ begin
117
+ callback.call yield(k,v)
118
+ ensure
119
+ bar.tick if bar
120
+ end
110
121
  end
111
- end
112
- else
113
- bar.init if bar
114
- hash.each do |k,v|
115
- begin
116
- yield k,v
117
- ensure
118
- bar.tick if bar
122
+ else
123
+ bar.init if bar
124
+ hash.each do |k,v|
125
+ begin
126
+ yield k,v
127
+ ensure
128
+ bar.tick if bar
129
+ end
119
130
  end
120
131
  end
132
+ rescue
133
+ error = true
134
+ raise $!
135
+ ensure
136
+ Log::ProgressBar.remove_bar(bar) if bar
137
+ join.call(error) if join
121
138
  end
122
- Log::ProgressBar.remove_bar(bar) if bar
123
- join.call if join
124
139
  end
125
140
 
126
141
  def self.traverse_array(array, options = {}, &block)
127
142
  callback, bar, join = Misc.process_options options, :callback, :bar, :join
128
143
 
129
- if callback
130
- bar.init if bar
131
- array.each do |e|
132
- begin
133
- callback.call yield(e)
134
- ensure
135
- bar.tick if bar
144
+ begin
145
+ error = false
146
+ if callback
147
+ bar.init if bar
148
+ array.each do |e|
149
+ begin
150
+ callback.call yield(e)
151
+ ensure
152
+ bar.tick if bar
153
+ end
136
154
  end
137
- end
138
- else
139
- bar.init if bar
140
- array.each do |e|
141
- begin
142
- yield e
143
- rescue Exception
144
- Log.exception $!
145
- raise $!
146
- ensure
147
- bar.tick if bar
155
+ else
156
+ bar.init if bar
157
+ array.each do |e|
158
+ begin
159
+ yield e
160
+ rescue Exception
161
+ Log.exception $!
162
+ raise $!
163
+ ensure
164
+ bar.tick if bar
165
+ end
148
166
  end
149
167
  end
168
+
169
+ rescue
170
+ error = true
171
+ raise $!
172
+ ensure
173
+ Log::ProgressBar.remove_bar(bar) if bar
174
+ join.call(error) if join
150
175
  end
151
- Log::ProgressBar.remove_bar(bar) if bar
152
- join.call if join
153
176
  end
154
177
 
155
178
  def self.traverse_io_array(io, options = {}, &block)
156
179
  callback, bar, join = Misc.process_options options, :callback, :bar, :join
157
- if File === io and io.closed?
158
- begin
159
- Log.low{"Rewinding stream #{stream_name(io)}"}
160
- io.reopen io.filename, "r"
161
- rescue
162
- Log.exception $!
163
- raise "File closed and could not reopen #{stream_name(io)}"
180
+ begin
181
+ error = false
182
+ if File === io and io.closed?
183
+ begin
184
+ Log.low{"Rewinding stream #{stream_name(io)}"}
185
+ io.reopen io.filename, "r"
186
+ rescue
187
+ Log.exception $!
188
+ raise "File closed and could not reopen #{stream_name(io)}"
189
+ end
164
190
  end
165
- end
166
191
 
167
- if callback
168
- bar.init if bar
169
- while line = io.gets
170
- if line[-1] != "\n"
171
- while c = io.getc
172
- line << c
173
- break if c=="\n"
192
+ if callback
193
+ bar.init if bar
194
+ while line = io.gets
195
+ if line[-1] != "\n"
196
+ while c = io.getc
197
+ line << c
198
+ break if c=="\n"
199
+ end
200
+ end
201
+ begin
202
+ callback.call yield line.chomp
203
+ ensure
204
+ bar.tick if bar
174
205
  end
175
206
  end
176
- begin
177
- callback.call yield line.chomp
178
- ensure
179
- bar.tick if bar
180
- end
181
- end
182
- else
183
- bar.init if bar
184
- while line = io.gets
185
- begin
186
- yield line.chomp
187
- ensure
188
- bar.tick if bar
207
+ else
208
+ bar.init if bar
209
+ while line = io.gets
210
+ begin
211
+ yield line.chomp
212
+ ensure
213
+ bar.tick if bar
214
+ end
189
215
  end
190
216
  end
217
+ rescue
218
+ error = true
219
+ raise $!
220
+ ensure
221
+ Log::ProgressBar.remove_bar(bar) if bar
222
+ join.call(error) if join
191
223
  end
192
- Log::ProgressBar.remove_bar(bar) if bar
193
- join.call if join
194
224
  end
195
225
 
196
226
  def self.traverse_io(io, options = {}, &block)
197
227
  callback, bar, join = Misc.process_options options, :callback, :bar, :join
198
- if File === io and io.closed?
199
- begin
200
- Log.low{"Rewinding stream #{stream_name(io)}"}
201
- io.reopen io.filename, "r"
202
- rescue
203
- Log.exception $!
204
- raise "File closed and could not reopen #{stream_name(io)}"
205
- end
206
- end
207
228
 
208
- options[:monitor] = bar
209
- if callback
210
- bar.init if bar
211
- exception = nil
212
- begin
213
- TSV::Parser.traverse(io, options) do |k,v|
229
+ begin
230
+ error = false
231
+ if File === io and io.closed?
214
232
  begin
215
- callback.call yield k, v
216
- rescue Exception
217
- exception = $!
218
- raise $!
233
+ Log.low{"Rewinding stream #{stream_name(io)}"}
234
+ io.reopen io.filename, "r"
235
+ rescue
236
+ Log.exception $!
237
+ raise "File closed and could not reopen #{stream_name(io)}"
219
238
  end
220
- bar.tick if bar
221
239
  end
222
- ensure
223
- raise exception if exception
240
+
241
+ options[:monitor] = bar
242
+ if callback
243
+ bar.init if bar
244
+ exception = nil
245
+ begin
246
+ TSV::Parser.traverse(io, options) do |k,v|
247
+ begin
248
+ callback.call yield k, v
249
+ rescue Exception
250
+ exception = $!
251
+ raise $!
252
+ end
253
+ bar.tick if bar
254
+ end
255
+ ensure
256
+ raise exception if exception
257
+ end
258
+ else
259
+ TSV::Parser.traverse(io, options.merge(:monitor => bar), &block)
224
260
  end
225
- else
226
- TSV::Parser.traverse(io, options.merge(:monitor => bar), &block)
261
+ rescue
262
+ error = true
263
+ raise $!
264
+ ensure
265
+ Log::ProgressBar.remove_bar(bar) if bar
266
+ join.call(error) if join
227
267
  end
228
- Log::ProgressBar.remove_bar(bar) if bar
229
- join.call if join
230
268
  end
231
269
 
232
270
  def self.traverse_obj(obj, options = {}, &block)
@@ -261,6 +299,7 @@ module TSV
261
299
  end
262
300
  rescue Aborted
263
301
  obj.abort if obj.respond_to? :abort
302
+ raise $!
264
303
  rescue Exception
265
304
  obj.abort if obj.respond_to? :abort
266
305
  raise $!
@@ -380,6 +419,7 @@ module TSV
380
419
  stream.abort if stream.respond_to? :abort
381
420
  stream = obj_stream(options[:into])
382
421
  stream.abort if stream.respond_to? :abort
422
+ q.join
383
423
  raise "Traversal aborted"
384
424
  rescue Exception
385
425
  error = true
@@ -389,6 +429,7 @@ module TSV
389
429
  stream.abort if stream.respond_to? :abort
390
430
  stream = obj_stream(options[:into])
391
431
  stream.abort if stream.respond_to? :abort
432
+ q.join
392
433
  raise $!
393
434
  ensure
394
435
  if bar
@@ -116,10 +116,16 @@ module CMD
116
116
  in_content.join if in_content.respond_to? :join
117
117
  end
118
118
  rescue
119
- parent.raise $!
120
- Process.kill "INT", pid
121
- ensure
122
- sin.close unless sin.closed?
119
+ Log.exception $!
120
+ raise $!
121
+ # begin
122
+ # Process.kill "INT", pid
123
+ # #parent.raise $!
124
+ # ensure
125
+ # raise $!
126
+ # end
127
+ #ensure
128
+ # #sin.close unless sin.closed?
123
129
  end
124
130
  end
125
131
  else
@@ -135,7 +135,7 @@ class RbbtProcessQueue
135
135
  retry
136
136
  rescue Aborted
137
137
  Log.low "Aborting manager thread #{Process.pid}"
138
- raise Aborted
138
+ raise $!
139
139
  rescue Exception
140
140
  raise Exception
141
141
  end
@@ -254,16 +254,19 @@ class RbbtProcessQueue
254
254
  @callback_thread.join
255
255
  error = false
256
256
  rescue Aborted, Interrupt
257
+ exception = $!
257
258
  Log.exception $!
258
- self.abort
259
259
  error = true
260
+ self.abort
260
261
  Log.high "Process queue #{@master_pid} aborted"
261
262
  retry
262
263
  rescue Errno::ESRCH, Errno::ECHILD
263
264
  retry if Misc.pid_exists? @master_pid
264
265
  error = ! @status.success?
265
266
  rescue ProcessFailed
267
+ exception = $!
266
268
  rescue Exception
269
+ exception = $!
267
270
  Log.exception $!
268
271
  retry
269
272
  ensure
@@ -292,6 +295,12 @@ class RbbtProcessQueue
292
295
  ensure
293
296
  self.clean
294
297
  end
298
+
299
+ if exception
300
+ raise exception
301
+ else
302
+ raise "Process queue #{@master_pid} failed"
303
+ end if error
295
304
  end
296
305
  end
297
306
 
@@ -321,8 +330,12 @@ class RbbtProcessQueue
321
330
 
322
331
  def abort
323
332
  _abort
324
- (@callback_thread.raise(Aborted.new); @callback_thread.join) if @callback_thread and @callback_thread.alive?
333
+ @callback_thread.raise(Aborted.new) if @callback_thread and @callback_thread.alive?
325
334
  @aborted = true
335
+ begin
336
+ _join
337
+ rescue
338
+ end
326
339
  end
327
340
 
328
341
  def clean
@@ -117,24 +117,26 @@ module ConcurrentStream
117
117
  end
118
118
 
119
119
  def join
120
- join_threads
121
- join_pids
122
-
123
- join_callback
124
-
125
- @joined = true
126
-
127
- lockfile.unlock if lockfile and lockfile.locked?
128
- close unless closed?
120
+ begin
121
+ join_threads
122
+ join_pids
123
+ join_callback
124
+ close unless closed?
125
+ ensure
126
+ @joined = true
127
+ lockfile.unlock if lockfile and lockfile.locked?
128
+ end
129
129
  end
130
130
 
131
131
  def abort_threads(exception = nil)
132
132
  return unless @threads and @threads.any?
133
- Log.low "Aborting threads (#{Thread.current.inspect}) #{@threads.collect{|t| t.inspect } * ", "}"
133
+ name = Thread.current.inspect
134
+ name = filename if filename
135
+ Log.low "Aborting threads (#{name}) #{@threads.collect{|t| t.inspect } * ", "}"
134
136
 
135
137
  @threads.each do |t|
136
138
  next if t == Thread.current
137
- Log.debug "Aborting thread #{t.inspect} with exception: #{exception}"
139
+ Log.debug "Aborting thread (#{name}) #{t.inspect} with exception: #{exception}"
138
140
  t.raise((exception.nil? ? Aborted.new : exception))
139
141
  end
140
142
 
@@ -142,14 +144,14 @@ module ConcurrentStream
142
144
  next if t == Thread.current
143
145
  if t.alive?
144
146
  sleep 1
145
- Log.low "Kill thread #{t.inspect}"
147
+ Log.low "Kill thread (#{name}) #{t.inspect}"
146
148
  t.kill
147
149
  end
148
150
  begin
149
151
  t.join unless t == Thread.current
150
152
  rescue Aborted
151
153
  rescue Exception
152
- Log.debug "Thread exception: #{$!.message}"
154
+ Log.debug "Thread (#{name}) exception: #{$!.message}"
153
155
  end
154
156
  end
155
157
  end
@@ -219,11 +221,15 @@ module ConcurrentStream
219
221
  end
220
222
 
221
223
  def raise(exception)
222
- threads.each do |thread|
223
- thread.raise exception
224
- end
224
+ begin
225
+ threads.each do |thread|
226
+ thread.raise exception
227
+ end
225
228
 
226
- self.abort
229
+ self.abort
230
+ ensure
231
+ Kernel.raise $!
232
+ end
227
233
  end
228
234
 
229
235
  end
@@ -155,8 +155,6 @@ def self.add_libdir(dir=nil)
155
155
  rescue StopInsist
156
156
  raise $!.exception
157
157
  rescue Aborted, Interrupt
158
- Log.exception $!
159
- Log.stack caller
160
158
  if msg
161
159
  Log.warn("Not Insisting after Aborted: #{$!.message} -- #{msg}")
162
160
  else
@@ -172,10 +170,6 @@ def self.add_libdir(dir=nil)
172
170
  Log.warn("Insisting after exception: #{$!.class} #{$!.message}")
173
171
  end
174
172
 
175
- Log.stack caller
176
- Log.exception $!
177
-
178
-
179
173
  if sleep and try > 0
180
174
  sleep sleep
181
175
  sleep = sleep_array.shift || sleep if sleep_array
@@ -68,7 +68,7 @@ module Misc
68
68
 
69
69
  if do_fork
70
70
 
71
- parent_pid = Process.pid
71
+ #parent_pid = Process.pid
72
72
  pid = Process.fork {
73
73
  purge_pipes(sin)
74
74
  sout.close
@@ -79,7 +79,7 @@ module Misc
79
79
 
80
80
  rescue Exception
81
81
  Log.exception $!
82
- Process.kill :INT, parent_pid
82
+ #Process.kill :INT, parent_pid
83
83
  Kernel.exit! -1
84
84
  end
85
85
  Kernel.exit! 0
@@ -92,7 +92,7 @@ module Misc
92
92
 
93
93
  ConcurrentStream.setup sin, :pair => sout
94
94
 
95
- thread = Thread.new(Thread.current) do |parent|
95
+ thread = Thread.new do
96
96
  begin
97
97
 
98
98
  yield sin
@@ -104,7 +104,7 @@ module Misc
104
104
  rescue Exception
105
105
  Log.medium "Exception in open_pipe: #{$!.message}"
106
106
  Log.exception $!
107
- parent.raise $!
107
+ sin.close
108
108
  raise $!
109
109
  end
110
110
  end
@@ -442,26 +442,34 @@ module Misc
442
442
 
443
443
  def self.sort_stream(stream, header_hash = "#", cmd_args = "-u")
444
444
  Misc.open_pipe do |sin|
445
- begin
446
- stream = TSV.get_stream stream
445
+ stream = TSV.get_stream stream
447
446
 
447
+ line = stream.gets
448
+ while line =~ /^#{header_hash}/ do
449
+ sin.puts line
448
450
  line = stream.gets
449
- while line =~ /^#{header_hash}/ do
450
- sin.puts line
451
- line = stream.gets
452
- end
451
+ end
453
452
 
454
- line_stream = Misc.open_pipe do |line_stream_in|
455
- line_stream_in.puts line
453
+ line_stream = Misc.open_pipe do |line_stream_in|
454
+ line_stream_in.puts line
455
+ begin
456
456
  Misc.consume_stream(stream, false, line_stream_in)
457
+ rescue
458
+ raise $!
457
459
  end
460
+ end
458
461
 
459
- sorted = CMD.cmd("env LC_ALL=C sort #{cmd_args || ""}", :in => line_stream, :pipe => true)
462
+ sorted = CMD.cmd("env LC_ALL=C sort #{cmd_args || ""}", :in => line_stream, :pipe => true)
460
463
 
464
+ begin
461
465
  Misc.consume_stream(sorted, false, sin)
462
466
  rescue
463
- if defined? step and step
464
- step.abort
467
+ begin
468
+ Log.exception $!
469
+ sorted.abort
470
+ stream.abort
471
+ ensure
472
+ raise $!
465
473
  end
466
474
  end
467
475
  end
@@ -236,29 +236,41 @@ class Step
236
236
  respawn = :always if respawn.nil?
237
237
 
238
238
  Misc.bootstrap(list, cpus, :bar => "Bootstrapping dependencies for #{path} [#{cpus}]", :respawn => respawn) do |dep|
239
- Misc.insist do
240
- begin
241
- dep.produce
242
- Log.warn "Error in bootstrap dependency #{dep.path}: #{dep.messages.last}" if dep.error? or dep.aborted?
243
-
244
- rescue Aborted
239
+ begin
240
+ Signal.trap(:INT) do
245
241
  dep.abort
246
- Log.warn "Aborted bootstrap dependency #{dep.path}: #{dep.messages.last}" if dep.error? or dep.aborted?
247
- raise $!
242
+ raise Aborted
243
+ end
248
244
 
249
- rescue RbbtException
250
- if canfail || dep.canfail?
251
- Log.warn "Allowing failing of #{dep.path}: #{dep.messages.last}"
252
- else
253
- Log.warn "NOT Allowing failing of #{dep.path}: #{dep.messages.last}"
254
- dep.exception $!
255
- if dep.recoverable_error?
256
- raise $!
245
+ Misc.insist do
246
+ begin
247
+ dep.produce
248
+ Log.warn "Error in bootstrap dependency #{dep.path}: #{dep.messages.last}" if dep.error? or dep.aborted?
249
+
250
+ rescue Aborted
251
+ dep.abort
252
+ Log.warn "Aborted bootstrap dependency #{dep.path}: #{dep.messages.last}" if dep.error? or dep.aborted?
253
+ raise $!
254
+
255
+ rescue RbbtException
256
+ if canfail || dep.canfail?
257
+ Log.warn "Allowing failing of #{dep.path}: #{dep.messages.last}"
257
258
  else
258
- raise StopInsist.new($!)
259
+ Log.warn "NOT Allowing failing of #{dep.path}: #{dep.messages.last}"
260
+ dep.exception $!
261
+ if dep.recoverable_error?
262
+ dep.abort
263
+ raise $!
264
+ else
265
+ raise StopInsist.new($!)
266
+ end
259
267
  end
260
268
  end
261
269
  end
270
+ rescue
271
+ iif [:ABORTIN, dep]
272
+ dep.abort
273
+ raise $!
262
274
  end
263
275
  nil
264
276
  end
@@ -416,15 +428,9 @@ class Step
416
428
  next
417
429
  end
418
430
 
419
- begin
420
- next if dep.done? or dep.aborted?
421
- rescue
422
- end
431
+ next if dep.done? or dep.aborted?
423
432
 
424
- begin
425
- dep.abort if dep.running?
426
- rescue
427
- end
433
+ dep.abort if dep.running?
428
434
  end
429
435
  kill_children
430
436
  end
@@ -344,7 +344,6 @@ class Step
344
344
  end
345
345
  _clean_finished
346
346
  rescue
347
- Log.exception $!
348
347
  stop_dependencies
349
348
  set_info :pid, nil
350
349
  FileUtils.rm pid_file if File.exist?(pid_file)
@@ -563,15 +562,16 @@ class Step
563
562
  doretry = true
564
563
  begin
565
564
  return if done?
566
- stop_dependencies
567
- abort_stream
568
565
  abort_pid if running?
566
+ abort_stream
567
+ stop_dependencies
569
568
  rescue Aborted, Interrupt
570
569
  Log.medium{"#{Log.color :red, "Aborting ABORTED RETRY"} #{Log.color :blue, path}"}
571
570
  if doretry
572
571
  doretry = false
573
572
  retry
574
573
  end
574
+ raise $!
575
575
  rescue Exception
576
576
  if doretry
577
577
  doretry = false
@@ -269,4 +269,24 @@ line4
269
269
  assert_equal text, lines.to_a * ""
270
270
  end
271
271
  end
272
+
273
+ def test_sort
274
+ assert_raise RbbtException do
275
+ io = Misc.open_pipe do |sin|
276
+ sin.puts "#START"
277
+ 20.times do
278
+ sin.puts rand(1000).to_s
279
+ sleep 0.1
280
+ end
281
+ raise RbbtException
282
+ end
283
+
284
+ sio = Misc.sort_stream(io)
285
+ begin
286
+ Misc.consume_stream(sio, false, STDOUT)
287
+ rescue
288
+ Log.exception $!
289
+ end
290
+ end
291
+ end
272
292
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbbt-util
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.23.7
4
+ version: 5.23.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Vazquez