aggkit 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
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
+