test-cmd.rb 2.1.0 → 2.4.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/LICENSE +21 -15
- data/README.md +55 -37
- data/lib/test/command/version.rb +8 -0
- data/lib/test/{cmd.rb → command.rb} +42 -12
- data/lib/test-cmd.rb +1 -1
- data/rubydev.svg +108 -36
- data/test/cmd_test.rb +26 -0
- data/test/setup.rb +1 -1
- data/test-cmd.rb.gemspec +14 -4
- metadata +17 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b091ee25f1e890969728e516747d3104c20076d2a71973e02ccc346a9eb1cc8e
|
|
4
|
+
data.tar.gz: 4dbb449b245f30e89285b7cae84de42564e352a4f0790fcc3a8a048e21b3ede2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 43fb7bb3700e9f384c253c8ab36ec3a1ebb2ec5e807b3af1d57883a64bddb132838086fc15b242ce3a65b85092941d23a040b866b3e173bed4bf5254e2829690
|
|
7
|
+
data.tar.gz: c314163ab04470596296e8644414bec98414955b7423a1cc5affe202184befedffaff5f1f63427b18dd192b356fe491d3ec85e1b1c5140857c185b3a7ea37402
|
data/LICENSE
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
granted
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
OF
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Robert Gleeson <robert@r.uby.dev>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
|
@@ -10,16 +10,19 @@
|
|
|
10
10
|
</a>
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
|
-
>
|
|
13
|
+
> [r.uby.dev](https://r.uby.dev) project.
|
|
14
14
|
|
|
15
15
|
Welcome to the canonical test-cmd.rb repository.
|
|
16
16
|
|
|
17
17
|
test-cmd.rb is a Go-inspired, object-oriented interface for running
|
|
18
18
|
commands on UNIX-like systems, in the spirit of Go's `os/exec`. A
|
|
19
|
-
command
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
command can be built by chaining multiple method calls that impact
|
|
20
|
+
different command attributes. The environment the command executes
|
|
21
|
+
with can be set, its standard input stream can be written to, and
|
|
22
|
+
the standard output and standard error streams are captured so the
|
|
23
|
+
parent process can read them.
|
|
24
|
+
|
|
25
|
+
It has zero runtime dependencies (stdlib-only).
|
|
23
26
|
|
|
24
27
|
## Install
|
|
25
28
|
|
|
@@ -31,34 +34,42 @@ test-cmd.rb can be installed via rubygems.org:
|
|
|
31
34
|
|
|
32
35
|
### Commands
|
|
33
36
|
|
|
34
|
-
A command is created with
|
|
35
|
-
[`Test::Command#initialize`](https://r.uby.dev/api-docs/test-cmd.rb/Test/Command.html#initialize-instance_method)
|
|
36
|
-
which takes the name or path of a command, and given additional
|
|
37
|
-
arguments with
|
|
38
|
-
[`Test::Command#argv`](https://r.uby.dev/api-docs/test-cmd.rb/Test/Command.html#argv-instance_method).
|
|
39
|
-
Environment variables can be set for the spawned process with
|
|
40
|
-
[`Test::Command#env`](https://r.uby.dev/api-docs/test-cmd.rb/Test/Command.html#env-instance_method).
|
|
41
|
-
The instance has access to the command's process ID, exit status,
|
|
42
|
-
standard output stream, and standard error stream.
|
|
43
37
|
|
|
44
38
|
```ruby
|
|
45
39
|
require "test-cmd"
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Call the 'ls' command
|
|
43
|
+
p Test::Command
|
|
44
|
+
.new("ls")
|
|
45
|
+
.argv("-l")
|
|
46
|
+
.stdout
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
# Call the env command with the given environment
|
|
50
|
+
# variables set.
|
|
51
|
+
p Test::Command
|
|
52
|
+
.new("env")
|
|
53
|
+
.env("FOO" => "bar")
|
|
54
|
+
.stdout
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# Write to the stdin stream of the command that
|
|
58
|
+
# is executed.
|
|
59
|
+
p Test::Command
|
|
60
|
+
.new("tr", "a-z", "A-Z")
|
|
61
|
+
.stdin("hello")
|
|
62
|
+
.stdout # => "HELLO"
|
|
48
63
|
```
|
|
49
64
|
|
|
50
65
|
<details>
|
|
51
66
|
<summary>Environment</summary>
|
|
52
67
|
<br>
|
|
53
68
|
|
|
54
|
-
Environment variables for the spawned process are set with
|
|
55
|
-
[`Test::Command#env`](https://r.uby.dev/api-docs/test-cmd.rb/Test/Command.html#env-instance_method),
|
|
56
|
-
which merges the given variables into the child's environment and
|
|
57
|
-
returns the command for chaining.
|
|
58
|
-
|
|
59
69
|
```ruby
|
|
60
70
|
require "test-cmd"
|
|
61
|
-
|
|
71
|
+
|
|
72
|
+
p Test::Command
|
|
62
73
|
.new("ruby", "-e", "puts ENV['FOO']")
|
|
63
74
|
.env("FOO" => "42")
|
|
64
75
|
.stdout # => "42\n"
|
|
@@ -66,15 +77,27 @@ puts Test::Command
|
|
|
66
77
|
</details>
|
|
67
78
|
|
|
68
79
|
<details>
|
|
69
|
-
<summary>
|
|
80
|
+
<summary>Standard input</summary>
|
|
70
81
|
<br>
|
|
71
82
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
```ruby
|
|
84
|
+
require "test-cmd"
|
|
85
|
+
|
|
86
|
+
p Test::Command
|
|
87
|
+
.new("cat")
|
|
88
|
+
.stdin("hello world")
|
|
89
|
+
.stdout # => "hello world"
|
|
90
|
+
|
|
91
|
+
p Test::Command
|
|
92
|
+
.new("tr", "a-z", "A-Z")
|
|
93
|
+
.stdin(Test::Command.new("echo", "hello"))
|
|
94
|
+
.stdout # => "HELLO\n"
|
|
95
|
+
```
|
|
96
|
+
</details>
|
|
97
|
+
|
|
98
|
+
<details>
|
|
99
|
+
<summary>Callbacks</summary>
|
|
100
|
+
<br>
|
|
78
101
|
|
|
79
102
|
```ruby
|
|
80
103
|
require "test-cmd"
|
|
@@ -97,7 +120,7 @@ stream of the spawned ruby process:
|
|
|
97
120
|
|
|
98
121
|
```ruby
|
|
99
122
|
require "test/unit"
|
|
100
|
-
require "test
|
|
123
|
+
require "test-cmd"
|
|
101
124
|
|
|
102
125
|
class CmdTest < Test::Unit::TestCase
|
|
103
126
|
def test_ruby_stdout
|
|
@@ -125,12 +148,7 @@ end
|
|
|
125
148
|
```
|
|
126
149
|
</details>
|
|
127
150
|
|
|
128
|
-
## Documentation
|
|
129
|
-
|
|
130
|
-
A complete API reference is available at
|
|
131
|
-
[r.uby.dev/api-docs/test-cmd.rb](https://r.uby.dev/api-docs/test-cmd.rb)
|
|
132
|
-
|
|
133
151
|
## License
|
|
134
152
|
|
|
135
|
-
This software is released under the
|
|
136
|
-
See [LICENSE](
|
|
153
|
+
This software is released under the MIT license. <br>
|
|
154
|
+
See [LICENSE](LICENSE) for details.
|
|
@@ -5,6 +5,8 @@ end unless defined?(Test)
|
|
|
5
5
|
# test-cmd.rb provides an object oriented interface
|
|
6
6
|
# for spawning a command
|
|
7
7
|
class Test::Command
|
|
8
|
+
require_relative "command/version"
|
|
9
|
+
|
|
8
10
|
##
|
|
9
11
|
# @api private
|
|
10
12
|
class Pipe < Struct.new(:r, :w)
|
|
@@ -50,26 +52,36 @@ class Test::Command
|
|
|
50
52
|
tap { @env.merge!(env) }
|
|
51
53
|
end
|
|
52
54
|
|
|
55
|
+
##
|
|
56
|
+
# Presets the standard input that will be sent to the
|
|
57
|
+
# spawned process. Pass a String, or another
|
|
58
|
+
# {Test::Command Test::Command} whose standard output
|
|
59
|
+
# will be used as the standard input.
|
|
60
|
+
# @param [String, Test::Command] data
|
|
61
|
+
# The standard input of the spawned process
|
|
62
|
+
# @example
|
|
63
|
+
# cmd = Test::Command.new("cat").stdin("hello world")
|
|
64
|
+
# puts cmd.stdout
|
|
65
|
+
# @return [Test::Command]
|
|
66
|
+
def stdin(data)
|
|
67
|
+
tap { @stdin = data }
|
|
68
|
+
end
|
|
69
|
+
|
|
53
70
|
##
|
|
54
71
|
# Spawns a command
|
|
55
72
|
# @return [Test::Command]
|
|
56
73
|
def spawn
|
|
57
74
|
return self if @spawned
|
|
75
|
+
@in_r = input_pipe
|
|
58
76
|
tap do
|
|
59
77
|
@spawned = true
|
|
60
78
|
@out, @err = Pipe.pair, Pipe.pair
|
|
61
|
-
##
|
|
62
|
-
# Spawn in the calling thread so the command's fds are
|
|
63
|
-
# wired up before the reader thread starts. We then close
|
|
64
|
-
# our own copies of the write ends so the reader thread
|
|
65
|
-
# observes EOF the moment the child exits, and reads both
|
|
66
|
-
# streams with whole-buffer reads rather than a byte at
|
|
67
|
-
# a time.
|
|
68
79
|
@pid = Process.spawn(
|
|
69
80
|
@env,
|
|
70
|
-
@cmd, *@argv,
|
|
71
|
-
{out: @out.w, err: @err.w
|
|
81
|
+
@cmd, *@argv.map(&:to_s),
|
|
82
|
+
{in: @in_r, out: @out.w, err: @err.w}
|
|
72
83
|
)
|
|
84
|
+
@in_r.close unless @in_r.equal?(IO::NULL)
|
|
73
85
|
@out.w.close
|
|
74
86
|
@err.w.close
|
|
75
87
|
@producer = Thread.new do
|
|
@@ -86,8 +98,9 @@ class Test::Command
|
|
|
86
98
|
@stderr = ex.message
|
|
87
99
|
@enoent = true
|
|
88
100
|
##
|
|
89
|
-
#
|
|
90
|
-
#
|
|
101
|
+
# Close the read end of any input pipe so a pending
|
|
102
|
+
# writer thread does not block forever.
|
|
103
|
+
@in_r.close unless @in_r.equal?(IO::NULL)
|
|
91
104
|
@status = Process.waitpid2(Process.spawn("false")).last
|
|
92
105
|
end
|
|
93
106
|
|
|
@@ -219,6 +232,23 @@ class Test::Command
|
|
|
219
232
|
|
|
220
233
|
private
|
|
221
234
|
|
|
235
|
+
##
|
|
236
|
+
# Returns a pipe pair used for the command's
|
|
237
|
+
# standard input. When no input is set, the child
|
|
238
|
+
# reads from IO::NULL. When the input is another
|
|
239
|
+
# command, the source command is spawned first and
|
|
240
|
+
# its stdout feeds the pipe.
|
|
241
|
+
# @return [IO]
|
|
242
|
+
# A read end (IO::NULL or a pipe read end)
|
|
243
|
+
def input_pipe
|
|
244
|
+
return IO::NULL if @stdin.nil?
|
|
245
|
+
data = self.class === @stdin ? @stdin.stdout : @stdin.to_s
|
|
246
|
+
r, w = IO.pipe
|
|
247
|
+
w.write(data)
|
|
248
|
+
w.close
|
|
249
|
+
r
|
|
250
|
+
end
|
|
251
|
+
|
|
222
252
|
##
|
|
223
253
|
# Blocks until the spawned command has finished, its
|
|
224
254
|
# output has been read, and its exit status captured.
|
|
@@ -228,4 +258,4 @@ class Test::Command
|
|
|
228
258
|
return unless @producer&.alive?
|
|
229
259
|
@producer.join
|
|
230
260
|
end
|
|
231
|
-
end
|
|
261
|
+
end
|
data/lib/test-cmd.rb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
require_relative "test/
|
|
1
|
+
require_relative "test/command"
|
data/rubydev.svg
CHANGED
|
@@ -1,30 +1,78 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 560 220" role="img" aria-labelledby="title desc">
|
|
2
2
|
<title id="title">r.uby.dev</title>
|
|
3
|
-
<desc id="desc">A wide r.uby.dev wordmark with
|
|
3
|
+
<desc id="desc">A wide r.uby.dev wordmark with ruby, sapphire, and emerald gemstones moving around the text.</desc>
|
|
4
4
|
<defs>
|
|
5
5
|
<linearGradient id="body" x1="45" y1="35" x2="211" y2="224" gradientUnits="userSpaceOnUse">
|
|
6
|
-
<stop offset="0" stop-color="#
|
|
7
|
-
<stop offset="0.42" stop-color="#
|
|
6
|
+
<stop offset="0" stop-color="#e0796f"/>
|
|
7
|
+
<stop offset="0.42" stop-color="#a7312b"/>
|
|
8
8
|
<stop offset="1" stop-color="#5b090d"/>
|
|
9
9
|
</linearGradient>
|
|
10
10
|
<linearGradient id="table" x1="75" y1="31" x2="166" y2="104" gradientUnits="userSpaceOnUse">
|
|
11
11
|
<stop offset="0" stop-color="#fff3ec"/>
|
|
12
|
-
<stop offset="0.26" stop-color="#
|
|
13
|
-
<stop offset="1" stop-color="#
|
|
12
|
+
<stop offset="0.26" stop-color="#d9867d"/>
|
|
13
|
+
<stop offset="1" stop-color="#a32d2a"/>
|
|
14
14
|
</linearGradient>
|
|
15
15
|
<linearGradient id="right" x1="150" y1="59" x2="219" y2="195" gradientUnits="userSpaceOnUse">
|
|
16
|
-
<stop offset="0" stop-color="#
|
|
16
|
+
<stop offset="0" stop-color="#911b20"/>
|
|
17
17
|
<stop offset="1" stop-color="#3c0407"/>
|
|
18
18
|
</linearGradient>
|
|
19
19
|
<linearGradient id="center" x1="99" y1="104" x2="146" y2="226" gradientUnits="userSpaceOnUse">
|
|
20
|
-
<stop offset="0" stop-color="#
|
|
21
|
-
<stop offset="0.48" stop-color="#
|
|
22
|
-
<stop offset="1" stop-color="#
|
|
20
|
+
<stop offset="0" stop-color="#c8554f"/>
|
|
21
|
+
<stop offset="0.48" stop-color="#992522"/>
|
|
22
|
+
<stop offset="1" stop-color="#6d1315"/>
|
|
23
23
|
</linearGradient>
|
|
24
24
|
<radialGradient id="glow" cx="38%" cy="22%" r="66%">
|
|
25
25
|
<stop offset="0" stop-color="#fff8ed" stop-opacity="0.68"/>
|
|
26
|
-
<stop offset="0.42" stop-color="#
|
|
27
|
-
<stop offset="1" stop-color="#
|
|
26
|
+
<stop offset="0.42" stop-color="#d89a92" stop-opacity="0.18"/>
|
|
27
|
+
<stop offset="1" stop-color="#d89a92" stop-opacity="0"/>
|
|
28
|
+
</radialGradient>
|
|
29
|
+
<linearGradient id="body-blue" x1="45" y1="35" x2="211" y2="224" gradientUnits="userSpaceOnUse">
|
|
30
|
+
<stop offset="0" stop-color="#7aa5d9"/>
|
|
31
|
+
<stop offset="0.42" stop-color="#35669e"/>
|
|
32
|
+
<stop offset="1" stop-color="#162f4a"/>
|
|
33
|
+
</linearGradient>
|
|
34
|
+
<linearGradient id="table-blue" x1="75" y1="31" x2="166" y2="104" gradientUnits="userSpaceOnUse">
|
|
35
|
+
<stop offset="0" stop-color="#edf4ff"/>
|
|
36
|
+
<stop offset="0.26" stop-color="#7d9ed9"/>
|
|
37
|
+
<stop offset="1" stop-color="#2a5ca3"/>
|
|
38
|
+
</linearGradient>
|
|
39
|
+
<linearGradient id="right-blue" x1="150" y1="59" x2="219" y2="195" gradientUnits="userSpaceOnUse">
|
|
40
|
+
<stop offset="0" stop-color="#1f4a91"/>
|
|
41
|
+
<stop offset="1" stop-color="#071b3c"/>
|
|
42
|
+
</linearGradient>
|
|
43
|
+
<linearGradient id="center-blue" x1="99" y1="104" x2="146" y2="226" gradientUnits="userSpaceOnUse">
|
|
44
|
+
<stop offset="0" stop-color="#4f78c8"/>
|
|
45
|
+
<stop offset="0.48" stop-color="#254a99"/>
|
|
46
|
+
<stop offset="1" stop-color="#132a6d"/>
|
|
47
|
+
</linearGradient>
|
|
48
|
+
<radialGradient id="glow-blue" cx="38%" cy="22%" r="66%">
|
|
49
|
+
<stop offset="0" stop-color="#edf6ff" stop-opacity="0.68"/>
|
|
50
|
+
<stop offset="0.42" stop-color="#92aed9" stop-opacity="0.18"/>
|
|
51
|
+
<stop offset="1" stop-color="#92aed9" stop-opacity="0"/>
|
|
52
|
+
</radialGradient>
|
|
53
|
+
<linearGradient id="body-green" x1="45" y1="35" x2="211" y2="224" gradientUnits="userSpaceOnUse">
|
|
54
|
+
<stop offset="0" stop-color="#79d9a0"/>
|
|
55
|
+
<stop offset="0.42" stop-color="#359e66"/>
|
|
56
|
+
<stop offset="1" stop-color="#164a2f"/>
|
|
57
|
+
</linearGradient>
|
|
58
|
+
<linearGradient id="table-green" x1="75" y1="31" x2="166" y2="104" gradientUnits="userSpaceOnUse">
|
|
59
|
+
<stop offset="0" stop-color="#edfff4"/>
|
|
60
|
+
<stop offset="0.26" stop-color="#7dd9a5"/>
|
|
61
|
+
<stop offset="1" stop-color="#2aa360"/>
|
|
62
|
+
</linearGradient>
|
|
63
|
+
<linearGradient id="right-green" x1="150" y1="59" x2="219" y2="195" gradientUnits="userSpaceOnUse">
|
|
64
|
+
<stop offset="0" stop-color="#1b9147"/>
|
|
65
|
+
<stop offset="1" stop-color="#043c1c"/>
|
|
66
|
+
</linearGradient>
|
|
67
|
+
<linearGradient id="center-green" x1="99" y1="104" x2="146" y2="226" gradientUnits="userSpaceOnUse">
|
|
68
|
+
<stop offset="0" stop-color="#4fc87d"/>
|
|
69
|
+
<stop offset="0.48" stop-color="#259950"/>
|
|
70
|
+
<stop offset="1" stop-color="#136d30"/>
|
|
71
|
+
</linearGradient>
|
|
72
|
+
<radialGradient id="glow-green" cx="38%" cy="22%" r="66%">
|
|
73
|
+
<stop offset="0" stop-color="#edfff4" stop-opacity="0.68"/>
|
|
74
|
+
<stop offset="0.42" stop-color="#92d9b0" stop-opacity="0.18"/>
|
|
75
|
+
<stop offset="1" stop-color="#92d9b0" stop-opacity="0"/>
|
|
28
76
|
</radialGradient>
|
|
29
77
|
<linearGradient id="wordmark" x1="0" y1="76" x2="0" y2="138" gradientUnits="userSpaceOnUse">
|
|
30
78
|
<stop offset="0" stop-color="#ffffff"/>
|
|
@@ -33,7 +81,7 @@
|
|
|
33
81
|
</linearGradient>
|
|
34
82
|
<linearGradient id="accentLine" x1="90" y1="0" x2="470" y2="0" gradientUnits="userSpaceOnUse">
|
|
35
83
|
<stop offset="0" stop-color="#30363d"/>
|
|
36
|
-
<stop offset="0.5" stop-color="#
|
|
84
|
+
<stop offset="0.5" stop-color="#a7312b"/>
|
|
37
85
|
<stop offset="1" stop-color="#30363d"/>
|
|
38
86
|
</linearGradient>
|
|
39
87
|
<filter id="shadow" x="-18%" y="-18%" width="136%" height="146%">
|
|
@@ -45,17 +93,47 @@
|
|
|
45
93
|
<symbol id="gemstone" viewBox="0 0 256 256">
|
|
46
94
|
<path d="M33 91 78 30h100l45 61-95 134Z" fill="url(#body)" stroke="#250507" stroke-width="7" stroke-linejoin="round"/>
|
|
47
95
|
<path d="M78 30h100l-50 61Z" fill="url(#table)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
48
|
-
<path d="M33 91h95l-52 44Z" fill="#
|
|
96
|
+
<path d="M33 91h95l-52 44Z" fill="#b03a33" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
49
97
|
<path d="M223 91h-95l52 44Z" fill="url(#right)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
50
|
-
<path d="M76 135 128 225 33 91Z" fill="#
|
|
98
|
+
<path d="M76 135 128 225 33 91Z" fill="#7a1a1b" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
51
99
|
<path d="M180 135 128 225 223 91Z" fill="#62080d" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
52
100
|
<path d="M76 135h104l-52 90Z" fill="url(#center)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
53
|
-
<path d="M78 30 128 91 76 135 33 91Z" fill="#
|
|
54
|
-
<path d="M178 30 128 91 180 135 223 91Z" fill="#
|
|
55
|
-
<path d="M128 91 76 135h104Z" fill="#
|
|
101
|
+
<path d="M78 30 128 91 76 135 33 91Z" fill="#a32d29" opacity="0.72"/>
|
|
102
|
+
<path d="M178 30 128 91 180 135 223 91Z" fill="#6f1416" opacity="0.72"/>
|
|
103
|
+
<path d="M128 91 76 135h104Z" fill="#c44f47" opacity="0.5"/>
|
|
56
104
|
<path d="M49 91 84 43h43L86 96Z" fill="url(#glow)"/>
|
|
57
105
|
<path d="M85 62 101 43h35L93 87Z" fill="#fff6eb" opacity="0.52"/>
|
|
58
|
-
<path d="M97 153h62" fill="none" stroke="#
|
|
106
|
+
<path d="M97 153h62" fill="none" stroke="#cf8d85" stroke-width="4" stroke-linecap="round" opacity="0.25"/>
|
|
107
|
+
</symbol>
|
|
108
|
+
<symbol id="gemstone-blue" viewBox="0 0 256 256">
|
|
109
|
+
<path d="M33 91 78 30h100l45 61-95 134Z" fill="url(#body-blue)" stroke="#250507" stroke-width="7" stroke-linejoin="round"/>
|
|
110
|
+
<path d="M78 30h100l-50 61Z" fill="url(#table-blue)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
111
|
+
<path d="M33 91h95l-52 44Z" fill="#336fb0" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
112
|
+
<path d="M223 91h-95l52 44Z" fill="url(#right-blue)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
113
|
+
<path d="M76 135 128 225 33 91Z" fill="#1a3a7a" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
114
|
+
<path d="M180 135 128 225 223 91Z" fill="#081a62" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
115
|
+
<path d="M76 135h104l-52 90Z" fill="url(#center-blue)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
116
|
+
<path d="M78 30 128 91 76 135 33 91Z" fill="#2d5ba3" opacity="0.72"/>
|
|
117
|
+
<path d="M178 30 128 91 180 135 223 91Z" fill="#142d6f" opacity="0.72"/>
|
|
118
|
+
<path d="M128 91 76 135h104Z" fill="#4774c4" opacity="0.5"/>
|
|
119
|
+
<path d="M49 91 84 43h43L86 96Z" fill="url(#glow-blue)"/>
|
|
120
|
+
<path d="M85 62 101 43h35L93 87Z" fill="#edf4ff" opacity="0.52"/>
|
|
121
|
+
<path d="M97 153h62" fill="none" stroke="#85a5cf" stroke-width="4" stroke-linecap="round" opacity="0.25"/>
|
|
122
|
+
</symbol>
|
|
123
|
+
<symbol id="gemstone-green" viewBox="0 0 256 256">
|
|
124
|
+
<path d="M33 91 78 30h100l45 61-95 134Z" fill="url(#body-green)" stroke="#250507" stroke-width="7" stroke-linejoin="round"/>
|
|
125
|
+
<path d="M78 30h100l-50 61Z" fill="url(#table-green)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
126
|
+
<path d="M33 91h95l-52 44Z" fill="#33b070" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
127
|
+
<path d="M223 91h-95l52 44Z" fill="url(#right-green)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
128
|
+
<path d="M76 135 128 225 33 91Z" fill="#1a7a4b" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
129
|
+
<path d="M180 135 128 225 223 91Z" fill="#086220" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
130
|
+
<path d="M76 135h104l-52 90Z" fill="url(#center-green)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
|
|
131
|
+
<path d="M78 30 128 91 76 135 33 91Z" fill="#2da36a" opacity="0.72"/>
|
|
132
|
+
<path d="M178 30 128 91 180 135 223 91Z" fill="#146f3d" opacity="0.72"/>
|
|
133
|
+
<path d="M128 91 76 135h104Z" fill="#47c478" opacity="0.5"/>
|
|
134
|
+
<path d="M49 91 84 43h43L86 96Z" fill="url(#glow-green)"/>
|
|
135
|
+
<path d="M85 62 101 43h35L93 87Z" fill="#edfff4" opacity="0.52"/>
|
|
136
|
+
<path d="M97 153h62" fill="none" stroke="#85cf9f" stroke-width="4" stroke-linecap="round" opacity="0.25"/>
|
|
59
137
|
</symbol>
|
|
60
138
|
</defs>
|
|
61
139
|
<style>
|
|
@@ -99,22 +177,22 @@
|
|
|
99
177
|
stroke: var(--accent-shadow);
|
|
100
178
|
}
|
|
101
179
|
.gem {
|
|
102
|
-
animation-duration:
|
|
180
|
+
animation-duration: 6.5s;
|
|
103
181
|
animation-iteration-count: infinite;
|
|
104
182
|
animation-timing-function: ease-in-out;
|
|
105
183
|
}
|
|
106
184
|
.gem-a { animation-name: gem-a; }
|
|
107
|
-
.gem-b { animation-name: gem-b; animation-duration:
|
|
108
|
-
.gem-c { animation-name: gem-c; animation-duration:
|
|
185
|
+
.gem-b { animation-name: gem-b; animation-duration: 7.5s; }
|
|
186
|
+
.gem-c { animation-name: gem-c; animation-duration: 8s; }
|
|
109
187
|
.gem-front {
|
|
110
188
|
opacity: 0;
|
|
111
|
-
animation-duration:
|
|
189
|
+
animation-duration: 12s;
|
|
112
190
|
animation-iteration-count: infinite;
|
|
113
191
|
animation-timing-function: ease-in-out;
|
|
114
192
|
}
|
|
115
193
|
.gem-front-a { animation-name: gem-front-a; }
|
|
116
|
-
.gem-front-b { animation-name: gem-front-b; animation-delay: -
|
|
117
|
-
.gem-front-c { animation-name: gem-front-c; animation-delay: -
|
|
194
|
+
.gem-front-b { animation-name: gem-front-b; animation-delay: -4s; }
|
|
195
|
+
.gem-front-c { animation-name: gem-front-c; animation-delay: -8s; }
|
|
118
196
|
@keyframes gem-a {
|
|
119
197
|
0%, 100% { transform: translate(42px, 82px) rotate(-10deg); }
|
|
120
198
|
35% { transform: translate(66px, 45px) rotate(5deg); }
|
|
@@ -151,13 +229,10 @@
|
|
|
151
229
|
}
|
|
152
230
|
</style>
|
|
153
231
|
|
|
154
|
-
<
|
|
155
|
-
<path class="rule-strong" d="M90 32h380" stroke-width="2" stroke-linecap="round" opacity="0.72"/>
|
|
156
|
-
|
|
157
|
-
<g filter="url(#shadow)" opacity="0.92">
|
|
232
|
+
<g opacity="0.92">
|
|
158
233
|
<g class="gem gem-a"><use href="#gemstone" width="78" height="78"/></g>
|
|
159
|
-
<g class="gem gem-b"><use href="#gemstone" width="84" height="84"/></g>
|
|
160
|
-
<g class="gem gem-c"><use href="#gemstone" width="78" height="78"/></g>
|
|
234
|
+
<g class="gem gem-b"><use href="#gemstone-blue" width="84" height="84"/></g>
|
|
235
|
+
<g class="gem gem-c"><use href="#gemstone-green" width="78" height="78"/></g>
|
|
161
236
|
</g>
|
|
162
237
|
|
|
163
238
|
<g font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" text-anchor="middle">
|
|
@@ -170,15 +245,12 @@
|
|
|
170
245
|
font-size="72" font-weight="800">r.uby.dev</text>
|
|
171
246
|
</g>
|
|
172
247
|
|
|
173
|
-
<g
|
|
248
|
+
<g>
|
|
174
249
|
<g class="gem gem-a"><use class="gem-front gem-front-a" href="#gemstone" width="78" height="78"/></g>
|
|
175
|
-
<g class="gem gem-b"><use class="gem-front gem-front-b" href="#gemstone" width="84" height="84"/></g>
|
|
176
|
-
<g class="gem gem-c"><use class="gem-front gem-front-c" href="#gemstone" width="78" height="78"/></g>
|
|
250
|
+
<g class="gem gem-b"><use class="gem-front gem-front-b" href="#gemstone-blue" width="84" height="84"/></g>
|
|
251
|
+
<g class="gem gem-c"><use class="gem-front gem-front-c" href="#gemstone-green" width="78" height="78"/></g>
|
|
177
252
|
</g>
|
|
178
253
|
|
|
179
|
-
<path class="accent-shadow" d="M90 176h380" stroke-width="8" stroke-linecap="round"/>
|
|
180
|
-
<path d="M90 176h380" stroke="url(#accentLine)" stroke-width="4" stroke-linecap="round"/>
|
|
181
|
-
<circle cx="280" cy="176" r="5" fill="#cc342d"/>
|
|
182
254
|
<text class="tagline" x="280" y="204"
|
|
183
255
|
font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
|
|
184
256
|
text-anchor="middle" font-size="18" font-weight="650">Building cool stuff with Ruby</text>
|
data/test/cmd_test.rb
CHANGED
|
@@ -19,6 +19,14 @@ class Test::Command
|
|
|
19
19
|
.argv("-e", "warn 42")
|
|
20
20
|
.stderr
|
|
21
21
|
end
|
|
22
|
+
|
|
23
|
+
def test_ruby_argv_to_s
|
|
24
|
+
arg = Object.new
|
|
25
|
+
def arg.to_s = "-e"
|
|
26
|
+
assert_equal "42\n", ::Test::Command.new("ruby")
|
|
27
|
+
.argv(arg, "warn 42")
|
|
28
|
+
.stderr
|
|
29
|
+
end
|
|
22
30
|
end
|
|
23
31
|
|
|
24
32
|
##
|
|
@@ -32,6 +40,24 @@ class Test::Command
|
|
|
32
40
|
end
|
|
33
41
|
end
|
|
34
42
|
|
|
43
|
+
##
|
|
44
|
+
# Test::Command#stdin
|
|
45
|
+
class StdinTest < Test
|
|
46
|
+
def test_ruby_stdin_string
|
|
47
|
+
assert_equal "hello world",
|
|
48
|
+
::Test::Command.new("cat")
|
|
49
|
+
.stdin("hello world")
|
|
50
|
+
.stdout
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_ruby_stdin_command
|
|
54
|
+
assert_equal "42\n",
|
|
55
|
+
::Test::Command.new("cat")
|
|
56
|
+
.stdin(ruby("puts 42"))
|
|
57
|
+
.stdout
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
35
61
|
##
|
|
36
62
|
# Test::Command#{exit_status, status, success?}
|
|
37
63
|
class ExitStatusTest < Test
|
data/test/setup.rb
CHANGED
data/test-cmd.rb.gemspec
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require File.join(__dir__, "lib", "test", "command", "version.rb")
|
|
4
|
+
|
|
3
5
|
Gem::Specification.new do |gem|
|
|
4
6
|
gem.name = "test-cmd.rb"
|
|
5
|
-
gem.authors = ["
|
|
7
|
+
gem.authors = ["Robert Gleeson"]
|
|
6
8
|
gem.email = ["robert@r.uby.dev"]
|
|
7
9
|
gem.homepage = "https://github.com/0x1eef/test-cmd.rb#readme"
|
|
8
|
-
gem.version =
|
|
10
|
+
gem.version = Test::Command::VERSION
|
|
9
11
|
gem.required_ruby_version = ">= 3.0"
|
|
10
|
-
gem.licenses = ["
|
|
12
|
+
gem.licenses = ["MIT"]
|
|
11
13
|
gem.files = `git ls-files`.split($/)
|
|
12
14
|
gem.require_paths = ["lib"]
|
|
13
|
-
gem.summary =
|
|
15
|
+
gem.summary = <<~SUMMARY
|
|
16
|
+
test-cmd.rb is a Go-inspired, object-oriented interface for running
|
|
17
|
+
commands on UNIX-like systems, in the spirit of Go's `os/exec`. A
|
|
18
|
+
command can be built by chaining multiple method calls that impact
|
|
19
|
+
different command attributes. The environment the command executes
|
|
20
|
+
with can be set, its standard input stream can be written to, and
|
|
21
|
+
the standard output and standard error streams are captured so the
|
|
22
|
+
parent process can read them.
|
|
23
|
+
SUMMARY
|
|
14
24
|
gem.description = gem.summary
|
|
15
25
|
gem.add_development_dependency "test-unit", "~> 3.5.7"
|
|
16
26
|
gem.add_development_dependency "yard", "~> 0.9"
|
metadata
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: test-cmd.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- Robert Gleeson
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
@@ -79,7 +79,12 @@ dependencies:
|
|
|
79
79
|
- - "~>"
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
81
|
version: '13.1'
|
|
82
|
-
description: test-cmd.rb
|
|
82
|
+
description: test-cmd.rb is a Go-inspired, object-oriented interface for running commands
|
|
83
|
+
on UNIX-like systems, in the spirit of Go's `os/exec`. A command can be built by
|
|
84
|
+
chaining multiple method calls that impact different command attributes. The environment
|
|
85
|
+
the command executes with can be set, its standard input stream can be written to,
|
|
86
|
+
and the standard output and standard error streams are captured so the parent process
|
|
87
|
+
can read them.
|
|
83
88
|
email:
|
|
84
89
|
- robert@r.uby.dev
|
|
85
90
|
executables: []
|
|
@@ -95,14 +100,15 @@ files:
|
|
|
95
100
|
- README.md
|
|
96
101
|
- Rakefile.rb
|
|
97
102
|
- lib/test-cmd.rb
|
|
98
|
-
- lib/test/
|
|
103
|
+
- lib/test/command.rb
|
|
104
|
+
- lib/test/command/version.rb
|
|
99
105
|
- rubydev.svg
|
|
100
106
|
- test-cmd.rb.gemspec
|
|
101
107
|
- test/cmd_test.rb
|
|
102
108
|
- test/setup.rb
|
|
103
109
|
homepage: https://github.com/0x1eef/test-cmd.rb#readme
|
|
104
110
|
licenses:
|
|
105
|
-
-
|
|
111
|
+
- MIT
|
|
106
112
|
metadata: {}
|
|
107
113
|
rdoc_options: []
|
|
108
114
|
require_paths:
|
|
@@ -120,5 +126,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
120
126
|
requirements: []
|
|
121
127
|
rubygems_version: 4.0.16
|
|
122
128
|
specification_version: 4
|
|
123
|
-
summary: test-cmd.rb
|
|
129
|
+
summary: test-cmd.rb is a Go-inspired, object-oriented interface for running commands
|
|
130
|
+
on UNIX-like systems, in the spirit of Go's `os/exec`. A command can be built by
|
|
131
|
+
chaining multiple method calls that impact different command attributes. The environment
|
|
132
|
+
the command executes with can be set, its standard input stream can be written to,
|
|
133
|
+
and the standard output and standard error streams are captured so the parent process
|
|
134
|
+
can read them.
|
|
124
135
|
test_files: []
|