scout-gear 10.7.0 → 10.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +8 -1
  3. data/VERSION +1 -1
  4. data/lib/scout/association/index.rb +1 -1
  5. data/lib/scout/association.rb +21 -5
  6. data/lib/scout/entity/format.rb +9 -4
  7. data/lib/scout/entity/identifiers.rb +2 -2
  8. data/lib/scout/entity/named_array.rb +13 -0
  9. data/lib/scout/entity/property.rb +2 -1
  10. data/lib/scout/entity.rb +9 -4
  11. data/lib/scout/persist/tsv/adapter/base.rb +13 -1
  12. data/lib/scout/persist/tsv.rb +2 -1
  13. data/lib/scout/tsv/attach.rb +10 -2
  14. data/lib/scout/tsv/change_id.rb +3 -0
  15. data/lib/scout/tsv/dumper.rb +34 -30
  16. data/lib/scout/tsv/open.rb +1 -0
  17. data/lib/scout/tsv/parser.rb +22 -10
  18. data/lib/scout/tsv/path.rb +8 -0
  19. data/lib/scout/tsv/stream.rb +15 -8
  20. data/lib/scout/tsv/traverse.rb +12 -2
  21. data/lib/scout/tsv/util/process.rb +4 -1
  22. data/lib/scout/tsv/util/select.rb +8 -2
  23. data/lib/scout/tsv/util/sort.rb +23 -15
  24. data/lib/scout/tsv/util.rb +11 -2
  25. data/lib/scout/tsv.rb +23 -11
  26. data/lib/scout/workflow/definition.rb +24 -9
  27. data/lib/scout/workflow/deployment/orchestrator.rb +10 -7
  28. data/lib/scout/workflow/exceptions.rb +1 -0
  29. data/lib/scout/workflow/path.rb +40 -0
  30. data/lib/scout/workflow/step/dependencies.rb +36 -12
  31. data/lib/scout/workflow/step/file.rb +2 -1
  32. data/lib/scout/workflow/step/info.rb +20 -4
  33. data/lib/scout/workflow/step/load.rb +5 -3
  34. data/lib/scout/workflow/step/progress.rb +6 -0
  35. data/lib/scout/workflow/step/provenance.rb +1 -1
  36. data/lib/scout/workflow/step/status.rb +11 -4
  37. data/lib/scout/workflow/step.rb +33 -12
  38. data/lib/scout/workflow/task/dependencies.rb +33 -24
  39. data/lib/scout/workflow/task/inputs.rb +42 -12
  40. data/lib/scout/workflow/task.rb +22 -11
  41. data/lib/scout/workflow/usage.rb +3 -3
  42. data/lib/scout/workflow.rb +3 -0
  43. data/scout-gear.gemspec +13 -4
  44. data/scout_commands/db/query +83 -0
  45. data/scout_commands/db/register +43 -0
  46. data/scout_commands/db/show +47 -0
  47. data/test/scout/entity/test_named_array.rb +21 -0
  48. data/test/scout/persist/test_tsv.rb +20 -0
  49. data/test/scout/persist/tsv/adapter/test_base.rb +20 -0
  50. data/test/scout/test_tsv.rb +40 -0
  51. data/test/scout/tsv/test_dumper.rb +24 -0
  52. data/test/scout/tsv/test_path.rb +24 -0
  53. data/test/scout/tsv/test_stream.rb +93 -0
  54. data/test/scout/tsv/test_traverse.rb +99 -0
  55. data/test/scout/tsv/test_util.rb +2 -0
  56. data/test/scout/tsv/util/test_select.rb +22 -0
  57. data/test/scout/tsv/util/test_sort.rb +24 -0
  58. data/test/scout/workflow/step/test_dependencies.rb +26 -0
  59. data/test/scout/workflow/step/test_info.rb +35 -0
  60. data/test/scout/workflow/task/test_dependencies.rb +67 -1
  61. data/test/scout/workflow/task/test_inputs.rb +24 -7
  62. data/test/scout/workflow/test_definition.rb +31 -0
  63. data/test/scout/workflow/test_path.rb +9 -0
  64. data/test/scout/workflow/test_task.rb +36 -0
  65. data/test/scout/workflow/test_usage.rb +0 -1
  66. metadata +12 -3
