progeny 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +9 -11
- data/lib/progeny/command.rb +48 -7
- data/lib/progeny/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b4b80a4ad000727e13f154cef131b4299d27eed0ed4f200586defa86c60d829
|
4
|
+
data.tar.gz: 31a7c9a885fc3ada1ff8a66ae85a7400b56a0bcb17c1dca0ee9649eac56d7919
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15a7df8729f641d566a5b69d388592cbe536177c165c4260954a8a23d57c735d3cb4af242ca958f85de79198b33ffecaaba4551d514e2674720f409f433e930b
|
7
|
+
data.tar.gz: 27049a985faef5bd21a349feaece2480b70eba62b3ed253caf941e48e4af841f79797538e5ffaef78518da90ba13cd96a0db439e9d59b1363ba3cce254e7f991
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -12,10 +12,11 @@ strings and is therefore not well-suited to streaming large quantities of data
|
|
12
12
|
in and out of commands. That said, it has some benefits:
|
13
13
|
|
14
14
|
- **Simple** - requires little code for simple stream input and capture.
|
15
|
-
- **Internally non-blocking** (using `select(2)`) - handles all pipe hang
|
16
|
-
due to exceeding `PIPE_BUF` limits on one or more streams.
|
17
|
-
- **Uses Ruby under the hood** - It leverages Ruby's `
|
18
|
-
|
15
|
+
- **Internally non-blocking** (using `select(2)`) - handles all pipe hang
|
16
|
+
cases due to exceeding `PIPE_BUF` limits on one or more streams.
|
17
|
+
- **Uses Ruby under the hood** - It leverages Ruby's `Process.spawn` behind
|
18
|
+
the scenes so it's widely supported and consistently getting performance
|
19
|
+
updates.
|
19
20
|
|
20
21
|
`Progeny::Command` takes the [standard `Process::spawn`
|
21
22
|
arguments](https://ruby-doc.org/current/Process.html#method-c-spawn) when
|
@@ -132,10 +133,9 @@ end
|
|
132
133
|
```
|
133
134
|
|
134
135
|
You will need to remove the include statements and replace any use of `#spawn`
|
135
|
-
with Ruby's native `Process.spawn` and `#popen4` with
|
136
|
+
with Ruby's native `Process.spawn` and `#popen4` with `Progeny::Command.spawn_with_pipes`
|
136
137
|
```diff
|
137
138
|
- require 'posix/spawn'
|
138
|
-
+ require 'open3'
|
139
139
|
|
140
140
|
class YourSpawnerClass
|
141
141
|
- include POSIX::Spawn
|
@@ -148,16 +148,14 @@ class YourSpawnerClass
|
|
148
148
|
|
149
149
|
def calculate(expression)
|
150
150
|
- pid, in, out, err = popen4('bc')
|
151
|
-
+ in, out, err
|
152
|
-
+ pid = wait_thr[:pid] # if pid is needed
|
151
|
+
+ pid, in, out, err = Progeny::Command.spawn_with_pipes('bc')
|
153
152
|
in.write(expression)
|
154
153
|
in.close
|
155
154
|
out.read
|
156
155
|
ensure
|
157
156
|
[in, out, err].each { |io| io.close if !io.closed? }
|
158
|
-
|
159
|
-
|
160
|
-
+ wait_thr.value
|
157
|
+
Process::waitpid(pid)
|
158
|
+
$?
|
161
159
|
end
|
162
160
|
end
|
163
161
|
```
|
data/lib/progeny/command.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require "open3"
|
2
|
-
|
3
1
|
module Progeny
|
4
2
|
# Progeny::Command includes logic for executing child processes and
|
5
3
|
# reading/writing from their standard input, output, and error streams. It's
|
@@ -123,6 +121,41 @@ module Progeny
|
|
123
121
|
new(*(args + [{ :noexec => true }.merge(options)]))
|
124
122
|
end
|
125
123
|
|
124
|
+
# Spawn a child process with all standard IO streams piped in and out of
|
125
|
+
# the spawning process. Supports the standard `Process.spawn` interface.
|
126
|
+
#
|
127
|
+
# Returns a [pid, stdin, stdout, stderr] tuple, where pid is the new
|
128
|
+
# process's pid, stdin is a writeable IO object, and stdout / stderr are
|
129
|
+
# readable IO objects. The caller should take care to close all IO objects
|
130
|
+
# when finished and the child process's status must be collected by a call
|
131
|
+
# to Process::waitpid or equivalent.
|
132
|
+
def self.spawn_with_pipes(*argv)
|
133
|
+
if argv.last.is_a?(Hash)
|
134
|
+
opts = argv.pop.dup
|
135
|
+
else
|
136
|
+
opts = {}
|
137
|
+
end
|
138
|
+
|
139
|
+
ird, iwr = IO.pipe
|
140
|
+
ord, owr = IO.pipe
|
141
|
+
erd, ewr = IO.pipe
|
142
|
+
|
143
|
+
opts = opts.merge(
|
144
|
+
# redirect fds # close other sides
|
145
|
+
:in => ird, iwr => :close,
|
146
|
+
:out => owr, ord => :close,
|
147
|
+
:err => ewr, erd => :close
|
148
|
+
)
|
149
|
+
pid = spawn(*(argv + [opts]))
|
150
|
+
[pid, iwr, ord, erd]
|
151
|
+
ensure
|
152
|
+
# we're in the parent, close child-side fds
|
153
|
+
[ird, owr, ewr].each { |fd| fd.close if fd }
|
154
|
+
end
|
155
|
+
|
156
|
+
# All data written to the child process's stdin stream as a String.
|
157
|
+
attr_reader :input
|
158
|
+
|
126
159
|
# All data written to the child process's stdout stream as a String.
|
127
160
|
attr_reader :out
|
128
161
|
|
@@ -149,14 +182,14 @@ module Progeny
|
|
149
182
|
# immediately when a new instance of this object is created, or
|
150
183
|
# can be called explicitly when creating the Command via `build`.
|
151
184
|
def exec!
|
152
|
-
stdin, stdout, stderr
|
153
|
-
@pid =
|
185
|
+
pid, stdin, stdout, stderr = self.class.spawn_with_pipes(@env, *@argv, @options)
|
186
|
+
@pid = pid
|
154
187
|
|
155
188
|
# async read from all streams into buffers
|
156
189
|
read_and_write(@input, stdin, stdout, stderr, @timeout, @max)
|
157
190
|
|
158
|
-
#
|
159
|
-
@status =
|
191
|
+
# wait for the termination of the process and return exit status
|
192
|
+
@status = waitpid(pid)
|
160
193
|
rescue Object
|
161
194
|
[stdin, stdout, stderr].each { |fd| fd.close rescue nil }
|
162
195
|
if @status.nil?
|
@@ -165,7 +198,7 @@ module Progeny
|
|
165
198
|
else
|
166
199
|
::Process.kill('-TERM', pid) rescue nil
|
167
200
|
end
|
168
|
-
@status =
|
201
|
+
@status = waitpid(pid) rescue nil
|
169
202
|
end
|
170
203
|
raise
|
171
204
|
ensure
|
@@ -268,5 +301,13 @@ module Progeny
|
|
268
301
|
|
269
302
|
[@out, @err]
|
270
303
|
end
|
304
|
+
|
305
|
+
# Wait for the child process to exit
|
306
|
+
#
|
307
|
+
# Returns the Process::Status object obtained by reaping the process.
|
308
|
+
def waitpid(pid)
|
309
|
+
Process::waitpid(pid)
|
310
|
+
$?
|
311
|
+
end
|
271
312
|
end
|
272
313
|
end
|
data/lib/progeny/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: progeny
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luan Vieira
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-05-
|
11
|
+
date: 2023-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -77,5 +77,5 @@ requirements: []
|
|
77
77
|
rubygems_version: 3.4.10
|
78
78
|
signing_key:
|
79
79
|
specification_version: 4
|
80
|
-
summary: A
|
80
|
+
summary: A process spawn wrapper with a nice interface and extra options.
|
81
81
|
test_files: []
|