rbbt-util 5.22.4 → 5.22.5
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/lib/rbbt/annotations.rb +1 -1
- data/lib/rbbt/monitor.rb +3 -2
- data/lib/rbbt/resource.rb +1 -4
- data/lib/rbbt/resource/path.rb +4 -2
- data/lib/rbbt/util/concurrency/processes.rb +2 -1
- data/lib/rbbt/util/docker.rb +7 -3
- data/lib/rbbt/util/misc.rb +20 -0
- data/lib/rbbt/util/open.rb +47 -2
- data/lib/rbbt/workflow.rb +6 -3
- data/lib/rbbt/workflow/accessor.rb +75 -17
- data/lib/rbbt/workflow/step.rb +21 -5
- data/lib/rbbt/workflow/step/dependencies.rb +1 -1
- data/lib/rbbt/workflow/step/run.rb +9 -2
- data/lib/rbbt/workflow/usage.rb +6 -1
- data/share/install/software/lib/install_helpers +41 -5
- data/share/rbbt_commands/system/clean +16 -3
- data/share/rbbt_commands/system/status +3 -1
- data/share/rbbt_commands/tsv/get +4 -1
- data/share/rbbt_commands/workflow/info +3 -1
- data/share/rbbt_commands/workflow/prov +13 -8
- data/share/rbbt_commands/workflow/task +12 -1
- data/test/rbbt/resource/test_path.rb +13 -3
- data/test/rbbt/test_resource.rb +2 -1
- data/test/rbbt/test_tsv.rb +1 -1
- data/test/rbbt/test_workflow.rb +28 -0
- data/test/rbbt/util/test_misc.rb +8 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c617d4a4ffaed12ddf8a5cdf44a4ff5113e47d0
|
4
|
+
data.tar.gz: 74125cd2876fff8d7c097d89eee4adb47f61a26c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81bf1cb9b56203f6ab747ef961fc920146e07b78e2a220fdf2e9174adfd0effbf01974e4560ff6759c2e180d4ce03ea6c2db4fc2a047e07162c342a265735b8f
|
7
|
+
data.tar.gz: c4ef6e26f7683f2365f9ca15cfc045cf69a04a174d2f59a0dce0a22ede010b22f962d17d9bc03f73469338c1c47c2c6cf33a6d65173e387e6f71c633462fabfc
|
data/lib/rbbt/annotations.rb
CHANGED
data/lib/rbbt/monitor.rb
CHANGED
@@ -146,12 +146,13 @@ module Rbbt
|
|
146
146
|
task = File.basename(taskdir)
|
147
147
|
next if tasks and not tasks.include? task
|
148
148
|
|
149
|
-
cmd = "find -L '#{ taskdir }/'
|
149
|
+
#cmd = "find -L '#{ taskdir }/' -not \\( -path \"#{taskdir}/*.files/*\" -prune \\) -not -name '*.pid' -not -name '*.notify' -not -name '\\.*' 2>/dev/null"
|
150
|
+
cmd = "find -L '#{ taskdir }/' -not \\( -path \"#{taskdir}/*.files/*\" -prune \\) -not -name '*.pid' -not -name '*.notify' -not -name '\\.*' \\( -not -type d -o -name '*.files' \\) 2>/dev/null"
|
150
151
|
|
151
152
|
files = CMD.cmd(cmd, :pipe => true)
|
152
153
|
TSV.traverse files, :type => :array, :into => jobs, :_bar => "Finding jobs in #{ taskdir }" do |file|
|
153
154
|
_files << file
|
154
|
-
if m = file.match(/(.*)
|
155
|
+
if m = file.match(/(.*)\.(info|pid|files)$/)
|
155
156
|
file = m[1]
|
156
157
|
end
|
157
158
|
next if seen.include? file
|
data/lib/rbbt/resource.rb
CHANGED
@@ -194,10 +194,7 @@ source "$INSTALL_HELPER_FILE"
|
|
194
194
|
EOF
|
195
195
|
|
196
196
|
script = preamble + "\n" + Open.read(content)
|
197
|
-
|
198
|
-
while line = install_io.gets
|
199
|
-
Log.debug line
|
200
|
-
end
|
197
|
+
CMD.cmd_log('bash', :in => script)
|
201
198
|
|
202
199
|
set_software_env(software_dir)
|
203
200
|
else
|
data/lib/rbbt/resource/path.rb
CHANGED
@@ -141,7 +141,7 @@ module Path
|
|
141
141
|
if self.match(/(.*?)\/(.*)/)
|
142
142
|
toplevel, subpath = self.match(/(.*?)\/(.*)/).values_at 1, 2
|
143
143
|
else
|
144
|
-
toplevel, subpath =
|
144
|
+
toplevel, subpath = "{REMOVE}", self
|
145
145
|
end
|
146
146
|
|
147
147
|
path = nil
|
@@ -199,7 +199,9 @@ module Path
|
|
199
199
|
sub('{SUBPATH}', subpath).
|
200
200
|
sub('{BASENAME}', File.basename(self)).
|
201
201
|
sub('{PATH}', self).
|
202
|
-
sub('{LIBDIR}', libdir)
|
202
|
+
sub('{LIBDIR}', libdir).
|
203
|
+
sub('{REMOVE}/', '').
|
204
|
+
sub('{REMOVE}', '')
|
203
205
|
|
204
206
|
path = path + '.gz' if File.exist? path + '.gz'
|
205
207
|
path = path + '.bgz' if File.exist? path + '.bgz'
|
@@ -94,6 +94,7 @@ class RbbtProcessQueue
|
|
94
94
|
Log.debug "Closing up process queue #{Process.pid}"
|
95
95
|
@count = 0
|
96
96
|
Thread.new do
|
97
|
+
Log.debug "Pushing closed stream #{Process.pid}"
|
97
98
|
while true
|
98
99
|
@queue.push ClosedStream.new unless @queue.cleaned
|
99
100
|
end unless @processes.empty?
|
@@ -127,7 +128,7 @@ class RbbtProcessQueue
|
|
127
128
|
rescue TryAgain
|
128
129
|
retry
|
129
130
|
rescue Aborted
|
130
|
-
Log.low "
|
131
|
+
Log.low "Aborting manager thread #{Process.pid}"
|
131
132
|
raise Aborted
|
132
133
|
rescue Exception
|
133
134
|
Log.exception $!
|
data/lib/rbbt/util/docker.rb
CHANGED
@@ -32,7 +32,7 @@ module Docker
|
|
32
32
|
Open.write(directory[name], obj)
|
33
33
|
end
|
34
34
|
end
|
35
|
-
end
|
35
|
+
end if job_inputs
|
36
36
|
else
|
37
37
|
TmpFile.with_file do |tmpfile|
|
38
38
|
Path.setup(tmpfile)
|
@@ -55,12 +55,16 @@ module Docker
|
|
55
55
|
Open.write(tmpfile[name], obj)
|
56
56
|
end
|
57
57
|
end
|
58
|
-
end
|
58
|
+
end if job_inputs
|
59
59
|
pipe = false
|
60
60
|
end
|
61
61
|
|
62
62
|
end
|
63
63
|
cmd = "docker run #{mount_cmd} #{image_cmd} #{cmd}"
|
64
|
-
|
64
|
+
if pipe
|
65
|
+
CMD.cmd(cmd, :log => true, :pipe => true)
|
66
|
+
else
|
67
|
+
CMD.cmd_log(cmd, :log => true)
|
68
|
+
end
|
65
69
|
end
|
66
70
|
end
|
data/lib/rbbt/util/misc.rb
CHANGED
@@ -67,6 +67,26 @@ module Misc
|
|
67
67
|
def self.tokenize(str)
|
68
68
|
str.scan(/"[^"]*"|'[^']*'|[^"'\s]+/)
|
69
69
|
end
|
70
|
+
|
71
|
+
def self.timespan(str, default = "s")
|
72
|
+
tokens = {
|
73
|
+
"s" => (1),
|
74
|
+
"m" => (60),
|
75
|
+
"h" => (60 * 60),
|
76
|
+
"d" => (60 * 60 * 24),
|
77
|
+
"w" => (60 * 60 * 24 * 7),
|
78
|
+
}
|
79
|
+
|
80
|
+
tokens[nil] = tokens[default]
|
81
|
+
tokens[""] = tokens[default]
|
82
|
+
time = 0
|
83
|
+
str.scan(/(\d+)(\w?)/).each do |amount, measure|
|
84
|
+
time += amount.to_i * tokens[measure]
|
85
|
+
end
|
86
|
+
time
|
87
|
+
end
|
88
|
+
|
89
|
+
|
70
90
|
end
|
71
91
|
|
72
92
|
module PDF2Text
|
data/lib/rbbt/util/open.rb
CHANGED
@@ -236,7 +236,52 @@ module Open
|
|
236
236
|
end
|
237
237
|
end
|
238
238
|
|
239
|
-
def self.
|
239
|
+
def self.ln_s(source, target, options = {})
|
240
|
+
source = source.find if Path === source
|
241
|
+
target = target.find if Path === target
|
242
|
+
|
243
|
+
FileUtils.mkdir_p File.dirname(target) unless File.exists?(File.dirname(target))
|
244
|
+
FileUtils.rm target if File.exists?(target)
|
245
|
+
FileUtils.ln_s source, target
|
246
|
+
end
|
247
|
+
|
248
|
+
def self.ln(source, target, options = {})
|
249
|
+
source = source.find if Path === source
|
250
|
+
target = target.find if Path === target
|
251
|
+
|
252
|
+
FileUtils.mkdir_p File.dirname(target) unless File.exists?(File.dirname(target))
|
253
|
+
FileUtils.rm target if File.exists?(target)
|
254
|
+
FileUtils.ln source, target
|
255
|
+
end
|
256
|
+
|
257
|
+
def self.ln_h(source, target, options = {})
|
258
|
+
source = source.find if Path === source
|
259
|
+
target = target.find if Path === target
|
260
|
+
|
261
|
+
FileUtils.mkdir_p File.dirname(target) unless File.exists?(File.dirname(target))
|
262
|
+
FileUtils.rm target if File.exists?(target)
|
263
|
+
begin
|
264
|
+
CMD.cmd("ln -L '#{ source }' '#{ target }'")
|
265
|
+
rescue ProcessFailed
|
266
|
+
if $!.message.include? "Invalid cross-device link"
|
267
|
+
Log.debug "Could not hard link #{source} and #{target}: cross-device link"
|
268
|
+
CMD.cmd("cp -L '#{ source }' '#{ target }'")
|
269
|
+
else
|
270
|
+
raise $!
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def self.cp(source, target, options = {})
|
276
|
+
source = source.find if Path === source
|
277
|
+
target = target.find if Path === target
|
278
|
+
|
279
|
+
FileUtils.mkdir_p File.dirname(target) unless File.exists?(File.dirname(target))
|
280
|
+
FileUtils.rm target if File.exists?(target)
|
281
|
+
FileUtils.cp source, target
|
282
|
+
end
|
283
|
+
|
284
|
+
def self.mv(source, target, options = {})
|
240
285
|
dir_sub_path_source = find_repo_dir(source)
|
241
286
|
dir_sub_path_target = find_repo_dir(target)
|
242
287
|
|
@@ -276,7 +321,7 @@ module Open
|
|
276
321
|
exists_in_repo(*dir_sub_path)
|
277
322
|
else
|
278
323
|
file = file.find if Path === file
|
279
|
-
File.exist? file
|
324
|
+
File.exist?(file) || File.symlink?(file)
|
280
325
|
end
|
281
326
|
end
|
282
327
|
|
data/lib/rbbt/workflow.rb
CHANGED
@@ -310,7 +310,8 @@ module Workflow
|
|
310
310
|
|
311
311
|
task_info = task_info(taskname)
|
312
312
|
task_inputs = task_info[:inputs]
|
313
|
-
defaults = IndiferentHash.setup(task_info[:input_defaults]).merge(task.input_defaults)
|
313
|
+
#defaults = IndiferentHash.setup(task_info[:input_defaults]).merge(task.input_defaults)
|
314
|
+
defaults = IndiferentHash.setup(task.input_defaults)
|
314
315
|
|
315
316
|
missing_inputs = []
|
316
317
|
task.required_inputs.each do |input|
|
@@ -328,7 +329,6 @@ module Workflow
|
|
328
329
|
dependencies = real_dependencies(task, jobname, defaults.merge(inputs), task_dependencies[taskname] || [])
|
329
330
|
|
330
331
|
real_inputs = {}
|
331
|
-
recursive_inputs = rec_inputs(taskname)
|
332
332
|
|
333
333
|
inputs.each do |k,v|
|
334
334
|
default = defaults[k]
|
@@ -339,7 +339,9 @@ module Workflow
|
|
339
339
|
real_inputs[k] = v
|
340
340
|
end
|
341
341
|
|
342
|
-
|
342
|
+
overriden = dependencies.select{|dep| dep.overriden }.any?
|
343
|
+
|
344
|
+
if real_inputs.empty? and not Workflow::TAG == :inputs and not overriden
|
343
345
|
step_path = step_path taskname, jobname, [], [], task.extension
|
344
346
|
input_values = task.take_input_values(inputs)
|
345
347
|
else
|
@@ -350,6 +352,7 @@ module Workflow
|
|
350
352
|
job = get_job_step step_path, task, input_values, dependencies
|
351
353
|
job.workflow = self
|
352
354
|
job.clean_name = jobname
|
355
|
+
job.overriden = overriden
|
353
356
|
job
|
354
357
|
end
|
355
358
|
|
@@ -378,6 +378,7 @@ class Step
|
|
378
378
|
canfail_paths = self.canfail_paths
|
379
379
|
dirty_files = rec_dependencies.reject{|dep|
|
380
380
|
(defined?(WorkflowRESTClient) && WorkflowRESTClient::RemoteStep === dep) ||
|
381
|
+
! Open.exists?(dep.info_file) ||
|
381
382
|
(dep.path && (Open.exists?(dep.path) || Open.remote?(dep.path))) ||
|
382
383
|
((dep.error? || dep.aborted?) && (! dep.recoverable_error? || canfail_paths.include?(dep.path)))
|
383
384
|
}
|
@@ -392,6 +393,7 @@ class Step
|
|
392
393
|
if done? and not (status == :done or status == :ending or status == :producing) and not status == :noinfo
|
393
394
|
return true
|
394
395
|
end
|
396
|
+
|
395
397
|
if status == :done and not done?
|
396
398
|
return true
|
397
399
|
end
|
@@ -561,6 +563,18 @@ class Step
|
|
561
563
|
|
562
564
|
value || default
|
563
565
|
end
|
566
|
+
|
567
|
+
def access
|
568
|
+
CMD.cmd("touch -c -h -a #{self.path} #{self.info_file}")
|
569
|
+
end
|
570
|
+
|
571
|
+
def rec_access
|
572
|
+
access
|
573
|
+
rec_dependencies.each do |dep|
|
574
|
+
dep.access
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
564
578
|
end
|
565
579
|
|
566
580
|
module Workflow
|
@@ -832,6 +846,18 @@ module Workflow
|
|
832
846
|
def real_dependencies(task, orig_jobname, inputs, dependencies)
|
833
847
|
real_dependencies = []
|
834
848
|
path_deps = {}
|
849
|
+
|
850
|
+
override_dependencies = IndiferentHash.setup({})
|
851
|
+
|
852
|
+
inputs.each do |key,value|
|
853
|
+
if String === key && m = key.match(/(.*)#(.*)/)
|
854
|
+
workflow, task = m.values_at 1, 2
|
855
|
+
workflow = self.to_s if workflow.empty?
|
856
|
+
override_dependencies[workflow] ||= IndiferentHash.setup({})
|
857
|
+
override_dependencies[workflow][task] = value
|
858
|
+
end
|
859
|
+
end
|
860
|
+
|
835
861
|
dependencies.each do |dependency|
|
836
862
|
_inputs = IndiferentHash.setup(inputs.dup)
|
837
863
|
jobname = orig_jobname
|
@@ -841,20 +867,37 @@ module Workflow
|
|
841
867
|
when Array
|
842
868
|
workflow, dep_task, options = dependency
|
843
869
|
|
844
|
-
|
870
|
+
if override_dependencies[workflow.to_s] && value = override_dependencies[workflow.to_s][dep_task]
|
871
|
+
d_ = Step === value ? value : Workflow.load_step(value)
|
872
|
+
d_.task = workflow.tasks[dep_task]
|
873
|
+
d_.workflow = workflow
|
874
|
+
d_.overriden = true
|
875
|
+
d_
|
876
|
+
else
|
877
|
+
|
878
|
+
compute = options[:compute] if options
|
845
879
|
|
846
|
-
|
847
|
-
|
848
|
-
_inputs = assign_dep_inputs(_inputs, options, all_d, workflow.task_info(dep_task))
|
849
|
-
jobname = _inputs[:jobname] if _inputs.include? :jobname
|
880
|
+
all_d = (real_dependencies + real_dependencies.flatten.collect{|d| d.rec_dependencies} ).flatten.compact.uniq
|
850
881
|
|
851
|
-
|
852
|
-
|
853
|
-
|
882
|
+
_inputs = assign_dep_inputs(_inputs, options, all_d, workflow.task_info(dep_task))
|
883
|
+
jobname = _inputs[:jobname] if _inputs.include? :jobname
|
884
|
+
|
885
|
+
job = workflow.job(dep_task, jobname, _inputs)
|
886
|
+
ComputeDependency.setup(job, compute) if compute
|
887
|
+
job
|
888
|
+
end
|
854
889
|
when Step
|
855
890
|
dependency
|
856
891
|
when Symbol
|
857
|
-
|
892
|
+
if override_dependencies[self.to_s] && value = override_dependencies[self.to_s][dependency]
|
893
|
+
d_ = Step === value ? value : Workflow.load_step(value)
|
894
|
+
d_.task = self.tasks[dependency]
|
895
|
+
d_.workflow = self
|
896
|
+
d_.overriden = true
|
897
|
+
d_
|
898
|
+
else
|
899
|
+
job(dependency, jobname, _inputs)
|
900
|
+
end
|
858
901
|
when Proc
|
859
902
|
if DependencyBlock === dependency
|
860
903
|
orig_dep = dependency.dependency
|
@@ -874,10 +917,18 @@ module Workflow
|
|
874
917
|
if Hash === d
|
875
918
|
d[:workflow] ||= wf
|
876
919
|
d[:task] ||= task_name
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
920
|
+
if override_dependencies[d[:workflow].to_s] && value = override_dependencies[d[:workflow].to_s][d[:task]]
|
921
|
+
d = (Step === value ? value : Workflow.load_step(value))
|
922
|
+
d.task = d[:workflow].tasks[d[:task]]
|
923
|
+
d.workflow = self
|
924
|
+
d.overriden = true
|
925
|
+
d
|
926
|
+
else
|
927
|
+
task_info = d[:workflow].task_info(d[:task])
|
928
|
+
|
929
|
+
inputs = assign_dep_inputs({}, options.merge(d[:inputs] || {}), real_dependencies, task_info)
|
930
|
+
d = d[:workflow].job(d[:task], d[:jobname], inputs)
|
931
|
+
end
|
881
932
|
end
|
882
933
|
ComputeDependency.setup(d, compute) if compute
|
883
934
|
new_ << d
|
@@ -888,9 +939,16 @@ module Workflow
|
|
888
939
|
dep = dependency.call jobname, _inputs, real_dependencies
|
889
940
|
if Hash === dep
|
890
941
|
dep[:workflow] ||= wf || self
|
891
|
-
|
892
|
-
|
893
|
-
|
942
|
+
if override_dependencies[d[:workflow].to_s] && value = override_dependencies[d[:workflow].to_s][d[:task]]
|
943
|
+
dep = (Step === value ? value : Workflow.load_step(value))
|
944
|
+
dep.task = d[:workflow].tasks[d[:task]]
|
945
|
+
dep.workflow = self
|
946
|
+
dep.overriden = true
|
947
|
+
else
|
948
|
+
task_info = (dep[:task] && dep[:workflow]) ? dep[:workflow].task_info(dep[:task]) : nil
|
949
|
+
inputs = assign_dep_inputs({}, dep[:inputs], real_dependencies, task_info)
|
950
|
+
dep = dep[:workflow].job(dep[:task], dep[:jobname], inputs)
|
951
|
+
end
|
894
952
|
end
|
895
953
|
end
|
896
954
|
|
@@ -915,7 +973,7 @@ module Workflow
|
|
915
973
|
key_obj = {:inputs => clean_inputs, :dependencies => dependencies}
|
916
974
|
key_str = Misc.obj2str(key_obj)
|
917
975
|
hash_str = Misc.digest(key_str)
|
918
|
-
Log.debug "Hash for '#{[taskname, jobname] * "/"}' #{hash_str} for #{key_str}"
|
976
|
+
#Log.debug "Hash for '#{[taskname, jobname] * "/"}' #{hash_str} for #{key_str}"
|
919
977
|
jobname + '_' << hash_str
|
920
978
|
when :inputs
|
921
979
|
all_inputs = {}
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -6,6 +6,7 @@ require 'rbbt/workflow/accessor'
|
|
6
6
|
|
7
7
|
class Step
|
8
8
|
attr_accessor :clean_name, :path, :task, :workflow, :inputs, :dependencies, :bindings
|
9
|
+
attr_accessor :task_name, :overriden
|
9
10
|
attr_accessor :pid
|
10
11
|
attr_accessor :exec
|
11
12
|
attr_accessor :result, :mutex, :seen
|
@@ -28,6 +29,14 @@ class Step
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
32
|
+
def overriden
|
33
|
+
if @overriden.nil?
|
34
|
+
dependencies.select{|dep| dep.overriden }.any?
|
35
|
+
else
|
36
|
+
@overriden
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
31
40
|
def initialize(path, task = nil, inputs = nil, dependencies = nil, bindings = nil, clean_name = nil)
|
32
41
|
path = Path.setup(Misc.sanitize_filename(path)) if String === path
|
33
42
|
path = path.call if Proc === path
|
@@ -100,8 +109,13 @@ class Step
|
|
100
109
|
end
|
101
110
|
|
102
111
|
def task_name
|
103
|
-
|
104
|
-
|
112
|
+
@task_name ||= begin
|
113
|
+
if @task.nil?
|
114
|
+
@path.split("/")[-2]
|
115
|
+
else
|
116
|
+
@task.name
|
117
|
+
end
|
118
|
+
end
|
105
119
|
end
|
106
120
|
|
107
121
|
def path
|
@@ -259,7 +273,7 @@ class Step
|
|
259
273
|
pid_file = Step.pid_file path
|
260
274
|
files_dir = Step.files_dir path
|
261
275
|
|
262
|
-
if Open.exists?(path) or Open.exists?(pid_file) or Open.exists?(info_file)
|
276
|
+
if Open.exists?(path) or Open.exists?(pid_file) or Open.exists?(info_file) or Open.exists?(files_dir)
|
263
277
|
|
264
278
|
@result = nil
|
265
279
|
@pid = nil
|
@@ -291,7 +305,7 @@ class Step
|
|
291
305
|
self
|
292
306
|
end
|
293
307
|
|
294
|
-
def rec_dependencies
|
308
|
+
def rec_dependencies(need_run = false)
|
295
309
|
|
296
310
|
# A step result with no info_file means that it was manually
|
297
311
|
# placed. In that case, do not consider its dependencies
|
@@ -301,7 +315,9 @@ class Step
|
|
301
315
|
|
302
316
|
new_dependencies = []
|
303
317
|
dependencies.each{|step|
|
304
|
-
|
318
|
+
next if self.done? && need_run && Open.exists?(step.info_file)
|
319
|
+
|
320
|
+
r = step.rec_dependencies(need_run)
|
305
321
|
new_dependencies.concat r
|
306
322
|
new_dependencies << step
|
307
323
|
}
|
@@ -108,6 +108,7 @@ class Step
|
|
108
108
|
rec_dependencies.
|
109
109
|
select{|dependency| ! (defined? WorkflowRESTClient and WorkflowRESTClient::RemoteStep === dependency) }.
|
110
110
|
select{|dependency| ! Open.remote?(dependency.path) }.
|
111
|
+
select{|dependency| Open.exists?(dependency.info_file) }.
|
111
112
|
select{|dependency| ! dependency.error? }
|
112
113
|
end
|
113
114
|
|
@@ -126,9 +127,15 @@ class Step
|
|
126
127
|
outdated_dep = []
|
127
128
|
canfail_paths = self.canfail_paths
|
128
129
|
checks.each do |dep|
|
129
|
-
|
130
|
-
|
130
|
+
next unless Open.exists?(dep.info_file)
|
131
|
+
|
132
|
+
begin
|
133
|
+
if dep.done? && self.done? && Open.exists?(dep.path) && Open.exists?(self.path) && (File.mtime(dep.path) > File.mtime(self.path))
|
134
|
+
outdated_time << dep
|
135
|
+
end
|
136
|
+
rescue
|
131
137
|
end
|
138
|
+
|
132
139
|
if (! dep.done? && ! canfail_paths.include?(dep.path)) || ! dep.updated?
|
133
140
|
outdated_dep << dep
|
134
141
|
end
|
data/lib/rbbt/workflow/usage.rb
CHANGED
@@ -32,7 +32,12 @@ module Task
|
|
32
32
|
seen = []
|
33
33
|
task_inputs = dep_inputs deps, workflow
|
34
34
|
task_inputs.each do |task,new_inputs|
|
35
|
-
|
35
|
+
new_inputs.zip(task.input_types.values_at(*new_inputs)).select do |i,t|
|
36
|
+
t.to_sym == :select and task.input_options[i][:select_options]
|
37
|
+
end.each do |i,t|
|
38
|
+
selects << [i, task.input_options[i][:select_options]]
|
39
|
+
end
|
40
|
+
|
36
41
|
if task.workflow and task.workflow != workflow
|
37
42
|
puts " #{Log.color :yellow, ["[#{task.workflow.to_s}]", task.name.to_s] *" "}:"
|
38
43
|
else
|
@@ -93,10 +93,13 @@ get_git(){
|
|
93
93
|
cd $OPT_SCM_DIR
|
94
94
|
if [ -d "$name" ]; then
|
95
95
|
cd "$name"
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
96
|
+
|
97
|
+
if [ ! "$NOWEB" == "true" ]; then
|
98
|
+
git stash
|
99
|
+
git pull origin master
|
100
|
+
git rebase master
|
101
|
+
git stash apply
|
102
|
+
fi
|
100
103
|
else
|
101
104
|
git clone "$url" "$name"
|
102
105
|
fi
|
@@ -211,11 +214,23 @@ setup(){
|
|
211
214
|
local old_pwd="`expand_path $(pwd)`"
|
212
215
|
cd "$OPT_DIR/bin"
|
213
216
|
|
214
|
-
for exe in `
|
217
|
+
for exe in ` find "$pkg_dir/bin/" -maxdepth 1 -type f -executable`; do
|
218
|
+
exe=$(basename $exe)
|
215
219
|
rm -f ./$exe
|
216
220
|
ln -s "$pkg_dir/bin/$exe" . 2>/dev/null
|
217
221
|
done
|
218
222
|
|
223
|
+
cd "$old_pwd"
|
224
|
+
else
|
225
|
+
local old_pwd="`expand_path $(pwd)`"
|
226
|
+
cd "$OPT_DIR/bin"
|
227
|
+
|
228
|
+
for exe in ` find "$pkg_dir/" -maxdepth 1 -type f -executable`; do
|
229
|
+
exe=$(basename $exe)
|
230
|
+
rm -f ./$exe
|
231
|
+
ln -s "$pkg_dir/$exe" . 2>/dev/null
|
232
|
+
done
|
233
|
+
|
219
234
|
cd "$old_pwd"
|
220
235
|
fi
|
221
236
|
|
@@ -236,6 +251,27 @@ install_src(){
|
|
236
251
|
build "$name" "$extra"
|
237
252
|
}
|
238
253
|
|
254
|
+
custom_build(){
|
255
|
+
local name="$1"
|
256
|
+
shift;
|
257
|
+
local cmd="$@"
|
258
|
+
|
259
|
+
echo "Building $name"
|
260
|
+
|
261
|
+
local old_pwd="`expand_path $(pwd)`"
|
262
|
+
cd "`build_dir`"
|
263
|
+
echo `pwd`
|
264
|
+
ls
|
265
|
+
|
266
|
+
eval $cmd
|
267
|
+
|
268
|
+
move_opt "$name"
|
269
|
+
setup "$name"
|
270
|
+
clean_build
|
271
|
+
|
272
|
+
cd "$old_pwd"
|
273
|
+
}
|
274
|
+
|
239
275
|
install_git(){
|
240
276
|
local name="$1"
|
241
277
|
local url="$2"
|
@@ -14,6 +14,7 @@ Clean orphaned files
|
|
14
14
|
$ rbbt system clean <workflow> <task>
|
15
15
|
|
16
16
|
-a--all Apply to all jobs, not only uncompleted
|
17
|
+
-o--older* Clean jobs not access in some time
|
17
18
|
-f--force Remove locks and files regardless of been active
|
18
19
|
-q--quick Quick check
|
19
20
|
-d--dirty Clean dirty jobs
|
@@ -29,6 +30,9 @@ task = task.split "," if task
|
|
29
30
|
all = options.delete :all
|
30
31
|
force = options.delete :force
|
31
32
|
dirty = options.delete :dirty
|
33
|
+
time = options.delete :older
|
34
|
+
|
35
|
+
time = Misc.timespan time, 'd' if time
|
32
36
|
|
33
37
|
puts Log.color(:magenta, "# System clean")
|
34
38
|
|
@@ -103,8 +107,17 @@ TSV.traverse jobs, :_bar => "Checking job status" do |file,i|
|
|
103
107
|
status = status.to_s
|
104
108
|
end
|
105
109
|
|
106
|
-
|
107
|
-
|
108
|
-
|
110
|
+
if time and File.exists?(file)
|
111
|
+
old = Time.now - File.atime(file)
|
112
|
+
status = 'old'
|
113
|
+
end
|
114
|
+
|
115
|
+
if (force and status !~ /done/) or
|
116
|
+
status =~ /\b(old|dirty|nopid|error|missing|aborted|dead|sync)$/ or
|
117
|
+
status == ""
|
118
|
+
|
119
|
+
puts " Removing #{ file } - #{status}"
|
120
|
+
Step.clean(file)
|
121
|
+
end
|
109
122
|
end
|
110
123
|
|
data/share/rbbt_commands/tsv/get
CHANGED
@@ -17,6 +17,7 @@ Use - to read from STDIN
|
|
17
17
|
-k--key_field* Use this field as key
|
18
18
|
-h--help Print this help
|
19
19
|
-l--lines Separate in lines
|
20
|
+
-t--type* Type of tsv
|
20
21
|
EOF
|
21
22
|
|
22
23
|
rbbt_usage and exit 0 if options[:help]
|
@@ -44,11 +45,13 @@ fields = options[:fields]
|
|
44
45
|
key_field = options[:key_field]
|
45
46
|
fields = fields.split(/[,|]/, -1) unless fields.nil?
|
46
47
|
|
47
|
-
parser = TSV::Parser.new tsv, :key_field => key_field, :fields => fields
|
48
|
+
parser = TSV::Parser.new tsv, :key_field => key_field, :fields => fields, :type => options[:type]
|
48
49
|
fields ||= parser.fields
|
49
50
|
|
50
51
|
TSV.traverse(parser) do |k,v|
|
51
52
|
next unless k.include? key
|
53
|
+
k = k.first if Array === k
|
54
|
+
puts Log.color(:blue, "Key: #{ k }")
|
52
55
|
if fields.length == 1
|
53
56
|
if options[:lines]
|
54
57
|
puts (Array === v ? v.flatten*"\n" : v.to_s )
|
@@ -45,8 +45,10 @@ def status_msg(status)
|
|
45
45
|
:red
|
46
46
|
when :streaming, :started
|
47
47
|
:cyan
|
48
|
-
when :done
|
48
|
+
when :done
|
49
49
|
:green
|
50
|
+
when :noinfo
|
51
|
+
:blue
|
50
52
|
when :dependencies, :waiting, :setyp
|
51
53
|
:yellow
|
52
54
|
else
|
@@ -60,16 +62,18 @@ def status_msg(status)
|
|
60
62
|
end
|
61
63
|
|
62
64
|
def report_msg(status, name, path, info = nil)
|
63
|
-
|
64
65
|
parts = path.sub(/\{.*/,'').sub(/#{Regexp.quote(name)}$/,'').split "/"
|
65
66
|
|
66
67
|
task = Log.color(:yellow, parts.pop)
|
67
68
|
workflow = Log.color(:magenta, parts.pop)
|
69
|
+
if status.to_s == 'noinfo' and parts.last != 'jobs'
|
70
|
+
task, status, workflow = Log.color(:yellow, info[:task_name]), Log.color(:blue, "file"), Log.color(:magenta, "-")
|
71
|
+
end
|
68
72
|
|
69
73
|
str = if not Open.remote?(path) and (File.exists?(path) and $main_mtime and ($main_mtime - File.mtime(path)) < 0)
|
70
|
-
status_msg(status.to_s) << " " << [workflow, task, path] * " " << " (#{Log.color(:red, "Mtime out of sync") })"
|
74
|
+
status_msg(status.to_s) << " " << [workflow, task, path].compact * " " << " (#{Log.color(:red, "Mtime out of sync") })"
|
71
75
|
else
|
72
|
-
status_msg(status.to_s) << " " << [workflow, task, path] * " "
|
76
|
+
status_msg(status.to_s) << " " << [workflow, task, path].compact * " "
|
73
77
|
end
|
74
78
|
|
75
79
|
if $inputs and $inputs.any?
|
@@ -97,8 +101,9 @@ def report_msg(status, name, path, info = nil)
|
|
97
101
|
str << "\n"
|
98
102
|
end
|
99
103
|
|
100
|
-
def report(step, offset = 0)
|
101
|
-
info = step.info
|
104
|
+
def report(step, offset = 0, task = nil)
|
105
|
+
info = step.info || {}
|
106
|
+
info[:task_name] = task
|
102
107
|
path = step.path
|
103
108
|
status = info[:status] || :missing
|
104
109
|
status = "remote" if Open.remote?(path)
|
@@ -110,9 +115,9 @@ def report(step, offset = 0)
|
|
110
115
|
new = ! $seen.include?(path)
|
111
116
|
dep = get_step path
|
112
117
|
if new
|
113
|
-
str << report(dep, offset + 1)
|
118
|
+
str << report(dep, offset + 1, task)
|
114
119
|
else
|
115
|
-
str << Log.color(:blue, Log.uncolor(report(dep, offset+1)))
|
120
|
+
str << Log.color(:blue, Log.uncolor(report(dep, offset+1, task)))
|
116
121
|
end
|
117
122
|
end if info[:dependencies]
|
118
123
|
str
|
@@ -202,6 +202,7 @@ the job dependencies recursively.
|
|
202
202
|
-W--workflows* Load a list of workflows
|
203
203
|
-R--requires* Require a list of files
|
204
204
|
-rwt--remote_workflow_tasks* Load a yaml file describing remote workflow tasks
|
205
|
+
-od--override_deps* Override deps using 'Workflow#task=<path>' array_separated
|
205
206
|
EOF
|
206
207
|
|
207
208
|
workflow = ARGV.shift
|
@@ -216,6 +217,7 @@ detach = !!options.delete(:detach)
|
|
216
217
|
do_exec = !!options.delete(:exec)
|
217
218
|
clean = !!options.delete(:clean)
|
218
219
|
clean_task = options.delete(:clean_task)
|
220
|
+
override_deps = options.delete(:override_deps)
|
219
221
|
recursive_clean = !!options.delete(:recursive_clean)
|
220
222
|
out = options.include?(:output) ? File.open(options[:output], 'wb') : STDOUT
|
221
223
|
|
@@ -294,6 +296,13 @@ saved_job_options = job_options
|
|
294
296
|
|
295
297
|
workflow.workdir = Path.setup(File.expand_path(options.delete(:workdir))) if options[:workdir]
|
296
298
|
|
299
|
+
if override_deps
|
300
|
+
override_deps.split($array_separator).each do |part|
|
301
|
+
t_, value = part.split("=")
|
302
|
+
job_options.merge!( t_ => value)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
297
306
|
#- get job
|
298
307
|
|
299
308
|
job = workflow.job(task.name, name, job_options)
|
@@ -306,7 +315,9 @@ end
|
|
306
315
|
|
307
316
|
if clean_task
|
308
317
|
job.rec_dependencies.each do |dep|
|
309
|
-
|
318
|
+
next unless dep.task_name.to_s == clean_task.to_s
|
319
|
+
dep.clean
|
320
|
+
dep.set_info :status, :cleaned
|
310
321
|
end
|
311
322
|
end
|
312
323
|
|
@@ -17,6 +17,16 @@ class TestTSV < Test::Unit::TestCase
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
def test_find_current
|
21
|
+
TmpFile.with_file do |dir|
|
22
|
+
Misc.in_dir dir do
|
23
|
+
CMD.cmd('touch foo')
|
24
|
+
p = Path.setup('foo')
|
25
|
+
assert_equal File.join(dir, 'foo'), p.find(:current)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
20
30
|
def test_prev
|
21
31
|
path = Path.setup "/tmp"
|
22
32
|
assert_equal "/tmp/bar/foo", path.foo("bar")
|
@@ -31,9 +41,9 @@ class TestTSV < Test::Unit::TestCase
|
|
31
41
|
assert_equal path.find, path.doc_file.find(:lib).source_for_doc_file
|
32
42
|
assert_equal path.find, path.doc_file.source_for_doc_file.find
|
33
43
|
|
34
|
-
assert_equal "doc/lib/rbbt/resource.doc", path.doc_file.set_extension('doc')
|
35
|
-
assert_equal "lib/rbbt/resource.rb", path.doc_file.set_extension('doc').source_for_doc_file
|
44
|
+
assert_equal "doc/lib/rbbt/resource.rb.doc", path.doc_file.set_extension('doc')
|
45
|
+
#assert_equal "lib/rbbt/resource.rb", path.doc_file.set_extension('doc').source_for_doc_file
|
36
46
|
|
37
|
-
assert_equal "doc/lib/rbbt/resource.doc", path.doc_file.set_extension('doc')
|
47
|
+
assert_equal "doc/lib/rbbt/resource.rb.doc", path.doc_file.set_extension('doc')
|
38
48
|
end
|
39
49
|
end
|
data/test/rbbt/test_resource.rb
CHANGED
@@ -33,7 +33,8 @@ class TestTSV < Test::Unit::TestCase
|
|
33
33
|
assert TSV === TestResource.tmp.test.test_tsv.tsv
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
36
|
+
def __test_rake
|
37
|
+
iii TestResource.tmp.test.work.footest.foo.find
|
37
38
|
TestResource.tmp.test.work.footest.foo.read == "TEST"
|
38
39
|
assert TestResource.tmp.test.work.footest.foo.read == "TEST"
|
39
40
|
end
|
data/test/rbbt/test_tsv.rb
CHANGED
data/test/rbbt/test_workflow.rb
CHANGED
@@ -107,6 +107,23 @@ for this dependency
|
|
107
107
|
task :send_input_dep_to_reverse => :text do
|
108
108
|
TSV.get_stream step(:reverse_input_text)
|
109
109
|
end
|
110
|
+
|
111
|
+
input :i, :string, "Input", "A"
|
112
|
+
task :t1 => :string do |i|
|
113
|
+
i
|
114
|
+
end
|
115
|
+
|
116
|
+
input :i, :string, "Input", "B"
|
117
|
+
task :t2 => :string do |i|
|
118
|
+
i
|
119
|
+
end
|
120
|
+
|
121
|
+
dep :t1, :i => "C"
|
122
|
+
dep :t2
|
123
|
+
task :t3 => :string do |i|
|
124
|
+
step(:t1).load + step(:t2).load
|
125
|
+
end
|
126
|
+
|
110
127
|
end
|
111
128
|
|
112
129
|
TestWF.workdir = Rbbt.tmp.test.workflow
|
@@ -198,6 +215,12 @@ class TestWorkflow < Test::Unit::TestCase
|
|
198
215
|
assert_equal "V:AA", job.run
|
199
216
|
end
|
200
217
|
|
218
|
+
def test_override_dep
|
219
|
+
TmpFile.with_file("OTHER") do |file|
|
220
|
+
assert TestWF.job(:repeat2, nil, :number => 3, "TestWF#str" => file).run.include? "OTHER"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
201
224
|
def __test_stream
|
202
225
|
io = TestWF.job(:stream).run(:stream)
|
203
226
|
Misc.consume_stream(TSV.get_stream(io), false, STDOUT)
|
@@ -228,4 +251,9 @@ class TestWorkflow < Test::Unit::TestCase
|
|
228
251
|
assert TestWF.rec_input_use(:double_dep)[:times][TestWF].include?(:repeat)
|
229
252
|
end
|
230
253
|
|
254
|
+
def test_shared_inputs
|
255
|
+
assert_equal "CB", TestWF.job(:t3).run
|
256
|
+
assert_equal "CB", TestWF.job(:t3).run
|
257
|
+
end
|
258
|
+
|
231
259
|
end
|
data/test/rbbt/util/test_misc.rb
CHANGED
@@ -602,4 +602,12 @@ EOF
|
|
602
602
|
assert_equal 1, hash[:A]
|
603
603
|
assert_equal 3, hash[:C]
|
604
604
|
end
|
605
|
+
|
606
|
+
def test_time_stamp
|
607
|
+
assert_equal 10, Misc.timespan('10')
|
608
|
+
assert_equal 10, Misc.timespan('10s')
|
609
|
+
assert_equal 60, Misc.timespan('1m')
|
610
|
+
assert_equal 60*60*24, Misc.timespan('1d')
|
611
|
+
assert_equal 60*60*24, Misc.timespan('1d')
|
612
|
+
end
|
605
613
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.22.
|
4
|
+
version: 5.22.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|