command_utils 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/command_utils.rb +68 -34
- metadata +16 -17
- data/lib/command_utils/non_zero_status.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43313ab411781575b5f54cd723d95189d6ef8cfd
|
4
|
+
data.tar.gz: 9f7aeb3db8f866314c1d0c59efcf9a7a29e6d681
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f1175dd3ab6259546955779aefca5375a5e7da16c65d00f1af6265ac8874e5a1ee2b9d8ab2d0993dc0550779856ff702e663f578b810ab2a55ffb388dd2f040
|
7
|
+
data.tar.gz: 31be009f839f09db332d9012a71a3e9ef6cd82cf701a1474938bb4c5e75794b4691f2cc424f1cf05ecc6214e8465eea4c58d19448ce609aef7fe558bcac9e92b
|
data/lib/command_utils.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require_relative 'command_utils/non_zero_status'
|
2
1
|
require_relative 'command_utils/line_buffer'
|
3
2
|
|
4
3
|
# Class to assist calling external commands, while processing its output and return code.
|
5
|
-
# All methods which execute given command, raise NonZeroStatus if its return is not 0.
|
6
4
|
class CommandUtils
|
7
5
|
|
6
|
+
# PID of currently running process.
|
7
|
+
attr_reader :pid
|
8
|
+
|
8
9
|
# call-seq:
|
9
10
|
# new([env,] command...)
|
10
11
|
#
|
@@ -24,29 +25,30 @@ class CommandUtils
|
|
24
25
|
yield self if block_given?
|
25
26
|
end
|
26
27
|
|
27
|
-
# Execute command, yielding to given block, each time there is output available
|
28
|
+
# Execute command, yielding to given block, each time there is output available (not line buffered):
|
28
29
|
# stream:: either +:stdout+ or +:stderr+.
|
29
30
|
# data:: data read from respective stream.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
label = case io
|
41
|
-
when @stdout_read
|
42
|
-
:stdout
|
43
|
-
when @stderr_read
|
44
|
-
:stderr
|
45
|
-
end
|
46
|
-
yield label, io.read
|
31
|
+
# Raises CommandUtils::StatusError class exception if command execution is not successfull.
|
32
|
+
def each_output &block # :yields: stream, data
|
33
|
+
spawn
|
34
|
+
loop do
|
35
|
+
io_list = [@stdout_read, @stderr_read].keep_if{|io| not io.closed?}
|
36
|
+
break if io_list.empty?
|
37
|
+
IO.select(io_list).first.each do |io|
|
38
|
+
if io.eof?
|
39
|
+
io.close
|
40
|
+
next
|
47
41
|
end
|
42
|
+
label = case io
|
43
|
+
when @stdout_read
|
44
|
+
:stdout
|
45
|
+
when @stderr_read
|
46
|
+
:stderr
|
47
|
+
end
|
48
|
+
yield label, io.read
|
48
49
|
end
|
49
50
|
end
|
51
|
+
process_status
|
50
52
|
end
|
51
53
|
|
52
54
|
# call-seq:
|
@@ -57,9 +59,10 @@ class CommandUtils
|
|
57
59
|
self.new(*args).each_output(&block)
|
58
60
|
end
|
59
61
|
|
60
|
-
# Execute command, yielding to given block, each time there is a new line available
|
62
|
+
# Execute command, yielding to given block, each time there is a new line available (does line buffering):
|
61
63
|
# stream:: either +:stdout+ or +:stderr+.
|
62
64
|
# data:: data read from respective stream.
|
65
|
+
# Raises CommandUtils::StatusError class exception if command execution is not successfull.
|
63
66
|
def each_line &block # :yields: stream, data
|
64
67
|
stdout_lb = LineBuffer.new(
|
65
68
|
proc do |data|
|
@@ -99,6 +102,7 @@ class CommandUtils
|
|
99
102
|
# and optionally:
|
100
103
|
# +:stdout_prefix+:: Prefix to use for all stdout messages.
|
101
104
|
# +:stderr_prefix+:: Prefix to use for all stderr messages.
|
105
|
+
# Raises CommandUtils::StatusError class exception if command execution is not successfull.
|
102
106
|
def logger_exec options
|
103
107
|
each_line do |stream, data|
|
104
108
|
level = options["#{stream}_level".to_sym]
|
@@ -117,12 +121,9 @@ class CommandUtils
|
|
117
121
|
|
118
122
|
private
|
119
123
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
process_status
|
124
|
-
end
|
125
|
-
|
124
|
+
# Process.spawn a new process with @env and @command.
|
125
|
+
#
|
126
|
+
# Sets @pid, @stdout_write and @stderr_write.
|
126
127
|
def spawn
|
127
128
|
@stdout_read, @stdout_write = IO.pipe
|
128
129
|
@stderr_read, @stderr_write = IO.pipe
|
@@ -142,14 +143,47 @@ class CommandUtils
|
|
142
143
|
@stderr_write.close
|
143
144
|
end
|
144
145
|
|
146
|
+
# Parent class for all status errors.
|
147
|
+
class StatusError < StandardError
|
148
|
+
# Process::Status
|
149
|
+
attr_accessor :status
|
150
|
+
# Command as passed to Process#spawn
|
151
|
+
attr_accessor :command
|
152
|
+
def initialize message, status, command
|
153
|
+
super message
|
154
|
+
@status, @command = status, command
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Raised when process exited with non zero status.
|
159
|
+
class NonZeroExit < StatusError ; end
|
160
|
+
# Raised when process was signaled.
|
161
|
+
class Signaled < StatusError ; end
|
162
|
+
# Raised when process was stopped.
|
163
|
+
class Stopped < StatusError ; end
|
164
|
+
# Raised when process exited with unknown status.
|
165
|
+
class Unknown < StatusError ; end
|
166
|
+
|
167
|
+
# Wait for process termination, then process its status.
|
145
168
|
def process_status
|
146
|
-
Process
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
status
|
151
|
-
@command
|
152
|
-
|
169
|
+
flags = Process::WNOHANG|Process::WUNTRACED
|
170
|
+
pid, status = Process.wait2(@pid, flags)
|
171
|
+
if status.exited?
|
172
|
+
unless status.exitstatus == 0
|
173
|
+
message = "Command exited with #{status.exitstatus}."
|
174
|
+
raise NonZeroExit.new(message, status, @command)
|
175
|
+
end
|
176
|
+
elsif status.signaled?
|
177
|
+
message = "Command was signaled with #{status.termsig}."
|
178
|
+
message += " Core dump generated." if status.coredump?
|
179
|
+
raise Signaled.new(message, status, @command)
|
180
|
+
elsif status.stopped?
|
181
|
+
message = "Command was stopped with signal #{status.stopsig}, PID=#{pid}."
|
182
|
+
raise Stopped.new(message, status, @command)
|
183
|
+
else
|
184
|
+
message = "Unknown return status."
|
185
|
+
raise Unknown.new(message, status, @command)
|
153
186
|
end
|
154
187
|
end
|
188
|
+
|
155
189
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: command_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fabio Pugliese Ornellas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -16,48 +16,48 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '3.
|
19
|
+
version: '3.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '3.
|
26
|
+
version: '3.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: guard-
|
28
|
+
name: guard-rdoc
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.0'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.0.3
|
34
37
|
type: :development
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
41
|
- - "~>"
|
39
42
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
43
|
+
version: '1.0'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.0.3
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: guard-
|
48
|
+
name: guard-rspec
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
51
|
- - "~>"
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
48
|
-
- - ">="
|
49
|
-
- !ruby/object:Gem::Version
|
50
|
-
version: 1.0.3
|
53
|
+
version: '4.6'
|
51
54
|
type: :development
|
52
55
|
prerelease: false
|
53
56
|
version_requirements: !ruby/object:Gem::Requirement
|
54
57
|
requirements:
|
55
58
|
- - "~>"
|
56
59
|
- !ruby/object:Gem::Version
|
57
|
-
version: '
|
58
|
-
- - ">="
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: 1.0.3
|
60
|
+
version: '4.6'
|
61
61
|
description: This Gem will help you call external commands, process its stdout and
|
62
62
|
stderr, to your own fit, and at the end, validate its return code.
|
63
63
|
email: fabio.ornellas@gmail.com
|
@@ -67,7 +67,6 @@ extra_rdoc_files: []
|
|
67
67
|
files:
|
68
68
|
- lib/command_utils.rb
|
69
69
|
- lib/command_utils/line_buffer.rb
|
70
|
-
- lib/command_utils/non_zero_status.rb
|
71
70
|
homepage: https://github.com/fornellas/command_utils
|
72
71
|
licenses:
|
73
72
|
- GPL
|
@@ -1,18 +0,0 @@
|
|
1
|
-
class CommandUtils
|
2
|
-
|
3
|
-
# Raised when executed command does not return 0
|
4
|
-
class NonZeroStatus < RuntimeError
|
5
|
-
|
6
|
-
# Command exit status
|
7
|
-
attr_accessor :status
|
8
|
-
# Command as passed to Process#spawn
|
9
|
-
attr_accessor :command
|
10
|
-
|
11
|
-
def initialize message, status, command
|
12
|
-
super message
|
13
|
-
@status, @command = status, command
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|