rubygems-update 2.4.5 → 2.4.6

Sign up to get free protection for your applications and to get access to all the features.

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: