aggkit 0.2.5

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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +20 -0
  3. data/.gitignore +109 -0
  4. data/.gitlab-ci.yml +66 -0
  5. data/.rspec +4 -0
  6. data/.rubocop.yml +98 -0
  7. data/.travis.yml +30 -0
  8. data/Gemfile +12 -0
  9. data/Gemfile.lock +55 -0
  10. data/README.md +96 -0
  11. data/aggkit.gemspec +38 -0
  12. data/bin/agg +167 -0
  13. data/bin/aggconsul +222 -0
  14. data/bin/agglock +71 -0
  15. data/bin/aggmerge +118 -0
  16. data/bin/aggwait +262 -0
  17. data/bin/consul.rb +222 -0
  18. data/bin/locker.rb +71 -0
  19. data/bin/merger.rb +118 -0
  20. data/bin/terminator.rb +71 -0
  21. data/bin/waiter.rb +262 -0
  22. data/docker/Dockerfile +112 -0
  23. data/docker/docker-compose.yml +12 -0
  24. data/docker/down.sh +4 -0
  25. data/docker/run_tests.sh +23 -0
  26. data/lib/aggkit/childprocess/abstract_io.rb +38 -0
  27. data/lib/aggkit/childprocess/abstract_process.rb +194 -0
  28. data/lib/aggkit/childprocess/errors.rb +28 -0
  29. data/lib/aggkit/childprocess/jruby/io.rb +17 -0
  30. data/lib/aggkit/childprocess/jruby/process.rb +161 -0
  31. data/lib/aggkit/childprocess/jruby/pump.rb +55 -0
  32. data/lib/aggkit/childprocess/jruby.rb +58 -0
  33. data/lib/aggkit/childprocess/tools/generator.rb +148 -0
  34. data/lib/aggkit/childprocess/unix/fork_exec_process.rb +72 -0
  35. data/lib/aggkit/childprocess/unix/io.rb +22 -0
  36. data/lib/aggkit/childprocess/unix/lib.rb +188 -0
  37. data/lib/aggkit/childprocess/unix/platform/i386-linux.rb +14 -0
  38. data/lib/aggkit/childprocess/unix/platform/i386-solaris.rb +13 -0
  39. data/lib/aggkit/childprocess/unix/platform/x86_64-linux.rb +14 -0
  40. data/lib/aggkit/childprocess/unix/platform/x86_64-macosx.rb +13 -0
  41. data/lib/aggkit/childprocess/unix/posix_spawn_process.rb +135 -0
  42. data/lib/aggkit/childprocess/unix/process.rb +91 -0
  43. data/lib/aggkit/childprocess/unix.rb +11 -0
  44. data/lib/aggkit/childprocess/version.rb +5 -0
  45. data/lib/aggkit/childprocess/windows/handle.rb +93 -0
  46. data/lib/aggkit/childprocess/windows/io.rb +25 -0
  47. data/lib/aggkit/childprocess/windows/lib.rb +418 -0
  48. data/lib/aggkit/childprocess/windows/process.rb +132 -0
  49. data/lib/aggkit/childprocess/windows/process_builder.rb +177 -0
  50. data/lib/aggkit/childprocess/windows/structs.rb +151 -0
  51. data/lib/aggkit/childprocess/windows.rb +35 -0
  52. data/lib/aggkit/childprocess.rb +213 -0
  53. data/lib/aggkit/env.rb +219 -0
  54. data/lib/aggkit/runner.rb +80 -0
  55. data/lib/aggkit/version.rb +5 -0
  56. data/lib/aggkit/watcher.rb +239 -0
  57. data/lib/aggkit.rb +15 -0
  58. metadata +196 -0
data/bin/waiter.rb ADDED
@@ -0,0 +1,262 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'securerandom'
5
+ require 'English'
6
+ require 'openssl'
7
+ require 'tempfile'
8
+ require 'json'
9
+
10
+ STDOUT.sync = true
11
+ STDERR.sync = true
12
+
13
+ TIMEOUT = 15
14
+ INTERVAL = 3
15
+
16
+ @opts = {}
17
+
18
+ @opts[:exec] = (begin
19
+ ARGV.join(' ').split(' -- ')[1].strip
20
+ rescue StandardError
21
+ nil
22
+ end)
23
+ @opts[:timeout] = TIMEOUT
24
+ @opts[:interval] = INTERVAL
25
+ @opts[:consul_addr] = 'http://localhost:8500'
26
+ @opts[:consul_service_count] = 1
27
+
28
+
29
+ OptionParser.new do |o|
30
+ o.banner = 'Usage: waiter.rb [options] -- exec'
31
+
32
+ o.on('--tcp host:port', 'Wait for tcp accepts on host:port') do |addr|
33
+ host, port = addr.split(':')
34
+ @opts[:tcp] = addr.strip
35
+ @opts[:host] = host.strip
36
+ @opts[:port] = port.strip
37
+ end
38
+
39
+ o.on('--db dbname', 'Wait for PG database exists. Using --tcp to conenct PG') do |db|
40
+ @opts[:db] = db.strip
41
+ end
42
+
43
+ o.on('--tb tablename', 'Wait for PG table exists. Using --tcp to conenct PG') do |tb|
44
+ @opts[:tb] = tb.strip
45
+ end
46
+
47
+ o.on('-f', '--file filename', 'Wait for file exists.') do |file|
48
+ @opts[:file] = file.strip
49
+ end
50
+
51
+ o.on("--consul-addr addr=#{@opts[:consul_addr]}", 'HTTP addres to connect to consul') do |addr|
52
+ @opts[:consul_addr] = addr.strip
53
+ end
54
+
55
+ o.on('--consul', 'Wait for local consul agent to be ready') do
56
+ @opts[:consul] = true
57
+ end
58
+
59
+ o.on('--consul-service service', 'Wait for service appear in consul') do |service|
60
+ @opts[:consul_service] = service
61
+ end
62
+
63
+ o.on("--consul-service-count count=#{@opts[:consul_service_count]}", 'Wait for this count of service appear in consul') do |count|
64
+ @opts[:consul_service_count] = count.to_i
65
+ end
66
+
67
+ o.on('--consul-tag tag', 'Filter consul service by tag') do |tag|
68
+ @opts[:consul_tag] = tag.to_s
69
+ end
70
+
71
+ o.on('--user user', 'username') do |user|
72
+ @opts[:user] = user.strip
73
+ end
74
+
75
+ o.on('--pass pass', 'password') do |pass|
76
+ @opts[:pass] = pass.strip
77
+ end
78
+
79
+ o.on('-t', '--timeout secs=15', 'Total timeout') do |timeout|
80
+ @opts[:timeout] = timeout.to_i
81
+ end
82
+
83
+ o.on('-i', '--interval secs=2', 'Interval between attempts') do |interval|
84
+ @opts[:interval] = interval.to_i
85
+ end
86
+
87
+ o.on('-q', '--quiet', 'Do not output any status messages') do
88
+ @opts[:quiet] = true
89
+ end
90
+ end.parse!
91
+
92
+ def log(message)
93
+ puts message unless @opts[:quiet]
94
+ end
95
+
96
+ @opts[:timeout] = @opts[:timeout].to_i
97
+ @opts[:interval] = @opts[:interval].to_i
98
+
99
+ if @opts[:db]
100
+ @pg = {}
101
+ @pg[:db] = "-d #{@opts[:db]}"
102
+ @pg[:user] = "-U #{@opts[:user]}" if @opts[:user]
103
+ @pg[:pass] = if @opts[:pass] && !@opts[:pass].empty?
104
+ "PGPASSWORD=#{@opts[:pass]}"
105
+ else
106
+ ''
107
+ end
108
+
109
+ @pg[:host] = "-h #{@opts[:host]}" if @opts[:host]
110
+ @pg[:port] = "-p #{@opts[:port]}" if @opts[:port]
111
+
112
+ @pg[:tb] = @opts[:tb] if @opts[:tb]
113
+ end
114
+
115
+ def wait_for(timeout)
116
+ starttime = Time.now
117
+ loop do
118
+ success = yield
119
+
120
+ return success if success
121
+
122
+ return false if (Time.now - starttime) > timeout
123
+ sleep @opts[:interval]
124
+ end
125
+
126
+ false
127
+ end
128
+
129
+ def complete!(success)
130
+ if success
131
+ if @opts[:exec]
132
+ exec @opts[:exec]
133
+ else
134
+ exit 0
135
+ end
136
+ end
137
+
138
+ STDERR.puts 'Operation timed out'
139
+ exit 1
140
+ end
141
+
142
+ def wait_for_consul
143
+ log('Waiting for consul...')
144
+ ret = wait_for @opts[:timeout] do
145
+ cmd = "consul operator raft list-peers -http-addr=#{@opts[:consul_addr]} > /dev/null 2>&1"
146
+ system(cmd)
147
+ $?.success?
148
+ end
149
+
150
+ yield(ret)
151
+ end
152
+
153
+ def wait_for_consul_service(service)
154
+ log("Waiting for consul service #{service}...")
155
+ ret = wait_for @opts[:timeout] do
156
+ cmd = "curl -s #{@opts[:consul_addr]}/v1/health/service/#{service}?passing"
157
+ cmd += "&tag=#{@opts[:consul_tag]}" if @opts[:consul_tag]
158
+ result = `#{cmd}`
159
+ result = begin
160
+ JSON.parse(result)
161
+ rescue StandardError
162
+ []
163
+ end
164
+ result.count >= @opts[:consul_service_count]
165
+ end
166
+
167
+ yield(ret)
168
+ end
169
+
170
+ def wait_for_tcp
171
+ log("Waiting for TCP: #{@opts[:host]}:#{@opts[:port]}...")
172
+ ret = wait_for @opts[:timeout] do
173
+ cmd = "nc -z #{@opts[:host]} #{@opts[:port]} > /dev/null 2>&1"
174
+ system(cmd)
175
+ $?.success?
176
+ end
177
+
178
+ yield(ret)
179
+ end
180
+
181
+ def wait_for_db
182
+ log("Waiting for DB: pg://#{@opts[:user]}:#{@opts[:pass]}@#{@opts[:host]}:#{@opts[:port]}/#{@opts[:db]}...")
183
+ ret = wait_for @opts[:timeout] do
184
+ cmd = "#{@pg[:pass]} psql -lqt #{@pg[:user]} #{@pg[:host]} #{@pg[:port]} #{@pg[:db]} 2>/dev/null | cut -d \\| -f 1 | grep -qw #{@opts[:db]} > /dev/null 2>&1"
185
+ system(cmd)
186
+ $?.success?
187
+ end
188
+
189
+ yield(ret)
190
+ end
191
+
192
+ def wait_for_tb
193
+ log("Waiting for TABLE: pg://#{@opts[:user]}:#{@opts[:pass]}@#{@opts[:host]}:#{@opts[:port]}/#{@opts[:db]}##{@opts[:tb]}...")
194
+ ret = wait_for @opts[:timeout] do
195
+ cmd = "echo \"\\dt\" | psql -qt #{@pg[:user]} #{@pg[:pass]} #{@pg[:host]} #{@pg[:port]} #{@pg[:db]} 2>/dev/null | cut -d \\| -f 2 | grep -qw #{@pg[:tb]} > /dev/null 2>&1"
196
+ system(cmd)
197
+ $?.success?
198
+ end
199
+
200
+ yield(ret)
201
+ end
202
+
203
+ def wait_for_file(file = @opts[:file], timeout = @opts[:timeout])
204
+ log("Waiting for FILE: #{file}")
205
+ ret = wait_for timeout do
206
+ File.exist? file
207
+ end
208
+ yield(ret)
209
+ end
210
+
211
+ if @opts[:tb]
212
+ wait_for_tcp do |success|
213
+ if success
214
+ wait_for_db do |success|
215
+ if success
216
+ wait_for_tb do |success|
217
+ complete!(success)
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ complete!(false)
224
+ end
225
+ end
226
+
227
+ if @opts[:db]
228
+ wait_for_tcp do |success|
229
+ if success
230
+ wait_for_db do |success|
231
+ complete!(success)
232
+ end
233
+ end
234
+
235
+ complete!(false)
236
+ end
237
+ end
238
+
239
+
240
+ if @opts[:consul]
241
+ wait_for_consul do |success|
242
+ complete!(success)
243
+ end
244
+ end
245
+
246
+ if @opts[:consul_service]
247
+ wait_for_consul_service(@opts[:consul_service]) do |success|
248
+ complete!(success)
249
+ end
250
+ end
251
+
252
+ if @opts[:tcp]
253
+ wait_for_tcp do |success|
254
+ complete!(success)
255
+ end
256
+ end
257
+
258
+ if @opts[:file]
259
+ wait_for_file(@opts[:file], @opts[:timeout]) do |success|
260
+ complete!(success)
261
+ end
262
+ end
data/docker/Dockerfile ADDED
@@ -0,0 +1,112 @@
1
+ FROM alpine:3.8
2
+ MAINTAINER Firmhouse "kinnalru@gmail.com"
3
+
4
+ WORKDIR /home/app
5
+
6
+ RUN mkdir -p ~/.ssh && echo -e "Host * \
7
+ \n StrictHostKeyChecking no \
8
+ \n UserKnownHostsFile=/dev/null\n" >> ~/.ssh/config
9
+
10
+ RUN set -ex \
11
+ && apk add --no-cache \
12
+ alpine-sdk \
13
+ bash \
14
+ curl \
15
+ gcc \
16
+ git \
17
+ gnupg \
18
+ libcurl \
19
+ libstdc++ \
20
+ libxml2 \
21
+ linux-headers \
22
+ make \
23
+ openssl \
24
+ openssl-dev \
25
+ procps \
26
+ ruby \
27
+ ruby-libs \
28
+ shadow \
29
+ tzdata \
30
+ wget
31
+
32
+ RUN set -ex \
33
+ && gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB \
34
+ && ln -sf /bin/bash /bin/ash \
35
+ && ln -sf /bin/bash /bin/sh \
36
+ && sed -i s%bin\\/ash%bin\\/bash%g /etc/passwd
37
+
38
+ SHELL ["/bin/bash", "-c", "-l"]
39
+
40
+ RUN set -ex \
41
+ && apk add --no-cache --virtual .builddeps \
42
+ alpine-sdk \
43
+ curl \
44
+ gcc \
45
+ libssl1.0 \
46
+ linux-headers \
47
+ make \
48
+ musl-dev \
49
+ openssl \
50
+ openssl-dev \
51
+ procps \
52
+ ruby \
53
+ zlib \
54
+ zlib-dev \
55
+ sqlite sqlite-dev libtool autoconf automake bison readline yaml ncurses \
56
+ && curl -sSL https://get.rvm.io | bash -s stable --autolibs=0 \
57
+ && usermod -a -G rvm root \
58
+ && set +x \
59
+ && source /etc/profile && source /etc/profile.d/rvm.sh \
60
+ && export PATH=$PATH:/usr/local/rvm/bin \
61
+ && rvm install 2.1 && rvm use 2.1 && gem install bundler -v 1.17.3 \
62
+ && rvm install 2.5 && rvm use 2.5 && gem install bundler \
63
+ && rvm use --default 2.5 \
64
+ && set -x \
65
+ && apk del .builddeps \
66
+ && gem cleanup \
67
+ && rm -rf /tmp/* /var/tmp/* /usr/src/ruby /root/.gem /usr/local/bundle/cache
68
+
69
+ RUN mkdir -p /usr/local/etc \
70
+ && { \
71
+ echo 'install: --no-document'; \
72
+ echo 'update: --no-document'; \
73
+ } >> /usr/local/etc/gemrc \
74
+ && echo 'gem: --no-ri --no-rdoc' > ~/.gemrc
75
+
76
+ RUN set -ex \
77
+ && curl -sSLo /tmp/consul.zip https://releases.hashicorp.com/consul/1.2.1/consul_1.2.1_linux_amd64.zip \
78
+ && unzip -d /bin /tmp/consul.zip \
79
+ && rm -rf /tmp/consul.zip \
80
+ && addgroup consul \
81
+ && adduser -D -g "" -s /bin/sh -G consul consul \
82
+ && mkdir -p /tmp/consul \
83
+ && chown -R consul:consul /tmp/consul
84
+
85
+ RUN set -ex \
86
+ && curl -so envconsul.tgz https://releases.hashicorp.com/envconsul/0.7.3/envconsul_0.7.3_linux_amd64.tgz \
87
+ && tar -xvzf envconsul.tgz \
88
+ && rm -rf envconsul.tgz \
89
+ && mv envconsul /bin/envconsul \
90
+ && chmod +x /bin/envconsul
91
+
92
+ ADD Gemfile Gemfile.lock aggkit.gemspec /home/app/
93
+ ADD lib/ /home/app/lib
94
+
95
+
96
+ RUN set -e \
97
+ && source /etc/profile && source /etc/profile.d/rvm.sh \
98
+ && rvm use 2.1 && bundle install \
99
+ && rvm use 2.5 && bundle install
100
+
101
+ ADD . /home/app
102
+
103
+ RUN set -e \
104
+ && rvm use 2.1 \
105
+ && gem build `ls | grep gemspec` && gem install `ls | grep -e '.gem$'` \
106
+ && rvm use 2.5 \
107
+ && gem build `ls | grep gemspec` && gem install `ls | grep -e '.gem$'`
108
+
109
+ CMD ["/bin/bash"]
110
+
111
+
112
+
@@ -0,0 +1,12 @@
1
+ version: "2"
2
+ services:
3
+ tests:
4
+ build:
5
+ context: ../
6
+ dockerfile: docker/Dockerfile
7
+ image: aggkit_tests:latest
8
+ working_dir: /home/app
9
+ command: ["tail", "-f", "/dev/null"]
10
+
11
+
12
+
data/docker/down.sh ADDED
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ docker-compose down -v || true
3
+
4
+
@@ -0,0 +1,23 @@
1
+ #!/bin/sh
2
+ SELF=$(readlink -f $0)
3
+ export ENV_ROOT=$(dirname "${SELF}")
4
+
5
+ trap '$ENV_ROOT/down.sh' EXIT
6
+
7
+ cd $ENV_ROOT
8
+
9
+ if [ -z "${RUBY_VERSION}" ]; then
10
+ export RUBY_VERSION=2.5
11
+ fi
12
+
13
+ docker-compose up -d --force-recreate --build || exit 1
14
+ echo "\n ** Testing with Ruby $RUBY_VERSION **\n"
15
+ docker-compose exec -T tests /bin/bash -c -l "rvm use $RUBY_VERSION; exec bundle exec rspec $@"
16
+
17
+
18
+ code=$?
19
+ if [ $code -ne 0 ]; then
20
+ docker-compose logs
21
+ fi
22
+
23
+ exit $code
@@ -0,0 +1,38 @@
1
+ module Aggkit
2
+ module ChildProcess
3
+ class AbstractIO
4
+ attr_reader :stderr, :stdout, :stdin
5
+
6
+ def inherit!
7
+ @stdout = STDOUT
8
+ @stderr = STDERR
9
+ end
10
+
11
+ def stderr=(io)
12
+ check_type io
13
+ @stderr = io
14
+ end
15
+
16
+ def stdout=(io)
17
+ check_type io
18
+ @stdout = io
19
+ end
20
+
21
+ #
22
+ # @api private
23
+ #
24
+
25
+ def _stdin=(io)
26
+ check_type io
27
+ @stdin = io
28
+ end
29
+
30
+ private
31
+
32
+ def check_type(io)
33
+ raise SubclassResponsibility, "check_type"
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,194 @@
1
+ module Aggkit
2
+ module ChildProcess
3
+ class AbstractProcess
4
+ POLL_INTERVAL = 0.1
5
+
6
+ attr_reader :exit_code
7
+
8
+ #
9
+ # Set this to true if you do not care about when or if the process quits.
10
+ #
11
+ attr_accessor :detach
12
+
13
+ #
14
+ # Set this to true if you want to write to the process' stdin (process.io.stdin)
15
+ #
16
+ attr_accessor :duplex
17
+
18
+ #
19
+ # Modify the child's environment variables
20
+ #
21
+ attr_reader :environment
22
+
23
+ #
24
+ # Set the child's current working directory.
25
+ #
26
+ attr_accessor :cwd
27
+
28
+ #
29
+ # Set this to true to make the child process the leader of a new process group
30
+ #
31
+ # This can be used to make sure that all grandchildren are killed
32
+ # when the child process dies.
33
+ #
34
+ attr_accessor :leader
35
+
36
+ #
37
+ # Create a new process with the given args.
38
+ #
39
+ # @api private
40
+ # @see ChildProcess.build
41
+ #
42
+
43
+ def initialize(args)
44
+ unless args.all? { |e| e.kind_of?(String) }
45
+ raise ArgumentError, "all arguments must be String: #{args.inspect}"
46
+ end
47
+
48
+ @args = args
49
+ @started = false
50
+ @exit_code = nil
51
+ @io = nil
52
+ @cwd = nil
53
+ @detach = false
54
+ @duplex = false
55
+ @leader = false
56
+ @environment = {}
57
+ end
58
+
59
+ #
60
+ # Returns a ChildProcess::AbstractIO subclass to configure the child's IO streams.
61
+ #
62
+
63
+ def io
64
+ raise SubclassResponsibility, "io"
65
+ end
66
+
67
+ #
68
+ # @return [Integer] the pid of the process after it has started
69
+ #
70
+
71
+ def pid
72
+ raise SubclassResponsibility, "pid"
73
+ end
74
+
75
+ #
76
+ # Launch the child process
77
+ #
78
+ # @return [AbstractProcess] self
79
+ #
80
+
81
+ def start
82
+ launch_process
83
+ @started = true
84
+
85
+ self
86
+ end
87
+
88
+ #
89
+ # Forcibly terminate the process, using increasingly harsher methods if possible.
90
+ #
91
+ # @param [Integer] timeout (3) Seconds to wait before trying the next method.
92
+ #
93
+
94
+ def stop(timeout = 3)
95
+ raise SubclassResponsibility, "stop"
96
+ end
97
+
98
+ #
99
+ # Block until the process has been terminated.
100
+ #
101
+ # @return [Integer] The exit status of the process
102
+ #
103
+
104
+ def wait
105
+ raise SubclassResponsibility, "wait"
106
+ end
107
+
108
+ #
109
+ # Did the process exit?
110
+ #
111
+ # @return [Boolean]
112
+ #
113
+
114
+ def exited?
115
+ raise SubclassResponsibility, "exited?"
116
+ end
117
+
118
+ #
119
+ # Has the process started?
120
+ #
121
+ # @return [Boolean]
122
+ #
123
+
124
+ def started?
125
+ @started
126
+ end
127
+
128
+ #
129
+ # Is this process running?
130
+ #
131
+ # @return [Boolean]
132
+ #
133
+
134
+ def alive?
135
+ started? && !exited?
136
+ end
137
+
138
+ #
139
+ # Returns true if the process has exited and the exit code was not 0.
140
+ #
141
+ # @return [Boolean]
142
+ #
143
+
144
+ def crashed?
145
+ exited? && @exit_code != 0
146
+ end
147
+
148
+ #
149
+ # Wait for the process to exit, raising a ChildProcess::TimeoutError if
150
+ # the timeout expires.
151
+ #
152
+
153
+ def poll_for_exit(timeout)
154
+ log "polling #{timeout} seconds for exit"
155
+
156
+ end_time = Time.now + timeout
157
+ until (ok = exited?) || Time.now > end_time
158
+ sleep POLL_INTERVAL
159
+ end
160
+
161
+ unless ok
162
+ raise TimeoutError, "process still alive after #{timeout} seconds"
163
+ end
164
+ end
165
+
166
+ private
167
+
168
+ def launch_process
169
+ raise SubclassResponsibility, "launch_process"
170
+ end
171
+
172
+ def detach?
173
+ @detach
174
+ end
175
+
176
+ def duplex?
177
+ @duplex
178
+ end
179
+
180
+ def leader?
181
+ @leader
182
+ end
183
+
184
+ def log(*args)
185
+ ChildProcess.logger.debug "#{self.inspect} : #{args.inspect}"
186
+ end
187
+
188
+ def assert_started
189
+ raise Error, "process not started" unless started?
190
+ end
191
+
192
+ end # AbstractProcess
193
+ end # ChildProcess
194
+ end
@@ -0,0 +1,28 @@
1
+ module Aggkit
2
+ module ChildProcess
3
+ class Error < StandardError
4
+ end
5
+
6
+ class TimeoutError < Error
7
+ end
8
+
9
+ class SubclassResponsibility < Error
10
+ end
11
+
12
+ class InvalidEnvironmentVariable < Error
13
+ end
14
+
15
+ class LaunchError < Error
16
+ end
17
+
18
+ class MissingPlatformError < Error
19
+ def initialize
20
+ message = "posix_spawn is not yet supported on #{ChildProcess.platform_name} (#{RUBY_PLATFORM}), falling back to default implementation. " +
21
+ "If you believe this is an error, please file a bug at http://github.com/enkessler/childprocess/issues"
22
+
23
+ super(message)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module Aggkit
2
+ module ChildProcess
3
+ module JRuby
4
+ class IO < AbstractIO
5
+ private
6
+
7
+ def check_type(output)
8
+ unless output.respond_to?(:to_outputstream) && output.respond_to?(:write)
9
+ raise ArgumentError, "expected #{output.inspect} to respond to :to_outputstream"
10
+ end
11
+ end
12
+
13
+ end # IO
14
+ end # Unix
15
+ end # ChildProcess
16
+ end
17
+