-
Notifications
You must be signed in to change notification settings - Fork 3
/
ep3-runner
executable file
·212 lines (193 loc) · 5.62 KB
/
ep3-runner
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#!/usr/bin/env ruby
# coding: utf-8
require 'optparse'
require 'fileutils'
require 'tmpdir'
require 'json'
require 'time'
# log levels
Quiet = 0
Normal = 1
Verbose = 2
VeryVerbose = 3
# keep tmpdir levels
RemoveAlways = 0
LeaveOnErrors = 1
LeaveAlways = 2
def run_cmd(cmd, loglevel)
pid = nil
begin
pid = spawn(cmd)
_, status = Process.wait2 pid
pid = nil
succ = status.exited? && status.exitstatus == 0
lv = if succ then 'info' else 'error' end
hash = {
'log-level' => lv,
'success' => succ,
'commmand' => cmd, 'return' => status.exitstatus,
'tag' => 'ep3.system', 'timestamp' => Time.now.iso8601(7),
}
if lv == 'error' || loglevel >= Verbose
warn JSON.dump hash
end
hash
rescue SignalException
unless pid.nil?
Process.wait pid
pid = nil
end
hash = {
'log-level' => 'error',
'success' => false,
'commmand' => cmd, 'interrupted' => true,
'tag' => 'ep3.system', 'timestamp' => Time.now.iso8601(7),
}
warn JSON.dump hash
hash
rescue => e
unless pid.nil?
Process.wait pid
pid = nil
end
hash = {
'log-level' => 'critical',
'success' => false,
'commmand' => cmd, 'interrupted' => false,
'message' => e.to_s,
'tag' => 'ep3.system', 'timestamp' => Time.now.iso8601(7),
}
warn JSON.dump hash
hash
end
end
if $0 == __FILE__
extensions = []
compute_checksum = true
loglevel = Normal
keep_tmpdir_level = nil
parser = OptionParser.new
parser.banner = "Usage: #{$0} cwl [jobfile]"
parser.on('--tmpdir=TMP', 'directory for temporary files')
parser.on('--outdir=OUT', 'directory for output objects')
parser.on('--leave-tmpdir', 'always leave temporary directory') {
unless keep_tmpdir_level.nil?
raise "Cannot specify --leave-tmpdir, --remove-tmpdir and --leave-tmpdir-on-errors simultaneously"
end
keep_tmpdir_level = LeaveAlways
}
parser.on('--leave-tmpdir-on-errors', 'leave temporary directory on errors (default)') {
unless keep_tmpdir_level.nil?
raise "Cannot specify --leave-tmpdir, --remove-tmpdir and --leave-tmpdir-on-errors simultaneously"
end
keep_tmpdir_level = LeaveOnErrors
}
parser.on('--remove-tmpfir', 'always remove temporary directory') {
unless keep_tmpdir_level.nil?
raise "Cannot specify --leave-tmpdir, --remove-tmpdir and --leave-tmpdir-on-errors simultaneously"
end
keep_tmpdir_level = RemoveAlways
}
parser.on('--quiet', 'only print warnings and errors') {
loglevel = Quiet
}
parser.on('--verbose', 'verbose output') {
loglevel = Verbose
}
parser.on('--veryverbose', 'more verbose output') {
loglevel = VeryVerbose
}
parser.on('--[no-]compute-checksum', 'compute (or do not compute) checksum of contents (default: --compute-checksum)') { |cs|
compute_checksum = cs
}
parser.on('--extension=EXT', 'specify extension') { |ext|
extensions.push ext
}
parser.on('--version', 'show version information') {
system('git describe', :chdir => File.dirname($0))
exit
}
basedir = File.dirname(File.realpath($0))
opts = parser.getopts(ARGV)
unless ARGV.length == 1 or ARGV.length == 2
puts parser.help
exit
end
keep_tmpdir_level = keep_tmpdir_level or LeaveOnErrors
cwl = ARGV.shift
job = if ARGV.empty?
nil
else
ARGV.shift
end
# Note: Dir.mktmpdir includes side effect
if opts.include?('tmpdir') && Dir.exist?(opts['tmpdir'])
hash = {
'log-level' => 'error',
'success' => false,
'message' => "Directory already exists: #{opts['tmpdir']}",
'tag' => 'ep3.system', 'timestamp' => Time.now.iso8601(7),
}
warn JSON.dump hash
exit 1
end
tmpdir = opts.fetch('tmpdir', Dir.mktmpdir)
target_arg = "--target-dir=#{tmpdir}"
outdir = opts.fetch('outdir', '.')
dst_arg = "--destination=#{outdir}"
ret_init = run_cmd("#{basedir}/ep3 init --force #{target_arg} #{cwl} > /dev/null", loglevel)
unless ret_init['success']
if Dir.exist?(tmpdir) && keep_tmpdir_level != LeaveAlways
FileUtils.remove_entry tmpdir
end
exit ret_init.fetch('return', 1)
end
tmpdir_will_be_removed = keep_tmpdir_level == RemoveAlways
begin
unless extensions.empty?
ret_hook = run_cmd("#{basedir}/ep3 hook --extensions=#{extensions.join(',')} #{target_arg}", loglevel)
if ret_hook.include? 'interrupted'
exit 1
elsif not ret_hook['success']
exit ret_hook.fetch('return', 1)
end
end
lopt = case loglevel
when Quiet then '--quiet'
when Normal then ''
when Verbose then '--verbose'
when VeryVerbose then '--veryverbose'
end
ret_run = run_cmd("#{basedir}/ep3 run #{lopt} #{target_arg} #{job}", loglevel)
if ret_run.include? 'interrupted'
exit 1
elsif not ret_run['success']
exit ret_run.fetch('return', 1)
end
copt = if compute_checksum
'--compute-checksum'
else
'--no-compute-checksum'
end
ret_list = run_cmd("#{basedir}/ep3 list #{target_arg} #{copt} --copy #{dst_arg}", loglevel)
if ret_list['success']
tmpdir_will_be_removed = true unless keep_tmpdir_level == LeaveAlways
exit 0
else
exit ret_list.fetch('return', 1)
end
rescue => e
hash = {
'log-level' => 'critical',
'success' => false,
'message' => "Uncaught exception: #{e}",
'tag' => 'ep3.system', 'timestamp' => Time.now.iso8601(7),
}
warn JSON.dump(hash)
exit 1
ensure
if tmpdir_will_be_removed
FileUtils.remove_entry tmpdir
end
end
end