scout-gear 5.1.1 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|