scmd 3.0.1 → 3.0.5
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 +7 -7
- data/Gemfile +14 -6
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +1 -1
- data/bench/results.txt +32 -32
- data/bench/runner.rb +16 -13
- data/lib/scmd/command.rb +59 -43
- data/lib/scmd/command_spy.rb +22 -24
- data/lib/scmd/stored_commands.rb +10 -14
- data/lib/scmd/version.rb +3 -1
- data/lib/scmd.rb +17 -16
- data/scmd.gemspec +13 -6
- data/script/bench.rb +6 -7
- data/test/helper.rb +13 -2
- data/test/support/factory.rb +3 -2
- data/test/system/command_tests.rb +22 -27
- data/test/unit/command_spy_tests.rb +30 -16
- data/test/unit/command_tests.rb +8 -9
- data/test/unit/scmd_tests.rb +17 -22
- data/test/unit/stored_commands_tests.rb +7 -9
- metadata +62 -49
- data/.gitignore +0 -19
- data/Rakefile +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
---
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
SHA512:
|
6
|
-
|
7
|
-
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f93aa47368dbe362f4e21f275f29e463e1be3ac7a4eec07b5ce2d18b77155543
|
4
|
+
data.tar.gz: 3d9daf1670226711e0852c079276823f211088eb306e7b147b8bba140d5aee74
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6aab5d881aa873b1f95309ecd760a2e04e349df5821b3ac8814e5a4aba0fbe95e38aa6638cd3f9b5b70e0fea410b93a1aba65c78bf82ac8223b33514f9740616
|
7
|
+
data.tar.gz: 4a167c35519b264b3c33c93c72315af1f73f50c8b0b3373fb59946dcd95dbd5d93046d4978560ee1568a9cedd241487df27d986607ae6cc31373136fc179fd88
|
data/Gemfile
CHANGED
@@ -1,11 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "https://rubygems.org"
|
2
4
|
|
5
|
+
ruby ">= 2.5"
|
6
|
+
|
3
7
|
gemspec
|
4
8
|
|
5
|
-
gem
|
6
|
-
gem
|
7
|
-
|
9
|
+
gem "pry"
|
10
|
+
gem "whysoslow"
|
11
|
+
|
12
|
+
# to release, uncomment this and run `bundle exec ggem r -f`
|
13
|
+
gem 'ggem'
|
8
14
|
|
9
|
-
|
10
|
-
|
11
|
-
|
15
|
+
gem "assert", path: "/Users/kellyredding/projects/tmp/assert"
|
16
|
+
gem "much-style-guide", path: "/Users/kellyredding/projects/tmp/much-style-guide"
|
17
|
+
gem "much-factory", path: "/Users/kellyredding/projects/tmp/much-factory"
|
18
|
+
gem "much-not-given", path: "/Users/kellyredding/projects/tmp/much-not-given"
|
19
|
+
gem "much-stub", path: "/Users/kellyredding/projects/tmp/much-stub"
|
data/{LICENSE.txt → LICENSE}
RENAMED
File without changes
|
data/README.md
CHANGED
data/bench/results.txt
CHANGED
@@ -2,79 +2,79 @@ echo hi: 1 times
|
|
2
2
|
----------------
|
3
3
|
whysoslow? ..
|
4
4
|
|
5
|
-
mem @ start
|
6
|
-
mem @ finish
|
5
|
+
mem @ start 17 MB ??
|
6
|
+
mem @ finish 17 MB [31m+ 0 MB, 0%[0m
|
7
7
|
|
8
|
-
|
9
|
-
time
|
8
|
+
user system total real
|
9
|
+
time 0.5820000000000001 ms 0.5519999999999999 ms 3.786 ms 3.7030000000000003 ms
|
10
10
|
|
11
11
|
echo hi: 10 times
|
12
12
|
-----------------
|
13
13
|
whysoslow? ..
|
14
14
|
|
15
|
-
mem @ start
|
16
|
-
mem @ finish
|
15
|
+
mem @ start 17 MB ??
|
16
|
+
mem @ finish 17 MB [31m+ 0 MB, 0%[0m
|
17
17
|
|
18
|
-
|
19
|
-
time
|
18
|
+
user system total real
|
19
|
+
time 2.475 ms 3.822 ms 32.675999999999995 ms 34.702 ms
|
20
20
|
|
21
21
|
echo hi: 100 times
|
22
22
|
------------------
|
23
23
|
whysoslow? ..
|
24
24
|
|
25
|
-
mem @ start
|
26
|
-
mem @ finish
|
25
|
+
mem @ start 17 MB ??
|
26
|
+
mem @ finish 18 MB [31m+ 0 MB, 2%[0m
|
27
27
|
|
28
|
-
|
29
|
-
time
|
28
|
+
user system total real
|
29
|
+
time 19.75 ms 31.77 ms 281.766 ms 306.74899999999997 ms
|
30
30
|
|
31
31
|
echo hi: 1000 times
|
32
32
|
-------------------
|
33
33
|
whysoslow? ..
|
34
34
|
|
35
|
-
mem @ start
|
36
|
-
mem @ finish
|
35
|
+
mem @ start 18 MB ??
|
36
|
+
mem @ finish 29 MB [31m+ 11 MB, 61%[0m
|
37
37
|
|
38
|
-
|
39
|
-
time
|
38
|
+
user system total real
|
39
|
+
time 161.98399999999998 ms 271.296 ms 2432.76 ms 2662.98 ms
|
40
40
|
|
41
41
|
cat test/support/bigger-than-64k.txt: 1 times
|
42
42
|
---------------------------------------------
|
43
43
|
whysoslow? ..
|
44
44
|
|
45
|
-
mem @ start
|
46
|
-
mem @ finish
|
45
|
+
mem @ start 31 MB ??
|
46
|
+
mem @ finish 31 MB [31m+ 0 MB, 1%[0m
|
47
47
|
|
48
|
-
|
49
|
-
time
|
48
|
+
user system total real
|
49
|
+
time 0.412 ms 0.504 ms 4.343999999999999 ms 4.654 ms
|
50
50
|
|
51
51
|
cat test/support/bigger-than-64k.txt: 10 times
|
52
52
|
----------------------------------------------
|
53
53
|
whysoslow? ..
|
54
54
|
|
55
|
-
mem @ start
|
56
|
-
mem @ finish
|
55
|
+
mem @ start 31 MB ??
|
56
|
+
mem @ finish 34 MB [31m+ 2 MB, 7%[0m
|
57
57
|
|
58
|
-
|
59
|
-
time
|
58
|
+
user system total real
|
59
|
+
time 3.2880000000000003 ms 4.386 ms 43.447 ms 46.552 ms
|
60
60
|
|
61
61
|
cat test/support/bigger-than-64k.txt: 100 times
|
62
62
|
-----------------------------------------------
|
63
63
|
whysoslow? ..
|
64
64
|
|
65
|
-
mem @ start
|
66
|
-
mem @ finish
|
65
|
+
mem @ start 33 MB ??
|
66
|
+
mem @ finish 56 MB [31m+ 23 MB, 68%[0m
|
67
67
|
|
68
|
-
|
69
|
-
time
|
68
|
+
user system total real
|
69
|
+
time 28.892999999999997 ms 40.599000000000004 ms 407.804 ms 440.11 ms
|
70
70
|
|
71
71
|
cat test/support/bigger-than-64k.txt: 1000 times
|
72
72
|
------------------------------------------------
|
73
73
|
whysoslow? ..
|
74
74
|
|
75
|
-
mem @ start
|
76
|
-
mem @ finish
|
75
|
+
mem @ start 44 MB ??
|
76
|
+
mem @ finish 297 MB [31m+ 254 MB, 582%[0m
|
77
77
|
|
78
|
-
|
79
|
-
time
|
78
|
+
user system total real
|
79
|
+
time 285.236 ms 408.677 ms 4097.647 ms 4428.276999999999 ms
|
80
80
|
|
data/bench/runner.rb
CHANGED
@@ -1,29 +1,32 @@
|
|
1
|
-
|
2
|
-
require 'scmd'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
require "whysoslow"
|
4
|
+
require "scmd"
|
5
5
|
|
6
|
+
class ScmdBenchRunner
|
6
7
|
attr_reader :result
|
7
8
|
|
8
9
|
def self.run(*args)
|
9
|
-
|
10
|
+
new(*args).run
|
10
11
|
end
|
11
12
|
|
12
13
|
def initialize(printer_io, cmd, num_times = 10)
|
13
14
|
@cmd = cmd
|
14
|
-
@proc =
|
15
|
-
|
16
|
-
|
15
|
+
@proc =
|
16
|
+
proc do
|
17
|
+
num_times.times{ cmd.run! }
|
18
|
+
end
|
17
19
|
|
18
|
-
@printer =
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
@printer =
|
21
|
+
Whysoslow::DefaultPrinter.new(
|
22
|
+
printer_io,
|
23
|
+
title: "#{@cmd.cmd_str}: #{num_times} times",
|
24
|
+
verbose: true,
|
25
|
+
)
|
22
26
|
@runner = Whysoslow::Runner.new(@printer)
|
23
27
|
end
|
24
28
|
|
25
29
|
def run
|
26
|
-
@runner.run
|
30
|
+
@runner.run(&@proc)
|
27
31
|
end
|
28
|
-
|
29
32
|
end
|
data/lib/scmd/command.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thread"
|
4
|
+
require "posix-spawn"
|
5
|
+
require "scmd"
|
4
6
|
|
5
7
|
# Scmd::Command is a base wrapper for handling system commands. Initialize it
|
6
8
|
# with with a string specifying the command to execute. You can then run the
|
@@ -8,7 +10,6 @@ require 'scmd'
|
|
8
10
|
# create a more custom command wrapper.
|
9
11
|
|
10
12
|
module Scmd
|
11
|
-
|
12
13
|
class Command
|
13
14
|
READ_SIZE = 10240 # bytes
|
14
15
|
READ_CHECK_TIMEOUT = 0.001 # seconds
|
@@ -26,7 +27,11 @@ module Scmd
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def run(input = nil)
|
29
|
-
|
30
|
+
begin
|
31
|
+
run!(input)
|
32
|
+
rescue
|
33
|
+
RunError
|
34
|
+
end
|
30
35
|
self
|
31
36
|
end
|
32
37
|
|
@@ -34,11 +39,13 @@ module Scmd
|
|
34
39
|
start_err_msg, start_err_bt = nil, nil
|
35
40
|
begin
|
36
41
|
start(input)
|
37
|
-
rescue
|
38
|
-
start_err_msg, start_err_bt =
|
42
|
+
rescue => ex
|
43
|
+
start_err_msg, start_err_bt = ex.message, ex.backtrace
|
39
44
|
ensure
|
40
45
|
wait # indefinitely until cmd is done running
|
41
|
-
|
46
|
+
unless success?
|
47
|
+
raise RunError.new(start_err_msg || @stderr, start_err_bt || caller)
|
48
|
+
end
|
42
49
|
end
|
43
50
|
|
44
51
|
self
|
@@ -49,19 +56,20 @@ module Scmd
|
|
49
56
|
|
50
57
|
@pid = @child_process.pid.to_i
|
51
58
|
@child_process.write(input)
|
52
|
-
@read_output_thread =
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
@read_output_thread =
|
60
|
+
Thread.new do
|
61
|
+
while @child_process.check_for_exit
|
62
|
+
begin
|
63
|
+
read_output
|
64
|
+
rescue EOFError # rubocop:disable Lint/SuppressedException
|
65
|
+
end
|
57
66
|
end
|
67
|
+
@stop_w.write_nonblock(".")
|
58
68
|
end
|
59
|
-
@stop_w.write_nonblock('.')
|
60
|
-
end
|
61
69
|
end
|
62
70
|
|
63
71
|
def wait(timeout = nil)
|
64
|
-
return
|
72
|
+
return unless running?
|
65
73
|
|
66
74
|
wait_for_exit(timeout)
|
67
75
|
if @child_process.running?
|
@@ -78,18 +86,18 @@ module Scmd
|
|
78
86
|
end
|
79
87
|
|
80
88
|
def stop(timeout = nil)
|
81
|
-
return
|
89
|
+
return unless running?
|
82
90
|
|
83
91
|
send_term
|
84
92
|
begin
|
85
93
|
wait(timeout || DEFAULT_STOP_TIMEOUT)
|
86
|
-
rescue TimeoutError
|
94
|
+
rescue TimeoutError
|
87
95
|
kill
|
88
96
|
end
|
89
97
|
end
|
90
98
|
|
91
99
|
def kill(signal = nil)
|
92
|
-
return
|
100
|
+
return unless running?
|
93
101
|
|
94
102
|
send_kill(signal)
|
95
103
|
wait # indefinitely until cmd is killed
|
@@ -108,25 +116,28 @@ module Scmd
|
|
108
116
|
end
|
109
117
|
|
110
118
|
def inspect
|
111
|
-
reference =
|
119
|
+
reference = "0x0%x" % (object_id << 1)
|
112
120
|
"#<#{self.class}:#{reference}"\
|
113
|
-
" @cmd_str=#{
|
121
|
+
" @cmd_str=#{cmd_str.inspect}"\
|
114
122
|
" @exitstatus=#{@exitstatus.inspect}>"
|
115
123
|
end
|
116
124
|
|
117
125
|
private
|
118
126
|
|
119
127
|
def read_output
|
120
|
-
@child_process.read(READ_SIZE)
|
128
|
+
@child_process.read(READ_SIZE) do |out, err|
|
129
|
+
@stdout += out
|
130
|
+
@stderr += err
|
131
|
+
end
|
121
132
|
end
|
122
133
|
|
123
134
|
def wait_for_exit(timeout)
|
124
|
-
ios, _, _ = IO.select([
|
125
|
-
@stop_r.read_nonblock(1) if ios
|
135
|
+
ios, _, _ = IO.select([@stop_r], nil, nil, timeout)
|
136
|
+
@stop_r.read_nonblock(1) if ios&.include?(@stop_r)
|
126
137
|
end
|
127
138
|
|
128
139
|
def reset_attrs
|
129
|
-
@stdout, @stderr, @pid, @exitstatus =
|
140
|
+
@stdout, @stderr, @pid, @exitstatus = +"", +"", nil, nil
|
130
141
|
end
|
131
142
|
|
132
143
|
def setup_run
|
@@ -145,33 +156,32 @@ module Scmd
|
|
145
156
|
end
|
146
157
|
|
147
158
|
def send_term
|
148
|
-
send_signal
|
159
|
+
send_signal "TERM"
|
149
160
|
end
|
150
161
|
|
151
162
|
def send_kill(signal = nil)
|
152
|
-
send_signal(signal ||
|
163
|
+
send_signal(signal || "KILL")
|
153
164
|
end
|
154
165
|
|
155
166
|
def send_signal(sig)
|
156
|
-
return
|
167
|
+
return unless running?
|
157
168
|
@child_process.send_signal(sig)
|
158
169
|
end
|
159
170
|
|
160
171
|
def stringify_hash(hash)
|
161
|
-
hash.
|
172
|
+
hash.reduce({}) do |h, (k, v)|
|
162
173
|
h.merge(k.to_s => v.to_s)
|
163
174
|
end
|
164
175
|
end
|
165
176
|
|
166
177
|
class ChildProcess
|
167
|
-
|
168
178
|
attr_reader :pid, :stdin, :stdout, :stderr
|
169
179
|
|
170
180
|
def initialize(cmd_str, env, options)
|
171
|
-
@pid, @stdin, @stdout, @stderr = *::POSIX::Spawn
|
181
|
+
@pid, @stdin, @stdout, @stderr = *::POSIX::Spawn.popen4(
|
172
182
|
env,
|
173
183
|
cmd_str,
|
174
|
-
options
|
184
|
+
options,
|
175
185
|
)
|
176
186
|
@wait_pid, @wait_status = nil, nil
|
177
187
|
end
|
@@ -194,25 +204,34 @@ module Scmd
|
|
194
204
|
end
|
195
205
|
|
196
206
|
def write(input)
|
197
|
-
|
207
|
+
unless input.nil?
|
198
208
|
[*input].each{ |line| @stdin.puts line.to_s }
|
199
209
|
@stdin.close
|
200
210
|
end
|
201
211
|
end
|
202
212
|
|
203
213
|
def read(size)
|
204
|
-
ios, _, _ =
|
214
|
+
ios, _, _ =
|
215
|
+
IO.select([@stdout, @stderr], nil, nil, READ_CHECK_TIMEOUT)
|
205
216
|
if ios && block_given?
|
206
|
-
yield
|
217
|
+
yield(
|
218
|
+
read_if_ready(ios, @stdout, size),
|
219
|
+
read_if_ready(ios, @stderr, size)
|
220
|
+
)
|
207
221
|
end
|
208
222
|
end
|
209
223
|
|
210
224
|
def send_signal(sig)
|
211
|
-
process_kill(sig,
|
225
|
+
process_kill(sig, pid)
|
226
|
+
end
|
227
|
+
|
228
|
+
def flush_stdout
|
229
|
+
@stdout.read
|
212
230
|
end
|
213
231
|
|
214
|
-
def
|
215
|
-
|
232
|
+
def flush_stderr
|
233
|
+
@stderr.read
|
234
|
+
end
|
216
235
|
|
217
236
|
def teardown
|
218
237
|
[@stdin, @stdout, @stderr].each{ |fd| fd.close if fd && !fd.closed? }
|
@@ -221,7 +240,7 @@ module Scmd
|
|
221
240
|
private
|
222
241
|
|
223
242
|
def read_if_ready(ready_ios, io, size)
|
224
|
-
ready_ios.include?(io) ? read_by_size(io, size) :
|
243
|
+
ready_ios.include?(io) ? read_by_size(io, size) : ""
|
225
244
|
end
|
226
245
|
|
227
246
|
def read_by_size(io, size)
|
@@ -238,11 +257,8 @@ module Scmd
|
|
238
257
|
end
|
239
258
|
|
240
259
|
def pgrep
|
241
|
-
@pgrep ||= Command.new(
|
260
|
+
@pgrep ||= Command.new("which pgrep").run.stdout.strip
|
242
261
|
end
|
243
|
-
|
244
262
|
end
|
245
|
-
|
246
263
|
end
|
247
|
-
|
248
264
|
end
|
data/lib/scmd/command_spy.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "scmd"
|
4
4
|
|
5
|
+
module Scmd
|
5
6
|
class CommandSpy
|
6
|
-
|
7
7
|
attr_reader :cmd_str, :env, :options
|
8
8
|
attr_reader :run_calls, :run_bang_calls, :start_calls
|
9
9
|
attr_reader :wait_calls, :stop_calls, :kill_calls
|
@@ -20,12 +20,12 @@ module Scmd
|
|
20
20
|
|
21
21
|
@running = false
|
22
22
|
|
23
|
-
@stdout, @stderr, @pid, @exitstatus =
|
23
|
+
@stdout, @stderr, @pid, @exitstatus = "", "", 1, 0
|
24
24
|
end
|
25
25
|
|
26
26
|
def run(input = nil)
|
27
27
|
@run_calls.push(InputCall.new(input))
|
28
|
-
Scmd.calls.push(Scmd::Call.new(self, input))
|
28
|
+
Scmd.calls.push(Scmd::Call.new(self, input)) if ENV["SCMD_TEST_MODE"]
|
29
29
|
self
|
30
30
|
end
|
31
31
|
|
@@ -35,7 +35,7 @@ module Scmd
|
|
35
35
|
|
36
36
|
def run!(input = nil)
|
37
37
|
@run_bang_calls.push(InputCall.new(input))
|
38
|
-
Scmd.calls.push(Scmd::Call.new(self, input))
|
38
|
+
Scmd.calls.push(Scmd::Call.new(self, input)) if ENV["SCMD_TEST_MODE"]
|
39
39
|
self
|
40
40
|
end
|
41
41
|
|
@@ -45,7 +45,7 @@ module Scmd
|
|
45
45
|
|
46
46
|
def start(input = nil)
|
47
47
|
@start_calls.push(InputCall.new(input))
|
48
|
-
Scmd.calls.push(Scmd::Call.new(self, input))
|
48
|
+
Scmd.calls.push(Scmd::Call.new(self, input)) if ENV["SCMD_TEST_MODE"]
|
49
49
|
@running = true
|
50
50
|
end
|
51
51
|
|
@@ -92,21 +92,21 @@ module Scmd
|
|
92
92
|
@cmd_str.to_s
|
93
93
|
end
|
94
94
|
|
95
|
-
def ==(
|
96
|
-
if
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
95
|
+
def ==(other)
|
96
|
+
if other.is_a?(CommandSpy)
|
97
|
+
cmd_str == other.cmd_str &&
|
98
|
+
env == other.env &&
|
99
|
+
options == other.options &&
|
100
|
+
run_calls == other.run_calls &&
|
101
|
+
run_bang_calls == other.run_bang_calls &&
|
102
|
+
start_calls == other.start_calls &&
|
103
|
+
wait_calls == other.wait_calls &&
|
104
|
+
stop_calls == other.stop_calls &&
|
105
|
+
kill_calls == other.kill_calls &&
|
106
|
+
pid == other.pid &&
|
107
|
+
exitstatus == other.exitstatus &&
|
108
|
+
stdout == other.stdout &&
|
109
|
+
stderr == other.stderr
|
110
110
|
else
|
111
111
|
super
|
112
112
|
end
|
@@ -115,7 +115,5 @@ module Scmd
|
|
115
115
|
InputCall = Struct.new(:input)
|
116
116
|
TimeoutCall = Struct.new(:timeout)
|
117
117
|
SignalCall = Struct.new(:signal)
|
118
|
-
|
119
118
|
end
|
120
|
-
|
121
119
|
end
|
data/lib/scmd/stored_commands.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "scmd/command_spy"
|
4
4
|
|
5
|
+
module Scmd
|
5
6
|
class StoredCommands
|
6
|
-
|
7
7
|
attr_reader :hash
|
8
8
|
|
9
9
|
def initialize
|
@@ -30,16 +30,15 @@ module Scmd
|
|
30
30
|
@hash.empty?
|
31
31
|
end
|
32
32
|
|
33
|
-
def ==(
|
34
|
-
if
|
35
|
-
|
33
|
+
def ==(other)
|
34
|
+
if other.is_a?(StoredCommands)
|
35
|
+
hash == other.hash
|
36
36
|
else
|
37
37
|
super
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
class Stub
|
42
|
-
|
43
42
|
attr_reader :cmd_str, :hash
|
44
43
|
|
45
44
|
def initialize(cmd_str)
|
@@ -62,17 +61,14 @@ module Scmd
|
|
62
61
|
CommandSpy.new(@cmd_str, opts).tap(&block)
|
63
62
|
end
|
64
63
|
|
65
|
-
def ==(
|
66
|
-
if
|
67
|
-
|
68
|
-
|
64
|
+
def ==(other)
|
65
|
+
if other.is_a?(Stub)
|
66
|
+
cmd_str == other.cmd_str &&
|
67
|
+
hash == other.hash
|
69
68
|
else
|
70
69
|
super
|
71
70
|
end
|
72
71
|
end
|
73
|
-
|
74
72
|
end
|
75
|
-
|
76
73
|
end
|
77
|
-
|
78
74
|
end
|
data/lib/scmd/version.rb
CHANGED
data/lib/scmd.rb
CHANGED
@@ -1,42 +1,44 @@
|
|
1
|
-
|
2
|
-
require 'scmd/command'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
require "scmd/version"
|
4
|
+
require "scmd/command"
|
5
5
|
|
6
|
+
module Scmd
|
6
7
|
# Scmd can be run in "test mode". This means that command spies will be used
|
7
8
|
# in place of "live" commands, each time a command is run or started will be
|
8
9
|
# logged in a collection and option-specific spies can be added and used to
|
9
10
|
# "stub" spies with specific attributes in specific contexts.
|
10
11
|
|
11
12
|
def self.new(*args)
|
12
|
-
if !ENV[
|
13
|
+
if !ENV["SCMD_TEST_MODE"]
|
13
14
|
Command.new(*args)
|
14
15
|
else
|
15
|
-
|
16
|
+
commands.get(*args)
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
20
|
def self.commands
|
20
|
-
raise NoMethodError
|
21
|
-
@commands ||=
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
raise NoMethodError unless ENV["SCMD_TEST_MODE"]
|
22
|
+
@commands ||=
|
23
|
+
begin
|
24
|
+
require "scmd/stored_commands"
|
25
|
+
StoredCommands.new
|
26
|
+
end
|
25
27
|
end
|
26
28
|
|
27
29
|
def self.calls
|
28
|
-
raise NoMethodError
|
30
|
+
raise NoMethodError unless ENV["SCMD_TEST_MODE"]
|
29
31
|
@calls ||= []
|
30
32
|
end
|
31
33
|
|
32
34
|
def self.reset
|
33
|
-
raise NoMethodError
|
34
|
-
|
35
|
-
|
35
|
+
raise NoMethodError unless ENV["SCMD_TEST_MODE"]
|
36
|
+
calls.clear
|
37
|
+
commands.remove_all
|
36
38
|
end
|
37
39
|
|
38
40
|
def self.add_command(cmd_str, &block)
|
39
|
-
|
41
|
+
commands.add(cmd_str, &block)
|
40
42
|
end
|
41
43
|
|
42
44
|
class Call < Struct.new(:cmd_str, :input, :cmd)
|
@@ -53,5 +55,4 @@ module Scmd
|
|
53
55
|
set_backtrace(called_from || caller)
|
54
56
|
end
|
55
57
|
end
|
56
|
-
|
57
58
|
end
|