libis-tools 0.9.60 → 0.9.62
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/libis/tools/command.rb +82 -11
- data/lib/libis/tools/mets_file.rb +1 -5
- data/lib/libis/tools/mets_objects.rb +4 -3
- data/lib/libis/tools/version.rb +1 -1
- data/spec/command_spec.rb +23 -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: a2464bf3e02e56791cd56ff6c266ab875fec58b5
|
4
|
+
data.tar.gz: cbef32af7fde215e0b7cf2b3e8f1ca4d0c5609b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94c9e9154bfdb7b56ef646dded3b31031f8011c01a1cfd9e6f15e23349a680bcecb984734da1a383663993e0ae69c36b066f9b71364d4b39842645cd33e65e47
|
7
|
+
data.tar.gz: d67f4c5487a564cf9d24a55fd500017706d669caa3b7d7667ddf2767e3f4430d99051993073531cbad57a053f52be0860097cd94b2ed66947f90d58d18f8c1ea
|
data/lib/libis/tools/command.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require '
|
2
|
+
require 'timeout'
|
3
3
|
|
4
4
|
module Libis
|
5
5
|
module Tools
|
@@ -10,6 +10,17 @@ module Libis
|
|
10
10
|
# * :out => an array with lines that were printed on the external program's standard out.
|
11
11
|
# * :err => an array with lines that were printed on the external program's standard error.
|
12
12
|
# * :status => exit code returned by the external program.
|
13
|
+
# * :timeout => true if the command was terminated due to a timeout.
|
14
|
+
# * :pid => pid of the command (in case <pid>.log files need to be cleaned up)
|
15
|
+
#
|
16
|
+
# Optionally an option hash can be appended to the list of arguments with:
|
17
|
+
# * :stdin_data => values sent to the command's standard input (optional, nothing sent if not present)
|
18
|
+
# * :binmode => if present and true, will set the IO communication to binary data
|
19
|
+
# * :timeout => if specified, SIGTERM signal is sent to the command after the number of seconds
|
20
|
+
# * :signal => Signal sent to the command instead of the default SIGTERM
|
21
|
+
# * :kill_after => if specified, SIGKILL signal is sent aftern the number of seconds if command is still running
|
22
|
+
# after initial signal was sent
|
23
|
+
# * any other options will be handed over to the spawn command (e.g. pgroup)
|
13
24
|
#
|
14
25
|
# Examples:
|
15
26
|
#
|
@@ -30,32 +41,92 @@ module Libis
|
|
30
41
|
# Run an external program and return status, stdout and stderr.
|
31
42
|
#
|
32
43
|
#
|
33
|
-
# @param [String] cmd
|
34
|
-
# @param [Array<String>] opts optional list of command line arguments
|
44
|
+
# @param [Array<String>] cmd command name optionally prepended with env and appended with command-line arguments
|
35
45
|
# @return [Hash] a Hash with:
|
36
46
|
# * :status (Integer) - the exit status of the command
|
37
47
|
# * :out (Array<String>) - the stdout output of the command
|
38
48
|
# * :err (Array<String>)- the stderr output of the command
|
39
|
-
|
49
|
+
# * :timeout(Boolean) - if true, the command did not return in time
|
50
|
+
# * :pid(Integer) - the command's processID
|
51
|
+
def self.run(*cmd)
|
52
|
+
|
53
|
+
spawn_opts = Hash === cmd.last ? cmd.pop.dup : {}
|
54
|
+
opts = {
|
55
|
+
:stdin_data => spawn_opts.delete(:stdin_data) || '',
|
56
|
+
:binmode => spawn_opts.delete(:binmode) || false,
|
57
|
+
:timeout => spawn_opts.delete(:timeout),
|
58
|
+
:signal => spawn_opts.delete(:signal) || :TERM,
|
59
|
+
:kill_after => spawn_opts.delete(:kill_after),
|
60
|
+
}
|
61
|
+
in_r, in_w = IO.pipe
|
62
|
+
out_r, out_w = IO.pipe
|
63
|
+
err_r, err_w = IO.pipe
|
64
|
+
in_w.sync = true
|
65
|
+
|
66
|
+
if opts[:binmode]
|
67
|
+
in_w.binmode
|
68
|
+
out_r.binmode
|
69
|
+
err_r.binmode
|
70
|
+
end
|
71
|
+
|
72
|
+
spawn_opts[:in] = in_r
|
73
|
+
spawn_opts[:out] = out_w
|
74
|
+
spawn_opts[:err] = err_w
|
75
|
+
|
40
76
|
result = {
|
41
|
-
|
42
|
-
|
43
|
-
|
77
|
+
:pid => nil,
|
78
|
+
:status => nil,
|
79
|
+
:out => [],
|
80
|
+
:err => [],
|
81
|
+
:timeout => false,
|
44
82
|
}
|
83
|
+
|
84
|
+
out_reader = nil
|
85
|
+
err_reader = nil
|
86
|
+
wait_thr = nil
|
87
|
+
|
45
88
|
begin
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
89
|
+
Timeout.timeout(opts[:timeout]) do
|
90
|
+
result[:pid] = spawn(*cmd, spawn_opts)
|
91
|
+
wait_thr = Process.detach(result[:pid])
|
92
|
+
in_r.close
|
93
|
+
out_w.close
|
94
|
+
err_w.close
|
95
|
+
|
96
|
+
out_reader = Thread.new {out_r.read}
|
97
|
+
err_reader = Thread.new {err_r.read}
|
98
|
+
|
99
|
+
in_w.write opts[:stdin_data]
|
100
|
+
in_w.close
|
101
|
+
|
102
|
+
result[:status] = wait_thr.value
|
103
|
+
end
|
104
|
+
|
105
|
+
rescue Timeout::Error
|
106
|
+
result[:timeout] = true
|
107
|
+
pid = spawn_opts[:pgroup] ? -result[:pid] : result[:pid]
|
108
|
+
Process.kill(opts[:signal], pid)
|
109
|
+
if opts[:kill_after]
|
110
|
+
unless wait_thr.join(opts[:kill_after])
|
111
|
+
Process.kill(:KILL, pid)
|
112
|
+
end
|
113
|
+
end
|
50
114
|
|
51
115
|
rescue StandardError => e
|
52
116
|
result[:err] = [e.class.name, e.message]
|
53
117
|
|
118
|
+
ensure
|
119
|
+
result[:status] = wait_thr.value.exitstatus if wait_thr
|
120
|
+
result[:out] += out_reader.value.split("\n").map(&:chomp) if out_reader
|
121
|
+
result[:err] += err_reader.value.split("\n").map(&:chomp) if err_reader
|
122
|
+
out_r.close unless out_r.closed?
|
123
|
+
err_r.close unless err_r.closed?
|
54
124
|
end
|
55
125
|
|
56
126
|
result
|
57
127
|
|
58
128
|
end
|
129
|
+
|
59
130
|
end
|
60
131
|
|
61
132
|
end
|
@@ -240,11 +240,7 @@ module Libis
|
|
240
240
|
|
241
241
|
def get_id(klass)
|
242
242
|
self.mutex.synchronize do
|
243
|
-
|
244
|
-
@id_map[klass] += 1
|
245
|
-
else
|
246
|
-
@id_map[klass] = 1
|
247
|
-
end
|
243
|
+
@id_map[klass] = (@id_map[klass] ? @id_map[klass] + 1 : 1)
|
248
244
|
return @id_map[klass]
|
249
245
|
end
|
250
246
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'libis/tools/thread_safe'
|
2
|
+
require 'uri'
|
2
3
|
|
3
4
|
module Libis
|
4
5
|
module Tools
|
@@ -280,9 +281,9 @@ module Libis
|
|
280
281
|
compositionLevel: composition_level,
|
281
282
|
# fileLocationType: 'FILE',
|
282
283
|
# fileLocation: '',
|
283
|
-
fileOriginalName: orig_name,
|
284
|
-
fileOriginalPath: orig_path,
|
285
|
-
fileOriginalID: location,
|
284
|
+
fileOriginalName: URI.encode(orig_name),
|
285
|
+
fileOriginalPath: URI.encode(orig_path),
|
286
|
+
fileOriginalID: URI.encode(location),
|
286
287
|
fileExtension: ::File.extname(orig_name),
|
287
288
|
fileMIMEType: mimetype,
|
288
289
|
fileSizeBytes: size,
|
data/lib/libis/tools/version.rb
CHANGED
data/spec/command_spec.rb
CHANGED
@@ -61,4 +61,27 @@ describe 'Command' do
|
|
61
61
|
|
62
62
|
end
|
63
63
|
|
64
|
+
it 'should allow to supply input data' do
|
65
|
+
|
66
|
+
result = Libis::Tools::Command.run('cat', stdin_data: "FooBar", timeout: 1)
|
67
|
+
expect(result[:out]).to eq ['FooBar']
|
68
|
+
expect(result[:err].size).to eq 0
|
69
|
+
expect(result[:status]).to eq 0
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should not timeout if command finishes' do
|
74
|
+
|
75
|
+
result = Libis::Tools::Command.run('cat', stdin_data: "FooBar", timeout: 1)
|
76
|
+
expect(result[:timeout]).to be_falsey
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should timeout if command hangs' do
|
81
|
+
|
82
|
+
result = Libis::Tools::Command.run('ls', '-aRlp', '/', timeout: 1)
|
83
|
+
expect(result[:timeout]).to be_truthy
|
84
|
+
|
85
|
+
end
|
86
|
+
|
64
87
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libis-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.62
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kris Dekeyser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|