kommando 0.0.19 → 0.0.21
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 +7 -0
- data/README.md +88 -3
- data/bin/loop +23 -0
- data/examples/passwd.rb +42 -0
- data/examples/stackprof.rb +18 -0
- data/examples/thread_leak.rb +15 -3
- data/kommando.gemspec +2 -0
- data/lib/kommando.rb +47 -18
- data/lib/kommando/buffer.rb +8 -0
- data/lib/kommando/version.rb +1 -1
- data/lib/kommando/when.rb +25 -3
- metadata +34 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 28bb48c41521e414b25f99f504388d7f487540e7
|
|
4
|
+
data.tar.gz: c5a621a4d4e123a1e384662d8beac09eafd3c289
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dac7252e7d4af6dc8ceeeff7c53a2b087e193ca2f9a87c2a5b44d9287bf3a65a883495845e87122ce9860e574e72a90722017264c5885af520087457a124ff85
|
|
7
|
+
data.tar.gz: 36802a54834ad364b2addabf3ea8679c801c82b3f68090c129cd5b9a0b32ddad8d198b35b229143619df6072e91995b1625601a2cee997886195afeab5d39d02
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -2,6 +2,94 @@
|
|
|
2
2
|
|
|
3
3
|
Command runner with expect-like features. Great for integration testing.
|
|
4
4
|
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
### Automating GNU nano:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
require "./lib/kommando"
|
|
11
|
+
require "tempfile"
|
|
12
|
+
|
|
13
|
+
scratch = Tempfile.new
|
|
14
|
+
|
|
15
|
+
k = Kommando.new "nano #{scratch.path}", {
|
|
16
|
+
output: true
|
|
17
|
+
}
|
|
18
|
+
k.out.on "GNU nano" do
|
|
19
|
+
k.in << "hello\r"
|
|
20
|
+
k.in << "\x1B\x1Bx"
|
|
21
|
+
|
|
22
|
+
k.out.on "Save modified buffer" do
|
|
23
|
+
sleep 1
|
|
24
|
+
k.in << "y"
|
|
25
|
+
|
|
26
|
+
k.out.on "File Name to Write" do
|
|
27
|
+
sleep 1
|
|
28
|
+
k.in << "\r"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
k.when "start" do
|
|
34
|
+
puts "Kommando started running nano"
|
|
35
|
+
sleep 2
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
k.when "exit" do
|
|
39
|
+
puts "Kommando finished"
|
|
40
|
+
sleep 1
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
k.run
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Shell scripting
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
require "./lib/kommando"
|
|
50
|
+
|
|
51
|
+
script = '
|
|
52
|
+
printf "new password: "
|
|
53
|
+
read input1
|
|
54
|
+
printf "password again: "
|
|
55
|
+
read input2
|
|
56
|
+
|
|
57
|
+
if [ "$input1" == "$input2" ]; then
|
|
58
|
+
printf "Are you sure that you want to change it? (y/N): "
|
|
59
|
+
read input3
|
|
60
|
+
if [ "$input3" == "y" ]; then
|
|
61
|
+
echo "changed"
|
|
62
|
+
else
|
|
63
|
+
echo "not changed"
|
|
64
|
+
fi
|
|
65
|
+
else
|
|
66
|
+
echo "Passwords did not match"
|
|
67
|
+
fi
|
|
68
|
+
'
|
|
69
|
+
|
|
70
|
+
k = Kommando.new "$ #{script}", {
|
|
71
|
+
output: true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
k.out.on "new password:" do
|
|
75
|
+
k.in.write "lol\r"
|
|
76
|
+
|
|
77
|
+
k.out.on "password again:" do
|
|
78
|
+
k.in.writeln "lol"
|
|
79
|
+
|
|
80
|
+
k.out.on /want to change it\?/ do
|
|
81
|
+
k.in << "y\r"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
k.out.on /Passwords did not match/ do
|
|
85
|
+
raise "this should never happen with that script."
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
k.run
|
|
91
|
+
```
|
|
92
|
+
|
|
5
93
|
## Installation
|
|
6
94
|
|
|
7
95
|
Add this line to your application's Gemfile:
|
|
@@ -18,9 +106,6 @@ Or install it yourself as:
|
|
|
18
106
|
|
|
19
107
|
$ gem install kommando
|
|
20
108
|
|
|
21
|
-
## Usage
|
|
22
|
-
|
|
23
|
-
TODO: Write usage instructions here
|
|
24
109
|
|
|
25
110
|
## Development
|
|
26
111
|
|
data/bin/loop
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "./lib/kommando"
|
|
4
|
+
|
|
5
|
+
while true do
|
|
6
|
+
k = Kommando.new "rake", {
|
|
7
|
+
timeout: 5
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
k.when :timeout do
|
|
11
|
+
print "t"
|
|
12
|
+
puts k.out
|
|
13
|
+
end
|
|
14
|
+
k.when :error do
|
|
15
|
+
print "e"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
k.run
|
|
19
|
+
|
|
20
|
+
if k.code == 0
|
|
21
|
+
print "."
|
|
22
|
+
end
|
|
23
|
+
end
|
data/examples/passwd.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require "./lib/kommando"
|
|
2
|
+
|
|
3
|
+
script = '
|
|
4
|
+
printf "new password: "
|
|
5
|
+
read input1
|
|
6
|
+
printf "password again: "
|
|
7
|
+
read input2
|
|
8
|
+
|
|
9
|
+
if [ "$input1" == "$input2" ]; then
|
|
10
|
+
printf "Are you sure that you want to change it? (y/N): "
|
|
11
|
+
read input3
|
|
12
|
+
if [ "$input3" == "y" ]; then
|
|
13
|
+
echo "changed"
|
|
14
|
+
else
|
|
15
|
+
echo "not changed"
|
|
16
|
+
fi
|
|
17
|
+
else
|
|
18
|
+
echo "Passwords did not match"
|
|
19
|
+
fi
|
|
20
|
+
'
|
|
21
|
+
|
|
22
|
+
k = Kommando.new "$ #{script}", {
|
|
23
|
+
output: true
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
k.out.on "new password:" do
|
|
27
|
+
k.in.write "lol\r"
|
|
28
|
+
|
|
29
|
+
k.out.on "password again:" do
|
|
30
|
+
k.in.writeln "lol"
|
|
31
|
+
|
|
32
|
+
k.out.on /want to change it\?/ do
|
|
33
|
+
k.in << "y\r"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
k.out.on /Passwords did not match/ do
|
|
37
|
+
raise "this should never happen with that script."
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
k.run
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require "./lib/kommando"
|
|
2
|
+
require 'stackprof'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
profile = StackProf.run(mode: :wall, out: 'tmp/stackprof-wall.dump', interval: 100) do
|
|
6
|
+
100.times {
|
|
7
|
+
Kommando.run "uptime"
|
|
8
|
+
}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
profile = StackProf.run(mode: :cpu, out: 'tmp/stackprof-cpu.dump', interval: 100) do
|
|
12
|
+
100.times {
|
|
13
|
+
Kommando.run "uptime"
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Kommando.puts "stackprof tmp/stackprof-wall.dump --text"
|
|
18
|
+
Kommando.puts "stackprof tmp/stackprof-cpu.dump --text"
|
data/examples/thread_leak.rb
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
require "./lib/kommando"
|
|
2
2
|
|
|
3
|
+
last_k = nil
|
|
3
4
|
100.times do
|
|
4
|
-
|
|
5
|
+
last_k = Kommando.run "uptime", {
|
|
6
|
+
timeout: 0.1
|
|
7
|
+
}
|
|
8
|
+
last_k.when :timeout do
|
|
9
|
+
print "t"
|
|
10
|
+
puts last_k.out
|
|
11
|
+
end
|
|
5
12
|
print "."
|
|
6
13
|
end
|
|
7
|
-
sleep 0.25
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
puts ""
|
|
16
|
+
unless Thread.list.count == 1
|
|
17
|
+
puts Thread.list.map(&:inspect).join("\n")
|
|
18
|
+
puts last_k.out
|
|
19
|
+
raise "Thread leak"
|
|
20
|
+
|
|
21
|
+
end
|
|
10
22
|
puts "ok"
|
data/kommando.gemspec
CHANGED
|
@@ -25,4 +25,6 @@ Gem::Specification.new do |spec|
|
|
|
25
25
|
spec.add_development_dependency "rspec-autotest", "~> 1.0"
|
|
26
26
|
spec.add_development_dependency "ZenTest", "~> 4.11"
|
|
27
27
|
spec.add_development_dependency "byebug"
|
|
28
|
+
spec.add_development_dependency "stackprof"
|
|
29
|
+
spec.add_development_dependency "trapper"
|
|
28
30
|
end
|
data/lib/kommando.rb
CHANGED
|
@@ -88,7 +88,7 @@ class Kommando
|
|
|
88
88
|
begin
|
|
89
89
|
Process.kill('KILL', @pid)
|
|
90
90
|
rescue Errno::ESRCH => ex
|
|
91
|
-
raise ex # see if happens
|
|
91
|
+
#raise ex # see if happens
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
@kill_happened = true
|
|
@@ -145,7 +145,10 @@ class Kommando
|
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
begin
|
|
148
|
+
debug "pty before spawn"
|
|
148
149
|
make_pty_testable.spawn(command, *interpolated_args) do |stdout, stdin, pid|
|
|
150
|
+
debug "pty in spawn"
|
|
151
|
+
|
|
149
152
|
@pid = pid
|
|
150
153
|
|
|
151
154
|
if @output_file
|
|
@@ -153,25 +156,36 @@ class Kommando
|
|
|
153
156
|
stdout_file.sync = true
|
|
154
157
|
end
|
|
155
158
|
|
|
156
|
-
thread_stdin =
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
159
|
+
thread_stdin = nil
|
|
160
|
+
self.when :start do
|
|
161
|
+
thread_stdin = Thread.new do
|
|
162
|
+
while true do
|
|
163
|
+
break if @process_completed
|
|
164
|
+
# c = nil
|
|
165
|
+
# Timeout.timeout(1) do
|
|
166
|
+
c = @stdin.getc
|
|
167
|
+
#end
|
|
168
|
+
|
|
169
|
+
unless c
|
|
170
|
+
sleep 0.01
|
|
171
|
+
next
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
stdin.write c
|
|
168
175
|
end
|
|
169
|
-
|
|
170
|
-
stdin.write c
|
|
171
176
|
end
|
|
172
177
|
end
|
|
173
178
|
|
|
174
|
-
|
|
179
|
+
|
|
180
|
+
debug "thread_stdin started"
|
|
181
|
+
|
|
182
|
+
unless @start_fired
|
|
183
|
+
debug "when :start firing"
|
|
184
|
+
@when.fire :start
|
|
185
|
+
debug "when :start fired"
|
|
186
|
+
else
|
|
187
|
+
debug "when :start NOT fired, as :start has already been fired"
|
|
188
|
+
end
|
|
175
189
|
|
|
176
190
|
if @timeout
|
|
177
191
|
begin
|
|
@@ -186,7 +200,9 @@ class Kommando
|
|
|
186
200
|
process_stdout(pid, stdout, stdout_file)
|
|
187
201
|
end
|
|
188
202
|
@process_completed = true
|
|
189
|
-
|
|
203
|
+
debug "thread_stdin joining"
|
|
204
|
+
thread_stdin.join
|
|
205
|
+
debug "thread_stdin joined"
|
|
190
206
|
stdout_file.close if @output_file
|
|
191
207
|
end
|
|
192
208
|
|
|
@@ -239,6 +255,7 @@ class Kommando
|
|
|
239
255
|
@when.fire :timeout if @timeout_happened
|
|
240
256
|
@when.fire :exit
|
|
241
257
|
|
|
258
|
+
debug "run returning true"
|
|
242
259
|
true
|
|
243
260
|
end
|
|
244
261
|
|
|
@@ -267,7 +284,13 @@ class Kommando
|
|
|
267
284
|
end
|
|
268
285
|
|
|
269
286
|
def wait
|
|
270
|
-
|
|
287
|
+
debug "k.wait starting"
|
|
288
|
+
exited = false
|
|
289
|
+
self.when :exit do
|
|
290
|
+
exited = true
|
|
291
|
+
end
|
|
292
|
+
sleep 0.0001 until exited
|
|
293
|
+
debug "k.wait done"
|
|
271
294
|
end
|
|
272
295
|
|
|
273
296
|
def when(event, &block)
|
|
@@ -276,6 +299,11 @@ class Kommando
|
|
|
276
299
|
|
|
277
300
|
private
|
|
278
301
|
|
|
302
|
+
def debug(msg)
|
|
303
|
+
return unless ENV["DEBUG"]
|
|
304
|
+
print "|#{msg}"
|
|
305
|
+
end
|
|
306
|
+
|
|
279
307
|
def raise_after_callbacks(exception)
|
|
280
308
|
@when.fire :error
|
|
281
309
|
@when.fire :exit
|
|
@@ -289,6 +317,7 @@ class Kommando
|
|
|
289
317
|
def process_stdout(pid, stdout, stdout_file)
|
|
290
318
|
flushing = false
|
|
291
319
|
while true do
|
|
320
|
+
debug "process_stdout started"
|
|
292
321
|
begin
|
|
293
322
|
Process.getpgid(pid)
|
|
294
323
|
rescue Errno::ESRCH => ex
|
data/lib/kommando/buffer.rb
CHANGED
data/lib/kommando/version.rb
CHANGED
data/lib/kommando/when.rb
CHANGED
|
@@ -3,6 +3,7 @@ class Kommando::When
|
|
|
3
3
|
|
|
4
4
|
def initialize
|
|
5
5
|
@whens = {}
|
|
6
|
+
@fired = []
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
def register(event_name, block)
|
|
@@ -14,16 +15,32 @@ class Kommando::When
|
|
|
14
15
|
else
|
|
15
16
|
[block]
|
|
16
17
|
end
|
|
18
|
+
|
|
19
|
+
if @fired.include? event_name_as_sym
|
|
20
|
+
debug "cb firing as #{event_name_as_sym} already fired."
|
|
21
|
+
block.call
|
|
22
|
+
debug "cb fired as #{event_name_as_sym} already fired."
|
|
23
|
+
else
|
|
24
|
+
debug "cb for #{event_name_as_sym} registered, not fired."
|
|
25
|
+
end
|
|
17
26
|
end
|
|
18
27
|
|
|
19
28
|
def fire(event_name)
|
|
20
29
|
event_name_as_sym = event_name.to_sym
|
|
21
30
|
validate_event_name(event_name_as_sym)
|
|
22
31
|
|
|
23
|
-
|
|
32
|
+
@fired << event_name_as_sym
|
|
33
|
+
debug "set #{event_name_as_sym} as fired"
|
|
24
34
|
|
|
25
|
-
blocks
|
|
26
|
-
|
|
35
|
+
if blocks = @whens[event_name]
|
|
36
|
+
debug "firing cbs for #{event_name_as_sym}"
|
|
37
|
+
blocks.each do |block|
|
|
38
|
+
debug "firing cb for #{event_name_as_sym}"
|
|
39
|
+
block.call
|
|
40
|
+
debug "fired cb for #{event_name_as_sym}"
|
|
41
|
+
end
|
|
42
|
+
else
|
|
43
|
+
debug "no cbs for #{event_name_as_sym}"
|
|
27
44
|
end
|
|
28
45
|
end
|
|
29
46
|
|
|
@@ -31,4 +48,9 @@ class Kommando::When
|
|
|
31
48
|
def validate_event_name(event_name_as_sym)
|
|
32
49
|
raise Kommando::Error, "When '#{event_name_as_sym}' is not known." unless VALID_EVENTS.include? event_name_as_sym
|
|
33
50
|
end
|
|
51
|
+
|
|
52
|
+
def debug(msg)
|
|
53
|
+
return unless ENV["DEBUG"]
|
|
54
|
+
print "W#{msg}"
|
|
55
|
+
end
|
|
34
56
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kommando
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.21
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matti Paksula
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2016-
|
|
11
|
+
date: 2016-10-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -94,6 +94,34 @@ dependencies:
|
|
|
94
94
|
- - ">="
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: stackprof
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: trapper
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
97
125
|
description: Great for integration testing.
|
|
98
126
|
email:
|
|
99
127
|
- matti.paksula@iki.fi
|
|
@@ -113,6 +141,7 @@ files:
|
|
|
113
141
|
- Rakefile
|
|
114
142
|
- bin/console
|
|
115
143
|
- bin/e2e
|
|
144
|
+
- bin/loop
|
|
116
145
|
- bin/reinstall
|
|
117
146
|
- bin/release
|
|
118
147
|
- bin/setup
|
|
@@ -127,9 +156,11 @@ files:
|
|
|
127
156
|
- examples/live_output.rb
|
|
128
157
|
- examples/nano.rb
|
|
129
158
|
- examples/nano_match.rb
|
|
159
|
+
- examples/passwd.rb
|
|
130
160
|
- examples/ping.rb
|
|
131
161
|
- examples/shell.rb
|
|
132
162
|
- examples/shorthands.rb
|
|
163
|
+
- examples/stackprof.rb
|
|
133
164
|
- examples/stderr_to_out.rb
|
|
134
165
|
- examples/stdout_to_file.rb
|
|
135
166
|
- examples/thread_leak.rb
|
|
@@ -145,6 +176,7 @@ files:
|
|
|
145
176
|
- lib/kommando/when.rb
|
|
146
177
|
- tests/forever_true.rb
|
|
147
178
|
- tests/forever_uptime.rb
|
|
179
|
+
- tmp/.gitkeep
|
|
148
180
|
homepage: http://github.com/matti/kommando
|
|
149
181
|
licenses:
|
|
150
182
|
- MIT
|