awesome_spawn 1.0.0

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.

Potentially problematic release.


This version of awesome_spawn might be problematic. Click here for more details.

@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
@@ -0,0 +1 @@
1
+ --markup markdown
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in awesome_spawn.gemspec
4
+ gemspec
@@ -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.
@@ -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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new('spec')
5
+ task :test => :spec
6
+ task :default => :spec
@@ -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 CommandResultError < StandardError
3
+ # @return [CommandResult] The command that caused the error
4
+ attr_reader :result
5
+
6
+ def initialize(message, result)
7
+ super(message)
8
+ @result = result
9
+ end
10
+ end
11
+ 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,3 @@
1
+ module AwesomeSpawn
2
+ VERSION = "1.0.0"
3
+ 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
@@ -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: