scout-gear 8.0.0 → 8.1.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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +26 -9
  3. data/Rakefile +6 -1
  4. data/VERSION +1 -1
  5. data/bin/scout +15 -4
  6. data/doc/lib/scout/path.md +35 -0
  7. data/doc/lib/scout/workflow/task.md +13 -0
  8. data/lib/scout/cmd.rb +23 -24
  9. data/lib/scout/concurrent_stream.rb +36 -19
  10. data/lib/scout/exceptions.rb +10 -0
  11. data/lib/scout/log/color.rb +11 -11
  12. data/lib/scout/log/progress/report.rb +7 -5
  13. data/lib/scout/log/progress/util.rb +3 -0
  14. data/lib/scout/log/trap.rb +3 -3
  15. data/lib/scout/log.rb +64 -36
  16. data/lib/scout/meta_extension.rb +34 -0
  17. data/lib/scout/misc/digest.rb +11 -2
  18. data/lib/scout/misc/format.rb +12 -7
  19. data/lib/scout/misc/monitor.rb +11 -0
  20. data/lib/scout/misc/system.rb +48 -0
  21. data/lib/scout/named_array.rb +8 -0
  22. data/lib/scout/offsite/ssh.rb +171 -0
  23. data/lib/scout/offsite/step.rb +83 -0
  24. data/lib/scout/offsite/sync.rb +55 -0
  25. data/lib/scout/offsite.rb +3 -0
  26. data/lib/scout/open/lock.rb +5 -24
  27. data/lib/scout/open/remote.rb +12 -1
  28. data/lib/scout/open/stream.rb +110 -122
  29. data/lib/scout/open/util.rb +9 -0
  30. data/lib/scout/open.rb +5 -4
  31. data/lib/scout/path/find.rb +15 -10
  32. data/lib/scout/path/util.rb +5 -0
  33. data/lib/scout/persist/serialize.rb +3 -3
  34. data/lib/scout/persist.rb +1 -1
  35. data/lib/scout/resource/path.rb +4 -0
  36. data/lib/scout/resource/util.rb +10 -4
  37. data/lib/scout/tsv/dumper.rb +2 -0
  38. data/lib/scout/tsv/index.rb +28 -86
  39. data/lib/scout/tsv/open.rb +35 -14
  40. data/lib/scout/tsv/parser.rb +9 -2
  41. data/lib/scout/tsv/persist/tokyocabinet.rb +2 -0
  42. data/lib/scout/tsv/stream.rb +204 -0
  43. data/lib/scout/tsv/transformer.rb +11 -0
  44. data/lib/scout/tsv.rb +9 -2
  45. data/lib/scout/work_queue/worker.rb +2 -2
  46. data/lib/scout/work_queue.rb +36 -12
  47. data/lib/scout/workflow/definition.rb +2 -1
  48. data/lib/scout/workflow/deployment/orchestrator.rb +245 -0
  49. data/lib/scout/workflow/deployment.rb +1 -0
  50. data/lib/scout/workflow/step/dependencies.rb +37 -11
  51. data/lib/scout/workflow/step/file.rb +5 -0
  52. data/lib/scout/workflow/step/info.rb +5 -3
  53. data/lib/scout/workflow/step/load.rb +1 -1
  54. data/lib/scout/workflow/step/provenance.rb +1 -0
  55. data/lib/scout/workflow/step/status.rb +6 -8
  56. data/lib/scout/workflow/step.rb +75 -30
  57. data/lib/scout/workflow/task/dependencies.rb +114 -0
  58. data/lib/scout/workflow/task/inputs.rb +27 -13
  59. data/lib/scout/workflow/task.rb +9 -108
  60. data/lib/scout/workflow/usage.rb +40 -12
  61. data/lib/scout/workflow.rb +4 -2
  62. data/lib/scout-gear.rb +2 -0
  63. data/lib/scout.rb +6 -0
  64. data/scout-gear.gemspec +32 -7
  65. data/scout_commands/doc +37 -0
  66. data/scout_commands/find +1 -0
  67. data/scout_commands/offsite +30 -0
  68. data/scout_commands/update +29 -0
  69. data/scout_commands/workflow/info +15 -3
  70. data/scout_commands/workflow/install +102 -0
  71. data/scout_commands/workflow/task +26 -5
  72. data/test/scout/offsite/test_ssh.rb +15 -0
  73. data/test/scout/offsite/test_step.rb +33 -0
  74. data/test/scout/offsite/test_sync.rb +36 -0
  75. data/test/scout/offsite/test_task.rb +0 -0
  76. data/test/scout/resource/test_path.rb +6 -0
  77. data/test/scout/test_named_array.rb +6 -0
  78. data/test/scout/test_persist.rb +3 -2
  79. data/test/scout/test_tsv.rb +17 -0
  80. data/test/scout/test_work_queue.rb +63 -41
  81. data/test/scout/tsv/persist/test_adapter.rb +1 -1
  82. data/test/scout/tsv/test_index.rb +14 -0
  83. data/test/scout/tsv/test_parser.rb +14 -0
  84. data/test/scout/tsv/test_stream.rb +200 -0
  85. data/test/scout/tsv/test_transformer.rb +12 -0
  86. data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
  87. data/test/scout/workflow/step/test_dependencies.rb +68 -0
  88. data/test/scout/workflow/step/test_info.rb +18 -0
  89. data/test/scout/workflow/step/test_status.rb +0 -1
  90. data/test/scout/workflow/task/test_dependencies.rb +355 -0
  91. data/test/scout/workflow/task/test_inputs.rb +53 -0
  92. data/test/scout/workflow/test_definition.rb +18 -0
  93. data/test/scout/workflow/test_documentation.rb +24 -0
  94. data/test/scout/workflow/test_step.rb +109 -0
  95. data/test/scout/workflow/test_task.rb +0 -287
  96. data/test/test_scout.rb +9 -0
  97. metadata +83 -5
  98. data/scout_commands/workflow/task_old +0 -706
