miga-base 1.1.3.6 → 1.2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/miga/cli/action/browse.rb +1 -1
- data/lib/miga/cli/action/daemon.rb +7 -3
- data/lib/miga/cli/action/derep_wf.rb +5 -5
- data/lib/miga/cli/action/doctor.rb +16 -7
- data/lib/miga/cli/action/get_db.rb +5 -1
- data/lib/miga/cli/action/init/files_helper.rb +6 -1
- data/lib/miga/cli/action/init.rb +30 -26
- data/lib/miga/cli/action/ls.rb +35 -16
- data/lib/miga/cli/action/run.rb +21 -9
- data/lib/miga/cli/action/tax_dist.rb +0 -1
- data/lib/miga/cli/base.rb +3 -4
- data/lib/miga/cli/opt_helper.rb +11 -6
- data/lib/miga/common/errors.rb +12 -0
- data/lib/miga/common/format.rb +5 -4
- data/lib/miga/common/system_call.rb +93 -0
- data/lib/miga/common.rb +14 -5
- data/lib/miga/daemon.rb +4 -2
- data/lib/miga/result/stats.rb +5 -6
- data/lib/miga/tax_dist.rb +0 -1
- data/lib/miga/version.rb +2 -2
- data/test/format_test.rb +21 -0
- data/test/system_call_test.rb +50 -0
- data/utils/distance/base.rb +1 -1
- data/utils/distance/commands.rb +1 -2
- data/utils/distance/pipeline.rb +3 -3
- data/utils/find-medoid.R +1 -2
- data/utils/subclade/base.rb +6 -1
- data/utils/subclade/pipeline.rb +18 -7
- data/utils/subclade/runner.rb +2 -6
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: afb7c816474f73c547c7f54982293fe72c24d7829184801ab51fc848adf3d9e3
|
4
|
+
data.tar.gz: 06d51ebc47e96c28072c8415321014535ea7576d9e6f1c381e3ca62dc880df15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4f5279fdba54ad1f8bcbce86cb84a7643b473b7742686e8e9992f8c4af7c982d5776a5a06775b10df67b61de90c4a32f915b51a17a9b11a223474574e7f8159
|
7
|
+
data.tar.gz: bcd547a1dc5337fbf036ba8e2df6de6db4c4fb34979afeb30ce6c1a692e76166b5412457fb3cc778e03cb601a192af0c8d33709b2e5d7233508dfdbd1c5156ed
|
@@ -179,7 +179,7 @@ class MiGA::Cli::Action::Browse < MiGA::Cli::Action
|
|
179
179
|
str
|
180
180
|
.to_s.unmiga_name
|
181
181
|
.sub(/^./, &:upcase)
|
182
|
-
.gsub(/(Aai|Ani|Ogs|Cds|Ssu| db$| ssu )/, &:upcase)
|
182
|
+
.gsub(/(Aai|Ani|Ogs|Cds|Ssu|Rds|ani95|aai90| db$| ssu )/, &:upcase)
|
183
183
|
.sub(/Haai/, 'hAAI')
|
184
184
|
.sub(/Mytaxa/, 'MyTaxa')
|
185
185
|
.sub(/ pvalue$/, ' p-value')
|
@@ -38,9 +38,13 @@ class MiGA::Cli::Action::Daemon < MiGA::Cli::Action
|
|
38
38
|
'Path to the list of execution hostnames'
|
39
39
|
) { |v| cli[:nodelist] = v }
|
40
40
|
opt.on(
|
41
|
-
'--ppn INT',
|
41
|
+
'--ppn INT', Integer,
|
42
42
|
'Maximum number of cores to use in a single job'
|
43
|
-
) { |v| cli[:ppn] = v
|
43
|
+
) { |v| cli[:ppn] = v }
|
44
|
+
opt.on(
|
45
|
+
'--ppn-project INT', Integer,
|
46
|
+
'Maximum number of cores to use in project-wide tasks'
|
47
|
+
) { |v| cli[:ppn_project] = v }
|
44
48
|
opt.on(
|
45
49
|
'--json PATH',
|
46
50
|
'Path to a custom daemon definition in json format'
|
@@ -81,7 +85,7 @@ class MiGA::Cli::Action::Daemon < MiGA::Cli::Action
|
|
81
85
|
# Configure and run daemon
|
82
86
|
p = cli.load_project
|
83
87
|
d = MiGA::Daemon.new(p, cli[:json])
|
84
|
-
dopts = %i[latency maxjobs nodelist ppn shutdown_when_done]
|
88
|
+
dopts = %i[latency maxjobs nodelist ppn ppn_project shutdown_when_done]
|
85
89
|
dopts.each { |k| d.runopts(k, cli[k]) }
|
86
90
|
d.show_log! if cli[:show_log]
|
87
91
|
d.daemon(cli.operation, cli[:daemon_opts])
|
@@ -73,14 +73,14 @@ class MiGA::Cli::Action::DerepWf < MiGA::Cli::Action
|
|
73
73
|
c_f = r.file_path(:clades_gsp) or raise 'Result incomplete: run failed'
|
74
74
|
clades = File.readlines(c_f).map { |i| i.chomp.split("\t") }
|
75
75
|
rep = representatives(p)
|
76
|
-
File.open(File.
|
76
|
+
File.open(File.join(cli[:outdir], 'genomospecies.tsv'), 'w') do |fh|
|
77
77
|
fh.puts "Clade\tRepresentative\tMembers"
|
78
78
|
clades.each_with_index do |i, k|
|
79
79
|
fh.puts ["gsp_#{k + 1}", rep[k], i.join(',')].join("\t")
|
80
80
|
end
|
81
81
|
end
|
82
82
|
if cli[:collection]
|
83
|
-
dir = File.
|
83
|
+
dir = File.join(cli[:outdir], 'representatives')
|
84
84
|
FileUtils.mkdir_p(dir)
|
85
85
|
rep.each do |i|
|
86
86
|
f = p.dataset(i).result(:assembly).file_path(:largecontigs)
|
@@ -91,12 +91,12 @@ class MiGA::Cli::Action::DerepWf < MiGA::Cli::Action
|
|
91
91
|
|
92
92
|
def representatives(p)
|
93
93
|
cli.say 'Identifying representatives'
|
94
|
-
f = File.
|
94
|
+
f = File.join(cli[:outdir], 'representatives.txt')
|
95
95
|
if cli[:criterion] == :medoids
|
96
96
|
FileUtils.cp(p.result(:clade_finding).file_path(:medoids_gsp), f)
|
97
97
|
else
|
98
|
-
src = File.
|
99
|
-
|
98
|
+
src = File.join(MiGA::MiGA.root_path, 'utils/representatives.rb')
|
99
|
+
MiGA::MiGA.run_cmd("ruby '#{src}' '#{p.path}' | cut -f 2", stdout: f)
|
100
100
|
end
|
101
101
|
File.readlines(f).map(&:chomp)
|
102
102
|
end
|
@@ -236,8 +236,7 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
|
|
236
236
|
file = res.file_path(f) or next
|
237
237
|
if file !~ /\.gz/
|
238
238
|
cli.say " > Gzipping #{d.name} #{f} "
|
239
|
-
|
240
|
-
warn(cmdo) unless cmdo.empty?
|
239
|
+
run_cmd(['gzip', '-9', file])
|
241
240
|
changed = true
|
242
241
|
end
|
243
242
|
end
|
@@ -267,8 +266,9 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
|
|
267
266
|
next if Dir["#{dir}/*.faa"].empty?
|
268
267
|
|
269
268
|
cli.say " > Fixing #{d.name}"
|
270
|
-
|
271
|
-
|
269
|
+
run_cmd <<~CMD
|
270
|
+
cd #{dir.shellescape} && tar -zcf proteins.tar.gz *.faa && rm *.faa
|
271
|
+
CMD
|
272
272
|
end
|
273
273
|
end
|
274
274
|
|
@@ -292,10 +292,11 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
|
|
292
292
|
fix = false
|
293
293
|
unless dir.nil?
|
294
294
|
if Dir.exist? dir
|
295
|
-
|
295
|
+
run_cmd <<~CMD
|
296
|
+
cd #{dir.shellescape}/.. \
|
296
297
|
&& tar -zcf '#{d.name}.reg.tar.gz' '#{d.name}.reg' \
|
297
|
-
&& rm -r '#{d.name}.reg'
|
298
|
-
|
298
|
+
&& rm -r '#{d.name}.reg'
|
299
|
+
CMD
|
299
300
|
end
|
300
301
|
fix = true
|
301
302
|
end
|
@@ -335,4 +336,12 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
|
|
335
336
|
# TODO: Find different 95%ANI clusters with genomes from the same species
|
336
337
|
# TODO: Find AAI values too high or too low for each LCA rank
|
337
338
|
end
|
339
|
+
|
340
|
+
##
|
341
|
+
# Run command +cmd+ with options +opts+
|
342
|
+
def run_cmd(cmd, opts = {})
|
343
|
+
opts = { return: :output, err2out: true, raise: false }.merge(opts)
|
344
|
+
cmdo = MiGA::MiGA.run_cmd(cmd, opts).chomp
|
345
|
+
warn(cmdo) unless cmdo.empty?
|
346
|
+
end
|
338
347
|
end
|
@@ -190,7 +190,11 @@ class MiGA::Cli::Action::GetDb < MiGA::Cli::Action
|
|
190
190
|
|
191
191
|
def unarchive(file)
|
192
192
|
cli.say "Unarchiving #{file}"
|
193
|
-
|
193
|
+
MiGA::MiGA.run_cmd <<~CMD
|
194
|
+
cd #{cli[:local].shellescape} \
|
195
|
+
&& tar -zxf #{file.shellescape} \
|
196
|
+
&& rm #{file.shellescape}
|
197
|
+
CMD
|
194
198
|
end
|
195
199
|
|
196
200
|
def register_database(manif, db, ver)
|
@@ -107,7 +107,12 @@ module MiGA::Cli::Action::Init::FilesHelper
|
|
107
107
|
MiGA::MiGA.download_file_ftp(
|
108
108
|
:miga_dist, arch, File.join(miga_db, arch)
|
109
109
|
) { |n, size| cli.advance("#{arch}:", n, size) }
|
110
|
-
|
110
|
+
cmd = <<~CMD
|
111
|
+
cd #{miga_db.shellescape} \
|
112
|
+
&& tar zxf #{arch.shellescape} \
|
113
|
+
&& rm #{arch.shellescape}
|
114
|
+
CMD
|
115
|
+
run_cmd(cmd, source: nil)
|
111
116
|
cli.puts
|
112
117
|
end
|
113
118
|
end
|
data/lib/miga/cli/action/init.rb
CHANGED
@@ -83,14 +83,16 @@ class MiGA::Cli::Action::Init < MiGA::Cli::Action
|
|
83
83
|
def empty_action
|
84
84
|
end
|
85
85
|
|
86
|
-
def run_cmd(cli, cmd)
|
87
|
-
|
86
|
+
def run_cmd(cli, cmd, opts = {})
|
87
|
+
opts = { return: :output, source: cli[:config] }.merge(opts)
|
88
|
+
MiGA::MiGA.run_cmd(cmd, opts)
|
88
89
|
end
|
89
90
|
|
90
|
-
def run_r_cmd(cli, paths, cmd)
|
91
|
+
def run_r_cmd(cli, paths, cmd, opts = {})
|
91
92
|
run_cmd(
|
92
93
|
cli,
|
93
|
-
"echo #{cmd.shellescape} | #{paths['R'].shellescape} --vanilla -q
|
94
|
+
"echo #{cmd.shellescape} | #{paths['R'].shellescape} --vanilla -q",
|
95
|
+
{ err2out: true, stdout: '/dev/null' }.merge(opts)
|
94
96
|
)
|
95
97
|
end
|
96
98
|
|
@@ -159,7 +161,7 @@ class MiGA::Cli::Action::Init < MiGA::Cli::Action
|
|
159
161
|
def find_software(exec)
|
160
162
|
path = nil
|
161
163
|
loop do
|
162
|
-
d_path = File.dirname(run_cmd(cli,
|
164
|
+
d_path = File.dirname(run_cmd(cli, ['which', exec], raise: false))
|
163
165
|
if cli[:ask] || d_path == '.'
|
164
166
|
path = cli.ask_user('Where can I find it?', d_path, nil, true)
|
165
167
|
else
|
@@ -172,7 +174,7 @@ class MiGA::Cli::Action::Init < MiGA::Cli::Action
|
|
172
174
|
end
|
173
175
|
break
|
174
176
|
end
|
175
|
-
cli.print "I cannot find #{exec} "
|
177
|
+
cli.print "I cannot find #{exec}. "
|
176
178
|
end
|
177
179
|
path
|
178
180
|
end
|
@@ -208,19 +210,21 @@ class MiGA::Cli::Action::Init < MiGA::Cli::Action
|
|
208
210
|
end
|
209
211
|
|
210
212
|
def test_library(cli, paths, language, pkg)
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
213
|
+
opts = { raise: false, return: :status, stderr: '/dev/null' }
|
214
|
+
status =
|
215
|
+
case language
|
216
|
+
when :r
|
217
|
+
run_r_cmd(cli, paths, "library('#{pkg}')", opts)
|
218
|
+
when :ruby
|
219
|
+
x = [paths['ruby'], '-r', pkg, '-e', '']
|
220
|
+
run_cmd(cli, x, opts)
|
221
|
+
when :python
|
222
|
+
x = [paths['python3'], '-c', "import #{pkg}"]
|
223
|
+
run_cmd(cli, x, opts)
|
224
|
+
else
|
225
|
+
raise "Unrecognized language: #{language}"
|
226
|
+
end
|
227
|
+
status.success?
|
224
228
|
end
|
225
229
|
|
226
230
|
def install_library(cli, paths, language, pkg)
|
@@ -232,14 +236,14 @@ class MiGA::Cli::Action::Init < MiGA::Cli::Action
|
|
232
236
|
# This hackey mess is meant to ensure the test and installation are done
|
233
237
|
# on the configuration Ruby, not on the Ruby currently executing the
|
234
238
|
# init action
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
+
x = [
|
240
|
+
paths['ruby'], '-r', 'rubygems', '-r', 'rubygems/gem_runner',
|
241
|
+
'-e', "Gem::GemRunner.new.run %w(install --user #{pkg})"
|
242
|
+
]
|
243
|
+
run_cmd(cli, x, err2out: true)
|
239
244
|
when :python
|
240
|
-
x =
|
241
|
-
|
242
|
-
run_cmd(cli, x)
|
245
|
+
x = [paths['python3'], '-m', 'pip', 'install', '--user', pkg]
|
246
|
+
run_cmd(cli, x, err2out: true)
|
243
247
|
else
|
244
248
|
raise "Unrecognized language: #{language}"
|
245
249
|
end
|
data/lib/miga/cli/action/ls.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
#
|
2
|
-
# @license Artistic-2.0
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require 'miga/cli/action'
|
5
4
|
|
@@ -42,33 +41,53 @@ class MiGA::Cli::Action::Ls < MiGA::Cli::Action
|
|
42
41
|
'-s', '--silent',
|
43
42
|
'No output and exit with non-zero status if the dataset list is empty'
|
44
43
|
) { |v| cli[:silent] = v }
|
44
|
+
opt.on(
|
45
|
+
'--exec CMD',
|
46
|
+
'Command to execute per dataset, with the following token variables:',
|
47
|
+
'~ {{dataset}}: Name of the dataset',
|
48
|
+
'~ {{project}}: Path to the project'
|
49
|
+
) { |v| cli[:exec] = v }
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
48
53
|
def perform
|
49
54
|
ds = cli.load_and_filter_datasets(cli[:silent])
|
55
|
+
p = cli.load_project
|
50
56
|
exit(ds.empty? ? 1 : 0) if cli[:silent]
|
51
|
-
|
57
|
+
|
58
|
+
head = nil
|
59
|
+
fun = nil
|
60
|
+
if cli[:datum]
|
52
61
|
cli[:tabular] = true
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
62
|
+
head = [nil, nil]
|
63
|
+
fun = proc { |d| [d.name, d.metadata[cli[:datum]]] }
|
64
|
+
elsif cli[:fields]
|
65
|
+
head = [:name] + cli[:fields]
|
66
|
+
fun = proc { |d| [d.name] + cli[:fields].map { |f| d.metadata[f] } }
|
58
67
|
elsif cli[:info]
|
59
|
-
|
68
|
+
head = Dataset.INFO_FIELDS
|
69
|
+
fun = proc(&:info)
|
60
70
|
elsif cli[:processing]
|
61
|
-
|
62
|
-
|
63
|
-
[d.name] + d.profile_advance.map { |i|
|
71
|
+
head = [:name] + MiGA::Dataset.PREPROCESSING_TASKS
|
72
|
+
fun = proc do |d|
|
73
|
+
[d.name] + d.profile_advance.map { |i| %w[- done queued][i] }
|
64
74
|
end
|
65
75
|
elsif cli[:taskstatus]
|
66
|
-
|
67
|
-
|
68
|
-
end
|
76
|
+
head = [:name] + MiGA::Dataset.PREPROCESSING_TASKS
|
77
|
+
fun = proc { |d| [d.name] + d.results_status.values }
|
69
78
|
else
|
70
79
|
cli[:tabular] = true
|
71
|
-
|
80
|
+
head = [nil]
|
81
|
+
fun = proc { |d| [d.name] }
|
82
|
+
end
|
83
|
+
|
84
|
+
format_table(ds, head) do |d|
|
85
|
+
if cli[:exec]
|
86
|
+
MiGA::MiGA.run_cmd(
|
87
|
+
cli[:exec].miga_variables(dataset: d.name, project: p.path)
|
88
|
+
)
|
89
|
+
end
|
90
|
+
fun[d]
|
72
91
|
end
|
73
92
|
end
|
74
93
|
|
data/lib/miga/cli/action/run.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
# @license Artistic-2.0
|
3
3
|
|
4
4
|
require 'miga/cli/action'
|
5
|
-
require 'shellwords'
|
6
5
|
|
7
6
|
class MiGA::Cli::Action::Run < MiGA::Cli::Action
|
8
7
|
def parse_cli
|
@@ -54,9 +53,13 @@ class MiGA::Cli::Action::Run < MiGA::Cli::Action
|
|
54
53
|
|
55
54
|
# Prepare command
|
56
55
|
miga = MiGA.root_path
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
opts = {}
|
57
|
+
cmd = [
|
58
|
+
"PROJECT=#{p.path.shellescape}",
|
59
|
+
"RUNTYPE=#{cli[:remote] ? 'ssh' : 'bash'}",
|
60
|
+
"MIGA=#{miga.shellescape}",
|
61
|
+
"CORES=#{cli[:thr]}"
|
62
|
+
]
|
60
63
|
obj = cli.load_project_or_dataset
|
61
64
|
klass = obj.class
|
62
65
|
virtual_task = %i[p d maintenance].include?(cli[:result])
|
@@ -67,13 +70,22 @@ class MiGA::Cli::Action::Run < MiGA::Cli::Action
|
|
67
70
|
|
68
71
|
cmd << MiGA.script_path(cli[:result], miga: miga, project: p).shellescape
|
69
72
|
if cli[:remote]
|
70
|
-
cmd = [
|
71
|
-
|
73
|
+
cmd = [
|
74
|
+
'ssh', '-t', '-t',
|
75
|
+
cli[:remote].shellescape,
|
76
|
+
cmd.join(' ').shellescape
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
80
|
+
if cli[:log]
|
81
|
+
opts[:stdout] = cli[:log]
|
82
|
+
opts[:err2out] = true
|
72
83
|
end
|
73
|
-
cmd << ['>', cli[:log].shellescape, '2>&1'] if cli[:log]
|
74
84
|
|
75
85
|
# Launch
|
76
|
-
|
77
|
-
|
86
|
+
# note that all elements were carefully escaped in advace, so this has to be
|
87
|
+
# passed as String to avoid double-escaping or unintentionally escaping
|
88
|
+
# characters such as `=` and `>`
|
89
|
+
MiGA::MiGA.run_cmd(cmd.join(' '), opts)
|
78
90
|
end
|
79
91
|
end
|
data/lib/miga/cli/base.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
#
|
2
|
-
# @license Artistic-2.0
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module MiGA::Cli::Base
|
5
4
|
@@TASK_DESC = {
|
@@ -20,10 +19,10 @@ module MiGA::Cli::Base
|
|
20
19
|
add: 'Create a dataset in a MiGA project',
|
21
20
|
get: 'Download a dataset from public databases into a MiGA project',
|
22
21
|
ncbi_get: 'Download all genomes in a taxon from NCBI into a MiGA project',
|
23
|
-
rm: 'Remove a dataset from
|
22
|
+
rm: 'Remove a dataset from a MiGA project',
|
24
23
|
find: 'Find unregistered datasets based on result files',
|
25
24
|
ln: 'Link datasets (including results) from one project to another',
|
26
|
-
ls: 'List all registered datasets in
|
25
|
+
ls: 'List all registered datasets in a MiGA project',
|
27
26
|
archive: 'Generate a tar-ball with all files from select datasets',
|
28
27
|
# Results
|
29
28
|
add_result: 'Register a result',
|
data/lib/miga/cli/opt_helper.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
#
|
2
|
-
# @license Artistic-2.0
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
3
|
+
##
|
4
|
+
# Helper module including functions for CLI options
|
4
5
|
module MiGA::Cli::OptHelper
|
5
6
|
##
|
6
7
|
# Send MiGA's banner to OptionParser +opt+
|
@@ -26,6 +27,10 @@ module MiGA::Cli::OptHelper
|
|
26
27
|
'Accept all defaults as answers'
|
27
28
|
) { |v| self[:auto] = v }
|
28
29
|
end
|
30
|
+
opt.on(
|
31
|
+
'--rand-seed INT', Integer,
|
32
|
+
'Set this seed to initialize pseudo-randomness'
|
33
|
+
) { |v| srand(v) }
|
29
34
|
opt.on(
|
30
35
|
'-v', '--verbose',
|
31
36
|
'Print additional information to STDERR'
|
@@ -61,7 +66,7 @@ module MiGA::Cli::OptHelper
|
|
61
66
|
# - :result_project To require a type of project result
|
62
67
|
# The options :result, :result_opt, :result_dataset, and :result_project
|
63
68
|
# are mutually exclusive
|
64
|
-
def opt_object(opt, what = [
|
69
|
+
def opt_object(opt, what = %i[project dataset])
|
65
70
|
what.each do |w|
|
66
71
|
case w
|
67
72
|
when :project
|
@@ -86,7 +91,7 @@ module MiGA::Cli::OptHelper
|
|
86
91
|
when :result, :result_opt
|
87
92
|
opt.on(
|
88
93
|
'-r', '--result STRING',
|
89
|
-
"#{
|
94
|
+
"#{'(Mandatory) ' if w == :result}Name of the result",
|
90
95
|
'Recognized names for dataset-specific results include:',
|
91
96
|
*MiGA::Dataset.RESULT_DIRS.keys.map { |n| " ~ #{n}" },
|
92
97
|
'Recognized names for project-wide results include:',
|
@@ -118,7 +123,7 @@ module MiGA::Cli::OptHelper
|
|
118
123
|
# - :active To filter by active (--active) or inactive (--no-active)
|
119
124
|
# - :taxonomy To filter by taxonomy (--taxonomy)
|
120
125
|
# The "k-th" filter (--dataset-k) is always included
|
121
|
-
def opt_filter_datasets(opt, what = [
|
126
|
+
def opt_filter_datasets(opt, what = %i[ref multi active taxonomy])
|
122
127
|
what.each do |w|
|
123
128
|
case w
|
124
129
|
when :ref
|
@@ -161,6 +166,6 @@ module MiGA::Cli::OptHelper
|
|
161
166
|
# If +sym+ is nil, +flag+ is used as Symbol
|
162
167
|
def opt_flag(opt, flag, description, sym = nil)
|
163
168
|
sym = flag.to_sym if sym.nil?
|
164
|
-
opt.on("--#{flag.to_s.
|
169
|
+
opt.on("--#{flag.to_s.tr('_', '-')}", description) { |v| self[sym] = v }
|
165
170
|
end
|
166
171
|
end
|
data/lib/miga/common/format.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'tempfile'
|
2
|
-
require 'zlib'
|
3
4
|
|
4
5
|
##
|
5
6
|
# General formatting functions shared throughout MiGA.
|
@@ -38,13 +39,13 @@ module MiGA::Common::Format
|
|
38
39
|
tmp_path = tmp_fh.path
|
39
40
|
fh = File.open(file, 'r')
|
40
41
|
end
|
41
|
-
buffer = ''
|
42
|
+
buffer = ''.dup
|
42
43
|
fh.each_line do |ln|
|
43
44
|
ln.chomp!
|
44
45
|
if ln =~ /^>\s*(\S+)(.*)/
|
45
46
|
id, df = $1, $2
|
46
47
|
tmp_fh.print buffer.wrap_width(80)
|
47
|
-
buffer = ''
|
48
|
+
buffer = ''.dup
|
48
49
|
tmp_fh.puts ">#{id.gsub(/[^A-Za-z0-9_\|\.]/, '_')}#{df}"
|
49
50
|
else
|
50
51
|
buffer << ln.gsub(/[^A-Za-z\.\-]/, '')
|
@@ -166,7 +167,7 @@ class String
|
|
166
167
|
##
|
167
168
|
# Replace {{variables}} using the +vars+ hash
|
168
169
|
def miga_variables(vars)
|
169
|
-
o =
|
170
|
+
o = self.dup
|
170
171
|
vars.each { |k, v| o.gsub!("{{#{k}}}", v.to_s) }
|
171
172
|
o
|
172
173
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
##
|
4
|
+
# General functions for process (system call) execution
|
5
|
+
module MiGA::Common::SystemCall
|
6
|
+
##
|
7
|
+
# Execute the command +cmd+ with options +opts+ determined by #run_cmd_opts
|
8
|
+
#
|
9
|
+
# The command +cmd+ can be:
|
10
|
+
# - String: The command is processed as is, without changes
|
11
|
+
# - Array: The command is built with +shelljoin+ so each value is escaped
|
12
|
+
def run_cmd(cmd, opts = {})
|
13
|
+
opts = run_cmd_opts(opts)
|
14
|
+
cmd = cmd.shelljoin if cmd.is_a?(Array)
|
15
|
+
spawn_opts = {}
|
16
|
+
spawn_opts[:out] = opts[:stdout] if opts[:stdout]
|
17
|
+
spawn_opts[:err] = opts[:stderr] if opts[:stderr]
|
18
|
+
out_io, spawn_opts[:out] = IO.pipe if opts[:return] == :output
|
19
|
+
spawn_opts[:err] = [:child, :out] if opts[:err2out] && spawn_opts[:out]
|
20
|
+
opts[:source] = MiGA::MiGA.rc_path if opts[:source] == :miga
|
21
|
+
if opts[:source] && File.exist?(opts[:source])
|
22
|
+
cmd = ". #{opts[:source].shellescape} && #{cmd}"
|
23
|
+
end
|
24
|
+
|
25
|
+
DEBUG "CMD: #{cmd}"
|
26
|
+
puts "CMD: #{cmd}" if opts[:show_cmd]
|
27
|
+
return if opts[:dry]
|
28
|
+
|
29
|
+
pid = nil
|
30
|
+
error = nil
|
31
|
+
begin
|
32
|
+
pid = spawn(opts[:env], cmd, spawn_opts)
|
33
|
+
Process.wait(pid)
|
34
|
+
rescue => e
|
35
|
+
error = e
|
36
|
+
end
|
37
|
+
status = $?
|
38
|
+
|
39
|
+
if opts[:raise] && !status&.success?
|
40
|
+
raise MiGA::SystemCallError.new(
|
41
|
+
"Command failed with status " \
|
42
|
+
"#{status&.exitstatus}#{' (core dump)' if status&.coredump?}:\n" \
|
43
|
+
"#{error&.class}: #{error&.message}\n" \
|
44
|
+
"OPT: #{opts}\n" \
|
45
|
+
"CMD: #{cmd}"
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
case opts[:return]
|
50
|
+
when :status ; status
|
51
|
+
when :pid ; pid
|
52
|
+
when :error ; error
|
53
|
+
when :output
|
54
|
+
spawn_opts[:out].close
|
55
|
+
output = out_io.read
|
56
|
+
out_io.close
|
57
|
+
output
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Options for #run_cmd using a Hash +opts+ to modify defaults
|
63
|
+
#
|
64
|
+
# Supported keys (as Symbol) include:
|
65
|
+
# - stdout: Redirect STDOUT to this file
|
66
|
+
# - stderr: Redirect STDOUT to this file
|
67
|
+
# - dry: Don't run, just send the command to debug (default: false)
|
68
|
+
# - return: What should the function return, supported values are
|
69
|
+
# +:status+ (Process::Status, default), +:pid+ (Integer, process ID),
|
70
|
+
# +:error+ (Error if failed, nil otherwise), +:output+ (String,
|
71
|
+
# contents sent to STDOUT)
|
72
|
+
# - raise: Raise an exception (MiGA::SystemCallError) in case of failure
|
73
|
+
# (default: true)
|
74
|
+
# - show_cmd: Print command to the STDOUT (prefixed with CMD: ) to ease
|
75
|
+
# debugging (default: false)
|
76
|
+
# - err2out: Redirect STDERR to STDOUT
|
77
|
+
# - env: Environmental variables as a Hash, keys and values must be strings
|
78
|
+
# - source: A file to be sourced before running, or the Symbol +:miga+ to
|
79
|
+
# source the MiGA configuration file
|
80
|
+
def run_cmd_opts(opts = {})
|
81
|
+
{
|
82
|
+
stdout: nil,
|
83
|
+
stderr: nil,
|
84
|
+
dry: false,
|
85
|
+
return: :status,
|
86
|
+
raise: true,
|
87
|
+
show_cmd: false,
|
88
|
+
err2out: false,
|
89
|
+
env: {},
|
90
|
+
source: nil
|
91
|
+
}.merge(opts)
|
92
|
+
end
|
93
|
+
end
|
data/lib/miga/common.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
#
|
2
|
-
# @license Artistic-2.0
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
3
|
+
require 'zlib'
|
4
|
+
require 'stringio'
|
4
5
|
require 'miga/version'
|
5
6
|
require 'miga/json'
|
6
7
|
require 'miga/parallel'
|
7
8
|
require 'miga/common/base'
|
9
|
+
require 'miga/common/errors'
|
8
10
|
require 'miga/common/path'
|
9
11
|
require 'miga/common/format'
|
10
12
|
require 'miga/common/net'
|
11
|
-
require '
|
13
|
+
require 'miga/common/system_call'
|
12
14
|
|
13
15
|
##
|
14
16
|
# Generic class used to handle system-wide information and methods, and parent
|
@@ -19,14 +21,21 @@ class MiGA::MiGA
|
|
19
21
|
extend MiGA::Common::Path
|
20
22
|
extend MiGA::Common::Format
|
21
23
|
extend MiGA::Common::Net
|
24
|
+
extend MiGA::Common::SystemCall
|
22
25
|
|
23
26
|
ENV['MIGA_HOME'] ||= ENV['HOME']
|
24
27
|
|
28
|
+
##
|
29
|
+
# Path to the +.miga_rc+ file
|
30
|
+
def self.rc_path
|
31
|
+
File.join(ENV['MIGA_HOME'], '.miga_rc')
|
32
|
+
end
|
33
|
+
|
25
34
|
##
|
26
35
|
# Has MiGA been initialized?
|
27
36
|
def self.initialized?
|
28
|
-
File.exist?(
|
29
|
-
File.exist?(File.
|
37
|
+
File.exist?(rc_path) &&
|
38
|
+
File.exist?(File.join(ENV['MIGA_HOME'], '.miga_daemon.json'))
|
30
39
|
end
|
31
40
|
|
32
41
|
##
|
data/lib/miga/daemon.rb
CHANGED
@@ -321,7 +321,9 @@ class MiGA::Daemon < MiGA::MiGA
|
|
321
321
|
def purge!
|
322
322
|
say 'Probing running jobs'
|
323
323
|
@jobs_running.select! do |job|
|
324
|
-
|
324
|
+
MiGA::MiGA.run_cmd(
|
325
|
+
runopts(:alive).miga_variables(pid: job[:pid]), return: :output
|
326
|
+
).chomp.to_i == 1
|
325
327
|
end
|
326
328
|
end
|
327
329
|
|
@@ -346,7 +348,7 @@ class MiGA::Daemon < MiGA::MiGA
|
|
346
348
|
Process.detach(job[:pid]) unless [nil, '', 0].include?(job[:pid])
|
347
349
|
else
|
348
350
|
# Schedule cluster job (qsub, msub, slurm)
|
349
|
-
job[:pid] =
|
351
|
+
job[:pid] = MiGA::MiGA.run_cmd(job[:cmd], return: :output).chomp
|
350
352
|
end
|
351
353
|
|
352
354
|
# Check if registered
|
data/lib/miga/result/stats.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'zlib'
|
2
1
|
require 'miga/result/base'
|
3
2
|
|
4
3
|
##
|
@@ -198,12 +197,12 @@ module MiGA::Result::Stats
|
|
198
197
|
file_path(:raw_report)
|
199
198
|
|
200
199
|
MiGA::MiGA.DEBUG "Fixing essential genes by domain"
|
201
|
-
scr =
|
200
|
+
scr = File.join(MiGA::MiGA.root_path, 'utils', 'domain-ess-genes.rb')
|
202
201
|
rep = file_path(:report)
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
202
|
+
$stderr.print MiGA::MiGA.run_cmd(
|
203
|
+
['ruby', scr, rep, "#{rep}.domain", tax[:d][0]],
|
204
|
+
return: :output, err2out: true, source: :miga
|
205
|
+
)
|
207
206
|
add_file(:raw_report, "#{source.name}.ess/log")
|
208
207
|
add_file(:report, "#{source.name}.ess/log.domain")
|
209
208
|
end
|
data/lib/miga/tax_dist.rb
CHANGED
data/lib/miga/version.rb
CHANGED
@@ -12,7 +12,7 @@ module MiGA
|
|
12
12
|
# - String indicating release status:
|
13
13
|
# - rc* release candidate, not released as gem
|
14
14
|
# - [0-9]+ stable release, released as gem
|
15
|
-
VERSION = [1.
|
15
|
+
VERSION = [1.2, 1, 0].freeze
|
16
16
|
|
17
17
|
##
|
18
18
|
# Nickname for the current major.minor version.
|
@@ -20,7 +20,7 @@ module MiGA
|
|
20
20
|
|
21
21
|
##
|
22
22
|
# Date of the current gem relese.
|
23
|
-
VERSION_DATE = Date.new(2021, 12,
|
23
|
+
VERSION_DATE = Date.new(2021, 12, 12)
|
24
24
|
|
25
25
|
##
|
26
26
|
# References of MiGA
|
data/test/format_test.rb
CHANGED
@@ -58,6 +58,9 @@ class FormatTest < Test::Unit::TestCase
|
|
58
58
|
assert_equal(50.0, o[:gc])
|
59
59
|
assert_equal(5, o[:n50])
|
60
60
|
assert_equal(4.0, o[:med])
|
61
|
+
o = MiGA::MiGA.seqs_length(f, :fasta, skew: true)
|
62
|
+
assert_equal(-50.0, o[:at_skew])
|
63
|
+
assert_equal(-25.0, o[:gc_skew])
|
61
64
|
end
|
62
65
|
|
63
66
|
def test_seqs_length_fastq
|
@@ -77,4 +80,22 @@ class FormatTest < Test::Unit::TestCase
|
|
77
80
|
assert_equal('123 45', tab[2])
|
78
81
|
assert_equal('678 90', tab[3])
|
79
82
|
end
|
83
|
+
|
84
|
+
def test_miga_name
|
85
|
+
assert_not('a-bad-name'.miga_name?)
|
86
|
+
assert('a_good_one'.miga_name?)
|
87
|
+
|
88
|
+
assert('After_it_s_fixed_', 'After it\'s fixed!'.miga_name)
|
89
|
+
|
90
|
+
assert('A sp.', 'A_sp_'.unmiga_name)
|
91
|
+
assert('B str. C', 'B_sp_C'.unmiga_name)
|
92
|
+
assert('The X content', 'The_x_content'.unmiga_name)
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_miga_variables
|
96
|
+
assert_equal(
|
97
|
+
'1 a box!',
|
98
|
+
'{{n}} {{my}} {{secret}}!'.miga_variables(my: 'a', secret: :box, n: 1)
|
99
|
+
)
|
100
|
+
end
|
80
101
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SystemCallTest < Test::Unit::TestCase
|
4
|
+
include TestHelper
|
5
|
+
|
6
|
+
def test_run_cmd_opts
|
7
|
+
assert_equal(true, MiGA::MiGA.run_cmd_opts[:raise])
|
8
|
+
assert_equal(:status, MiGA::MiGA.run_cmd_opts[:return])
|
9
|
+
assert_equal(:pid, MiGA::MiGA.run_cmd_opts(return: :pid)[:return])
|
10
|
+
assert_nil(MiGA::MiGA.run_cmd_opts[:stdout])
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_run_cmd_redirection
|
14
|
+
f1 = tmpfile('f1')
|
15
|
+
MiGA::MiGA.run_cmd('echo 1', stdout: f1)
|
16
|
+
assert_equal("1\n", File.read(f1))
|
17
|
+
|
18
|
+
MiGA::MiGA.run_cmd('echo 2 >&2', stderr: f1)
|
19
|
+
assert_equal("2\n", File.read(f1))
|
20
|
+
|
21
|
+
f2 = tmpfile('with spaces')
|
22
|
+
MiGA::MiGA.run_cmd('echo 3', stdout: f2)
|
23
|
+
assert_equal("3\n", File.read(f2))
|
24
|
+
|
25
|
+
MiGA::MiGA.run_cmd(['echo', 4], stdout: f2)
|
26
|
+
assert_equal("4\n", File.read(f2))
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_run_cmd_return
|
30
|
+
o = MiGA::MiGA.run_cmd('echo 1', stdout: '/dev/null')
|
31
|
+
assert(o.is_a? Process::Status)
|
32
|
+
assert(o.success?)
|
33
|
+
|
34
|
+
o = MiGA::MiGA.run_cmd('echo 1', stdout: '/dev/null', return: :pid)
|
35
|
+
assert(o.is_a? Integer)
|
36
|
+
|
37
|
+
o = MiGA::MiGA.run_cmd('echo 1', stdout: '/dev/null', return: :error)
|
38
|
+
assert_nil(o)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_run_cmd_raise
|
42
|
+
assert_raise(MiGA::SystemCallError) { MiGA::MiGA.run_cmd('echoes!!!') }
|
43
|
+
|
44
|
+
o = MiGA::MiGA.run_cmd('echoes!!!', raise: false, return: :status)
|
45
|
+
assert_not(o.success?)
|
46
|
+
|
47
|
+
o = MiGA::MiGA.run_cmd('echoes!!!', raise: false, return: :error)
|
48
|
+
assert(o.is_a? Errno::ENOENT)
|
49
|
+
end
|
50
|
+
end
|
data/utils/distance/base.rb
CHANGED
data/utils/distance/commands.rb
CHANGED
data/utils/distance/pipeline.rb
CHANGED
@@ -58,9 +58,9 @@ module MiGA::DistanceRunner::Pipeline
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
ds_matrix_fh.close
|
61
|
-
ref_tree = File.
|
62
|
-
|
63
|
-
File.unlink
|
61
|
+
ref_tree = File.join(MiGA::MiGA.root_path, 'utils', 'ref-tree.R')
|
62
|
+
MiGA::MiGA.run_cmd([ref_tree, ds_matrix, out_base, dataset.name])
|
63
|
+
File.unlink(ds_matrix)
|
64
64
|
end
|
65
65
|
|
66
66
|
# Tests taxonomy
|
data/utils/find-medoid.R
CHANGED
@@ -26,7 +26,6 @@ find_medoids <- function (ani.df, out, clades) {
|
|
26
26
|
medoids <- c()
|
27
27
|
for(i in cl){
|
28
28
|
lab <- strsplit(i, ",")[[1]]
|
29
|
-
cat("Clade of:", lab[1], "\n")
|
30
29
|
if(length(lab) == 1) {
|
31
30
|
lab.s <- lab
|
32
31
|
} else {
|
@@ -44,7 +43,7 @@ find_medoids <- function (ani.df, out, clades) {
|
|
44
43
|
}
|
45
44
|
|
46
45
|
#= Main
|
47
|
-
cat("Finding Medoids")
|
46
|
+
cat("Finding Medoids\n")
|
48
47
|
ani <- readRDS(argv[1])
|
49
48
|
find_medoids(ani.df = ani, out = argv[2], clades = argv[3])
|
50
49
|
|
data/utils/subclade/base.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
require 'zlib'
|
2
2
|
require 'miga'
|
3
3
|
|
4
|
-
class MiGA::SubcladeRunner
|
4
|
+
class MiGA::SubcladeRunner < MiGA::MiGA
|
5
|
+
require_relative 'temporal.rb'
|
6
|
+
require_relative 'pipeline.rb'
|
7
|
+
|
8
|
+
include MiGA::SubcladeRunner::Temporal
|
9
|
+
include MiGA::SubcladeRunner::Pipeline
|
5
10
|
end
|
data/utils/subclade/pipeline.rb
CHANGED
@@ -29,7 +29,10 @@ module MiGA::SubcladeRunner::Pipeline
|
|
29
29
|
ofh.close
|
30
30
|
# Cluster genomes
|
31
31
|
if File.size? abc_path
|
32
|
-
|
32
|
+
run_cmd([
|
33
|
+
'ogs.mcl.rb',
|
34
|
+
'-o', "#{ogs_file}.tmp", '--abc', abc_path, '-t', opts[:thr]
|
35
|
+
])
|
33
36
|
File.open(ogs_file, 'w') do |fh|
|
34
37
|
File.foreach("#{ogs_file}.tmp").with_index do |ln, lno|
|
35
38
|
fh.puts(ln) if lno > 0
|
@@ -45,8 +48,10 @@ module MiGA::SubcladeRunner::Pipeline
|
|
45
48
|
# Find genomospecies medoids
|
46
49
|
src = File.expand_path('utils/find-medoid.R', MiGA::MiGA.root_path)
|
47
50
|
dir = opts[:gsp_metric] == 'aai' ? '02.aai' : '03.ani'
|
48
|
-
|
49
|
-
|
51
|
+
run_cmd([
|
52
|
+
'Rscript', src, "../../09.distances/#{dir}/miga-project.rds",
|
53
|
+
'miga-project.gsp-medoids', 'miga-project.gsp-clades'
|
54
|
+
])
|
50
55
|
if File.exist? 'miga-project.gsp-clades.sorted'
|
51
56
|
File.rename 'miga-project.gsp-clades.sorted', 'miga-project.gsp-clades'
|
52
57
|
end
|
@@ -62,13 +67,15 @@ module MiGA::SubcladeRunner::Pipeline
|
|
62
67
|
ofh.close
|
63
68
|
end
|
64
69
|
|
65
|
-
def subclades
|
70
|
+
def subclades(metric)
|
66
71
|
src = File.expand_path('utils/subclades.R', MiGA::MiGA.root_path)
|
67
72
|
step = :"#{metric}_distances"
|
68
73
|
metric_res = project.result(step) or raise "Incomplete step #{step}"
|
69
74
|
matrix = metric_res.file_path(:matrix)
|
70
|
-
|
71
|
-
miga-project
|
75
|
+
run_cmd([
|
76
|
+
'Rscript', src, matrix, 'miga-project', opts[:thr],
|
77
|
+
'miga-project.gsp-medoids', opts[:run_clades] ? 'cluster' : 'empty'
|
78
|
+
])
|
72
79
|
if File.exist? 'miga-project.nwk'
|
73
80
|
File.rename('miga-project.nwk', "miga-project.#{metric}.nwk")
|
74
81
|
end
|
@@ -76,6 +83,10 @@ module MiGA::SubcladeRunner::Pipeline
|
|
76
83
|
|
77
84
|
def compile
|
78
85
|
src = File.expand_path('utils/subclades-compile.rb', MiGA::MiGA.root_path)
|
79
|
-
|
86
|
+
run_cmd(['ruby', src, '.', 'miga-project.class'])
|
87
|
+
end
|
88
|
+
|
89
|
+
def run_cmd(cmd)
|
90
|
+
MiGA::MiGA.run_cmd(cmd, show_cmd: true, err2out: true)
|
80
91
|
end
|
81
92
|
end
|
data/utils/subclade/runner.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
|
+
|
1
2
|
require_relative 'base.rb'
|
2
|
-
require_relative 'temporal.rb'
|
3
|
-
require_relative 'pipeline.rb'
|
4
3
|
|
5
4
|
class MiGA::SubcladeRunner
|
6
|
-
|
7
|
-
include MiGA::SubcladeRunner::Pipeline
|
8
|
-
|
9
|
-
attr_reader :project, :step, :opts, :home, :tmp
|
5
|
+
attr_reader(:project, :step, :opts, :home, :tmp)
|
10
6
|
|
11
7
|
def initialize(project_path, step, opts_hash = {})
|
12
8
|
@opts = opts_hash
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: miga-base
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luis M. Rodriguez-R
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-12-
|
11
|
+
date: 2021-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: daemons
|
@@ -176,10 +176,12 @@ files:
|
|
176
176
|
- lib/miga/cli/opt_helper.rb
|
177
177
|
- lib/miga/common.rb
|
178
178
|
- lib/miga/common/base.rb
|
179
|
+
- lib/miga/common/errors.rb
|
179
180
|
- lib/miga/common/format.rb
|
180
181
|
- lib/miga/common/hooks.rb
|
181
182
|
- lib/miga/common/net.rb
|
182
183
|
- lib/miga/common/path.rb
|
184
|
+
- lib/miga/common/system_call.rb
|
183
185
|
- lib/miga/common/with_daemon.rb
|
184
186
|
- lib/miga/common/with_daemon_class.rb
|
185
187
|
- lib/miga/common/with_option.rb
|
@@ -253,6 +255,7 @@ files:
|
|
253
255
|
- test/remote_dataset_test.rb
|
254
256
|
- test/result_stats_test.rb
|
255
257
|
- test/result_test.rb
|
258
|
+
- test/system_call_test.rb
|
256
259
|
- test/tax_dist_test.rb
|
257
260
|
- test/tax_index_test.rb
|
258
261
|
- test/taxonomy_test.rb
|