awesome_spawn 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of awesome_spawn might be problematic. Click here for more details.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/awesome_spawn.gemspec +34 -0
- data/lib/awesome_spawn.rb +174 -0
- data/lib/awesome_spawn/command_result.rb +16 -0
- data/lib/awesome_spawn/command_result_error.rb +11 -0
- data/lib/awesome_spawn/no_such_file_error.rb +11 -0
- data/lib/awesome_spawn/version.rb +3 -0
- data/spec/awesome_spawn_spec.rb +159 -0
- data/spec/command_result_spec.rb +13 -0
- data/spec/spec_helper.rb +26 -0
- metadata +176 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Red Hat, Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# AwesomeSpawn
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/awesome_spawn.png)](http://badge.fury.io/rb/awesome_spawn)
|
4
|
+
[![Build Status](https://travis-ci.org/ManageIQ/awesome_spawn.png)](https://travis-ci.org/ManageIQ/awesome_spawn)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/ManageIQ/awesome_spawn.png)](https://codeclimate.com/github/ManageIQ/awesome_spawn)
|
6
|
+
[![Coverage Status](https://coveralls.io/repos/ManageIQ/awesome_spawn/badge.png?branch=master)](https://coveralls.io/r/ManageIQ/awesome_spawn)
|
7
|
+
[![Dependency Status](https://gemnasium.com/ManageIQ/awesome_spawn.png)](https://gemnasium.com/ManageIQ/awesome_spawn)
|
8
|
+
|
9
|
+
AwesomeSpawn is a module that provides some useful features over Ruby's Kernel.spawn.
|
10
|
+
|
11
|
+
Some additional features include...
|
12
|
+
|
13
|
+
- Parameter passing as a Hash or associative Array sanitizing them to prevent command line injection.
|
14
|
+
- Results returned as an object giving access to the output stream, error stream, and exit status.
|
15
|
+
- Optionally raising an exception when exit status is not 0.
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
See the [YARD documentation](http://rubydoc.info/gems/awesome_spawn)
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
gem 'awesome_spawn'
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
$ bundle
|
30
|
+
|
31
|
+
Or install it yourself as:
|
32
|
+
|
33
|
+
$ gem install awesome_spawn
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
1. Fork it
|
38
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
39
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
40
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
41
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'awesome_spawn/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
authors = {
|
8
|
+
"Jason Frey" => "jfrey@redhat.com",
|
9
|
+
"Brandon Dunne" => "bdunne@redhat.com",
|
10
|
+
"Joe Rafaniello" => "jrafanie@redhat.com",
|
11
|
+
"Mo Morsi" => "mmorsi@redhat.com"
|
12
|
+
}
|
13
|
+
|
14
|
+
spec.name = "awesome_spawn"
|
15
|
+
spec.version = AwesomeSpawn::VERSION
|
16
|
+
spec.authors = authors.keys
|
17
|
+
spec.email = authors.values
|
18
|
+
spec.description = %q{AwesomeSpawn is a module that provides some useful features over Ruby's Kernel.spawn.}
|
19
|
+
spec.summary = spec.description
|
20
|
+
spec.homepage = "https://github.com/ManageIQ/awesome_spawn"
|
21
|
+
spec.license = "MIT"
|
22
|
+
|
23
|
+
spec.files = `git ls-files`.split($/)
|
24
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
25
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
29
|
+
spec.add_development_dependency "rake"
|
30
|
+
spec.add_development_dependency "rspec"
|
31
|
+
spec.add_development_dependency "coveralls"
|
32
|
+
spec.add_development_dependency "yard"
|
33
|
+
spec.add_development_dependency "redcarpet"
|
34
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require "awesome_spawn/version"
|
2
|
+
require "awesome_spawn/command_result"
|
3
|
+
require "awesome_spawn/command_result_error"
|
4
|
+
require "awesome_spawn/no_such_file_error"
|
5
|
+
|
6
|
+
require "shellwords"
|
7
|
+
|
8
|
+
module AwesomeSpawn
|
9
|
+
extend self
|
10
|
+
|
11
|
+
# Execute `command` synchronously via Kernel.spawn and gather the output
|
12
|
+
# stream, error stream, and exit status in a {CommandResult}.
|
13
|
+
#
|
14
|
+
# @example With normal output
|
15
|
+
# result = AwesomeSpawn.run('echo Hi')
|
16
|
+
# # => #<AwesomeSpawn::CommandResult:0x007f9d1d197320 @exit_status=0>
|
17
|
+
# result.output # => "Hi\n"
|
18
|
+
# result.error # => ""
|
19
|
+
# result.exit_status # => 0
|
20
|
+
#
|
21
|
+
# @example With error output as well
|
22
|
+
# result = AwesomeSpawn.run('echo Hi; echo "Hi2" 1>&2')
|
23
|
+
# # => <AwesomeSpawn::CommandResult:0x007ff64b98d930 @exit_status=0>
|
24
|
+
# result.output # => "Hi\n"
|
25
|
+
# result.error # => "Hi2\n"
|
26
|
+
# result.exit_status # => 0
|
27
|
+
#
|
28
|
+
# @example With exit status that is not 0
|
29
|
+
# result = AwesomeSpawn.run('false')
|
30
|
+
# #<AwesomeSpawn::CommandResult:0x007ff64b971410 @exit_status=1>
|
31
|
+
# result.exit_status # => 1
|
32
|
+
#
|
33
|
+
# @example With parameters sanitized
|
34
|
+
# result = AwesomeSpawn.run('echo', :params => {"--out" => "; rm /some/file"})
|
35
|
+
# # => #<AwesomeSpawn::CommandResult:0x007ff64baa6650 @exit_status=0>
|
36
|
+
# result.command_line
|
37
|
+
# # => "echo --out \\;\\ rm\\ /some/file"
|
38
|
+
#
|
39
|
+
# @param [String] command The command to run
|
40
|
+
# @param [Hash] options The options for running the command
|
41
|
+
# @option options [Hash,Array] :params The command line parameters. See
|
42
|
+
# {#build_command_line} for how to specify params. Alternate key
|
43
|
+
# `:parameters`.
|
44
|
+
# @option options [String] :chdir see the `:chdir` parameter for Kernel.spawn
|
45
|
+
#
|
46
|
+
# @raise [NoSuchFileError] if the `command` is not found
|
47
|
+
# @return [CommandResult] the output stream, error stream, and exit status
|
48
|
+
# @see http://ruby-doc.org/core/Kernel.html#method-i-spawn Kernel.spawn
|
49
|
+
def run(command, options = {})
|
50
|
+
params = options[:params] || options[:parameters]
|
51
|
+
|
52
|
+
launch_params = {}
|
53
|
+
launch_params[:chdir] = options[:chdir] if options[:chdir]
|
54
|
+
|
55
|
+
output = ""
|
56
|
+
error = ""
|
57
|
+
status = nil
|
58
|
+
command_line = build_command_line(command, params)
|
59
|
+
|
60
|
+
begin
|
61
|
+
output, error = launch(command_line, launch_params)
|
62
|
+
status = exitstatus
|
63
|
+
ensure
|
64
|
+
output ||= ""
|
65
|
+
error ||= ""
|
66
|
+
self.exitstatus = nil
|
67
|
+
end
|
68
|
+
rescue Errno::ENOENT => err
|
69
|
+
raise NoSuchFileError.new(err.message) if NoSuchFileError.detected?(err.message)
|
70
|
+
raise
|
71
|
+
else
|
72
|
+
CommandResult.new(command_line, output, error, status)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Same as {#run}, additionally raising a {CommandResultError} if the exit
|
76
|
+
# status is not 0.
|
77
|
+
#
|
78
|
+
# @example With exit status that is not 0
|
79
|
+
# error = AwesomeSpawn.run!('false') rescue $!
|
80
|
+
# # => #<AwesomeSpawn::CommandResultError: false exit code: 1>
|
81
|
+
# error.message # => false exit code: 1
|
82
|
+
# error.result # => #<AwesomeSpawn::CommandResult:0x007ff64ba08018 @exit_status=1>
|
83
|
+
#
|
84
|
+
# @raise [CommandResultError] if the exit status is not 0.
|
85
|
+
# @return (see #run)
|
86
|
+
def run!(command, options = {})
|
87
|
+
command_result = run(command, options)
|
88
|
+
|
89
|
+
if command_result.exit_status != 0
|
90
|
+
message = "#{command} exit code: #{command_result.exit_status}"
|
91
|
+
raise CommandResultError.new(message, command_result)
|
92
|
+
end
|
93
|
+
|
94
|
+
command_result
|
95
|
+
end
|
96
|
+
|
97
|
+
# Build the full command line.
|
98
|
+
#
|
99
|
+
# @param [String] command The command to run
|
100
|
+
# @param [Hash,Array] params Optional command line parameters. They can
|
101
|
+
# be passed as a Hash or associative Array. The values are sanitized to
|
102
|
+
# prevent command line injection.
|
103
|
+
#
|
104
|
+
# - `{"--key" => "value"}` generates `--key value`
|
105
|
+
# - `{"--key=" => "value"}` generates `--key=value`
|
106
|
+
# - `{"--key" => nil}` generates `--key`
|
107
|
+
# - `{"-f" => ["file1", "file2"]}` generates `-f file1 file2`
|
108
|
+
# - `{nil => ["file1", "file2"]}` generates `file1 file2`
|
109
|
+
#
|
110
|
+
# @return [String] The full command line
|
111
|
+
def build_command_line(command, params = nil)
|
112
|
+
return command.to_s if params.nil? || params.empty?
|
113
|
+
"#{command} #{assemble_params(sanitize(params))}"
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def sanitize(params)
|
119
|
+
return [] if params.nil? || params.empty?
|
120
|
+
params.collect do |k, v|
|
121
|
+
v = case v
|
122
|
+
when Array; v.collect {|i| i.to_s.shellescape}
|
123
|
+
when NilClass; v
|
124
|
+
else v.to_s.shellescape
|
125
|
+
end
|
126
|
+
[k, v]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def assemble_params(sanitized_params)
|
131
|
+
sanitized_params.collect do |pair|
|
132
|
+
pair_joiner = pair.first.to_s.end_with?("=") ? "" : " "
|
133
|
+
pair.flatten.compact.join(pair_joiner)
|
134
|
+
end.join(" ")
|
135
|
+
end
|
136
|
+
|
137
|
+
# IO pipes have a maximum size of 64k before blocking,
|
138
|
+
# so we need to read and write synchronously.
|
139
|
+
# http://stackoverflow.com/questions/13829830/ruby-process-spawn-stdout-pipe-buffer-size-limit/13846146#13846146
|
140
|
+
THREAD_SYNC_KEY = "#{self.name}-exitstatus"
|
141
|
+
|
142
|
+
def launch(command, spawn_options = {})
|
143
|
+
out_r, out_w = IO.pipe
|
144
|
+
err_r, err_w = IO.pipe
|
145
|
+
pid = Kernel.spawn(command, {:err => err_w, :out => out_w}.merge(spawn_options))
|
146
|
+
wait_for_process(pid, out_w, err_w)
|
147
|
+
wait_for_pipes(out_r, err_r)
|
148
|
+
end
|
149
|
+
|
150
|
+
def wait_for_process(pid, out_w, err_w)
|
151
|
+
self.exitstatus = :not_done
|
152
|
+
Thread.new(Thread.current) do |parent_thread|
|
153
|
+
_, status = Process.wait2(pid)
|
154
|
+
out_w.close
|
155
|
+
err_w.close
|
156
|
+
parent_thread[THREAD_SYNC_KEY] = status.exitstatus
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def wait_for_pipes(out_r, err_r)
|
161
|
+
out = out_r.read
|
162
|
+
err = err_r.read
|
163
|
+
sleep(0.1) while exitstatus == :not_done
|
164
|
+
return out, err
|
165
|
+
end
|
166
|
+
|
167
|
+
def exitstatus
|
168
|
+
Thread.current[THREAD_SYNC_KEY]
|
169
|
+
end
|
170
|
+
|
171
|
+
def exitstatus=(value)
|
172
|
+
Thread.current[THREAD_SYNC_KEY] = value
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module AwesomeSpawn
|
2
|
+
class CommandResult
|
3
|
+
attr_reader :command_line, :output, :error, :exit_status
|
4
|
+
|
5
|
+
def initialize(command_line, output, error, exit_status)
|
6
|
+
@command_line = command_line
|
7
|
+
@output = output
|
8
|
+
@error = error
|
9
|
+
@exit_status = exit_status
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"#{to_s.chop} @exit_status=#{@exit_status}>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module AwesomeSpawn
|
2
|
+
class NoSuchFileError < Errno::ENOENT
|
3
|
+
def initialize(message)
|
4
|
+
super(message.split("No such file or directory -").last.split(" ").first)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.detected?(message)
|
8
|
+
message.start_with?("No such file or directory -")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pathname' # For Pathname specific specs
|
3
|
+
|
4
|
+
describe AwesomeSpawn do
|
5
|
+
subject { described_class }
|
6
|
+
|
7
|
+
let(:params) do
|
8
|
+
{
|
9
|
+
"--user" => "bob",
|
10
|
+
"--pass" => "P@$sw0^& |<>/-+*d%",
|
11
|
+
"--db" => nil,
|
12
|
+
"--desc=" => "Some Description",
|
13
|
+
nil => ["pkg1", "some pkg"]
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
let (:modified_params) do
|
18
|
+
params.to_a + [123, 456].collect {|pool| ["--pool", pool]}
|
19
|
+
end
|
20
|
+
|
21
|
+
shared_examples_for "run" do
|
22
|
+
context "parameters" do
|
23
|
+
before do
|
24
|
+
subject.stub(:exitstatus => 0)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "won't modify caller params" do
|
28
|
+
orig_params = params.dup
|
29
|
+
subject.stub(:launch)
|
30
|
+
subject.send(run_method, "true", :params => params)
|
31
|
+
expect(orig_params).to eq(params)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "supports spawn's chdir option" do
|
35
|
+
subject.should_receive(:launch).once.with("true", {:chdir => ".."})
|
36
|
+
subject.send(run_method, "true", :chdir => "..")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with real execution" do
|
41
|
+
before do
|
42
|
+
# Re-enable actual spawning just for these specs.
|
43
|
+
Kernel.stub(:spawn).and_call_original
|
44
|
+
end
|
45
|
+
|
46
|
+
it "command ok exit ok" do
|
47
|
+
expect(subject.send(run_method, "true")).to be_kind_of AwesomeSpawn::CommandResult
|
48
|
+
end
|
49
|
+
|
50
|
+
it "command ok exit bad" do
|
51
|
+
if run_method == "run!"
|
52
|
+
error = nil
|
53
|
+
|
54
|
+
# raise_error with do/end block notation is broken in rspec-expectations 2.14.x
|
55
|
+
# and has been fixed in master but not yet released.
|
56
|
+
# See: https://github.com/rspec/rspec-expectations/commit/b0df827f4c12870aa4df2f20a817a8b01721a6af
|
57
|
+
expect { subject.send(run_method, "false") }.to raise_error {|e| error = e }
|
58
|
+
expect(error).to be_kind_of AwesomeSpawn::CommandResultError
|
59
|
+
expect(error.result).to be_kind_of AwesomeSpawn::CommandResult
|
60
|
+
else
|
61
|
+
expect { subject.send(run_method, "false") }.to_not raise_error
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "command bad" do
|
66
|
+
expect { subject.send(run_method, "XXXXX --user=bob") }.to raise_error(Errno::ENOENT, "No such file or directory - XXXXX")
|
67
|
+
end
|
68
|
+
|
69
|
+
context "#exit_status" do
|
70
|
+
it "command ok exit ok" do
|
71
|
+
expect(subject.send(run_method, "true").exit_status).to eq(0)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "command ok exit bad" do
|
75
|
+
expect(subject.send(run_method, "false").exit_status).to eq(1) if run_method == "run"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "#output" do
|
80
|
+
it "command ok exit ok" do
|
81
|
+
expect(subject.send(run_method, "echo \"Hello World\"").output).to eq("Hello World\n")
|
82
|
+
end
|
83
|
+
|
84
|
+
it "command ok exit bad" do
|
85
|
+
expect(subject.send(run_method, "echo 'bad' && false").output).to eq("bad\n") if run_method == "run"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "#error" do
|
90
|
+
it "command ok exit ok" do
|
91
|
+
expect(subject.send(run_method, "echo \"Hello World\" >&2").error).to eq("Hello World\n")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "command ok exit bad" do
|
95
|
+
expect(subject.send(run_method, "echo 'bad' >&2 && false").error).to eq("bad\n") if run_method == "run"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context ".run" do
|
102
|
+
include_examples "run" do
|
103
|
+
let(:run_method) {"run"}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context ".run!" do
|
108
|
+
include_examples "run" do
|
109
|
+
let(:run_method) {"run!"}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context ".build_command_line" do
|
114
|
+
it "sanitizes crazy params" do
|
115
|
+
cl = subject.build_command_line("true", modified_params)
|
116
|
+
expect(cl).to eq "true --user bob --pass P@\\$sw0\\^\\&\\ \\|\\<\\>/-\\+\\*d\\% --db --desc=Some\\ Description pkg1 some\\ pkg --pool 123 --pool 456"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "sanitizes Fixnum array param value" do
|
120
|
+
cl = subject.build_command_line("true", nil => [1])
|
121
|
+
expect(cl).to eq "true 1"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "sanitizes Pathname param value" do
|
125
|
+
cl = subject.build_command_line("true", nil => [Pathname.new("/usr/bin/ruby")])
|
126
|
+
expect(cl).to eq "true /usr/bin/ruby"
|
127
|
+
end
|
128
|
+
|
129
|
+
it "sanitizes Pathname param key" do
|
130
|
+
cl = subject.build_command_line("true", Pathname.new("/usr/bin/ruby") => nil)
|
131
|
+
expect(cl).to eq "true /usr/bin/ruby"
|
132
|
+
end
|
133
|
+
|
134
|
+
it "with params as empty Hash" do
|
135
|
+
cl = subject.build_command_line("true", {})
|
136
|
+
expect(cl).to eq "true"
|
137
|
+
end
|
138
|
+
|
139
|
+
it "with params as nil" do
|
140
|
+
cl = subject.build_command_line("true", nil)
|
141
|
+
expect(cl).to eq "true"
|
142
|
+
end
|
143
|
+
|
144
|
+
it "without params" do
|
145
|
+
cl = subject.build_command_line("true")
|
146
|
+
expect(cl).to eq "true"
|
147
|
+
end
|
148
|
+
|
149
|
+
it "with Pathname command" do
|
150
|
+
cl = subject.build_command_line(Pathname.new("/usr/bin/ruby"))
|
151
|
+
expect(cl).to eq "/usr/bin/ruby"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "with Pathname command and params" do
|
155
|
+
cl = subject.build_command_line(Pathname.new("/usr/bin/ruby"), "-v" => nil)
|
156
|
+
expect(cl).to eq "/usr/bin/ruby -v"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AwesomeSpawn::CommandResult do
|
4
|
+
context "#inspect" do
|
5
|
+
it "will not display sensitive information" do
|
6
|
+
str = described_class.new("aaa", "bbb", "ccc", 0).inspect
|
7
|
+
|
8
|
+
expect(str.include?("aaa")).to be_false
|
9
|
+
expect(str.include?("bbb")).to be_false
|
10
|
+
expect(str.include?("ccc")).to be_false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
|
18
|
+
config.before do
|
19
|
+
Kernel.stub(:spawn).and_raise("Spawning is not permitted in specs. Please change your spec to use expectations/stubs.")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'coveralls'
|
24
|
+
Coveralls.wear!
|
25
|
+
|
26
|
+
require 'awesome_spawn'
|
metadata
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: awesome_spawn
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jason Frey
|
9
|
+
- Brandon Dunne
|
10
|
+
- Joe Rafaniello
|
11
|
+
- Mo Morsi
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
date: 2014-01-04 00:00:00.000000000 Z
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: bundler
|
19
|
+
requirement: !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '1.3'
|
25
|
+
type: :development
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.3'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rake
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
type: :development
|
42
|
+
prerelease: false
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
requirement: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: coveralls
|
67
|
+
requirement: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
type: :development
|
74
|
+
prerelease: false
|
75
|
+
version_requirements: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: yard
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: redcarpet
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
description: AwesomeSpawn is a module that provides some useful features over Ruby's
|
114
|
+
Kernel.spawn.
|
115
|
+
email:
|
116
|
+
- jfrey@redhat.com
|
117
|
+
- bdunne@redhat.com
|
118
|
+
- jrafanie@redhat.com
|
119
|
+
- mmorsi@redhat.com
|
120
|
+
executables: []
|
121
|
+
extensions: []
|
122
|
+
extra_rdoc_files: []
|
123
|
+
files:
|
124
|
+
- .gitignore
|
125
|
+
- .rspec
|
126
|
+
- .travis.yml
|
127
|
+
- .yardopts
|
128
|
+
- Gemfile
|
129
|
+
- LICENSE.txt
|
130
|
+
- README.md
|
131
|
+
- Rakefile
|
132
|
+
- awesome_spawn.gemspec
|
133
|
+
- lib/awesome_spawn.rb
|
134
|
+
- lib/awesome_spawn/command_result.rb
|
135
|
+
- lib/awesome_spawn/command_result_error.rb
|
136
|
+
- lib/awesome_spawn/no_such_file_error.rb
|
137
|
+
- lib/awesome_spawn/version.rb
|
138
|
+
- spec/awesome_spawn_spec.rb
|
139
|
+
- spec/command_result_spec.rb
|
140
|
+
- spec/spec_helper.rb
|
141
|
+
homepage: https://github.com/ManageIQ/awesome_spawn
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
post_install_message:
|
145
|
+
rdoc_options: []
|
146
|
+
require_paths:
|
147
|
+
- lib
|
148
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
149
|
+
none: false
|
150
|
+
requirements:
|
151
|
+
- - ! '>='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
segments:
|
155
|
+
- 0
|
156
|
+
hash: -1223152174146401530
|
157
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
|
+
none: false
|
159
|
+
requirements:
|
160
|
+
- - ! '>='
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
segments:
|
164
|
+
- 0
|
165
|
+
hash: -1223152174146401530
|
166
|
+
requirements: []
|
167
|
+
rubyforge_project:
|
168
|
+
rubygems_version: 1.8.23
|
169
|
+
signing_key:
|
170
|
+
specification_version: 3
|
171
|
+
summary: AwesomeSpawn is a module that provides some useful features over Ruby's Kernel.spawn.
|
172
|
+
test_files:
|
173
|
+
- spec/awesome_spawn_spec.rb
|
174
|
+
- spec/command_result_spec.rb
|
175
|
+
- spec/spec_helper.rb
|
176
|
+
has_rdoc:
|