@@ -0,0 +1,3 @@
1
+ require_relative 'offsite/ssh'
2
+ require_relative 'offsite/step'
3
+ require_relative 'offsite/sync'
@@ -4,27 +4,13 @@ require_relative '../exceptions'
4
4
  require_relative 'lock/lockfile'
5
5
 
6
6
  module Open
7
- def self.thread_in_lock(t)
8
- t.backtrace.select{|l| l.include?("lockfile") }.any?
9
- end
10
-
11
- def self.unlock_thread(t, exception = nil)
12
- while t.alive? && t.backtrace.select{|l| l.include?("lockfile") }.any?
13
- iii :UNLOCK
14
- t.raise(exception)
15
- Log.stack t.backtrace
16
- locks = t["locks"]
17
- return if locks.nil? || locks.empty?
18
- locks.each do |lock|
19
- lock.unlock if lock.locked?
20
- Open.rm(lock.path)
21
- end
22
- iii Thread.current
23
- Thread.list.each{|t| iii [t, t["locks"]]; Log.stack t.backtrace }
24
- Log.stack t.backtrace
25
- end
7
+ def self.init_lock
8
+ Lockfile.refresh = 2
9
+ Lockfile.max_age = 30
10
+ Lockfile.suspend = 4
26
11
  end
27
12
 
13
+ self.init_lock
28
14
 
29
15
  def self.lock(file, unlock = true, options = {})
30
16
  unlock, options = true, unlock if Hash === unlock
@@ -57,9 +43,6 @@ module Open
57
43
  raise LockInterrupted
58
44
  end
59
45
 
60
- iii Thread.current["lock_exception"] if Thread.current["lock_exception"]
61
- raise Thread.current["lock_exception"] if Thread.current["lock_exception"]
62
-
63
46
  res = nil
64
47
 
65
48
  begin
@@ -73,8 +56,6 @@ module Open
73
56
  if lockfile.locked?
74
57
  lockfile.unlock
75
58
  end
76
- iii Thread.current["lock_exception"] if Thread.current["lock_exception"]
77
- raise Thread.current["lock_exception"] if Thread.current["lock_exception"]
78
59
  rescue Exception
79
60
  Log.warn "Exception unlocking: #{lockfile.path}"
80
61
  Log.exception $!
@@ -23,7 +23,11 @@ module Open
23
23
  m = file.match(/ssh:\/\/([^:]+):(.*)/)
24
24
  server = m[1]
25
25
  file = m[2]
26
- CMD.cmd("ssh '#{server}' cat '#{file}'", :pipe => true, :autojoin => true)
26
+ if server == 'localhost'
27
+ Open.open(file)
28
+ else
29
+ CMD.cmd("ssh '#{server}' cat '#{file}'", :pipe => true, :autojoin => true)
30
+ end
27
31
  end
28
32
 
29
33
  def self.wget(url, options = {})
@@ -121,4 +125,11 @@ module Open
121
125
  filename = cache_file(url, options)
122
126
  Open.open(filename)
123
127
  end
128
+
129
+ def self.scp(source_file, target_file, target: nil, source: nil)
130
+ CMD.cmd_log("ssh #{target} mkdir -p #{File.dirname(target_file)}")
131
+ target_file = [target, target_file] * ":" if target && ! target_file.start_with?(target+":")
132
+ source_file = [source, source_file] * ":" if source && ! source_file.start_with?(source+":")
133
+ CMD.cmd_log("scp -r '#{ source_file }' #{target_file}")
134
+ end
124
135
  end
@@ -3,7 +3,7 @@ module Open
3
3
 
4
4
  class << self
5
5
  attr_accessor :sensible_write_lock_dir
6
-
6
+
7
7
  def sensible_write_lock_dir
8
8
  @sensible_write_lock_dir ||= Path.setup("tmp/sensible_write_locks").find
9
9
  end
@@ -18,7 +18,7 @@ module Open
18
18
 
19
19
  def self.consume_stream(io, in_thread = false, into = nil, into_close = true, &block)
20
20
  return if Path === io
21
- return unless io.respond_to? :read
21
+ return unless io.respond_to? :read
22
22
 
23
23
  if io.respond_to? :closed? and io.closed?
24
24
  io.join if io.respond_to? :join
@@ -46,12 +46,12 @@ module Open
46
46
  begin
47
47
  into = into.find if Path === into
48
48
 
49
- if String === into
49
+ if String === into
50
50
  dir = File.dirname(into)
51
51
  Open.mkdir dir unless File.exist?(dir)
52
- into_path, into = into, File.open(into, 'w')
52
+ into_path, into = into, File.open(into, 'w')
53
53
  end
54
-
54
+
55
55
  into_close = false unless into.respond_to? :close
56
56
 
57
57
  while c = io.read(BLOCK_SIZE)
@@ -66,6 +66,7 @@ module Open
66
66
  into.close if into and into_close and not into.closed?
67
67
  block.call if block_given?
68
68
 
69
+ Log.debug "Consume stream done #{Log.fingerprint io} -> #{Log.fingerprint(into_path ||into)}"
69
70
  last_c
70
71
  rescue Aborted
71
72
  Thread.current["exception"] = true
@@ -81,7 +82,7 @@ module Open
81
82
  into.close if into.respond_to?(:closed?) && ! into.closed?
82
83
  into_path = into if into_path.nil? && String === into
83
84
  if into_path and File.exist?(into_path)
84
- FileUtils.rm into_path
85
+ FileUtils.rm into_path
85
86
  end
86
87
  raise exception
87
88
  end
@@ -92,7 +93,7 @@ module Open
92
93
  force = IndiferentHash.process_options options, :force
93
94
 
94
95
  if File.exist?(path) and not force
95
- Open.consume_stream content
96
+ Open.consume_stream content
96
97
  return
97
98
  end
98
99
 
@@ -107,10 +108,11 @@ module Open
107
108
 
108
109
  if File.exist? path and not force
109
110
  Log.warn "Path exists in sensible_write, not forcing update: #{ path }"
110
- Open.consume_stream content
111
+ Open.consume_stream content
111
112
  else
112
113
  FileUtils.mkdir_p File.dirname(tmp_path) unless File.directory?(File.dirname(tmp_path))
113
114
  FileUtils.rm_f tmp_path if File.exist? tmp_path
115
+ Log.low "Sensible write stream #{Log.fingerprint content} -> #{Log.fingerprint path}" if IO === content
114
116
  begin
115
117
  case
116
118
  when block_given?
@@ -122,7 +124,7 @@ module Open
122
124
  while block = content.read(BLOCK_SIZE)
123
125
  f.write block
124
126
  break if content.closed?
125
- end
127
+ end
126
128
  end
127
129
  else
128
130
  File.open(tmp_path, 'wb') do |f| end
@@ -139,8 +141,7 @@ module Open
139
141
  Open.touch path if File.exist? path
140
142
  content.join if content.respond_to?(:join) and not Path === content and not (content.respond_to?(:joined?) && content.joined?)
141
143
 
142
- Open.notify_write(path)
143
- Log.debug "Done sensible write: [#{Process.pid}] -- #{ path }"
144
+ Open.notify_write(path)
144
145
  rescue Aborted
145
146
  Log.low "Aborted sensible_write -- #{ Log.reset << path }"
146
147
  content.abort if content.respond_to? :abort
@@ -174,7 +175,7 @@ module Open
174
175
 
175
176
  [sout, sin]
176
177
  end
177
- Log.debug{"Creating pipe #{[Log.fingerprint(res.last), Log.fingerprint(res.first)] * " => "}"}
178
+ Log.low{"Creating pipe #{[Log.fingerprint(res.last), Log.fingerprint(res.first)] * " -> "}"}
178
179
  res
179
180
  end
180
181
 
@@ -214,14 +215,13 @@ module Open
214
215
 
215
216
  if do_fork
216
217
 
217
- #parent_pid = Process.pid
218
218
  pid = Process.fork {
219
219
  begin
220
220
  purge_pipes(sin)
221
221
  sout.close
222
222
 
223
223
  yield sin
224
- sin.close if close and not sin.closed?
224
+ sin.close if close and not sin.closed?
225
225
 
226
226
  rescue Exception
227
227
  Log.exception $!
@@ -237,34 +237,20 @@ module Open
237
237
  ConcurrentStream.setup sin, :pair => sout
238
238
  ConcurrentStream.setup sout, :pair => sin
239
239
 
240
- thread = Thread.new do
240
+ thread = Thread.new do
241
241
  begin
242
- Thread.current.report_on_exception = false
243
- Thread.current["name"] = "Pipe input #{Log.fingerprint sin} => #{Log.fingerprint sout}"
244
-
245
- yield sin
242
+ ConcurrentStream.process_stream(sin, :message => "Open pipe") do
243
+ Thread.current.report_on_exception = false
244
+ Thread.current["name"] = "Pipe input #{Log.fingerprint sin} => #{Log.fingerprint sout}"
246
245
 
247
- sin.close if close and not sin.closed? and not sin.aborted?
248
- rescue Aborted
249
- Log.low "Aborted open_pipe: #{$!.message}"
250
- raise $!
251
- rescue Exception
252
- Log.low "Exception in open_pipe: #{$!.message}"
253
- begin
254
- sout.threads.delete(Thread.current)
255
- sout.pair = []
256
- sout.abort($!) if sout.respond_to?(:abort)
257
- sin.threads.delete(Thread.current)
258
- sin.pair = []
259
- sin.abort($!) if sin.respond_to?(:abort)
260
- ensure
261
- raise $!
246
+ yield sin
262
247
  end
263
248
  end
264
249
  end
265
250
 
266
251
  sin.threads = [thread]
267
252
  sout.threads = [thread]
253
+
268
254
  Thread.pass until thread["name"]
269
255
  end
270
256
 
@@ -274,12 +260,14 @@ module Open
274
260
  def self.tee_stream_thread_multiple(stream, num = 2)
275
261
  in_pipes = []
276
262
  out_pipes = []
277
- num.times do
263
+ num.times do
278
264
  sout, sin = Open.pipe
279
265
  in_pipes << sin
280
266
  out_pipes << sout
281
267
  end
282
268
 
269
+ Log.low("Tee stream #{Log.fingerprint stream} -> #{Log.fingerprint out_pipes}")
270
+
283
271
  filename = stream.filename if stream.respond_to? :filename
284
272
 
285
273
  splitter_thread = Thread.new(Thread.current) do |parent|
@@ -291,7 +279,7 @@ module Open
291
279
  while block = stream.read(BLOCK_SIZE)
292
280
 
293
281
  in_pipes.each_with_index do |sin,i|
294
- begin
282
+ begin
295
283
  sin.write block
296
284
  rescue IOError
297
285
  Log.warn("Tee stream #{i} #{Log.fingerprint stream} IOError: #{$!.message} (#{Log.fingerprint sin})");
@@ -299,13 +287,12 @@ module Open
299
287
  rescue
300
288
  Log.warn("Tee stream #{i} #{Log.fingerprint stream} Exception: #{$!.message} (#{Log.fingerprint sin})");
301
289
  raise $!
302
- end unless skip[i]
290
+ end unless skip[i]
303
291
  end
304
292
  break if stream.closed?
305
293
  end
306
294
 
307
295
  stream.join if stream.respond_to? :join
308
- stream.close unless stream.closed?
309
296
  in_pipes.first.close unless in_pipes.first.closed?
310
297
  rescue Aborted, Interrupt
311
298
  stream.abort if stream.respond_to?(:abort) && ! stream.aborted?
@@ -348,18 +335,32 @@ module Open
348
335
  end
349
336
  end
350
337
 
351
- out_pipes.each do |sout|
352
- ConcurrentStream.setup sout, :threads => splitter_thread, :filename => filename, :pair => stream
353
- end
354
338
  Thread.pass until splitter_thread["name"]
355
339
 
356
340
  main_pipe = out_pipes.first
357
- main_pipe.autojoin = true
358
341
 
359
- main_pipe.callback = Proc.new do
360
- stream.join if stream.respond_to? :join
361
- in_pipes[1..-1].each do |sin|
362
- sin.close unless sin.closed?
342
+ ConcurrentStream.setup(main_pipe, :threads => [splitter_thread], :filename => filename, :autojoin => true)
343
+
344
+ out_pipes[1..-1].each do |sout|
345
+ ConcurrentStream.setup sout, :filename => filename, :threads => [splitter_thread]
346
+ end
347
+
348
+ main_pipe.callback = proc do
349
+ begin
350
+ stream.join if stream.respond_to?(:join) && ! stream.joined?
351
+ in_pipes[1..-1].each do |sin|
352
+ sin.close unless sin.closed?
353
+ end
354
+ rescue
355
+ main_pipe.abort_callback.call($!)
356
+ raise $!
357
+ end
358
+ end
359
+
360
+ main_pipe.abort_callback = proc do |exception|
361
+ stream.abort(exception)
362
+ out_pipes[1..-1].each do |sout|
363
+ sout.abort(exception)
363
364
  end
364
365
  end
365
366
 
@@ -378,7 +379,7 @@ module Open
378
379
  str = nil
379
380
  Thread.pass while IO.select([stream],nil,nil,1).nil?
380
381
  while not str = stream.read(size)
381
- IO.select([stream],nil,nil,1)
382
+ IO.select([stream],nil,nil,1)
382
383
  Thread.pass
383
384
  raise ClosedStream if stream.eof?
384
385
  end
@@ -403,102 +404,89 @@ module Open
403
404
  str
404
405
  end
405
406
 
406
- def self.sort_stream(stream, header_hash = "#", cmd_args = "-u")
407
- Open.open_pipe do |sin|
408
- line = stream.gets
409
- while line =~ /^#{header_hash}/ do
410
- sin.puts line
407
+ def self.sort_stream(stream, header_hash: "#", cmd_args: "-u", memory: false)
408
+ sout = Open.open_pipe do |sin|
409
+ ConcurrentStream.process_stream(stream) do
411
410
  line = stream.gets
412
- end
411
+ while line && line.start_with?(header_hash) do
412
+ sin.puts line
413
+ line = stream.gets
414
+ end
413
415
 
414
- line_stream = Open.open_pipe do |line_stream_in|
415
- line_stream_in.puts line
416
- begin
416
+ line_stream = Open.open_pipe do |line_stream_in|
417
+ line_stream_in.puts line if line
417
418
  Open.consume_stream(stream, false, line_stream_in)
418
- rescue
419
- raise $!
420
419
  end
421
- end
420
+ Log.low "Sub-sort stream #{Log.fingerprint stream} -> #{Log.fingerprint line_stream}"
422
421
 
423
- sorted = CMD.cmd("env LC_ALL=C sort #{cmd_args || ""}", :in => line_stream, :pipe => true)
424
-
425
- begin
426
- Open.consume_stream(sorted, false, sin)
427
- rescue
428
- Log.exception $!
429
- begin
430
- sorted.raise($!) if sorted.respond_to? :raise
431
- stream.raise($!) if stream.respond_to? :raise
432
- ensure
433
- raise $!
422
+ if memory
423
+ line_stream.read.split("\n").sort.each do |line|
424
+ sin.puts line
425
+ end
426
+ else
427
+ io = CMD.cmd("env LC_ALL=C sort #{cmd_args || ""}", :in => line_stream, :pipe => true)
428
+ Open.consume_stream(io, false, sin)
434
429
  end
435
430
  end
436
431
  end
432
+ Log.low "Sort #{Log.fingerprint stream} -> #{Log.fingerprint sout}"
433
+ sout
437
434
  end
438
435
 
439
- def self.process_stream(s)
440
- begin
441
- yield s
442
- s.close if s.respond_to?(:close) && ! s.closed?
443
- s.join if s.respond_to?(:join)
444
- rescue
445
- s.abort($!) if s.respond_to? :abort
446
- raise $!
447
- end
448
- end
449
-
436
+ #def self.sort_stream(stream, header_hash = "#", cmd_args = "-u")
437
+ # StringIO.new stream.read.split("\n").sort.uniq * "\n"
438
+ #end
450
439
 
451
440
  def self.collapse_stream(s, line: nil, sep: "\t", header: nil, &block)
452
441
  sep ||= "\t"
453
442
  Open.open_pipe do |sin|
443
+
454
444
  sin.puts header if header
455
- process_stream(s) do |s|
456
- line ||= s.gets
457
445
 
458
- current_parts = []
459
- while line
460
- key, *parts = line.chomp.split(sep, -1)
461
- case
462
- when key.nil?
463
- when current_parts.nil?
464
- current_parts = parts
465
- current_key = key
466
- when current_key == key
467
- parts.each_with_index do |part,i|
468
- if current_parts[i].nil?
469
- current_parts[i] = "|" << part
470
- else
471
- current_parts[i] = current_parts[i] << "|" << part
472
- end
446
+ line ||= s.gets
447
+
448
+ current_parts = []
449
+ while line
450
+ key, *parts = line.chomp.split(sep, -1)
451
+ case
452
+ when key.nil?
453
+ when current_parts.nil?
454
+ current_parts = parts
455
+ current_key = key
456
+ when current_key == key
457
+ parts.each_with_index do |part,i|
458
+ if current_parts[i].nil?
459
+ current_parts[i] = "|" << part
460
+ else
461
+ current_parts[i] = current_parts[i] << "|" << part
473
462
  end
463
+ end
474
464
 
475
- (parts.length..current_parts.length-1).to_a.each do |pos|
476
- current_parts[pos] = current_parts[pos] << "|" << ""
477
- end
478
- when current_key.nil?
479
- current_key = key
480
- current_parts = parts
481
- when current_key != key
482
- if block_given?
483
- res = block.call(current_parts)
484
- sin.puts [current_key, res] * sep
485
- else
486
- sin.puts [current_key, current_parts].flatten * sep
487
- end
488
- current_key = key
489
- current_parts = parts
465
+ (parts.length..current_parts.length-1).to_a.each do |pos|
466
+ current_parts[pos] = current_parts[pos] << "|" << ""
490
467
  end
491
- line = s.gets
468
+ when current_key.nil?
469
+ current_key = key
470
+ current_parts = parts
471
+ when current_key != key
472
+ if block_given?
473
+ res = block.call(current_parts)
474
+ sin.puts [current_key, res] * sep
475
+ else
476
+ sin.puts [current_key, current_parts].flatten * sep
477
+ end
478
+ current_key = key
479
+ current_parts = parts
492
480
  end
493
-
494
- if block_given?
495
- res = block.call(current_parts)
496
- sin.puts [current_key, res] * sep
497
- else
498
- sin.puts [current_key, current_parts].flatten * sep
499
- end unless current_key.nil?
481
+ line = s.gets
500
482
  end
483
+
484
+ if block_given?
485
+ res = block.call(current_parts)
486
+ sin.puts [current_key, res] * sep
487
+ else
488
+ sin.puts [current_key, current_parts].flatten * sep
489
+ end unless current_key.nil?
501
490
  end
502
491
  end
503
-
504
492
  end
@@ -68,6 +68,15 @@ module Open
68
68
  !! (file =~ /\.zip$/)
69
69
  end
70
70
 
71
+ def self.is_stream?(obj)
72
+ IO === obj || StringIO === obj
73
+ end
74
+
75
+ def self.has_stream?(obj)
76
+ obj.respond_to?(:stream)
77
+ end
78
+
79
+
71
80
  def self.notify_write(file)
72
81
  begin
73
82
  notification_file = file + '.notify'
data/lib/scout/open.rb CHANGED
@@ -21,6 +21,8 @@ module Open
21
21
  end
22
22
 
23
23
  def self.get_stream(file, mode = 'r')
24
+ return file if Open.is_stream?(file)
25
+ return file.stream if Open.has_stream?(file)
24
26
  file = file.find if Path === file
25
27
 
26
28
  return Open.ssh(file) if Open.ssh?(file)
@@ -56,11 +58,11 @@ module Open
56
58
  def self.open(file, options = {})
57
59
  if IO === file || StringIO === file
58
60
  if block_given?
59
- res = yield file
61
+ res = yield file
60
62
  file.close
61
63
  return res
62
64
  else
63
- return file
65
+ return file
64
66
  end
65
67
  end
66
68
 
@@ -163,7 +165,6 @@ module Open
163
165
  raise "Content unknown #{Log.fingerprint content}"
164
166
  end
165
167
 
166
- notify_write(file)
168
+ notify_write(file)
167
169
  end
168
-
169
170
  end
@@ -34,6 +34,7 @@ module Path
34
34
 
35
35
  def self.follow(path, map, map_name = nil)
36
36
  file = map.sub('{PKGDIR}', path.pkgdir.respond_to?(:pkgdir) ? path.pkgdir.pkgdir || Path.default_pkgdir : path.pkgdir || Path.default_pkgdir).
37
+ sub('{HOME}', ENV["HOME"]).
37
38
  sub('{RESOURCE}', path.pkgdir.to_s).
38
39
  sub('{PWD}', FileUtils.pwd).
39
40
  sub('{TOPLEVEL}', path._toplevel).
@@ -59,16 +60,17 @@ module Path
59
60
 
60
61
  def self.path_maps
61
62
  @@path_maps ||= IndiferentHash.setup({
62
- :current => File.join("{PWD}", "{TOPLEVEL}", "{SUBPATH}"),
63
- :user => File.join(ENV['HOME'], ".{PKGDIR}", "{TOPLEVEL}", "{SUBPATH}"),
64
- :global => File.join('/', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
65
- :usr => File.join('/usr/', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
66
- :local => File.join('/usr/local', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
67
- :fast => File.join('/fast', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
68
- :cache => File.join('/cache', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
69
- :bulk => File.join('/bulk', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
70
- :lib => File.join('{LIBDIR}', "{TOPLEVEL}", "{SUBPATH}"),
71
- :base => File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}", "{SUBPATH}"),
63
+ :current => "{PWD}/{TOPLEVEL}/{SUBPATH}",
64
+ :user => "{HOME}/.{PKGDIR}/{TOPLEVEL}/{SUBPATH}",
65
+ :global => '/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
66
+ :usr => '/usr/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
67
+ :local => '/usr/local/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
68
+ :fast => '/fast/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
69
+ :cache => '/cache/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
70
+ :bulk => '/bulk/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
71
+ :lib => '{LIBDIR}/{TOPLEVEL}/{SUBPATH}',
72
+ :scout_gear => File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}/{SUBPATH}"),
73
+ :tmp => '/tmp/{PKGDIR}/{TOPLEVEL}/{SUBPATH}',
72
74
  :default => :user
73
75
  })
74
76
  end
@@ -127,6 +129,9 @@ module Path
127
129
  def follow(map_name = :default, annotate = true)
128
130
  IndiferentHash.setup(path_maps)
129
131
  map = path_maps[map_name] || Path.path_maps[map_name]
132
+ if map.nil? && String === map_name
133
+ map = File.join(map_name, '{TOPLEVEL}/{SUBPATH}')
134
+ end
130
135
  raise "Map not found #{Log.fingerprint map_name} not in #{Log.fingerprint path_maps.keys}" if map.nil?
131
136
  while Symbol === map
132
137
  map_name = map
@@ -82,6 +82,11 @@ module Path
82
82
  self.annotate(self + ".#{extension}")
83
83
  end
84
84
 
85
+ def unset_extension
86
+ self.annotate(self.split(".")[0..-2] * ".")
87
+ end
88
+
89
+
85
90
  # Is 'file' newer than 'path'? return non-true if path is newer than file
86
91
  def self.newer?(path, file, by_link = false)
87
92
  return true if not Open.exists?(file)
@@ -20,7 +20,7 @@ module Persist
20
20
  type = type.to_sym if String === type
21
21
  type = SERIALIZER if type == :serializer
22
22
  case type
23
- when nil, :string, :integer, :float, :boolean, :file, :path, :select, :folder
23
+ when nil, :string, :text, :integer, :float, :boolean, :file, :path, :select, :folder, :binary
24
24
  if IO === content || StringIO === content
25
25
  content.read
26
26
  else
@@ -49,7 +49,7 @@ module Persist
49
49
  type = SERIALIZER if type == :serializer
50
50
 
51
51
  case type
52
- when nil, :string, :file, :stream, :select, :folder
52
+ when nil, :string, :text, :file, :stream, :select, :folder
53
53
  serialized
54
54
  when :path
55
55
  Path.setup(serialized)
@@ -58,7 +58,7 @@ module Persist
58
58
  when :float
59
59
  serialized.to_f
60
60
  when :boolean
61
- TRUE_STRINGS.include? serialized
61
+ TRUE_STRINGS.include? serialized.strip
62
62
  when :array
63
63
  serialized.split("\n")
64
64
  when :yaml
data/lib/scout/persist.rb CHANGED
@@ -80,7 +80,7 @@ module Persist
80
80
  pres = Persist.save(res, file, type)
81
81
  res = pres unless pres.nil?
82
82
  end
83
- rescue
83
+ rescue Exception
84
84
  Thread.handle_interrupt(Exception => :never) do
85
85
  if Open.exist?(file)
86
86
  Log.debug "Failed persistence #{file} - erasing"
@@ -47,6 +47,10 @@ module Path
47
47
  Resource.relocate(self)
48
48
  end
49
49
 
50
+ def identify
51
+ Resource.identify(self)
52
+ end
53
+
50
54
  def open(*args, &block)
51
55
  produce
52
56
  Open.open(self, *args, &block)