bundler 2.4.2 → 2.4.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c50aec0246059478bdcdda64f7415e38e121d9da86c2699aaa783b4285582ad5
4
- data.tar.gz: e2d1a40547e08d932b46e0888d84cef117397403cd4ce880290551cdf7b071db
3
+ metadata.gz: 3c086402f586de5162fbccb5f97175ef0539debc5010faed4a7cd25b94c9a0c1
4
+ data.tar.gz: 5b0c3726de4085c618f785727c4572b70717e390bf7444a07ff44a3b2c46de64
5
5
  SHA512:
6
- metadata.gz: 393eb0a68ebe556e755fabbd606702eb1515f7538fbf90b319867c994ba3e460f719bede31dd877176eb9b72f213af2cd429af580ec6a4b54dfca7e83e988080
7
- data.tar.gz: a8988d4ace205c0ea09f59775ed87e73ae16f91c2f41580b0e6eb0a98040caad70899bb4892413abd66b02d7f36c967b6c47e775fd354d8460ccea1ad0e1f756
6
+ metadata.gz: fee7f484591b307723fad8855c6b76d516648e37a0e51636d67fd642cf65a057a0e48c7ed80588833fb962196694f23644c3965cd5490c6c70f0add41d1d371e
7
+ data.tar.gz: 362ccbe671ea531b2e187c468ec6e841fffe3e500d56d3f99e283623b791c62643d8098d0460c77285d09353009bdd135369ce45746a8da368e696e70cafc45b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ # 2.4.4 (January 16, 2023)
2
+
3
+ ## Bug fixes:
4
+
5
+ - Fix platform specific gems removed from the lockfile [#6266](https://github.com/rubygems/rubygems/pull/6266)
6
+ - Properly handle incompatibilities on platform specific gems [#6270](https://github.com/rubygems/rubygems/pull/6270)
7
+ - Optimistically exclude prereleases from initial resolution [#6246](https://github.com/rubygems/rubygems/pull/6246)
8
+ - Fix another case of not properly falling back to ruby variant when materializing [#6261](https://github.com/rubygems/rubygems/pull/6261)
9
+ - Skip setting `BUNDLER_SETUP` on Ruby 2.6 [#6252](https://github.com/rubygems/rubygems/pull/6252)
10
+ - Let resolver deal with legacy gems with equivalent version and different dependencies [#6219](https://github.com/rubygems/rubygems/pull/6219)
11
+
12
+ # 2.4.3 (January 6, 2023)
13
+
14
+ ## Enhancements:
15
+
16
+ - Enhance `bundle open` command to allow opening subdir/file of gem [#6146](https://github.com/rubygems/rubygems/pull/6146)
17
+
18
+ ## Bug fixes:
19
+
20
+ - Fix pointing GitHub sources to PRs [#6241](https://github.com/rubygems/rubygems/pull/6241)
21
+ - Fix version ranges incorrectly handling platforms [#6240](https://github.com/rubygems/rubygems/pull/6240)
22
+ - Cleanup unnecessary gems when removing lockfile platforms [#6234](https://github.com/rubygems/rubygems/pull/6234)
23
+ - When auto-removing RUBY platform don't add specific platform if not needed [#6233](https://github.com/rubygems/rubygems/pull/6233)
24
+ - Fallback to selecting installable candidates if possible when materializing specs [#6225](https://github.com/rubygems/rubygems/pull/6225)
25
+
26
+ ## Documentation:
27
+
28
+ - Fix several typos [#6224](https://github.com/rubygems/rubygems/pull/6224)
29
+
1
30
  # 2.4.2 (January 1, 2023)
2
31
 
3
32
  ## Performance:
@@ -1518,7 +1547,7 @@ Changes
1518
1547
 
1519
1548
  - avoid new RubyGems warning about unsafe YAML loading (to keep output consistent) (@segiddins)
1520
1549
  - load digest subclasses in a thread-safe manner (@segiddins, @colby-swandale)
1521
- - avoid unusued variable warnings under ruby 2.5 (@amatsuda)
1550
+ - avoid unused variable warnings under ruby 2.5 (@amatsuda)
1522
1551
  - fix printing the same message twice in verbose mode ([#6028](https://github.com/rubygems/bundler/issues/6028), @akhramov)
1523
1552
  - allow `SignalException`s to bubble up to the interpreter during `bundle exec` ([#6090](https://github.com/rubygems/bundler/issues/6090), @dekellum)
1524
1553
  - avoid activating stdlib digest under Ruby 2.5 (@segiddins)
@@ -4,8 +4,8 @@ module Bundler
4
4
  # Represents metadata from when the Bundler gem was built.
5
5
  module BuildMetadata
6
6
  # begin ivars
7
- @built_at = "2023-01-01".freeze
8
- @git_commit_sha = "2cd3ed45bf".freeze
7
+ @built_at = "2023-01-16".freeze
8
+ @git_commit_sha = "e1c0b50e84".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -2,23 +2,25 @@
2
2
 
3
3
  module Bundler
4
4
  class CLI::Open
5
- attr_reader :options, :name
5
+ attr_reader :options, :name, :path
6
6
  def initialize(options, name)
7
7
  @options = options
8
8
  @name = name
9
+ @path = options[:path] unless options[:path].nil?
9
10
  end
10
11
 
11
12
  def run
13
+ raise InvalidOption, "Cannot specify `--path` option without a value" if !@path.nil? && @path.empty?
12
14
  editor = [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }
13
15
  return Bundler.ui.info("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR") unless editor
14
16
  return unless spec = Bundler::CLI::Common.select_spec(name, :regex_match)
15
17
  if spec.default_gem?
16
18
  Bundler.ui.info "Unable to open #{name} because it's a default gem, so the directory it would normally be installed to does not exist."
17
19
  else
18
- path = spec.full_gem_path
19
- Dir.chdir(path) do
20
+ root_path = spec.full_gem_path
21
+ Dir.chdir(root_path) do
20
22
  require "shellwords"
21
- command = Shellwords.split(editor) + [path]
23
+ command = Shellwords.split(editor) << File.join([root_path, path].compact)
22
24
  Bundler.with_original_env do
23
25
  system(*command)
24
26
  end || Bundler.ui.info("Could not run '#{command.join(" ")}'")
data/lib/bundler/cli.rb CHANGED
@@ -509,6 +509,7 @@ module Bundler
509
509
  subcommand "config", Config
510
510
 
511
511
  desc "open GEM", "Opens the source directory of the given bundled gem"
512
+ method_option "path", :type => :string, :lazy_default => "", :banner => "Open relative path of the gem source."
512
513
  def open(name)
513
514
  require_relative "cli/open"
514
515
  Open.new(options, name).run
@@ -79,6 +79,7 @@ module Bundler
79
79
  @locked_bundler_version = nil
80
80
  @locked_ruby_version = nil
81
81
  @new_platform = nil
82
+ @removed_platform = nil
82
83
 
83
84
  if lockfile && File.exist?(lockfile)
84
85
  @lockfile_contents = Bundler.read_file(lockfile)
@@ -129,7 +130,7 @@ module Bundler
129
130
  end
130
131
  @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
131
132
 
132
- add_current_platform unless current_ruby_platform_locked? || Bundler.frozen_bundle?
133
+ add_current_platform unless Bundler.frozen_bundle?
133
134
 
134
135
  converge_path_sources_to_gemspec_sources
135
136
  @path_changes = converge_paths
@@ -158,13 +159,6 @@ module Bundler
158
159
  resolve
159
160
  end
160
161
 
161
- def resolve_prefering_local!
162
- @prefer_local = true
163
- @remote = true
164
- sources.remote!
165
- resolve
166
- end
167
-
168
162
  def resolve_with_cache!
169
163
  sources.cached!
170
164
  resolve
@@ -176,6 +170,23 @@ module Bundler
176
170
  resolve
177
171
  end
178
172
 
173
+ def resolution_mode=(options)
174
+ if options["local"]
175
+ @remote = false
176
+ else
177
+ @remote = true
178
+ @prefer_local = options["prefer-local"]
179
+ end
180
+ end
181
+
182
+ def setup_sources_for_resolve
183
+ if @remote == false
184
+ sources.cached!
185
+ else
186
+ sources.remote!
187
+ end
188
+ end
189
+
179
190
  # For given dependency list returns a SpecSet with Gemspec of all the required
180
191
  # dependencies.
181
192
  # 1. The method first resolves the dependencies specified in Gemfile
@@ -267,7 +278,7 @@ module Bundler
267
278
  SpecSet.new(filter_specs(@locked_specs, @dependencies - deleted_deps))
268
279
  else
269
280
  Bundler.ui.debug "Found no changes, using resolution from the lockfile"
270
- if @locked_gems.may_include_redundant_platform_specific_gems?
281
+ if @removed_platform || @locked_gems.may_include_redundant_platform_specific_gems?
271
282
  SpecSet.new(filter_specs(@locked_specs, @dependencies))
272
283
  else
273
284
  @locked_specs
@@ -446,7 +457,9 @@ module Bundler
446
457
  end
447
458
 
448
459
  def remove_platform(platform)
449
- return if @platforms.delete(Gem::Platform.new(platform))
460
+ removed_platform = @platforms.delete(Gem::Platform.new(platform))
461
+ @removed_platform ||= removed_platform
462
+ return if removed_platform
450
463
  raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
451
464
  end
452
465
 
@@ -470,11 +483,7 @@ module Bundler
470
483
  private
471
484
 
472
485
  def resolver
473
- @resolver ||= begin
474
- last_resolve = converge_locked_specs
475
- remove_ruby_from_platforms_if_necessary!(current_dependencies)
476
- Resolver.new(source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve(last_resolve))
477
- end
486
+ @resolver ||= Resolver.new(resolution_packages, gem_version_promoter)
478
487
  end
479
488
 
480
489
  def expanded_dependencies
@@ -483,18 +492,10 @@ module Bundler
483
492
 
484
493
  def resolution_packages
485
494
  @resolution_packages ||= begin
486
- packages = Hash.new do |h, k|
487
- h[k] = Resolver::Package.new(k, @platforms, @originally_locked_specs, @unlock[:gems])
488
- end
489
-
490
- expanded_dependencies.each do |dep|
491
- name = dep.name
492
- platforms = dep.gem_platforms(@platforms)
493
-
494
- packages[name] = Resolver::Package.new(name, platforms, @originally_locked_specs, @unlock[:gems], :dependency => dep)
495
- end
496
-
497
- packages
495
+ last_resolve = converge_locked_specs
496
+ remove_ruby_from_platforms_if_necessary!(current_dependencies)
497
+ packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, :locked_specs => @originally_locked_specs, :unlock => @unlock[:gems], :prerelease => gem_version_promoter.pre?)
498
+ additional_base_requirements_for_resolve(packages, last_resolve)
498
499
  end
499
500
  end
500
501
 
@@ -528,13 +529,15 @@ module Bundler
528
529
  break if incomplete_specs.empty?
529
530
 
530
531
  Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
531
- @resolve = start_resolution(:exclude_specs => incomplete_specs)
532
+ setup_sources_for_resolve
533
+ resolution_packages.delete(incomplete_specs)
534
+ @resolve = start_resolution
532
535
  specs = resolve.materialize(dependencies)
533
536
 
534
537
  still_incomplete_specs = specs.incomplete_specs
535
538
 
536
539
  if still_incomplete_specs == incomplete_specs
537
- package = resolution_packages[incomplete_specs.first.name]
540
+ package = resolution_packages.get_package(incomplete_specs.first.name)
538
541
  resolver.raise_not_found! package
539
542
  end
540
543
 
@@ -547,8 +550,8 @@ module Bundler
547
550
  specs
548
551
  end
549
552
 
550
- def start_resolution(exclude_specs: [])
551
- result = resolver.start(expanded_dependencies, resolution_packages, :exclude_specs => exclude_specs)
553
+ def start_resolution
554
+ result = resolver.start(expanded_dependencies)
552
555
 
553
556
  SpecSet.new(SpecSet.new(result).for(dependencies, false, @platforms))
554
557
  end
@@ -584,6 +587,8 @@ module Bundler
584
587
  end
585
588
 
586
589
  def add_current_platform
590
+ return if current_ruby_platform_locked?
591
+
587
592
  add_platform(local_platform)
588
593
  end
589
594
 
@@ -880,11 +885,12 @@ module Bundler
880
885
  current == proposed
881
886
  end
882
887
 
883
- def additional_base_requirements_for_resolve(last_resolve)
884
- return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
885
- converge_specs(@originally_locked_specs - last_resolve).map do |locked_spec|
886
- Dependency.new(locked_spec.name, ">= #{locked_spec.version}")
887
- end.uniq
888
+ def additional_base_requirements_for_resolve(resolution_packages, last_resolve)
889
+ return resolution_packages unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
890
+ converge_specs(@originally_locked_specs - last_resolve).each do |locked_spec|
891
+ resolution_packages.base_requirements[locked_spec.name] = Gem::Requirement.new(">= #{locked_spec.version}")
892
+ end
893
+ resolution_packages
888
894
  end
889
895
 
890
896
  def remove_ruby_from_platforms_if_necessary!(dependencies)
data/lib/bundler/dsl.rb CHANGED
@@ -277,8 +277,8 @@ module Bundler
277
277
  if repo_name =~ GITHUB_PULL_REQUEST_URL
278
278
  {
279
279
  "git" => "https://github.com/#{$1}.git",
280
- "branch" => "refs/pull/#{$2}/head",
281
- "ref" => nil,
280
+ "branch" => nil,
281
+ "ref" => "refs/pull/#{$2}/head",
282
282
  "tag" => nil,
283
283
  }
284
284
  else
@@ -249,17 +249,13 @@ module Bundler
249
249
 
250
250
  # returns whether or not a re-resolve was needed
251
251
  def resolve_if_needed(options)
252
+ @definition.resolution_mode = options
253
+
252
254
  if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
253
255
  return false if @definition.nothing_changed? && !@definition.missing_specs?
254
256
  end
255
257
 
256
- if options["local"]
257
- @definition.resolve_with_cache!
258
- elsif options["prefer-local"]
259
- @definition.resolve_prefering_local!
260
- else
261
- @definition.resolve_remotely!
262
- end
258
+ @definition.setup_sources_for_resolve
263
259
 
264
260
  true
265
261
  end
@@ -16,7 +16,6 @@ module Bundler
16
16
  @dependencies = []
17
17
  @platform = platform || Gem::Platform::RUBY
18
18
  @source = source
19
- @specification = nil
20
19
  @force_ruby_platform = default_force_ruby_platform
21
20
  end
22
21
 
@@ -80,37 +79,46 @@ module Bundler
80
79
  def materialize_for_installation
81
80
  source.local!
82
81
 
83
- candidates = if source.is_a?(Source::Path) || !ruby_platform_materializes_to_ruby_platform?
84
- target_platform = ruby_platform_materializes_to_ruby_platform? ? platform : local_platform
82
+ matching_specs = source.specs.search(use_exact_resolved_specifications? ? self : [name, version])
83
+ return self if matching_specs.empty?
85
84
 
86
- GemHelpers.select_best_platform_match(source.specs.search([name, version]), target_platform)
85
+ candidates = if use_exact_resolved_specifications?
86
+ matching_specs
87
87
  else
88
- source.specs.search(self)
89
- end
88
+ target_platform = ruby_platform_materializes_to_ruby_platform? ? platform : local_platform
90
89
 
91
- return self if candidates.empty?
90
+ installable_candidates = GemHelpers.select_best_platform_match(matching_specs, target_platform)
92
91
 
93
- __materialize__(candidates)
94
- end
92
+ specification = __materialize__(installable_candidates, :fallback_to_non_installable => false)
93
+ return specification unless specification.nil?
95
94
 
96
- def __materialize__(candidates)
97
- @specification = begin
98
- search = candidates.reverse.find do |spec|
99
- spec.is_a?(StubSpecification) ||
100
- (spec.matches_current_ruby? &&
101
- spec.matches_current_rubygems?)
102
- end
103
- if search.nil? && Bundler.frozen_bundle?
104
- search = candidates.last
105
- else
106
- search.dependencies = dependencies if search && search.full_name == full_name && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
95
+ if target_platform != platform
96
+ installable_candidates = GemHelpers.select_best_platform_match(matching_specs, platform)
107
97
  end
108
- search
98
+
99
+ installable_candidates
109
100
  end
101
+
102
+ __materialize__(candidates)
110
103
  end
111
104
 
112
- def respond_to?(*args)
113
- super || @specification ? @specification.respond_to?(*args) : nil
105
+ # If in frozen mode, we fallback to a non-installable candidate because by
106
+ # doing this we avoid re-resolving and potentially end up changing the
107
+ # lock file, which is not allowed. In that case, we will give a proper error
108
+ # about the mismatch higher up the stack, right before trying to install the
109
+ # bad gem.
110
+ def __materialize__(candidates, fallback_to_non_installable: Bundler.frozen_bundle?)
111
+ search = candidates.reverse.find do |spec|
112
+ spec.is_a?(StubSpecification) ||
113
+ (spec.matches_current_ruby? &&
114
+ spec.matches_current_rubygems?)
115
+ end
116
+ if search.nil? && fallback_to_non_installable
117
+ search = candidates.last
118
+ else
119
+ search.dependencies = dependencies if search && search.full_name == full_name && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
120
+ end
121
+ search
114
122
  end
115
123
 
116
124
  def to_s
@@ -132,16 +140,8 @@ module Bundler
132
140
 
133
141
  private
134
142
 
135
- def to_ary
136
- nil
137
- end
138
-
139
- def method_missing(method, *args, &blk)
140
- raise "LazySpecification has not been materialized yet (calling :#{method} #{args.inspect})" unless @specification
141
-
142
- return super unless respond_to?(method)
143
-
144
- @specification.send(method, *args, &blk)
143
+ def use_exact_resolved_specifications?
144
+ @use_exact_resolved_specifications ||= !source.is_a?(Source::Path) && ruby_platform_materializes_to_ruby_platform?
145
145
  end
146
146
 
147
147
  #
@@ -7,7 +7,7 @@
7
7
  \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
8
8
  .
9
9
  .SH "SYNOPSIS"
10
- \fBbundle open\fR [GEM]
10
+ \fBbundle open\fR [GEM] [\-\-path=PATH]
11
11
  .
12
12
  .SH "DESCRIPTION"
13
13
  Opens the source directory of the provided GEM in your editor\.
@@ -30,3 +30,23 @@ bundle open \'rack\'
30
30
  .
31
31
  .P
32
32
  Will open the source directory for the \'rack\' gem in your bundle\.
33
+ .
34
+ .IP "" 4
35
+ .
36
+ .nf
37
+
38
+ bundle open \'rack\' \-\-path \'README\.md\'
39
+ .
40
+ .fi
41
+ .
42
+ .IP "" 0
43
+ .
44
+ .P
45
+ Will open the README\.md file of the \'rack\' gem source in your bundle\.
46
+ .
47
+ .SH "OPTIONS"
48
+ .
49
+ .TP
50
+ \fB\-\-path\fR
51
+ Specify GEM source relative path to open\.
52
+
@@ -3,7 +3,7 @@ bundle-open(1) -- Opens the source directory for a gem in your bundle
3
3
 
4
4
  ## SYNOPSIS
5
5
 
6
- `bundle open` [GEM]
6
+ `bundle open` [GEM] [--path=PATH]
7
7
 
8
8
  ## DESCRIPTION
9
9
 
@@ -17,3 +17,11 @@ Example:
17
17
  bundle open 'rack'
18
18
 
19
19
  Will open the source directory for the 'rack' gem in your bundle.
20
+
21
+ bundle open 'rack' --path 'README.md'
22
+
23
+ Will open the README.md file of the 'rack' gem source in your bundle.
24
+
25
+ ## OPTIONS
26
+ * `--path`:
27
+ Specify GEM source relative path to open.
@@ -1,19 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "package"
4
+
3
5
  module Bundler
4
6
  class Resolver
5
7
  class Base
6
- def initialize(base, additional_base_requirements)
8
+ attr_reader :packages, :source_requirements
9
+
10
+ def initialize(source_requirements, dependencies, base, platforms, options)
11
+ @source_requirements = source_requirements
12
+
7
13
  @base = base
8
- @additional_base_requirements = additional_base_requirements
14
+
15
+ @packages = Hash.new do |hash, name|
16
+ hash[name] = Package.new(name, platforms, **options)
17
+ end
18
+
19
+ dependencies.each do |dep|
20
+ name = dep.name
21
+
22
+ @packages[name] = Package.new(name, dep.gem_platforms(platforms), **options.merge(:dependency => dep))
23
+ end
9
24
  end
10
25
 
11
26
  def [](name)
12
27
  @base[name]
13
28
  end
14
29
 
15
- def delete(spec)
16
- @base.delete(spec)
30
+ def delete(specs)
31
+ specs.each do |spec|
32
+ @base.delete(spec)
33
+ end
34
+ end
35
+
36
+ def get_package(name)
37
+ @packages[name]
17
38
  end
18
39
 
19
40
  def base_requirements
@@ -24,10 +45,14 @@ module Bundler
24
45
  names.each do |name|
25
46
  @base.delete_by_name(name)
26
47
 
27
- @additional_base_requirements.reject! {|dep| dep.name == name }
48
+ @base_requirements.delete(name)
28
49
  end
50
+ end
29
51
 
30
- @base_requirements = nil
52
+ def include_prereleases(names)
53
+ names.each do |name|
54
+ get_package(name).consider_prereleases!
55
+ end
31
56
  end
32
57
 
33
58
  private
@@ -38,7 +63,6 @@ module Bundler
38
63
  req = Gem::Requirement.new(ls.version)
39
64
  base_requirements[ls.name] = req
40
65
  end
41
- @additional_base_requirements.each {|d| base_requirements[d.name] = d.requirement }
42
66
  base_requirements
43
67
  end
44
68
  end
@@ -26,9 +26,8 @@ module Bundler
26
26
 
27
27
  def initialize(version, specs: [])
28
28
  @spec_group = Resolver::SpecGroup.new(specs)
29
- @platforms = specs.map(&:platform).sort_by(&:to_s).uniq
30
29
  @version = Gem::Version.new(version)
31
- @ruby_only = @platforms == [Gem::Platform::RUBY]
30
+ @ruby_only = specs.map(&:platform).uniq == [Gem::Platform::RUBY]
32
31
  end
33
32
 
34
33
  def dependencies
@@ -41,6 +40,18 @@ module Bundler
41
40
  @spec_group.to_specs(package.force_ruby_platform?)
42
41
  end
43
42
 
43
+ def generic!
44
+ @ruby_only = true
45
+
46
+ self
47
+ end
48
+
49
+ def platform_specific!
50
+ @ruby_only = false
51
+
52
+ self
53
+ end
54
+
44
55
  def prerelease?
45
56
  @version.prerelease?
46
57
  end
@@ -53,27 +64,20 @@ module Bundler
53
64
  [@version, @ruby_only ? -1 : 1]
54
65
  end
55
66
 
56
- def canonical?
57
- !@spec_group.empty?
58
- end
59
-
60
67
  def <=>(other)
61
68
  return unless other.is_a?(self.class)
62
- return @version <=> other.version unless canonical? && other.canonical?
63
69
 
64
70
  sort_obj <=> other.sort_obj
65
71
  end
66
72
 
67
73
  def ==(other)
68
74
  return unless other.is_a?(self.class)
69
- return @version == other.version unless canonical? && other.canonical?
70
75
 
71
76
  sort_obj == other.sort_obj
72
77
  end
73
78
 
74
79
  def eql?(other)
75
80
  return unless other.is_a?(self.class)
76
- return @version.eql?(other.version) unless canonical? || other.canonical?
77
81
 
78
82
  sort_obj.eql?(other.sort_obj)
79
83
  end
@@ -83,9 +87,7 @@ module Bundler
83
87
  end
84
88
 
85
89
  def to_s
86
- return @version.to_s if @platforms.empty? || @ruby_only
87
-
88
- "#{@version} (#{@platforms.join(", ")})"
90
+ @version.to_s
89
91
  end
90
92
  end
91
93
  end
@@ -15,12 +15,13 @@ module Bundler
15
15
  class Package
16
16
  attr_reader :name, :platforms, :dependency, :locked_version
17
17
 
18
- def initialize(name, platforms, locked_specs, unlock, dependency: nil)
18
+ def initialize(name, platforms, locked_specs:, unlock:, prerelease: false, dependency: nil)
19
19
  @name = name
20
20
  @platforms = platforms
21
21
  @locked_version = locked_specs[name].first&.version
22
22
  @unlock = unlock
23
23
  @dependency = dependency || Dependency.new(name, @locked_version)
24
+ @prerelease = @dependency.prerelease? || @locked_version&.prerelease? || prerelease ? :consider_first : :ignore
24
25
  end
25
26
 
26
27
  def to_s
@@ -47,8 +48,16 @@ module Bundler
47
48
  @unlock.empty? || @unlock.include?(name)
48
49
  end
49
50
 
51
+ def ignores_prereleases?
52
+ @prerelease == :ignore
53
+ end
54
+
50
55
  def prerelease_specified?
51
- @dependency.prerelease?
56
+ @prerelease == :consider_first
57
+ end
58
+
59
+ def consider_prereleases!
60
+ @prerelease = :consider_last
52
61
  end
53
62
 
54
63
  def force_ruby_platform?
@@ -9,26 +9,21 @@ module Bundler
9
9
  class Resolver
10
10
  require_relative "vendored_pub_grub"
11
11
  require_relative "resolver/base"
12
- require_relative "resolver/package"
13
12
  require_relative "resolver/candidate"
14
13
  require_relative "resolver/incompatibility"
15
14
  require_relative "resolver/root"
16
15
 
17
16
  include GemHelpers
18
17
 
19
- def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements)
20
- @source_requirements = source_requirements
21
- @base = Resolver::Base.new(base, additional_base_requirements)
18
+ def initialize(base, gem_version_promoter)
19
+ @source_requirements = base.source_requirements
20
+ @base = base
22
21
  @gem_version_promoter = gem_version_promoter
23
22
  end
24
23
 
25
- def start(requirements, packages, exclude_specs: [])
26
- exclude_specs.each do |spec|
27
- remove_from_candidates(spec)
28
- end
29
-
24
+ def start(requirements)
30
25
  @requirements = requirements
31
- @packages = packages
26
+ @packages = @base.packages
32
27
 
33
28
  root, logger = setup_solver
34
29
 
@@ -78,33 +73,26 @@ module Bundler
78
73
  rescue PubGrub::SolveFailure => e
79
74
  incompatibility = e.incompatibility
80
75
 
81
- names_to_unlock = []
82
- extended_explanation = nil
76
+ names_to_unlock, names_to_allow_prereleases_for, extended_explanation = find_names_to_relax(incompatibility)
83
77
 
84
- while incompatibility.conflict?
85
- cause = incompatibility.cause
86
- incompatibility = cause.incompatibility
87
-
88
- incompatibility.terms.each do |term|
89
- name = term.package.name
90
- names_to_unlock << name if base_requirements[name]
78
+ names_to_relax = names_to_unlock + names_to_allow_prereleases_for
91
79
 
92
- no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
93
- next unless no_versions_incompat
80
+ if names_to_relax.any?
81
+ if names_to_unlock.any?
82
+ Bundler.ui.debug "Found conflicts with locked dependencies. Will retry with #{names_to_unlock.join(", ")} unlocked...", true
94
83
 
95
- extended_explanation = no_versions_incompat.extended_explanation
84
+ @base.unlock_names(names_to_unlock)
96
85
  end
97
- end
98
-
99
- names_to_unlock.uniq!
100
86
 
101
- if names_to_unlock.any?
102
- Bundler.ui.debug "Found conflicts with locked dependencies. Retrying with #{names_to_unlock.join(", ")} unlocked...", true
87
+ if names_to_allow_prereleases_for.any?
88
+ Bundler.ui.debug "Found conflicts with dependencies with prereleases. Will retrying considering prereleases for #{names_to_allow_prereleases_for.join(", ")}...", true
103
89
 
104
- @base.unlock_names(names_to_unlock)
90
+ @base.include_prereleases(names_to_allow_prereleases_for)
91
+ end
105
92
 
106
93
  root, logger = setup_solver
107
94
 
95
+ Bundler.ui.debug "Retrying resolution...", true
108
96
  retry
109
97
  end
110
98
 
@@ -118,6 +106,35 @@ module Bundler
118
106
  raise SolveFailure.new(explanation)
119
107
  end
120
108
 
109
+ def find_names_to_relax(incompatibility)
110
+ names_to_unlock = []
111
+ names_to_allow_prereleases_for = []
112
+ extended_explanation = nil
113
+
114
+ while incompatibility.conflict?
115
+ cause = incompatibility.cause
116
+ incompatibility = cause.incompatibility
117
+
118
+ incompatibility.terms.each do |term|
119
+ package = term.package
120
+ name = package.name
121
+
122
+ if base_requirements[name]
123
+ names_to_unlock << name
124
+ elsif package.ignores_prereleases?
125
+ names_to_allow_prereleases_for << name
126
+ end
127
+
128
+ no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
129
+ next unless no_versions_incompat
130
+
131
+ extended_explanation = no_versions_incompat.extended_explanation
132
+ end
133
+ end
134
+
135
+ [names_to_unlock.uniq, names_to_allow_prereleases_for.uniq, extended_explanation]
136
+ end
137
+
121
138
  def parse_dependency(package, dependency)
122
139
  range = if repository_for(package).is_a?(Source::Gemspec)
123
140
  PubGrub::VersionRange.any
@@ -215,7 +232,7 @@ module Bundler
215
232
 
216
233
  def all_versions_for(package)
217
234
  name = package.name
218
- results = (@base[name] + @all_specs[name]).uniq(&:full_name)
235
+ results = (@base[name] + filter_prereleases(@all_specs[name], package)).uniq {|spec| [spec.version.hash, spec.platform] }
219
236
  locked_requirement = base_requirements[name]
220
237
  results = filter_matching_specs(results, locked_requirement) if locked_requirement
221
238
 
@@ -284,6 +301,12 @@ module Bundler
284
301
  end
285
302
  end
286
303
 
304
+ def filter_prereleases(specs, package)
305
+ return specs unless package.ignores_prereleases?
306
+
307
+ specs.reject {|s| s.version.prerelease? }
308
+ end
309
+
287
310
  def requirement_satisfied_by?(requirement, spec)
288
311
  requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
289
312
  end
@@ -304,10 +327,6 @@ module Bundler
304
327
  @base.base_requirements
305
328
  end
306
329
 
307
- def remove_from_candidates(spec)
308
- @base.delete(spec)
309
- end
310
-
311
330
  def prepare_dependencies(requirements, packages)
312
331
  to_dependency_hash(requirements, packages).map do |dep_package, dep_constraint|
313
332
  name = dep_package.name
@@ -322,7 +341,15 @@ module Bundler
322
341
  end
323
342
 
324
343
  next [dep_package, dep_constraint] if name == "bundler"
325
- next [dep_package, dep_constraint] unless versions_for(dep_package, dep_constraint.range).empty?
344
+
345
+ versions = versions_for(dep_package, dep_constraint.range)
346
+ if versions.empty? && dep_package.ignores_prereleases?
347
+ @sorted_versions.delete(dep_package)
348
+ dep_package.consider_prereleases!
349
+ versions = versions_for(dep_package, dep_constraint.range)
350
+ end
351
+ next [dep_package, dep_constraint] unless versions.empty?
352
+
326
353
  next unless dep_package.current_platform?
327
354
 
328
355
  raise_not_found!(dep_package)
@@ -337,7 +364,8 @@ module Bundler
337
364
 
338
365
  def requirement_to_range(requirement)
339
366
  ranges = requirement.requirements.map do |(op, version)|
340
- ver = Resolver::Candidate.new(version)
367
+ ver = Resolver::Candidate.new(version).generic!
368
+ platform_ver = Resolver::Candidate.new(version).platform_specific!
341
369
 
342
370
  case op
343
371
  when "~>"
@@ -345,17 +373,17 @@ module Bundler
345
373
  bump = Resolver::Candidate.new(version.bump.to_s + ".A")
346
374
  PubGrub::VersionRange.new(:name => name, :min => ver, :max => bump, :include_min => true)
347
375
  when ">"
348
- PubGrub::VersionRange.new(:min => ver)
376
+ PubGrub::VersionRange.new(:min => platform_ver)
349
377
  when ">="
350
378
  PubGrub::VersionRange.new(:min => ver, :include_min => true)
351
379
  when "<"
352
380
  PubGrub::VersionRange.new(:max => ver)
353
381
  when "<="
354
- PubGrub::VersionRange.new(:max => ver, :include_max => true)
382
+ PubGrub::VersionRange.new(:max => platform_ver, :include_max => true)
355
383
  when "="
356
- PubGrub::VersionRange.new(:min => ver, :max => ver, :include_min => true, :include_max => true)
384
+ PubGrub::VersionRange.new(:min => ver, :max => platform_ver, :include_min => true, :include_max => true)
357
385
  when "!="
358
- PubGrub::VersionRange.new(:min => ver, :max => ver, :include_min => true, :include_max => true).invert
386
+ PubGrub::VersionRange.new(:min => ver, :max => platform_ver, :include_min => true, :include_max => true).invert
359
387
  else
360
388
  raise "bad version specifier: #{op}"
361
389
  end
@@ -284,7 +284,7 @@ module Bundler
284
284
  Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", exe_file
285
285
  Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", find_gemfile.to_s
286
286
  Bundler::SharedHelpers.set_env "BUNDLER_VERSION", Bundler::VERSION
287
- Bundler::SharedHelpers.set_env "BUNDLER_SETUP", File.expand_path("setup", __dir__)
287
+ Bundler::SharedHelpers.set_env "BUNDLER_SETUP", File.expand_path("setup", __dir__) unless RUBY_VERSION < "2.7"
288
288
  end
289
289
 
290
290
  def set_path
@@ -1,5 +1,5 @@
1
1
  # This Cargo.toml is here to let externals tools (IDEs, etc.) know that this is
2
- # a Rust project. Your extensions depedencies should be added to the Cargo.toml
2
+ # a Rust project. Your extensions dependencies should be added to the Cargo.toml
3
3
  # in the ext/ directory.
4
4
 
5
5
  [workspace]
@@ -397,7 +397,7 @@ module Bundler::PubGrub
397
397
 
398
398
  def constraints
399
399
  return ["any"] if any?
400
- return ["= #{min}"] if min == max
400
+ return ["= #{min}"] if min.to_s == max.to_s
401
401
 
402
402
  c = []
403
403
  c << "#{include_min ? ">=" : ">"} #{min}" if min
@@ -148,7 +148,7 @@ module Bundler::PubGrub
148
148
  while !ranges.empty?
149
149
  ne = []
150
150
  range = ranges.shift
151
- while !ranges.empty? && ranges[0].min == range.max
151
+ while !ranges.empty? && ranges[0].min.to_s == range.max.to_s
152
152
  ne << range.max
153
153
  range = range.span(ranges.shift)
154
154
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.4.2".freeze
4
+ VERSION = "2.4.4".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i
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: 2.4.2
4
+ version: 2.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - André Arko
@@ -22,7 +22,7 @@ authors:
22
22
  autorequire:
23
23
  bindir: exe
24
24
  cert_chain: []
25
- date: 2023-01-01 00:00:00.000000000 Z
25
+ date: 2023-01-16 00:00:00.000000000 Z
26
26
  dependencies: []
27
27
  description: Bundler manages an application's dependencies through its entire life,
28
28
  across many machines, systematically and repeatably
@@ -380,7 +380,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
380
380
  - !ruby/object:Gem::Version
381
381
  version: 3.0.1
382
382
  requirements: []
383
- rubygems_version: 3.4.2
383
+ rubygems_version: 3.4.4
384
384
  signing_key:
385
385
  specification_version: 4
386
386
  summary: The best way to manage your application's dependencies