rubygems-update 3.5.11 → 3.5.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/Manifest.txt +1 -0
  4. data/bundler/CHANGELOG.md +20 -0
  5. data/bundler/lib/bundler/build_metadata.rb +2 -2
  6. data/bundler/lib/bundler/cli.rb +5 -8
  7. data/bundler/lib/bundler/compact_index_client/cache.rb +47 -81
  8. data/bundler/lib/bundler/compact_index_client/parser.rb +84 -0
  9. data/bundler/lib/bundler/compact_index_client.rb +51 -80
  10. data/bundler/lib/bundler/definition.rb +6 -3
  11. data/bundler/lib/bundler/fetcher/compact_index.rb +15 -24
  12. data/bundler/lib/bundler/installer/gem_installer.rb +0 -1
  13. data/bundler/lib/bundler/man/bundle-config.1 +1 -1
  14. data/bundler/lib/bundler/man/bundle-config.1.ronn +1 -1
  15. data/bundler/lib/bundler/rubygems_integration.rb +14 -0
  16. data/bundler/lib/bundler/self_manager.rb +5 -0
  17. data/bundler/lib/bundler/settings.rb +12 -8
  18. data/bundler/lib/bundler/setup.rb +3 -0
  19. data/bundler/lib/bundler/shared_helpers.rb +2 -2
  20. data/bundler/lib/bundler/source/git.rb +14 -0
  21. data/bundler/lib/bundler/source/path.rb +0 -13
  22. data/bundler/lib/bundler/source/rubygems.rb +29 -13
  23. data/bundler/lib/bundler/version.rb +1 -1
  24. data/bundler/lib/bundler/yaml_serializer.rb +1 -8
  25. data/bundler/lib/bundler.rb +6 -1
  26. data/lib/rubygems/basic_specification.rb +27 -0
  27. data/lib/rubygems/commands/pristine_command.rb +3 -3
  28. data/lib/rubygems/specification.rb +11 -2
  29. data/lib/rubygems/specification_record.rb +0 -1
  30. data/lib/rubygems/stub_specification.rb +21 -0
  31. data/lib/rubygems/uninstaller.rb +12 -11
  32. data/lib/rubygems/yaml_serializer.rb +1 -8
  33. data/lib/rubygems.rb +1 -1
  34. data/rubygems-update.gemspec +1 -1
  35. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd4f648b70b6865239d7b78c7773946b5be7fa737c540ffcc33e1266e1ef3f88
4
- data.tar.gz: 4c94ce1d451e13399cf9c29154707d75b5bde5dfe2a663864dff4587bf724017
3
+ metadata.gz: c35be5895f916b09303ca0a72f0cc908f52df658c8860de916b73d4e0637fb1d
4
+ data.tar.gz: 5ca038be72e7dd475544a0fe4baa5998dc4ec4fc40169c86bbceaf3004a28993
5
5
  SHA512:
6
- metadata.gz: 4ea473f16af7b832d500c6b5692039281f77f5f581fe1f114d7f183443bfb4149a415fc5f021d8255662d5712a369d0a52d943367962ea14b301b7f12ef859f5
7
- data.tar.gz: 492b437441e43a45505cb6223c7e317341eee786436cc44bd619dd00f765c07867bcd8b11824eef968360e6798aa9c83013e543a69466c48b81cb51f0a831979
6
+ metadata.gz: '018263fd318b8ff0f135774f71daac0b005472254e524cf93fc9616650ddba36f397a0c0f94ed2c278e276ab8ec6cc5a6323af2375d0a1a220e066d863904142'
7
+ data.tar.gz: f9713050e6ab501c1777a44c1409c5aa45cb17bdf5795f61113d27bbad2abf502a604a1d6d4930ff59c548349920a61ea7d4bae1a99eeef8e41842b6a9a3af1a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ # 3.5.12 / 2024-06-13
2
+
3
+ ## Enhancements:
4
+
5
+ * Installs bundler 2.5.12 as a default gem.
6
+
7
+ ## Bug fixes:
8
+
9
+ * Fix `gem uninstall` unresolved specifications warning. Pull request
10
+ [#7667](https://github.com/rubygems/rubygems/pull/7667) by
11
+ deivid-rodriguez
12
+ * Fix `gem pristine` sometimes failing to pristine user installed gems.
13
+ Pull request [#7664](https://github.com/rubygems/rubygems/pull/7664) by
14
+ deivid-rodriguez
15
+
1
16
  # 3.5.11 / 2024-05-28
2
17
 
3
18
  ## Enhancements:
data/Manifest.txt CHANGED
@@ -54,6 +54,7 @@ bundler/lib/bundler/compact_index_client.rb
54
54
  bundler/lib/bundler/compact_index_client/cache.rb
55
55
  bundler/lib/bundler/compact_index_client/cache_file.rb
56
56
  bundler/lib/bundler/compact_index_client/gem_parser.rb
57
+ bundler/lib/bundler/compact_index_client/parser.rb
57
58
  bundler/lib/bundler/compact_index_client/updater.rb
58
59
  bundler/lib/bundler/constants.rb
59
60
  bundler/lib/bundler/current_ruby.rb
data/bundler/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ # 2.5.12 (June 13, 2024)
2
+
3
+ ## Enhancements:
4
+
5
+ - Keep credentials in lockfile if they are already there [#7720](https://github.com/rubygems/rubygems/pull/7720)
6
+ - Auto switch to locked bundler version even when using binstubs [#7719](https://github.com/rubygems/rubygems/pull/7719)
7
+ - Don't validate local gemspecs twice unnecessarily [#7725](https://github.com/rubygems/rubygems/pull/7725)
8
+ - Improve default gem handling by treating default gems as any other gem [#7673](https://github.com/rubygems/rubygems/pull/7673)
9
+
10
+ ## Bug fixes:
11
+
12
+ - Fix slow and incorrect resolution when adding `sorbet` to a Gemfile and the lockfile only includes "RUBY" in the platforms section [#7731](https://github.com/rubygems/rubygems/pull/7731)
13
+ - Fix duplicated config keys generated when `fallback_timeout` uri option is used [#7704](https://github.com/rubygems/rubygems/pull/7704)
14
+ - Fix `bundle exec` no longer working in truffleruby after explicit `require` of `pathname` was removed [#7703](https://github.com/rubygems/rubygems/pull/7703)
15
+ - Don't let `bundle config` report a path without a Gemfile as "local app" [#7687](https://github.com/rubygems/rubygems/pull/7687)
16
+
17
+ ## Documentation:
18
+
19
+ - Clarify BUNDLE_USER_CONFIG is a file [#7668](https://github.com/rubygems/rubygems/pull/7668)
20
+
1
21
  # 2.5.11 (May 28, 2024)
2
22
 
3
23
  ## Deprecations:
@@ -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 = "2024-05-28".freeze
8
- @git_commit_sha = "4afb2d450a".freeze
7
+ @built_at = "2024-06-13".freeze
8
+ @git_commit_sha = "05dc7d98e5".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -65,7 +65,7 @@ module Bundler
65
65
  Bundler.reset_settings_and_root!
66
66
  end
67
67
 
68
- Bundler.self_manager.restart_with_locked_bundler_if_needed
68
+ Bundler.auto_switch
69
69
 
70
70
  Bundler.settings.set_command_option_if_given :retry, options[:retry]
71
71
 
@@ -767,13 +767,10 @@ module Bundler
767
767
 
768
768
  return unless SharedHelpers.md5_available?
769
769
 
770
- latest = Fetcher::CompactIndex.
771
- new(nil, Source::Rubygems::Remote.new(Gem::URI("https://rubygems.org")), nil, nil).
772
- send(:compact_index_client).
773
- instance_variable_get(:@cache).
774
- dependencies("bundler").
775
- map {|d| Gem::Version.new(d.first) }.
776
- max
770
+ require_relative "vendored_uri"
771
+ remote = Source::Rubygems::Remote.new(Gem::URI("https://rubygems.org"))
772
+ cache_path = Bundler.user_cache.join("compact_index", remote.cache_slug)
773
+ latest = Bundler::CompactIndexClient.new(cache_path).latest_version("bundler")
777
774
  return unless latest
778
775
 
779
776
  current = Gem::Version.new(VERSION)
@@ -7,123 +7,89 @@ module Bundler
7
7
  class Cache
8
8
  attr_reader :directory
9
9
 
10
- def initialize(directory)
10
+ def initialize(directory, fetcher = nil)
11
11
  @directory = Pathname.new(directory).expand_path
12
- info_roots.each {|dir| mkdir(dir) }
13
- mkdir(info_etag_root)
12
+ @updater = Updater.new(fetcher) if fetcher
13
+ @mutex = Thread::Mutex.new
14
+ @endpoints = Set.new
15
+
16
+ @info_root = mkdir("info")
17
+ @special_characters_info_root = mkdir("info-special-characters")
18
+ @info_etag_root = mkdir("info-etags")
14
19
  end
15
20
 
16
21
  def names
17
- lines(names_path)
22
+ fetch("names", names_path, names_etag_path)
18
23
  end
19
24
 
20
- def names_path
21
- directory.join("names")
25
+ def versions
26
+ fetch("versions", versions_path, versions_etag_path)
22
27
  end
23
28
 
24
- def names_etag_path
25
- directory.join("names.etag")
26
- end
29
+ def info(name, remote_checksum = nil)
30
+ path = info_path(name)
27
31
 
28
- def versions
29
- versions_by_name = Hash.new {|hash, key| hash[key] = [] }
30
- info_checksums_by_name = {}
31
-
32
- lines(versions_path).each do |line|
33
- name, versions_string, info_checksum = line.split(" ", 3)
34
- info_checksums_by_name[name] = info_checksum || ""
35
- versions_string.split(",") do |version|
36
- delete = version.delete_prefix!("-")
37
- version = version.split("-", 2).unshift(name)
38
- if delete
39
- versions_by_name[name].delete(version)
40
- else
41
- versions_by_name[name] << version
42
- end
43
- end
32
+ if remote_checksum && remote_checksum != SharedHelpers.checksum_for_file(path, :MD5)
33
+ fetch("info/#{name}", path, info_etag_path(name))
34
+ else
35
+ Bundler::CompactIndexClient.debug { "update skipped info/#{name} (#{remote_checksum ? "versions index checksum is nil" : "versions index checksum matches local"})" }
36
+ read(path)
44
37
  end
45
-
46
- [versions_by_name, info_checksums_by_name]
47
- end
48
-
49
- def versions_path
50
- directory.join("versions")
51
38
  end
52
39
 
53
- def versions_etag_path
54
- directory.join("versions.etag")
40
+ def reset!
41
+ @mutex.synchronize { @endpoints.clear }
55
42
  end
56
43
 
57
- def checksums
58
- lines(versions_path).each_with_object({}) do |line, checksums|
59
- parse_version_checksum(line, checksums)
60
- end
61
- end
44
+ private
62
45
 
63
- def dependencies(name)
64
- lines(info_path(name)).map do |line|
65
- parse_gem(line)
66
- end
67
- end
46
+ def names_path = directory.join("names")
47
+ def names_etag_path = directory.join("names.etag")
48
+ def versions_path = directory.join("versions")
49
+ def versions_etag_path = directory.join("versions.etag")
68
50
 
69
51
  def info_path(name)
70
52
  name = name.to_s
53
+ # TODO: converge this into the info_root by hashing all filenames like info_etag_path
71
54
  if /[^a-z0-9_-]/.match?(name)
72
55
  name += "-#{SharedHelpers.digest(:MD5).hexdigest(name).downcase}"
73
- info_roots.last.join(name)
56
+ @special_characters_info_root.join(name)
74
57
  else
75
- info_roots.first.join(name)
58
+ @info_root.join(name)
76
59
  end
77
60
  end
78
61
 
79
62
  def info_etag_path(name)
80
63
  name = name.to_s
81
- info_etag_root.join("#{name}-#{SharedHelpers.digest(:MD5).hexdigest(name).downcase}")
64
+ @info_etag_root.join("#{name}-#{SharedHelpers.digest(:MD5).hexdigest(name).downcase}")
82
65
  end
83
66
 
84
- private
85
-
86
- def mkdir(dir)
87
- SharedHelpers.filesystem_access(dir) do
88
- FileUtils.mkdir_p(dir)
67
+ def mkdir(name)
68
+ directory.join(name).tap do |dir|
69
+ SharedHelpers.filesystem_access(dir) do
70
+ FileUtils.mkdir_p(dir)
71
+ end
89
72
  end
90
73
  end
91
74
 
92
- def lines(path)
93
- return [] unless path.file?
94
- lines = SharedHelpers.filesystem_access(path, :read, &:read).split("\n")
95
- header = lines.index("---")
96
- header ? lines[header + 1..-1] : lines
97
- end
98
-
99
- def parse_gem(line)
100
- @dependency_parser ||= GemParser.new
101
- @dependency_parser.parse(line)
102
- end
75
+ def fetch(remote_path, path, etag_path)
76
+ if already_fetched?(remote_path)
77
+ Bundler::CompactIndexClient.debug { "already fetched #{remote_path}" }
78
+ else
79
+ Bundler::CompactIndexClient.debug { "fetching #{remote_path}" }
80
+ @updater&.update(remote_path, path, etag_path)
81
+ end
103
82
 
104
- # This is mostly the same as `split(" ", 3)` but it avoids allocating extra objects.
105
- # This method gets called at least once for every gem when parsing versions.
106
- def parse_version_checksum(line, checksums)
107
- line.freeze # allows slicing into the string to not allocate a copy of the line
108
- name_end = line.index(" ")
109
- checksum_start = line.index(" ", name_end + 1) + 1
110
- checksum_end = line.size - checksum_start
111
- # freeze name since it is used as a hash key
112
- # pre-freezing means a frozen copy isn't created
113
- name = line[0, name_end].freeze
114
- checksum = line[checksum_start, checksum_end]
115
- checksums[name] = checksum
83
+ read(path)
116
84
  end
117
85
 
118
- def info_roots
119
- [
120
- directory.join("info"),
121
- directory.join("info-special-characters"),
122
- ]
86
+ def already_fetched?(remote_path)
87
+ @mutex.synchronize { !@endpoints.add?(remote_path) }
123
88
  end
124
89
 
125
- def info_etag_root
126
- directory.join("info-etags")
90
+ def read(path)
91
+ return unless path.file?
92
+ SharedHelpers.filesystem_access(path, :read, &:read)
127
93
  end
128
94
  end
129
95
  end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class CompactIndexClient
5
+ class Parser
6
+ # `compact_index` - an object responding to #names, #versions, #info(name, checksum),
7
+ # returning the file contents as a string
8
+ def initialize(compact_index)
9
+ @compact_index = compact_index
10
+ @info_checksums = nil
11
+ @versions_by_name = nil
12
+ @available = nil
13
+ @gem_parser = nil
14
+ end
15
+
16
+ def names
17
+ lines(@compact_index.names)
18
+ end
19
+
20
+ def versions
21
+ @versions_by_name ||= Hash.new {|hash, key| hash[key] = [] }
22
+ @info_checksums = {}
23
+
24
+ lines(@compact_index.versions).each do |line|
25
+ name, versions_string, checksum = line.split(" ", 3)
26
+ @info_checksums[name] = checksum || ""
27
+ versions_string.split(",") do |version|
28
+ delete = version.delete_prefix!("-")
29
+ version = version.split("-", 2).unshift(name)
30
+ if delete
31
+ @versions_by_name[name].delete(version)
32
+ else
33
+ @versions_by_name[name] << version
34
+ end
35
+ end
36
+ end
37
+
38
+ @versions_by_name
39
+ end
40
+
41
+ def info(name)
42
+ data = @compact_index.info(name, info_checksums[name])
43
+ lines(data).map {|line| gem_parser.parse(line).unshift(name) }
44
+ end
45
+
46
+ def available?
47
+ return @available unless @available.nil?
48
+ @available = !info_checksums.empty?
49
+ end
50
+
51
+ private
52
+
53
+ def info_checksums
54
+ @info_checksums ||= lines(@compact_index.versions).each_with_object({}) do |line, checksums|
55
+ parse_version_checksum(line, checksums)
56
+ end
57
+ end
58
+
59
+ def lines(data)
60
+ return [] if data.nil? || data.empty?
61
+ lines = data.split("\n")
62
+ header = lines.index("---")
63
+ header ? lines[header + 1..-1] : lines
64
+ end
65
+
66
+ def gem_parser
67
+ @gem_parser ||= GemParser.new
68
+ end
69
+
70
+ # This is mostly the same as `split(" ", 3)` but it avoids allocating extra objects.
71
+ # This method gets called at least once for every gem when parsing versions.
72
+ def parse_version_checksum(line, checksums)
73
+ return unless (name_end = line.index(" ")) # Artifactory bug causes blank lines in artifactor index files
74
+ return unless (checksum_start = line.index(" ", name_end + 1) + 1)
75
+ checksum_end = line.size - checksum_start
76
+
77
+ line.freeze # allows slicing into the string to not allocate a copy of the line
78
+ name = line[0, name_end]
79
+ checksum = line[checksum_start, checksum_end]
80
+ checksums[name.freeze] = checksum # freeze name since it is used as a hash key
81
+ end
82
+ end
83
+ end
84
+ end
@@ -4,6 +4,29 @@ require "pathname"
4
4
  require "set"
5
5
 
6
6
  module Bundler
7
+ # The CompactIndexClient is responsible for fetching and parsing the compact index.
8
+ #
9
+ # The compact index is a set of caching optimized files that are used to fetch gem information.
10
+ # The files are:
11
+ # - names: a list of all gem names
12
+ # - versions: a list of all gem versions
13
+ # - info/[gem]: a list of all versions of a gem
14
+ #
15
+ # The client is instantiated with:
16
+ # - `directory`: the root directory where the cache files are stored.
17
+ # - `fetcher`: (optional) an object that responds to #call(uri_path, headers) and returns an http response.
18
+ # If the `fetcher` is not provided, the client will only read cached files from disk.
19
+ #
20
+ # The client is organized into:
21
+ # - `Updater`: updates the cached files on disk using the fetcher.
22
+ # - `Cache`: calls the updater, caches files, read and return them from disk
23
+ # - `Parser`: parses the compact index file data
24
+ # - `CacheFile`: a concurrency safe file reader/writer that verifies checksums
25
+ #
26
+ # The client is intended to optimize memory usage and performance.
27
+ # It is called 100s or 1000s of times, parsing files with hundreds of thousands of lines.
28
+ # It may be called concurrently without global interpreter lock in some Rubies.
29
+ # As a result, some methods may look more complex than necessary to save memory or time.
7
30
  class CompactIndexClient
8
31
  # NOTE: MD5 is here not because we expect a server to respond with it, but
9
32
  # because we use it to generate the etag on first request during the upgrade
@@ -12,6 +35,13 @@ module Bundler
12
35
  SUPPORTED_DIGESTS = { "sha-256" => :SHA256, "md5" => :MD5 }.freeze
13
36
  DEBUG_MUTEX = Thread::Mutex.new
14
37
 
38
+ # info returns an Array of INFO Arrays. Each INFO Array has the following indices:
39
+ INFO_NAME = 0
40
+ INFO_VERSION = 1
41
+ INFO_PLATFORM = 2
42
+ INFO_DEPS = 3
43
+ INFO_REQS = 4
44
+
15
45
  def self.debug
16
46
  return unless ENV["DEBUG_COMPACT_INDEX"]
17
47
  DEBUG_MUTEX.synchronize { warn("[#{self}] #{yield}") }
@@ -21,106 +51,47 @@ module Bundler
21
51
 
22
52
  require_relative "compact_index_client/cache"
23
53
  require_relative "compact_index_client/cache_file"
54
+ require_relative "compact_index_client/parser"
24
55
  require_relative "compact_index_client/updater"
25
56
 
26
- attr_reader :directory
27
-
28
- def initialize(directory, fetcher)
29
- @directory = Pathname.new(directory)
30
- @updater = Updater.new(fetcher)
31
- @cache = Cache.new(@directory)
32
- @endpoints = Set.new
33
- @info_checksums_by_name = {}
34
- @parsed_checksums = false
35
- @mutex = Thread::Mutex.new
36
- end
37
-
38
- def execution_mode=(block)
39
- Bundler::CompactIndexClient.debug { "execution_mode=" }
40
- @endpoints = Set.new
41
-
42
- @execution_mode = block
43
- end
44
-
45
- # @return [Lambda] A lambda that takes an array of inputs and a block, and
46
- # maps the inputs with the block in parallel.
47
- #
48
- def execution_mode
49
- @execution_mode || sequentially
50
- end
51
-
52
- def sequential_execution_mode!
53
- self.execution_mode = sequentially
54
- end
55
-
56
- def sequentially
57
- @sequentially ||= lambda do |inputs, &blk|
58
- inputs.map(&blk)
59
- end
57
+ def initialize(directory, fetcher = nil)
58
+ @cache = Cache.new(directory, fetcher)
59
+ @parser = Parser.new(@cache)
60
60
  end
61
61
 
62
62
  def names
63
- Bundler::CompactIndexClient.debug { "/names" }
64
- update("names", @cache.names_path, @cache.names_etag_path)
65
- @cache.names
63
+ Bundler::CompactIndexClient.debug { "names" }
64
+ @parser.names
66
65
  end
67
66
 
68
67
  def versions
69
- Bundler::CompactIndexClient.debug { "/versions" }
70
- update("versions", @cache.versions_path, @cache.versions_etag_path)
71
- versions, @info_checksums_by_name = @cache.versions
72
- versions
68
+ Bundler::CompactIndexClient.debug { "versions" }
69
+ @parser.versions
73
70
  end
74
71
 
75
72
  def dependencies(names)
76
73
  Bundler::CompactIndexClient.debug { "dependencies(#{names})" }
77
- execution_mode.call(names) do |name|
78
- update_info(name)
79
- @cache.dependencies(name).map {|d| d.unshift(name) }
80
- end.flatten(1)
74
+ names.map {|name| info(name) }
81
75
  end
82
76
 
83
- def update_and_parse_checksums!
84
- Bundler::CompactIndexClient.debug { "update_and_parse_checksums!" }
85
- return @info_checksums_by_name if @parsed_checksums
86
- update("versions", @cache.versions_path, @cache.versions_etag_path)
87
- @info_checksums_by_name = @cache.checksums
88
- @parsed_checksums = true
89
- end
90
-
91
- private
92
-
93
- def update(remote_path, local_path, local_etag_path)
94
- Bundler::CompactIndexClient.debug { "update(#{local_path}, #{remote_path})" }
95
- unless synchronize { @endpoints.add?(remote_path) }
96
- Bundler::CompactIndexClient.debug { "already fetched #{remote_path}" }
97
- return
98
- end
99
- @updater.update(url(remote_path), local_path, local_etag_path)
77
+ def info(name)
78
+ Bundler::CompactIndexClient.debug { "info(#{name})" }
79
+ @parser.info(name)
100
80
  end
101
81
 
102
- def update_info(name)
103
- Bundler::CompactIndexClient.debug { "update_info(#{name})" }
104
- path = @cache.info_path(name)
105
- unless existing = @info_checksums_by_name[name]
106
- Bundler::CompactIndexClient.debug { "skipping updating info for #{name} since it is missing from versions" }
107
- return
108
- end
109
- checksum = SharedHelpers.checksum_for_file(path, :MD5)
110
- if checksum == existing
111
- Bundler::CompactIndexClient.debug { "skipping updating info for #{name} since the versions checksum matches the local checksum" }
112
- return
113
- end
114
- Bundler::CompactIndexClient.debug { "updating info for #{name} since the versions checksum #{existing} != the local checksum #{checksum}" }
115
- update("info/#{name}", path, @cache.info_etag_path(name))
82
+ def latest_version(name)
83
+ Bundler::CompactIndexClient.debug { "latest_version(#{name})" }
84
+ @parser.info(name).map {|d| Gem::Version.new(d[INFO_VERSION]) }.max
116
85
  end
117
86
 
118
- def url(path)
119
- path
87
+ def available?
88
+ Bundler::CompactIndexClient.debug { "available?" }
89
+ @parser.available?
120
90
  end
121
91
 
122
- def synchronize
123
- @mutex.synchronize { yield }
92
+ def reset!
93
+ Bundler::CompactIndexClient.debug { "reset!" }
94
+ @cache.reset!
124
95
  end
125
96
  end
126
97
  end
@@ -624,6 +624,11 @@ module Bundler
624
624
  result = SpecSet.new(resolver.start)
625
625
 
626
626
  @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
627
+
628
+ if @current_ruby_locked_platform && @current_ruby_locked_platform != local_platform
629
+ @platforms.delete(result.incomplete_for_platform?(dependencies, @current_ruby_locked_platform) ? @current_ruby_locked_platform : local_platform)
630
+ end
631
+
627
632
  @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
628
633
 
629
634
  result.complete_platforms!(platforms)
@@ -650,7 +655,6 @@ module Bundler
650
655
 
651
656
  def current_ruby_platform_locked?
652
657
  return false unless generic_local_platform_is_ruby?
653
- return false if Bundler.settings[:force_ruby_platform] && !@platforms.include?(Gem::Platform::RUBY)
654
658
 
655
659
  current_platform_locked?
656
660
  end
@@ -662,7 +666,7 @@ module Bundler
662
666
  end
663
667
 
664
668
  def add_current_platform
665
- return if current_ruby_platform_locked?
669
+ @current_ruby_locked_platform = most_specific_locked_platform if current_ruby_platform_locked?
666
670
 
667
671
  add_platform(local_platform)
668
672
  end
@@ -1050,7 +1054,6 @@ module Bundler
1050
1054
  !@originally_locked_specs.incomplete_for_platform?(dependencies, platform)
1051
1055
 
1052
1056
  remove_platform(platform)
1053
- add_current_platform if platform == Gem::Platform::RUBY
1054
1057
  end
1055
1058
  end
1056
1059
 
@@ -4,8 +4,6 @@ require_relative "base"
4
4
  require_relative "../worker"
5
5
 
6
6
  module Bundler
7
- autoload :CompactIndexClient, File.expand_path("../compact_index_client", __dir__)
8
-
9
7
  class Fetcher
10
8
  class CompactIndex < Base
11
9
  def self.compact_index_request(method_name)
@@ -36,15 +34,8 @@ module Bundler
36
34
 
37
35
  until remaining_gems.empty?
38
36
  log_specs { "Looking up gems #{remaining_gems.inspect}" }
39
-
40
- deps = begin
41
- parallel_compact_index_client.dependencies(remaining_gems)
42
- rescue TooManyRequestsError
43
- @bundle_worker&.stop
44
- @bundle_worker = nil # reset it. Not sure if necessary
45
- serial_compact_index_client.dependencies(remaining_gems)
46
- end
47
- next_gems = deps.flat_map {|d| d[3].flat_map(&:first) }.uniq
37
+ deps = fetch_gem_infos(remaining_gems).flatten(1)
38
+ next_gems = deps.flat_map {|d| d[CompactIndexClient::INFO_DEPS].flat_map(&:first) }.uniq
48
39
  deps.each {|dep| gem_info << dep }
49
40
  complete_gems.concat(deps.map(&:first)).uniq!
50
41
  remaining_gems = next_gems - complete_gems
@@ -61,7 +52,7 @@ module Bundler
61
52
  return nil
62
53
  end
63
54
  # Read info file checksums out of /versions, so we can know if gems are up to date
64
- compact_index_client.update_and_parse_checksums!
55
+ compact_index_client.available?
65
56
  rescue CompactIndexClient::Updater::MismatchedChecksumError => e
66
57
  Bundler.ui.debug(e.message)
67
58
  nil
@@ -81,20 +72,20 @@ module Bundler
81
72
  end
82
73
  end
83
74
 
84
- def parallel_compact_index_client
85
- compact_index_client.execution_mode = lambda do |inputs, &blk|
86
- func = lambda {|object, _index| blk.call(object) }
87
- worker = bundle_worker(func)
88
- inputs.each {|input| worker.enq(input) }
89
- inputs.map { worker.deq }
90
- end
91
-
92
- compact_index_client
75
+ def fetch_gem_infos(names)
76
+ in_parallel(names) {|name| compact_index_client.info(name) }
77
+ rescue TooManyRequestsError # rubygems.org is rate limiting us, slow down.
78
+ @bundle_worker&.stop
79
+ @bundle_worker = nil # reset it. Not sure if necessary
80
+ compact_index_client.reset!
81
+ names.map {|name| compact_index_client.info(name) }
93
82
  end
94
83
 
95
- def serial_compact_index_client
96
- compact_index_client.sequential_execution_mode!
97
- compact_index_client
84
+ def in_parallel(inputs, &blk)
85
+ func = lambda {|object, _index| blk.call(object) }
86
+ worker = bundle_worker(func)
87
+ inputs.each {|input| worker.enq(input) }
88
+ inputs.map { worker.deq }
98
89
  end
99
90
 
100
91
  def bundle_worker(func = nil)
@@ -54,7 +54,6 @@ module Bundler
54
54
  spec.source.install(
55
55
  spec,
56
56
  force: force,
57
- ensure_builtin_gems_cached: standalone,
58
57
  build_args: Array(spec_settings),
59
58
  previous_spec: previous_spec,
60
59
  )
@@ -307,7 +307,7 @@ Any \fB\.\fR characters in a host name are mapped to a double underscore (\fB__\
307
307
  .P
308
308
  This means that if you have a gem server named \fBmy\.gem\-host\.com\fR, you'll need to use the \fBBUNDLE_MY__GEM___HOST__COM\fR variable to configure credentials for it through ENV\.
309
309
  .SH "CONFIGURE BUNDLER DIRECTORIES"
310
- Bundler's home, config, cache and plugin directories are able to be configured through environment variables\. The default location for Bundler's home directory is \fB~/\.bundle\fR, which all directories inherit from by default\. The following outlines the available environment variables and their default values
310
+ Bundler's home, cache and plugin directories and config file can be configured through environment variables\. The default location for Bundler's home directory is \fB~/\.bundle\fR, which all directories inherit from by default\. The following outlines the available environment variables and their default values
311
311
  .IP "" 4
312
312
  .nf
313
313
  BUNDLE_USER_HOME : $HOME/\.bundle
@@ -397,7 +397,7 @@ through ENV.
397
397
 
398
398
  ## CONFIGURE BUNDLER DIRECTORIES
399
399
 
400
- Bundler's home, config, cache and plugin directories are able to be configured
400
+ Bundler's home, cache and plugin directories and config file can be configured
401
401
  through environment variables. The default location for Bundler's home directory is
402
402
  `~/.bundle`, which all directories inherit from by default. The following
403
403
  outlines the available environment variables and their default values