scout-gear 8.0.0 → 9.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +48 -9
  3. data/Rakefile +6 -1
  4. data/VERSION +1 -1
  5. data/bin/scout +16 -4
  6. data/doc/lib/scout/path.md +35 -0
  7. data/doc/lib/scout/workflow/task.md +13 -0
  8. data/lib/rbbt-scout.rb +2 -1
  9. data/lib/scout/cmd.rb +32 -29
  10. data/lib/scout/concurrent_stream.rb +36 -19
  11. data/lib/scout/exceptions.rb +10 -0
  12. data/lib/scout/indiferent_hash.rb +17 -0
  13. data/lib/scout/log/color.rb +11 -11
  14. data/lib/scout/log/progress/report.rb +8 -5
  15. data/lib/scout/log/progress/util.rb +3 -0
  16. data/lib/scout/log/trap.rb +3 -3
  17. data/lib/scout/log.rb +67 -36
  18. data/lib/scout/meta_extension.rb +34 -0
  19. data/lib/scout/misc/digest.rb +11 -2
  20. data/lib/scout/misc/filesystem.rb +2 -3
  21. data/lib/scout/misc/format.rb +12 -7
  22. data/lib/scout/misc/monitor.rb +11 -0
  23. data/lib/scout/misc/system.rb +48 -0
  24. data/lib/scout/named_array.rb +8 -0
  25. data/lib/scout/offsite/ssh.rb +174 -0
  26. data/lib/scout/offsite/step.rb +100 -0
  27. data/lib/scout/offsite/sync.rb +55 -0
  28. data/lib/scout/offsite.rb +3 -0
  29. data/lib/scout/open/lock.rb +5 -24
  30. data/lib/scout/open/remote.rb +12 -1
  31. data/lib/scout/open/stream.rb +109 -122
  32. data/lib/scout/open/util.rb +9 -0
  33. data/lib/scout/open.rb +12 -11
  34. data/lib/scout/path/find.rb +15 -10
  35. data/lib/scout/path/util.rb +5 -0
  36. data/lib/scout/path.rb +1 -1
  37. data/lib/scout/persist/serialize.rb +4 -4
  38. data/lib/scout/persist.rb +1 -1
  39. data/lib/scout/resource/open.rb +8 -0
  40. data/lib/scout/resource/path.rb +16 -9
  41. data/lib/scout/resource/software.rb +4 -2
  42. data/lib/scout/resource/util.rb +10 -4
  43. data/lib/scout/resource.rb +2 -0
  44. data/lib/scout/tsv/dumper.rb +5 -1
  45. data/lib/scout/tsv/index.rb +28 -86
  46. data/lib/scout/tsv/open.rb +35 -14
  47. data/lib/scout/tsv/parser.rb +22 -5
  48. data/lib/scout/tsv/persist/tokyocabinet.rb +2 -0
  49. data/lib/scout/tsv/stream.rb +204 -0
  50. data/lib/scout/tsv/transformer.rb +11 -0
  51. data/lib/scout/tsv.rb +9 -2
  52. data/lib/scout/work_queue/worker.rb +2 -2
  53. data/lib/scout/work_queue.rb +37 -12
  54. data/lib/scout/workflow/definition.rb +2 -1
  55. data/lib/scout/workflow/deployment/orchestrator.rb +254 -0
  56. data/lib/scout/workflow/deployment.rb +1 -0
  57. data/lib/scout/workflow/step/dependencies.rb +46 -14
  58. data/lib/scout/workflow/step/file.rb +5 -0
  59. data/lib/scout/workflow/step/info.rb +13 -3
  60. data/lib/scout/workflow/step/inputs.rb +5 -0
  61. data/lib/scout/workflow/step/load.rb +1 -1
  62. data/lib/scout/workflow/step/provenance.rb +1 -0
  63. data/lib/scout/workflow/step/status.rb +27 -9
  64. data/lib/scout/workflow/step.rb +82 -30
  65. data/lib/scout/workflow/task/dependencies.rb +116 -0
  66. data/lib/scout/workflow/task/inputs.rb +36 -17
  67. data/lib/scout/workflow/task.rb +12 -109
  68. data/lib/scout/workflow/usage.rb +57 -41
  69. data/lib/scout/workflow.rb +19 -13
  70. data/lib/scout-gear.rb +2 -0
  71. data/lib/scout.rb +6 -0
  72. data/scout-gear.gemspec +38 -7
  73. data/scout_commands/doc +37 -0
  74. data/scout_commands/find +1 -0
  75. data/scout_commands/offsite +30 -0
  76. data/scout_commands/resource/produce +66 -0
  77. data/scout_commands/template +52 -0
  78. data/scout_commands/update +29 -0
  79. data/scout_commands/workflow/info +15 -3
  80. data/scout_commands/workflow/install +105 -0
  81. data/scout_commands/workflow/task +46 -6
  82. data/share/software/install_helpers +2 -2
  83. data/share/templates/command +25 -0
  84. data/share/templates/workflow.rb +14 -0
  85. data/test/scout/offsite/test_ssh.rb +15 -0
  86. data/test/scout/offsite/test_step.rb +32 -0
  87. data/test/scout/offsite/test_sync.rb +36 -0
  88. data/test/scout/offsite/test_task.rb +0 -0
  89. data/test/scout/resource/test_path.rb +6 -0
  90. data/test/scout/test_named_array.rb +6 -0
  91. data/test/scout/test_persist.rb +3 -2
  92. data/test/scout/test_tsv.rb +17 -0
  93. data/test/scout/test_work_queue.rb +64 -42
  94. data/test/scout/tsv/persist/test_adapter.rb +1 -1
  95. data/test/scout/tsv/test_index.rb +14 -0
  96. data/test/scout/tsv/test_parser.rb +35 -0
  97. data/test/scout/tsv/test_stream.rb +200 -0
  98. data/test/scout/tsv/test_transformer.rb +12 -0
  99. data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
  100. data/test/scout/workflow/step/test_dependencies.rb +68 -0
  101. data/test/scout/workflow/step/test_info.rb +17 -0
  102. data/test/scout/workflow/step/test_status.rb +0 -1
  103. data/test/scout/workflow/task/test_dependencies.rb +357 -0
  104. data/test/scout/workflow/task/test_inputs.rb +52 -0
  105. data/test/scout/workflow/test_definition.rb +18 -0
  106. data/test/scout/workflow/test_documentation.rb +24 -0
  107. data/test/scout/workflow/test_step.rb +109 -0
  108. data/test/scout/workflow/test_task.rb +0 -287
  109. data/test/test_scout.rb +9 -0
  110. metadata +89 -5
  111. data/scout_commands/workflow/task_old +0 -706
@@ -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)
@@ -81,7 +81,7 @@ module Open
81
81
  into.close if into.respond_to?(:closed?) && ! into.closed?
82
82
  into_path = into if into_path.nil? && String === into
83
83
  if into_path and File.exist?(into_path)
84
- FileUtils.rm into_path
84
+ FileUtils.rm into_path
85
85
  end
86
86
  raise exception
87
87
  end
@@ -92,7 +92,7 @@ module Open
92
92
  force = IndiferentHash.process_options options, :force
93
93
 
94
94
  if File.exist?(path) and not force
95
- Open.consume_stream content
95
+ Open.consume_stream content
96
96
  return
97
97
  end
98
98
 
@@ -107,10 +107,11 @@ module Open
107
107
 
108
108
  if File.exist? path and not force
109
109
  Log.warn "Path exists in sensible_write, not forcing update: #{ path }"
110
- Open.consume_stream content
110
+ Open.consume_stream content
111
111
  else
112
112
  FileUtils.mkdir_p File.dirname(tmp_path) unless File.directory?(File.dirname(tmp_path))
113
113
  FileUtils.rm_f tmp_path if File.exist? tmp_path
114
+ Log.low "Sensible write stream #{Log.fingerprint content} -> #{Log.fingerprint path}" if IO === content
114
115
  begin
115
116
  case
116
117
  when block_given?
@@ -122,7 +123,7 @@ module Open
122
123
  while block = content.read(BLOCK_SIZE)
123
124
  f.write block
124
125
  break if content.closed?
125
- end
126
+ end
126
127
  end
127
128
  else
128
129
  File.open(tmp_path, 'wb') do |f| end
@@ -139,8 +140,7 @@ module Open
139
140
  Open.touch path if File.exist? path
140
141
  content.join if content.respond_to?(:join) and not Path === content and not (content.respond_to?(:joined?) && content.joined?)
141
142
 
142
- Open.notify_write(path)
143
- Log.debug "Done sensible write: [#{Process.pid}] -- #{ path }"
143
+ Open.notify_write(path)
144
144
  rescue Aborted
145
145
  Log.low "Aborted sensible_write -- #{ Log.reset << path }"
146
146
  content.abort if content.respond_to? :abort
@@ -174,7 +174,7 @@ module Open
174
174
 
175
175
  [sout, sin]
176
176
  end
177
- Log.debug{"Creating pipe #{[Log.fingerprint(res.last), Log.fingerprint(res.first)] * " => "}"}
177
+ Log.low{"Creating pipe #{[Log.fingerprint(res.last), Log.fingerprint(res.first)] * " -> "}"}
178
178
  res
179
179
  end
180
180
 
@@ -214,14 +214,13 @@ module Open
214
214
 
215
215
  if do_fork
216
216
 
217
- #parent_pid = Process.pid
218
217
  pid = Process.fork {
219
218
  begin
220
219
  purge_pipes(sin)
221
220
  sout.close
222
221
 
223
222
  yield sin
224
- sin.close if close and not sin.closed?
223
+ sin.close if close and not sin.closed?
225
224
 
226
225
  rescue Exception
227
226
  Log.exception $!
@@ -237,34 +236,20 @@ module Open
237
236
  ConcurrentStream.setup sin, :pair => sout
238
237
  ConcurrentStream.setup sout, :pair => sin
239
238
 
240
- thread = Thread.new do
239
+ thread = Thread.new do
241
240
  begin
242
- Thread.current.report_on_exception = false
243
- Thread.current["name"] = "Pipe input #{Log.fingerprint sin} => #{Log.fingerprint sout}"
244
-
245
- yield sin
241
+ ConcurrentStream.process_stream(sin, :message => "Open pipe") do
242
+ Thread.current.report_on_exception = false
243
+ Thread.current["name"] = "Pipe input #{Log.fingerprint sin} => #{Log.fingerprint sout}"
246
244
 
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 $!
245
+ yield sin
262
246
  end
263
247
  end
264
248
  end
265
249
 
266
250
  sin.threads = [thread]
267
251
  sout.threads = [thread]
252
+
268
253
  Thread.pass until thread["name"]
269
254
  end
270
255
 
@@ -274,12 +259,14 @@ module Open
274
259
  def self.tee_stream_thread_multiple(stream, num = 2)
275
260
  in_pipes = []
276
261
  out_pipes = []
277
- num.times do
262
+ num.times do
278
263
  sout, sin = Open.pipe
279
264
  in_pipes << sin
280
265
  out_pipes << sout
281
266
  end
282
267
 
268
+ Log.low("Tee stream #{Log.fingerprint stream} -> #{Log.fingerprint out_pipes}")
269
+
283
270
  filename = stream.filename if stream.respond_to? :filename
284
271
 
285
272
  splitter_thread = Thread.new(Thread.current) do |parent|
@@ -291,7 +278,7 @@ module Open
291
278
  while block = stream.read(BLOCK_SIZE)
292
279
 
293
280
  in_pipes.each_with_index do |sin,i|
294
- begin
281
+ begin
295
282
  sin.write block
296
283
  rescue IOError
297
284
  Log.warn("Tee stream #{i} #{Log.fingerprint stream} IOError: #{$!.message} (#{Log.fingerprint sin})");
@@ -299,13 +286,12 @@ module Open
299
286
  rescue
300
287
  Log.warn("Tee stream #{i} #{Log.fingerprint stream} Exception: #{$!.message} (#{Log.fingerprint sin})");
301
288
  raise $!
302
- end unless skip[i]
289
+ end unless skip[i]
303
290
  end
304
291
  break if stream.closed?
305
292
  end
306
293
 
307
294
  stream.join if stream.respond_to? :join
308
- stream.close unless stream.closed?
309
295
  in_pipes.first.close unless in_pipes.first.closed?
310
296
  rescue Aborted, Interrupt
311
297
  stream.abort if stream.respond_to?(:abort) && ! stream.aborted?
@@ -348,18 +334,32 @@ module Open
348
334
  end
349
335
  end
350
336
 
351
- out_pipes.each do |sout|
352
- ConcurrentStream.setup sout, :threads => splitter_thread, :filename => filename, :pair => stream
353
- end
354
337
  Thread.pass until splitter_thread["name"]
355
338
 
356
339
  main_pipe = out_pipes.first
357
- main_pipe.autojoin = true
358
340
 
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?
341
+ ConcurrentStream.setup(main_pipe, :threads => [splitter_thread], :filename => filename, :autojoin => true)
342
+
343
+ out_pipes[1..-1].each do |sout|
344
+ ConcurrentStream.setup sout, :filename => filename, :threads => [splitter_thread]
345
+ end
346
+
347
+ main_pipe.callback = proc do
348
+ begin
349
+ stream.join if stream.respond_to?(:join) && ! stream.joined?
350
+ in_pipes[1..-1].each do |sin|
351
+ sin.close unless sin.closed?
352
+ end
353
+ rescue
354
+ main_pipe.abort_callback.call($!)
355
+ raise $!
356
+ end
357
+ end
358
+
359
+ main_pipe.abort_callback = proc do |exception|
360
+ stream.abort(exception)
361
+ out_pipes[1..-1].each do |sout|
362
+ sout.abort(exception)
363
363
  end
364
364
  end
365
365
 
@@ -378,7 +378,7 @@ module Open
378
378
  str = nil
379
379
  Thread.pass while IO.select([stream],nil,nil,1).nil?
380
380
  while not str = stream.read(size)
381
- IO.select([stream],nil,nil,1)
381
+ IO.select([stream],nil,nil,1)
382
382
  Thread.pass
383
383
  raise ClosedStream if stream.eof?
384
384
  end
@@ -403,102 +403,89 @@ module Open
403
403
  str
404
404
  end
405
405
 
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
406
+ def self.sort_stream(stream, header_hash: "#", cmd_args: "-u", memory: false)
407
+ sout = Open.open_pipe do |sin|
408
+ ConcurrentStream.process_stream(stream) do
411
409
  line = stream.gets
412
- end
410
+ while line && line.start_with?(header_hash) do
411
+ sin.puts line
412
+ line = stream.gets
413
+ end
413
414
 
414
- line_stream = Open.open_pipe do |line_stream_in|
415
- line_stream_in.puts line
416
- begin
415
+ line_stream = Open.open_pipe do |line_stream_in|
416
+ line_stream_in.puts line if line
417
417
  Open.consume_stream(stream, false, line_stream_in)
418
- rescue
419
- raise $!
420
418
  end
421
- end
419
+ Log.low "Sub-sort stream #{Log.fingerprint stream} -> #{Log.fingerprint line_stream}"
422
420
 
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 $!
421
+ if memory
422
+ line_stream.read.split("\n").sort.each do |line|
423
+ sin.puts line
424
+ end
425
+ else
426
+ io = CMD.cmd("env LC_ALL=C sort #{cmd_args || ""}", :in => line_stream, :pipe => true)
427
+ Open.consume_stream(io, false, sin)
434
428
  end
435
429
  end
436
430
  end
431
+ Log.low "Sort #{Log.fingerprint stream} -> #{Log.fingerprint sout}"
432
+ sout
437
433
  end
438
434
 
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
-
435
+ #def self.sort_stream(stream, header_hash = "#", cmd_args = "-u")
436
+ # StringIO.new stream.read.split("\n").sort.uniq * "\n"
437
+ #end
450
438
 
451
439
  def self.collapse_stream(s, line: nil, sep: "\t", header: nil, &block)
452
440
  sep ||= "\t"
453
441
  Open.open_pipe do |sin|
442
+
454
443
  sin.puts header if header
455
- process_stream(s) do |s|
456
- line ||= s.gets
457
444
 
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
445
+ line ||= s.gets
446
+
447
+ current_parts = []
448
+ while line
449
+ key, *parts = line.chomp.split(sep, -1)
450
+ case
451
+ when key.nil?
452
+ when current_parts.nil?
453
+ current_parts = parts
454
+ current_key = key
455
+ when current_key == key
456
+ parts.each_with_index do |part,i|
457
+ if current_parts[i].nil?
458
+ current_parts[i] = "|" << part
459
+ else
460
+ current_parts[i] = current_parts[i] << "|" << part
473
461
  end
462
+ end
474
463
 
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
464
+ (parts.length..current_parts.length-1).to_a.each do |pos|
465
+ current_parts[pos] = current_parts[pos] << "|" << ""
490
466
  end
491
- line = s.gets
467
+ when current_key.nil?
468
+ current_key = key
469
+ current_parts = parts
470
+ when current_key != key
471
+ if block_given?
472
+ res = block.call(current_parts)
473
+ sin.puts [current_key, res] * sep
474
+ else
475
+ sin.puts [current_key, current_parts].flatten * sep
476
+ end
477
+ current_key = key
478
+ current_parts = parts
492
479
  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?
480
+ line = s.gets
500
481
  end
482
+
483
+ if block_given?
484
+ res = block.call(current_parts)
485
+ sin.puts [current_key, res] * sep
486
+ else
487
+ sin.puts [current_key, current_parts].flatten * sep
488
+ end unless current_key.nil?
501
489
  end
502
490
  end
503
-
504
491
  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
@@ -20,19 +20,21 @@ module Open
20
20
  end
21
21
  end
22
22
 
23
- def self.get_stream(file, mode = 'r')
23
+ def self.get_stream(file, mode = 'r', options = {})
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
- return Open.ssh(file) if Open.ssh?(file)
27
- return Open.wget(file) if Open.remote?(file)
28
+ return Open.ssh(file, options) if Open.ssh?(file)
29
+ return Open.wget(file, options) if Open.remote?(file)
28
30
 
29
31
  File.open(file, mode)
30
32
  end
31
33
 
32
- def self.file_open(file, grep = false, mode = 'r', invert_grep = false)
34
+ def self.file_open(file, grep = false, mode = 'r', invert_grep = false, options = {})
33
35
  Open.mkdir File.dirname(file) if mode.include? 'w'
34
36
 
35
- stream = get_stream(file, mode)
37
+ stream = get_stream(file, mode, options)
36
38
 
37
39
  if grep
38
40
  grep(stream, grep, invert_grep)
@@ -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, options
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
 
@@ -70,7 +72,7 @@ module Open
70
72
 
71
73
  options[:noz] = true if mode.include? "w"
72
74
 
73
- io = file_open(file, options[:grep], mode, options[:invert_grep])
75
+ io = file_open(file, options[:grep], mode, options[:invert_grep], options)
74
76
 
75
77
  io = unzip(io) if ((String === file and zip?(file)) and not options[:noz]) or options[:zip]
76
78
  io = gunzip(io) if ((String === file and gzip?(file)) and not options[:noz]) or options[:gzip]
@@ -86,7 +88,7 @@ module Open
86
88
  rescue DontClose
87
89
  res = $!.payload
88
90
  rescue Exception
89
- io.abort if io.respond_to? :abort
91
+ io.abort $! if io.respond_to? :abort
90
92
  io.join if io.respond_to? :join
91
93
  raise $!
92
94
  ensure
@@ -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)
data/lib/scout/path.rb CHANGED
@@ -32,7 +32,7 @@ module Path
32
32
  prevpath = prevpath.to_s if Symbol === prevpath
33
33
 
34
34
  subpath = File.join(prevpath.to_s, subpath) if prevpath
35
- new = self.empty? ? subpath : File.join(self, subpath)
35
+ new = self.empty? ? subpath.dup : File.join(self, subpath)
36
36
  self.annotate(new)
37
37
  new
38
38
  end
@@ -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
@@ -104,7 +104,7 @@ module Persist
104
104
 
105
105
  if type == :binary
106
106
  content.force_encoding("ASCII-8BIT") if content.respond_to? :force_encoding
107
- Open.open(path, :mode => 'wb') do |f|
107
+ Open.open(file, :mode => 'wb') do |f|
108
108
  f.puts content
109
109
  end
110
110
  content
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"
@@ -0,0 +1,8 @@
1
+ class << Open
2
+ alias _just_open open
3
+
4
+ def open(file, *args, **kwargs, &block)
5
+ file.produce if Path === file
6
+ _just_open(file, *args, **kwargs, &block)
7
+ end
8
+ end
@@ -3,7 +3,7 @@ module Path
3
3
  return self if ! force && (Open.exist?(self) || @produced)
4
4
  begin
5
5
  if Resource === self.pkgdir
6
- self.pkgdir.produce self
6
+ self.pkgdir.produce self, force
7
7
  else
8
8
  false
9
9
  end
@@ -13,7 +13,7 @@ module Path
13
13
  message = $!.message
14
14
  message = "No exception message" if message.nil? || message.empty?
15
15
  Log.warn "Error producing #{self}: #{message}"
16
- false
16
+ raise $!
17
17
  ensure
18
18
  @produced = true
19
19
  end
@@ -33,13 +33,16 @@ module Path
33
33
  end
34
34
 
35
35
  def produce_and_find(extension = nil, *args)
36
- if extension
37
- found = find_with_extension(extension, *args)
38
- found.exists? ? found : produce_with_extension(extension, *args)
39
- else
40
- found = find
41
- found.exists? ? found : produce(*args)
42
- end
36
+ found = if extension
37
+ found = find_with_extension(extension, *args)
38
+ found.exists? ? found : produce_with_extension(extension, *args)
39
+ else
40
+ found = find
41
+ found.exists? ? found : produce(*args)
42
+ end
43
+ raise "Not found: #{self}" unless found
44
+
45
+ found
43
46
  end
44
47
 
45
48
  def relocate
@@ -47,6 +50,10 @@ module Path
47
50
  Resource.relocate(self)
48
51
  end
49
52
 
53
+ def identify
54
+ Resource.identify(self)
55
+ end
56
+
50
57
  def open(*args, &block)
51
58
  produce
52
59
  Open.open(self, *args, &block)