rubygems-update 2.4.5 → 2.4.6

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.

Potentially problematic release.


This version of rubygems-update might be problematic. Click here for more details.

Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/History.txt +27 -0
  3. data/Manifest.txt +4 -0
  4. data/lib/rubygems.rb +2 -2
  5. data/lib/rubygems/basic_specification.rb +2 -3
  6. data/lib/rubygems/commands/help_command.rb +2 -2
  7. data/lib/rubygems/commands/open_command.rb +3 -1
  8. data/lib/rubygems/commands/yank_command.rb +1 -1
  9. data/lib/rubygems/compatibility.rb +1 -2
  10. data/lib/rubygems/dependency_installer.rb +11 -1
  11. data/lib/rubygems/installer.rb +1 -1
  12. data/lib/rubygems/package.rb +2 -1
  13. data/lib/rubygems/package/tar_writer.rb +4 -4
  14. data/lib/rubygems/path_support.rb +0 -7
  15. data/lib/rubygems/psych_additions.rb +1 -1
  16. data/lib/rubygems/remote_fetcher.rb +1 -1
  17. data/lib/rubygems/request_set.rb +10 -4
  18. data/lib/rubygems/request_set/gem_dependency_api.rb +4 -4
  19. data/lib/rubygems/request_set/lockfile.rb +52 -464
  20. data/lib/rubygems/request_set/lockfile/parser.rb +334 -0
  21. data/lib/rubygems/request_set/lockfile/tokenizer.rb +108 -0
  22. data/lib/rubygems/requirement.rb +12 -1
  23. data/lib/rubygems/security/signer.rb +1 -1
  24. data/lib/rubygems/specification.rb +12 -12
  25. data/lib/rubygems/test_case.rb +18 -1
  26. data/lib/rubygems/user_interaction.rb +0 -8
  27. data/test/rubygems/test_gem.rb +2 -5
  28. data/test/rubygems/test_gem_commands_open_command.rb +9 -3
  29. data/test/rubygems/test_gem_commands_pristine_command.rb +2 -2
  30. data/test/rubygems/test_gem_commands_unpack_command.rb +2 -2
  31. data/test/rubygems/test_gem_dependency_installer.rb +27 -1
  32. data/test/rubygems/test_gem_ext_cmake_builder.rb +1 -1
  33. data/test/rubygems/test_gem_installer.rb +1 -1
  34. data/test/rubygems/test_gem_package.rb +1 -1
  35. data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +30 -11
  36. data/test/rubygems/test_gem_request_set_lockfile.rb +19 -824
  37. data/test/rubygems/test_gem_request_set_lockfile_parser.rb +543 -0
  38. data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +305 -0
  39. data/test/rubygems/test_gem_requirement.rb +10 -0
  40. data/test/rubygems/test_gem_specification.rb +7 -1
  41. data/test/rubygems/test_gem_stub_specification.rb +1 -1
  42. data/test/rubygems/test_gem_uninstaller.rb +2 -2
  43. metadata +8 -2
@@ -0,0 +1,334 @@
1
+ class Gem::RequestSet::Lockfile::Parser
2
+ ###
3
+ # Parses lockfiles
4
+
5
+ def initialize tokenizer, set, platforms, filename = nil
6
+ @tokens = tokenizer
7
+ @filename = filename
8
+ @set = set
9
+ @platforms = platforms
10
+ end
11
+
12
+ def parse
13
+ until @tokens.empty? do
14
+ type, data, column, line = get
15
+
16
+ case type
17
+ when :section then
18
+ @tokens.skip :newline
19
+
20
+ case data
21
+ when 'DEPENDENCIES' then
22
+ parse_DEPENDENCIES
23
+ when 'GIT' then
24
+ parse_GIT
25
+ when 'GEM' then
26
+ parse_GEM
27
+ when 'PATH' then
28
+ parse_PATH
29
+ when 'PLATFORMS' then
30
+ parse_PLATFORMS
31
+ else
32
+ type, = get until @tokens.empty? or peek.first == :section
33
+ end
34
+ else
35
+ raise "BUG: unhandled token #{type} (#{data.inspect}) at line #{line} column #{column}"
36
+ end
37
+ end
38
+ end
39
+
40
+ ##
41
+ # Gets the next token for a Lockfile
42
+
43
+ def get expected_types = nil, expected_value = nil # :nodoc:
44
+ current_token = @tokens.shift
45
+
46
+ type, value, column, line = current_token
47
+
48
+ if expected_types and not Array(expected_types).include? type then
49
+ unget current_token
50
+
51
+ message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
52
+ "expected #{expected_types.inspect}"
53
+
54
+ raise Gem::RequestSet::Lockfile::ParseError.new message, column, line, @filename
55
+ end
56
+
57
+ if expected_value and expected_value != value then
58
+ unget current_token
59
+
60
+ message = "unexpected token [#{type.inspect}, #{value.inspect}], " +
61
+ "expected [#{expected_types.inspect}, " +
62
+ "#{expected_value.inspect}]"
63
+
64
+ raise Gem::RequestSet::Lockfile::ParseError.new message, column, line, @filename
65
+ end
66
+
67
+ current_token
68
+ end
69
+
70
+ def parse_DEPENDENCIES # :nodoc:
71
+ while not @tokens.empty? and :text == peek.first do
72
+ _, name, = get :text
73
+
74
+ requirements = []
75
+
76
+ case peek[0]
77
+ when :bang then
78
+ get :bang
79
+
80
+ requirements << pinned_requirement(name)
81
+ when :l_paren then
82
+ get :l_paren
83
+
84
+ loop do
85
+ _, op, = get :requirement
86
+ _, version, = get :text
87
+
88
+ requirements << "#{op} #{version}"
89
+
90
+ break unless peek[0] == :comma
91
+
92
+ get :comma
93
+ end
94
+
95
+ get :r_paren
96
+
97
+ if peek[0] == :bang then
98
+ requirements.clear
99
+ requirements << pinned_requirement(name)
100
+
101
+ get :bang
102
+ end
103
+ end
104
+
105
+ @set.gem name, *requirements
106
+
107
+ skip :newline
108
+ end
109
+ end
110
+
111
+ def parse_GEM # :nodoc:
112
+ sources = []
113
+
114
+ while [:entry, 'remote'] == peek.first(2) do
115
+ get :entry, 'remote'
116
+ _, data, = get :text
117
+ skip :newline
118
+
119
+ sources << Gem::Source.new(data)
120
+ end
121
+
122
+ sources << Gem::Source.new(Gem::DEFAULT_HOST) if sources.empty?
123
+
124
+ get :entry, 'specs'
125
+
126
+ skip :newline
127
+
128
+ set = Gem::Resolver::LockSet.new sources
129
+ last_specs = nil
130
+
131
+ while not @tokens.empty? and :text == peek.first do
132
+ _, name, column, = get :text
133
+
134
+ case peek[0]
135
+ when :newline then
136
+ last_specs.each do |spec|
137
+ spec.add_dependency Gem::Dependency.new name if column == 6
138
+ end
139
+ when :l_paren then
140
+ get :l_paren
141
+
142
+ type, data, = get [:text, :requirement]
143
+
144
+ if type == :text and column == 4 then
145
+ version, platform = data.split '-', 2
146
+
147
+ platform =
148
+ platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
149
+
150
+ last_specs = set.add name, version, platform
151
+ else
152
+ dependency = parse_dependency name, data
153
+
154
+ last_specs.each do |spec|
155
+ spec.add_dependency dependency
156
+ end
157
+ end
158
+
159
+ get :r_paren
160
+ else
161
+ raise "BUG: unknown token #{peek}"
162
+ end
163
+
164
+ skip :newline
165
+ end
166
+
167
+ @set.sets << set
168
+ end
169
+
170
+ def parse_GIT # :nodoc:
171
+ get :entry, 'remote'
172
+ _, repository, = get :text
173
+
174
+ skip :newline
175
+
176
+ get :entry, 'revision'
177
+ _, revision, = get :text
178
+
179
+ skip :newline
180
+
181
+ type, value = peek.first 2
182
+ if type == :entry and %w[branch ref tag].include? value then
183
+ get
184
+ get :text
185
+
186
+ skip :newline
187
+ end
188
+
189
+ get :entry, 'specs'
190
+
191
+ skip :newline
192
+
193
+ set = Gem::Resolver::GitSet.new
194
+ set.root_dir = @set.install_dir
195
+
196
+ last_spec = nil
197
+
198
+ while not @tokens.empty? and :text == peek.first do
199
+ _, name, column, = get :text
200
+
201
+ case peek[0]
202
+ when :newline then
203
+ last_spec.add_dependency Gem::Dependency.new name if column == 6
204
+ when :l_paren then
205
+ get :l_paren
206
+
207
+ type, data, = get [:text, :requirement]
208
+
209
+ if type == :text and column == 4 then
210
+ last_spec = set.add_git_spec name, data, repository, revision, true
211
+ else
212
+ dependency = parse_dependency name, data
213
+
214
+ last_spec.add_dependency dependency
215
+ end
216
+
217
+ get :r_paren
218
+ else
219
+ raise "BUG: unknown token #{peek}"
220
+ end
221
+
222
+ skip :newline
223
+ end
224
+
225
+ @set.sets << set
226
+ end
227
+
228
+ def parse_PATH # :nodoc:
229
+ get :entry, 'remote'
230
+ _, directory, = get :text
231
+
232
+ skip :newline
233
+
234
+ get :entry, 'specs'
235
+
236
+ skip :newline
237
+
238
+ set = Gem::Resolver::VendorSet.new
239
+ last_spec = nil
240
+
241
+ while not @tokens.empty? and :text == peek.first do
242
+ _, name, column, = get :text
243
+
244
+ case peek[0]
245
+ when :newline then
246
+ last_spec.add_dependency Gem::Dependency.new name if column == 6
247
+ when :l_paren then
248
+ get :l_paren
249
+
250
+ type, data, = get [:text, :requirement]
251
+
252
+ if type == :text and column == 4 then
253
+ last_spec = set.add_vendor_gem name, directory
254
+ else
255
+ dependency = parse_dependency name, data
256
+
257
+ last_spec.dependencies << dependency
258
+ end
259
+
260
+ get :r_paren
261
+ else
262
+ raise "BUG: unknown token #{peek}"
263
+ end
264
+
265
+ skip :newline
266
+ end
267
+
268
+ @set.sets << set
269
+ end
270
+
271
+ def parse_PLATFORMS # :nodoc:
272
+ while not @tokens.empty? and :text == peek.first do
273
+ _, name, = get :text
274
+
275
+ @platforms << name
276
+
277
+ skip :newline
278
+ end
279
+ end
280
+
281
+ ##
282
+ # Parses the requirements following the dependency +name+ and the +op+ for
283
+ # the first token of the requirements and returns a Gem::Dependency object.
284
+
285
+ def parse_dependency name, op # :nodoc:
286
+ return Gem::Dependency.new name, op unless peek[0] == :text
287
+
288
+ _, version, = get :text
289
+
290
+ requirements = ["#{op} #{version}"]
291
+
292
+ while peek[0] == :comma do
293
+ get :comma
294
+ _, op, = get :requirement
295
+ _, version, = get :text
296
+
297
+ requirements << "#{op} #{version}"
298
+ end
299
+
300
+ Gem::Dependency.new name, requirements
301
+ end
302
+
303
+ private
304
+
305
+ def skip type # :nodoc:
306
+ @tokens.skip type
307
+ end
308
+
309
+ ##
310
+ # Peeks at the next token for Lockfile
311
+
312
+ def peek # :nodoc:
313
+ @tokens.peek
314
+ end
315
+
316
+ def pinned_requirement name # :nodoc:
317
+ spec = @set.sets.select { |set|
318
+ Gem::Resolver::GitSet === set or
319
+ Gem::Resolver::VendorSet === set
320
+ }.map { |set|
321
+ set.specs[name]
322
+ }.compact.first
323
+
324
+ spec.version
325
+ end
326
+
327
+ ##
328
+ # Ungets the last token retrieved by #get
329
+
330
+ def unget token # :nodoc:
331
+ @tokens.unshift token
332
+ end
333
+ end
334
+
@@ -0,0 +1,108 @@
1
+ require 'strscan'
2
+ require 'rubygems/request_set/lockfile/parser'
3
+
4
+ class Gem::RequestSet::Lockfile::Tokenizer
5
+ def self.from_file file
6
+ new File.read(file), file
7
+ end
8
+
9
+ def initialize input, filename = nil, line = 0, pos = 0
10
+ @line = line
11
+ @line_pos = pos
12
+ @tokens = []
13
+ @filename = filename
14
+ tokenize input
15
+ end
16
+
17
+ def make_parser set, platforms
18
+ Gem::RequestSet::Lockfile::Parser.new self, set, platforms, @filename
19
+ end
20
+
21
+ def to_a
22
+ @tokens
23
+ end
24
+
25
+ def skip type
26
+ @tokens.shift while not @tokens.empty? and peek.first == type
27
+ end
28
+
29
+ ##
30
+ # Calculates the column (by byte) and the line of the current token based on
31
+ # +byte_offset+.
32
+
33
+ def token_pos byte_offset # :nodoc:
34
+ [byte_offset - @line_pos, @line]
35
+ end
36
+
37
+ def empty?
38
+ @tokens.empty?
39
+ end
40
+
41
+ def unshift token
42
+ @tokens.unshift token
43
+ end
44
+
45
+ def next_token
46
+ @tokens.shift
47
+ end
48
+ alias :shift :next_token
49
+
50
+ def peek
51
+ @tokens.first || [:EOF]
52
+ end
53
+
54
+ private
55
+
56
+ def tokenize input
57
+ s = StringScanner.new input
58
+
59
+ until s.eos? do
60
+ pos = s.pos
61
+
62
+ pos = s.pos if leading_whitespace = s.scan(/ +/)
63
+
64
+ if s.scan(/[<|=>]{7}/) then
65
+ message = "your #{@filename} contains merge conflict markers"
66
+ column, line = token_pos pos
67
+
68
+ raise Gem::RequestSet::Lockfile::ParseError.new message, column, line, @filename
69
+ end
70
+
71
+ @tokens <<
72
+ case
73
+ when s.scan(/\r?\n/) then
74
+ token = [:newline, nil, *token_pos(pos)]
75
+ @line_pos = s.pos
76
+ @line += 1
77
+ token
78
+ when s.scan(/[A-Z]+/) then
79
+ if leading_whitespace then
80
+ text = s.matched
81
+ text += s.scan(/[^\s)]*/).to_s # in case of no match
82
+ [:text, text, *token_pos(pos)]
83
+ else
84
+ [:section, s.matched, *token_pos(pos)]
85
+ end
86
+ when s.scan(/([a-z]+):\s/) then
87
+ s.pos -= 1 # rewind for possible newline
88
+ [:entry, s[1], *token_pos(pos)]
89
+ when s.scan(/\(/) then
90
+ [:l_paren, nil, *token_pos(pos)]
91
+ when s.scan(/\)/) then
92
+ [:r_paren, nil, *token_pos(pos)]
93
+ when s.scan(/<=|>=|=|~>|<|>|!=/) then
94
+ [:requirement, s.matched, *token_pos(pos)]
95
+ when s.scan(/,/) then
96
+ [:comma, nil, *token_pos(pos)]
97
+ when s.scan(/!/) then
98
+ [:bang, nil, *token_pos(pos)]
99
+ when s.scan(/[^\s),!]*/) then
100
+ [:text, s.matched, *token_pos(pos)]
101
+ else
102
+ raise "BUG: can't create token for: #{s.string[s.pos..-1].inspect}"
103
+ end
104
+ end
105
+
106
+ @tokens
107
+ end
108
+ end
@@ -23,6 +23,8 @@ class Gem::Requirement
23
23
  "~>" => lambda { |v, r| v >= r && v.release < r.bump }
24
24
  }
25
25
 
26
+ SOURCE_SET_REQUIREMENT = Struct.new(:for_lockfile).new "!" # :nodoc:
27
+
26
28
  quoted = OPS.keys.map { |k| Regexp.quote k }.join "|"
27
29
  PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*" # :nodoc:
28
30
 
@@ -54,6 +56,8 @@ class Gem::Requirement
54
56
  input
55
57
  when Gem::Version, Array then
56
58
  new input
59
+ when '!' then
60
+ source_set
57
61
  else
58
62
  if input.respond_to? :to_str then
59
63
  new [input.to_str]
@@ -70,6 +74,13 @@ class Gem::Requirement
70
74
  new '>= 0'
71
75
  end
72
76
 
77
+ ###
78
+ # A source set requirement, used for Gemfiles and lockfiles
79
+
80
+ def self.source_set # :nodoc:
81
+ SOURCE_SET_REQUIREMENT
82
+ end
83
+
73
84
  ##
74
85
  # Parse +obj+, returning an <tt>[op, version]</tt> pair. +obj+ can
75
86
  # be a String or a Gem::Version.
@@ -171,7 +182,7 @@ class Gem::Requirement
171
182
  end
172
183
 
173
184
  def hash # :nodoc:
174
- requirements.hash
185
+ requirements.sort.hash
175
186
  end
176
187
 
177
188
  def marshal_dump # :nodoc: