scout-gear 5.2.0 → 7.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.vimproject +450 -440
- data/VERSION +1 -1
- data/lib/scout/exceptions.rb +22 -2
- data/lib/scout/log/color.rb +61 -10
- data/lib/scout/log/progress/report.rb +5 -4
- data/lib/scout/log/progress/util.rb +2 -0
- data/lib/scout/log/progress.rb +2 -0
- data/lib/scout/log.rb +5 -1
- data/lib/scout/misc/digest.rb +1 -3
- data/lib/scout/misc/monitor.rb +18 -0
- data/lib/scout/open/stream.rb +50 -19
- data/lib/scout/semaphore.rb +148 -0
- data/lib/scout/tsv/parser.rb +144 -0
- data/lib/scout/tsv.rb +14 -0
- data/lib/scout/work_queue/socket.rb +119 -0
- data/lib/scout/work_queue/worker.rb +59 -0
- data/lib/scout/work_queue.rb +113 -0
- data/lib/scout/workflow/step/info.rb +2 -2
- data/lib/scout/workflow/step.rb +2 -1
- data/lib/scout/workflow/task.rb +2 -2
- data/scout-gear.gemspec +18 -3
- data/share/color/color_names +507 -0
- data/share/color/diverging_colors.hex +12 -0
- data/test/scout/log/test_color.rb +0 -0
- data/test/scout/open/test_stream.rb +1 -1
- data/test/scout/test_semaphore.rb +17 -0
- data/test/scout/test_tsv.rb +34 -0
- data/test/scout/test_work_queue.rb +121 -0
- data/test/scout/tsv/test_parser.rb +87 -0
- data/test/scout/work_queue/test_socket.rb +46 -0
- data/test/scout/work_queue/test_worker.rb +147 -0
- metadata +17 -2
@@ -0,0 +1,144 @@
|
|
1
|
+
module TSV
|
2
|
+
def self.cast_value(value, cast)
|
3
|
+
if Array === value
|
4
|
+
value.collect{|e| cast_value(e, cast) }
|
5
|
+
else
|
6
|
+
value.send(cast)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.parse_line(line, type: :list, key: 0, positions: nil, sep: "\t", sep2: "|", cast: nil)
|
11
|
+
items = line.split(sep, -1)
|
12
|
+
|
13
|
+
if positions.nil? && key == 0
|
14
|
+
key = items.shift
|
15
|
+
elsif positions.nil?
|
16
|
+
key = items.delete(key)
|
17
|
+
else
|
18
|
+
key, items = items[key], items.values_at(*positions)
|
19
|
+
end
|
20
|
+
|
21
|
+
items = case type
|
22
|
+
when :list
|
23
|
+
items
|
24
|
+
when :single
|
25
|
+
items.first
|
26
|
+
when :flat
|
27
|
+
[items]
|
28
|
+
when :double
|
29
|
+
items.collect{|i| i.split(sep2, -1) }
|
30
|
+
end
|
31
|
+
|
32
|
+
key = key.partition(sep2).first if type == :double
|
33
|
+
|
34
|
+
if cast
|
35
|
+
items = cast_value(items, cast)
|
36
|
+
end
|
37
|
+
|
38
|
+
[key, items]
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.parse_stream(stream, data: nil, merge: true, type: :list, fix: true, bar: false, first_line: nil, **kargs, &block)
|
42
|
+
begin
|
43
|
+
bar = Log::ProgressBar.new_bar(bar) if bar
|
44
|
+
|
45
|
+
data = {} if data.nil?
|
46
|
+
merge = false if type != :double
|
47
|
+
line = first_line || stream.gets
|
48
|
+
while line
|
49
|
+
begin
|
50
|
+
line.strip!
|
51
|
+
line = Misc.fixutf8(line) if fix
|
52
|
+
bar.tick if bar
|
53
|
+
key, items = parse_line(line, type: type, **kargs)
|
54
|
+
|
55
|
+
if block_given?
|
56
|
+
res = block.call(key, items)
|
57
|
+
data[key] = res unless res.nil?
|
58
|
+
next
|
59
|
+
end
|
60
|
+
|
61
|
+
if ! merge || ! data.include?(key)
|
62
|
+
data[key] = items
|
63
|
+
else
|
64
|
+
current = data[key]
|
65
|
+
if merge == :concat
|
66
|
+
items.each_with_index do |new,i|
|
67
|
+
next if new.empty?
|
68
|
+
current[i].concat(new)
|
69
|
+
end
|
70
|
+
else
|
71
|
+
merged = []
|
72
|
+
items.each_with_index do |new,i|
|
73
|
+
next if new.empty?
|
74
|
+
merged[i] = current[i] + new
|
75
|
+
end
|
76
|
+
data[key] = merged
|
77
|
+
end
|
78
|
+
end
|
79
|
+
ensure
|
80
|
+
line = stream.gets
|
81
|
+
end
|
82
|
+
end
|
83
|
+
data
|
84
|
+
ensure
|
85
|
+
Log::ProgressBar.remove_bar(bar) if bar
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.parse_header(stream, fix: true, header_hash: '#', sep: "\n")
|
90
|
+
raise "Closed stream" if IO === stream && stream.closed?
|
91
|
+
|
92
|
+
options = {}
|
93
|
+
preamble = []
|
94
|
+
|
95
|
+
# Get line
|
96
|
+
|
97
|
+
#Thread.pass while IO.select([stream], nil, nil, 1).nil? if IO === stream
|
98
|
+
line = stream.gets
|
99
|
+
return {} if line.nil?
|
100
|
+
line = Misc.fixutf8 line.chomp if fix
|
101
|
+
|
102
|
+
# Process options line
|
103
|
+
if line and (String === header_hash && m = line.match(/^#{header_hash}: (.*)/))
|
104
|
+
options = IndiferentHash.string2hash m.captures.first.chomp
|
105
|
+
line = stream.gets
|
106
|
+
line = Misc.fixutf8 line.chomp if line && fix
|
107
|
+
end
|
108
|
+
|
109
|
+
# Determine separator
|
110
|
+
sep = options[:sep] if options[:sep]
|
111
|
+
|
112
|
+
# Process fields line
|
113
|
+
preamble << line if line
|
114
|
+
while line && (TrueClass === header_hash || (String === header_hash && line.start_with?(header_hash)))
|
115
|
+
fields = line.split(sep, -1)
|
116
|
+
key_field = fields.shift
|
117
|
+
key_field = key_field.sub(header_hash, '') if String === header_hash && ! header_hash.empty?
|
118
|
+
|
119
|
+
line = (header_hash != "" ? stream.gets : nil)
|
120
|
+
line = Misc.fixutf8 line.chomp if line
|
121
|
+
preamble << line if line
|
122
|
+
break if TrueClass === header_hash || header_hash == ""
|
123
|
+
end
|
124
|
+
|
125
|
+
preamble = preamble[0..-3] * "\n"
|
126
|
+
|
127
|
+
line ||= stream.gets
|
128
|
+
|
129
|
+
first_line = line
|
130
|
+
|
131
|
+
[options, key_field, fields, first_line, preamble]
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.parse(stream, **kwargs)
|
135
|
+
options, key_field, fields, first_line, preamble = parse_header(stream)
|
136
|
+
|
137
|
+
options.each do |option,value|
|
138
|
+
option = option.to_sym
|
139
|
+
kwargs[option] = value unless kwargs.include?(option)
|
140
|
+
end
|
141
|
+
data = parse_stream(stream, first_line: first_line, **kwargs)
|
142
|
+
TSV.setup data, :key_field => key_field, :fields => fields
|
143
|
+
end
|
144
|
+
end
|
data/lib/scout/tsv.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'meta_extension'
|
2
|
+
require_relative 'tsv/parser'
|
3
|
+
|
4
|
+
module TSV
|
5
|
+
extend MetaExtension
|
6
|
+
extension_attr :key_field, :fields
|
7
|
+
|
8
|
+
def self.open(file, options = {})
|
9
|
+
Open.open(file) do |f|
|
10
|
+
TSV.parse(f,**options)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'scout/open'
|
2
|
+
require 'scout/semaphore'
|
3
|
+
require 'scout/exceptions'
|
4
|
+
class WorkQueue
|
5
|
+
class Socket
|
6
|
+
attr_accessor :sread, :swrite, :write_sem, :read_sem, :cleaned
|
7
|
+
def initialize(serializer = nil)
|
8
|
+
@sread, @swrite = Open.pipe
|
9
|
+
|
10
|
+
@serializer = serializer || Marshal
|
11
|
+
|
12
|
+
@key = "/" << rand(1000000000).to_s << '.' << Process.pid.to_s;
|
13
|
+
@write_sem = @key + '.in'
|
14
|
+
@read_sem = @key + '.out'
|
15
|
+
Log.debug "Creating socket semaphores: #{@key}"
|
16
|
+
ScoutSemaphore.create_semaphore(@write_sem,1)
|
17
|
+
ScoutSemaphore.create_semaphore(@read_sem,1)
|
18
|
+
end
|
19
|
+
|
20
|
+
def clean
|
21
|
+
@cleaned = true
|
22
|
+
@sread.close unless @sread.closed?
|
23
|
+
@swrite.close unless @swrite.closed?
|
24
|
+
Log.low "Destroying socket semaphores: #{[@key] * ", "}"
|
25
|
+
ScoutSemaphore.delete_semaphore(@write_sem)
|
26
|
+
ScoutSemaphore.delete_semaphore(@read_sem)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def dump(obj)
|
31
|
+
stream = @swrite
|
32
|
+
obj.concurrent_stream = nil if obj.respond_to?(:concurrent_stream)
|
33
|
+
case obj
|
34
|
+
when Integer
|
35
|
+
size_head = [obj,"I"].pack 'La'
|
36
|
+
str = size_head
|
37
|
+
when nil
|
38
|
+
size_head = [0,"N"].pack 'La'
|
39
|
+
str = size_head
|
40
|
+
when String
|
41
|
+
payload = obj
|
42
|
+
size_head = [payload.bytesize,"C"].pack 'La'
|
43
|
+
str = size_head << payload
|
44
|
+
else
|
45
|
+
payload = @serializer.dump(obj)
|
46
|
+
size_head = [payload.bytesize,"S"].pack 'La'
|
47
|
+
str = size_head << payload
|
48
|
+
end
|
49
|
+
|
50
|
+
write_length = str.length
|
51
|
+
wrote = stream.write(str)
|
52
|
+
while wrote < write_length
|
53
|
+
wrote += stream.write(str[wrote..-1])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def load
|
58
|
+
stream = @sread
|
59
|
+
size_head = Open.read_stream stream, 5
|
60
|
+
|
61
|
+
size, type = size_head.unpack('La')
|
62
|
+
|
63
|
+
return nil if type == "N"
|
64
|
+
return size.to_i if type == "I"
|
65
|
+
begin
|
66
|
+
payload = Open.read_stream stream, size
|
67
|
+
case type
|
68
|
+
when "S"
|
69
|
+
begin
|
70
|
+
@serializer.load(payload)
|
71
|
+
rescue Exception
|
72
|
+
Log.exception $!
|
73
|
+
raise $!
|
74
|
+
end
|
75
|
+
when "C"
|
76
|
+
payload
|
77
|
+
end
|
78
|
+
rescue TryAgain
|
79
|
+
retry
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def closed_read?
|
84
|
+
@sread.closed?
|
85
|
+
end
|
86
|
+
|
87
|
+
def closed_write?
|
88
|
+
@swrite.closed?
|
89
|
+
end
|
90
|
+
|
91
|
+
def close_write
|
92
|
+
self.dump ClosedStream.new
|
93
|
+
@swrite.close unless closed_write?
|
94
|
+
end
|
95
|
+
|
96
|
+
def close_read
|
97
|
+
@sread.close unless closed_read?
|
98
|
+
end
|
99
|
+
|
100
|
+
#{{{ ACCESSOR
|
101
|
+
def push(obj)
|
102
|
+
ScoutSemaphore.synchronize(@write_sem) do
|
103
|
+
self.dump(obj)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def pop
|
108
|
+
ScoutSemaphore.synchronize(@read_sem) do
|
109
|
+
res = self.load
|
110
|
+
raise res if ClosedStream === res
|
111
|
+
res
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
alias write push
|
116
|
+
|
117
|
+
alias read pop
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class WorkQueue
|
2
|
+
class Worker
|
3
|
+
attr_accessor :pid, :ignore_ouput
|
4
|
+
def initialize(ignore_ouput = false)
|
5
|
+
@ignore_output = ignore_ouput
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
@pid = Process.fork do
|
10
|
+
Log.debug "Worker start with #{Process.pid}"
|
11
|
+
yield
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def process(input, output = nil, &block)
|
16
|
+
run do
|
17
|
+
begin
|
18
|
+
while obj = input.read
|
19
|
+
if DoneProcessing === obj
|
20
|
+
output.write DoneProcessing.new
|
21
|
+
raise obj
|
22
|
+
end
|
23
|
+
res = block.call obj
|
24
|
+
output.write res unless output.nil? || ignore_ouput || res == :ignore
|
25
|
+
end
|
26
|
+
rescue DoneProcessing
|
27
|
+
rescue Interrupt
|
28
|
+
rescue Exception
|
29
|
+
output.write WorkerException.new($!, Process.pid)
|
30
|
+
exit -1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def abort
|
36
|
+
begin
|
37
|
+
Log.log "Aborting worker #{@pid}"
|
38
|
+
Process.kill "INT", @pid
|
39
|
+
rescue Errno::ECHILD
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def join
|
44
|
+
Log.log "Joining worker #{@pid}"
|
45
|
+
Process.waitpid @pid
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.join(workers)
|
49
|
+
workers = [workers] unless Array === workers
|
50
|
+
begin
|
51
|
+
while pid = Process.wait
|
52
|
+
status = $?
|
53
|
+
worker = workers.select{|w| w.pid == pid }.first
|
54
|
+
end
|
55
|
+
rescue Errno::ECHILD
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require_relative 'work_queue/socket'
|
2
|
+
require_relative 'work_queue/worker'
|
3
|
+
|
4
|
+
class WorkQueue
|
5
|
+
attr_accessor :workers, :worker_proc, :callback
|
6
|
+
|
7
|
+
def initialize(workers = 0, &block)
|
8
|
+
@input = WorkQueue::Socket.new
|
9
|
+
@output = WorkQueue::Socket.new
|
10
|
+
@workers = workers.times.collect{ Worker.new }
|
11
|
+
@worker_proc = block
|
12
|
+
@worker_mutex = Mutex.new
|
13
|
+
@removed_workers = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_worker(&block)
|
17
|
+
worker = Worker.new
|
18
|
+
@worker_mutex.synchronize do
|
19
|
+
@workers.push(worker)
|
20
|
+
if block_given?
|
21
|
+
worker.process @input, @output, &block
|
22
|
+
else
|
23
|
+
worker.process @input, @output, &@worker_proc
|
24
|
+
end
|
25
|
+
end
|
26
|
+
worker
|
27
|
+
end
|
28
|
+
|
29
|
+
def ignore_ouput
|
30
|
+
@workers.each{|w| w.ignore_ouput = true }
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove_one_worker
|
34
|
+
@input.write DoneProcessing.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove_worker(pid)
|
38
|
+
@worker_mutex.synchronize do
|
39
|
+
@workers.delete_if{|w| w.pid == pid }
|
40
|
+
@removed_workers << pid
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def process(&callback)
|
45
|
+
@reader = Thread.new do |parent|
|
46
|
+
begin
|
47
|
+
Thread.current.report_on_exception = false
|
48
|
+
Thread.current["name"] = "Output reader #{Process.pid}"
|
49
|
+
@done_workers ||= []
|
50
|
+
while true
|
51
|
+
obj = @output.read
|
52
|
+
if DoneProcessing === obj
|
53
|
+
done = @worker_mutex.synchronize do
|
54
|
+
Log.low "Worker #{obj.pid} done"
|
55
|
+
@done_workers << obj.pid
|
56
|
+
@done_workers.length == @removed_workers.length + @workers.length
|
57
|
+
end
|
58
|
+
break if done
|
59
|
+
elsif Exception === obj
|
60
|
+
raise obj
|
61
|
+
else
|
62
|
+
callback.call obj if callback
|
63
|
+
end
|
64
|
+
end
|
65
|
+
rescue DoneProcessing
|
66
|
+
rescue Aborted
|
67
|
+
rescue WorkerException
|
68
|
+
Log.error "Exception in worker #{obj.pid} #{Log.fingerprint obj.exception}"
|
69
|
+
self.abort
|
70
|
+
raise obj.exception
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
@workers.each do |w|
|
75
|
+
w.process @input, @output, &@worker_proc
|
76
|
+
end
|
77
|
+
|
78
|
+
Thread.pass until @reader["name"]
|
79
|
+
|
80
|
+
@waiter = Thread.new do
|
81
|
+
begin
|
82
|
+
Thread.current.report_on_exception = false
|
83
|
+
Thread.current["name"] = "Worker waiter #{Process.pid}"
|
84
|
+
while true
|
85
|
+
pid = Process.wait
|
86
|
+
remove_worker(pid)
|
87
|
+
break if workers.empty?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
Thread.pass until @waiter["name"]
|
93
|
+
end
|
94
|
+
|
95
|
+
def write(obj)
|
96
|
+
@input.write obj
|
97
|
+
end
|
98
|
+
|
99
|
+
def abort
|
100
|
+
workers.each{|w| w.abort }
|
101
|
+
end
|
102
|
+
|
103
|
+
def close
|
104
|
+
@worker_mutex.synchronize{ @workers.length }.times do
|
105
|
+
@input.write DoneProcessing.new()
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def join
|
110
|
+
@waiter.join if @waiter
|
111
|
+
@reader.join if @reader
|
112
|
+
end
|
113
|
+
end
|
@@ -55,9 +55,9 @@ class Step
|
|
55
55
|
|
56
56
|
def report_status(status, message = nil)
|
57
57
|
if message.nil?
|
58
|
-
Log.info Log.color(:
|
58
|
+
Log.info Log.color(:status, status, true) + " " + Log.color(:path, path)
|
59
59
|
else
|
60
|
-
Log.info Log.color(:
|
60
|
+
Log.info Log.color(:status, status, true) + " " + Log.color(:path, path) + " " + message
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
data/lib/scout/workflow/step.rb
CHANGED
data/lib/scout/workflow/task.rb
CHANGED
@@ -143,8 +143,8 @@ module Task
|
|
143
143
|
non_default_inputs.concat provided_inputs.keys.select{|k| String === k && k.include?("#") } if Hash === provided_inputs
|
144
144
|
|
145
145
|
if non_default_inputs.any?
|
146
|
-
hash = Misc.digest(:inputs => input_hash, :
|
147
|
-
Log.debug "Hash #{name} - #{hash}: #{Misc.digest_str(:inputs => inputs, :dependencies => dependencies)}"
|
146
|
+
hash = Misc.digest(:inputs => input_hash, :dependencies => dependencies)
|
147
|
+
Log.debug "Hash #{name} - #{hash}: #{Misc.digest_str(:inputs => inputs, :non_default_inputs => non_default_inputs, :dependencies => dependencies)}"
|
148
148
|
id = [id, hash] * "_"
|
149
149
|
end
|
150
150
|
|
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
|
5
|
+
# stub: scout-gear 7.1.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "scout-gear".freeze
|
9
|
-
s.version = "
|
9
|
+
s.version = "7.1.0"
|
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 = "2023-
|
14
|
+
s.date = "2023-05-01"
|
15
15
|
s.description = "Temporary files, logs, etc.".freeze
|
16
16
|
s.email = "mikisvaz@gmail.com".freeze
|
17
17
|
s.executables = ["scout".freeze]
|
@@ -69,6 +69,7 @@ Gem::Specification.new do |s|
|
|
69
69
|
"lib/scout/resource/produce/rake.rb",
|
70
70
|
"lib/scout/resource/scout.rb",
|
71
71
|
"lib/scout/resource/util.rb",
|
72
|
+
"lib/scout/semaphore.rb",
|
72
73
|
"lib/scout/simple_opt.rb",
|
73
74
|
"lib/scout/simple_opt/accessor.rb",
|
74
75
|
"lib/scout/simple_opt/doc.rb",
|
@@ -76,6 +77,11 @@ Gem::Specification.new do |s|
|
|
76
77
|
"lib/scout/simple_opt/parse.rb",
|
77
78
|
"lib/scout/simple_opt/setup.rb",
|
78
79
|
"lib/scout/tmpfile.rb",
|
80
|
+
"lib/scout/tsv.rb",
|
81
|
+
"lib/scout/tsv/parser.rb",
|
82
|
+
"lib/scout/work_queue.rb",
|
83
|
+
"lib/scout/work_queue/socket.rb",
|
84
|
+
"lib/scout/work_queue/worker.rb",
|
79
85
|
"lib/scout/workflow.rb",
|
80
86
|
"lib/scout/workflow/definition.rb",
|
81
87
|
"lib/scout/workflow/documentation.rb",
|
@@ -96,8 +102,11 @@ Gem::Specification.new do |s|
|
|
96
102
|
"scout_commands/workflow/list",
|
97
103
|
"scout_commands/workflow/task",
|
98
104
|
"scout_commands/workflow/task_old",
|
105
|
+
"share/color/color_names",
|
106
|
+
"share/color/diverging_colors.hex",
|
99
107
|
"test/scout/indiferent_hash/test_case_insensitive.rb",
|
100
108
|
"test/scout/indiferent_hash/test_options.rb",
|
109
|
+
"test/scout/log/test_color.rb",
|
101
110
|
"test/scout/log/test_progress.rb",
|
102
111
|
"test/scout/misc/test_digest.rb",
|
103
112
|
"test/scout/misc/test_filesystem.rb",
|
@@ -128,8 +137,14 @@ Gem::Specification.new do |s|
|
|
128
137
|
"test/scout/test_path.rb",
|
129
138
|
"test/scout/test_persist.rb",
|
130
139
|
"test/scout/test_resource.rb",
|
140
|
+
"test/scout/test_semaphore.rb",
|
131
141
|
"test/scout/test_tmpfile.rb",
|
142
|
+
"test/scout/test_tsv.rb",
|
143
|
+
"test/scout/test_work_queue.rb",
|
132
144
|
"test/scout/test_workflow.rb",
|
145
|
+
"test/scout/tsv/test_parser.rb",
|
146
|
+
"test/scout/work_queue/test_socket.rb",
|
147
|
+
"test/scout/work_queue/test_worker.rb",
|
133
148
|
"test/scout/workflow/step/test_info.rb",
|
134
149
|
"test/scout/workflow/step/test_load.rb",
|
135
150
|
"test/scout/workflow/task/test_inputs.rb",
|