@@ -138,18 +138,32 @@ class Step
138
138
 
139
139
  attr_reader :result
140
140
  def run(stream = false)
141
+ case stream
142
+ when TrueClass, :stream
143
+ no_load = :stream
144
+ when :no_load
145
+ no_load = true
146
+ else
147
+ no_load = false
148
+ end
149
+
150
+ if done?
151
+ if no_load
152
+ if no_load == :stream
153
+ return self.stream
154
+ else
155
+ return self.path
156
+ end
157
+ else
158
+ return @result || self.load
159
+ end
160
+ end
161
+
162
+
141
163
  return @result || self.load if done?
142
164
  prepare_dependencies
143
165
  begin
144
166
 
145
- case stream
146
- when TrueClass, :stream
147
- no_load = :stream
148
- when :no_load
149
- no_load = true
150
- else
151
- no_load = false
152
- end
153
167
 
154
168
  @result = Persist.persist(name, type, :path => path, :tee_copies => tee_copies, no_load: no_load) do
155
169
  input_names = (task.respond_to?(:inputs) && task.inputs) ? task.inputs.collect{|name,_| name} : []
@@ -206,6 +220,7 @@ class Step
206
220
  end
207
221
 
208
222
  @result.abort_callback = proc do |exception|
223
+ Open.rm self.path
209
224
  if exception.nil? || Aborted === exception || Interrupt === exception
210
225
  merge_info :status => :aborted, :end => Time.now
211
226
  else
@@ -240,6 +255,7 @@ class Step
240
255
  run(noload)
241
256
  end
242
257
  join
258
+ exit! 0
243
259
  end
244
260
  Process.detach pid
245
261
  grace
@@ -350,6 +366,10 @@ class Step
350
366
 
351
367
  def step(task_name)
352
368
  task_name = task_name.to_sym
369
+ dependencies.each do |dep|
370
+ return dep if dep.task_name && dep.task_name.to_sym == task_name
371
+ return dep if dep.overriden_task && dep.overriden_task.to_sym == task_name
372
+ end
353
373
  dependencies.each do |dep|
354
374
  return dep if dep.task_name && dep.task_name.to_sym == task_name
355
375
  return dep if dep.overriden_task && dep.overriden_task.to_sym == task_name
@@ -359,12 +379,12 @@ class Step
359
379
  nil
360
380
  end
361
381
 
362
- def short_path
363
- Resource.identify @path
382
+ def identify_path
383
+ Resource.identify path
364
384
  end
365
385
 
366
386
  def digest_str
367
- "Step: " + short_path
387
+ "Step: " + identify_path
368
388
  end
369
389
 
370
390
  def fingerprint
@@ -372,7 +392,8 @@ class Step
372
392
  end
373
393
 
374
394
  def task_signature
375
- [workflow.to_s, task_name] * "#"
395
+ workflow_name = String === workflow ? workflow : workflow.name
396
+ [workflow_name, task_name] * "#"
376
397
  end
377
398
 
378
399
  def alias?
@@ -9,22 +9,33 @@ module Task
9
9
  load_dep = proc do |id, workflow, task, step_options, definition_options, dependencies|
10
10
  task = step_options.delete(:task) if step_options.include?(:task)
11
11
  workflow = step_options.delete(:workflow) if step_options.include?(:workflow)
12
- id = step_options.delete(:id) if step_options.include?(:id)
13
- id = step_options.delete(:jobname) if step_options.include?(:jobname)
12
+
13
+ step_id = id
14
+ step_id = step_options.delete(:jobname) if step_options.include?(:jobname)
15
+ step_id = nil if step_id == Task::DEFAULT_NAME
14
16
 
