bundler 2.3.17 → 2.3.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/lib/bundler/build_metadata.rb +2 -2
  4. data/lib/bundler/cli/common.rb +1 -0
  5. data/lib/bundler/cli/install.rb +5 -2
  6. data/lib/bundler/cli/outdated.rb +12 -3
  7. data/lib/bundler/cli/platform.rb +1 -1
  8. data/lib/bundler/cli.rb +5 -3
  9. data/lib/bundler/compact_index_client/updater.rb +16 -3
  10. data/lib/bundler/definition.rb +111 -28
  11. data/lib/bundler/dependency.rb +2 -1
  12. data/lib/bundler/dsl.rb +3 -3
  13. data/lib/bundler/fetcher.rb +6 -6
  14. data/lib/bundler/gem_helpers.rb +8 -1
  15. data/lib/bundler/incomplete_specification.rb +12 -0
  16. data/lib/bundler/index.rb +10 -12
  17. data/lib/bundler/installer/standalone.rb +1 -1
  18. data/lib/bundler/installer.rb +8 -1
  19. data/lib/bundler/lazy_specification.rb +30 -21
  20. data/lib/bundler/lockfile_parser.rb +4 -0
  21. data/lib/bundler/man/bundle-add.1 +1 -1
  22. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  23. data/lib/bundler/man/bundle-cache.1 +7 -1
  24. data/lib/bundler/man/bundle-cache.1.ronn +7 -0
  25. data/lib/bundler/man/bundle-check.1 +1 -1
  26. data/lib/bundler/man/bundle-clean.1 +1 -1
  27. data/lib/bundler/man/bundle-config.1 +15 -5
  28. data/lib/bundler/man/bundle-config.1.ronn +12 -5
  29. data/lib/bundler/man/bundle-doctor.1 +1 -1
  30. data/lib/bundler/man/bundle-exec.1 +2 -2
  31. data/lib/bundler/man/bundle-exec.1.ronn +1 -1
  32. data/lib/bundler/man/bundle-gem.1 +1 -1
  33. data/lib/bundler/man/bundle-info.1 +1 -1
  34. data/lib/bundler/man/bundle-init.1 +1 -1
  35. data/lib/bundler/man/bundle-inject.1 +5 -2
  36. data/lib/bundler/man/bundle-inject.1.ronn +3 -1
  37. data/lib/bundler/man/bundle-install.1 +5 -1
  38. data/lib/bundler/man/bundle-install.1.ronn +6 -0
  39. data/lib/bundler/man/bundle-list.1 +1 -1
  40. data/lib/bundler/man/bundle-lock.1 +1 -1
  41. data/lib/bundler/man/bundle-open.1 +1 -1
  42. data/lib/bundler/man/bundle-outdated.1 +1 -1
  43. data/lib/bundler/man/bundle-platform.1 +16 -6
  44. data/lib/bundler/man/bundle-platform.1.ronn +14 -7
  45. data/lib/bundler/man/bundle-pristine.1 +1 -1
  46. data/lib/bundler/man/bundle-remove.1 +1 -1
  47. data/lib/bundler/man/bundle-show.1 +1 -1
  48. data/lib/bundler/man/bundle-update.1 +1 -1
  49. data/lib/bundler/man/bundle-viz.1 +4 -1
  50. data/lib/bundler/man/bundle-viz.1.ronn +2 -0
  51. data/lib/bundler/man/bundle.1 +6 -9
  52. data/lib/bundler/man/bundle.1.ronn +5 -6
  53. data/lib/bundler/man/gemfile.5 +77 -47
  54. data/lib/bundler/man/gemfile.5.ronn +75 -54
  55. data/lib/bundler/remote_specification.rb +5 -4
  56. data/lib/bundler/resolver/spec_group.rb +5 -4
  57. data/lib/bundler/resolver.rb +10 -7
  58. data/lib/bundler/ruby_dsl.rb +1 -1
  59. data/lib/bundler/ruby_version.rb +5 -5
  60. data/lib/bundler/rubygems_ext.rb +13 -0
  61. data/lib/bundler/rubygems_gem_installer.rb +19 -12
  62. data/lib/bundler/runtime.rb +0 -1
  63. data/lib/bundler/settings.rb +1 -0
  64. data/lib/bundler/source/metadata.rb +1 -1
  65. data/lib/bundler/source/rubygems.rb +12 -6
  66. data/lib/bundler/source_list.rb +4 -0
  67. data/lib/bundler/spec_set.rb +26 -31
  68. data/lib/bundler/version.rb +1 -1
  69. data/lib/bundler.rb +1 -0
  70. metadata +4 -3
