cocaine 0.5.3 → 0.5.4
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 -0
- data/.travis.yml +1 -0
- data/LICENSE +1 -1
- data/NEWS.md +18 -0
- data/README.md +1 -1
- data/cocaine.gemspec +1 -0
- data/lib/cocaine/command_line.rb +25 -12
- data/lib/cocaine/command_line/runners/backticks_runner.rb +1 -1
- data/lib/cocaine/command_line/runners/fake_runner.rb +1 -1
- data/lib/cocaine/command_line/runners/popen_runner.rb +2 -2
- data/lib/cocaine/command_line/runners/posix_runner.rb +20 -15
- data/lib/cocaine/command_line/runners/process_runner.rb +17 -12
- data/lib/cocaine/version.rb +1 -1
- data/spec/cocaine/command_line_spec.rb +3 -118
- data/spec/cocaine/errors_spec.rb +69 -0
- data/spec/cocaine/runners_spec.rb +94 -0
- metadata +33 -44
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 54155863b7f03aa7f26da5dd746c959d9911d4a3
|
|
4
|
+
data.tar.gz: f65332c0a145b19251e71e32e020e507d10151ea
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5787857e52b0a42f9ef27be222ca10a0c6ef6a21915dc6f9f75d56bc9bc6886dcfba7c110dc934a58c1d95252723a3199ceaad8422d63ff0bdc7a629f12eb717
|
|
7
|
+
data.tar.gz: 5d380053dfc1b8774df7966fa2819498619b1e53898145c087d860e647d71be1e2c7cfd974a77cb1148c012fa5b77d5b72d51040ccd094124284cee9cc05e00b
|
data/.travis.yml
CHANGED
data/LICENSE
CHANGED
|
@@ -3,7 +3,7 @@ LICENSE
|
|
|
3
3
|
|
|
4
4
|
The MIT License
|
|
5
5
|
|
|
6
|
-
Copyright (c) 2011-
|
|
6
|
+
Copyright (c) 2011-2014 Jon Yurek and thoughtbot, inc.
|
|
7
7
|
|
|
8
8
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
9
|
of this software and associated documentation files (the "Software"), to deal
|
data/NEWS.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
New for 0.5.4:
|
|
2
|
+
|
|
3
|
+
* Bug Fix: PosixRunner and ProcessRunner respect supplemental paths now.
|
|
4
|
+
|
|
5
|
+
New for 0.5.3:
|
|
6
|
+
|
|
7
|
+
* SECURITY: Fix exploitable bug that could allow arbitrary command execution.
|
|
8
|
+
See CVE-2013-4457 for more details. Thanks to Holger Just for report and fix!
|
|
9
|
+
* Bug fix: Sub-word interpolations can be confused for the longer version
|
|
10
|
+
|
|
11
|
+
New for 0.5.2:
|
|
12
|
+
|
|
13
|
+
* Improvement: Close all the IO objects!
|
|
14
|
+
* Feature: Add an Runner that uses IO.popen, so JRuby can play
|
|
15
|
+
* Improvement: Officially drop Ruby 1.8 support, add Ruby 2.0 support
|
|
16
|
+
* Bug fix: Prevent a crash if no command was actually run
|
|
17
|
+
* Improvement: Add security cautions to the README
|
|
18
|
+
|
|
1
19
|
New for 0.5.1:
|
|
2
20
|
|
|
3
21
|
* Fixed a bug preventing running on 1.8.7 for no good reason.
|
data/README.md
CHANGED
|
@@ -215,7 +215,7 @@ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
|
|
215
215
|
|
|
216
216
|
## License
|
|
217
217
|
|
|
218
|
-
Copyright 2011-
|
|
218
|
+
Copyright 2011-2014 Jon Yurek and thoughtbot, inc. This is free software, and
|
|
219
219
|
may be redistributed under the terms specified in the
|
|
220
220
|
[LICENSE](https://github.com/thoughtbot/cocaine/blob/master/LICENSE)
|
|
221
221
|
file.
|
data/cocaine.gemspec
CHANGED
|
@@ -10,6 +10,7 @@ Gem::Specification.new do |s|
|
|
|
10
10
|
s.homepage = "http://github.com/thoughtbot/cocaine"
|
|
11
11
|
s.summary = "A small library for doing (command) lines"
|
|
12
12
|
s.description = "A small library for doing (command) lines"
|
|
13
|
+
s.license = "MIT"
|
|
13
14
|
|
|
14
15
|
s.files = `git ls-files`.split("\n")
|
|
15
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/lib/cocaine/command_line.rb
CHANGED
|
@@ -23,6 +23,10 @@ module Cocaine
|
|
|
23
23
|
@runner || best_runner
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
def runner_options
|
|
27
|
+
@default_runner_options ||= {}
|
|
28
|
+
end
|
|
29
|
+
|
|
26
30
|
def fake!
|
|
27
31
|
@runner = FakeRunner.new
|
|
28
32
|
end
|
|
@@ -57,12 +61,11 @@ module Cocaine
|
|
|
57
61
|
@swallow_stderr = @options.delete(:swallow_stderr)
|
|
58
62
|
@expected_outcodes = @options.delete(:expected_outcodes) || [0]
|
|
59
63
|
@environment = @options.delete(:environment) || {}
|
|
64
|
+
@runner_options = @options.delete(:runner_options) || {}
|
|
60
65
|
end
|
|
61
66
|
|
|
62
67
|
def command(interpolations = {})
|
|
63
|
-
cmd = []
|
|
64
|
-
cmd << @binary
|
|
65
|
-
cmd << interpolate(@params, interpolations)
|
|
68
|
+
cmd = [@binary, interpolate(@params, interpolations)]
|
|
66
69
|
cmd << bit_bucket if @swallow_stderr
|
|
67
70
|
cmd.join(" ").strip
|
|
68
71
|
end
|
|
@@ -74,14 +77,16 @@ module Cocaine
|
|
|
74
77
|
full_command = command(interpolations)
|
|
75
78
|
log("#{colored("Command")} :: #{full_command}")
|
|
76
79
|
output = execute(full_command)
|
|
77
|
-
rescue Errno::ENOENT
|
|
78
|
-
raise Cocaine::CommandNotFoundError
|
|
80
|
+
rescue Errno::ENOENT => e
|
|
81
|
+
raise Cocaine::CommandNotFoundError, e.message
|
|
79
82
|
ensure
|
|
80
83
|
@exit_status = $?.exitstatus if $?.respond_to?(:exitstatus)
|
|
81
84
|
end
|
|
85
|
+
|
|
82
86
|
if @exit_status == 127
|
|
83
87
|
raise Cocaine::CommandNotFoundError
|
|
84
88
|
end
|
|
89
|
+
|
|
85
90
|
unless @expected_outcodes.include?(@exit_status)
|
|
86
91
|
message = [
|
|
87
92
|
"Command '#{full_command}' returned #{@exit_status}. Expected #{@expected_outcodes.join(", ")}",
|
|
@@ -114,27 +119,35 @@ module Cocaine
|
|
|
114
119
|
end
|
|
115
120
|
|
|
116
121
|
def execute(command)
|
|
117
|
-
runner.call(command, environment)
|
|
122
|
+
runner.call(command, environment, runner_options)
|
|
118
123
|
end
|
|
119
124
|
|
|
120
125
|
def environment
|
|
121
126
|
self.class.environment.merge(@environment)
|
|
122
127
|
end
|
|
123
128
|
|
|
129
|
+
def runner_options
|
|
130
|
+
self.class.runner_options.merge(@runner_options)
|
|
131
|
+
end
|
|
132
|
+
|
|
124
133
|
def interpolate(pattern, interpolations)
|
|
125
134
|
interpolations = stringify_keys(interpolations)
|
|
126
135
|
pattern.gsub(/:\{?(\w+)\b\}?/) do |match|
|
|
127
136
|
key = match.tr(":{}", "")
|
|
128
|
-
interpolations.key?(key)
|
|
137
|
+
if interpolations.key?(key)
|
|
138
|
+
shell_quote_all_values(interpolations[key])
|
|
139
|
+
else
|
|
140
|
+
match
|
|
141
|
+
end
|
|
129
142
|
end
|
|
130
143
|
end
|
|
131
144
|
|
|
132
145
|
def stringify_keys(hash)
|
|
133
|
-
hash
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
146
|
+
Hash[hash.map{ |k, v| [k.to_s, v] }]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def shell_quote_all_values(values)
|
|
150
|
+
Array(values).map(&method(:shell_quote)).join(" ")
|
|
138
151
|
end
|
|
139
152
|
|
|
140
153
|
def shell_quote(string)
|
|
@@ -11,9 +11,9 @@ module Cocaine
|
|
|
11
11
|
self.class.supported?
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def call(command, env = {})
|
|
14
|
+
def call(command, env = {}, options = {})
|
|
15
15
|
with_modified_environment(env) do
|
|
16
|
-
IO.popen(command, "r") do |pipe|
|
|
16
|
+
IO.popen(command, "r", options) do |pipe|
|
|
17
17
|
pipe.read
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -4,12 +4,10 @@ module Cocaine
|
|
|
4
4
|
class CommandLine
|
|
5
5
|
class PosixRunner
|
|
6
6
|
def self.available?
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
false
|
|
12
|
-
end
|
|
7
|
+
require 'posix/spawn'
|
|
8
|
+
true
|
|
9
|
+
rescue LoadError
|
|
10
|
+
false
|
|
13
11
|
end
|
|
14
12
|
|
|
15
13
|
def self.supported?
|
|
@@ -20,17 +18,20 @@ module Cocaine
|
|
|
20
18
|
self.class.supported?
|
|
21
19
|
end
|
|
22
20
|
|
|
23
|
-
def call(command, env = {})
|
|
21
|
+
def call(command, env = {}, options = {})
|
|
24
22
|
input, output = IO.pipe
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
result
|
|
23
|
+
options[:out] = output
|
|
24
|
+
with_modified_environment(env) do
|
|
25
|
+
pid = spawn(env, command, options)
|
|
26
|
+
output.close
|
|
27
|
+
result = ""
|
|
28
|
+
while partial_result = input.read(8192)
|
|
29
|
+
result << partial_result
|
|
30
|
+
end
|
|
31
|
+
waitpid(pid)
|
|
32
|
+
input.close
|
|
33
|
+
result
|
|
30
34
|
end
|
|
31
|
-
waitpid(pid)
|
|
32
|
-
input.close
|
|
33
|
-
result
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
private
|
|
@@ -43,6 +44,10 @@ module Cocaine
|
|
|
43
44
|
Process.waitpid(pid)
|
|
44
45
|
end
|
|
45
46
|
|
|
47
|
+
def with_modified_environment(env, &block)
|
|
48
|
+
ClimateControl.modify(env, &block)
|
|
49
|
+
end
|
|
50
|
+
|
|
46
51
|
end
|
|
47
52
|
end
|
|
48
53
|
end
|
|
@@ -15,14 +15,17 @@ module Cocaine
|
|
|
15
15
|
self.class.supported?
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def call(command, env = {})
|
|
18
|
+
def call(command, env = {}, options = {})
|
|
19
19
|
input, output = IO.pipe
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
options[:out] = output
|
|
21
|
+
with_modified_environment(env) do
|
|
22
|
+
pid = spawn(env, command, options)
|
|
23
|
+
output.close
|
|
24
|
+
result = input.read
|
|
25
|
+
waitpid(pid)
|
|
26
|
+
input.close
|
|
27
|
+
result
|
|
28
|
+
end
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
private
|
|
@@ -32,11 +35,13 @@ module Cocaine
|
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
def waitpid(pid)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
Process.waitpid(pid)
|
|
39
|
+
rescue Errno::ECHILD
|
|
40
|
+
# In JRuby, waiting on a finished pid raises.
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def with_modified_environment(env, &block)
|
|
44
|
+
ClimateControl.modify(env, &block)
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
end
|
data/lib/cocaine/version.rb
CHANGED
|
@@ -78,13 +78,9 @@ describe Cocaine::CommandLine do
|
|
|
78
78
|
command.run(:hello_world => "Hello, world").should match(/Hello, world/)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
it "
|
|
82
|
-
|
|
83
|
-
command
|
|
84
|
-
command.stubs(:command).raises("An Error")
|
|
85
|
-
|
|
86
|
-
lambda{ command.run }.should raise_error("An Error")
|
|
87
|
-
command.exit_status.should be_nil
|
|
81
|
+
it "interpolates any Array arguments when running a command" do
|
|
82
|
+
command = Cocaine::CommandLine.new("echo", "Hello :worlds and :dwarfs")
|
|
83
|
+
command.command(:worlds => %w[mercury venus earth], :dwarfs => "pluto").should == "echo Hello 'mercury' 'venus' 'earth' and 'pluto'"
|
|
88
84
|
end
|
|
89
85
|
|
|
90
86
|
it "quotes command line options differently if we're on windows" do
|
|
@@ -156,53 +152,6 @@ describe Cocaine::CommandLine do
|
|
|
156
152
|
end
|
|
157
153
|
end
|
|
158
154
|
|
|
159
|
-
it "raises a CommandLineError if the result code from the command isn't expected" do
|
|
160
|
-
cmd = Cocaine::CommandLine.new("convert", "a.jpg b.png", :swallow_stderr => false)
|
|
161
|
-
cmd.stubs(:execute).with("convert a.jpg b.png").returns(:correct_value)
|
|
162
|
-
with_exitstatus_returning(1) do
|
|
163
|
-
lambda do
|
|
164
|
-
cmd.run
|
|
165
|
-
end.should raise_error(Cocaine::CommandLineError)
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
it "does not raise if the result code is expected, even if nonzero" do
|
|
170
|
-
cmd = Cocaine::CommandLine.new("convert",
|
|
171
|
-
"a.jpg b.png",
|
|
172
|
-
:expected_outcodes => [0, 1],
|
|
173
|
-
:swallow_stderr => false)
|
|
174
|
-
cmd.stubs(:execute).with("convert a.jpg b.png").returns(:correct_value)
|
|
175
|
-
with_exitstatus_returning(1) do
|
|
176
|
-
lambda do
|
|
177
|
-
cmd.run
|
|
178
|
-
end.should_not raise_error
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
it "adds command output to exception message if the result code is nonzero" do
|
|
183
|
-
cmd = Cocaine::CommandLine.new("convert",
|
|
184
|
-
"a.jpg b.png",
|
|
185
|
-
:swallow_stderr => false)
|
|
186
|
-
error_output = "Error 315"
|
|
187
|
-
cmd.stubs(:execute).with("convert a.jpg b.png").returns(error_output)
|
|
188
|
-
with_exitstatus_returning(1) do
|
|
189
|
-
begin
|
|
190
|
-
cmd.run
|
|
191
|
-
rescue Cocaine::ExitStatusError => e
|
|
192
|
-
e.message.should =~ /#{error_output}/
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
it "should keep result code in #exitstatus" do
|
|
198
|
-
cmd = Cocaine::CommandLine.new("convert")
|
|
199
|
-
cmd.stubs(:execute).with("convert").returns(:correct_value)
|
|
200
|
-
with_exitstatus_returning(1) do
|
|
201
|
-
cmd.run rescue nil
|
|
202
|
-
end
|
|
203
|
-
cmd.exit_status.should == 1
|
|
204
|
-
end
|
|
205
|
-
|
|
206
155
|
it "detects that the system is unix" do
|
|
207
156
|
Cocaine::CommandLine.new("convert").should be_unix
|
|
208
157
|
end
|
|
@@ -249,68 +198,4 @@ describe Cocaine::CommandLine do
|
|
|
249
198
|
cmd = Cocaine::CommandLine.new("echo", "'Logging!'", :logger => nil)
|
|
250
199
|
lambda { cmd.run }.should_not raise_error
|
|
251
200
|
end
|
|
252
|
-
|
|
253
|
-
describe "command execution" do
|
|
254
|
-
it "uses the BackticksRunner by default" do
|
|
255
|
-
Cocaine::CommandLine::ProcessRunner.stubs(:supported?).returns(false)
|
|
256
|
-
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(false)
|
|
257
|
-
|
|
258
|
-
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
259
|
-
|
|
260
|
-
cmd.runner.class.should == Cocaine::CommandLine::BackticksRunner
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
it "uses the ProcessRunner on 1.9 and it's available" do
|
|
264
|
-
Cocaine::CommandLine::ProcessRunner.stubs(:supported?).returns(true)
|
|
265
|
-
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(false)
|
|
266
|
-
|
|
267
|
-
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
268
|
-
cmd.runner.class.should == Cocaine::CommandLine::ProcessRunner
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
it "uses the PosixRunner if the PosixRunner is available" do
|
|
272
|
-
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(true)
|
|
273
|
-
|
|
274
|
-
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
275
|
-
cmd.runner.class.should == Cocaine::CommandLine::PosixRunner
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
it "uses the BackticksRunner if the PosixRunner is available, but we told it to use Backticks all the time" do
|
|
279
|
-
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(true)
|
|
280
|
-
Cocaine::CommandLine.runner = Cocaine::CommandLine::BackticksRunner.new
|
|
281
|
-
|
|
282
|
-
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
283
|
-
cmd.runner.class.should == Cocaine::CommandLine::BackticksRunner
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
it "uses the BackticksRunner if the PosixRunner is available, but we told it to use Backticks" do
|
|
287
|
-
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(true)
|
|
288
|
-
|
|
289
|
-
cmd = Cocaine::CommandLine.new("echo", "hello", :runner => Cocaine::CommandLine::BackticksRunner.new)
|
|
290
|
-
cmd.runner.class.should == Cocaine::CommandLine::BackticksRunner
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
it "can go into 'Fake' mode" do
|
|
294
|
-
Cocaine::CommandLine.fake!
|
|
295
|
-
|
|
296
|
-
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
297
|
-
cmd.runner.class.should eq Cocaine::CommandLine::FakeRunner
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
it "can turn off Fake mode" do
|
|
301
|
-
Cocaine::CommandLine.fake!
|
|
302
|
-
Cocaine::CommandLine.unfake!
|
|
303
|
-
|
|
304
|
-
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
305
|
-
cmd.runner.class.should_not eq Cocaine::CommandLine::FakeRunner
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
it "can use a FakeRunner even if not in Fake mode" do
|
|
309
|
-
Cocaine::CommandLine.unfake!
|
|
310
|
-
|
|
311
|
-
cmd = Cocaine::CommandLine.new("echo", "hello", :runner => Cocaine::CommandLine::FakeRunner.new)
|
|
312
|
-
cmd.runner.class.should eq Cocaine::CommandLine::FakeRunner
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
end
|
|
316
201
|
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "When an error happens" do
|
|
4
|
+
it "raises a CommandLineError if the result code from the command isn't expected" do
|
|
5
|
+
cmd = Cocaine::CommandLine.new("convert", "a.jpg b.png", :swallow_stderr => false)
|
|
6
|
+
cmd.stubs(:execute).with("convert a.jpg b.png").returns(:correct_value)
|
|
7
|
+
with_exitstatus_returning(1) do
|
|
8
|
+
lambda do
|
|
9
|
+
cmd.run
|
|
10
|
+
end.should raise_error(Cocaine::CommandLineError)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "does not raise if the result code is expected, even if nonzero" do
|
|
15
|
+
cmd = Cocaine::CommandLine.new("convert",
|
|
16
|
+
"a.jpg b.png",
|
|
17
|
+
:expected_outcodes => [0, 1],
|
|
18
|
+
:swallow_stderr => false)
|
|
19
|
+
cmd.stubs(:execute).with("convert a.jpg b.png").returns(:correct_value)
|
|
20
|
+
with_exitstatus_returning(1) do
|
|
21
|
+
lambda do
|
|
22
|
+
cmd.run
|
|
23
|
+
end.should_not raise_error
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "adds command output to exception message if the result code is nonzero" do
|
|
28
|
+
cmd = Cocaine::CommandLine.new("convert",
|
|
29
|
+
"a.jpg b.png",
|
|
30
|
+
:swallow_stderr => false)
|
|
31
|
+
error_output = "Error 315"
|
|
32
|
+
cmd.stubs(:execute).with("convert a.jpg b.png").returns(error_output)
|
|
33
|
+
with_exitstatus_returning(1) do
|
|
34
|
+
begin
|
|
35
|
+
cmd.run
|
|
36
|
+
rescue Cocaine::ExitStatusError => e
|
|
37
|
+
e.message.should =~ /#{error_output}/
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'passes error message to the exception when command fails with Errno::ENOENT' do
|
|
43
|
+
cmd = Cocaine::CommandLine.new('test', '')
|
|
44
|
+
cmd.stubs(:execute).with('test').raises(Errno::ENOENT.new("not found"))
|
|
45
|
+
begin
|
|
46
|
+
cmd.run
|
|
47
|
+
rescue Cocaine::CommandNotFoundError => e
|
|
48
|
+
expect(e.message).to eq 'No such file or directory - not found'
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should keep result code in #exitstatus" do
|
|
53
|
+
cmd = Cocaine::CommandLine.new("convert")
|
|
54
|
+
cmd.stubs(:execute).with("convert").returns(:correct_value)
|
|
55
|
+
with_exitstatus_returning(1) do
|
|
56
|
+
cmd.run rescue nil
|
|
57
|
+
end
|
|
58
|
+
cmd.exit_status.should == 1
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "does not blow up if running the command errored before the actual execution" do
|
|
62
|
+
assuming_no_processes_have_been_run
|
|
63
|
+
command = Cocaine::CommandLine.new("echo", ":hello_world")
|
|
64
|
+
command.stubs(:command).raises("An Error")
|
|
65
|
+
|
|
66
|
+
lambda{ command.run }.should raise_error("An Error")
|
|
67
|
+
command.exit_status.should be_nil
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "When picking a Runner" do
|
|
4
|
+
it "uses the BackticksRunner by default" do
|
|
5
|
+
Cocaine::CommandLine::ProcessRunner.stubs(:supported?).returns(false)
|
|
6
|
+
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(false)
|
|
7
|
+
|
|
8
|
+
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
9
|
+
|
|
10
|
+
cmd.runner.class.should == Cocaine::CommandLine::BackticksRunner
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "uses the ProcessRunner on 1.9 and it's available" do
|
|
14
|
+
Cocaine::CommandLine::ProcessRunner.stubs(:supported?).returns(true)
|
|
15
|
+
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(false)
|
|
16
|
+
|
|
17
|
+
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
18
|
+
cmd.runner.class.should == Cocaine::CommandLine::ProcessRunner
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "uses the PosixRunner if the PosixRunner is available" do
|
|
22
|
+
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(true)
|
|
23
|
+
|
|
24
|
+
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
25
|
+
cmd.runner.class.should == Cocaine::CommandLine::PosixRunner
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "uses the BackticksRunner if the PosixRunner is available, but we told it to use Backticks all the time" do
|
|
29
|
+
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(true)
|
|
30
|
+
Cocaine::CommandLine.runner = Cocaine::CommandLine::BackticksRunner.new
|
|
31
|
+
|
|
32
|
+
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
33
|
+
cmd.runner.class.should == Cocaine::CommandLine::BackticksRunner
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "uses the BackticksRunner if the PosixRunner is available, but we told it to use Backticks" do
|
|
37
|
+
Cocaine::CommandLine::PosixRunner.stubs(:supported?).returns(true)
|
|
38
|
+
|
|
39
|
+
cmd = Cocaine::CommandLine.new("echo", "hello", :runner => Cocaine::CommandLine::BackticksRunner.new)
|
|
40
|
+
cmd.runner.class.should == Cocaine::CommandLine::BackticksRunner
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "can go into 'Fake' mode" do
|
|
44
|
+
Cocaine::CommandLine.fake!
|
|
45
|
+
|
|
46
|
+
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
47
|
+
cmd.runner.class.should eq Cocaine::CommandLine::FakeRunner
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "can turn off Fake mode" do
|
|
51
|
+
Cocaine::CommandLine.fake!
|
|
52
|
+
Cocaine::CommandLine.unfake!
|
|
53
|
+
|
|
54
|
+
cmd = Cocaine::CommandLine.new("echo", "hello")
|
|
55
|
+
cmd.runner.class.should_not eq Cocaine::CommandLine::FakeRunner
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "can use a FakeRunner even if not in Fake mode" do
|
|
59
|
+
Cocaine::CommandLine.unfake!
|
|
60
|
+
|
|
61
|
+
cmd = Cocaine::CommandLine.new("echo", "hello", :runner => Cocaine::CommandLine::FakeRunner.new)
|
|
62
|
+
cmd.runner.class.should eq Cocaine::CommandLine::FakeRunner
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe 'When running an executable in the supplemental path' do
|
|
67
|
+
before do
|
|
68
|
+
path = Pathname.new(File.dirname(__FILE__)) + '..' + 'support'
|
|
69
|
+
File.open(path + 'ls', 'w'){|f| f.puts "#!/bin/sh\necho overridden-ls\n" }
|
|
70
|
+
FileUtils.chmod(0755, path + 'ls')
|
|
71
|
+
Cocaine::CommandLine.path = path
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
after do
|
|
75
|
+
FileUtils.rm_f(Cocaine::CommandLine.path + 'ls')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
[
|
|
79
|
+
Cocaine::CommandLine::BackticksRunner,
|
|
80
|
+
Cocaine::CommandLine::PopenRunner,
|
|
81
|
+
Cocaine::CommandLine::PosixRunner,
|
|
82
|
+
Cocaine::CommandLine::ProcessRunner
|
|
83
|
+
].each do |runner_class|
|
|
84
|
+
describe runner_class do
|
|
85
|
+
describe '#run' do
|
|
86
|
+
it 'finds the correct executable' do
|
|
87
|
+
Cocaine::CommandLine.runner = runner_class.new
|
|
88
|
+
result = Cocaine::CommandLine.new('ls').run
|
|
89
|
+
expect(result.strip).to eq('overridden-ls')
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
metadata
CHANGED
|
@@ -1,138 +1,123 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cocaine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 0.5.4
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
7
|
- Jon Yurek
|
|
9
8
|
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 2014-03-28 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: climate_control
|
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
|
17
|
-
none: false
|
|
18
16
|
requirements:
|
|
19
|
-
- -
|
|
17
|
+
- - ">="
|
|
20
18
|
- !ruby/object:Gem::Version
|
|
21
19
|
version: 0.0.3
|
|
22
|
-
- - <
|
|
20
|
+
- - "<"
|
|
23
21
|
- !ruby/object:Gem::Version
|
|
24
22
|
version: '1.0'
|
|
25
23
|
type: :runtime
|
|
26
24
|
prerelease: false
|
|
27
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
28
|
-
none: false
|
|
29
26
|
requirements:
|
|
30
|
-
- -
|
|
27
|
+
- - ">="
|
|
31
28
|
- !ruby/object:Gem::Version
|
|
32
29
|
version: 0.0.3
|
|
33
|
-
- - <
|
|
30
|
+
- - "<"
|
|
34
31
|
- !ruby/object:Gem::Version
|
|
35
32
|
version: '1.0'
|
|
36
33
|
- !ruby/object:Gem::Dependency
|
|
37
34
|
name: rspec
|
|
38
35
|
requirement: !ruby/object:Gem::Requirement
|
|
39
|
-
none: false
|
|
40
36
|
requirements:
|
|
41
|
-
- -
|
|
37
|
+
- - ">="
|
|
42
38
|
- !ruby/object:Gem::Version
|
|
43
39
|
version: '0'
|
|
44
40
|
type: :development
|
|
45
41
|
prerelease: false
|
|
46
42
|
version_requirements: !ruby/object:Gem::Requirement
|
|
47
|
-
none: false
|
|
48
43
|
requirements:
|
|
49
|
-
- -
|
|
44
|
+
- - ">="
|
|
50
45
|
- !ruby/object:Gem::Version
|
|
51
46
|
version: '0'
|
|
52
47
|
- !ruby/object:Gem::Dependency
|
|
53
48
|
name: bourne
|
|
54
49
|
requirement: !ruby/object:Gem::Requirement
|
|
55
|
-
none: false
|
|
56
50
|
requirements:
|
|
57
|
-
- -
|
|
51
|
+
- - ">="
|
|
58
52
|
- !ruby/object:Gem::Version
|
|
59
53
|
version: '0'
|
|
60
54
|
type: :development
|
|
61
55
|
prerelease: false
|
|
62
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
63
|
-
none: false
|
|
64
57
|
requirements:
|
|
65
|
-
- -
|
|
58
|
+
- - ">="
|
|
66
59
|
- !ruby/object:Gem::Version
|
|
67
60
|
version: '0'
|
|
68
61
|
- !ruby/object:Gem::Dependency
|
|
69
62
|
name: mocha
|
|
70
63
|
requirement: !ruby/object:Gem::Requirement
|
|
71
|
-
none: false
|
|
72
64
|
requirements:
|
|
73
|
-
- -
|
|
65
|
+
- - ">="
|
|
74
66
|
- !ruby/object:Gem::Version
|
|
75
67
|
version: '0'
|
|
76
68
|
type: :development
|
|
77
69
|
prerelease: false
|
|
78
70
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
none: false
|
|
80
71
|
requirements:
|
|
81
|
-
- -
|
|
72
|
+
- - ">="
|
|
82
73
|
- !ruby/object:Gem::Version
|
|
83
74
|
version: '0'
|
|
84
75
|
- !ruby/object:Gem::Dependency
|
|
85
76
|
name: rake
|
|
86
77
|
requirement: !ruby/object:Gem::Requirement
|
|
87
|
-
none: false
|
|
88
78
|
requirements:
|
|
89
|
-
- -
|
|
79
|
+
- - ">="
|
|
90
80
|
- !ruby/object:Gem::Version
|
|
91
81
|
version: '0'
|
|
92
82
|
type: :development
|
|
93
83
|
prerelease: false
|
|
94
84
|
version_requirements: !ruby/object:Gem::Requirement
|
|
95
|
-
none: false
|
|
96
85
|
requirements:
|
|
97
|
-
- -
|
|
86
|
+
- - ">="
|
|
98
87
|
- !ruby/object:Gem::Version
|
|
99
88
|
version: '0'
|
|
100
89
|
- !ruby/object:Gem::Dependency
|
|
101
90
|
name: activesupport
|
|
102
91
|
requirement: !ruby/object:Gem::Requirement
|
|
103
|
-
none: false
|
|
104
92
|
requirements:
|
|
105
|
-
- -
|
|
93
|
+
- - ">="
|
|
106
94
|
- !ruby/object:Gem::Version
|
|
107
95
|
version: 3.0.0
|
|
108
|
-
- - <
|
|
96
|
+
- - "<"
|
|
109
97
|
- !ruby/object:Gem::Version
|
|
110
98
|
version: '5.0'
|
|
111
99
|
type: :development
|
|
112
100
|
prerelease: false
|
|
113
101
|
version_requirements: !ruby/object:Gem::Requirement
|
|
114
|
-
none: false
|
|
115
102
|
requirements:
|
|
116
|
-
- -
|
|
103
|
+
- - ">="
|
|
117
104
|
- !ruby/object:Gem::Version
|
|
118
105
|
version: 3.0.0
|
|
119
|
-
- - <
|
|
106
|
+
- - "<"
|
|
120
107
|
- !ruby/object:Gem::Version
|
|
121
108
|
version: '5.0'
|
|
122
109
|
- !ruby/object:Gem::Dependency
|
|
123
110
|
name: pry
|
|
124
111
|
requirement: !ruby/object:Gem::Requirement
|
|
125
|
-
none: false
|
|
126
112
|
requirements:
|
|
127
|
-
- -
|
|
113
|
+
- - ">="
|
|
128
114
|
- !ruby/object:Gem::Version
|
|
129
115
|
version: '0'
|
|
130
116
|
type: :development
|
|
131
117
|
prerelease: false
|
|
132
118
|
version_requirements: !ruby/object:Gem::Requirement
|
|
133
|
-
none: false
|
|
134
119
|
requirements:
|
|
135
|
-
- -
|
|
120
|
+
- - ">="
|
|
136
121
|
- !ruby/object:Gem::Version
|
|
137
122
|
version: '0'
|
|
138
123
|
description: A small library for doing (command) lines
|
|
@@ -141,8 +126,8 @@ executables: []
|
|
|
141
126
|
extensions: []
|
|
142
127
|
extra_rdoc_files: []
|
|
143
128
|
files:
|
|
144
|
-
- .gitignore
|
|
145
|
-
- .travis.yml
|
|
129
|
+
- ".gitignore"
|
|
130
|
+
- ".travis.yml"
|
|
146
131
|
- GOALS
|
|
147
132
|
- Gemfile
|
|
148
133
|
- LICENSE
|
|
@@ -166,6 +151,8 @@ files:
|
|
|
166
151
|
- spec/cocaine/command_line/runners/posix_runner_spec.rb
|
|
167
152
|
- spec/cocaine/command_line/runners/process_runner_spec.rb
|
|
168
153
|
- spec/cocaine/command_line_spec.rb
|
|
154
|
+
- spec/cocaine/errors_spec.rb
|
|
155
|
+
- spec/cocaine/runners_spec.rb
|
|
169
156
|
- spec/spec_helper.rb
|
|
170
157
|
- spec/support/fake_logger.rb
|
|
171
158
|
- spec/support/nonblocking_examples.rb
|
|
@@ -173,28 +160,28 @@ files:
|
|
|
173
160
|
- spec/support/unsetting_exitstatus.rb
|
|
174
161
|
- spec/support/with_exitstatus.rb
|
|
175
162
|
homepage: http://github.com/thoughtbot/cocaine
|
|
176
|
-
licenses:
|
|
163
|
+
licenses:
|
|
164
|
+
- MIT
|
|
165
|
+
metadata: {}
|
|
177
166
|
post_install_message:
|
|
178
167
|
rdoc_options: []
|
|
179
168
|
require_paths:
|
|
180
169
|
- lib
|
|
181
170
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
182
|
-
none: false
|
|
183
171
|
requirements:
|
|
184
|
-
- -
|
|
172
|
+
- - ">="
|
|
185
173
|
- !ruby/object:Gem::Version
|
|
186
174
|
version: '0'
|
|
187
175
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
|
-
none: false
|
|
189
176
|
requirements:
|
|
190
|
-
- -
|
|
177
|
+
- - ">="
|
|
191
178
|
- !ruby/object:Gem::Version
|
|
192
179
|
version: '0'
|
|
193
180
|
requirements: []
|
|
194
181
|
rubyforge_project:
|
|
195
|
-
rubygems_version:
|
|
182
|
+
rubygems_version: 2.2.2
|
|
196
183
|
signing_key:
|
|
197
|
-
specification_version:
|
|
184
|
+
specification_version: 4
|
|
198
185
|
summary: A small library for doing (command) lines
|
|
199
186
|
test_files:
|
|
200
187
|
- spec/cocaine/command_line/runners/backticks_runner_spec.rb
|
|
@@ -203,6 +190,8 @@ test_files:
|
|
|
203
190
|
- spec/cocaine/command_line/runners/posix_runner_spec.rb
|
|
204
191
|
- spec/cocaine/command_line/runners/process_runner_spec.rb
|
|
205
192
|
- spec/cocaine/command_line_spec.rb
|
|
193
|
+
- spec/cocaine/errors_spec.rb
|
|
194
|
+
- spec/cocaine/runners_spec.rb
|
|
206
195
|
- spec/spec_helper.rb
|
|
207
196
|
- spec/support/fake_logger.rb
|
|
208
197
|
- spec/support/nonblocking_examples.rb
|