15
17
  step_inputs = step_options.include?(:inputs)? step_options.delete(:inputs) : step_options
16
- step_inputs = IndiferentHash.add_defaults step_inputs, definition_options
18
+ step_inputs = IndiferentHash.add_defaults step_inputs.dup, definition_options
17
19
 
18
20
  resolved_inputs = {}
19
21
  step_inputs.each do |k,v|
20
22
  if Symbol === v
21
23
  input_dep = dependencies.select{|d| d.task_name == v }.first
22
- resolved_inputs[k] = input_dep || provided_inputs[v] || step_inputs[v] || v
24
+ resolved_inputs[k] = if input_dep
25
+ input_dep
26
+ elsif provided_inputs.include?(v) && self.inputs.collect(&:first).include?(v)
27
+ provided_inputs[v]
28
+ elsif step_inputs.include?(v) && self.inputs.collect(&:first).include?(v)
29
+ step_inputs[v]
30
+ else
31
+ v
32
+ end
23
33
  else
24
34
  resolved_inputs[k] = v
25
35
  end
26
36
  end
27
- job = workflow.job(task, id, resolved_inputs)
37
+
38
+ job = workflow.job(task, step_id, resolved_inputs)
28
39
  compute_options = definition_options[:compute] || []
29
40
  compute_options = [compute_options] unless Array === compute_options
30
41
  compute_options << :canfail if definition_options[:canfail]
@@ -33,26 +44,25 @@ module Task
33
44
  compute[job.path] = compute_options if compute_options.any?
34
45
 
35
46
  job.overriden = false if definition_options[:not_overriden]
47
+ job.compute = job.compute.nil? ? compute : job.compute.merge(compute)
36
48
 
37
49
  [job, step_inputs]
38
50
  end
39
51
 
40
52
  # Helper function
41
- find_dep_non_default_inputs = proc do |dep,definition_options,step_inputs={}|
53
+ filter_dep_non_default_inputs = proc do |dep,definition_options|
42
54
  dep_non_default_inputs = dep.non_default_inputs
43
- dep_non_default_inputs.select do |name|
44
- step_inputs.include?(name)
45
- end
46
55
  dep_non_default_inputs.reject! do |name|
47
- definition_options.include?(name) &&
48
- (definition_options[name] != :placeholder || definition_options[name] != dep.inputs[name])
56
+ definition_options.include?(name)
49
57
  end
50
58
 
51
59
  dep_non_default_inputs
52
60
  end
53
61
 
54
62
  deps.each do |workflow,task,definition_options,block=nil|
55
- definition_options[:id] = definition_options.delete(:jobname) if definition_options.include?(:jobname)
63
+ definition_options = definition_options.nil? ? {} : definition_options.dup
64
+
65
+ dep_id = definition_options.include?(:jobname) ? definition_options.delete(:jobname) : id
56
66
 
57
67
  if provided_inputs.include?(overriden = [workflow.name, task] * "#")
58
68
  dep = provided_inputs[overriden]
@@ -66,51 +76,50 @@ module Task
66
76
  next
67
77
  end
68
78
 
69
- definition_options ||= {}
70
79
 
71
80
  if block
72
- fixed_provided_inputs = self.assign_inputs(provided_inputs).first.to_hash
73
- self.inputs.each do |name,type,desc,value|
81
+ fixed_provided_inputs = self.assign_inputs(provided_inputs, dep_id).first.to_hash
82
+ self.inputs.each do |name,type,desc,value,options|
74
83
  fixed_provided_inputs[name] = value unless fixed_provided_inputs.include?(name)
75
84
  end
76
85
  fixed_provided_inputs = IndiferentHash.add_defaults fixed_provided_inputs, provided_inputs
77
86
  block_options = IndiferentHash.add_defaults definition_options.dup, fixed_provided_inputs
78
87
 
