scout-gear 7.1.0 → 7.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +29 -0
  3. data/VERSION +1 -1
  4. data/bin/scout +5 -1
  5. data/lib/rbbt-scout.rb +5 -0
  6. data/lib/scout/concurrent_stream.rb +6 -2
  7. data/lib/scout/config.rb +168 -0
  8. data/lib/scout/exceptions.rb +4 -3
  9. data/lib/scout/indiferent_hash/options.rb +1 -0
  10. data/lib/scout/indiferent_hash.rb +4 -2
  11. data/lib/scout/log/color.rb +3 -1
  12. data/lib/scout/log/progress/report.rb +1 -0
  13. data/lib/scout/log/progress/util.rb +1 -1
  14. data/lib/scout/log/progress.rb +5 -3
  15. data/lib/scout/log.rb +3 -2
  16. data/lib/scout/misc/monitor.rb +3 -0
  17. data/lib/scout/misc/system.rb +15 -0
  18. data/lib/scout/misc.rb +1 -0
  19. data/lib/scout/named_array.rb +68 -0
  20. data/lib/scout/open/stream.rb +38 -7
  21. data/lib/scout/path/find.rb +27 -3
  22. data/lib/scout/path/util.rb +7 -4
  23. data/lib/scout/persist/serialize.rb +7 -14
  24. data/lib/scout/persist.rb +21 -1
  25. data/lib/scout/resource/produce.rb +7 -94
  26. data/lib/scout/resource/software.rb +176 -0
  27. data/lib/scout/tsv/dumper.rb +107 -0
  28. data/lib/scout/tsv/index.rb +49 -0
  29. data/lib/scout/tsv/parser.rb +203 -30
  30. data/lib/scout/tsv/path.rb +13 -0
  31. data/lib/scout/tsv/persist/adapter.rb +348 -0
  32. data/lib/scout/tsv/persist/tokyocabinet.rb +113 -0
  33. data/lib/scout/tsv/persist.rb +15 -0
  34. data/lib/scout/tsv/traverse.rb +48 -0
  35. data/lib/scout/tsv/util.rb +24 -0
  36. data/lib/scout/tsv.rb +16 -3
  37. data/lib/scout/work_queue/worker.rb +3 -3
  38. data/lib/scout/work_queue.rb +22 -7
  39. data/lib/scout/workflow/definition.rb +93 -4
  40. data/lib/scout/workflow/step/config.rb +18 -0
  41. data/lib/scout/workflow/step/dependencies.rb +40 -0
  42. data/lib/scout/workflow/step/file.rb +15 -0
  43. data/lib/scout/workflow/step/info.rb +31 -4
  44. data/lib/scout/workflow/step/provenance.rb +148 -0
  45. data/lib/scout/workflow/step.rb +68 -19
  46. data/lib/scout/workflow/task.rb +3 -2
  47. data/lib/scout/workflow/usage.rb +1 -1
  48. data/lib/scout/workflow.rb +11 -3
  49. data/lib/scout-gear.rb +1 -0
  50. data/lib/scout.rb +1 -0
  51. data/scout-gear.gemspec +34 -3
  52. data/scout_commands/find +1 -1
  53. data/scout_commands/workflow/task +16 -10
  54. data/share/software/install_helpers +523 -0
  55. data/test/scout/log/test_progress.rb +0 -2
  56. data/test/scout/misc/test_system.rb +21 -0
  57. data/test/scout/open/test_stream.rb +159 -0
  58. data/test/scout/path/test_find.rb +14 -7
  59. data/test/scout/resource/test_software.rb +24 -0
  60. data/test/scout/test_config.rb +66 -0
  61. data/test/scout/test_meta_extension.rb +10 -0
  62. data/test/scout/test_named_array.rb +19 -0
  63. data/test/scout/test_persist.rb +35 -0
  64. data/test/scout/test_tmpfile.rb +2 -2
  65. data/test/scout/test_tsv.rb +41 -1
  66. data/test/scout/test_work_queue.rb +40 -13
  67. data/test/scout/tsv/persist/test_adapter.rb +34 -0
  68. data/test/scout/tsv/persist/test_tokyocabinet.rb +92 -0
  69. data/test/scout/tsv/test_dumper.rb +44 -0
  70. data/test/scout/tsv/test_index.rb +64 -0
  71. data/test/scout/tsv/test_parser.rb +86 -0
  72. data/test/scout/tsv/test_persist.rb +36 -0
  73. data/test/scout/tsv/test_traverse.rb +9 -0
  74. data/test/scout/tsv/test_util.rb +0 -0
  75. data/test/scout/work_queue/test_worker.rb +3 -3
  76. data/test/scout/workflow/step/test_dependencies.rb +25 -0
  77. data/test/scout/workflow/step/test_info.rb +15 -17
  78. data/test/scout/workflow/step/test_load.rb +16 -18
  79. data/test/scout/workflow/step/test_provenance.rb +25 -0
  80. data/test/scout/workflow/test_step.rb +206 -10
  81. data/test/scout/workflow/test_task.rb +0 -3
  82. data/test/test_helper.rb +6 -0
  83. metadata +33 -2
@@ -1,4 +1,9 @@
1
1
  module Path
2
+ def no_method_missing
3
+ class << self
4
+ undef_method :method_missing
5
+ end
6
+ end
2
7
 
3
8
  def self.is_filename?(string, need_to_exists = true)
4
9
  return false if string.nil?
@@ -56,9 +61,7 @@ module Path
56
61
  end.flatten.uniq
57
62
  end
58
63
 
59
- def no_method_missing
60
- class << self
61
- undef_method :method_missing
62
- end
64
+ def set_extension(extension)
65
+ self.annotate(self + ".#{extension}")
63
66
  end
64
67
  end
@@ -93,22 +93,15 @@ module Persist
93
93
 
94
94
  Log.debug "Save #{Log.fingerprint type} on #{file}"
95
95
  if save_drivers[type]
96
- Open.write(file, save_drivers[type].call(content))
97
- return
98
- end
99
-
100
- if IO === content || StringIO === content
101
- main, copy = Open.tee_stream_thread content
102
- t = Thread.new do
103
- Thread.current["name"] = "file saver: " + file
104
- Open.sensible_write(file, main)
96
+ if save_drivers[type].arity == 1
97
+ return Open.sensible_write(file, save_drivers[type].call(content))
98
+ else
99
+ return save_drivers[type].call(file, content)
105
100
  end
106
- ConcurrentStream.setup copy, :threads => t, :filename => file, :autojoin => true
107
- else
108
- serialized = serialize(content, type)
109
- Open.sensible_write(file, serialized, :force => true)
110
- content
111
101
  end
102
+ serialized = serialize(content, type)
103
+ Open.sensible_write(file, serialized, :force => true)
104
+ return nil
112
105
  end
113
106
 
114
107
  def self.load(file, type = :serializer)
data/lib/scout/persist.rb CHANGED
@@ -26,6 +26,7 @@ module Persist
26
26
 
27
27
  def self.persist(name, type = :serializer, options = {}, &block)
28
28
  persist_options = IndiferentHash.pull_keys options, :persist
29
+ return yield if FalseClass === persist_options[:persist]
29
30
  file = persist_options[:path] || options[:path] || persistence_path(name, options)
30
31
 
31
32
  update = options[:update] || persist_options[:update]
@@ -35,10 +36,29 @@ module Persist
35
36
  if Open.exist?(file) && ! update
36
37
  Persist.load(file, type)
37
38
  else
39
+ return yield(file) if block.arity == 1
38
40
  res = yield
39
41
  begin
40
42
  Open.rm(file)
41
- res = Persist.save(res, file, type)
43
+
44
+ if IO === res || StringIO === res
45
+ tee_copies = options[:tee_copies] || 1
46
+ main, *copies = Open.tee_stream_thread_multiple res, tee_copies + 1
47
+ t = Thread.new do
48
+ Thread.current.report_on_exception = false
49
+ Thread.current["name"] = "file saver: " + file
50
+ Open.sensible_write(file, main)
51
+ end
52
+ Thread.pass until t["name"]
53
+ copies.each_with_index do |copy,i|
54
+ next_stream = copies[i+1] if copies.length > i
55
+ ConcurrentStream.setup copy, :threads => t, :filename => file, :autojoin => true, :next => next_stream
56
+ end
57
+ res = copies.first
58
+ else
59
+ pres = Persist.save(res, file, type)
60
+ res = pres unless pres.nil?
61
+ end
42
62
  rescue
43
63
  raise $! unless options[:canfail]
44
64
  Log.debug "Could not persist #{type} on #{file}"
@@ -39,7 +39,7 @@ module Resource
39
39
  else
40
40
  ScoutRake.run(rakefile, rake_dir, task)
41
41
  end
42
- rescue Rake::TaskNotFound
42
+ rescue ScoutRake::TaskNotFound
43
43
  if rake_dir.nil? or rake_dir.empty? or rake_dir == "/" or rake_dir == "./"
44
44
  raise $!
45
45
  end
@@ -51,9 +51,9 @@ module Resource
51
51
 
52
52
  def produce(path, force = false)
53
53
  case
54
- when @resources.include?(path)
54
+ when (@resources && @resources.include?(path))
55
55
  type, content = @resources[path]
56
- when (Path === path && @resources.include?(path.original))
56
+ when (Path === path && @resources && @resources.include?(path.original))
57
57
  type, content = @resources[path.original]
58
58
  when has_rake(path)
59
59
  type = :rake
@@ -126,97 +126,10 @@ module Resource
126
126
  when :rake
127
127
  run_rake(path, content, rake_dir)
128
128
  when :install
129
- Log.debug "Installing software: #{path}"
130
-
131
- $set_software_env = false unless File.exist? path
132
-
133
- software_dir = path.resource.root.software.find :user
134
- helper_file = File.expand_path(Rbbt.share.install.software.lib.install_helpers.find(:lib, caller_lib_dir(__FILE__)))
135
- #helper_file = File.expand_path(Rbbt.share.install.software.lib.install_helpers.find)
136
-
137
- preamble = <<-EOF
138
- #!/bin/bash
139
-
140
- RBBT_SOFTWARE_DIR="#{software_dir}"
141
-
142
- INSTALL_HELPER_FILE="#{helper_file}"
143
- source "$INSTALL_HELPER_FILE"
144
- EOF
145
-
146
- content = content.call if Proc === content
147
-
148
- content = if content =~ /git:|\.git$/
149
- {:git => content}
150
- else
151
- {:src => content}
152
- end if String === content and Open.remote?(content)
153
-
154
- script_text = case content
155
- when nil
156
- raise "No way to install #{path}"
157
- when Path
158
- Open.read(content)
159
- when String
160
- if Path.is_filename?(content) and Open.exists?(content)
161
- Open.read(content)
162
- else
163
- content
164
- end
165
- when Hash
166
- name = content[:name] || File.basename(path)
167
- git = content[:git]
168
- src = content[:src]
169
- url = content[:url]
170
- jar = content[:jar]
171
- extra = content[:extra]
172
- commands = content[:commands]
173
- if git
174
- <<-EOF
175
-
176
- name='#{name}'
177
- url='#{git}'
178
-
179
- install_git "$name" "$url" #{extra}
180
-
181
- #{commands}
182
- EOF
183
- elsif src
184
- <<-EOF
185
-
186
- name='#{name}'
187
- url='#{src}'
188
-
189
- install_src "$name" "$url" #{extra}
190
-
191
- #{commands}
192
- EOF
193
- elsif jar
194
- <<-EOF
195
-
196
- name='#{name}'
197
- url='#{jar}'
198
-
199
- install_jar "$name" "$url" #{extra}
200
-
201
- #{commands}
202
- EOF
203
- else
204
- <<-EOF
205
-
206
- name='#{name}'
207
- url='#{url}'
208
-
209
- #{commands}
210
- EOF
211
- end
212
- end
213
-
214
- script = preamble + "\n" + script_text
215
- Log.debug "Installing software with script:\n" << script
216
- CMD.cmd_log('bash', :in => script)
217
-
218
- set_software_env(software_dir) unless $set_software_env
219
- $set_software_env = true
129
+ software_dir = self.root.software
130
+ name = File.basename(path)
131
+ Resource.install(content, name, software_dir)
132
+ set_software_env(software_dir)
220
133
  else
221
134
  raise "Could not produce #{ resource }. (#{ type }, #{ content })"
222
135
  end
@@ -0,0 +1,176 @@
1
+ module Resource
2
+
3
+ def self.install_helpers
4
+ File.expand_path(Scout.share.software.install_helpers.find(:lib))
5
+ end
6
+
7
+ def self.install(content, name, software_dir = Path.setup('software'), &block)
8
+ software_dir ||= Path.setup('software')
9
+ software_dir = software_dir.find if Path === software_dir
10
+
11
+ content = block if block_given?
12
+
13
+ preamble = <<-EOF
14
+ #!/bin/bash
15
+
16
+ SOFTWARE_DIR="#{software_dir}"
17
+
18
+ INSTALL_HELPER_FILE="#{install_helpers}"
19
+ source "$INSTALL_HELPER_FILE"
20
+ EOF
21
+
22
+ content = content.call if Proc === content
23
+
24
+ name = content[:name] if Hash === content && content.include?(:name)
25
+ content =
26
+ if content =~ /git:|\.git$/
27
+ {:git => content}
28
+ else
29
+ {:src => content}
30
+ end if String === content and Open.remote?(content)
31
+
32
+ script_text =
33
+ case content
34
+ when nil
35
+ raise "No way to install #{name}"
36
+ when Path
37
+ Open.read(content)
38
+ when String
39
+ if Path.is_filename?(content) and Open.exists?(content)
40
+ Open.read(content)
41
+ else
42
+ content
43
+ end
44
+ when Hash
45
+ name = content[:name] || name
46
+ git = content[:git]
47
+ src = content[:src]
48
+ url = content[:url]
49
+ jar = content[:jar]
50
+ extra = content[:extra]
51
+ commands = content[:commands]
52
+ if git
53
+ <<-EOF
54
+
55
+ name='#{name}'
56
+ url='#{git}'
57
+
58
+ install_git "$name" "$url" #{extra}
59
+
60
+ #{commands}
61
+ EOF
62
+ elsif src
63
+ <<-EOF
64
+
65
+ name='#{name}'
66
+ url='#{src}'
67
+
68
+ install_src "$name" "$url" #{extra}
69
+
70
+ #{commands}
71
+ EOF
72
+ elsif jar
73
+ <<-EOF
74
+
75
+ name='#{name}'
76
+ url='#{jar}'
77
+
78
+ install_jar "$name" "$url" #{extra}
79
+
80
+ #{commands}
81
+ EOF
82
+ else
83
+ <<-EOF
84
+
85
+ name='#{name}'
86
+ url='#{url}'
87
+
88
+ #{commands}
89
+ EOF
90
+ end
91
+ end
92
+
93
+ script = preamble + "\n" + script_text
94
+ Log.debug "Installing software #{name} into #{software_dir} with script:\n" << script
95
+ CMD.cmd_log('bash', :in => script)
96
+ Resource.set_software_env(software_dir)
97
+ end
98
+
99
+ def self.set_software_env(software_dir = Path.setup('software'))
100
+ software_dir.opt.find_all.collect{|d| d.annotate(File.dirname(d)) }.reverse.each do |software_dir|
101
+ next unless software_dir.exists?
102
+ Log.medium "Preparing software env at #{software_dir}"
103
+
104
+ software_dir = File.expand_path(software_dir)
105
+ opt_dir = File.join(software_dir, 'opt')
106
+ bin_dir = File.join(opt_dir, 'bin')
107
+
108
+ Misc.env_add 'PATH', bin_dir
109
+
110
+ FileUtils.mkdir_p opt_dir unless File.exist? opt_dir
111
+
112
+ %w(.ld-paths .c-paths .pkgconfig-paths .aclocal-paths .java-classpaths).each do |file|
113
+ filename = File.join(opt_dir, file)
114
+ begin
115
+ FileUtils.touch filename unless File.exist? filename
116
+ rescue
117
+ Log.warn("Could not touch #{ filename }")
118
+ end
119
+ end
120
+
121
+ Open.read(File.join opt_dir, '.c-paths').split(/\n/).each do |line|
122
+ dir = line.chomp
123
+ dir = File.join(opt_dir, dir) unless dir[0] == "/"
124
+ Misc.env_add('CPLUS_INCLUDE_PATH',dir)
125
+ Misc.env_add('C_INCLUDE_PATH',dir)
126
+ end if File.exist? File.join(opt_dir, '.c-paths')
127
+
128
+ Open.read(File.join opt_dir, '.ld-paths').split(/\n/).each do |line|
129
+ dir = line.chomp
130
+ dir = File.join(opt_dir, dir) unless dir[0] == "/"
131
+ Misc.env_add('LIBRARY_PATH',dir)
132
+ Misc.env_add('LD_LIBRARY_PATH',dir)
133
+ Misc.env_add('LD_RUN_PATH',dir)
134
+ end if File.exist? File.join(opt_dir, '.ld-paths')
135
+
136
+ Open.read(File.join opt_dir, '.pkgconfig-paths').split(/\n/).each do |line|
137
+ dir = line.chomp
138
+ dir = File.join(opt_dir, dir) unless dir[0] == "/"
139
+ Misc.env_add('PKG_CONFIG_PATH',dir)
140
+ end if File.exist? File.join(opt_dir, '.pkgconfig-paths')
141
+
142
+ Open.read(File.join opt_dir, '.aclocal-paths').split(/\n/).each do |line|
143
+ dir = line.chomp
144
+ dir = File.join(opt_dir, dir) unless dir[0] == "/"
145
+ Misc.env_add('ACLOCAL_FLAGS', "-I #{dir}", ' ')
146
+ end if File.exist? File.join(opt_dir, '.aclocal-paths')
147
+
148
+ Open.read(File.join opt_dir, '.java-classpaths').split(/\n/).each do |line|
149
+ dir = line.chomp
150
+ dir = File.join(opt_dir, dir) unless dir[0] == "/"
151
+ Misc.env_add('CLASSPATH', "#{dir}")
152
+ end if File.exist? File.join(opt_dir, '.java-classpaths')
153
+
154
+ Dir.glob(File.join opt_dir, 'jars', '*.jar').each do |file|
155
+ Misc.env_add('CLASSPATH', "#{file}")
156
+ end
157
+
158
+ if File.exist?(File.join(opt_dir, '.post_install')) and File.directory?(File.join(opt_dir, '.post_install'))
159
+ Dir.glob(File.join(opt_dir, '.post_install','*')).each do |file|
160
+
161
+ # Load exports
162
+ Open.read(file).split("\n").each do |line|
163
+ next unless line =~ /^\s*export\s+([^=]+)=(.*)/
164
+ var = $1.strip
165
+ value = $2.strip
166
+ value.sub!(/^['"]/,'')
167
+ value.sub!(/['"]$/,'')
168
+ value.gsub!(/\$[a-z_0-9]+/i){|var| ENV[var[1..-1]] }
169
+ Log.debug "Set variable export from .post_install: #{Misc.fingerprint [var,value]*"="}"
170
+ ENV[var] = value
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,107 @@
1
+ module TSV
2
+ class Dumper
3
+ def self.header_lines(key_field, fields, entry_hash = nil)
4
+ if Hash === entry_hash
5
+ sep = entry_hash[:sep] ? entry_hash[:sep] : "\t"
6
+ preamble = entry_hash[:preamble]
7
+ header_hash = entry_hash[:header_hash]
8
+ end
9
+
10
+ header_hash = "#" if header_hash.nil?
11
+
12
+ preamble = "#: " << Misc.hash2string(entry_hash.merge(:key_field => nil, :fields => nil)) << "\n" if preamble.nil? and entry_hash and entry_hash.values.compact.any?
13
+
14
+ str = ""
15
+ str << preamble.strip << "\n" if preamble and not preamble.empty?
16
+ if fields
17
+ if fields.empty?
18
+ str << header_hash << (key_field || "ID").to_s << "\n"
19
+ else
20
+ str << header_hash << (key_field || "ID").to_s << sep << (fields * sep) << "\n"
21
+ end
22
+ end
23
+
24
+ str
25
+ end
26
+
27
+ def self.header(options={})
28
+ key_field, fields, sep, header_hash, preamble = IndiferentHash.process_options options,
29
+ :key_field, :fields, :sep, :header_hash, :preamble,
30
+ :sep => "\t", :header_hash => "#", :preamble => true
31
+
32
+ if fields.nil? || key_field.nil?
33
+ fields_str = nil
34
+ else
35
+ fields_str = "#{header_hash}#{key_field}#{sep}#{fields*sep}"
36
+ end
37
+
38
+ if preamble && options.values.compact.any?
39
+ preamble_str = "#: " << IndiferentHash.hash2string(options)
40
+ else
41
+ preamble_str = nil
42
+ end
43
+
44
+ [preamble_str, fields_str].compact * "\n"
45
+ end
46
+
47
+
48
+ attr_accessor :options
49
+ def initialize(options = {})
50
+ @sep, @type = IndiferentHash.process_options options,
51
+ :sep, :type,
52
+ :sep => "\t", :type => :double
53
+ @options = options
54
+ @sout, @sin = Open.pipe
55
+ ConcurrentStream.setup(@sin, :pair => @sout)
56
+ ConcurrentStream.setup(@sout, :pair => @sin)
57
+ end
58
+
59
+ def init
60
+ header = Dumper.header(@options.merge(:type => @type, :sep => @sep))
61
+ @sin.puts header if header and ! header.empty?
62
+ end
63
+
64
+ def add(key, value)
65
+
66
+ case @type
67
+ when :single
68
+ @sin.puts key + @sep + value
69
+ when :list, :flat
70
+ @sin.puts key + @sep + value * @sep
71
+ when :double
72
+ @sin.puts key + @sep + value.collect{|v| v * "|" } * @sep
73
+ end
74
+ end
75
+
76
+ def close
77
+ @sin.close
78
+ @sin.join
79
+ end
80
+
81
+ def stream
82
+ @sout
83
+ end
84
+
85
+ def abort(exception=nil)
86
+ @sin.abort(exception)
87
+ end
88
+ end
89
+
90
+ def stream
91
+ iii self.extension_attr_hash
92
+ dumper = TSV::Dumper.new self.extension_attr_hash
93
+ dumper.init
94
+ Thread.new do
95
+ Thread.current["name"] = "Dumper thread"
96
+ self.each do |k,v|
97
+ dumper.add k, v
98
+ end
99
+ dumper.close
100
+ end
101
+ dumper.stream
102
+ end
103
+
104
+ def to_s
105
+ stream.read
106
+ end
107
+ end
@@ -0,0 +1,49 @@
1
+ require_relative 'parser'
2
+ module TSV
3
+ def self.index(tsv_file, target: 0, order: true, **kwargs)
4
+ persist, type = IndiferentHash.process_options kwargs,
5
+ :persist, :persist_type,
6
+ :persist => false, :persist_type => "HDB"
7
+ kwargs.delete :type
8
+
9
+ Persist.persist(tsv_file, type, kwargs.merge(:persist => persist, :persist_prefix => "Index")) do |filename|
10
+ if filename
11
+ index = ScoutCabinet.open(filename, true, type)
12
+ TSV.setup(index, :type => :single)
13
+ index.extend TSVAdapter
14
+ else
15
+ index = TSV.setup({}, :type => :single)
16
+ end
17
+
18
+ dummy_data = nil
19
+ if order
20
+ tmp_index = {}
21
+ dummy_data = Open.open(tsv_file) do |file|
22
+ TSV.parse file, key_field: target, type: :double, **kwargs do |k,values|
23
+ values.each_with_index do |list,i|
24
+ list.each do |e|
25
+ tmp_index[e] ||= []
26
+ tmp_index[e][i] ||= []
27
+ tmp_index[e][i] << k
28
+ end
29
+ end
30
+ end
31
+ end
32
+ tmp_index.each do |e,list|
33
+ index[e] = list.flatten.compact.uniq.first
34
+ end
35
+ else
36
+ dummy_data = Open.open(tsv_file) do |file|
37
+ TSV.parse file, key_field: target, type: :flat, **kwargs do |k,values|
38
+ values.each do |e|
39
+ index[e] = k unless index.include?(e)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ index.key_field = dummy_data.fields * ", "
45
+ index.fields = [dummy_data.key_field]
46
+ index
47
+ end
48
+ end
49
+ end