scout-gear 8.0.0 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48f6bb392f3391e2816e701887bfd98617b1a68bc533c8b6de3307f25c84906d
4
- data.tar.gz: 476858f63deaa7fa9fc531c7872bdaefa1d6b3ed32cdacbe41f53d1d170fcc87
3
+ metadata.gz: 9ca509bfb5065aabcdae73545139db0f8b04748084821e002c0475a55be5cb70
4
+ data.tar.gz: 6f0333ca6dd0ceee0ea9290cf3c30f7164c2f0732b76ce739e29da19a0687242
5
5
  SHA512:
6
- metadata.gz: c61501c8cc79b57b64cb8613efc8b00fb84908bf0d55b008c6a6a39b99ea6bffa53630a8e134c07a49cb7bc4145ec181df057b6ba1eebfd2d722b2aa2d2e63d0
7
- data.tar.gz: 100356a04cd34eba627239668747023ee5be4455ebbee715df39dbe04e9c8dfcac7007ce310e4622cf0c7e16ee9159e6fc2d4eefcaa486c24519c7f99185facf
6
+ metadata.gz: 2cbd82d97ec0dad50e624cda26ae6a05aeba8b9e5ff07a5b4746c677b8e2ab1996378237095ba09a70f8ed8cc926d782c1677aa24d6f94784f560090d6845a2c
7
+ data.tar.gz: aa9529b3393016c846b578b736428b964519d2fb5c1507a6335eff651d0588a5d9191cc61cff52279c18902f2efce386415099bcd92f8736f6d67cef1d33b561
data/.vimproject CHANGED
@@ -8,11 +8,14 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
8
8
  alias
9
9
  find
10
10
  glob
11
+ doc
12
+ update
13
+ offsite
11
14
  workflow=workflow{
12
15
  task
13
16
  list
14
17
  info
15
- task_old
18
+ install
16
19
  }
17
20
  }
18
21
  lib=lib {
@@ -99,24 +102,29 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
99
102
  workflow.rb
100
103
  workflow=workflow{
101
104
  definition.rb
105
+ documentation.rb
106
+ usage.rb
107
+ util.rb
102
108
  step.rb
103
109
  step=step{
104
- info.rb
105
- status.rb
106
- load.rb
107
- file.rb
108
110
  config.rb
109
111
  dependencies.rb
110
- provenance.rb
112
+ file.rb
113
+ info.rb
114
+ load.rb
111
115
  progress.rb
116
+ provenance.rb
117
+ status.rb
112
118
  }
113
119
  task.rb
114
120
  task=task{
121
+ dependencies.rb
115
122
  inputs.rb
116
123
  }
117
- documentation.rb
118
- usage.rb
119
- util.rb
124
+ deployment.rb
125
+ deployment=deployment{
126
+ orchestrator.rb
127
+ }
120
128
  }
121
129
  semaphore.rb
122
130
  work_queue.rb
@@ -141,6 +149,8 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
141
149
  persist=persist{
142
150
  adapter.rb
143
151
  serialize.rb
152
+ sdbm.rb
153
+ tkrzw.rb
144
154
  tokyocabinet.rb
145
155
  fix_width_table.rb
146
156
  }
@@ -149,8 +159,15 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
149
159
  attach.rb
150
160
  change_id.rb
151
161
  path.rb
162
+ stream.rb
152
163
  open.rb
153
164
  }
165
+ offsite.rb
166
+ offsite=offsite{
167
+ ssh.rb
168
+ sync.rb
169
+ step.rb
170
+ }
154
171
  }
155
172
  }
156
173
  test=test {
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ Juwelier::Tasks.new do |gem|
12
12
  gem.homepage = "http://github.com/mikisvaz/scout-gear"
13
13
  gem.license = "MIT"
14
14
  gem.summary = %Q{basic gear for scouts}
15
- gem.description = %Q{Temporary files, logs, etc.}
15
+ gem.description = %Q{Temporary files, logs, path, resources, persistence, workflows, TSV, etc.}
16
16
  gem.email = "mikisvaz@gmail.com"
17
17
  gem.authors = ["Miguel Vazquez"]
18
18
 
@@ -21,6 +21,11 @@ Juwelier::Tasks.new do |gem|
21
21
  # gem.add_runtime_dependency 'jabber4r', '> 0.1'
22
22
  # gem.add_development_dependency 'rspec', '> 1.2.3'
23
23
  gem.add_runtime_dependency 'term-ansicolor'
24
+ gem.add_runtime_dependency 'net-ssh'
25
+ gem.add_runtime_dependency 'matrix'
26
+ gem.add_runtime_dependency 'sys-proctable'
27
+ gem.add_runtime_dependency 'RubyInline'
28
+ #gem.add_runtime_dependency 'tokyocabinet'
24
29
 
25
30
  gem.add_development_dependency "rdoc", "~> 3.12"
26
31
  gem.add_development_dependency "bundler", "~> 1.0"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 8.0.0
1
+ 8.1.0
data/bin/scout CHANGED
@@ -35,6 +35,12 @@ if dev_dir.nil?
35
35
  ARGV.delete _s if _s
36
36
  end
37
37
 
38
+ if dev_dir.nil? && ENV["SCOUT_DEV"]
39
+ dev_dir = ENV["SCOUT_DEV"]
40
+ ARGV.delete "--dev"
41
+ ARGV.delete dev_dir
42
+ end
43
+
38
44
  if dev_dir
39
45
  ['scout-*/lib'].each do |pattern|
40
46
  Dir.glob(File.join(File.expand_path(dev_dir), pattern)).each do |f|
@@ -62,6 +68,7 @@ $ #{$0} <command> <subcommand> ... -a --arg1 --arg2='value' --arg3 'another-valu
62
68
  --nocolor #{Log.color :yellow, "Disable colored output"}
63
69
  --nobar #{Log.color :yellow, "Disable progress report"}
64
70
  --locate_file #{Log.color :yellow, "Report the location of the script instead of executing it"}
71
+ -ck--config_keys* #{Log.color :yellow, "Override some config keys"}
65
72
  EOF
66
73
 
67
74
  Log.nocolor = true if options[:nocolor]
@@ -84,6 +91,14 @@ else
84
91
  end
85
92
  end
86
93
 
94
+ if config_keys = options.delete(:config_keys)
95
+ config_keys.split(",").each do |config|
96
+ config = config.strip
97
+ Scout::Config.process_config config
98
+ end
99
+ end
100
+
101
+
87
102
  $scout_command_dir = Scout.bin.scout
88
103
  $scout_command_dir.path_maps[:scout_commands] = File.join(File.dirname(__dir__), "{PATH/bin\\/scout/scout_commands}")
89
104
 
@@ -217,7 +232,6 @@ begin
217
232
 
218
233
  scout_usage($previous_commands)
219
234
  exit_status = 0
220
- exit exit_status
221
235
 
222
236
  rescue ParameterException
223
237
  puts
@@ -225,14 +239,11 @@ rescue ParameterException
225
239
  print_error($!.message, $!.backtrace)
226
240
  puts
227
241
  exit_status = -1
228
- exit exit_status
229
242
  rescue SystemExit,CmdStop
230
243
  exit_status = $!.status
231
- exit exit_status
232
244
  rescue Exception
233
245
  Log.exception $!
234
246
  exit_status = -1
235
- exit exit_status
236
247
  ensure
237
248
  if options[:profile]
238
249
  result = RubyProf.stop
@@ -0,0 +1,35 @@
1
+ Path
2
+ ===
3
+
4
+ ```ruby
5
+ :current => '{PWD}/{TOPLEVEL}/{SUBPATH}',
6
+ :user => '{HOME}/.{PKGDIR}/{TOPLEVEL}/{SUBPATH}',
7
+ :global => '/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
8
+ :usr => '/usr/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
9
+ :local => '/usr/local/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
10
+ :fast => '/fast/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
11
+ :cache => '/cache/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
12
+ :bulk => '/bulk/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
13
+ :lib => '{LIBDIR}/{TOPLEVEL}/{SUBPATH}',
14
+ :scout_gear => File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}/{SUBPATH}"),
15
+ :tmp => '/tmp/{PKGDIR}/{TOPLEVEL}/{SUBPATH}',
16
+ :default => :user
17
+
18
+ @@basic_map_order ||= %w(current workflow user local global lib fast cache bulk)
19
+
20
+ ```
21
+
22
+
23
+
24
+ # tags
25
+ {PKGDIR}
26
+ {LIBDIR}
27
+ {RESOURCE}
28
+ {HOME}
29
+ {PWD}
30
+ {TOPLEVEL}
31
+ {SUBPATH}
32
+ {BASENAME}
33
+ {PATH}
34
+ {MAPNAME}
35
+ {REMOVE}
@@ -0,0 +1,13 @@
1
+ Task
2
+ ====
3
+
4
+ ```ruby
5
+ wf = Workflow.annonymous_workflow "TaskInputs" do
6
+ input :input1, :integer
7
+ task :step1 => :integer do |i| i end
8
+
9
+ dep :step1
10
+ input :input2, :integer, "Integer", 3
11
+ task :step2 => :integer do |i| i * step(:step1).load end
12
+ end
13
+ ```
data/lib/scout/cmd.rb CHANGED
@@ -14,9 +14,9 @@ module CMD
14
14
 
15
15
  def self.conda(tool, env = nil, channel = 'bioconda')
16
16
  if env
17
- CMD.cmd("bash -l -c '(conda activate #{env} && conda install #{tool} -c #{channel})'")
17
+ CMD.cmd("bash -l -c '(conda activate #{env} && conda install #{tool} -c #{channel})'")
18
18
  else
19
- CMD.cmd("bash -l -c 'conda install #{tool} -c #{channel}'")
19
+ CMD.cmd("bash -l -c 'conda install #{tool} -c #{channel}'")
20
20
  end
21
21
  end
22
22
 
@@ -61,6 +61,7 @@ module CMD
61
61
 
62
62
  def self.scan_version_text(text, cmd = nil)
63
63
  cmd = "NOCMDGIVE" if cmd.nil? || cmd.empty?
64
+ text = Misc.fixutf8 text
64
65
  text.split("\n").each do |line|
65
66
  next unless line =~ /\W#{cmd}\W/i
66
67
  m = line.match(/(v(?:\d+\.)*\d+(?:-[a-z_]+)?)/i)
@@ -98,8 +99,8 @@ module CMD
98
99
 
99
100
  option = "--" << option.to_s if add_dashes and option.to_s[0] != '-'
100
101
 
101
- case
102
- when value.nil? || FalseClass === value
102
+ case
103
+ when value.nil? || FalseClass === value
103
104
  next
104
105
  when TrueClass === value
105
106
  string << "#{option} "
@@ -136,8 +137,8 @@ module CMD
136
137
  dont_close_in = options.delete(:dont_close_in)
137
138
 
138
139
  log = true if log.nil?
139
-
140
- if cmd.nil? && ! Symbol === tool
140
+
141
+ if cmd.nil? && ! Symbol === tool
141
142
  cmd = tool
142
143
  else
143
144
  tool = get_tool(tool)
@@ -163,7 +164,7 @@ module CMD
163
164
 
164
165
  cmd_options = process_cmd_options options
165
166
  if cmd =~ /'\{opt\}'/
166
- cmd.sub!('\'{opt}\'', cmd_options)
167
+ cmd.sub!('\'{opt}\'', cmd_options)
167
168
  else
168
169
  cmd << " " << cmd_options
169
170
  end
@@ -179,29 +180,28 @@ module CMD
179
180
  end
180
181
  pid = wait_thr.pid
181
182
 
182
- Log.debug{"CMD: [#{pid}] #{cmd}" if log}
183
+ Log.debug{"CMD: [#{pid}] #{cmd}".strip if log}
183
184
 
184
185
  if in_content.respond_to?(:read)
185
186
  in_thread = Thread.new(Thread.current) do |parent|
186
- Thread.current.report_on_exception = false if no_fail
187
187
  begin
188
- begin
189
- while c = in_content.readpartial(Open::BLOCK_SIZE)
190
- sin << c
191
- end
192
- rescue EOFError
188
+ Thread.current.report_on_exception = false if no_fail
189
+ Thread.current["name"] = "CMD in"
190
+ while c = in_content.read(Open::BLOCK_SIZE)
191
+ sin << c
193
192
  end
194
193
  sin.close unless sin.closed?
195
194
 
196
195
  unless dont_close_in
197
- in_content.close unless in_content.closed?
198
- in_content.join if in_content.respond_to? :join
196
+ in_content.close unless in_content.closed?
197
+ in_content.join if in_content.respond_to? :join
199
198
  end
200
199
  rescue
201
200
  Log.error "Error in CMD [#{pid}] #{cmd}: #{$!.message}" unless no_fail
202
201
  raise $!
203
202
  end
204
203
  end
204
+ Thread.pass until in_thread["name"]
205
205
  else
206
206
  in_thread = nil
207
207
  sin.close
@@ -211,7 +211,7 @@ module CMD
211
211
 
212
212
  if pipe
213
213
 
214
- ConcurrentStream.setup sout, :pids => pids, :autojoin => autojoin, :no_fail => no_fail
214
+ ConcurrentStream.setup sout, :pids => pids, :autojoin => autojoin, :no_fail => no_fail
215
215
 
216
216
  sout.callback = post if post
217
217
 
@@ -224,7 +224,7 @@ module CMD
224
224
  sout.log = line
225
225
  sout.std_err << line if save_stderr
226
226
  Log.log "STDERR [#{pid}]: " + line, stderr if log
227
- end
227
+ end
228
228
  serr.close
229
229
  rescue
230
230
  Log.exception $!
@@ -244,8 +244,8 @@ module CMD
244
244
  err = ""
245
245
  err_thread = Thread.new do
246
246
  while not serr.eof?
247
- line = serr.gets
248
- bar.process(line)
247
+ line = serr.gets
248
+ bar.process(line)
249
249
  err << line if Integer === stderr and log
250
250
  end
251
251
  serr.close
@@ -254,18 +254,17 @@ module CMD
254
254
  err = ""
255
255
  err_thread = Thread.new do
256
256
  while not serr.eof?
257
- err << serr.gets
257
+ err << serr.gets
258
258
  end
259
259
  serr.close
260
260
  end
261
261
  else
262
262
  Open.consume_stream(serr, true)
263
- #serr.close
264
263
  err_thread = nil
265
264
  err = ""
266
265
  end
267
266
 
268
- ConcurrentStream.setup sout, :pids => pids, :threads => [in_thread, err_thread].compact, :autojoin => autojoin, :no_fail => no_fail
267
+ ConcurrentStream.setup sout, :pids => pids, :threads => [in_thread, err_thread].compact, :autojoin => autojoin, :no_fail => no_fail
269
268
 
270
269
  begin
271
270
  out = StringIO.new sout.read
@@ -324,7 +323,7 @@ module CMD
324
323
  starting = true
325
324
  line = "" if bar
326
325
  end
327
- end
326
+ end
328
327
  begin
329
328
  io.join
330
329
  bar.remove if bar
@@ -12,13 +12,12 @@ module ConcurrentStream
12
12
  attr_accessor :threads, :pids, :callback, :abort_callback, :filename, :joined, :aborted, :autojoin, :lock, :no_fail, :pair, :thread, :stream_exception, :log, :std_err, :next
13
13
 
14
14
  def self.setup(stream, options = {}, &block)
15
-
16
15
  threads, pids, callback, abort_callback, filename, autojoin, lock, no_fail, pair, next_stream = IndiferentHash.process_options options, :threads, :pids, :callback, :abort_callback, :filename, :autojoin, :lock, :no_fail, :pair, :next
17
16
  stream.extend ConcurrentStream unless ConcurrentStream === stream
18
17
 
19
18
  stream.threads ||= []
20
19
  stream.pids ||= []
21
- stream.threads.concat(Array === threads ? threads : [threads]) unless threads.nil?
20
+ stream.threads.concat(Array === threads ? threads : [threads]) unless threads.nil?
22
21
  stream.pids.concat(Array === pids ? pids : [pids]) unless pids.nil? or pids.empty?
23
22
  stream.autojoin = autojoin unless autojoin.nil?
24
23
  stream.no_fail = no_fail unless no_fail.nil?
@@ -36,7 +35,7 @@ module ConcurrentStream
36
35
  callback.call
37
36
  end
38
37
  else
39
- stream.callback = callback
38
+ stream.callback = callback
40
39
  end
41
40
  end
42
41
 
@@ -48,7 +47,7 @@ module ConcurrentStream
48
47
  abort_callback.call
49
48
  end
50
49
  else
51
- stream.abort_callback = abort_callback
50
+ stream.abort_callback = abort_callback
52
51
  end
53
52
  end
54
53
 
@@ -80,7 +79,7 @@ module ConcurrentStream
80
79
 
81
80
  def join_threads
82
81
  if @threads
83
- @threads.each do |t|
82
+ @threads.each do |t|
84
83
  next if t == Thread.current
85
84
  begin
86
85
  t.join
@@ -101,7 +100,7 @@ module ConcurrentStream
101
100
  Log.low "Not failing on exception joining thread in ConcurrenStream - #{filename} - #{$!.message}"
102
101
  else
103
102
  Log.low "Exception joining thread in ConcurrenStream #{Log.fingerprint self} - #{Log.fingerprint t} - #{$!.message}"
104
- stream_raise_exception $!
103
+ stream_raise_exception $!
105
104
  end
106
105
  end
107
106
  end
@@ -111,13 +110,13 @@ module ConcurrentStream
111
110
 
112
111
  def join_pids
113
112
  if @pids and @pids.any?
114
- @pids.each do |pid|
113
+ @pids.each do |pid|
115
114
  begin
116
115
  Process.waitpid(pid, Process::WUNTRACED)
117
116
  stream_raise_exception ConcurrentStreamProcessFailed.new(pid, "Error in waitpid", self) unless $?.success? or no_fail
118
117
  rescue Errno::ECHILD
119
118
  end
120
- end
119
+ end
121
120
  @pids = []
122
121
  end
123
122
  end
@@ -143,7 +142,7 @@ module ConcurrentStream
143
142
  @joined = true
144
143
  begin
145
144
  lock.unlock if lock && lock.locked?
146
- rescue
145
+ rescue
147
146
  Log.exception $!
148
147
  end
149
148
  raise stream_exception if stream_exception
@@ -158,7 +157,7 @@ module ConcurrentStream
158
157
 
159
158
  threads = @threads.dup
160
159
  @threads.clear
161
- threads.each do |t|
160
+ threads.each do |t|
162
161
  next if t == Thread.current
163
162
  next if t["aborted"]
164
163
  t["aborted"] = true
@@ -166,14 +165,14 @@ module ConcurrentStream
166
165
  Log.debug "Aborting thread #{Log.fingerprint(t)} with exception: #{exception}"
167
166
  t.raise(exception)
168
167
  t.join
169
- end
168
+ end
170
169
  end
171
170
 
172
171
  def abort_pids
173
172
  @pids.each do |pid|
174
- begin
173
+ begin
175
174
  Log.low "Killing PID #{pid} in ConcurrentStream #{filename}"
176
- Process.kill :INT, pid
175
+ Process.kill :INT, pid
177
176
  rescue Errno::ESRCH
178
177
  end
179
178
  end if @pids
@@ -189,7 +188,7 @@ module ConcurrentStream
189
188
  Log.medium "Aborting stream #{Log.fingerprint self} [#{@aborted}]"
190
189
  end
191
190
  AbortedStream.setup(self, exception)
192
- @aborted = true
191
+ @aborted = true
193
192
  begin
194
193
  @abort_callback.call exception if @abort_callback
195
194
 
@@ -207,7 +206,7 @@ module ConcurrentStream
207
206
  close unless closed?
208
207
 
209
208
  if lock and lock.locked?
210
- lock.unlock
209
+ lock.unlock
211
210
  end
212
211
  end
213
212
  end
@@ -218,7 +217,7 @@ module ConcurrentStream
218
217
  super(*args)
219
218
  rescue
220
219
  self.abort
221
- self.join
220
+ self.join
222
221
  stream_raise_exception $!
223
222
  ensure
224
223
  self.join if ! @stream_exception && (self.closed? || self.eof?)
@@ -249,19 +248,37 @@ module ConcurrentStream
249
248
 
250
249
  def add_callback(&block)
251
250
  old_callback = callback
252
- @callback = Proc.new do
251
+ @callback = Proc.new do
253
252
  old_callback.call if old_callback
254
253
  block.call
255
254
  end
256
255
  end
257
256
 
258
257
  def stream_raise_exception(exception)
258
+ self.stream_exception = exception
259
259
  threads.each do |thread|
260
260
  thread.raise exception
261
261
  end
262
- self.stream_exception = exception
263
-
264
262
  self.abort
265
263
  end
266
264
 
265
+ def self.process_stream(stream, close: true, join: true, message: "process_stream", **kwargs, &block)
266
+ ConcurrentStream.setup(stream, **kwargs)
267
+ begin
268
+ begin
269
+ yield
270
+ ensure
271
+ stream.close if close && stream.respond_to?(:close) && ! (stream.respond_to?(:closed?) && stream.closed?)
272
+ stream.join if join && stream.respond_to?(:join) && ! stream.joined?
273
+ end
274
+ rescue Aborted
275
+ Log.low "Aborted #{message}: #{$!.message}"
276
+ stream.abort($!) if stream.respond_to?(:abort) && ! stream.aborted?
277
+ raise $!
278
+ rescue Exception
279
+ Log.low "Exception #{message}: #{$!.message}"
280
+ stream.abort($!) if stream.respond_to?(:abort) && ! stream.aborted?
281
+ raise $!
282
+ end
283
+ end
267
284
  end
@@ -139,3 +139,13 @@ class SemaphoreInterrupted < TryAgain; end
139
139
  #
140
140
  #
141
141
  class ResourceNotFound < ScoutException; end
142
+
143
+ class SSHProcessFailed < StandardError
144
+ attr_accessor :host, :cmd
145
+ def initialize(host, cmd)
146
+ @host = host
147
+ @cmd = cmd
148
+ message = "SSH server #{host} failed cmd '#{cmd}'"
149
+ super(message)
150
+ end
151
+ end
@@ -10,8 +10,8 @@ module Colorize
10
10
 
11
11
  def self.colors
12
12
  @colors ||= IndiferentHash.setup(Hash[<<-EOF.split("\n").collect{|l| l.split(" ")}])
13
- green #00cd00
14
- red #cd0000
13
+ green #00cd00
14
+ red #cd0000
15
15
  yellow #ffd700
16
16
  blue #0000cd
17
17
  path blue
@@ -49,26 +49,26 @@ EOF
49
49
  when "black"
50
50
  '#fff'
51
51
  when 'green'
52
- colors["green3"]
52
+ colors["green3"]
53
53
  when 'red'
54
- colors["red3"]
54
+ colors["red3"]
55
55
  when 'yellow'
56
- colors["gold1"]
56
+ colors["gold1"]
57
57
  when 'blue'
58
- colors["RoyalBlue"]
58
+ colors["RoyalBlue"]
59
59
  else
60
60
  colors[color.to_s] || color.to_s
61
61
  end
62
62
  end
63
63
 
64
- def self.continuous(array, start = "#40324F", eend = "#EABD5D", percent = false)
64
+ def self.continuous(array, start = "#40324F", eend = "#EABD5D", percent = false)
65
65
  start_color = Color.new from_name(start)
66
66
  end_color = Color.new from_name(eend)
67
67
 
68
68
  if percent
69
69
  array = array.collect{|v| n = v.to_f; n = n > 100 ? 100 : n; n < 0.001 ? 0.001 : n}
70
70
  else
71
- array = array.collect{|v| v.to_f }
71
+ array = array.collect{|v| v.to_f }
72
72
  end
73
73
  max = array.max
74
74
  min = array.min
@@ -157,7 +157,7 @@ module Log
157
157
  :workflow => yellow,
158
158
  })