79
- res = block.call id, block_options, dependencies
88
+ res = block.call dep_id, block_options, dependencies
80
89
 
81
90
  case res
82
91
  when Step
83
92
  dep = res
84
93
  dependencies << dep
85
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options)
94
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
86
95
  non_default_inputs.concat(dep_non_default_inputs)
87
96
  when Hash
88
97
  step_options = block_options.merge(res)
89
- dep, step_inputs = load_dep.call(id, workflow, task, step_options, block_options, dependencies)
98
+ dep, step_inputs = load_dep.call(dep_id, workflow, task, step_options.dup, block_options, dependencies)
90
99
  dependencies << dep
91
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options, step_inputs)
100
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
92
101
  non_default_inputs.concat(dep_non_default_inputs)
93
102
  when Array
94
103
  res.each do |_res|
95
104
  if Hash === _res
96
105
  step_options = block_options.merge(_res)
97
- dep, step_inputs = load_dep.call(id, workflow, task, step_options, block_options, dependencies)
106
+ dep, step_inputs = load_dep.call(dep_id, workflow, task, step_options.dup, block_options, dependencies)
98
107
  dependencies << dep
99
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options, step_inputs)
108
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
100
109
  non_default_inputs.concat(dep_non_default_inputs)
101
110
  else
102
111
  dep = _res
103
112
  dependencies << dep
104
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options)
113
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
105
114
  non_default_inputs.concat(dep_non_default_inputs)
106
115
  end
107
116
  end
108
117
  end
109
118
  else
110
119
  step_options = IndiferentHash.add_defaults definition_options.dup, provided_inputs
111
- dep, step_inputs = load_dep.call(id, workflow, task, step_options, definition_options, dependencies)
120
+ dep, step_inputs = load_dep.call(dep_id, workflow, task, step_options, definition_options, dependencies)
112
121
  dependencies << dep
113
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options, step_inputs)
122
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
114
123
  non_default_inputs.concat(dep_non_default_inputs)
115
124
  end
116
125
  end
@@ -3,7 +3,7 @@ module Task
3
3
  def self.format_input(value, type, options = {})
4
4
  return value if IO === value || StringIO === value || Step === value
5
5
 
6
- if String === value && ! [:path, :file, :folder, :binary, :tsv].include?(type) && ! (options && (options[:noload] || options[:stream] || options[:nofile]))
6
+ if String === value && ! [:path, :file, :folder, :binary, :tsv].include?(type) && ! (options && (options[:noload] || options[:stream] || options[:nofile] || options[:asfile]))
7
7
  if Open.exists?(value) && ! Open.directory?(value)
8
8
  Persist.load(value, type)
9
9
  else
@@ -35,11 +35,13 @@ module Task
35
35
  input_array = []
36
36
  input_names = []
37
37
  non_default_inputs = []
38
+ jobname_input = nil
38
39
  self.inputs.each_with_index do |p,i|
39
40
  name, type, desc, value, options = p
40
41
  input_names << name
41
42
  provided = Hash === provided_inputs ? provided_inputs[name] : provided_inputs[i]
42
43
  provided = Task.format_input(provided, type, options || {})
44
+
43
45
  if provided == value
44
46
  same_as_default = true
45
47
  elsif String === provided && Symbol === value && provided == value.to_s
@@ -49,25 +51,39 @@ module Task
49
51
  else
50
52
  same_as_default = false
51
53
  end
52
- if ! provided.nil? && ! same_as_default
53
- non_default_inputs << name.to_sym
54
- input_array << provided
55
- elsif options && options[:jobname]
56
- input_array << id
57
- else
58
- input_array << value
54
+
55
+ if options && options[:jobname] && id == provided
56
+ same_as_jobname = true
59
57
  end
