mongoid 8.1.10 → 8.1.11
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 +4 -4
- data/Rakefile +9 -9
- data/lib/mongoid/association/embedded/embeds_one/proxy.rb +1 -1
- data/lib/mongoid/contextual/mongo.rb +1 -1
- data/lib/mongoid/validatable/associated.rb +1 -1
- data/lib/mongoid/validatable/macros.rb +15 -0
- data/lib/mongoid/validatable/numericality.rb +19 -0
- data/lib/mongoid/validatable.rb +1 -0
- data/lib/mongoid/version.rb +5 -1
- data/spec/integration/app_spec.rb +6 -0
- data/spec/integration/associations/embeds_one_spec.rb +25 -5
- data/spec/mongoid/association_spec.rb +0 -60
- data/spec/mongoid/contextual/mongo_spec.rb +6 -0
- data/spec/mongoid/validatable/numericality_spec.rb +16 -0
- data/spec/shared/LICENSE +20 -0
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/bin/s3-copy +45 -0
- data/spec/shared/bin/s3-upload +69 -0
- data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
- data/spec/shared/lib/mrss/cluster_config.rb +231 -0
- data/spec/shared/lib/mrss/constraints.rb +378 -0
- data/spec/shared/lib/mrss/docker_runner.rb +298 -0
- data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
- data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
- data/spec/shared/lib/mrss/release/candidate.rb +281 -0
- data/spec/shared/lib/mrss/release/product_data.rb +144 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
- data/spec/shared/lib/mrss/session_registry.rb +69 -0
- data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
- data/spec/shared/lib/mrss/utils.rb +37 -0
- data/spec/shared/lib/tasks/candidate.rake +64 -0
- data/spec/shared/share/Dockerfile.erb +251 -0
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/config.sh +27 -0
- data/spec/shared/shlib/distro.sh +84 -0
- data/spec/shared/shlib/server.sh +423 -0
- data/spec/shared/shlib/set_env.sh +110 -0
- data/spec/support/expectations.rb +20 -17
- metadata +58 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21db50efa946dce1a9e43718d0e15d37c0e4373c9d693123d21cfe13b8afb3bf
|
4
|
+
data.tar.gz: 7d01ee5d5a8eb3c81a92c3055e94bf8bb90a8a911258401459b5e447c45a220c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1e10a0cb03863509acb1d150460e4f7c475092b45bb65f7619ecd8f0384d4ed6e92416565a07e6e900af26fbf26b32c4cd2c9418c4dfbe1f858da451a3e9378
|
7
|
+
data.tar.gz: e2e75603f8ba8f3debead96161f81350ced4696aac125ba0b17f48a94a42cc48e867651deb1b6a60c3d57f48fa237f26ac61775f3c2be3750f62fc2b66d27661
|
data/Rakefile
CHANGED
@@ -10,16 +10,16 @@ $: << File.join(ROOT, 'spec/shared/lib')
|
|
10
10
|
require "rake"
|
11
11
|
require "rspec/core/rake_task"
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
if File.exist?('./spec/shared/lib/tasks/candidate.rake')
|
14
|
+
load 'spec/shared/lib/tasks/candidate.rake'
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Build the gem'
|
17
18
|
task :build do
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
WARNING
|
19
|
+
command = %w[ gem build ]
|
20
|
+
command << "--output=#{ENV['GEM_FILE_NAME']}" if ENV['GEM_FILE_NAME']
|
21
|
+
command << (ENV['GEMSPEC'] || 'mongoid.gemspec')
|
22
|
+
system(*command)
|
23
23
|
end
|
24
24
|
|
25
25
|
# `rake version` is used by the deployment system so get the release version
|
@@ -1091,7 +1091,7 @@ module Mongoid
|
|
1091
1091
|
end
|
1092
1092
|
|
1093
1093
|
def retrieve_nth_to_last_with_limit(n, limit)
|
1094
|
-
v = view.sort(inverse_sorting).
|
1094
|
+
v = view.sort(inverse_sorting).limit(limit || 1)
|
1095
1095
|
v = v.skip(n) if n > 0
|
1096
1096
|
raw_docs = v.to_a.reverse
|
1097
1097
|
process_raw_docs(raw_docs, limit)
|
@@ -73,7 +73,7 @@ module Mongoid
|
|
73
73
|
# use map.all? instead of just all?, because all? will do short-circuit
|
74
74
|
# evaluation and terminate on the first failed validation.
|
75
75
|
list.map do |value|
|
76
|
-
if value && !value.flagged_for_destroy?
|
76
|
+
if value && !value.flagged_for_destroy? && (!value.persisted? || value.changed?)
|
77
77
|
value.validated? ? true : value.valid?
|
78
78
|
else
|
79
79
|
true
|
@@ -84,6 +84,21 @@ module Mongoid
|
|
84
84
|
def validates_presence_of(*args)
|
85
85
|
validates_with(PresenceValidator, _merge_attributes(args))
|
86
86
|
end
|
87
|
+
|
88
|
+
# Validates whether or not a field contains a numeric value.
|
89
|
+
#
|
90
|
+
# @example
|
91
|
+
# class Person
|
92
|
+
# include Mongoid::Document
|
93
|
+
# field :cost
|
94
|
+
#
|
95
|
+
# validates_numericality_of :cost
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# @param [ Object... ] *args The names of the field(s) to validate.
|
99
|
+
def validates_numericality_of(*args)
|
100
|
+
validates_with(NumericalityValidator, _merge_attributes(args))
|
101
|
+
end
|
87
102
|
end
|
88
103
|
end
|
89
104
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Validatable
|
5
|
+
# A specialization of the ActiveModel numericality validator, which adds
|
6
|
+
# logic to recognize and accept BSON::Decimal128 as a number.
|
7
|
+
class NumericalityValidator < ActiveModel::Validations::NumericalityValidator
|
8
|
+
private
|
9
|
+
|
10
|
+
# Ensure that BSON::Decimal128 is treated as a BigDecimal during the
|
11
|
+
# validation step.
|
12
|
+
def prepare_value_for_validation(value, record, attr_name)
|
13
|
+
result = super
|
14
|
+
|
15
|
+
result.is_a?(BSON::Decimal128) ? result.to_big_decimal : result
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/mongoid/validatable.rb
CHANGED
@@ -5,6 +5,7 @@ require "mongoid/validatable/localizable"
|
|
5
5
|
require "mongoid/validatable/associated"
|
6
6
|
require "mongoid/validatable/format"
|
7
7
|
require "mongoid/validatable/length"
|
8
|
+
require "mongoid/validatable/numericality"
|
8
9
|
require "mongoid/validatable/queryable"
|
9
10
|
require "mongoid/validatable/presence"
|
10
11
|
require "mongoid/validatable/uniqueness"
|
data/lib/mongoid/version.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Mongoid
|
4
|
-
|
4
|
+
# The current version of Mongoid
|
5
|
+
#
|
6
|
+
# Note that this file is automatically updated via `rake candidate:create`.
|
7
|
+
# Manual changes to this file will be overwritten by that rake task.
|
8
|
+
VERSION = '8.1.11'
|
5
9
|
end
|
@@ -95,6 +95,12 @@ describe 'Mongoid application tests' do
|
|
95
95
|
end
|
96
96
|
|
97
97
|
context 'new application - rails' do
|
98
|
+
before(:all) do
|
99
|
+
if SpecConfig.instance.rails_version < '7.1'
|
100
|
+
skip '`rails new` with rails < 7.1 fails because modern concurrent-ruby removed logger dependency'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
98
104
|
it 'creates' do
|
99
105
|
install_rails
|
100
106
|
|
@@ -3,8 +3,7 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe 'embeds_one associations' do
|
6
|
-
|
7
|
-
context 're-associating the same object' do
|
6
|
+
context 'when re-associating the same object' do
|
8
7
|
context 'with dependent: destroy' do
|
9
8
|
let(:canvas) do
|
10
9
|
Canvas.create!(palette: Palette.new)
|
@@ -16,7 +15,7 @@ describe 'embeds_one associations' do
|
|
16
15
|
canvas.palette = canvas.palette
|
17
16
|
canvas.save!
|
18
17
|
canvas.reload
|
19
|
-
canvas.palette.
|
18
|
+
expect(canvas.palette).to eq palette
|
20
19
|
end
|
21
20
|
end
|
22
21
|
end
|
@@ -30,12 +29,33 @@ describe 'embeds_one associations' do
|
|
30
29
|
end
|
31
30
|
|
32
31
|
it 'loads the association correctly' do
|
33
|
-
expect { klass }.
|
34
|
-
expect { klass.new.address }.
|
32
|
+
expect { klass }.not_to raise_error
|
33
|
+
expect { klass.new.address }.not_to raise_error
|
35
34
|
instance = klass.new
|
36
35
|
address = Address.new
|
37
36
|
instance.address = address
|
38
37
|
expect(instance.address).to eq address
|
39
38
|
end
|
40
39
|
end
|
40
|
+
|
41
|
+
context 'when parent is persisted' do
|
42
|
+
let!(:person) do
|
43
|
+
Person.create!
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when assigning the new child' do
|
47
|
+
context 'when assigning an attribute to the child' do
|
48
|
+
before do
|
49
|
+
# person.reload
|
50
|
+
person.name = Name.new
|
51
|
+
person.name.first_name = 'Dmitry'
|
52
|
+
person.save!
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'persists the child' do
|
56
|
+
expect(person.reload.name.first_name).to eq 'Dmitry'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
41
61
|
end
|
@@ -100,66 +100,6 @@ describe Mongoid::Association do
|
|
100
100
|
expect(name).to_not be_an_embedded_many
|
101
101
|
end
|
102
102
|
end
|
103
|
-
|
104
|
-
context "when validation depends on association" do
|
105
|
-
before(:all) do
|
106
|
-
class Author
|
107
|
-
include Mongoid::Document
|
108
|
-
embeds_many :books, cascade_callbacks: true
|
109
|
-
field :condition, type: Boolean
|
110
|
-
end
|
111
|
-
|
112
|
-
class Book
|
113
|
-
include Mongoid::Document
|
114
|
-
embedded_in :author
|
115
|
-
validate :parent_condition_is_not_true
|
116
|
-
|
117
|
-
def parent_condition_is_not_true
|
118
|
-
return unless author&.condition
|
119
|
-
errors.add :base, "Author condition is true."
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
Author.delete_all
|
124
|
-
Book.delete_all
|
125
|
-
end
|
126
|
-
|
127
|
-
let(:author) { Author.new }
|
128
|
-
let(:book) { Book.new }
|
129
|
-
|
130
|
-
context "when author is not persisted" do
|
131
|
-
it "is valid without books" do
|
132
|
-
expect(author.valid?).to be true
|
133
|
-
end
|
134
|
-
|
135
|
-
it "is valid with a book" do
|
136
|
-
author.books << book
|
137
|
-
expect(author.valid?).to be true
|
138
|
-
end
|
139
|
-
|
140
|
-
it "is not valid when condition is true with a book" do
|
141
|
-
author.condition = true
|
142
|
-
author.books << book
|
143
|
-
expect(author.valid?).to be false
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
context "when author is persisted" do
|
148
|
-
before do
|
149
|
-
author.books << book
|
150
|
-
author.save
|
151
|
-
end
|
152
|
-
|
153
|
-
it "remains valid initially" do
|
154
|
-
expect(author.valid?).to be true
|
155
|
-
end
|
156
|
-
|
157
|
-
it "becomes invalid when condition is set to true" do
|
158
|
-
author.update_attributes(condition: true)
|
159
|
-
expect(author.valid?).to be false
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
103
|
end
|
164
104
|
|
165
105
|
describe "#embedded_one?" do
|
@@ -3387,6 +3387,12 @@ describe Mongoid::Contextual::Mongo do
|
|
3387
3387
|
it "limits the results" do
|
3388
3388
|
expect(context.skip(1).entries).to eq([ new_order ])
|
3389
3389
|
end
|
3390
|
+
|
3391
|
+
context "with #last" do
|
3392
|
+
it "returns the nth from last element" do
|
3393
|
+
expect(context.skip(1).last).to eq(depeche_mode)
|
3394
|
+
end
|
3395
|
+
end
|
3390
3396
|
end
|
3391
3397
|
|
3392
3398
|
describe "#sort" do
|
@@ -28,5 +28,21 @@ describe ActiveModel::Validations::NumericalityValidator do
|
|
28
28
|
expect(model).to_not be_valid
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
context 'when the value is numeric' do
|
33
|
+
let(:model) { TestModel.new(amount: '15.0') }
|
34
|
+
|
35
|
+
it 'returns true' do
|
36
|
+
expect(model).to be_valid
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when the value is a BSON::Decimal128' do
|
41
|
+
let(:model) { TestModel.new(amount: BSON::Decimal128.new('15.0')) }
|
42
|
+
|
43
|
+
it 'returns true' do
|
44
|
+
expect(model).to be_valid
|
45
|
+
end
|
46
|
+
end
|
31
47
|
end
|
32
48
|
end
|
data/spec/shared/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2020 MongoDB, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
desired_version, arch = ARGV
|
4
|
+
if arch.nil?
|
5
|
+
STDERR.puts "Usage: get-mongodb-download-url desired-version arch"
|
6
|
+
exit 1
|
7
|
+
end
|
8
|
+
|
9
|
+
$: << File.join(File.dirname(__FILE__), '../lib')
|
10
|
+
require 'mrss/server_version_registry'
|
11
|
+
|
12
|
+
begin
|
13
|
+
puts Mrss::ServerVersionRegistry.new(desired_version, arch).download_url
|
14
|
+
rescue Mrss::ServerVersionRegistry::Error => exc
|
15
|
+
STDERR.puts "Error: #{exc}"
|
16
|
+
exit 2
|
17
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'aws-sdk-s3'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: s3-copy options"
|
9
|
+
|
10
|
+
opts.on("-r", "--region=REGION", "AWS region to use (default us-east-1)") do |v|
|
11
|
+
options[:region] = v
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on("-p", "--param=KEY=VALUE", "Specify parameter for new files") do |v|
|
15
|
+
options[:params] ||= {}
|
16
|
+
k, v = v.split('=', 2)
|
17
|
+
options[:params][k.to_sym] = v
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-f", "--from=BUCKET:PATH", "Bucket name and key (or path) to copy from") do |v|
|
21
|
+
options[:from] = v
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-t", "--to=BUCKET:PATH", "Bucket name and key (or path) to write to (may be specified more than once)") do |v|
|
25
|
+
options[:to] ||= []
|
26
|
+
options[:to] << v
|
27
|
+
end
|
28
|
+
end.parse!
|
29
|
+
|
30
|
+
ENV['AWS_REGION'] ||= options[:region] || 'us-east-1'
|
31
|
+
|
32
|
+
bucket, key = options.fetch(:from).split(':', 2)
|
33
|
+
|
34
|
+
s3 = Aws::S3::Client.new
|
35
|
+
|
36
|
+
options.fetch(:to).each do |dest|
|
37
|
+
STDERR.puts "Copying to #{dest}"
|
38
|
+
dbucket, dkey = dest.split(':', 2)
|
39
|
+
s3.copy_object(
|
40
|
+
bucket: dbucket,
|
41
|
+
key: dkey,
|
42
|
+
copy_source: "/#{bucket}/#{key}",
|
43
|
+
**options[:params] || {},
|
44
|
+
)
|
45
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'aws-sdk-s3'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: s3-upload options"
|
9
|
+
|
10
|
+
opts.on("-r", "--region=REGION", "AWS region to use (default us-east-1)") do |v|
|
11
|
+
options[:region] = v
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on("-p", "--param=KEY=VALUE", "Specify parameter for S3 upload") do |v|
|
15
|
+
options[:params] ||= {}
|
16
|
+
k, v = v.split('=', 2)
|
17
|
+
options[:params][k.to_sym] = v
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-f", "--file=PATH", "Path to the file to upload, - to upload standard input") do |v|
|
21
|
+
options[:file] = v
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-w", "--write=BUCKET:PATH", "Bucket name and key (or path) to upload to") do |v|
|
25
|
+
options[:write] = v
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-c", "--copy=BUCKET:PATH", "Bucket name and key (or path) to copy to (may be specified more than once)") do |v|
|
29
|
+
options[:copy] ||= []
|
30
|
+
options[:copy] << v
|
31
|
+
end
|
32
|
+
end.parse!
|
33
|
+
|
34
|
+
ENV['AWS_REGION'] ||= options[:region] || 'us-east-1'
|
35
|
+
|
36
|
+
def upload(f, options)
|
37
|
+
s3 = Aws::S3::Client.new
|
38
|
+
write = options.fetch(:write)
|
39
|
+
STDERR.puts "Writing #{write}"
|
40
|
+
bucket, key = write.split(':', 2)
|
41
|
+
s3.put_object(
|
42
|
+
body: f.read,
|
43
|
+
bucket: bucket,
|
44
|
+
key: key,
|
45
|
+
**options[:params] || {},
|
46
|
+
)
|
47
|
+
if copy = options[:copy]
|
48
|
+
copy.each do |dest|
|
49
|
+
STDERR.puts "Copying to #{dest}"
|
50
|
+
dbucket, dkey = dest.split(':', 2)
|
51
|
+
s3.copy_object(
|
52
|
+
bucket: dbucket,
|
53
|
+
key: dkey,
|
54
|
+
copy_source: "/#{bucket}/#{key}",
|
55
|
+
**options[:params] || {},
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
if options[:file] == '-'
|
62
|
+
upload(STDIN, options)
|
63
|
+
elsif options[:file]
|
64
|
+
File.open(options[:file]) do |f|
|
65
|
+
upload(f, options)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
upload(STDIN, options)
|
69
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
autoload :ChildProcess, 'childprocess'
|
5
|
+
autoload :Tempfile, 'tempfile'
|
6
|
+
|
7
|
+
module Mrss
|
8
|
+
module ChildProcessHelper
|
9
|
+
class SpawnError < StandardError; end
|
10
|
+
|
11
|
+
module_function def call(cmd, env: nil, cwd: nil)
|
12
|
+
process = ChildProcess.new(*cmd)
|
13
|
+
process.io.inherit!
|
14
|
+
if cwd
|
15
|
+
process.cwd = cwd
|
16
|
+
end
|
17
|
+
if env
|
18
|
+
env.each do |k, v|
|
19
|
+
process.environment[k.to_s] = v
|
20
|
+
end
|
21
|
+
end
|
22
|
+
process.start
|
23
|
+
process.wait
|
24
|
+
process
|
25
|
+
end
|
26
|
+
|
27
|
+
module_function def check_call(cmd, env: nil, cwd: nil)
|
28
|
+
process = call(cmd, env: env, cwd: cwd)
|
29
|
+
unless process.exit_code == 0
|
30
|
+
raise SpawnError, "Failed to execute: #{cmd}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module_function def get_output(cmd, env: nil, cwd: nil)
|
35
|
+
process = ChildProcess.new(*cmd)
|
36
|
+
process.io.inherit!
|
37
|
+
if cwd
|
38
|
+
process.cwd = cwd
|
39
|
+
end
|
40
|
+
if env
|
41
|
+
env.each do |k, v|
|
42
|
+
process.environment[k.to_s] = v
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
output = ''
|
47
|
+
r, w = IO.pipe
|
48
|
+
|
49
|
+
begin
|
50
|
+
process.io.stdout = w
|
51
|
+
process.start
|
52
|
+
w.close
|
53
|
+
|
54
|
+
thread = Thread.new do
|
55
|
+
begin
|
56
|
+
loop do
|
57
|
+
output << r.readpartial(16384)
|
58
|
+
end
|
59
|
+
rescue EOFError
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
process.wait
|
64
|
+
thread.join
|
65
|
+
ensure
|
66
|
+
r.close
|
67
|
+
end
|
68
|
+
|
69
|
+
[process, output]
|
70
|
+
end
|
71
|
+
|
72
|
+
module_function def check_output(*args)
|
73
|
+
process, output = get_output(*args)
|
74
|
+
unless process.exit_code == 0
|
75
|
+
raise SpawnError,"Failed to execute: #{args}"
|
76
|
+
end
|
77
|
+
output
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|