bundler 2.6.5 → 2.6.7

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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -6
  3. data/lib/bundler/build_metadata.rb +2 -2
  4. data/lib/bundler/checksum.rb +22 -12
  5. data/lib/bundler/cli/doctor.rb +14 -14
  6. data/lib/bundler/cli/inject.rb +2 -2
  7. data/lib/bundler/cli/lock.rb +2 -1
  8. data/lib/bundler/compact_index_client/cache.rb +1 -1
  9. data/lib/bundler/compact_index_client/parser.rb +1 -1
  10. data/lib/bundler/compact_index_client/updater.rb +2 -1
  11. data/lib/bundler/definition.rb +108 -91
  12. data/lib/bundler/dsl.rb +2 -3
  13. data/lib/bundler/errors.rb +18 -0
  14. data/lib/bundler/injector.rb +9 -9
  15. data/lib/bundler/lazy_specification.rb +9 -1
  16. data/lib/bundler/lockfile_parser.rb +8 -5
  17. data/lib/bundler/man/bundle-add.1 +1 -1
  18. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  19. data/lib/bundler/man/bundle-cache.1 +1 -1
  20. data/lib/bundler/man/bundle-check.1 +1 -1
  21. data/lib/bundler/man/bundle-clean.1 +1 -1
  22. data/lib/bundler/man/bundle-config.1 +6 -6
  23. data/lib/bundler/man/bundle-config.1.ronn +9 -4
  24. data/lib/bundler/man/bundle-console.1 +1 -1
  25. data/lib/bundler/man/bundle-doctor.1 +1 -1
  26. data/lib/bundler/man/bundle-env.1 +1 -1
  27. data/lib/bundler/man/bundle-exec.1 +3 -3
  28. data/lib/bundler/man/bundle-exec.1.ronn +2 -2
  29. data/lib/bundler/man/bundle-fund.1 +1 -1
  30. data/lib/bundler/man/bundle-gem.1 +1 -1
  31. data/lib/bundler/man/bundle-help.1 +1 -1
  32. data/lib/bundler/man/bundle-info.1 +1 -1
  33. data/lib/bundler/man/bundle-init.1 +1 -1
  34. data/lib/bundler/man/bundle-inject.1 +1 -1
  35. data/lib/bundler/man/bundle-install.1 +1 -1
  36. data/lib/bundler/man/bundle-issue.1 +1 -1
  37. data/lib/bundler/man/bundle-licenses.1 +1 -1
  38. data/lib/bundler/man/bundle-list.1 +1 -1
  39. data/lib/bundler/man/bundle-lock.1 +1 -1
  40. data/lib/bundler/man/bundle-open.1 +1 -1
  41. data/lib/bundler/man/bundle-outdated.1 +1 -1
  42. data/lib/bundler/man/bundle-platform.1 +1 -1
  43. data/lib/bundler/man/bundle-plugin.1 +1 -1
  44. data/lib/bundler/man/bundle-pristine.1 +1 -1
  45. data/lib/bundler/man/bundle-remove.1 +1 -1
  46. data/lib/bundler/man/bundle-show.1 +1 -1
  47. data/lib/bundler/man/bundle-update.1 +1 -1
  48. data/lib/bundler/man/bundle-version.1 +1 -1
  49. data/lib/bundler/man/bundle-viz.1 +1 -1
  50. data/lib/bundler/man/bundle.1 +1 -1
  51. data/lib/bundler/man/gemfile.5 +1 -1
  52. data/lib/bundler/plugin/api/source.rb +1 -1
  53. data/lib/bundler/plugin/index.rb +1 -1
  54. data/lib/bundler/plugin/installer/path.rb +8 -0
  55. data/lib/bundler/plugin.rb +1 -1
  56. data/lib/bundler/resolver/candidate.rb +12 -9
  57. data/lib/bundler/resolver/strategy.rb +40 -0
  58. data/lib/bundler/resolver.rb +11 -22
  59. data/lib/bundler/rubygems_ext.rb +15 -0
  60. data/lib/bundler/runtime.rb +8 -5
  61. data/lib/bundler/shared_helpers.rb +4 -0
  62. data/lib/bundler/source/gemspec.rb +1 -4
  63. data/lib/bundler/source/git/git_proxy.rb +14 -3
  64. data/lib/bundler/source/git.rb +5 -1
  65. data/lib/bundler/source/path.rb +2 -2
  66. data/lib/bundler/source/rubygems/remote.rb +11 -3
  67. data/lib/bundler/source_list.rb +29 -11
  68. data/lib/bundler/spec_set.rb +11 -4
  69. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +53 -3
  70. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  71. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +11 -0
  72. data/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +4 -24
  73. data/lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb +42 -0
  74. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +20 -8
  75. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +17 -29
  76. data/lib/bundler/vendor/uri/lib/uri/common.rb +7 -3
  77. data/lib/bundler/vendor/uri/lib/uri/generic.rb +12 -11
  78. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +6 -6
  79. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  80. data/lib/bundler/version.rb +1 -1
  81. metadata +5 -4
  82. data/lib/bundler/compact_index_client/gem_parser.rb +0 -32
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-FUND" "1" "January 2025" ""
3
+ .TH "BUNDLE\-FUND" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-fund\fR \- Lists information about gems seeking funding assistance
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-GEM" "1" "January 2025" ""
3
+ .TH "BUNDLE\-GEM" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-HELP" "1" "January 2025" ""
3
+ .TH "BUNDLE\-HELP" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-help\fR \- Displays detailed help for each subcommand
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-INFO" "1" "January 2025" ""
3
+ .TH "BUNDLE\-INFO" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-info\fR \- Show information for the given gem in your bundle
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-INIT" "1" "January 2025" ""
3
+ .TH "BUNDLE\-INIT" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-init\fR \- Generates a Gemfile into the current working directory
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-INJECT" "1" "January 2025" ""
3
+ .TH "BUNDLE\-INJECT" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-INSTALL" "1" "January 2025" ""
3
+ .TH "BUNDLE\-INSTALL" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-ISSUE" "1" "January 2025" ""
3
+ .TH "BUNDLE\-ISSUE" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-issue\fR \- Get help reporting Bundler issues
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-LICENSES" "1" "January 2025" ""
3
+ .TH "BUNDLE\-LICENSES" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-licenses\fR \- Print the license of all gems in the bundle
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-LIST" "1" "January 2025" ""
3
+ .TH "BUNDLE\-LIST" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-list\fR \- List all the gems in the bundle
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-LOCK" "1" "January 2025" ""
3
+ .TH "BUNDLE\-LOCK" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-OPEN" "1" "January 2025" ""
3
+ .TH "BUNDLE\-OPEN" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-OUTDATED" "1" "January 2025" ""
3
+ .TH "BUNDLE\-OUTDATED" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-outdated\fR \- List installed gems with newer versions available
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-PLATFORM" "1" "January 2025" ""
3
+ .TH "BUNDLE\-PLATFORM" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-platform\fR \- Displays platform compatibility information
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-PLUGIN" "1" "January 2025" ""
3
+ .TH "BUNDLE\-PLUGIN" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-plugin\fR \- Manage Bundler plugins
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-PRISTINE" "1" "January 2025" ""
3
+ .TH "BUNDLE\-PRISTINE" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-REMOVE" "1" "January 2025" ""
3
+ .TH "BUNDLE\-REMOVE" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-remove\fR \- Removes gems from the Gemfile
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-SHOW" "1" "January 2025" ""
3
+ .TH "BUNDLE\-SHOW" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-UPDATE" "1" "January 2025" ""
3
+ .TH "BUNDLE\-UPDATE" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-update\fR \- Update your gems to the latest available versions
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-VERSION" "1" "January 2025" ""
3
+ .TH "BUNDLE\-VERSION" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-version\fR \- Prints Bundler version information
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE\-VIZ" "1" "January 2025" ""
3
+ .TH "BUNDLE\-VIZ" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "BUNDLE" "1" "January 2025" ""
3
+ .TH "BUNDLE" "1" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBbundle\fR \- Ruby Dependency Management
6
6
  .SH "SYNOPSIS"
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "GEMFILE" "5" "January 2025" ""
3
+ .TH "GEMFILE" "5" "March 2025" ""
4
4
  .SH "NAME"
5
5
  \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
6
6
  .SH "SYNOPSIS"
@@ -67,7 +67,7 @@ module Bundler
67
67
  # to check out same version of gem later.
68
68
  #
69
69
  # There options are passed when the source plugin is created from the
70
- # lock file.
70
+ # lockfile.
71
71
  #
72
72
  # @return [Hash]
73
73
  def options_to_lock
@@ -31,7 +31,7 @@ module Bundler
31
31
 
32
32
  begin
33
33
  load_index(global_index_file, true)
34
- rescue GenericSystemCallError
34
+ rescue PermissionError
35
35
  # no need to fail when on a read-only FS, for example
36
36
  nil
37
37
  rescue ArgumentError => e
@@ -8,6 +8,14 @@ module Bundler
8
8
  SharedHelpers.in_bundle? ? Bundler.root : Plugin.root
9
9
  end
10
10
 
11
+ def eql?(other)
12
+ return unless other.class == self.class
13
+ expanded_original_path == other.expanded_original_path &&
14
+ version == other.version
15
+ end
16
+
17
+ alias_method :==, :eql?
18
+
11
19
  def generate_bin(spec, disable_extensions = false)
12
20
  # Need to find a way without code duplication
13
21
  # For now, we can ignore this
@@ -195,7 +195,7 @@ module Bundler
195
195
  @sources[name]