58
+
59
+ jobname_input = name if same_as_jobname
60
+
61
+ final = if ! provided.nil? && ! same_as_default && ! same_as_jobname
62
+ non_default_inputs << name.to_sym
63
+ provided
64
+ elsif options && options[:jobname] && id
65
+ non_default_inputs << name.to_sym
66
+ provided || id
67
+ else
68
+ value
69
+ end
70
+
71
+ final = Path.setup(final.dup) if String === final && ! (Path === final) && (type == :file || type == :path || (options && options[:asfile]))
72
+
73
+ final = final.find if (Path === final) && (type == :file)
74
+
75
+ input_array << final
60
76
  end
61
77
 
62
78
  NamedArray.setup(input_array, input_names)
63
79
 
64
- [input_array, non_default_inputs]
80
+ [input_array, non_default_inputs, jobname_input]
65
81
  end
66
82
 
67
83
  def process_inputs(provided_inputs = {}, id = nil)
68
- input_array, non_default_inputs = assign_inputs provided_inputs, id
84
+ input_array, non_default_inputs, jobname_input = assign_inputs provided_inputs, id
69
85
  digest_str = Misc.digest_str(input_array)
70
- [input_array, non_default_inputs, digest_str]
86
+ [input_array, non_default_inputs, digest_str, jobname_input]
71
87
  end
72
88
 
73
89
  def self.save_file_input(orig_file, directory)
@@ -91,6 +107,8 @@ module Task
91
107
  if Path.is_filename?(value)
92
108
  if type == :path
93
109
  Open.write(input_file + ".as_path", value)
110
+ elsif Path.step_file?(value)
111
+ Open.write(input_file + ".as_path", value)
94
112
  else
95
113
  relative_file = save_file_input(value, directory)
96
114
  Open.write(input_file + ".as_file", relative_file)
@@ -137,7 +155,7 @@ module Task
137
155
  elsif filename.end_with?('.as_path')
138
156
  value = Open.read(filename).strip
139
157
  Path.setup value
140
- elsif (options && (options[:noload] || options[:stream] || options[:nofile]))
158
+ elsif (options && (options[:noload] || options[:stream] || options[:nofile] || options[:asfile]))
141
159
  filename
142
160
  else
143
161
  Persist.load(filename, type)
@@ -148,12 +166,24 @@ module Task
148
166
  end
149
167
 
150
168
  def load_inputs(directory)
169
+ if Open.exists?(directory) && ! Open.directory?(directory)
170
+ TmpFile.with_file do |tmp_directory|
171
+ Misc.in_dir tmp_directory do
172
+ CMD.cmd("tar xvfz '#{directory}'")
173
+ end
174
+ return load_inputs(tmp_directory)
175
+ end
176
+ end
177
+
151
178
  inputs = IndiferentHash.setup({})
179
+ seen = []
152
180
  self.recursive_inputs.each do |p|
153
181
  name, type, desc, value, options = p
182
+ next if seen.include?(name)
154
183
  filename = File.join(directory, name.to_s)
155
184
  value = Task.load_input_from_file(filename, type, options)
156
185
  inputs[name] = value unless value.nil?
186
+ seen << name
157
187
  end
158
188
 
159
189
  Dir.glob(File.join(directory, "*#*")).each do |file|
@@ -31,19 +31,29 @@ module Task
31
31
  end
32
32
 
33
33
  def job(id = nil, provided_inputs = nil)
34
- Persist.memory("Task job", other_options: {task: self, id: id, provided_inputs: provided_inputs}) do
34
+
35
+ if Hash === provided_inputs
36
+ memory_inputs = provided_inputs.values_at *self.recursive_inputs.collect{|t| t.first }.uniq
37
+ memory_inputs += provided_inputs.select{|k,v| k.to_s.include?("#") }.collect{|p| p * "=" }
38
+ memory_inputs << provided_inputs[:load_inputs]
39
+ else
40
+ memory_inputs = provided_inputs
41
+ end
42
+
43
+ Persist.memory("Task job #{self.name} #{id}", other_options: {task: self, id: id, provided_inputs: memory_inputs}) do
35
44
  provided_inputs, id = id, nil if (provided_inputs.nil? || provided_inputs.empty?) && (Hash === id || Array === id)
36
45
  provided_inputs = {} if provided_inputs.nil?
37
46
  IndiferentHash.setup(provided_inputs)
38
47
 
39
- if id.nil?
40
- inputs.each do |name,type,desc,default,input_options|
41
- next unless input_options && input_options[:jobname]
42
- id = provided_inputs[name] || default
43
- end
44
- id = DEFAULT_NAME if id.nil?
48
+ jobname_input = nil
49
+ inputs.each do |name,type,desc,default,input_options|
50
+ next unless input_options && input_options[:jobname]
51
+ jobname_input = name
45
52
  end
46
53
 
54
+ id = provided_inputs[jobname_input] if jobname_input && id.nil?
55
+ #id = provided_inputs[:id] if provided_inputs.include?(:id)
56
+
47
57
  missing_inputs = []
48
58
  self.inputs.each do |input,type,desc,val,options|
49
59
  next unless options && options[:required]
@@ -65,11 +75,13 @@ module Task
65
75
  compute = {}
66
76
  dependencies = dependencies(id, provided_inputs, non_default_inputs, compute)
67
77
 
68
- #non_default_inputs.concat provided_inputs.keys.select{|k| String === k && k.include?("#") } if Hash === provided_inputs
69
-
70
78
  non_default_inputs.uniq!
71
79
 
72
- if non_default_inputs.any?
80
+ non_default_inputs.delete_if{|k| k.to_s.include? "#" } unless dependencies.select{|d| d.overriden? }.any?
81
+
82
+ id = DEFAULT_NAME if id.nil?
83
+
84
+ if non_default_inputs.any? && !(non_default_inputs == [jobname_input] && provided_inputs[jobname_input] == id)
73
85
  hash = Misc.digest(:inputs => input_digest_str, :dependencies => dependencies)
74
86
  name = [id, hash] * "_"
75
87
  else
@@ -92,7 +104,6 @@ module Task
92
104
  end
93
105
  end
94
106
 
95
-
96
107
  path = directory[name]
97
108
 
98
109
  path = path.set_extension(extension) if extension
@@ -138,7 +138,7 @@ module Workflow
138
138
 
139
139
  dep_tree = {}
140
140
  task = self.tasks[task_name]
141
- raise "TaskNotFound: #{task_name}" if task.nil?
141
+ raise TaskNotFound, "Task #{task_name} in #{self.to_s}" if task.nil?
142
142
  task.deps.each do |workflow, task, options|
143
143
  next if seen.include? dep
144
144
  seen << [workflow, task, options.merge(seen_options)]
@@ -162,7 +162,7 @@ module Workflow
162
162
 
163
163
  def _prov_tasks(tree)
164
164
  tasks = []
165
- heap = [tree]
165
+ heap = tree.values
166
166
  while heap.any?
167
167
  t = heap.pop
168
168
  t.each do |k,v|
@@ -271,7 +271,7 @@ module Workflow
271
271
  description = description.split("\n\n").first
272
272
 
273
273
  next if abridge && ! final.include?(name)
274
- str.puts Misc.format_definition_list_item(name.to_s, description, nil, nil, :yellow)
274
+ str.puts Misc.format_definition_list_item(name.to_s, description, nil, nil, color: :yellow)
275
275
 
276
276
  prov_string = prov_string(dep_tree(name))
277
277
  str.puts Misc.format_paragraph Log.color(:blue, "->" + prov_string) if prov_string && ! prov_string.empty?
@@ -5,6 +5,8 @@ require_relative 'workflow/step'
5
5
  require_relative 'workflow/documentation'
6
6
  require_relative 'workflow/usage'
7
7
  require_relative 'workflow/deployment'
8
+ require_relative 'workflow/exceptions'
9
+ require_relative 'workflow/path'
8
10
 
9
11
  require 'scout/resource'
10
12
  require 'scout/resource/scout'
@@ -153,6 +155,7 @@ module Workflow
153
155
 
154
156
  def job(name, *args)
155
157
  task = tasks[name]
158
+ raise TaskNotFound, "Task #{name} in #{self.to_s}" if task.nil?
156
159
  step = task.job(*args)
157
160
  step.extend step_module
158
161
  step
data/scout-gear.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: scout-gear 10.7.0 ruby lib
5
+ # stub: scout-gear 10.7.2 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "scout-gear".freeze
9
- s.version = "10.7.0".freeze
9
+ s.version = "10.7.2".freeze
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Miguel Vazquez".freeze]
14
- s.date = "2024-06-05"
14
+ s.date = "2024-12-10"
15
15
  s.description = "Temporary files, logs, path, resources, persistence, workflows, TSV, etc.".freeze
16
16
  s.email = "mikisvaz@gmail.com".freeze
17
17
  s.executables = ["scout".freeze]
@@ -41,6 +41,7 @@ Gem::Specification.new do |s|
41
41
  "lib/scout/entity.rb",
42
42
  "lib/scout/entity/format.rb",
43
43
  "lib/scout/entity/identifiers.rb",
44
+ "lib/scout/entity/named_array.rb",
44
45
  "lib/scout/entity/object.rb",
45
46
  "lib/scout/entity/property.rb",
46
47
  "lib/scout/offsite.rb",
@@ -97,6 +98,8 @@ Gem::Specification.new do |s|
97
98
  "lib/scout/workflow/deployment/orchestrator.rb",
98
99
  "lib/scout/workflow/deployment/trace.rb",
99
100
  "lib/scout/workflow/documentation.rb",
101
+ "lib/scout/workflow/exceptions.rb",
102
+ "lib/scout/workflow/path.rb",
100
103
  "lib/scout/workflow/step.rb",
101
104
  "lib/scout/workflow/step/archive.rb",
102
105
  "lib/scout/workflow/step/children.rb",
@@ -119,6 +122,9 @@ Gem::Specification.new do |s|
119
122
  "scout_commands/alias",
120
123
  "scout_commands/batch/clean",
121
124
  "scout_commands/batch/list",
125
+ "scout_commands/db/query",
126
+ "scout_commands/db/register",
127
+ "scout_commands/db/show",
122
128
  "scout_commands/doc",
123
129
  "scout_commands/find",
124
130
  "scout_commands/glob",
@@ -149,6 +155,7 @@ Gem::Specification.new do |s|
149
155
  "test/scout/association/test_item.rb",
150
156
  "test/scout/entity/test_format.rb",
151
157
  "test/scout/entity/test_identifiers.rb",
158
+ "test/scout/entity/test_named_array.rb",
152
159
  "test/scout/entity/test_object.rb",
153
160
  "test/scout/entity/test_property.rb",
154
161
  "test/scout/offsite/test_ssh.rb",
@@ -186,6 +193,7 @@ Gem::Specification.new do |s|
186
193
  "test/scout/tsv/test_index.rb",
187
194
  "test/scout/tsv/test_open.rb",
188
195
  "test/scout/tsv/test_parser.rb",
196
+ "test/scout/tsv/test_path.rb",
189
197
  "test/scout/tsv/test_stream.rb",
190
198
  "test/scout/tsv/test_transformer.rb",
191
199
  "test/scout/tsv/test_traverse.rb",
@@ -212,6 +220,7 @@ Gem::Specification.new do |s|
212
220
  "test/scout/workflow/task/test_inputs.rb",
213
221
  "test/scout/workflow/test_definition.rb",
214
222
  "test/scout/workflow/test_documentation.rb",
223
+ "test/scout/workflow/test_path.rb",
215
224
  "test/scout/workflow/test_step.rb",
216
225
  "test/scout/workflow/test_task.rb",
217
226
  "test/scout/workflow/test_usage.rb",
@@ -222,7 +231,7 @@ Gem::Specification.new do |s|
222
231
  ]
223
232
  s.homepage = "http://github.com/mikisvaz/scout-gear".freeze
224
233
  s.licenses = ["MIT".freeze]
225
- s.rubygems_version = "3.5.10".freeze
234
+ s.rubygems_version = "3.5.23".freeze
226
235
  s.summary = "basic gear for scouts".freeze
227
236
 
228
237
  s.specification_version = 4
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'scout'
4
+ require 'scout/association'
5
+
6
+ $0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
7
+
8
+ options = SOPT.setup <<EOF
9
+
10
+ Query a database
11
+
12
+ $ #{$0} [<options>] <name> <entity>
13
+
14
+ -h--help Print this help
15
+ -l--list Only list matches
16
+ -s--source* Source description
17
+ -t--target* Target description
18
+ -n--namespace* Namespace
19
+ -i--identifiers* Identifiers
20
+ EOF
21
+ if options[:help]
22
+ if defined? scout_usage
23
+ scout_usage
24
+ else
25
+ puts SOPT.doc
26
+ end
27
+ exit 0
28
+ end
29
+
30
+ name, entity = ARGV
31
+
32
+ raise MissingParameterException, :name if name.nil?
33
+ raise MissingParameterException, :entity if entity.nil?
34
+
35
+ registry = begin
36
+ Scout.var.databases.registry.yaml
37
+ rescue
38
+ {}
39
+ end
40
+
41
+ list = IndiferentHash.process_options options, :list
42
+
43
+ raise ParameterException "Database #{name} not found Options: #{Log.fingerprint registry.keys}" unless registry.include? name
44
+
45
+ file, db_options = registry[name]
46
+ options = db_options.merge(options)
47
+
48
+ IndiferentHash.setup(options)
49
+ options.keys_to_sym!
50
+
51
+ index = Association.index(file, **options)
52
+
53
+ if entity.end_with?("~")
54
+ matches = index.match(entity[0..-2])
55
+ elsif entity.start_with?("~")
56
+ index = index.reverse
57
+ matches = index.match(entity[1..-1])
58
+ reverse = true
59
+ elsif entity.include?("~")
60
+ matches = [entity]
61
+ else
62
+ matches = index.match(entity)
63
+ end
64
+
65
+ AssociationItem.setup(matches) if reverse
66
+
67
+ if matches.any?
68
+ if list
69
+ if reverse
70
+ puts matches.collect(&:invert) * "\n"
71
+ else
72
+ puts matches * "\n"
73
+ end
74
+ else
75
+ matches.each do |match|
76
+ puts Log.color :magenta, (reverse ? match.invert : match)
77
+ puts index[match].prety_print
78
+ end
79
+ end
80
+ else
81
+ STDERR.puts "Query #{entity} return no results"
82
+ end
83
+
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'scout'
4
+
5
+ $0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
6
+
7
+ options = SOPT.setup <<EOF
8
+
9
+ Register a database
10
+
11
+ $ #{$0} [<options>] <name> <filename>
12
+
13
+ -h--help Print this help
14
+ -s--source* Source description
15
+ -t--target* Target description
16
+ -n--namespace* Namespace
17
+ -i--identifiers* Identifiers
18
+ EOF
19
+ if options.delete :help
20
+ if defined? scout_usage
21
+ scout_usage
22
+ else
23
+ puts SOPT.doc
24
+ end
25
+ exit 0
26
+ end
27
+
28
+ name, file = ARGV
29
+
30
+ raise MissingParameterException, :name if name.nil?
31
+ raise MissingParameterException, :file if file.nil?
32
+
33
+ registry = begin
34
+ Scout.var.databases.registry.yaml
35
+ rescue
36
+ {}
37
+ end
38
+
39
+ file = Scout.identify(File.expand_path(file))
40
+ registry[name] = [Scout.identify(file), options]
41
+
42
+ Scout.var.databases.registry.write(registry.to_yaml)
43
+