laborantin 0.0.14 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/INFO +1 -0
  2. data/README +148 -4
  3. data/Rakefile +73 -27
  4. data/TODO +27 -6
  5. data/bin/labor +2 -404
  6. data/lib/laborantin.rb +13 -26
  7. data/lib/laborantin/core/analysis.rb +231 -0
  8. data/lib/laborantin/core/command.rb +234 -0
  9. data/lib/laborantin/core/completeable.rb +30 -0
  10. data/lib/laborantin/core/configurable.rb +28 -0
  11. data/lib/laborantin/core/datable.rb +13 -0
  12. data/lib/laborantin/core/describable.rb +11 -0
  13. data/lib/laborantin/core/environment.rb +90 -52
  14. data/lib/laborantin/core/hookable.rb +20 -0
  15. data/lib/laborantin/core/monkey_patches.rb +0 -1
  16. data/lib/laborantin/core/multi_name.rb +25 -0
  17. data/lib/laborantin/core/parameter.rb +5 -12
  18. data/lib/laborantin/core/parameter_hash.rb +6 -2
  19. data/lib/laborantin/core/scenario.rb +93 -70
  20. data/lib/laborantin/core/table.rb +84 -0
  21. data/lib/laborantin/extra/commands/git.rb +40 -0
  22. data/lib/laborantin/extra/commands/git/check.rb +25 -0
  23. data/lib/laborantin/extra/commands/git/run.rb +100 -0
  24. data/lib/laborantin/extra/vectorial_product.rb +31 -0
  25. data/lib/laborantin/runner.rb +247 -0
  26. data/lib/laborantin/runner/commands/analyze.rb +58 -0
  27. data/lib/laborantin/runner/commands/cleanup.rb +40 -0
  28. data/lib/laborantin/runner/commands/complete.rb +111 -0
  29. data/lib/laborantin/runner/commands/config.rb +169 -0
  30. data/lib/laborantin/runner/commands/create.rb +61 -0
  31. data/lib/laborantin/runner/commands/describe.rb +215 -0
  32. data/lib/laborantin/runner/commands/find.rb +82 -0
  33. data/lib/laborantin/runner/commands/load_classes.rb +75 -0
  34. data/lib/laborantin/runner/commands/load_results.rb +143 -0
  35. data/lib/laborantin/runner/commands/note.rb +35 -0
  36. data/lib/laborantin/runner/commands/replay.rb +89 -0
  37. data/lib/laborantin/runner/commands/rm.rb +107 -0
  38. data/lib/laborantin/runner/commands/run.rb +131 -0
  39. data/lib/laborantin/runner/commands/scan.rb +77 -0
  40. metadata +45 -13
  41. data/bin/files/README.erb +0 -29
  42. data/bin/files/TODO.erb +0 -2
  43. data/bin/files/config/ftp.yaml.erb +0 -6
  44. data/bin/files/config/xmpp.yaml.erb +0 -7
  45. data/bin/files/environments/environment.rb.erb +0 -10
  46. data/bin/files/scenarii/scenario.rb.erb +0 -13
@@ -0,0 +1,58 @@
1
+ #runner/commands/analyze.rb
2
+
3
+ =begin
4
+
5
+ This file is part of Laborantin.
6
+
7
+ Laborantin is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Laborantin is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with Laborantin. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ Copyright (c) 2009, Lucas Di Cioccio
21
+
22
+ =end
23
+
24
+ module Laborantin
25
+ module Commands
26
+ class Analyze < Command
27
+ describe "Runs the analyses"
28
+
29
+ option(:analyses) do
30
+ describe "comma separated list of analyses"
31
+ short '-a'
32
+ long '--analyses=OPTIONAL'
33
+ default []
34
+ type Array
35
+ complete do |cmd|
36
+ completion_propositions_iterating_on(cmd, Laborantin::Analysis.all.map(&:cli_name))
37
+ end
38
+ end
39
+
40
+ execute do
41
+ anae = if opts[:analyses].empty?
42
+ Analysis.all
43
+ else
44
+ Analysis.all.select do |e|
45
+ opts[:analyses].find do |cli_name|
46
+ cli_name == e.cli_name
47
+ end
48
+ end
49
+ end
50
+
51
+ anae.each do |klass|
52
+ puts "Analyzing: #{klass.name}"
53
+ klass.new.analyze
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,40 @@
1
+ #runner/commands/cleanup.rb
2
+
3
+ =begin
4
+
5
+ This file is part of Laborantin.
6
+
7
+ Laborantin is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Laborantin is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with Laborantin. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ Copyright (c) 2009, Lucas Di Cioccio
21
+
22
+ =end
23
+
24
+ module Laborantin
25
+ module Commands
26
+ class Cleanup < Command
27
+ plumbery!
28
+ describe "Removes the result directories of the environments without scenarios"
29
+ execute do
30
+ results = Laborantin::Commands::LoadResults.new.run([],opts)
31
+ results[:envs].each do |env|
32
+ scii = env.populate
33
+ if scii.empty?
34
+ FileUtils.rm_rf(env.rundir, :verbose => true)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,111 @@
1
+
2
+ #$DEBUG = true
3
+
4
+ module Laborantin
5
+ module Commands
6
+ class Complete < Laborantin::Command
7
+ describe "completes a command line"
8
+ plumbery!
9
+
10
+ def maps_to_a_klass?(cmd)
11
+ runner.command_for_argv(cmd.split(' '))
12
+ end
13
+
14
+ def list_mapping_klasses(str)
15
+ #separate the case for modules
16
+ # labor config <tab>
17
+ # should propose config set|foo
18
+ if str == 'labor'
19
+ Command.reject(&:plumbery?).map{|cmd| runner.argv_klass_name(cmd).first}
20
+ else
21
+ size = str.split.size
22
+ cmds = Command.reject{|cmd| cmd.plumbery?}.map do |cmd|
23
+ runner.argv_klass_name(cmd).slice(0, size)
24
+ end
25
+
26
+ match = cmds.find do |cmd|
27
+ cmd.join(' ') == str
28
+ end
29
+
30
+ if match
31
+ cmds = Command.reject{|cmd| cmd.plumbery?}.map do |cmd|
32
+ runner.argv_klass_name(cmd).slice(0, size+1)
33
+ end
34
+ end
35
+
36
+ cmds.select do |cmd|
37
+ tst = cmd.join(' ').start_with?(str)
38
+ STDERR.puts "#{cmd} | #{str} | #{tst}" if $DEBUG
39
+ tst
40
+ end.map do |cmd|
41
+ cmd.last
42
+ end
43
+ end
44
+ end
45
+
46
+ def complete_option(opt, cmd)
47
+ opt.completion_block.call(cmd) if opt.completion_block
48
+ end
49
+
50
+ def list_long_option(klass, cmd)
51
+ # in the options of the command look for the one with long
52
+ opt = klass.options.find{|o| o.cli_long == cmd.split.last}
53
+
54
+ if opt
55
+ complete_option(opt,cmd)
56
+ else
57
+ end
58
+ end
59
+
60
+ def list_short_option(klass, cmd)
61
+ # in the options of the command look for the one with long
62
+ opt = klass.options.find{|o| o.cli_short == cmd.split.last}
63
+ if opt
64
+ complete_option(opt,cmd)
65
+ else
66
+ if cmd.split[-2].start_with?('-')
67
+ opt = klass.options.find{|o| o.cli_short == cmd.split[-2]}
68
+ complete_option(opt,cmd) if opt
69
+ else
70
+ klass.options.map(&:cli_short).select{|w|
71
+ w.start_with?(cmd)
72
+ }
73
+ end
74
+ end
75
+ end
76
+
77
+ def list_argv_and_options_line(klass, cmd)
78
+ klass.completion_block.call(cmd) if klass.completion_block
79
+ end
80
+
81
+ execute do |me|
82
+ STDERR.puts me.args if $DEBUG
83
+ cmd = STDIN.read.chomp
84
+ arg = me.args
85
+ cmd = cmd.sub(/^labor\s+/,'')
86
+
87
+ klass = maps_to_a_klass?(cmd)
88
+ list = if klass
89
+ if cmd.split.last.start_with?('--')
90
+ list_long_option(klass, cmd)
91
+ elsif cmd.split.last.start_with?('-')
92
+ list_short_option(klass, cmd)
93
+ elsif cmd.split[-2] and cmd.split[-2].start_with?('--')
94
+ list_long_option(klass, cmd)
95
+ elsif cmd.split[-2] and cmd.split[-2].start_with?('-')
96
+ list_short_option(klass, cmd)
97
+ else
98
+ list_argv_and_options_line(klass, cmd)
99
+ end
100
+ else
101
+ # complete finding a class
102
+ list_mapping_klasses(cmd)
103
+ end
104
+
105
+ list ||= []
106
+
107
+ puts list.compact.uniq.join("\n")
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,169 @@
1
+
2
+ module Laborantin::Commands
3
+ module Config
4
+
5
+ class ConfigError < StandardError ; end
6
+
7
+ class PathError < ConfigError ; end
8
+
9
+ class RootNotHashError < PathError
10
+ def initialize
11
+ super "The root node of the config must be a Hash"
12
+ end
13
+ end
14
+
15
+ class PathNotHashError < PathError
16
+ def initialize(path)
17
+ super "There already is a non-hash value at: '#{path}'."
18
+ end
19
+ end
20
+
21
+ # Stores the runner configuration into the configuration file.
22
+ def save_config
23
+ raise RootNotHashError unless runner.config.is_a? Hash
24
+ File.open(runner.config_path, 'w') do |f|
25
+ f.puts YAML.dump(runner.config)
26
+ end
27
+ end
28
+
29
+ # Interprets a string provided path as an array of symbols (the nodes of the config tree).
30
+ def interpret_path(path)
31
+ path.split(':').map{|i| i.to_sym}
32
+ end
33
+
34
+ # Interprets a string provided value into a ruby object.
35
+ # * if val is 'true' then the true object of class TrueClass
36
+ # * if val is 'false' then the false object of class FalseClass * if val is
37
+ # a string that can be read like a decimal, it's a decimal (Fixnum or
38
+ # Bignum), unlike in ruby interpreter 1_000 is not valid for 1000, see
39
+ # source for details * otherwise the string val itself
40
+ def interpret_value(val)
41
+ case val
42
+ when 'true'
43
+ true
44
+ when 'false'
45
+ false
46
+ when val.to_i.to_s == val
47
+ val.to_i
48
+ else
49
+ val
50
+ end
51
+ end
52
+
53
+ # Given a path made of an array of nodes (i.e., symbols to respect the syntax).
54
+ # Returns the object corresponding to this node in the configuration tree.
55
+ # Returns nil if there is no such object.
56
+ # If path is empty, simply returns the root node (i.e., the runner's config).
57
+ def get_node(path)
58
+ tree = runner.config
59
+ return tree if path.empty? #easy solution
60
+ path = path.clone
61
+ while (node = path.shift)
62
+ if tree.is_a? Hash
63
+ if path.empty? #terminal node
64
+ return tree[node]
65
+ else
66
+ tree = tree[node]
67
+ end
68
+ else #error
69
+ return nil
70
+ end
71
+ end
72
+ end
73
+
74
+ # Creates a path structure in the runner's config.
75
+ # If there already a non-hash node, will raise an error.
76
+ def build_path(path_arg)
77
+ path = path_arg.clone
78
+ tree = runner.config
79
+ while (node = path.shift)
80
+ case tree[node]
81
+ when Hash
82
+ tree = tree[node]
83
+ when NilClass
84
+ tree[node] = Hash.new
85
+ tree = tree[node]
86
+ else
87
+ raise PathNotHashError.new(orig.join(':'))
88
+ end
89
+ end
90
+ end
91
+
92
+ class Get < Laborantin::Command
93
+ include Config
94
+ describe "Show a configuration tree"
95
+ option(:path) do
96
+ describe "a column separated path of the config"
97
+ short '-p'
98
+ long '--path=OPTIONAL'
99
+ type String
100
+ default ''
101
+ end
102
+ execute do
103
+ path = interpret_path(opts[:path])
104
+ p get_node(path)
105
+ end
106
+ end
107
+
108
+ class Set < Laborantin::Command
109
+ include Config
110
+ describe "Set a configuration node"
111
+ option(:path) do
112
+ describe "a column separated path of the config"
113
+ short '-p'
114
+ long '--path=MANDATORY'
115
+ type String
116
+ default ''
117
+ end
118
+ option(:value) do
119
+ describe "the value to set the node to, interprets true, false, decimal integers, or string"
120
+ short '-v'
121
+ long '--value=MANDATORY'
122
+ type String
123
+ default ''
124
+ end
125
+ execute do
126
+ path = interpret_path(opts[:path])
127
+ value = interpret_value(opts[:value])
128
+ if path.empty?
129
+ puts "--path= should not be empty"
130
+ end
131
+ if value.is_a? String and value.empty?
132
+ puts "--value= should not be empty"
133
+ end
134
+
135
+ node = path.pop
136
+ begin
137
+ build_path(path)
138
+ rescue PathError => err
139
+ puts err
140
+ exit
141
+ end
142
+ get_node(path)[node] = value
143
+ save_config
144
+ end
145
+ end
146
+
147
+ class Del < Laborantin::Command
148
+ include Config
149
+ describe "Deletes a node from the configuration tree."
150
+ option(:path) do
151
+ describe "a column separated path"
152
+ short '-p'
153
+ long '--path=MANDATORY'
154
+ type String
155
+ default ''
156
+ end
157
+ execute do
158
+ path = interpret_path(opts[:path])
159
+ if path.empty?
160
+ puts "Cannot delete empty path, if you really want, remove #{runner.config_path}"
161
+ end
162
+ node = path.pop
163
+ tree = get_node(path)
164
+ tree.delete(node)
165
+ save_config
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,61 @@
1
+ #runner/commands/create.rb
2
+
3
+ =begin
4
+
5
+ This file is part of Laborantin.
6
+
7
+ Laborantin is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Laborantin is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with Laborantin. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ Copyright (c) 2009, Lucas Di Cioccio
21
+
22
+ =end
23
+
24
+ require 'fileutils'
25
+ require 'find'
26
+ require 'erb'
27
+
28
+ module Laborantin
29
+ module Commands
30
+ class Create < Command
31
+ describe "prepares a directory structure for Laborantin"
32
+
33
+ option(:force) do
34
+ describe 'force overwrite, use with care'
35
+ short '-f'
36
+ long '--force'
37
+ default false
38
+ end
39
+
40
+ execute do
41
+ #Build Tree Structure
42
+ dirs_to_build = []
43
+
44
+ rootdir = File.join('.', (args.first) || '')
45
+
46
+ dirs_to_build << rootdir
47
+
48
+ %w{analyses commands lib config environments reports results scripts scenarii}.each do |dirname|
49
+ dirs_to_build << File.join(rootdir, dirname)
50
+ end
51
+
52
+ dirs_to_build.each do |path|
53
+ FileUtils::Verbose.mkdir_p(path)
54
+ end
55
+
56
+ #TODO: create a README, a NOTEBOOK
57
+ end
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,215 @@
1
+ #runner/commands/describe.rb
2
+
3
+ =begin
4
+
5
+ This file is part of Laborantin.
6
+
7
+ Laborantin is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Laborantin is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with Laborantin. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ Copyright (c) 2009, Lucas Di Cioccio
21
+
22
+ =end
23
+
24
+ autoload :ERB, 'erb'
25
+ module Laborantin
26
+ module Commands
27
+ class Describe < Command
28
+ describe "Gives a summary of what the current Laborantin project is"
29
+
30
+
31
+ option(:scenarii) do
32
+ describe "comma separated list of scenarios to describe"
33
+ short "-s"
34
+ long "--scenarii=OPTIONAL"
35
+ type Array
36
+ default []
37
+ complete do |cmd|
38
+ completion_propositions_iterating_on(cmd, Laborantin::Scenario.all.map(&:cli_name))
39
+ end
40
+ end
41
+
42
+ option(:environments) do
43
+ describe "comma separated list of environments to describe"
44
+ short "-e"
45
+ long "--envs=OPTIONAL"
46
+ type Array
47
+ default []
48
+ complete do |cmd|
49
+ completion_propositions_iterating_on(cmd, Laborantin::Environment.all.map(&:cli_name))
50
+ end
51
+ end
52
+
53
+ option(:analyses) do
54
+ describe "comma separated list of analyses to describe"
55
+ short "-a"
56
+ long "--analyses=OPTIONAL"
57
+ type Array
58
+ default []
59
+ complete do |cmd|
60
+ completion_propositions_iterating_on(cmd, Laborantin::Analysis.all.map(&:cli_name))
61
+ end
62
+ end
63
+
64
+ option(:output) do
65
+ describe "print in a file instead of STDOUT"
66
+ short '-o'
67
+ long '--output=OPTIONAL'
68
+ type String
69
+ default ''
70
+ end
71
+
72
+ FORMATS = ['default', 'txt', 'html']
73
+
74
+ option(:format) do
75
+ describe "format the output in a certain form, among: [#{FORMATS.join(', ')}]"
76
+ short '-f'
77
+ long '--format=OPTIONAL'
78
+ type String
79
+ default 'default'
80
+ end
81
+
82
+ def stdout?
83
+ opts[:output].empty?
84
+ end
85
+
86
+ def out
87
+ @out ||= if stdout?
88
+ self #self.puts forward to the runner
89
+ else
90
+ File.open(opts[:output], 'w')
91
+ end
92
+ end
93
+
94
+ def close_out
95
+ @out.close unless stdout?
96
+ end
97
+
98
+ def environments
99
+ Environment.all
100
+ end
101
+
102
+ def scenarii
103
+ Scenario.all
104
+ end
105
+
106
+ def analyses
107
+ Analysis.all
108
+ end
109
+
110
+
111
+ HTML_TPL = <<ERB
112
+ <html>
113
+ <head>
114
+ </head>
115
+ <body>
116
+ <h1>Laborantin's description</h1>
117
+ <p>Project located at: <%= runner.root_dir %> </p>
118
+ <h2>List of environments</h2>
119
+ <ul>
120
+ <% Environment.all.each do |env| %>
121
+ <li><%= env.name %>
122
+ (<%= env.description %>)
123
+ </li>
124
+ <% end %>
125
+ </ul>
126
+ <h2>List of scenarios</h2>
127
+ <ul>
128
+ <% Scenario.all.each do |sc| %>
129
+ <li><%= sc.name %>
130
+ (<%= sc.description %>)
131
+ <ul>
132
+ <% sc.parameters.each_pair do |name, spec| %>
133
+ <li><%= name %></li>
134
+ <ul>
135
+ <li><%= spec.description %></li>
136
+ <li><%= spec.values.inspect %></li>
137
+ </ul>
138
+ <% end %>
139
+ </ul>
140
+ </li>
141
+ <% end %>
142
+ </ul>
143
+ <h2>List of analyses</h2>
144
+ <ul>
145
+ <% Analysis.all.each do |a| %>
146
+ <li><%= a.name %>
147
+ (<%= a.description %>)
148
+ <ul>
149
+ <% a.analyses.each do |hash| %>
150
+ <li>
151
+ <%= hash[:str] %>
152
+ </li>
153
+ <% end %>
154
+ </ul>
155
+ </li>
156
+ <% end %>
157
+ </ul>
158
+ </body>
159
+ </html>
160
+ ERB
161
+
162
+ TXT_TPL = <<ERB
163
+ Available environments:
164
+ <% Environment.all.each do |env| %>
165
+ * <%= env.name %> (<%= env.description %>)
166
+ <% end %>
167
+ Available scenarios:
168
+ <% Scenario.all.each do |sc| %>
169
+ * <%= sc.name %> (<%= sc.description %>)
170
+ <% sc.parameters.each_pair do |name, spec| %>
171
+ + <%= name %> (<%= spec.description %>) | <%= spec.values.inspect %>
172
+ <% end %>
173
+ <% end %>
174
+ Available analyses:
175
+ <% Analysis.all.each do |a| %>
176
+ * <%= a.name %> (<%= a.description %>)
177
+ <% a.analyses.each do |hash| %>
178
+ <% if hash[:params][:type] %>
179
+ + <%= hash[:str] %> (<%= hash[:params][:type] %>)
180
+ <% else %>
181
+ + <%= hash[:str] %>
182
+ <% end %>
183
+ <% end %>
184
+ <% end %>
185
+ ERB
186
+
187
+ def html_format
188
+ ERB.new(HTML_TPL).result(binding)
189
+ end
190
+
191
+ def txt_format
192
+ ERB.new(TXT_TPL).result(binding).lines.reject{|l| l =~/^\s*$/}.join
193
+ end
194
+
195
+ alias :default_format :txt_format
196
+
197
+ def format_str
198
+ case opts[:format]
199
+ when 'html'
200
+ html_format
201
+ else
202
+ default_format
203
+ end
204
+ end
205
+
206
+ execute do
207
+ begin
208
+ out.puts format_str
209
+ ensure
210
+ close_out
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end