196
196
  end
197
197
 
198
- # @param [Hash] The options that are present in the lock file
198
+ # @param [Hash] The options that are present in the lockfile
199
199
  # @return [API::Source] the instance of the class that handles the source
200
200
  # type passed in locked_opts
201
201
  def from_lock(locked_opts)
@@ -17,7 +17,7 @@ module Bundler
17
17
  # Some candidates may also keep some information explicitly about the
18
18
  # package they refer to. These candidates are referred to as "canonical" and
19
19
  # are used when materializing resolution results back into RubyGems
20
- # specifications that can be installed, written to lock files, and so on.
20
+ # specifications that can be installed, written to lockfiles, and so on.
21
21
  #
22
22
  class Candidate
23
23
  include Comparable
@@ -48,35 +48,38 @@ module Bundler
48
48
  @version.segments
49
49
  end
50
50
 
51
- def sort_obj
52
- [@version, @priority]
53
- end
54
-
55
51
  def <=>(other)
56
52
  return unless other.is_a?(self.class)
57
53
 
58
- sort_obj <=> other.sort_obj
54
+ version_comparison = version <=> other.version
55
+ return version_comparison unless version_comparison.zero?
56
+
57
+ priority <=> other.priority
59
58
  end
60
59
 
61
60
  def ==(other)
62
61
  return unless other.is_a?(self.class)
63
62
 
64
- sort_obj == other.sort_obj
63
+ version == other.version && priority == other.priority
65
64
  end
66
65
 
67
66
  def eql?(other)
68
67
  return unless other.is_a?(self.class)
69
68
 
70
- sort_obj.eql?(other.sort_obj)
69
+ version.eql?(other.version) && priority.eql?(other.priority)
71
70
  end
72
71
 
73
72
  def hash
74
- sort_obj.hash
73
+ [@version, @priority].hash
75
74
  end
76
75
 
77
76
  def to_s
78
77
  @version.to_s
79
78
  end
79
+
80
+ protected
81
+
82
+ attr_reader :priority
80
83
  end
81
84
  end
82
85
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class Resolver
5
+ class Strategy
6
+ def initialize(source)
7
+ @source = source
8
+ end
9
+
10
+ def next_package_and_version(unsatisfied)
11
+ package, range = next_term_to_try_from(unsatisfied)
12
+
13
+ [package, most_preferred_version_of(package, range).first]
14
+ end
15
+
16
+ private
17
+
18
+ def next_term_to_try_from(unsatisfied)
19
+ unsatisfied.min_by do |package, range|
20
+ matching_versions = @source.versions_for(package, range)
21
+ higher_versions = @source.versions_for(package, range.upper_invert)
22
+
23
+ [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
24
+ end
25
+ end
26
+
27
+ def most_preferred_version_of(package, range)
28
+ versions = @source.versions_for(package, range)
29
+
30
+ # Conditional avoids (among other things) calling
31
+ # sort_versions_by_preferred with the root package
32
+ if versions.size > 1
33
+ @source.sort_versions_by_preferred(package, versions)
34
+ else
35
+ versions
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -12,6 +12,7 @@ module Bundler
12
12
  require_relative "resolver/candidate"
13
13
  require_relative "resolver/incompatibility"
14
14
  require_relative "resolver/root"
15
+ require_relative "resolver/strategy"
15
16
 
16
17
  include GemHelpers
17
18
 
@@ -78,7 +79,7 @@ module Bundler
78
79
  end
79
80
 
80
81
  def solve_versions(root:, logger:)
81
- solver = PubGrub::VersionSolver.new(source: self, root: root, logger: logger)
82
+ solver = PubGrub::VersionSolver.new(source: self, root: root, strategy: Strategy.new(self), logger: logger)
82
83
  result = solver.solve
83
84
  resolved_specs = result.flat_map {|package, version| version.to_specs(package, @most_specific_locked_platform) }
84
85
  SpecSet.new(resolved_specs).specs_with_additional_variants_from(@base.locked_specs)
@@ -167,15 +168,7 @@ module Bundler
167
168
  end
168
169
 
169
170
  def versions_for(package, range=VersionRange.any)
170
- versions = select_sorted_versions(package, range)
171
-
172
- # Conditional avoids (among other things) calling
173
- # sort_versions_by_preferred with the root package
174
- if versions.size > 1
175
- sort_versions_by_preferred(package, versions)
176
- else
177
- versions
178
- end
171
+ range.select_versions(@sorted_versions[package])
179
172
  end
180
173
 
181
174
  def no_versions_incompatibility_for(package, unsatisfied_term)
@@ -284,8 +277,8 @@ module Bundler
284
277
  ruby_group = Resolver::SpecGroup.new(ruby_specs)
285
278
 
286
279
  unless ruby_group.empty?
287
- platform_specs.each do |specs|
288
- ruby_group.merge(Resolver::SpecGroup.new(specs))
280
+ platform_specs.each do |s|
281
+ ruby_group.merge(Resolver::SpecGroup.new(s))
289
282
  end
290
283
 
291
284
  groups << Resolver::Candidate.new(version, group: ruby_group, priority: -1)
@@ -355,6 +348,10 @@ module Bundler
355
348
  raise GemNotFound, message
356
349
  end
357
350
 
351
+ def sort_versions_by_preferred(package, versions)
352
+ @gem_version_promoter.sort_versions(package, versions)
353
+ end
354
+
358
355
  private
359
356
 
360
357
  def filtered_versions_for(package)
@@ -414,10 +411,6 @@ module Bundler
414
411
  requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
415
412
  end
416
413
 
417
- def sort_versions_by_preferred(package, versions)
418
- @gem_version_promoter.sort_versions(package, versions)
419
- end
420
-
421
414
  def repository_for(package)
422
415
  source_for(package.name)
423
416
  end
@@ -433,7 +426,7 @@ module Bundler
433
426
  next [dep_package, dep_constraint] if name == "bundler"
434
427
 
435
428
  dep_range = dep_constraint.range
436
- versions = select_sorted_versions(dep_package, dep_range)
429
+ versions = versions_for(dep_package, dep_range)
437
430
  if versions.empty?
438
431
  if dep_package.ignores_prereleases? || dep_package.prefer_local?
439
432
  @all_versions.delete(dep_package)
@@ -441,7 +434,7 @@ module Bundler
441
434
  end
442
435
  dep_package.consider_prereleases! if dep_package.ignores_prereleases?
443
436
  dep_package.consider_remote_versions! if dep_package.prefer_local?
444
- versions = select_sorted_versions(dep_package, dep_range)
437
+ versions = versions_for(dep_package, dep_range)
445
438
  end
446
439
 
447
440
  if versions.empty? && select_all_versions(dep_package, dep_range).any?
@@ -456,10 +449,6 @@ module Bundler
456
449
  end.to_h
457
450
  end
458
451
 
459
- def select_sorted_versions(package, range)
460
- range.select_versions(@sorted_versions[package])
461
- end
462
-
463
452
  def select_all_versions(package, range)
464
453
  range.select_versions(@all_versions[package])
465
454
  end
@@ -262,6 +262,10 @@ module Gem
262
262
  !default_gem? && !File.directory?(full_gem_path)
263
263
  end
264
264
 
265
+ def lock_name
266
+ @lock_name ||= name_tuple.lock_name
267
+ end
268
+
265
269
  unless VALIDATES_FOR_RESOLUTION
266
270
  def validate_for_resolution
267
271
  SpecificationPolicy.new(self).validate_for_resolution
@@ -443,6 +447,17 @@ module Gem
443
447
  end
444
448
  end
445
449
 
450
+ unless Gem.rubygems_version >= Gem::Version.new("3.6.7")
451
+ module UnfreezeCompactIndexParsedResponse
452
+ def parse(line)
453
+ version, platform, dependencies, requirements = super
454
+ [version, platform, dependencies.frozen? ? dependencies.dup : dependencies, requirements.frozen? ? requirements.dup : requirements]
455
+ end
456
+ end
457
+
458
+ Resolver::APISet::GemParser.prepend(UnfreezeCompactIndexParsedResponse)
459
+ end
460
+
446
461
  if Gem.rubygems_version < Gem::Version.new("3.6.0")
447
462
  class Package; end
448
463
  require "rubygems/package/tar_reader"
@@ -130,11 +130,14 @@ module Bundler
130
130
 
131
131
  specs_to_cache.each do |spec|
132
132
  next if spec.name == "bundler"
133
- next if spec.source.is_a?(Source::Gemspec)
134
- if spec.source.respond_to?(:migrate_cache)
135
- spec.source.migrate_cache(custom_path, local: local)
136
- elsif spec.source.respond_to?(:cache)
137
- spec.source.cache(spec, custom_path)
133
+
134
+ source = spec.source
135
+ next if source.is_a?(Source::Gemspec)
136
+
137
+ if source.respond_to?(:migrate_cache)
138
+ source.migrate_cache(custom_path, local: local)
139
+ elsif source.respond_to?(:cache)
140
+ source.cache(spec, custom_path)
138
141
  end
139
142
  end
140
143
 
@@ -115,6 +115,10 @@ module Bundler
115
115
  raise NoSpaceOnDeviceError.new(path, action)
116
116
  rescue Errno::ENOTSUP
117
117
  raise OperationNotSupportedError.new(path, action)
118
+ rescue Errno::EPERM
119
+ raise OperationNotPermittedError.new(path, action)
120
+ rescue Errno::EROFS
121
+ raise ReadOnlyFileSystemError.new(path, action)
118
122
  rescue Errno::EEXIST, Errno::ENOENT
119
123
  raise
120
124
  rescue SystemCallError => e
@@ -4,15 +4,12 @@ module Bundler
4
4
  class Source
5
5
  class Gemspec < Path
6
6
  attr_reader :gemspec
7
+ attr_writer :checksum_store
7
8
 
8
9
  def initialize(options)
9
10
  super
10
11
  @gemspec = options["gemspec"]
11
12
  end
12
-
13
- def as_path_source
14
- Path.new(options)
15
- end
16
13
  end
17
14
  end
18
15
  end
@@ -147,6 +147,12 @@ module Bundler
147
147
  end
148
148
  end
149
149
 
150
+ def installed_to?(destination)
151
+ # if copy_to is interrupted, it may leave a partially installed directory that
152
+ # contains .git but no other files -- consider this not to be installed
153
+ Dir.exist?(destination) && (Dir.children(destination) - [".git"]).any?
154
+ end
155
+
150
156
  private
151
157
 
152
158
  def git_remote_fetch(args)
@@ -179,7 +185,8 @@ module Bundler
179
185
  _, err, status = capture(command, nil)
180
186
  return extra_ref if status.success?
181
187
 
182
- if err.include?("Could not find remote branch")
188
+ if err.include?("Could not find remote branch") || # git up to 2.49
189
+ err.include?("Remote branch #{branch_option} not found") # git 2.49 or higher
183
190
  raise MissingGitRevisionError.new(command_with_no_credentials, nil, explicit_ref, credential_filtered_uri)
184
191
  else
185
192
  idx = command.index("--depth")
@@ -256,7 +263,7 @@ module Bundler
256
263
  end
257
264
 
258
265
  def not_pinned?
259
- branch || tag || ref.nil?
266
+ branch_option || ref.nil?
260
267
  end
261
268
 
262
269
  def pinned_to_full_sha?
@@ -420,7 +427,7 @@ module Bundler
420
427
  # anyways.
421
428
  return args if @revision
422
429
 
423
- args += ["--branch", branch || tag] if branch || tag
430
+ args += ["--branch", branch_option] if branch_option
424
431
  args
425
432
  end
426
433
 
@@ -436,6 +443,10 @@ module Bundler
436
443
  extra_args
437
444
  end
438
445
 
446
+ def branch_option
447
+ branch || tag
448
+ end
449
+
439
450
  def full_clone?
440
451
  depth.nil?
441
452
  end
@@ -360,7 +360,11 @@ module Bundler
360
360
  end
361
361
 
362
362
  def locked_revision_checked_out?
363
- locked_revision && locked_revision == revision && install_path.exist?
363
+ locked_revision && locked_revision == revision && installed?
364
+ end
365
+
366
+ def installed?
367
+ git_proxy.installed_to?(install_path)
364
368
  end
365
369
 
366
370
  def base_name
@@ -60,8 +60,8 @@ module Bundler
60
60
  end
61
61
 
62
62
  def eql?(other)
63
- return unless other.class == self.class
64
- expanded_original_path == other.expanded_original_path &&
63
+ [Gemspec, Path].include?(other.class) &&
64
+ expanded_original_path == other.expanded_original_path &&
65
65
  version == other.version
66
66
  end
67
67
 
@@ -16,6 +16,9 @@ module Bundler
16
16
  @anonymized_uri = remove_auth(@uri).freeze
17
17
  end
18
18
 
19
+ MAX_CACHE_SLUG_HOST_SIZE = 255 - 1 - 32 # 255 minus dot minus MD5 length
20
+ private_constant :MAX_CACHE_SLUG_HOST_SIZE
21
+
19
22
  # @return [String] A slug suitable for use as a cache key for this
20
23
  # remote.
21
24
  #
@@ -28,10 +31,15 @@ module Bundler
28
31
  host = cache_uri.to_s.start_with?("file://") ? nil : cache_uri.host
29
32
 
30
33
  uri_parts = [host, cache_uri.user, cache_uri.port, cache_uri.path]
31
- uri_digest = SharedHelpers.digest(:MD5).hexdigest(uri_parts.compact.join("."))
34
+ uri_parts.compact!
35
+ uri_digest = SharedHelpers.digest(:MD5).hexdigest(uri_parts.join("."))
36
+
37
+ uri_parts.pop
38
+ host_parts = uri_parts.join(".")
39
+ return uri_digest if host_parts.empty?
32
40
 
33
- uri_parts[-1] = uri_digest
34
- uri_parts.compact.join(".")
41
+ shortened_host_parts = host_parts[0...MAX_CACHE_SLUG_HOST_SIZE]
42
+ [shortened_host_parts, uri_digest].join(".")
35
43
  end
36
44
  end
37
45