cocaine 0.5.8 → 0.6.0.alpha
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 +5 -5
- data/README.md +13 -197
- data/cocaine.gemspec +1 -1
- data/lib/cocaine.rb +9 -9
- data/lib/cocaine/version.rb +1 -2
- metadata +10 -27
- data/lib/cocaine/command_line.rb +0 -197
- data/lib/cocaine/command_line/multi_pipe.rb +0 -50
- data/lib/cocaine/command_line/output.rb +0 -12
- data/lib/cocaine/command_line/runners.rb +0 -7
- data/lib/cocaine/command_line/runners/backticks_runner.rb +0 -30
- data/lib/cocaine/command_line/runners/fake_runner.rb +0 -30
- data/lib/cocaine/command_line/runners/popen_runner.rb +0 -29
- data/lib/cocaine/command_line/runners/posix_runner.rb +0 -49
- data/lib/cocaine/command_line/runners/process_runner.rb +0 -41
- data/lib/cocaine/exceptions.rb +0 -8
- data/lib/cocaine/os_detector.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 42a6b84941e1f52afbc43e5b0fff0dc534668c516427ba7dea6733082ee5f978
|
4
|
+
data.tar.gz: 58ef2f4fc4d3d85956500094a1727f61ace61e11f306704b15abd20ddacce8ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd079d559e02c3a1d53c1df45cba1cb9e88dce214cf3f6f92dd9a459174bb9505fc534ea7321cfbc2ff2200c6ab13aad2de7cc0c114f4bf50496cec806bcf74e
|
7
|
+
data.tar.gz: 9fd6add73507e9ef1139b05bfe3c7f53eaee262e5b366793f64addc9fdccdf286707ea68168ae746ae945e785332c6861be74d901ed5c8b23c061c5ea55c126b
|
data/README.md
CHANGED
@@ -1,215 +1,31 @@
|
|
1
|
-
# Cocaine
|
1
|
+
# Cocaine has been renamed to Terrapin
|
2
2
|
|
3
|
-
|
3
|
+
Please track further development on (the Terrapin project
|
4
|
+
page)[http://github.com/thoughtbot/terrapin].
|
4
5
|
|
5
|
-
|
6
|
+
The final version of this gem simply requires Terrapin. It should not function any
|
7
|
+
differently from previous versions.
|
6
8
|
|
7
|
-
##
|
9
|
+
## Upgrading to Terrapin
|
8
10
|
|
9
|
-
|
11
|
+
Upgrading to Terrapin is expected to be as simple as replacing the `Cocaine`
|
12
|
+
constant with `Terrapin`. That is
|
10
13
|
|
11
14
|
```ruby
|
12
|
-
|
13
|
-
line.command # => "echo hello 'world'"
|
14
|
-
line.run # => "hello world\n"
|
15
|
+
Cocaine::CommandLine.new("echo", "hello")
|
15
16
|
```
|
16
17
|
|
17
|
-
|
18
|
+
should become
|
18
19
|
|
19
20
|
```ruby
|
20
|
-
|
21
|
-
line.command(in: "omg.jpg",
|
22
|
-
resolution: "32x32",
|
23
|
-
out: "omg_thumb.jpg")
|
24
|
-
# => "convert 'omg.jpg' -scale '32x32' 'omg_thumb.jpg'"
|
21
|
+
Terrapin::CommandLine.new("echo", "hello")
|
25
22
|
```
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
```ruby
|
30
|
-
line = Cocaine::CommandLine.new("cat", ":file")
|
31
|
-
line.command(file: "haha`rm -rf /`.txt") # => "cat 'haha`rm -rf /`.txt'"
|
32
|
-
|
33
|
-
line = Cocaine::CommandLine.new("cat", ":file")
|
34
|
-
line.command(file: "ohyeah?'`rm -rf /`.ha!") # => "cat 'ohyeah?'\\''`rm -rf /`.ha!'"
|
35
|
-
```
|
36
|
-
|
37
|
-
NOTE: It only does that for arguments interpolated via `run`, NOT arguments
|
38
|
-
passed into `new` (see 'Security' below):
|
39
|
-
|
40
|
-
```ruby
|
41
|
-
line = Cocaine::CommandLine.new("echo", "haha`whoami`")
|
42
|
-
line.command # => "echo haha`whoami`"
|
43
|
-
line.run # => "hahawebserver"
|
44
|
-
```
|
45
|
-
|
46
|
-
You can ignore the result:
|
47
|
-
|
48
|
-
```ruby
|
49
|
-
line = Cocaine::CommandLine.new("noisy", "--extra-verbose", swallow_stderr: true)
|
50
|
-
line.command # => "noisy --extra-verbose 2>/dev/null"
|
51
|
-
|
52
|
-
# ... and on Windows...
|
53
|
-
line.command # => "noisy --extra-verbose 2>NUL"
|
54
|
-
```
|
55
|
-
|
56
|
-
If your command errors, you get an exception:
|
57
|
-
|
58
|
-
```ruby
|
59
|
-
line = Cocaine::CommandLine.new("git", "commit")
|
60
|
-
begin
|
61
|
-
line.run
|
62
|
-
rescue Cocaine::ExitStatusError => e
|
63
|
-
e.message # => "Command 'git commit' returned 1. Expected 0"
|
64
|
-
end
|
65
|
-
```
|
66
|
-
|
67
|
-
If your command might return something non-zero, and you expect that, it's cool:
|
68
|
-
|
69
|
-
```ruby
|
70
|
-
line = Cocaine::CommandLine.new("/usr/bin/false", "", expected_outcodes: [0, 1])
|
71
|
-
begin
|
72
|
-
line.run
|
73
|
-
rescue Cocaine::ExitStatusError => e
|
74
|
-
# => You never get here!
|
75
|
-
end
|
76
|
-
```
|
77
|
-
|
78
|
-
You don't have the command? You get an exception:
|
79
|
-
|
80
|
-
```ruby
|
81
|
-
line = Cocaine::CommandLine.new("lolwut")
|
82
|
-
begin
|
83
|
-
line.run
|
84
|
-
rescue Cocaine::CommandNotFoundError => e
|
85
|
-
e # => the command isn't in the $PATH for this process.
|
86
|
-
end
|
87
|
-
```
|
88
|
-
|
89
|
-
But don't fear, you can specify where to look for the command:
|
90
|
-
|
91
|
-
```ruby
|
92
|
-
Cocaine::CommandLine.path = "/opt/bin"
|
93
|
-
line = Cocaine::CommandLine.new("lolwut")
|
94
|
-
line.command # => "lolwut", but it looks in /opt/bin for it.
|
95
|
-
```
|
96
|
-
|
97
|
-
You can even give it a bunch of places to look:
|
98
|
-
|
99
|
-
```ruby
|
100
|
-
FileUtils.rm("/opt/bin/lolwut")
|
101
|
-
File.open('/usr/local/bin/lolwut') {|f| f.write('echo Hello') }
|
102
|
-
Cocaine::CommandLine.path = ["/opt/bin", "/usr/local/bin"]
|
103
|
-
line = Cocaine::CommandLine.new("lolwut")
|
104
|
-
line.run # => prints 'Hello', because it searches the path
|
105
|
-
```
|
106
|
-
|
107
|
-
Or just put it in the command:
|
108
|
-
|
109
|
-
```ruby
|
110
|
-
line = Cocaine::CommandLine.new("/opt/bin/lolwut")
|
111
|
-
line.command # => "/opt/bin/lolwut"
|
112
|
-
```
|
113
|
-
|
114
|
-
You can see what's getting run. The 'Command' part it logs is in green for visibility!
|
115
|
-
|
116
|
-
```ruby
|
117
|
-
line = Cocaine::CommandLine.new("echo", ":var", logger: Logger.new(STDOUT))
|
118
|
-
line.run(var: "LOL!") # => Logs this with #info -> Command :: echo 'LOL!'
|
119
|
-
```
|
120
|
-
|
121
|
-
Or log every command:
|
122
|
-
|
123
|
-
```ruby
|
124
|
-
Cocaine::CommandLine.logger = Logger.new(STDOUT)
|
125
|
-
Cocaine::CommandLine.new("date").run # => Logs this -> Command :: date
|
126
|
-
```
|
127
|
-
|
128
|
-
## Security
|
129
|
-
|
130
|
-
Short version: Only pass user-generated data into the `run` method and NOT
|
131
|
-
`new`.
|
132
|
-
|
133
|
-
As shown in examples above, Cocaine will only shell-escape what is passed in as
|
134
|
-
interpolations to the `run` method. It WILL NOT escape what is passed in to the
|
135
|
-
second argument of `new`. Cocaine assumes that you will not be manually
|
136
|
-
passing user-generated data to that argument and will be using it as a template
|
137
|
-
for your command line's structure.
|
138
|
-
|
139
|
-
## POSIX Spawn
|
140
|
-
|
141
|
-
You can potentially increase performance by installing [the posix-spawn
|
142
|
-
gem](https://rubygems.org/gems/posix-spawn). This gem can keep your
|
143
|
-
application's heap from being copied when forking command line
|
144
|
-
processes. For applications with large heaps the gain can be
|
145
|
-
significant. To include `posix-spawn`, simply add it to your `Gemfile` or,
|
146
|
-
if you don't use bundler, install the gem.
|
147
|
-
|
148
|
-
## Runners
|
149
|
-
|
150
|
-
Cocaine will attempt to choose from among 3 different ways of running commands.
|
151
|
-
The simplest is using backticks, and is the default in 1.8. In Ruby 1.9, it
|
152
|
-
will attempt to use `Process.spawn`. And, as mentioned above, if the
|
153
|
-
`posix-spawn` gem is installed, it will attempt to use that. If for some reason
|
154
|
-
one of the `.spawn` runners don't work for you, you can override them manually
|
155
|
-
by setting a new runner, like so:
|
156
|
-
|
157
|
-
```ruby
|
158
|
-
Cocaine::CommandLine.runner = Cocaine::CommandLine::BackticksRunner.new
|
159
|
-
```
|
160
|
-
|
161
|
-
And if you really want to, you can define your own Runner, though I can't
|
162
|
-
imagine why you would.
|
163
|
-
|
164
|
-
### JRuby issues
|
165
|
-
|
166
|
-
#### Caveat
|
167
|
-
|
168
|
-
If you get `Error::ECHILD` errors and are using JRuby, there is a very good
|
169
|
-
chance that the error is actually in JRuby. This was brought to our attention
|
170
|
-
in https://github.com/thoughtbot/cocaine/issues/24 and probably fixed in
|
171
|
-
http://jira.codehaus.org/browse/JRUBY-6162. You *will* want to use the
|
172
|
-
`BackticksRunner` if you are unable to update JRuby.
|
173
|
-
|
174
|
-
#### Spawn warning
|
175
|
-
|
176
|
-
If you get `unsupported spawn option: out` warning (like in [issue 38](https://github.com/thoughtbot/cocaine/issues/38)),
|
177
|
-
try to use `PopenRunner`:
|
178
|
-
|
179
|
-
```ruby
|
180
|
-
Cocaine::CommandLine.runner = Cocaine::CommandLine::PopenRunner.new
|
181
|
-
```
|
182
|
-
|
183
|
-
## Thread Safety
|
184
|
-
|
185
|
-
Cocaine should be thread safe. As discussed [here, in this climate_control
|
186
|
-
thread](https://github.com/thoughtbot/climate_control/pull/11), climate_control,
|
187
|
-
which modifies the environment under which commands are run for the
|
188
|
-
BackticksRunner and PopenRunner, is thread-safe but not reentrant. Please let us
|
189
|
-
know if you find this is ever not the case.
|
190
|
-
|
191
|
-
## Feedback
|
192
|
-
|
193
|
-
*Security* concerns must be privately emailed to
|
194
|
-
[security@thoughtbot.com](security@thoughtbot.com).
|
195
|
-
|
196
|
-
Question? Idea? Problem? Bug? Comment? Concern? Like using question marks?
|
197
|
-
|
198
|
-
[GitHub Issues For All!](https://github.com/thoughtbot/cocaine/issues)
|
199
|
-
|
200
|
-
## Credits
|
201
|
-
|
202
|
-
Thank you to all [the contributors](https://github.com/thoughtbot/cocaine/graphs/contributors)!
|
203
|
-
|
204
|
-

|
205
|
-
|
206
|
-
Cocaine is maintained and funded by [thoughtbot, inc](http://thoughtbot.com/community)
|
207
|
-
|
208
|
-
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
24
|
+
and should continue to work fine.
|
209
25
|
|
210
26
|
## License
|
211
27
|
|
212
|
-
Copyright 2011-
|
28
|
+
Copyright 2011-2018 Jon Yurek and thoughtbot, inc. This is free software, and
|
213
29
|
may be redistributed under the terms specified in the
|
214
30
|
[LICENSE](https://github.com/thoughtbot/cocaine/blob/master/LICENSE)
|
215
31
|
file.
|
data/cocaine.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
|
-
s.add_dependency(
|
20
|
+
s.add_dependency("terrapin", "= 0.6.0.alpha")
|
21
21
|
s.add_development_dependency('rspec')
|
22
22
|
s.add_development_dependency('bourne')
|
23
23
|
s.add_development_dependency('mocha')
|
data/lib/cocaine.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# coding: UTF-8
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
5
|
-
require 'cocaine/command_line'
|
6
|
-
require 'cocaine/command_line/output'
|
7
|
-
require 'cocaine/command_line/multi_pipe'
|
8
|
-
require 'cocaine/command_line/runners'
|
9
|
-
require 'cocaine/exceptions'
|
3
|
+
require 'terrapin'
|
4
|
+
Cocaine = Terrapin
|
10
5
|
|
11
|
-
|
12
|
-
|
6
|
+
$stderr.puts [
|
7
|
+
"===========================================\n",
|
8
|
+
"DEPRECATION: The cocaine gem is deprecated.",
|
9
|
+
"Please upgrade to terrapin.",
|
10
|
+
"See https://github.com/thoughtbot/terrapin/ for further instructions.",
|
11
|
+
"\n==========================================="
|
12
|
+
].join(" ")
|
data/lib/cocaine/version.rb
CHANGED
metadata
CHANGED
@@ -1,35 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocaine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Yurek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: terrapin
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 0.0.3
|
20
|
-
- - "<"
|
17
|
+
- - '='
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
19
|
+
version: 0.6.0.alpha
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '='
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.0.
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '1.0'
|
26
|
+
version: 0.6.0.alpha
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: rspec
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,17 +130,6 @@ files:
|
|
136
130
|
- Rakefile
|
137
131
|
- cocaine.gemspec
|
138
132
|
- lib/cocaine.rb
|
139
|
-
- lib/cocaine/command_line.rb
|
140
|
-
- lib/cocaine/command_line/multi_pipe.rb
|
141
|
-
- lib/cocaine/command_line/output.rb
|
142
|
-
- lib/cocaine/command_line/runners.rb
|
143
|
-
- lib/cocaine/command_line/runners/backticks_runner.rb
|
144
|
-
- lib/cocaine/command_line/runners/fake_runner.rb
|
145
|
-
- lib/cocaine/command_line/runners/popen_runner.rb
|
146
|
-
- lib/cocaine/command_line/runners/posix_runner.rb
|
147
|
-
- lib/cocaine/command_line/runners/process_runner.rb
|
148
|
-
- lib/cocaine/exceptions.rb
|
149
|
-
- lib/cocaine/os_detector.rb
|
150
133
|
- lib/cocaine/version.rb
|
151
134
|
- spec/cocaine/command_line/output_spec.rb
|
152
135
|
- spec/cocaine/command_line/runners/backticks_runner_spec.rb
|
@@ -180,12 +163,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
163
|
version: '0'
|
181
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
165
|
requirements:
|
183
|
-
- - "
|
166
|
+
- - ">"
|
184
167
|
- !ruby/object:Gem::Version
|
185
|
-
version:
|
168
|
+
version: 1.3.1
|
186
169
|
requirements: []
|
187
170
|
rubyforge_project:
|
188
|
-
rubygems_version: 2.4
|
171
|
+
rubygems_version: 2.7.4
|
189
172
|
signing_key:
|
190
173
|
specification_version: 4
|
191
174
|
summary: A small library for doing (command) lines
|
data/lib/cocaine/command_line.rb
DELETED
@@ -1,197 +0,0 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
module Cocaine
|
4
|
-
class CommandLine
|
5
|
-
class << self
|
6
|
-
attr_accessor :logger, :runner
|
7
|
-
|
8
|
-
def path
|
9
|
-
@supplemental_path
|
10
|
-
end
|
11
|
-
|
12
|
-
def path=(supplemental_path)
|
13
|
-
@supplemental_path = Array(supplemental_path).
|
14
|
-
flatten.
|
15
|
-
join(OS.path_separator)
|
16
|
-
end
|
17
|
-
|
18
|
-
def environment
|
19
|
-
@supplemental_environment ||= {}
|
20
|
-
end
|
21
|
-
|
22
|
-
def runner
|
23
|
-
@runner || best_runner
|
24
|
-
end
|
25
|
-
|
26
|
-
def runner_options
|
27
|
-
@default_runner_options ||= {}
|
28
|
-
end
|
29
|
-
|
30
|
-
def fake!
|
31
|
-
@runner = FakeRunner.new
|
32
|
-
end
|
33
|
-
|
34
|
-
def unfake!
|
35
|
-
@runner = nil
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def best_runner
|
41
|
-
[PosixRunner, ProcessRunner, BackticksRunner].detect do |runner|
|
42
|
-
runner.supported?
|
43
|
-
end.new
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
@environment = {}
|
48
|
-
|
49
|
-
attr_reader :exit_status, :runner
|
50
|
-
|
51
|
-
def initialize(binary, params = "", options = {})
|
52
|
-
@binary = binary.dup
|
53
|
-
@params = params.dup
|
54
|
-
@options = options.dup
|
55
|
-
@runner = @options.delete(:runner) || self.class.runner
|
56
|
-
@logger = @options.delete(:logger) || self.class.logger
|
57
|
-
@swallow_stderr = @options.delete(:swallow_stderr)
|
58
|
-
@expected_outcodes = @options.delete(:expected_outcodes) || [0]
|
59
|
-
@environment = @options.delete(:environment) || {}
|
60
|
-
@runner_options = @options.delete(:runner_options) || {}
|
61
|
-
end
|
62
|
-
|
63
|
-
def command(interpolations = {})
|
64
|
-
cmd = [path_prefix, @binary, interpolate(@params, interpolations)]
|
65
|
-
cmd << bit_bucket if @swallow_stderr
|
66
|
-
cmd.join(" ").strip
|
67
|
-
end
|
68
|
-
|
69
|
-
def run(interpolations = {})
|
70
|
-
@exit_status = nil
|
71
|
-
begin
|
72
|
-
full_command = command(interpolations)
|
73
|
-
log("#{colored("Command")} :: #{full_command}")
|
74
|
-
@output = execute(full_command)
|
75
|
-
rescue Errno::ENOENT => e
|
76
|
-
raise Cocaine::CommandNotFoundError, e.message
|
77
|
-
ensure
|
78
|
-
@exit_status = $?.respond_to?(:exitstatus) ? $?.exitstatus : 0
|
79
|
-
end
|
80
|
-
|
81
|
-
if @exit_status == 127
|
82
|
-
raise Cocaine::CommandNotFoundError
|
83
|
-
end
|
84
|
-
|
85
|
-
unless @expected_outcodes.include?(@exit_status)
|
86
|
-
message = [
|
87
|
-
"Command '#{full_command}' returned #{@exit_status}. Expected #{@expected_outcodes.join(", ")}",
|
88
|
-
"Here is the command output: STDOUT:\n", command_output,
|
89
|
-
"\nSTDERR:\n", command_error_output
|
90
|
-
].join("\n")
|
91
|
-
raise Cocaine::ExitStatusError, message
|
92
|
-
end
|
93
|
-
command_output
|
94
|
-
end
|
95
|
-
|
96
|
-
def command_output
|
97
|
-
output.output
|
98
|
-
end
|
99
|
-
|
100
|
-
def command_error_output
|
101
|
-
output.error_output
|
102
|
-
end
|
103
|
-
|
104
|
-
def output
|
105
|
-
@output || Output.new
|
106
|
-
end
|
107
|
-
|
108
|
-
private
|
109
|
-
|
110
|
-
def colored(text, ansi_color = "\e[32m")
|
111
|
-
if @logger && @logger.respond_to?(:tty?) && @logger.tty?
|
112
|
-
"#{ansi_color}#{text}\e[0m"
|
113
|
-
else
|
114
|
-
text
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def log(text)
|
119
|
-
if @logger
|
120
|
-
@logger.info(text)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def path_prefix
|
125
|
-
if !self.class.path.nil? && !self.class.path.empty?
|
126
|
-
os_path_prefix
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def os_path_prefix
|
131
|
-
if OS.unix?
|
132
|
-
unix_path_prefix
|
133
|
-
else
|
134
|
-
windows_path_prefix
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def unix_path_prefix
|
139
|
-
"PATH=#{self.class.path}#{OS.path_separator}$PATH;"
|
140
|
-
end
|
141
|
-
|
142
|
-
def windows_path_prefix
|
143
|
-
"SET PATH=#{self.class.path}#{OS.path_separator}%PATH% &"
|
144
|
-
end
|
145
|
-
|
146
|
-
def execute(command)
|
147
|
-
runner.call(command, environment, runner_options)
|
148
|
-
end
|
149
|
-
|
150
|
-
def environment
|
151
|
-
self.class.environment.merge(@environment)
|
152
|
-
end
|
153
|
-
|
154
|
-
def runner_options
|
155
|
-
self.class.runner_options.merge(@runner_options)
|
156
|
-
end
|
157
|
-
|
158
|
-
def interpolate(pattern, interpolations)
|
159
|
-
interpolations = stringify_keys(interpolations)
|
160
|
-
pattern.gsub(/:\{?(\w+)\b\}?/) do |match|
|
161
|
-
key = match.tr(":{}", "")
|
162
|
-
if interpolations.key?(key)
|
163
|
-
shell_quote_all_values(interpolations[key])
|
164
|
-
else
|
165
|
-
match
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def stringify_keys(hash)
|
171
|
-
Hash[hash.map{ |k, v| [k.to_s, v] }]
|
172
|
-
end
|
173
|
-
|
174
|
-
def shell_quote_all_values(values)
|
175
|
-
Array(values).map(&method(:shell_quote)).join(" ")
|
176
|
-
end
|
177
|
-
|
178
|
-
def shell_quote(string)
|
179
|
-
return "" if string.nil?
|
180
|
-
string = string.to_s if string.respond_to? :to_s
|
181
|
-
|
182
|
-
if OS.unix?
|
183
|
-
if string.empty?
|
184
|
-
"''"
|
185
|
-
else
|
186
|
-
string.split("'", -1).map{|m| "'#{m}'" }.join("\\'")
|
187
|
-
end
|
188
|
-
else
|
189
|
-
%{"#{string}"}
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def bit_bucket
|
194
|
-
OS.unix? ? "2>/dev/null" : "2>NUL"
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module Cocaine
|
2
|
-
class CommandLine
|
3
|
-
class MultiPipe
|
4
|
-
def initialize
|
5
|
-
@stdout_in, @stdout_out = IO.pipe
|
6
|
-
@stderr_in, @stderr_out = IO.pipe
|
7
|
-
end
|
8
|
-
|
9
|
-
def pipe_options
|
10
|
-
{ out: @stdout_out, err: @stderr_out }
|
11
|
-
end
|
12
|
-
|
13
|
-
def output
|
14
|
-
Output.new(@stdout_output, @stderr_output)
|
15
|
-
end
|
16
|
-
|
17
|
-
def read_and_then(&block)
|
18
|
-
close_write
|
19
|
-
read
|
20
|
-
block.call
|
21
|
-
close_read
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def close_write
|
27
|
-
@stdout_out.close
|
28
|
-
@stderr_out.close
|
29
|
-
end
|
30
|
-
|
31
|
-
def read
|
32
|
-
@stdout_output = read_stream(@stdout_in)
|
33
|
-
@stderr_output = read_stream(@stderr_in)
|
34
|
-
end
|
35
|
-
|
36
|
-
def close_read
|
37
|
-
@stdout_in.close
|
38
|
-
@stderr_in.close
|
39
|
-
end
|
40
|
-
|
41
|
-
def read_stream(io)
|
42
|
-
result = ""
|
43
|
-
while partial_result = io.read(8192)
|
44
|
-
result << partial_result
|
45
|
-
end
|
46
|
-
result
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,7 +0,0 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
require 'cocaine/command_line/runners/backticks_runner'
|
4
|
-
require 'cocaine/command_line/runners/process_runner'
|
5
|
-
require 'cocaine/command_line/runners/posix_runner'
|
6
|
-
require 'cocaine/command_line/runners/popen_runner'
|
7
|
-
require 'cocaine/command_line/runners/fake_runner'
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
require 'climate_control'
|
4
|
-
|
5
|
-
module Cocaine
|
6
|
-
class CommandLine
|
7
|
-
class BackticksRunner
|
8
|
-
def self.supported?
|
9
|
-
true
|
10
|
-
end
|
11
|
-
|
12
|
-
def supported?
|
13
|
-
self.class.supported?
|
14
|
-
end
|
15
|
-
|
16
|
-
def call(command, env = {}, options = {})
|
17
|
-
with_modified_environment(env) do
|
18
|
-
Output.new(`#{command}`)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def with_modified_environment(env, &block)
|
25
|
-
ClimateControl.modify(env, &block)
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
module Cocaine
|
4
|
-
class CommandLine
|
5
|
-
class FakeRunner
|
6
|
-
def self.supported?
|
7
|
-
false
|
8
|
-
end
|
9
|
-
|
10
|
-
def supported?
|
11
|
-
self.class.supported?
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_reader :commands
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
@commands = []
|
18
|
-
end
|
19
|
-
|
20
|
-
def call(command, env = {}, options = {})
|
21
|
-
commands << [command, env]
|
22
|
-
Output.new("")
|
23
|
-
end
|
24
|
-
|
25
|
-
def ran?(predicate_command)
|
26
|
-
@commands.any?{|(command, _)| command =~ Regexp.new(predicate_command) }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
module Cocaine
|
4
|
-
class CommandLine
|
5
|
-
class PopenRunner
|
6
|
-
def self.supported?
|
7
|
-
true
|
8
|
-
end
|
9
|
-
|
10
|
-
def supported?
|
11
|
-
self.class.supported?
|
12
|
-
end
|
13
|
-
|
14
|
-
def call(command, env = {}, options = {})
|
15
|
-
with_modified_environment(env) do
|
16
|
-
IO.popen(command, "r", options) do |pipe|
|
17
|
-
Output.new(pipe.read)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def with_modified_environment(env, &block)
|
25
|
-
ClimateControl.modify(env, &block)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
module Cocaine
|
4
|
-
class CommandLine
|
5
|
-
class PosixRunner
|
6
|
-
def self.available?
|
7
|
-
return @available unless @available.nil?
|
8
|
-
|
9
|
-
@available = posix_spawn_gem_available?
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.supported?
|
13
|
-
available? && !OS.java?
|
14
|
-
end
|
15
|
-
|
16
|
-
def supported?
|
17
|
-
self.class.supported?
|
18
|
-
end
|
19
|
-
|
20
|
-
def call(command, env = {}, options = {})
|
21
|
-
pipe = MultiPipe.new
|
22
|
-
pid = spawn(env, command, options.merge(pipe.pipe_options))
|
23
|
-
pipe.read_and_then do
|
24
|
-
waitpid(pid)
|
25
|
-
end
|
26
|
-
pipe.output
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def spawn(*args)
|
32
|
-
POSIX::Spawn.spawn(*args)
|
33
|
-
end
|
34
|
-
|
35
|
-
def waitpid(pid)
|
36
|
-
Process.waitpid(pid)
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.posix_spawn_gem_available?
|
40
|
-
require 'posix/spawn'
|
41
|
-
true
|
42
|
-
rescue LoadError
|
43
|
-
false
|
44
|
-
end
|
45
|
-
|
46
|
-
private_class_method :posix_spawn_gem_available?
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
module Cocaine
|
4
|
-
class CommandLine
|
5
|
-
class ProcessRunner
|
6
|
-
def self.available?
|
7
|
-
Process.respond_to?(:spawn)
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.supported?
|
11
|
-
available? && !OS.java?
|
12
|
-
end
|
13
|
-
|
14
|
-
def supported?
|
15
|
-
self.class.supported?
|
16
|
-
end
|
17
|
-
|
18
|
-
def call(command, env = {}, options = {})
|
19
|
-
pipe = MultiPipe.new
|
20
|
-
pid = spawn(env, command, options.merge(pipe.pipe_options))
|
21
|
-
pipe.read_and_then do
|
22
|
-
waitpid(pid)
|
23
|
-
end
|
24
|
-
pipe.output
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def spawn(*args)
|
30
|
-
Process.spawn(*args)
|
31
|
-
end
|
32
|
-
|
33
|
-
def waitpid(pid)
|
34
|
-
Process.waitpid(pid)
|
35
|
-
rescue Errno::ECHILD
|
36
|
-
# In JRuby, waiting on a finished pid raises.
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/cocaine/exceptions.rb
DELETED
data/lib/cocaine/os_detector.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
module Cocaine
|
4
|
-
class OSDetector
|
5
|
-
def java?
|
6
|
-
arch =~ /java/
|
7
|
-
end
|
8
|
-
|
9
|
-
def unix?
|
10
|
-
RbConfig::CONFIG['host_os'] !~ /mswin|mingw/
|
11
|
-
end
|
12
|
-
|
13
|
-
def windows?
|
14
|
-
!unix?
|
15
|
-
end
|
16
|
-
|
17
|
-
def path_separator
|
18
|
-
File::PATH_SEPARATOR
|
19
|
-
end
|
20
|
-
|
21
|
-
def arch
|
22
|
-
RUBY_PLATFORM
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
OS = OSDetector.new
|
27
|
-
end
|