scout-gear 5.1.1 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.vimproject +10 -4
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/bin/scout +2 -0
- data/lib/scout/meta_extension.rb +4 -2
- data/lib/scout/misc/format.rb +16 -4
- data/lib/scout/misc/monitor.rb +23 -0
- data/lib/scout/misc.rb +1 -0
- data/lib/scout/open/stream.rb +1 -0
- data/lib/scout/path/find.rb +2 -1
- data/lib/scout/path.rb +1 -1
- data/lib/scout/persist/serialize.rb +15 -4
- data/lib/scout/resource/path.rb +5 -0
- data/lib/scout/resource/util.rb +48 -0
- data/lib/scout/resource.rb +2 -0
- data/lib/scout/simple_opt/doc.rb +26 -2
- data/lib/scout/workflow/definition.rb +8 -2
- data/lib/scout/workflow/documentation.rb +32 -26
- data/lib/scout/workflow/step/info.rb +11 -11
- data/lib/scout/workflow/step/load.rb +18 -0
- data/lib/scout/workflow/step.rb +40 -4
- data/lib/scout/workflow/task/inputs.rb +4 -2
- data/lib/scout/workflow/task.rb +15 -1
- data/lib/scout/workflow/usage.rb +96 -76
- data/lib/scout/workflow.rb +1 -0
- data/scout-gear.gemspec +14 -3
- data/scout_commands/workflow/info +29 -0
- data/scout_commands/workflow/list +27 -0
- data/scout_commands/workflow/task +32 -681
- data/scout_commands/workflow/task_old +706 -0
- data/test/scout/resource/test_util.rb +27 -0
- data/test/scout/simple_opt/test_doc.rb +16 -0
- data/test/scout/test_meta_extension.rb +9 -0
- data/test/scout/workflow/step/test_info.rb +17 -15
- data/test/scout/workflow/step/test_load.rb +65 -0
- data/test/scout/workflow/test_definition.rb +0 -0
- data/test/scout/workflow/test_documentation.rb +30 -0
- data/test/scout/workflow/test_task.rb +1 -0
- data/test/scout/workflow/test_usage.rb +12 -3
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c39189bc9fe8816a3c0494c78966486f28383e8e15bf38ab33fe4dcde6739f3c
|
4
|
+
data.tar.gz: 5f2753e6810a68be44589f9392de1eff2f8592dd2704b05a0ccdf866f07f6a1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 820d17306f468e7b206672b717489f78eb6fbfa37c843441202ce124c54cb7b84b89062a951c14a2db65ada47faf073dbc6a1b863294388ce66a8c1f7dd36e9f
|
7
|
+
data.tar.gz: c0fe23608355128c0e709db78c5598c5ece26e885eaa8788872878b7d55e29fc50bcb8215d3b4080f9e8d89456630e2739b087ee7d8b4b57498b299df3dc89d2
|
data/.vimproject
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
scout-gear=/$PWD filter="*.rb *.yaml" {
|
2
2
|
Rakefile
|
3
|
-
bin=bin
|
3
|
+
bin=bin filter="*"{
|
4
4
|
scout
|
5
|
-
scout_rbbt
|
6
5
|
}
|
7
6
|
scout_commands=scout_commands filter="*"{
|
7
|
+
rbbt
|
8
|
+
alias
|
8
9
|
find
|
9
10
|
glob
|
10
11
|
workflow=workflow{
|
12
|
+
task_old
|
11
13
|
task
|
14
|
+
list
|
15
|
+
info
|
12
16
|
}
|
13
|
-
alias
|
14
17
|
}
|
15
18
|
lib=lib {
|
16
19
|
scout-gear.rb
|
@@ -26,6 +29,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
26
29
|
insist.rb
|
27
30
|
digest.rb
|
28
31
|
filesystem.rb
|
32
|
+
monitor.rb
|
29
33
|
}
|
30
34
|
indiferent_hash.rb
|
31
35
|
indiferent_hash=indiferent_hash{
|
@@ -73,8 +77,9 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
73
77
|
produce=produce{
|
74
78
|
rake.rb
|
75
79
|
}
|
76
|
-
path.rb
|
77
80
|
scout.rb
|
81
|
+
util.rb
|
82
|
+
path.rb
|
78
83
|
}
|
79
84
|
persist.rb
|
80
85
|
persist=persist{
|
@@ -88,6 +93,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
88
93
|
step.rb
|
89
94
|
step=step{
|
90
95
|
info.rb
|
96
|
+
load.rb
|
91
97
|
}
|
92
98
|
task.rb
|
93
99
|
task=task{
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
5.
|
1
|
+
5.2.0
|
data/bin/scout
CHANGED
data/lib/scout/meta_extension.rb
CHANGED
@@ -24,8 +24,10 @@ module MetaExtension
|
|
24
24
|
return if attrs.nil? || attrs.empty?
|
25
25
|
|
26
26
|
if rest.length == 1 && Hash === (rlast = rest.last) &&
|
27
|
-
! (rlkey = rlast.keys.first).nil? &&
|
28
|
-
|
27
|
+
((! (rlkey = rlast.keys.first).nil? && attrs.include?(rlkey.to_sym)) ||
|
28
|
+
(! attrs.length != 1 ))
|
29
|
+
|
30
|
+
|
29
31
|
|
30
32
|
pairs = rlast
|
31
33
|
else
|
data/lib/scout/misc/format.rb
CHANGED
@@ -25,7 +25,14 @@ module Misc
|
|
25
25
|
str
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
|
29
|
+
MAX_WIDTH = 100
|
30
|
+
def self.format_paragraph(text, size = nil, indent = nil, offset = nil)
|
31
|
+
size ||= Log.tty_size || MAX_WIDTH
|
32
|
+
size = MAX_WIDTH if size > MAX_WIDTH
|
33
|
+
indent ||= 0
|
34
|
+
offset ||= 0
|
35
|
+
|
29
36
|
i = 0
|
30
37
|
size = size + offset + indent
|
31
38
|
re = /((?:\n\s*\n\s*)|(?:\n\s*(?=\*)))/
|
@@ -55,7 +62,10 @@ module Misc
|
|
55
62
|
end*""
|
56
63
|
end
|
57
64
|
|
58
|
-
def self.format_definition_list_item(dt, dd,
|
65
|
+
def self.format_definition_list_item(dt, dd, indent = nil, size = nil, color = :yellow)
|
66
|
+
size ||= Log.tty_size || MAX_WIDTH
|
67
|
+
size = MAX_WIDTH if size > MAX_WIDTH
|
68
|
+
indent ||= size / 3
|
59
69
|
dd = "" if dd.nil?
|
60
70
|
dt = Log.color color, dt if color
|
61
71
|
dt = dt.to_s unless dd.empty?
|
@@ -73,10 +83,12 @@ module Misc
|
|
73
83
|
text
|
74
84
|
end
|
75
85
|
|
76
|
-
def self.format_definition_list(defs,
|
86
|
+
def self.format_definition_list(defs, indent = nil, size = nil, color = :yellow, sep = "\n\n")
|
87
|
+
size ||= Log.tty_size || MAX_WIDTH
|
88
|
+
indent ||= 30
|
77
89
|
entries = []
|
78
90
|
defs.each do |dt,dd|
|
79
|
-
text = format_definition_list_item(dt,dd,size,
|
91
|
+
text = format_definition_list_item(dt,dd,indent, size,color)
|
80
92
|
entries << text
|
81
93
|
end
|
82
94
|
entries * sep
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Misc
|
2
|
+
def self.benchmark(repeats = 1, message = nil)
|
3
|
+
require 'benchmark'
|
4
|
+
res = nil
|
5
|
+
begin
|
6
|
+
measure = Benchmark.measure do
|
7
|
+
repeats.times do
|
8
|
+
res = yield
|
9
|
+
end
|
10
|
+
end
|
11
|
+
if message
|
12
|
+
puts "#{message }: #{ repeats } repeats"
|
13
|
+
else
|
14
|
+
puts "Benchmark for #{ repeats } repeats"
|
15
|
+
end
|
16
|
+
puts measure
|
17
|
+
rescue Exception
|
18
|
+
puts "Benchmark aborted"
|
19
|
+
raise $!
|
20
|
+
end
|
21
|
+
res
|
22
|
+
end
|
23
|
+
end
|
data/lib/scout/misc.rb
CHANGED
data/lib/scout/open/stream.rb
CHANGED
@@ -68,6 +68,7 @@ module Open
|
|
68
68
|
block.call if block_given?
|
69
69
|
|
70
70
|
Log.high "Done consuming stream #{Log.fingerprint io} into #{into_path || into}"
|
71
|
+
c
|
71
72
|
rescue Aborted
|
72
73
|
Log.high "Consume stream Aborted #{Log.fingerprint io} into #{into_path || into}"
|
73
74
|
io.abort $! if io.respond_to? :abort
|
data/lib/scout/path/find.rb
CHANGED
@@ -123,7 +123,7 @@ module Path
|
|
123
123
|
|
124
124
|
def follow(map_name = :default, annotate = true)
|
125
125
|
IndiferentHash.setup(path_maps)
|
126
|
-
map = path_maps[map_name]
|
126
|
+
map = path_maps[map_name] || Path.path_maps[map_name]
|
127
127
|
raise "Map not found #{Log.fingerprint map_name} not in #{Log.fingerprint path_maps.keys}" if map.nil?
|
128
128
|
while Symbol === map
|
129
129
|
map_name = map
|
@@ -163,4 +163,5 @@ module Path
|
|
163
163
|
.collect{|where| find(where) }
|
164
164
|
.select{|file| file.exist? }.uniq
|
165
165
|
end
|
166
|
+
|
166
167
|
end
|
data/lib/scout/path.rb
CHANGED
@@ -3,6 +3,7 @@ require_relative 'open'
|
|
3
3
|
|
4
4
|
module Persist
|
5
5
|
TRUE_STRINGS = Set.new ["true", "True", "TRUE", "t", "T", "1", "yes", "Yes", "YES", "y", "Y", "ON", "on"] unless defined? TRUE_STRINGS
|
6
|
+
SERIALIZER = :json
|
6
7
|
|
7
8
|
class << self
|
8
9
|
attr_accessor :save_drivers, :load_drivers
|
@@ -15,6 +16,8 @@ module Persist
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def self.serialize(content, type)
|
19
|
+
type = type.to_sym if String === type
|
20
|
+
type = SERIALIZER if type == :serializer
|
18
21
|
case type
|
19
22
|
when nil, :string, :integer, :float, :boolean, :file, :path
|
20
23
|
if IO === content || StringIO === content
|
@@ -28,7 +31,7 @@ module Persist
|
|
28
31
|
content.to_yaml
|
29
32
|
when :json
|
30
33
|
content.to_json
|
31
|
-
when :marshal
|
34
|
+
when :marshal
|
32
35
|
Marshal.dump(content)
|
33
36
|
else
|
34
37
|
if m = type.to_s.match(/(.*)_array/)
|
@@ -41,6 +44,8 @@ module Persist
|
|
41
44
|
end
|
42
45
|
|
43
46
|
def self.deserialize(serialized, type)
|
47
|
+
type = type.to_sym if String === type
|
48
|
+
type = SERIALIZER if type == :serializer
|
44
49
|
case type
|
45
50
|
when nil, :string, :file, :stream
|
46
51
|
serialized
|
@@ -58,7 +63,7 @@ module Persist
|
|
58
63
|
YAML.parse(serialized)
|
59
64
|
when :json
|
60
65
|
JSON.parse(serialized)
|
61
|
-
when :marshal
|
66
|
+
when :marshal
|
62
67
|
Marshal.load(serialized)
|
63
68
|
else
|
64
69
|
if m = type.to_s.match(/(.*)_array/)
|
@@ -73,6 +78,10 @@ module Persist
|
|
73
78
|
|
74
79
|
MEMORY = {}
|
75
80
|
def self.save(content, file, type = :serializer)
|
81
|
+
type = :serializer if type.nil?
|
82
|
+
type = type.to_sym if String === type
|
83
|
+
type = SERIALIZER if type == :serializer
|
84
|
+
type = MEMORY if type == :memory
|
76
85
|
return if content.nil?
|
77
86
|
type = MEMORY if type == :memory
|
78
87
|
type = :serializer if type.nil?
|
@@ -97,16 +106,18 @@ module Persist
|
|
97
106
|
ConcurrentStream.setup copy, :threads => t, :filename => file, :autojoin => true
|
98
107
|
else
|
99
108
|
serialized = serialize(content, type)
|
100
|
-
Open.sensible_write(file, serialized)
|
109
|
+
Open.sensible_write(file, serialized, :force => true)
|
101
110
|
content
|
102
111
|
end
|
103
112
|
end
|
104
113
|
|
105
114
|
def self.load(file, type = :serializer)
|
106
115
|
file = file.find if Path === file
|
116
|
+
type = :serializer if type.nil?
|
117
|
+
type = type.to_sym if String === type
|
118
|
+
type = SERIALIZER if type == :serializer
|
107
119
|
type = MEMORY if type == :memory
|
108
120
|
return unless Hash === type || Open.exist?(file)
|
109
|
-
type = :serializer if type.nil?
|
110
121
|
|
111
122
|
Log.debug "Load #{Log.fingerprint type} on #{file}"
|
112
123
|
if load_drivers[type]
|
data/lib/scout/resource/path.rb
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Resource
|
2
|
+
def identify(path)
|
3
|
+
return path unless path.start_with?("/")
|
4
|
+
path_maps = path.path_maps || self.path_maps || Path.path_maps
|
5
|
+
path = File.expand_path(path)
|
6
|
+
path += "/" if File.directory?(path)
|
7
|
+
|
8
|
+
map_order ||= (path_maps.keys & Path.basic_map_order) + (path_maps.keys - Path.basic_map_order)
|
9
|
+
map_order -= [:current, "current"]
|
10
|
+
map_order << :current
|
11
|
+
|
12
|
+
choices = []
|
13
|
+
map_order.uniq.each do |name|
|
14
|
+
pattern = path_maps[name]
|
15
|
+
pattern = path_maps[pattern] while Symbol === pattern
|
16
|
+
next if pattern.nil?
|
17
|
+
|
18
|
+
pattern = pattern.sub('{PWD}', Dir.pwd)
|
19
|
+
if String === pattern and pattern.include?('{')
|
20
|
+
regexp = "^" + pattern
|
21
|
+
.gsub(/{(TOPLEVEL)}/,'(?<\1>[^/]+)')
|
22
|
+
.gsub(/{([^}]+)}/,'(?<\1>[^/]+)?') +
|
23
|
+
"(?:/(?<REST>.*))?/?$"
|
24
|
+
if m = path.match(regexp)
|
25
|
+
if ! m.named_captures.include?("PKGDIR") || m["PKGDIR"] == self.pkgdir
|
26
|
+
unlocated = %w(TOPLEVEL SUBPATH PATH REST).collect{|c|
|
27
|
+
m.named_captures.include?(c) ? m[c] : nil
|
28
|
+
}.compact * "/"
|
29
|
+
unlocated.gsub!(/\/+/,'/')
|
30
|
+
unlocated[self.subdir] = "" if self.subdir
|
31
|
+
choices << self.annotate(unlocated)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Path.setup(choices.sort_by{|s| s.length }.first, self, nil, path_maps)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.relocate(path)
|
41
|
+
return path if Open.exists?(path)
|
42
|
+
resource = path.pkgdir if Path === path
|
43
|
+
resource = Scout unless Resource === resource
|
44
|
+
unlocated = resource.identify path
|
45
|
+
unlocated.find
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
data/lib/scout/resource.rb
CHANGED
data/lib/scout/simple_opt/doc.rb
CHANGED
@@ -42,10 +42,33 @@ module SOPT
|
|
42
42
|
"=<#{ type }>"
|
43
43
|
end
|
44
44
|
#extra << " (default: #{Array === default ? (default.length > 3 ? default[0..2]*", " + ', ...' : default*", " ): default})" if default != nil
|
45
|
-
extra << " (default: #{
|
45
|
+
extra << " (default: #{Log.fingerprint(default)})" if default != nil
|
46
46
|
input_str << Log.color(:green, extra)
|
47
47
|
end
|
48
48
|
|
49
|
+
def self.input_array_doc(input_array)
|
50
|
+
input_array.collect do |name,type,description,default,options|
|
51
|
+
type = :string if type.nil?
|
52
|
+
|
53
|
+
name = name.to_s
|
54
|
+
shortcut, options = options, nil if String === options || Symbol === options
|
55
|
+
|
56
|
+
case options && options[:shortcut]
|
57
|
+
when FalseClass
|
58
|
+
shortcut = nil
|
59
|
+
when TrueClass, nil
|
60
|
+
shortcut = fix_shortcut(name[0], name)
|
61
|
+
else
|
62
|
+
shortcut = options[:shortcut]
|
63
|
+
end unless shortcut
|
64
|
+
|
65
|
+
shortcut = fix_shortcut(shortcut, name)
|
66
|
+
register(shortcut, name, type, description) unless self.inputs.include? name
|
67
|
+
name = SOPT.input_format(name, type.to_sym, default, shortcut )
|
68
|
+
Misc.format_definition_list_item(name, description)
|
69
|
+
end * "\n"
|
70
|
+
end
|
71
|
+
|
49
72
|
def self.input_doc(inputs, input_types = nil, input_descriptions = nil, input_defaults = nil, input_shortcuts = nil)
|
50
73
|
type = description = default = nil
|
51
74
|
shortcut = ""
|
@@ -73,10 +96,11 @@ module SOPT
|
|
73
96
|
register(shortcut, name, type, description) unless self.inputs.include? name
|
74
97
|
|
75
98
|
name = SOPT.input_format(name, type.to_sym, default, shortcut)
|
76
|
-
Misc.format_definition_list_item(name, description
|
99
|
+
Misc.format_definition_list_item(name, description)
|
77
100
|
end * "\n"
|
78
101
|
end
|
79
102
|
|
103
|
+
|
80
104
|
def self.doc
|
81
105
|
doc =<<-EOF
|
82
106
|
#{Log.color :magenta}#{command}(1) -- #{summary}
|
@@ -33,6 +33,11 @@ module Workflow
|
|
33
33
|
@annotate_next_task[type] << obj
|
34
34
|
end
|
35
35
|
|
36
|
+
def annotate_next_task_single(type, obj)
|
37
|
+
@annotate_next_task ||= {}
|
38
|
+
@annotate_next_task[type] = obj
|
39
|
+
end
|
40
|
+
|
36
41
|
def dep(*args, &block)
|
37
42
|
case args.length
|
38
43
|
when 3
|
@@ -60,13 +65,14 @@ module Workflow
|
|
60
65
|
@tasks ||= IndiferentHash.setup({})
|
61
66
|
begin
|
62
67
|
@annotate_next_task ||= {}
|
63
|
-
|
68
|
+
task = Task.setup(block, @annotate_next_task.merge(name: name, type: type, directory: directory[name]))
|
69
|
+
@tasks[name] = task
|
64
70
|
ensure
|
65
71
|
@annotate_next_task = {}
|
66
72
|
end
|
67
73
|
end
|
68
74
|
|
69
75
|
def desc(description)
|
70
|
-
|
76
|
+
annotate_next_task_single(:description, description)
|
71
77
|
end
|
72
78
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Workflow
|
2
|
+
attr_accessor :title, :description
|
2
3
|
|
3
4
|
def self.doc_parse_first_line(str)
|
4
5
|
if str.match(/^([^\n]*)\n\n(.*)/sm)
|
@@ -45,33 +46,38 @@ module Workflow
|
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
|
-
def load_documentation
|
49
|
-
return if @documentation
|
50
|
-
@documentation ||= Workflow.parse_workflow_doc documentation_markdown
|
51
|
-
@documentation[:tasks].each do |task, description|
|
52
|
-
if task.include? "#"
|
53
|
-
workflow, task = task.split("#")
|
54
|
-
workflow = begin
|
55
|
-
Kernel.const_get workflow
|
56
|
-
rescue
|
57
|
-
next
|
58
|
-
end
|
59
|
-
else
|
60
|
-
workflow = self
|
61
|
-
end
|
62
|
-
|
63
|
-
task = task.to_sym
|
64
|
-
if workflow.tasks.include? task
|
65
|
-
workflow.tasks[task].description = description
|
66
|
-
else
|
67
|
-
Log.low "Documentation for #{ task }, but not a #{ workflow.to_s } task"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
49
|
attr_accessor :documentation
|
73
50
|
def documentation
|
74
|
-
|
75
|
-
|
51
|
+
@documentation ||= begin
|
52
|
+
documentation = Workflow.parse_workflow_doc documentation_markdown
|
53
|
+
|
54
|
+
if @description && (documentation[:description].nil? || documentation[:description].empty?)
|
55
|
+
documentation[:description] = @description
|
56
|
+
end
|
57
|
+
|
58
|
+
if @title && (documentation[:title].nil? || documentation[:title].empty?)
|
59
|
+
documentation[:title] = @title
|
60
|
+
end
|
61
|
+
documentation[:tasks].each do |task, description|
|
62
|
+
if task.include? "#"
|
63
|
+
workflow, task = task.split("#")
|
64
|
+
workflow = begin
|
65
|
+
Kernel.const_get workflow
|
66
|
+
rescue
|
67
|
+
next
|
68
|
+
end
|
69
|
+
else
|
70
|
+
workflow = self
|
71
|
+
end
|
72
|
+
|
73
|
+
task = task.to_sym
|
74
|
+
if workflow.tasks.include? task
|
75
|
+
workflow.tasks[task].description = description
|
76
|
+
else
|
77
|
+
Log.low "Documentation for #{ task }, but not a #{ workflow.to_s } task"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
documentation
|
81
|
+
end
|
76
82
|
end
|
77
83
|
end
|
@@ -1,15 +1,21 @@
|
|
1
1
|
class Step
|
2
|
+
SERIALIZER = :json
|
2
3
|
def info_file
|
3
|
-
@info_file ||=
|
4
|
+
@info_file ||= begin
|
5
|
+
info_file = @path + ".info"
|
6
|
+
@path.annotate info_file if Path === @path
|
7
|
+
info_file
|
8
|
+
end
|
4
9
|
end
|
5
10
|
|
6
11
|
def load_info
|
7
|
-
@info = Persist.load(info_file,
|
12
|
+
@info = Persist.load(info_file, SERIALIZER) || {}
|
13
|
+
IndiferentHash.setup(@info)
|
8
14
|
@info_load_time = Time.now
|
9
15
|
end
|
10
16
|
|
11
|
-
def save_info
|
12
|
-
Persist.save(
|
17
|
+
def save_info(info = nil)
|
18
|
+
Persist.save(info, info_file, SERIALIZER)
|
13
19
|
@info_load_time = Time.now
|
14
20
|
end
|
15
21
|
|
@@ -40,19 +46,13 @@ class Step
|
|
40
46
|
info[key] = value
|
41
47
|
end
|
42
48
|
end
|
43
|
-
save_info
|
49
|
+
save_info(info)
|
44
50
|
end
|
45
51
|
|
46
52
|
def set_info(key, value)
|
47
53
|
merge_info(key => value)
|
48
54
|
end
|
49
55
|
|
50
|
-
def init_info
|
51
|
-
@info = {
|
52
|
-
:status => :waiting
|
53
|
-
}
|
54
|
-
end
|
55
|
-
|
56
56
|
def report_status(status, message = nil)
|
57
57
|
if message.nil?
|
58
58
|
Log.info Log.color(:green, status.to_s) + " " + Log.color(:blue, path)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Step
|
2
|
+
def self.relocate(path)
|
3
|
+
return path if Open.exists?(path)
|
4
|
+
Path.setup(path) unless Path === path
|
5
|
+
relocated = path.relocate
|
6
|
+
return relocated if Open.exists?(relocated)
|
7
|
+
subpath = path.split("/")[-3..-1] * "/"
|
8
|
+
relocated = Path.setup("var/jobs")[subpath]
|
9
|
+
return relocated if Open.exists?(relocated)
|
10
|
+
path
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.load(path)
|
14
|
+
path = relocate(path) unless Open.exists?(path)
|
15
|
+
raise "Could not load #{path}" unless Open.exists?(path)
|
16
|
+
s = Step.new path
|
17
|
+
end
|
18
|
+
end
|
data/lib/scout/workflow/step.rb
CHANGED
@@ -1,20 +1,43 @@
|
|
1
1
|
require_relative '../path'
|
2
2
|
require_relative '../persist'
|
3
3
|
require_relative 'step/info'
|
4
|
+
require_relative 'step/load'
|
4
5
|
|
5
6
|
class Step
|
6
7
|
|
7
8
|
attr_accessor :path, :inputs, :dependencies, :task
|
8
|
-
def initialize(path, inputs = nil, dependencies =
|
9
|
+
def initialize(path, inputs = nil, dependencies = nil, &task)
|
9
10
|
@path = path
|
10
11
|
@inputs = inputs
|
11
12
|
@dependencies = dependencies
|
12
13
|
@task = task
|
13
14
|
end
|
14
15
|
|
16
|
+
def inputs
|
17
|
+
@inputs ||= begin
|
18
|
+
if Open.exists?(info_file)
|
19
|
+
info[:inputs]
|
20
|
+
else
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def dependencies
|
27
|
+
@dependencies ||= begin
|
28
|
+
if Open.exists?(info_file)
|
29
|
+
info[:dependencies].collect do |path|
|
30
|
+
Step.load(path)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
[]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
15
38
|
attr_accessor :type
|
16
39
|
def type
|
17
|
-
@type ||= @task.respond_to?(:type) ? @task.type :
|
40
|
+
@type ||= @task.respond_to?(:type) ? @task.type : info[:type]
|
18
41
|
end
|
19
42
|
|
20
43
|
def name
|
@@ -31,14 +54,15 @@ class Step
|
|
31
54
|
|
32
55
|
attr_reader :result
|
33
56
|
def run
|
57
|
+
return @result || self.load if done?
|
58
|
+
dependencies.each{|dep| dep.run }
|
34
59
|
@result = Persist.persist(name, type, :path => path) do
|
35
60
|
begin
|
36
61
|
merge_info :status => :start, :start => Time.now,
|
37
62
|
:pid => Process.pid, :pid_hostname => ENV["HOSTNAME"],
|
38
|
-
:inputs => inputs,
|
63
|
+
:inputs => inputs, :type => type,
|
39
64
|
:dependencies => dependencies.collect{|d| d.path }
|
40
65
|
|
41
|
-
dependencies.each{|dep| dep.run }
|
42
66
|
@result = exec
|
43
67
|
ensure
|
44
68
|
if streaming?
|
@@ -61,6 +85,11 @@ class Step
|
|
61
85
|
IO === @result || StringIO === @result
|
62
86
|
end
|
63
87
|
|
88
|
+
def stream
|
89
|
+
join
|
90
|
+
streaming? ? @result : Open.open(path)
|
91
|
+
end
|
92
|
+
|
64
93
|
def join
|
65
94
|
if streaming?
|
66
95
|
Open.consume_stream(@result, false)
|
@@ -83,6 +112,13 @@ class Step
|
|
83
112
|
FileUtils.rm path.find if path.exist?
|
84
113
|
end
|
85
114
|
|
115
|
+
def recursive_clean
|
116
|
+
dependencies.each do |dep|
|
117
|
+
dep.recursive_clean
|
118
|
+
end
|
119
|
+
clean
|
120
|
+
end
|
121
|
+
|
86
122
|
def step(task_name)
|
87
123
|
dependencies.each do |dep|
|
88
124
|
return dep if dep.task_name == task_name
|
@@ -22,7 +22,7 @@ module Task
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def assign_inputs(provided_inputs = {})
|
25
|
-
if self.inputs.nil?
|
25
|
+
if self.inputs.nil? || (self.inputs.empty? && Array === provided_inputs)
|
26
26
|
case provided_inputs
|
27
27
|
when Array
|
28
28
|
return [provided_inputs, provided_inputs]
|
@@ -31,6 +31,8 @@ module Task
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
IndiferentHash.setup(provided_inputs) if Hash === provided_inputs
|
35
|
+
|
34
36
|
input_array = []
|
35
37
|
non_default_inputs = []
|
36
38
|
self.inputs.each_with_index do |p,i|
|
@@ -58,7 +60,7 @@ module Task
|
|
58
60
|
end
|
59
61
|
|
60
62
|
def process_inputs(provided_inputs = {})
|
61
|
-
input_array, non_default_inputs = assign_inputs
|
63
|
+
input_array, non_default_inputs = assign_inputs provided_inputs
|
62
64
|
digest = Misc.digest(input_array)
|
63
65
|
[input_array, non_default_inputs, digest]
|
64
66
|
end
|