process_executer 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 86a47c55d9ddea5ca45bd4126af5e2e09a50348e44d65ef089e6f4eab69eb302
4
+ data.tar.gz: 06b0a7ea4a9a134b5554b4dd673ecc087cf21d255e57dd18aca164644e4df644
5
+ SHA512:
6
+ metadata.gz: 5625c64aee302c872b097ffd4cf88ddaf3b28ebcfd5d1cfc52dacd53ab9ef4cbb323b7d6b985db3038ce2f86eb2891deb6245d7b047bd219e35d09415fa15fa0
7
+ data.tar.gz: 970147ff7974931dacaa0701ca32f5abcc540ade99ed8ca2b1b70b73cfa215bb09540931fc182fb67db13cbc920e17e3b55c9d07180fea98ed6bc0571aed6568
data/.markdownlint.yml ADDED
@@ -0,0 +1,25 @@
1
+ default: true
2
+
3
+ # Unordered list indentation
4
+ MD007: { indent: 4 }
5
+
6
+ # Line length
7
+ MD013: { line_length: 90, tables: false, code_blocks: false }
8
+
9
+ # Heading duplication is allowed for non-sibling headings
10
+ MD024: { siblings_only: true }
11
+
12
+ # Do not allow the specified trailing punctuation in a header
13
+ MD026: { punctuation: '.,;:' }
14
+
15
+ # Order list items must have a prefix that increases in numerical order
16
+ MD029: { style: 'ordered' }
17
+
18
+ # Lists do not need to be surrounded by blank lines
19
+ MD032: false
20
+
21
+ # Allow raw HTML in Markdown
22
+ MD033: false
23
+
24
+ # Allow emphasis to be used instead of a heading
25
+ MD036: false
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,20 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ # Output extra information for each offense to make it easier to diagnose:
4
+ DisplayCopNames: true
5
+ DisplayStyleGuide: true
6
+ ExtraDetails: true
7
+ SuggestExtensions: false
8
+ # RuboCop enforces rules depending on the oldest version of Ruby which
9
+ # your project supports:
10
+ TargetRubyVersion: 2.7
11
+
12
+ # The default max line length is 80 characters
13
+ Layout/LineLength:
14
+ Max: 120
15
+
16
+ # The DSL for RSpec and the gemspec file make it very hard to limit block length:
17
+ Metrics/BlockLength:
18
+ Exclude:
19
+ - "spec/**/*_spec.rb"
20
+ - "*.gemspec"
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --no-private
2
+ --hide-void-return
3
+ --markup-provider=redcarpet
4
+ --markup markdown
5
+ - LICENSE.md
data/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ ## v0.2.0 (2022-11-16)
2
+
3
+ [Full Changelog](https://github.com/main-branch/process_executer/compare/v0.1.0...v0.2.0)
4
+
5
+ * 8b70ac0 Use the create_github_release gem to make the release PR (#2)
6
+ * 4b2700e Add ProcessExecuter#execute to execute a command and return the result (#1)
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in process_executer.gemspec
6
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 James Couball
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # The ProcessExecuter Gem
2
+
3
+ An API for executing commands in a subprocess
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ ```shell
10
+ bundle add process_executer
11
+ ```
12
+
13
+ If bundler is not being used to manage dependencies, install the gem by executing:
14
+
15
+ ```shell
16
+ gem install process_executer
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ See the examples in the project's YARD documentation.
22
+
23
+ ## Development
24
+
25
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
26
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
27
+ prompt that will allow you to experiment.
28
+
29
+ To install this gem onto your local machine, run `bundle exec rake install`. To
30
+ release a new version, update the version number in `version.rb`, and then run
31
+ `bundle exec rake release`, which will create a git tag for the version, push git
32
+ commits and the created tag, and push the `.gem` file to
33
+ [rubygems.org](https://rubygems.org).
34
+
35
+ ## Contributing
36
+
37
+ Bug reports and pull requests are welcome on our
38
+ [GitHub issue tracker](https://github.com/main-branch/process_executer)
39
+
40
+ ## Feature Checklist
41
+
42
+ Here is the 1.0 feature checklist:
43
+
44
+ * [x] Run a command
45
+ * [x] Collect the command's stdout/stderr to a string
46
+ * [x] Passthru the command's stdout/stderr to this process's stdout/stderr
47
+ * [ ] Command execution timeout
48
+ * [ ] Redirect stdout/stderr to a named file
49
+ * [ ] Redirect stdout/stderr to a named file with open mode
50
+ * [ ] Redirect stdout/stderr to a named file with open mode and permissions
51
+ * [ ] Redirect stdout/stderr to an open File object
52
+ * [ ] Merge stdout & stderr
53
+ * [ ] Redirect a file to stdin
54
+ * [ ] Redirect from a butter to stdin
55
+ * [ ] Binary vs. text mode for stdin/stdout/stderr
56
+ * [ ] Environment isolation like Process.spawn
57
+ * [ ] Pass options to Process.spawn (chdir, umask, pgroup, etc.)
58
+ * [ ] Don't allow optionis to Process.spawn that would break the functionality
59
+ (:in, :out, :err, integer, #fileno, :close_others)
60
+
61
+ ## License
62
+
63
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The default task
4
+
5
+ desc 'Run the same tasks that the CI build will run'
6
+ task default: %w[spec rubocop yard yard:audit yard:coverage bundle:audit build]
7
+
8
+ # Bundler Audit
9
+
10
+ require 'bundler/audit/task'
11
+ Bundler::Audit::Task.new
12
+
13
+ # Bundler Gem Build
14
+
15
+ require 'bundler'
16
+ require 'bundler/gem_tasks'
17
+
18
+ begin
19
+ Bundler.setup(:default, :development)
20
+ rescue Bundler::BundlerError => e
21
+ warn e.message
22
+ warn 'Run `bundle install` to install missing gems'
23
+ exit e.status_code
24
+ end
25
+
26
+ CLEAN << 'pkg'
27
+ CLOBBER << 'Gemfile.lock'
28
+
29
+ # Bump
30
+
31
+ require 'bump/tasks'
32
+
33
+ # RSpec
34
+
35
+ require 'rspec/core/rake_task'
36
+
37
+ RSpec::Core::RakeTask.new
38
+
39
+ CLEAN << 'coverage'
40
+ CLEAN << '.rspec_status'
41
+ CLEAN << 'rspec-report.xml'
42
+
43
+ # Rubocop
44
+
45
+ require 'rubocop/rake_task'
46
+
47
+ RuboCop::RakeTask.new do |t|
48
+ t.options = %w[
49
+ --format progress
50
+ --format json --out rubocop-report.json
51
+ ]
52
+ end
53
+
54
+ CLEAN << 'rubocop-report.json'
55
+
56
+ # YARD
57
+
58
+ require 'yard'
59
+ YARD::Rake::YardocTask.new do |t|
60
+ t.files = %w[lib/**/*.rb examples/**/*]
61
+ end
62
+
63
+ CLEAN << '.yardoc'
64
+ CLEAN << 'doc'
65
+
66
+ # Yardstick
67
+
68
+ desc 'Run yardstick to show missing YARD doc elements'
69
+ task :'yard:audit' do
70
+ sh "yardstick 'lib/**/*.rb'"
71
+ end
72
+
73
+ # Yardstick coverage
74
+
75
+ require 'yardstick/rake/verify'
76
+
77
+ Yardstick::Rake::Verify.new(:'yard:coverage') do |verify|
78
+ verify.threshold = 100
79
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ProcessExecuter
4
+ # The result of executing a command
5
+ #
6
+ # @api public
7
+ #
8
+ class Result
9
+ # The status of the command process
10
+ #
11
+ # @example
12
+ # status # => #<Process::Status: pid 86235 exit 0>
13
+ # out = 'hello'
14
+ # err = 'ERROR'
15
+ # command = ProcessExecuter.new(status, out, err)
16
+ # command.status # => #<Process::Status: pid 86235 exit 0>
17
+ #
18
+ # @return [Process::Status]
19
+ #
20
+ attr_reader :status
21
+
22
+ # The command's stdout (if collected)
23
+ #
24
+ # @example
25
+ # status # => #<Process::Status: pid 86235 exit 0>
26
+ # out = 'hello'
27
+ # err = 'ERROR'
28
+ # command = ProcessExecuter.new(status, out, err)
29
+ # command.out # => "hello\n"
30
+ #
31
+ # @return [String, nil]
32
+ #
33
+ attr_reader :out
34
+
35
+ # The command's stderr (if collected)
36
+ #
37
+ # @example
38
+ # status # => #<Process::Status: pid 86235 exit 0>
39
+ # out = 'hello'
40
+ # err = 'ERROR'
41
+ # command = ProcessExecuter.new(status, out, err)
42
+ # command.out # => "ERROR\n"
43
+ #
44
+ # @return [String, nil]
45
+ #
46
+ attr_reader :err
47
+
48
+ # Create a new Result object
49
+ #
50
+ # @example
51
+ # status # => #<Process::Status: pid 86235 exit 0>
52
+ # out = 'hello'
53
+ # err = 'ERROR'
54
+ # command = ProcessExecuter.new(status, out, err)
55
+ #
56
+ # @param status [Process::Status] the status of the command process
57
+ # @param out [String, nil] the command's stdout (if collected)
58
+ # @param err [String, nil] the command's stderr (if collected)
59
+ #
60
+ # @return [ProcessExecuter::Result] the result object
61
+ #
62
+ def initialize(status, out, err)
63
+ @status = status
64
+ @out = out
65
+ @err = err
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ProcessExecuter
4
+ VERSION = '0.2.0'
5
+ end
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Style/SingleLineMethods
4
+
5
+ require 'process_executer/result'
6
+ # require 'nio'
7
+
8
+ # Execute a process and capture the output to a string, a file, and/or
9
+ # pass the output through to this process's stdout/stderr.
10
+ #
11
+ # @api public
12
+ #
13
+ class ProcessExecuter
14
+ # stdout collected from the command
15
+ #
16
+ # @example
17
+ # command = ProcessExecuter.new
18
+ # command.execute('echo hello')
19
+ # command.out # => "hello\n"
20
+ #
21
+ # @return [String, nil] nil if collect_out? is false
22
+ #
23
+ attr_reader :out
24
+
25
+ # stderr collected from the command
26
+ #
27
+ # @example
28
+ # command = ProcessExecuter.new
29
+ # command.execute('echo hello 1>&2')
30
+ # command.err # => "hello\n"
31
+ #
32
+ # @return [String, nil] nil if collect_err? is false
33
+ #
34
+ attr_reader :err
35
+
36
+ # The status of the command process
37
+ #
38
+ # Will be `nil` if the command has not completed execution.
39
+ #
40
+ # @example
41
+ # command = ProcessExecuter.new
42
+ # command.execute('echo hello')
43
+ # command.status # => #<Process::Status: pid 86235 exit 0>
44
+ #
45
+ # @return [Process::Status, nil]
46
+ #
47
+ attr_reader :status
48
+
49
+ # Show the command's stdout on this process's stdout
50
+ #
51
+ # @example
52
+ # command = ProcessExecuter.new(passthru_out: true)
53
+ # command.passthru_out? # => true
54
+ #
55
+ # @return [Boolean]
56
+ #
57
+ def passthru_out?; !!@passthru_out; end
58
+
59
+ # Show the command's stderr on this process's stderr
60
+ #
61
+ # @example
62
+ # command = ProcessExecuter.new(passthru_err: true)
63
+ # command.passthru_err? # => true
64
+ #
65
+ # @return [Boolean]
66
+ #
67
+ def passthru_err?; !!@passthru_err; end
68
+
69
+ # Collect the command's stdout the :out string (default is true)
70
+ #
71
+ # @example
72
+ # command = ProcessExecuter.new(collect_out: false)
73
+ # command.collect_out? # => false
74
+ #
75
+ # @return [Boolean]
76
+ #
77
+ def collect_out?; !!@collect_out; end
78
+
79
+ # Collect the command's stderr the :err string (default is true)
80
+ #
81
+ # @example
82
+ # command = ProcessExecuter.new(collect_err: false)
83
+ # command.collect_err? # => false
84
+ #
85
+ # @return [Boolean]
86
+ #
87
+ def collect_err?; !!@collect_err; end
88
+
89
+ # Create a new ProcessExecuter
90
+ #
91
+ # @example
92
+ # command = ProcessExecuter.new(passthru_out: false, passthru_err: false)
93
+ #
94
+ # @param passthru_out [Boolean] show the command's stdout on this process's stdout
95
+ # @param passthru_err [Boolean] show the command's stderr on this process's stderr
96
+ # @param collect_out [Boolean] collect the command's stdout the :out string
97
+ # @param collect_err [Boolean] collect the command's stderr the :err string
98
+ #
99
+ def initialize(passthru_out: false, passthru_err: false, collect_out: true, collect_err: true)
100
+ @passthru_out = passthru_out
101
+ @passthru_err = passthru_err
102
+ @collect_out = collect_out
103
+ @collect_err = collect_err
104
+ end
105
+
106
+ # rubocop:disable Metrics/AbcSize
107
+ # rubocop:disable Metrics/MethodLength
108
+
109
+ # Execute the given command in a subprocess
110
+ #
111
+ # See Process.spawn for acceptable values for command and options.
112
+ #
113
+ # Do no specify the following options: :in, :out, :err, integer, #fileno, :close_others.
114
+ #
115
+ # @example Execute a command as a single string
116
+ # result = ProcessExecuter.new.execute('echo hello')
117
+ #
118
+ # @example Execute a command as with each argument as a separate string
119
+ # result = ProcessExecuter.new.execute('echo', 'hello')
120
+ #
121
+ # @example Execute a command in a specific directory
122
+ # result = ProcessExecuter.new.execute('pwd', chdir: '/tmp')
123
+ # result.out # => "/tmp\n"
124
+ #
125
+ # @example Execute a command with specific environment variables
126
+ # result = ProcessExecuter.new.execute({ 'FOO' => 'bar' }, 'echo $FOO' )
127
+ # result.out # => "bar\n"
128
+ #
129
+ # @param command [String, Array<String>] the command to pass to Process.spawn
130
+ # @param options [Hash] options to pass to Process.spawn
131
+ #
132
+ # @return [ProcessExecuter::Result] the result of the command execution
133
+ #
134
+ def execute(*command, **options)
135
+ @status = nil
136
+ @out = (collect_out? ? '' : nil)
137
+ @err = (collect_err? ? '' : nil)
138
+
139
+ out_reader, out_writer = IO.pipe
140
+ err_reader, err_writer = IO.pipe
141
+
142
+ options[:out] = out_writer
143
+ options[:err] = err_writer
144
+
145
+ pid = Process.spawn(*command, options)
146
+
147
+ loop do
148
+ read_command_output(out_reader, err_reader)
149
+
150
+ _pid, @status = Process.wait2(pid, Process::WNOHANG)
151
+ break if @status
152
+
153
+ # puts "finished_pid: #{finished_pid}"
154
+ # puts "status: #{status}"
155
+
156
+ # puts 'starting select'
157
+ # readers, writers, exceptions = IO.select([stdout_reader, stderr_reader], nil, nil, 0.1)
158
+ IO.select([out_reader, err_reader], nil, nil, 0.05)
159
+
160
+ # puts "readers: #{readers}"
161
+ # puts "writers: #{writers}"
162
+ # puts "exceptions: #{exceptions}"
163
+
164
+ # break unless readers || writers || exceptions
165
+
166
+ _pid, @status = Process.wait2(pid, Process::WNOHANG)
167
+ break if @status
168
+
169
+ # puts "finished_pid: #{finished_pid}"
170
+ # puts "status: #{status}"
171
+ end
172
+
173
+ out_writer.close
174
+ err_writer.close
175
+
176
+ # Read whatever is left over after the process terminates
177
+ read_command_output(out_reader, err_reader)
178
+ ProcessExecuter::Result.new(@status, @out, @err)
179
+ end
180
+
181
+ # rubocop:enable Metrics/AbcSize
182
+ # rubocop:enable Metrics/MethodLength
183
+
184
+ private
185
+
186
+ # Read output from the given readers
187
+ # @return [void]
188
+ # @api private
189
+ def read_command_output(out_reader, err_reader)
190
+ loop do
191
+ # Keep reading until there is nothing left to read
192
+ break unless read_out(out_reader) || read_err(err_reader)
193
+ end
194
+ end
195
+
196
+ # Read stdout from the given reader
197
+ # @return [void]
198
+ # @api private
199
+ def read_out(reader)
200
+ new_data = reader.read_nonblock(1024)
201
+ # puts "new_stdout: '#{new_data}'"
202
+ @out += new_data if new_data && collect_out?
203
+ puts new_data if new_data && passthru_out?
204
+ true
205
+ rescue EOFError, IO::EAGAINWaitReadable
206
+ # Nothing to read at this time
207
+ false
208
+ end
209
+
210
+ # Read stderr from the given reader
211
+ # @return [void]
212
+ # @api private
213
+ def read_err(reader)
214
+ new_data = reader.read_nonblock(1024)
215
+ # puts "new_stderr: '#{new_data}'"
216
+ @err += new_data if new_data && collect_err?
217
+ warn new_data if new_data && passthru_err?
218
+ true
219
+ rescue EOFError, IO::EAGAINWaitReadable
220
+ # Nothing to read at this time
221
+ false
222
+ end
223
+ end
224
+
225
+ # rubocop:enable Style/SingleLineMethods
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/process_executer/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'process_executer'
7
+ spec.version = ProcessExecuter::VERSION
8
+ spec.authors = ['James Couball']
9
+ spec.email = ['jcouball@yahoo.com']
10
+
11
+ spec.summary = 'An API for executing commands in a subprocess'
12
+ spec.description = 'An API for executing commands in a subprocess'
13
+ spec.homepage = 'https://github.com/main_branch/process_executer'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = '>= 2.7.0'
16
+
17
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
18
+
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = 'https://github.com/main_branch/process_executer'
21
+ spec.metadata['changelog_uri'] = 'https://github.com/main_branch/process_executer'
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(__dir__) do
26
+ `git ls-files -z`.split("\x0").reject do |f|
27
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
28
+ end
29
+ end
30
+ spec.bindir = 'exe'
31
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ['lib']
33
+
34
+ # Uncomment to register a new dependency of your gem
35
+ # spec.add_dependency "example-gem", "~> 1.0"
36
+ spec.add_development_dependency 'bump', '~> 0.10'
37
+ spec.add_development_dependency 'bundler-audit', '~> 0.9'
38
+ spec.add_development_dependency 'create_github_release', '~> 0.2'
39
+ spec.add_development_dependency 'rake', '~> 13.0'
40
+ spec.add_development_dependency 'redcarpet', '~> 3.5'
41
+ spec.add_development_dependency 'rspec', '~> 3.10'
42
+ spec.add_development_dependency 'rubocop', '~> 1.36'
43
+ spec.add_development_dependency 'simplecov', '~> 0.21'
44
+ spec.add_development_dependency 'solargraph', '~> 0.47'
45
+ spec.add_development_dependency 'yard', '~> 0.9'
46
+ spec.add_development_dependency 'yardstick', '~> 0.9'
47
+
48
+ # For more information and examples about making a new gem, check out our
49
+ # guide at: https://bundler.io/guides/creating_gem.html
50
+ spec.metadata['rubygems_mfa_required'] = 'true'
51
+ end
metadata ADDED
@@ -0,0 +1,215 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: process_executer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - James Couball
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-11-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bump
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler-audit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: create_github_release
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '13.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '13.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: redcarpet
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.10'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.10'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.36'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.36'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.21'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.21'
125
+ - !ruby/object:Gem::Dependency
126
+ name: solargraph
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.47'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.47'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.9'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.9'
153
+ - !ruby/object:Gem::Dependency
154
+ name: yardstick
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.9'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '0.9'
167
+ description: An API for executing commands in a subprocess
168
+ email:
169
+ - jcouball@yahoo.com
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".markdownlint.yml"
175
+ - ".rspec"
176
+ - ".rubocop.yml"
177
+ - ".yardopts"
178
+ - CHANGELOG.md
179
+ - Gemfile
180
+ - LICENSE.md
181
+ - README.md
182
+ - Rakefile
183
+ - lib/process_executer.rb
184
+ - lib/process_executer/result.rb
185
+ - lib/process_executer/version.rb
186
+ - process_executer.gemspec
187
+ homepage: https://github.com/main_branch/process_executer
188
+ licenses:
189
+ - MIT
190
+ metadata:
191
+ allowed_push_host: https://rubygems.org
192
+ homepage_uri: https://github.com/main_branch/process_executer
193
+ source_code_uri: https://github.com/main_branch/process_executer
194
+ changelog_uri: https://github.com/main_branch/process_executer
195
+ rubygems_mfa_required: 'true'
196
+ post_install_message:
197
+ rdoc_options: []
198
+ require_paths:
199
+ - lib
200
+ required_ruby_version: !ruby/object:Gem::Requirement
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ version: 2.7.0
205
+ required_rubygems_version: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: '0'
210
+ requirements: []
211
+ rubygems_version: 3.3.7
212
+ signing_key:
213
+ specification_version: 4
214
+ summary: An API for executing commands in a subprocess
215
+ test_files: []