@@ -15,23 +15,28 @@ directory as the `Rakefile`.
15
15
  A `Gemfile` is evaluated as Ruby code, in a context which makes available
16
16
  a number of methods used to describe the gem requirements.
17
17
 
18
- ## GLOBAL SOURCES
18
+ ## GLOBAL SOURCE
19
19
 
20
- At the top of the `Gemfile`, add a line for the `Rubygems` source that contains
21
- the gems listed in the `Gemfile`.
20
+ At the top of the `Gemfile`, add a single line for the `RubyGems` source that
21
+ contains the gems listed in the `Gemfile`.
22
22
 
23
23
  source "https://rubygems.org"
24
24
 
25
- It is possible, but not recommended as of Bundler 1.7, to add multiple global
26
- `source` lines. Each of these `source`s `MUST` be a valid Rubygems repository.
25
+ You can add only one global source. In Bundler 1.13, adding multiple global
26
+ sources was deprecated. The `source` `MUST` be a valid RubyGems repository.
27
27
 
28
- Sources are checked for gems following the heuristics described in
29
- [SOURCE PRIORITY][]. If a gem is found in more than one global source, Bundler
28
+ To use more than one source of RubyGems, you should use [`source` block
29
+ ](#BLOCK-FORM-OF-SOURCE-GIT-PATH-GROUP-and-PLATFORMS).
30
+
31
+ A source is checked for gems following the heuristics described in
32
+ [SOURCE PRIORITY][].
33
+
34
+ **Note about a behavior of the feature deprecated in Bundler 1.13**:
35
+ If a gem is found in more than one global source, Bundler
30
36
  will print a warning after installing the gem indicating which source was used,
31
37
  and listing the other sources where the gem is available. A specific source can
32
38
  be selected for gems that need to use a non-standard repository, suppressing
33
- this warning, by using the [`:source` option](#SOURCE) or a
34
- [`source` block](#BLOCK-FORM-OF-SOURCE-GIT-PATH-GROUP-and-PLATFORMS).
39
+ this warning, by using the [`:source` option](#SOURCE) or `source` block.
35
40
 
36
41
  ### CREDENTIALS
37
42
 
@@ -91,13 +96,13 @@ Each application _may_ specify a Ruby engine version. If an engine version is
91
96
  specified, an engine _must_ also be specified. If the engine is "ruby" the
92
97
  engine version specified _must_ match the Ruby version.
93
98
 
94
- ruby "1.8.7", :engine => "jruby", :engine_version => "1.6.7"
99
+ ruby "1.8.7", engine: "jruby", engine_version: "1.6.7"
95
100
 
96
101
  ### PATCHLEVEL
97
102
 
98
103
  Each application _may_ specify a Ruby patchlevel.
99
104
 
100
- ruby "2.0.0", :patchlevel => "247"
105
+ ruby "2.0.0", patchlevel: "247"
101
106
 
102
107
  ## GEMS
103
108
 
@@ -124,23 +129,23 @@ Each _gem_ `MAY` specify files that should be used when autorequiring via
124
129
  you want `required` has the same name as _gem_ or `false` to
125
130
  prevent any file from being autorequired.
126
131
 
127
- gem "redis", :require => ["redis/connection/hiredis", "redis"]
128
- gem "webmock", :require => false
129
- gem "byebug", :require => true
132
+ gem "redis", require: ["redis/connection/hiredis", "redis"]
133
+ gem "webmock", require: false
134
+ gem "byebug", require: true
130
135
 
131
136
  The argument defaults to the name of the gem. For example, these are identical:
132
137
 
133
138
  gem "nokogiri"
134
- gem "nokogiri", :require => "nokogiri"
135
- gem "nokogiri", :require => true
139
+ gem "nokogiri", require: "nokogiri"
140
+ gem "nokogiri", require: true
136
141
 
137
142
  ### GROUPS
138
143
 
139
144
  Each _gem_ `MAY` specify membership in one or more groups. Any _gem_ that does
140
145
  not specify membership in any group is placed in the `default` group.
141
146
 
142
- gem "rspec", :group => :test
143
- gem "wirble", :groups => [:development, :test]
147
+ gem "rspec", group: :test
148
+ gem "wirble", groups: [:development, :test]
144
149
 
145
150
  The Bundler runtime allows its two main methods, `Bundler.setup` and
146
151
  `Bundler.require`, to limit their impact to particular groups.
@@ -223,32 +228,46 @@ The full list of platforms and supported versions includes:
223
228
 
224
229
  As with groups, you can specify one or more platforms:
225
230
 
226
- gem "weakling", :platforms => :jruby
227
- gem "ruby-debug", :platforms => :mri_18
228
- gem "nokogiri", :platforms => [:mri_18, :jruby]
231
+ gem "weakling", platforms: :jruby
232
+ gem "ruby-debug", platforms: :mri_18
233
+ gem "nokogiri", platforms: [:mri_18, :jruby]
229
234
 
230
235
  All operations involving groups ([`bundle install`](bundle-install.1.html), `Bundler.setup`,
231
236
  `Bundler.require`) behave exactly the same as if any groups not
232
237
  matching the current platform were explicitly excluded.
233
238
 
239
+ ### FORCE_RUBY_PLATFORM
240
+
241
+ If you always want the pure ruby variant of a gem to be chosen over platform
242
+ specific variants, you can use the `force_ruby_platform` option:
243
+
244
+ gem "ffi", force_ruby_platform: true
245
+
246
+ This can be handy (assuming the pure ruby variant works fine) when:
247
+
248
+ * You're having issues with the platform specific variant.
249
+ * The platform specific variant does not yet support a newer ruby (and thus has
250
+ a `required_ruby_version` upper bound), but you still want your Gemfile{.lock}
251
+ files to resolve under that ruby.
252
+
234
253
  ### SOURCE
235
254
 
236
- You can select an alternate Rubygems repository for a gem using the ':source'
255
+ You can select an alternate RubyGems repository for a gem using the ':source'
237
256
  option.
238
257
 
239
- gem "some_internal_gem", :source => "https://gems.example.com"
258
+ gem "some_internal_gem", source: "https://gems.example.com"
240
259
 
241
- This forces the gem to be loaded from this source and ignores any global sources
260
+ This forces the gem to be loaded from this source and ignores the global source
242
261
  declared at the top level of the file. If the gem does not exist in this source,
243
262
  it will not be installed.
244
263
 
245
264
  Bundler will search for child dependencies of this gem by first looking in the
246
265
  source selected for the parent, but if they are not found there, it will fall
247
- back on global sources using the ordering described in [SOURCE PRIORITY][].
266
+ back on the global source.
248
267
 
268
+ **Note about a behavior of the feature deprecated in Bundler 1.13**:
249
269
  Selecting a specific source repository this way also suppresses the ambiguous
250
- gem warning described above in
251
- [GLOBAL SOURCES (#source)](#GLOBAL-SOURCES).
270
+ gem warning described above in [GLOBAL SOURCE](#GLOBAL-SOURCE).
252
271
 
253
272
  Using the `:source` option for an individual gem will also make that source
254
273
  available as a possible global source for any other gems which do not specify
@@ -263,11 +282,11 @@ git repository using the `:git` parameter. The repository can be accessed via
263
282
  several protocols:
264
283
 
265
284
  * `HTTP(S)`:
266
- gem "rails", :git => "https://github.com/rails/rails.git"
285
+ gem "rails", git: "https://github.com/rails/rails.git"
267
286
  * `SSH`:
268
- gem "rails", :git => "git@github.com:rails/rails.git"
287
+ gem "rails", git: "git@github.com:rails/rails.git"
269
288
  * `git`:
270
- gem "rails", :git => "git://github.com/rails/rails.git"
289
+ gem "rails", git: "git://github.com/rails/rails.git"
271
290
 
272
291
  If using SSH, the user that you use to run `bundle install` `MUST` have the
273
292
  appropriate keys available in their `$HOME/.ssh`.
@@ -295,7 +314,7 @@ to, a version specifier, if provided, means that the git repository is
295
314
  only valid if the `.gemspec` specifies a version matching the version
296
315
  specifier. If not, bundler will print a warning.
297
316
 
298
- gem "rails", "2.3.8", :git => "https://github.com/rails/rails.git"
317
+ gem "rails", "2.3.8", git: "https://github.com/rails/rails.git"
299
318
  # bundle install will fail, because the .gemspec in the rails
300
319
  # repository's master branch specifies version 3.0.0
301
320
 
@@ -307,18 +326,18 @@ Git repositories support a number of additional options.
307
326
 
308
327
  * `branch`, `tag`, and `ref`:
309
328
  You `MUST` only specify at most one of these options. The default
310
- is `:branch => "master"`. For example:
329
+ is `branch: "master"`. For example:
311
330
 
312
- gem "rails", :git => "https://github.com/rails/rails.git", :branch => "5-0-stable"
331
+ gem "rails", git: "https://github.com/rails/rails.git", branch: "5-0-stable"
313
332
 
314
- gem "rails", :git => "https://github.com/rails/rails.git", :tag => "v5.0.0"
333
+ gem "rails", git: "https://github.com/rails/rails.git", tag: "v5.0.0"
315
334
 
316
- gem "rails", :git => "https://github.com/rails/rails.git", :ref => "4aded"
335
+ gem "rails", git: "https://github.com/rails/rails.git", ref: "4aded"
317
336
 
318
337
  * `submodules`:
319
338
  For reference, a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules)
320
339
  lets you have another git repository within a subfolder of your repository.
321
- Specify `:submodules => true` to cause bundler to expand any
340
+ Specify `submodules: true` to cause bundler to expand any
322
341
  submodules included in the git repository
323
342
 
324
343
  If a git repository contains multiple `.gemspecs`, each `.gemspec`
@@ -346,11 +365,11 @@ as an argument, and a block which receives a single argument and interpolates it
346
365
  string to return the full repo address:
347
366
 
348
367
  git_source(:stash){ |repo_name| "https://stash.corp.acme.pl/#{repo_name}.git" }
349
- gem 'rails', :stash => 'forks/rails'
368
+ gem 'rails', stash: 'forks/rails'
350
369
 
351
370
  In addition, if you wish to choose a specific branch:
352
371
 
353
- gem "rails", :stash => "forks/rails", :branch => "branch_name"
372
+ gem "rails", stash: "forks/rails", branch: "branch_name"
354
373
 
355
374
  ### GITHUB
356
375
 
@@ -363,33 +382,33 @@ If the git repository you want to use is hosted on GitHub and is public, you can
363
382
  trailing ".git"), separated by a slash. If both the username and repository name are the
364
383
  same, you can omit one.
365
384
 
366
- gem "rails", :github => "rails/rails"
367
- gem "rails", :github => "rails"
385
+ gem "rails", github: "rails/rails"
386
+ gem "rails", github: "rails"
368
387
 
369
388
  Are both equivalent to
370
389
 
371
- gem "rails", :git => "git://github.com/rails/rails.git"
390
+ gem "rails", git: "git://github.com/rails/rails.git"
372
391
 
373
392
  Since the `github` method is a specialization of `git_source`, it accepts a `:branch` named argument.
374
393
 
375
394
  You can also directly pass a pull request URL:
376
395
 
377
- gem "rails", :github => "https://github.com/rails/rails/pull/43753"
396
+ gem "rails", github: "https://github.com/rails/rails/pull/43753"
378
397
 
379
398
  Which is equivalent to:
380
399
 
381
- gem "rails", :github => "rails/rails", branch: "refs/pull/43753/head"
400
+ gem "rails", github: "rails/rails", branch: "refs/pull/43753/head"
382
401
 
383
402
  ### GIST
384
403
 
385
404
  If the git repository you want to use is hosted as a GitHub Gist and is public, you can use
386
405
  the :gist shorthand to specify the gist identifier (without the trailing ".git").
387
406
 
388
- gem "the_hatch", :gist => "4815162342"
407
+ gem "the_hatch", gist: "4815162342"
389
408
 
390
409
  Is equivalent to:
391
410
 
392
- gem "the_hatch", :git => "https://gist.github.com/4815162342.git"
411
+ gem "the_hatch", git: "https://gist.github.com/4815162342.git"
393
412
 
394
413
  Since the `gist` method is a specialization of `git_source`, it accepts a `:branch` named argument.
395
414
 
@@ -400,12 +419,12 @@ If the git repository you want to use is hosted on Bitbucket and is public, you
400
419
  trailing ".git"), separated by a slash. If both the username and repository name are the
401
420
  same, you can omit one.
402
421
 
403
- gem "rails", :bitbucket => "rails/rails"
404
- gem "rails", :bitbucket => "rails"
422
+ gem "rails", bitbucket: "rails/rails"
423
+ gem "rails", bitbucket: "rails"
405
424
 
406
425
  Are both equivalent to
407
426
 
408
- gem "rails", :git => "https://rails@bitbucket.org/rails/rails.git"
427
+ gem "rails", git: "https://rails@bitbucket.org/rails/rails.git"
409
428
 
410
429
  Since the `bitbucket` method is a specialization of `git_source`, it accepts a `:branch` named argument.
411
430
 
@@ -423,7 +442,7 @@ version that bundler should use.
423
442
  Unlike `:git`, bundler does not compile C extensions for
424
443
  gems specified as paths.
425
444
 
426
- gem "rails", :path => "vendor/rails"
445
+ gem "rails", path: "vendor/rails"
427
446
 
428
447
  If you would like to use multiple local gems directly from the filesystem, you can set a global `path` option to the path containing the gem's files. This will automatically load gemspec files from subdirectories.
429
448
 
@@ -452,7 +471,7 @@ applied to a group of gems by using block form.
452
471
  gem "sqlite3"
453
472
  end
454
473
 
455
- group :development, :optional => true do
474
+ group :development, optional: true do
456
475
  gem "wirble"
457
476
  gem "faker"
458
477
  end
@@ -495,8 +514,8 @@ the `.gemspec` file.
495
514
 
496
515
  The `gemspec` method adds any runtime dependencies as gem requirements in the
497
516
  default group. It also adds development dependencies as gem requirements in the
498
- `development` group. Finally, it adds a gem requirement on your project (`:path
499
- => '.'`). In conjunction with `Bundler.setup`, this allows you to require project
517
+ `development` group. Finally, it adds a gem requirement on your project (`path:
518
+ '.'`). In conjunction with `Bundler.setup`, this allows you to require project
500
519
  files in your test code as you would if the project were installed as a gem; you
501
520
  need not manipulate the load path manually or require project files via relative
502
521
  paths.
@@ -521,5 +540,7 @@ bundler uses the following priority order:
521
540
  repository declared on the parent. This results in bundler prioritizing the
522
541
  ActiveSupport gem from the Rails git repository over ones from
523
542
  `rubygems.org`
524
- 3. The sources specified via global `source` lines, searching each source in
525
- your `Gemfile` from last added to first added.
543
+ 3. If neither of the above conditions are met, the global source will be used.
544
+ If multiple global sources are specified, they will be prioritized from
545
+ last to first, but this is deprecated since Bundler 1.13, so Bundler prints
546
+ a warning and will abort with an error in the future.
@@ -16,7 +16,8 @@ module Bundler
16
16
  def initialize(name, version, platform, spec_fetcher)
17
17
  @name = name
18
18
  @version = Gem::Version.create version
19
- @platform = platform
19
+ @original_platform = platform || Gem::Platform::RUBY
20
+ @platform = Gem::Platform.new(platform)
20
21
  @spec_fetcher = spec_fetcher
21
22
  @dependencies = nil
22
23
  end
@@ -35,10 +36,10 @@ module Bundler
35
36
  end
36
37
 
37
38
  def full_name
38
- if platform == Gem::Platform::RUBY || platform.nil?
39
+ if @original_platform == Gem::Platform::RUBY
39
40
  "#{@name}-#{@version}"
40
41
  else
41
- "#{@name}-#{@version}-#{platform}"
42
+ "#{@name}-#{@version}-#{@original_platform}"
42
43
  end
43
44
  end
44
45
 
@@ -105,7 +106,7 @@ module Bundler
105
106
  end
106
107
 
107
108
  def _remote_specification
108
- @_remote_specification ||= @spec_fetcher.fetch_spec([@name, @version, @platform])
109
+ @_remote_specification ||= @spec_fetcher.fetch_spec([@name, @version, @original_platform])
109
110
  @_remote_specification || raise(GemspecError, "Gemspec data for #{full_name} was" \
110
111
  " missing from the server! Try installing with `--full-index` as a workaround.")
111
112
  end
@@ -4,7 +4,7 @@ module Bundler
4
4
  class Resolver
5
5
  class SpecGroup
6
6
  attr_accessor :name, :version, :source
7
- attr_accessor :activated_platforms
7
+ attr_accessor :activated_platforms, :force_ruby_platform
8
8
 
9
9
  def self.create_for(specs, all_platforms, specific_platform)
10
10
  specific_platform_specs = specs[specific_platform]
@@ -35,6 +35,7 @@ module Bundler
35
35
 
36
36
  specs.map do |s|
37
37
  lazy_spec = LazySpecification.new(name, version, s.platform, source)
38
+ lazy_spec.force_ruby_platform = force_ruby_platform
38
39
  lazy_spec.dependencies.replace s.dependencies
39
40
  lazy_spec
40
41
  end
@@ -88,7 +89,7 @@ module Bundler
88
89
  dependencies = []
89
90
  @specs[platform].first.dependencies.each do |dep|
90
91
  next if dep.type == :development
91
- dependencies << DepProxy.get_proxy(dep, platform)
92
+ dependencies << DepProxy.get_proxy(Dependency.new(dep.name, dep.requirement), platform)
92
93
  end
93
94
  dependencies
94
95
  end
@@ -98,10 +99,10 @@ module Bundler
98
99
  return [] if spec.is_a?(LazySpecification)
99
100
  dependencies = []
100
101
  unless spec.required_ruby_version.none?
101
- dependencies << DepProxy.get_proxy(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
102
+ dependencies << DepProxy.get_proxy(Dependency.new("Ruby\0", spec.required_ruby_version), platform)
102
103
  end
103
104
  unless spec.required_rubygems_version.none?
104
- dependencies << DepProxy.get_proxy(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
105
+ dependencies << DepProxy.get_proxy(Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
105
106
  end
106
107
  dependencies
107
108
  end
@@ -22,7 +22,7 @@ module Bundler
22
22
  metadata_requirements, regular_requirements = requirements.partition {|dep| dep.name.end_with?("\0") }
23
23
  resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms, metadata_requirements)
24
24
  result = resolver.start(requirements)
25
- SpecSet.new(SpecSet.new(result).for(regular_requirements))
25
+ SpecSet.new(SpecSet.new(result).for(regular_requirements, false, platforms))
26
26
  end
27
27
 
28
28
  def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms, metadata_requirements)
@@ -32,7 +32,7 @@ module Bundler
32
32
  @resolver = Molinillo::Resolver.new(self, self)
33
33
  @search_for = {}
34
34
  @base_dg = Molinillo::DependencyGraph.new
35
- @base.each do |ls|
35
+ base.each do |ls|
36
36
  dep = Dependency.new(ls.name, ls.version)
37
37
  @base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true)
38
38
  end
@@ -111,7 +111,7 @@ module Bundler
111
111
  dependency = dependency_proxy.dep
112
112
  name = dependency.name
113
113
  @search_for[dependency_proxy] ||= begin
114
- results = results_for(dependency, @base[name])
114
+ results = results_for(dependency) + @base[name].select {|spec| requirement_satisfied_by?(dependency, nil, spec) }
115
115
 
116
116
  if vertex = @base_dg.vertex_named(name)
117
117
  locked_requirement = vertex.payload.requirement
@@ -143,9 +143,12 @@ module Bundler
143
143
  end
144
144
 
145
145
  spec_group_ruby = SpecGroup.create_for(specs_by_platform, [Gem::Platform::RUBY], Gem::Platform::RUBY)
146
- groups << spec_group_ruby if spec_group_ruby
146
+ if spec_group_ruby
147
+ spec_group_ruby.force_ruby_platform = dependency.force_ruby_platform
148
+ groups << spec_group_ruby
149
+ end
147
150
 
148
- next groups if @resolving_only_for_ruby
151
+ next groups if @resolving_only_for_ruby || dependency.force_ruby_platform
149
152
 
150
153
  spec_group = SpecGroup.create_for(specs_by_platform, @platforms, platform)
151
154
  groups << spec_group
@@ -173,8 +176,8 @@ module Bundler
173
176
  @source_requirements[name] || @source_requirements[:default]
174
177
  end
175
178
 
176
- def results_for(dependency, base)
177
- index_for(dependency).search(dependency, base)
179
+ def results_for(dependency)
180
+ index_for(dependency).search(dependency)
178
181
  end
179
182
 
180
183
  def name_for(dependency)
@@ -9,7 +9,7 @@ module Bundler
9
9
  raise GemfileError, "Please define :engine" if options[:engine_version] && options[:engine].nil?
10
10
 
11
11
  if options[:engine] == "ruby" && options[:engine_version] &&
12
- ruby_version != Array(options[:engine_version])
12
+ ruby_version != Array(options[:engine_version])
13
13
  raise GemfileEvalError, "ruby_version must match the :engine_version for MRI"
14
14
  end
15
15
  @ruby_version = RubyVersion.new(ruby_version, options[:patchlevel], options[:engine], options[:engine_version])
@@ -32,12 +32,12 @@ module Bundler
32
32
  @engine = engine && engine.to_s || "ruby"
33
33
  @engine_versions = (engine_version && Array(engine_version)) || @versions
34
34
  @engine_gem_version = Gem::Requirement.create(@engine_versions.first).requirements.first.last
35
- @patchlevel = patchlevel
35
+ @patchlevel = patchlevel || (@gem_version.prerelease? ? "-1" : nil)
36
36
  end
37
37
 
38
38
  def to_s(versions = self.versions)
39
39
  output = String.new("ruby #{versions_string(versions)}")
40
- output << "p#{patchlevel}" if patchlevel
40
+ output << "p#{patchlevel}" if patchlevel && patchlevel != "-1"
41
41
  output << " (#{engine} #{versions_string(engine_versions)})" unless engine == "ruby"
42
42
 
43
43
  output
@@ -46,7 +46,7 @@ module Bundler
46
46
  # @private
47
47
  PATTERN = /
48
48
  ruby\s
49
- ([\d.]+) # ruby version
49
+ (\d+\.\d+\.\d+(?:\.\S+)?) # ruby version
50
50
  (?:p(-?\d+))? # optional patchlevel
51
51
  (?:\s\((\S+)\s(.+)\))? # optional engine info
52
52
  /xo.freeze
@@ -103,8 +103,8 @@ module Bundler
103
103
 
104
104
  def self.system
105
105
  ruby_engine = RUBY_ENGINE.dup
106
- ruby_version = RUBY_VERSION.dup
107
- ruby_engine_version = RUBY_ENGINE_VERSION.dup
106
+ ruby_version = Gem.ruby_version.to_s
107
+ ruby_engine_version = RUBY_ENGINE == "ruby" ? ruby_version : RUBY_ENGINE_VERSION.dup
108
108
  patchlevel = RUBY_PATCHLEVEL.to_s
109
109
 
110
110
  @ruby_version ||= RubyVersion.new(ruby_version, patchlevel, ruby_engine, ruby_engine_version)
@@ -17,6 +17,15 @@ require "rubygems/source"
17
17
 
18
18
  require_relative "match_platform"
19
19
 
20
+ # Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler
21
+ # versions and ignore patchlevels
22
+ # (https://github.com/rubygems/rubygems/pull/5472,
23
+ # https://github.com/rubygems/rubygems/pull/5486). May be removed once RubyGems
24
+ # 3.3.12 support is dropped.
25
+ unless Gem.ruby_version.to_s == RUBY_VERSION || RUBY_PATCHLEVEL == -1
26
+ Gem.instance_variable_set(:@ruby_version, Gem::Version.new(RUBY_VERSION))
27
+ end
28
+
20
29
  module Gem
21
30
  class Specification
22
31
  include ::Bundler::MatchPlatform
@@ -146,6 +155,10 @@ module Gem
146
155
 
147
156
  alias_method :eql?, :==
148
157
 
158
+ def force_ruby_platform
159
+ false
160
+ end
161
+
149
162
  def encode_with(coder)
150
163
  to_yaml_properties.each do |ivar|
151
164
  coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar)
@@ -25,7 +25,7 @@ module Bundler
25
25
 
26
26
  extract_files
27
27
 
28
- build_extensions
28
+ build_extensions if spec.extensions.any?
29
29
  write_build_info_file
30
30
  run_post_build_hooks
31
31
 
@@ -66,26 +66,26 @@ module Bundler
66
66
 
67
67
  def build_extensions
68
68
  extension_cache_path = options[:bundler_extension_cache_path]
69
- unless extension_cache_path && extension_dir = spec.extension_dir
70
- require "shellwords" unless Bundler.rubygems.provides?(">= 3.2.25")
69
+ extension_dir = spec.extension_dir
70
+ unless extension_cache_path && extension_dir
71
+ prepare_extension_build(extension_dir)
71
72
  return super
72
73
  end
73
74
 
74
- extension_dir = Pathname.new(extension_dir)
75
75
  build_complete = SharedHelpers.filesystem_access(extension_cache_path.join("gem.build_complete"), :read, &:file?)
76
76
  if build_complete && !options[:force]
77
- SharedHelpers.filesystem_access(extension_dir.parent, &:mkpath)
77
+ SharedHelpers.filesystem_access(File.dirname(extension_dir)) do |p|
78
+ FileUtils.mkpath p
79
+ end
78
80
  SharedHelpers.filesystem_access(extension_cache_path) do
79
- FileUtils.cp_r extension_cache_path, spec.extension_dir
81
+ FileUtils.cp_r extension_cache_path, extension_dir
80
82
  end
81
83
  else
82
- require "shellwords" # compensate missing require in rubygems before version 3.2.25
84
+ prepare_extension_build(extension_dir)
83
85
  super
84
- if extension_dir.directory? # not made for gems without extensions
85
- SharedHelpers.filesystem_access(extension_cache_path.parent, &:mkpath)
86
- SharedHelpers.filesystem_access(extension_cache_path) do
87
- FileUtils.cp_r extension_dir, extension_cache_path
88
- end
86
+ SharedHelpers.filesystem_access(extension_cache_path.parent, &:mkpath)
87
+ SharedHelpers.filesystem_access(extension_cache_path) do
88
+ FileUtils.cp_r extension_dir, extension_cache_path
89
89
  end
90
90
  end
91
91
  end
@@ -100,6 +100,13 @@ module Bundler
100
100
 
101
101
  private
102
102
 
103
+ def prepare_extension_build(extension_dir)
104
+ SharedHelpers.filesystem_access(extension_dir, :create) do
105
+ FileUtils.mkdir_p extension_dir
106
+ end
107
+ require "shellwords" unless Bundler.rubygems.provides?(">= 3.2.25")
108
+ end
109
+
103
110
  def strict_rm_rf(dir)
104
111
  Bundler.rm_rf dir
105
112
  rescue Errno::ENOTEMPTY => e
@@ -125,7 +125,6 @@ module Bundler
125
125
  specs_to_cache.each do |spec|
126
126
  next if spec.name == "bundler"
127
127
  next if spec.source.is_a?(Source::Gemspec)
128
- spec.source.send(:fetch_gem, spec) if Bundler.settings[:cache_all_platforms] && spec.source.respond_to?(:fetch_gem, true)
129
128
  spec.source.cache(spec, custom_path) if spec.source.respond_to?(:cache)
130
129
  end
131
130
 
@@ -57,6 +57,7 @@ module Bundler
57
57
  ].freeze
58
58
 
59
59
  ARRAY_KEYS = %w[
60
+ only
60
61
  with
61
62
  without
62
63
  ].freeze
@@ -5,7 +5,7 @@ module Bundler
5
5
  class Metadata < Source
6
6
  def specs
7
7
  @specs ||= Index.build do |idx|
8
- idx << Gem::Specification.new("Ruby\0", RubyVersion.system.gem_version)
8
+ idx << Gem::Specification.new("Ruby\0", Gem.ruby_version)
9
9
  idx << Gem::Specification.new("RubyGems\0", Gem::VERSION) do |s|
10
10
  s.required_rubygems_version = Gem::Requirement.default
11
11
  end
@@ -153,13 +153,11 @@ module Bundler
153
153
  # Check for this spec from other sources
154
154
  uris = [spec.remote, *remotes_for_spec(spec)].map(&:anonymized_uri).uniq
155
155
  Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1
156
-
157
- path = fetch_gem(spec, options[:previous_spec])
158
- else
159
- path = cached_gem(spec)
160
- raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
161
156
  end
162
157
 
158
+ path = fetch_gem_if_possible(spec, options[:previous_spec])
159
+ raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
160
+
163
161
  return if Bundler.settings[:no_install]
164
162
 
165
163
  if requires_sudo?
@@ -242,7 +240,7 @@ module Bundler
242
240
  end
243
241
 
244
242
  def cache(spec, custom_path = nil)
245
- cached_path = cached_gem(spec)
243
+ cached_path = Bundler.settings[:cache_all_platforms] ? fetch_gem_if_possible(spec) : cached_gem(spec)
246
244
  raise GemNotFound, "Missing gem file '#{spec.file_name}'." unless cached_path
247
245
  return if File.dirname(cached_path) == Bundler.app_cache.to_s
248
246
  Bundler.ui.info " * #{File.basename(cached_path)}"
@@ -462,6 +460,14 @@ module Bundler
462
460
  end
463
461
  end
464
462
 
463
+ def fetch_gem_if_possible(spec, previous_spec = nil)
464
+ if spec.remote
465
+ fetch_gem(spec, previous_spec)
466
+ else
467
+ cached_gem(spec)
468
+ end
469
+ end
470
+
465
471
  def fetch_gem(spec, previous_spec = nil)
466
472
  spec.fetch_platform
467
473
 
@@ -101,6 +101,10 @@ module Bundler
101
101
  source_list_for(source).find {|s| equivalent_source?(source, s) }
102
102
  end
103
103
 
104
+ def get_with_fallback(source)
105
+ get(source) || default_source
106
+ end
107
+
104
108
  def lock_sources
105
109
  lock_other_sources + lock_rubygems_sources
106
110
  end