kommando 0.0.19 → 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- 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
|