159
159
  HIGHLIGHT = "\033[1m"
160
-
160
+
161
161
  def self.uncolor(str)
162
162
  "" << Term::ANSIColor.uncolor(str)
163
163
  end
@@ -167,7 +167,7 @@ module Log
167
167
  end
168
168
 
169
169
  def self.color(color, str = nil, reset = false)
170
- return str.dup || "" if nocolor
170
+ return str.dup || "" if nocolor
171
171
 
172
172
  if (color == :integer || color == :float) && Numeric === str
173
173
  color = if str < 0
@@ -179,7 +179,7 @@ module Log
179
179
  end
180
180
  end
181
181
 
182
- if color == :status
182
+ if color == :status
183
183
  color = case str.to_sym
184
184
  when :done
185
185
  :green
@@ -4,8 +4,7 @@ module Log
4
4
  def print(io, str)
5
5
  return if self.severity && self.severity < Log.severity
6
6
  return if Log.no_bar
7
- STDERR.print str
8
- Log.logfile.puts str unless Log.logfile.nil?
7
+ Log.log_write str
9
8
  Log::LAST.replace "progress"
10
9
  end
11
10
 
@@ -57,9 +56,12 @@ module Log
57
56
  thr = short_mean
58
57
  else
59
58
  thr = begin
60
- (@ticks || 1) / (Time.now - @start)
61
- rescue
62
- 1
59
+ d = Time.now - @start
60
+ if d == 0
61
+ 1
62
+ else
63
+ (@ticks || 1) / d
64
+ end
63
65
  end
64
66
  end
65
67
 
@@ -74,6 +74,7 @@ module Log
74
74
  BAR_MUTEX.synchronize do
75
75
  REMOVE << bar
76
76
  end
77
+ cleanup_bars
77
78
  Log::LAST.replace "remove_bar" if Log::LAST == "progress"
78
79
  end
79
80
 
@@ -128,6 +129,8 @@ module Log
128
129
  nil
129
130
  end
130
131
  end
132
+ rescue Interrupt
133
+ raise $!
131
134
  rescue Exception
132
135
  nil
133
136
  end
@@ -1,7 +1,7 @@
1
1
  module Log
2
2
  def self.trap_std(msg = "STDOUT", msge = "STDERR", severity = 0, severity_err = nil)
3
- sout, sin = Misc.pipe
4
- soute, sine = Misc.pipe
3
+ sout, sin = Open.pipe
4
+ soute, sine = Open.pipe
5
5
  backup_stderr = STDERR.dup
6
6
  backup_stdout = STDOUT.dup
7
7
  old_logfile = Log.logfile
@@ -38,7 +38,7 @@ module Log
38
38
  end
39
39
 
40
40
  def self.trap_stderr(msg = "STDERR", severity = 0)
41
- sout, sin = Misc.pipe
41
+ sout, sin = Open.pipe
42
42
  backup_stderr = STDERR.dup
43
43
  old_logfile = Log.logfile
44
44
  Log.logfile(backup_stderr)