bundler 4.1.0.beta2 → 4.1.0.beta3
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/lib/bundler/build_metadata.rb +2 -2
- data/lib/bundler/cli/lock.rb +5 -1
- data/lib/bundler/definition.rb +45 -9
- data/lib/bundler/dsl.rb +34 -21
- data/lib/bundler/fetcher/downloader.rb +9 -3
- data/lib/bundler/fetcher.rb +4 -1
- data/lib/bundler/lockfile_generator.rb +6 -0
- data/lib/bundler/lockfile_parser.rb +17 -1
- data/lib/bundler/man/gemfile.5 +18 -9
- data/lib/bundler/man/gemfile.5.ronn +28 -14
- data/lib/bundler/match_platform.rb +12 -3
- data/lib/bundler/override.rb +60 -7
- data/lib/bundler/resolver.rb +1 -1
- data/lib/bundler/rubygems_ext.rb +15 -4
- data/lib/bundler/source/rubygems.rb +2 -2
- data/lib/bundler/source_map.rb +1 -1
- data/lib/bundler/vendor/fileutils/lib/fileutils.rb +54 -29
- data/lib/bundler/version.rb +1 -1
- data/lib/rubygems/compact_index_client/parser.rb +1 -0
- data/lib/rubygems/vendor/uri/lib/uri/common.rb +1 -1
- data/lib/rubygems/vendor/uri/lib/uri/generic.rb +15 -3
- data/lib/rubygems/vendor/uri/lib/uri/version.rb +1 -1
- data/lib/rubygems/yaml_serializer.rb +131 -103
- metadata +2 -2
|
@@ -16,30 +16,27 @@ end
|
|
|
16
16
|
|
|
17
17
|
module Gem
|
|
18
18
|
module YAMLSerializer
|
|
19
|
-
Scalar = Struct.new(:value, :tag, :anchor
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
super
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
Sequence = Struct.new(:items, :tag, :anchor, keyword_init: true) do
|
|
28
|
-
def initialize(items: [], tag: nil, anchor: nil)
|
|
29
|
-
super
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
AliasRef = Struct.new(:name, keyword_init: true)
|
|
19
|
+
Scalar = Struct.new(:value, :tag, :anchor)
|
|
20
|
+
Mapping = Struct.new(:pairs, :tag, :anchor)
|
|
21
|
+
Sequence = Struct.new(:items, :tag, :anchor)
|
|
22
|
+
AliasRef = Struct.new(:name)
|
|
34
23
|
|
|
35
24
|
class Parser
|
|
36
25
|
# A plain (unquoted) mapping key followed by ":". "#" inside a key is
|
|
37
26
|
# literal unless preceded by a space (which would start a comment).
|
|
38
|
-
MAPPING_KEY_RE =
|
|
27
|
+
MAPPING_KEY_RE = /\G((?:[^#:\s]|:[^ ])(?:[^#:]|:[^ ]|(?<=[^ ])#)*):(?:[ ]+(.*))?$/
|
|
39
28
|
# A quoted mapping key followed by ":". A whole-line quoted scalar
|
|
40
29
|
# cannot match because its closing quote is at the end of the line.
|
|
41
|
-
QUOTED_KEY_RE =
|
|
30
|
+
QUOTED_KEY_RE = /\G("(?:[^"\\]|\\.)*"|'(?:[^']|'')*'):(?:[ ]+(.*))?$/
|
|
31
|
+
# An entry of a flow sequence. A quoted entry may contain commas.
|
|
32
|
+
FLOW_SEQUENCE_ENTRY_RE = /"(?:[^"\\]|\\.)*"|'(?:[^']|'')*'|[^,\s](?:[^,]*[^,\s])?/
|
|
33
|
+
SEQUENCE_ENTRY_RE = /\G-(?: |\z)/
|
|
34
|
+
RUBY_OBJECT_TAG_RE = %r{\G!ruby/object:}
|
|
35
|
+
LSTRIP_BYTES = [0, 9, 10, 11, 12, 13, 32].freeze
|
|
42
36
|
MAX_NESTING_DEPTH = 1_000
|
|
37
|
+
NULL_SCALARS = %w[~ null].freeze
|
|
38
|
+
BLANK_RE = /\A[\0\s]*\z/
|
|
39
|
+
BLANK_OR_COMMENT_RE = /\A[\0\s]*(?:#|\z)/
|
|
43
40
|
|
|
44
41
|
STRING_UNESCAPES = {
|
|
45
42
|
"\\\\" => "\\",
|
|
@@ -53,10 +50,14 @@ module Gem
|
|
|
53
50
|
"\\f" => "\f",
|
|
54
51
|
"\\r" => "\r",
|
|
55
52
|
"\\e" => "\e",
|
|
53
|
+
"\\N" => "\u0085",
|
|
54
|
+
"\\_" => "\u00A0",
|
|
55
|
+
"\\L" => "\u2028",
|
|
56
|
+
"\\P" => "\u2029",
|
|
56
57
|
}.freeze
|
|
57
58
|
|
|
58
59
|
def initialize(source)
|
|
59
|
-
@lines = source.split(/\r?\n/)
|
|
60
|
+
@lines = source.split(/\r?\n/).each(&:freeze)
|
|
60
61
|
@anchors = {}
|
|
61
62
|
@depth = 0
|
|
62
63
|
strip_document_prefix
|
|
@@ -101,37 +102,35 @@ module Gem
|
|
|
101
102
|
return nil if @lines.empty?
|
|
102
103
|
|
|
103
104
|
line = @lines[0]
|
|
104
|
-
|
|
105
|
-
indent = line.size - stripped.size
|
|
105
|
+
indent = indent_of(line)
|
|
106
106
|
return nil if indent < base_indent
|
|
107
107
|
|
|
108
|
-
return parse_alias_ref if
|
|
108
|
+
return parse_alias_ref if /\G\*/.match?(line, indent)
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if anchor
|
|
110
|
+
pos = indent
|
|
111
|
+
if /\G&/.match?(line, indent) && (anchor = consume_anchor)
|
|
113
112
|
line = @lines[0]
|
|
114
|
-
|
|
113
|
+
pos = indent_of(line)
|
|
115
114
|
end
|
|
116
115
|
|
|
117
|
-
if
|
|
116
|
+
if SEQUENCE_ENTRY_RE.match?(line, pos)
|
|
118
117
|
parse_sequence(indent, anchor)
|
|
119
|
-
elsif QUOTED_KEY_RE.match?(
|
|
118
|
+
elsif QUOTED_KEY_RE.match?(line, pos)
|
|
120
119
|
# A mapping whose key is quoted, e.g. '"have: colon": value'.
|
|
121
120
|
parse_mapping(indent, anchor)
|
|
122
|
-
elsif (
|
|
123
|
-
(
|
|
121
|
+
elsif (/\G"/.match?(line, pos) && line.end_with?("\"")) ||
|
|
122
|
+
(/\G'/.match?(line, pos) && line.end_with?("'"))
|
|
124
123
|
# A whole-line quoted scalar, e.g. '"system: foo: bar"'. It may
|
|
125
124
|
# contain ": ", so it must be checked before MAPPING_KEY_RE.
|
|
126
125
|
parse_plain_scalar(indent, anchor)
|
|
127
|
-
elsif
|
|
126
|
+
elsif MAPPING_KEY_RE.match?(line, pos) && !RUBY_OBJECT_TAG_RE.match?(line, pos)
|
|
128
127
|
parse_mapping(indent, anchor)
|
|
129
|
-
elsif
|
|
128
|
+
elsif RUBY_OBJECT_TAG_RE.match?(line, pos)
|
|
130
129
|
parse_tagged_node(indent, anchor)
|
|
131
|
-
elsif
|
|
132
|
-
modifier =
|
|
130
|
+
elsif /\G\|/.match?(line, pos)
|
|
131
|
+
modifier = line[pos + 1, line.size].strip
|
|
133
132
|
@lines.shift
|
|
134
|
-
register_anchor(anchor, Scalar.new(
|
|
133
|
+
register_anchor(anchor, Scalar.new(parse_block_scalar(indent, modifier)))
|
|
135
134
|
else
|
|
136
135
|
parse_plain_scalar(indent, anchor)
|
|
137
136
|
end
|
|
@@ -142,22 +141,26 @@ module Gem
|
|
|
142
141
|
def parse_sequence(indent, anchor)
|
|
143
142
|
items = []
|
|
144
143
|
while @lines.any?
|
|
144
|
+
skip_blank_and_comments
|
|
145
|
+
break if @lines.empty?
|
|
145
146
|
line = @lines[0]
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
content
|
|
150
|
-
item_anchor
|
|
147
|
+
break unless indent_of(line) == indent && SEQUENCE_ENTRY_RE.match?(line, indent)
|
|
148
|
+
@lines.shift
|
|
149
|
+
content = line[indent + 1, line.size]
|
|
150
|
+
content.strip!
|
|
151
|
+
item_anchor = nil
|
|
152
|
+
item_anchor, content = extract_item_anchor(content) if content.start_with?("&")
|
|
151
153
|
item = parse_sequence_item(content, indent)
|
|
152
154
|
items << register_anchor(item_anchor, item)
|
|
153
155
|
end
|
|
154
|
-
register_anchor(anchor, Sequence.new(items
|
|
156
|
+
register_anchor(anchor, Sequence.new(items))
|
|
155
157
|
end
|
|
156
158
|
|
|
157
159
|
def parse_sequence_item(content, indent)
|
|
158
160
|
if content.start_with?("*")
|
|
159
161
|
parse_inline_alias(content)
|
|
160
162
|
elsif content.empty?
|
|
163
|
+
skip_blank_and_comments
|
|
161
164
|
@lines.any? && current_indent > indent ? parse_node(indent) : nil
|
|
162
165
|
elsif content.start_with?("!ruby/object:")
|
|
163
166
|
parse_tagged_content(content.strip, indent)
|
|
@@ -167,11 +170,11 @@ module Gem
|
|
|
167
170
|
@lines.unshift("#{" " * (indent + 2)}#{content}")
|
|
168
171
|
parse_node(indent)
|
|
169
172
|
elsif QUOTED_KEY_RE.match?(content) ||
|
|
170
|
-
(content
|
|
173
|
+
(MAPPING_KEY_RE.match?(content) && !content.start_with?("!ruby/object:"))
|
|
171
174
|
@lines.unshift("#{" " * (indent + 2)}#{content}")
|
|
172
175
|
parse_node(indent)
|
|
173
176
|
elsif content.start_with?("|")
|
|
174
|
-
Scalar.new(
|
|
177
|
+
Scalar.new(parse_block_scalar(indent, content[1..].to_s.strip))
|
|
175
178
|
else
|
|
176
179
|
parse_inline_scalar(content, indent)
|
|
177
180
|
end
|
|
@@ -180,28 +183,33 @@ module Gem
|
|
|
180
183
|
def parse_mapping(indent, anchor)
|
|
181
184
|
pairs = []
|
|
182
185
|
while @lines.any?
|
|
186
|
+
skip_blank_and_comments
|
|
187
|
+
break if @lines.empty?
|
|
183
188
|
line = @lines[0]
|
|
184
|
-
|
|
185
|
-
break unless line.size - stripped.size == indent
|
|
189
|
+
break unless indent_of(line) == indent
|
|
186
190
|
|
|
187
|
-
if (match = QUOTED_KEY_RE.match(
|
|
191
|
+
if (match = QUOTED_KEY_RE.match(line, indent))
|
|
188
192
|
key = coerce(match[1])
|
|
189
|
-
elsif (match = MAPPING_KEY_RE.match(
|
|
190
|
-
key = match[1]
|
|
193
|
+
elsif (match = MAPPING_KEY_RE.match(line, indent)) && !RUBY_OBJECT_TAG_RE.match?(line, indent)
|
|
194
|
+
key = match[1]
|
|
195
|
+
key.strip!
|
|
191
196
|
key = decode_binary_tag(key) if key.start_with?("!binary ")
|
|
192
197
|
else
|
|
193
198
|
break
|
|
194
199
|
end
|
|
195
200
|
@lines.shift
|
|
196
|
-
val =
|
|
201
|
+
val = match[2]
|
|
202
|
+
val&.strip!
|
|
203
|
+
val = strip_comment(val || "")
|
|
197
204
|
|
|
198
|
-
val_anchor
|
|
205
|
+
val_anchor = nil
|
|
206
|
+
val_anchor, val = consume_value_anchor(val) if val.start_with?("&")
|
|
199
207
|
value = parse_mapping_value(val, indent)
|
|
200
208
|
value = register_anchor(val_anchor, value) if val_anchor
|
|
201
209
|
|
|
202
|
-
pairs <<
|
|
210
|
+
pairs << key << value
|
|
203
211
|
end
|
|
204
|
-
register_anchor(anchor, Mapping.new(pairs
|
|
212
|
+
register_anchor(anchor, Mapping.new(pairs))
|
|
205
213
|
end
|
|
206
214
|
|
|
207
215
|
def parse_mapping_value(val, indent)
|
|
@@ -212,25 +220,19 @@ module Gem
|
|
|
212
220
|
elsif val.start_with?("!binary ")
|
|
213
221
|
parse_binary_value(val, indent)
|
|
214
222
|
elsif val.empty?
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if
|
|
218
|
-
next_stripped = @lines[0].lstrip
|
|
219
|
-
next_indent = @lines[0].size - next_stripped.size
|
|
220
|
-
end
|
|
221
|
-
if next_stripped &&
|
|
222
|
-
(next_stripped.start_with?("- ") || next_stripped == "-") &&
|
|
223
|
-
next_indent == indent
|
|
223
|
+
skip_blank_and_comments
|
|
224
|
+
line = @lines[0]
|
|
225
|
+
if line && indent_of(line) == indent && SEQUENCE_ENTRY_RE.match?(line, indent)
|
|
224
226
|
parse_node(indent)
|
|
225
227
|
else
|
|
226
228
|
parse_node(indent + 1)
|
|
227
229
|
end
|
|
228
230
|
elsif val == "[]"
|
|
229
|
-
Sequence.new
|
|
231
|
+
Sequence.new([])
|
|
230
232
|
elsif val == "{}"
|
|
231
|
-
Mapping.new
|
|
233
|
+
Mapping.new([])
|
|
232
234
|
elsif val.start_with?("|")
|
|
233
|
-
Scalar.new(
|
|
235
|
+
Scalar.new(parse_block_scalar(indent, val[1..].to_s.strip))
|
|
234
236
|
else
|
|
235
237
|
parse_inline_scalar(val, indent)
|
|
236
238
|
end
|
|
@@ -253,21 +255,24 @@ module Gem
|
|
|
253
255
|
node.anchor = anchor
|
|
254
256
|
node
|
|
255
257
|
else
|
|
256
|
-
Mapping.new(
|
|
258
|
+
Mapping.new(["value", node], tag, anchor)
|
|
257
259
|
end
|
|
258
260
|
end
|
|
259
261
|
|
|
260
262
|
def parse_block_scalar(base_indent, modifier)
|
|
261
263
|
parts = []
|
|
262
|
-
|
|
264
|
+
indentation = modifier[/\A[+-]?([1-9])/, 1]
|
|
265
|
+
chomping = modifier[/\A[1-9]?([+-])/, 1]
|
|
266
|
+
block_indent = indentation && base_indent + indentation.to_i
|
|
263
267
|
|
|
264
268
|
while @lines.any?
|
|
265
269
|
line = @lines[0]
|
|
266
|
-
if
|
|
270
|
+
if BLANK_RE.match?(line)
|
|
271
|
+
parts << line[block_indent..] if block_indent && line.size > block_indent
|
|
267
272
|
parts << "\n"
|
|
268
273
|
@lines.shift
|
|
269
274
|
else
|
|
270
|
-
line_indent = line
|
|
275
|
+
line_indent = indent_of(line)
|
|
271
276
|
break if line_indent <= base_indent
|
|
272
277
|
block_indent ||= line_indent
|
|
273
278
|
parts << @lines.shift[block_indent..].to_s << "\n"
|
|
@@ -275,30 +280,35 @@ module Gem
|
|
|
275
280
|
end
|
|
276
281
|
|
|
277
282
|
res = parts.join
|
|
278
|
-
res.
|
|
283
|
+
res.delete_suffix!("\n") while chomping == "-" && res.end_with?("\n")
|
|
279
284
|
res
|
|
280
285
|
end
|
|
281
286
|
|
|
282
287
|
def parse_plain_scalar(indent, anchor)
|
|
283
|
-
|
|
288
|
+
val = @lines.shift.strip
|
|
289
|
+
result = coerce(val)
|
|
284
290
|
return register_anchor(anchor, result) if result.is_a?(Mapping) || result.is_a?(Sequence)
|
|
285
291
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
result << " " << @lines.shift.strip
|
|
289
|
-
end
|
|
290
|
-
register_anchor(anchor, Scalar.new(value: result))
|
|
292
|
+
fold_continuation_lines(result, val, indent)
|
|
293
|
+
register_anchor(anchor, Scalar.new(result))
|
|
291
294
|
end
|
|
292
295
|
|
|
293
296
|
def parse_inline_scalar(val, indent)
|
|
294
297
|
result = coerce(val)
|
|
295
298
|
return result if result.is_a?(Mapping) || result.is_a?(Sequence)
|
|
296
299
|
|
|
297
|
-
|
|
298
|
-
|
|
300
|
+
fold_continuation_lines(result, val, indent)
|
|
301
|
+
Scalar.new(result)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def fold_continuation_lines(result, val, indent)
|
|
305
|
+
return unless result.is_a?(String)
|
|
306
|
+
|
|
307
|
+
# "#" does not start a comment inside a quoted scalar that runs onto the next lines.
|
|
308
|
+
stop = val.start_with?("'", "\"") && result == val ? BLANK_RE : BLANK_OR_COMMENT_RE
|
|
309
|
+
while @lines.any? && !stop.match?(@lines[0]) && current_indent > indent
|
|
299
310
|
result << " " << @lines.shift.strip
|
|
300
311
|
end
|
|
301
|
-
Scalar.new(value: result)
|
|
302
312
|
end
|
|
303
313
|
|
|
304
314
|
def coerce(val, depth = 0)
|
|
@@ -306,25 +316,30 @@ module Gem
|
|
|
306
316
|
|
|
307
317
|
val = val.sub(/^! /, "") if val.start_with?("! ")
|
|
308
318
|
|
|
309
|
-
if val
|
|
310
|
-
|
|
311
|
-
|
|
319
|
+
if val.size >= 2 && val.start_with?("\"") && val.end_with?("\"")
|
|
320
|
+
inner = val[1..-2]
|
|
321
|
+
return inner unless inner.include?("\\")
|
|
322
|
+
inner.gsub(/\\(?:["\\0abtnvfreN_LP]|x\h{2}|u\h{4}|U\h{8})/) do |m|
|
|
323
|
+
char = STRING_UNESCAPES[m] || unescape_code_point(m)
|
|
324
|
+
# Metadata is read as binary, where non-ASCII text stays as UTF-8 bytes.
|
|
325
|
+
Encoding.compatible?(inner, char) ? char : char.b
|
|
312
326
|
end
|
|
313
|
-
elsif val
|
|
314
|
-
|
|
327
|
+
elsif val.size >= 2 && val.start_with?("'") && val.end_with?("'")
|
|
328
|
+
inner = val[1..-2]
|
|
329
|
+
inner.include?("''") ? inner.gsub("''", "'") : inner
|
|
315
330
|
elsif val == "true"
|
|
316
331
|
true
|
|
317
332
|
elsif val == "false"
|
|
318
333
|
false
|
|
319
|
-
elsif
|
|
334
|
+
elsif NULL_SCALARS.include?(val)
|
|
320
335
|
nil
|
|
321
336
|
elsif val == "{}"
|
|
322
|
-
Mapping.new
|
|
337
|
+
Mapping.new([])
|
|
323
338
|
elsif val =~ /^\[(.*)\]$/
|
|
324
339
|
inner = $1.strip
|
|
325
|
-
return Sequence.new if inner.empty?
|
|
326
|
-
items = inner.
|
|
327
|
-
Sequence.new(items
|
|
340
|
+
return Sequence.new([]) if inner.empty?
|
|
341
|
+
items = inner.scan(FLOW_SEQUENCE_ENTRY_RE).map {|e| Scalar.new(coerce(e, depth + 1)) }
|
|
342
|
+
Sequence.new(items)
|
|
328
343
|
elsif /\A\d{4}-\d{2}-\d{2}([ T]\d{2}:\d{2}:\d{2})?/.match?(val)
|
|
329
344
|
begin
|
|
330
345
|
Time.new(val)
|
|
@@ -343,6 +358,12 @@ module Gem
|
|
|
343
358
|
end
|
|
344
359
|
end
|
|
345
360
|
|
|
361
|
+
def unescape_code_point(escape)
|
|
362
|
+
code = escape[2..].hex
|
|
363
|
+
return escape if code > 0x10FFFF || code.between?(0xD800, 0xDFFF)
|
|
364
|
+
code.chr(Encoding::UTF_8)
|
|
365
|
+
end
|
|
366
|
+
|
|
346
367
|
def decode_binary_tag(str)
|
|
347
368
|
content = str.sub(/\A!binary\s+/, "")
|
|
348
369
|
content = $1 if content =~ /\A"(.*)"\z/ || content =~ /\A'(.*)'\z/
|
|
@@ -353,23 +374,28 @@ module Gem
|
|
|
353
374
|
rest = val.sub(/\A!binary\s+/, "")
|
|
354
375
|
if rest.start_with?("|")
|
|
355
376
|
content = parse_block_scalar(indent, rest[1..].to_s.strip)
|
|
356
|
-
Scalar.new(
|
|
377
|
+
Scalar.new(content.unpack1("m"))
|
|
357
378
|
else
|
|
358
|
-
Scalar.new(
|
|
379
|
+
Scalar.new(decode_binary_tag(val))
|
|
359
380
|
end
|
|
360
381
|
end
|
|
361
382
|
|
|
362
383
|
def parse_alias_ref
|
|
363
|
-
AliasRef.new(
|
|
384
|
+
AliasRef.new(@lines.shift.lstrip[1..].strip)
|
|
364
385
|
end
|
|
365
386
|
|
|
366
387
|
def parse_inline_alias(content)
|
|
367
|
-
AliasRef.new(
|
|
388
|
+
AliasRef.new(content[1..].strip)
|
|
368
389
|
end
|
|
369
390
|
|
|
370
391
|
def current_indent
|
|
371
|
-
|
|
372
|
-
|
|
392
|
+
indent_of(@lines[0])
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def indent_of(line)
|
|
396
|
+
i = 0
|
|
397
|
+
i += 1 while LSTRIP_BYTES.include?(line.getbyte(i))
|
|
398
|
+
i
|
|
373
399
|
end
|
|
374
400
|
|
|
375
401
|
def consume_anchor
|
|
@@ -414,12 +440,7 @@ module Gem
|
|
|
414
440
|
end
|
|
415
441
|
|
|
416
442
|
def skip_blank_and_comments
|
|
417
|
-
while @lines.any?
|
|
418
|
-
line = @lines[0]
|
|
419
|
-
stripped = line.lstrip
|
|
420
|
-
break unless stripped.empty? || stripped.start_with?("#")
|
|
421
|
-
@lines.shift
|
|
422
|
-
end
|
|
443
|
+
@lines.shift while @lines.any? && BLANK_OR_COMMENT_RE.match?(@lines[0])
|
|
423
444
|
end
|
|
424
445
|
|
|
425
446
|
def strip_comment(val)
|
|
@@ -542,8 +563,7 @@ module Gem
|
|
|
542
563
|
|
|
543
564
|
def build_hash(node)
|
|
544
565
|
result = {}
|
|
545
|
-
node
|
|
546
|
-
key = key_node.is_a?(Scalar) ? key_node.value.to_s : build_node(key_node).to_s
|
|
566
|
+
each_pair(node) do |key, value_node|
|
|
547
567
|
value = build_node(value_node)
|
|
548
568
|
|
|
549
569
|
if ARRAY_FIELDS.include?(key)
|
|
@@ -643,13 +663,21 @@ module Gem
|
|
|
643
663
|
|
|
644
664
|
def pairs_to_hash(node)
|
|
645
665
|
result = {}
|
|
646
|
-
node
|
|
647
|
-
key = key_node.is_a?(Scalar) ? key_node.value.to_s : build_node(key_node).to_s
|
|
666
|
+
each_pair(node) do |key, value_node|
|
|
648
667
|
result[key] = build_node(value_node)
|
|
649
668
|
end
|
|
650
669
|
result
|
|
651
670
|
end
|
|
652
671
|
|
|
672
|
+
def each_pair(node)
|
|
673
|
+
pairs = node.pairs
|
|
674
|
+
i = 0
|
|
675
|
+
while i < pairs.size
|
|
676
|
+
yield pairs[i], pairs[i + 1]
|
|
677
|
+
i += 2
|
|
678
|
+
end
|
|
679
|
+
end
|
|
680
|
+
|
|
653
681
|
def validate_tag!(tag)
|
|
654
682
|
return if @permitted_classes.include?(tag)
|
|
655
683
|
raise_disallowed_class!(tag)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bundler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.1.0.
|
|
4
|
+
version: 4.1.0.beta3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yehuda Katz
|
|
@@ -411,7 +411,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
411
411
|
- !ruby/object:Gem::Version
|
|
412
412
|
version: 3.4.1
|
|
413
413
|
requirements: []
|
|
414
|
-
rubygems_version: 4.1.0.
|
|
414
|
+
rubygems_version: 4.1.0.beta3
|
|
415
415
|
specification_version: 4
|
|
416
416
|
summary: The best way to manage your application's dependencies
|
|
417
417
|
test_files: []
|