bundler 2.2.11 → 2.3.6

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 (174) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +414 -5
  3. data/README.md +1 -1
  4. data/bundler.gemspec +2 -3
  5. data/exe/bundle +7 -8
  6. data/lib/bundler/.document +1 -0
  7. data/lib/bundler/build_metadata.rb +2 -2
  8. data/lib/bundler/cli/cache.rb +1 -1
  9. data/lib/bundler/cli/check.rb +4 -2
  10. data/lib/bundler/cli/common.rb +15 -2
  11. data/lib/bundler/cli/doctor.rb +24 -5
  12. data/lib/bundler/cli/exec.rb +1 -6
  13. data/lib/bundler/cli/gem.rb +130 -26
  14. data/lib/bundler/cli/info.rb +16 -4
  15. data/lib/bundler/cli/install.rb +12 -27
  16. data/lib/bundler/cli/issue.rb +4 -3
  17. data/lib/bundler/cli/list.rb +7 -1
  18. data/lib/bundler/cli/lock.rb +5 -1
  19. data/lib/bundler/cli/open.rb +1 -2
  20. data/lib/bundler/cli/outdated.rb +10 -11
  21. data/lib/bundler/cli/platform.rb +1 -1
  22. data/lib/bundler/cli/remove.rb +1 -2
  23. data/lib/bundler/cli/update.rb +17 -8
  24. data/lib/bundler/cli.rb +41 -55
  25. data/lib/bundler/compact_index_client/cache.rb +0 -9
  26. data/lib/bundler/compact_index_client/updater.rb +10 -11
  27. data/lib/bundler/compact_index_client.rb +2 -8
  28. data/lib/bundler/current_ruby.rb +5 -4
  29. data/lib/bundler/definition.rb +147 -290
  30. data/lib/bundler/dependency.rb +5 -7
  31. data/lib/bundler/digest.rb +71 -0
  32. data/lib/bundler/dsl.rb +67 -66
  33. data/lib/bundler/endpoint_specification.rb +21 -11
  34. data/lib/bundler/env.rb +1 -1
  35. data/lib/bundler/environment_preserver.rb +4 -1
  36. data/lib/bundler/errors.rb +19 -3
  37. data/lib/bundler/feature_flag.rb +0 -4
  38. data/lib/bundler/fetcher/compact_index.rb +10 -15
  39. data/lib/bundler/fetcher/downloader.rb +9 -6
  40. data/lib/bundler/fetcher/index.rb +0 -27
  41. data/lib/bundler/fetcher.rb +10 -16
  42. data/lib/bundler/friendly_errors.rb +5 -32
  43. data/lib/bundler/gem_helper.rb +21 -16
  44. data/lib/bundler/index.rb +2 -7
  45. data/lib/bundler/injector.rb +12 -3
  46. data/lib/bundler/inline.rb +2 -1
  47. data/lib/bundler/installer/gem_installer.rb +4 -22
  48. data/lib/bundler/installer/parallel_installer.rb +36 -15
  49. data/lib/bundler/installer/standalone.rb +14 -9
  50. data/lib/bundler/installer.rb +8 -17
  51. data/lib/bundler/lazy_specification.rb +23 -2
  52. data/lib/bundler/lockfile_generator.rb +1 -1
  53. data/lib/bundler/lockfile_parser.rb +16 -45
  54. data/lib/bundler/man/bundle-add.1 +10 -2
  55. data/lib/bundler/man/bundle-add.1.ronn +7 -1
  56. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  57. data/lib/bundler/man/bundle-cache.1 +1 -1
  58. data/lib/bundler/man/bundle-check.1 +1 -1
  59. data/lib/bundler/man/bundle-clean.1 +1 -1
  60. data/lib/bundler/man/bundle-config.1 +23 -15
  61. data/lib/bundler/man/bundle-config.1.ronn +24 -17
  62. data/lib/bundler/man/bundle-doctor.1 +1 -1
  63. data/lib/bundler/man/bundle-exec.1 +1 -1
  64. data/lib/bundler/man/bundle-gem.1 +14 -1
  65. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  66. data/lib/bundler/man/bundle-info.1 +1 -1
  67. data/lib/bundler/man/bundle-init.1 +1 -1
  68. data/lib/bundler/man/bundle-inject.1 +1 -1
  69. data/lib/bundler/man/bundle-install.1 +2 -2
  70. data/lib/bundler/man/bundle-install.1.ronn +2 -2
  71. data/lib/bundler/man/bundle-list.1 +1 -1
  72. data/lib/bundler/man/bundle-lock.1 +1 -1
  73. data/lib/bundler/man/bundle-open.1 +1 -1
  74. data/lib/bundler/man/bundle-outdated.1 +1 -1
  75. data/lib/bundler/man/bundle-platform.1 +1 -1
  76. data/lib/bundler/man/bundle-pristine.1 +1 -1
  77. data/lib/bundler/man/bundle-remove.1 +1 -1
  78. data/lib/bundler/man/bundle-show.1 +1 -1
  79. data/lib/bundler/man/bundle-update.1 +5 -5
  80. data/lib/bundler/man/bundle-update.1.ronn +5 -4
  81. data/lib/bundler/man/bundle-viz.1 +1 -1
  82. data/lib/bundler/man/bundle.1 +1 -1
  83. data/lib/bundler/man/gemfile.5 +28 -2
  84. data/lib/bundler/man/gemfile.5.ronn +9 -1
  85. data/lib/bundler/plugin/api/source.rb +22 -0
  86. data/lib/bundler/plugin/index.rb +4 -1
  87. data/lib/bundler/plugin/installer.rb +10 -10
  88. data/lib/bundler/plugin/source_list.rb +4 -0
  89. data/lib/bundler/plugin.rb +28 -8
  90. data/lib/bundler/process_lock.rb +1 -1
  91. data/lib/bundler/psyched_yaml.rb +1 -13
  92. data/lib/bundler/remote_specification.rb +7 -0
  93. data/lib/bundler/resolver/spec_group.rb +1 -25
  94. data/lib/bundler/resolver.rb +55 -147
  95. data/lib/bundler/retry.rb +1 -1
  96. data/lib/bundler/ruby_version.rb +1 -1
  97. data/lib/bundler/rubygems_ext.rb +30 -8
  98. data/lib/bundler/rubygems_gem_installer.rb +68 -1
  99. data/lib/bundler/rubygems_integration.rb +43 -60
  100. data/lib/bundler/runtime.rb +18 -11
  101. data/lib/bundler/self_manager.rb +168 -0
  102. data/lib/bundler/settings.rb +96 -20
  103. data/lib/bundler/setup.rb +2 -2
  104. data/lib/bundler/shared_helpers.rb +4 -19
  105. data/lib/bundler/source/git/git_proxy.rb +8 -6
  106. data/lib/bundler/source/git.rb +22 -4
  107. data/lib/bundler/source/metadata.rb +1 -5
  108. data/lib/bundler/source/path/installer.rb +1 -1
  109. data/lib/bundler/source/path.rb +3 -1
  110. data/lib/bundler/source/rubygems.rb +111 -106
  111. data/lib/bundler/source/rubygems_aggregate.rb +68 -0
  112. data/lib/bundler/source.rb +21 -0
  113. data/lib/bundler/source_list.rb +100 -60
  114. data/lib/bundler/source_map.rb +58 -0
  115. data/lib/bundler/spec_set.rb +17 -31
  116. data/lib/bundler/stub_specification.rb +8 -0
  117. data/lib/bundler/templates/Executable.bundler +7 -7
  118. data/lib/bundler/templates/Gemfile +0 -2
  119. data/lib/bundler/templates/gems.rb +0 -3
  120. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  121. data/lib/bundler/templates/newgem/README.md.tt +5 -3
  122. data/lib/bundler/templates/newgem/Rakefile.tt +15 -2
  123. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +15 -6
  124. data/lib/bundler/templates/newgem/newgem.gemspec.tt +18 -16
  125. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  126. data/lib/bundler/templates/newgem/standard.yml.tt +3 -0
  127. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  128. data/lib/bundler/ui/shell.rb +1 -1
  129. data/lib/bundler/vendor/.document +1 -0
  130. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  131. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  132. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  133. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  134. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  135. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  136. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  137. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -2
  138. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -1
  139. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  140. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  141. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +5 -5
  142. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -2
  143. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -2
  144. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  145. data/lib/bundler/vendor/thor/lib/thor/error.rb +9 -4
  146. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +19 -1
  147. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +22 -4
  148. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  149. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  150. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  151. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +1 -1
  152. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  153. data/lib/bundler/vendor/tsort/lib/tsort.rb +453 -0
  154. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  155. data/lib/bundler/vendor/uri/lib/uri/common.rb +17 -80
  156. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -1
  157. data/lib/bundler/vendor/uri/lib/uri/generic.rb +5 -6
  158. data/lib/bundler/vendor/uri/lib/uri/http.rb +0 -1
  159. data/lib/bundler/vendor/uri/lib/uri/https.rb +0 -1
  160. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  161. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -1
  162. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +1 -14
  163. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +1 -12
  164. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  165. data/lib/bundler/vendor/uri/lib/uri/ws.rb +84 -0
  166. data/lib/bundler/vendor/uri/lib/uri/wss.rb +22 -0
  167. data/lib/bundler/vendor/uri/lib/uri.rb +0 -1
  168. data/lib/bundler/vendored_tsort.rb +4 -0
  169. data/lib/bundler/version.rb +1 -1
  170. data/lib/bundler/worker.rb +19 -4
  171. data/lib/bundler.rb +28 -31
  172. metadata +27 -9
  173. data/lib/bundler/gemdeps.rb +0 -29
  174. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -109,7 +109,7 @@ module Bundler
109
109
  raise VirtualProtocolError.new
110
110
  rescue Errno::ENOSPC
111
111
  raise NoSpaceOnDeviceError.new(path, action)
112
- rescue *[const_get_safely(:ENOTSUP, Errno)].compact
112
+ rescue Errno::ENOTSUP
113
113
  raise OperationNotSupportedError.new(path, action)
114
114
  rescue Errno::EEXIST, Errno::ENOENT
115
115
  raise
@@ -117,13 +117,6 @@ module Bundler
117
117
  raise GenericSystemCallError.new(e, "There was an error accessing `#{path}`.")
118
118
  end
119
119
 
120
- def const_get_safely(constant_name, namespace)
121
- const_in_namespace = namespace.constants.include?(constant_name.to_s) ||
122
- namespace.constants.include?(constant_name.to_sym)
123
- return nil unless const_in_namespace
124
- namespace.const_get(constant_name)
125
- end
126
-
127
120
  def major_deprecation(major_version, message, print_caller_location: false)
128
121
  if print_caller_location
129
122
  caller_location = caller_locations(2, 2).first
@@ -152,13 +145,6 @@ module Bundler
152
145
  Bundler.ui.warn message
153
146
  end
154
147
 
155
- def trap(signal, override = false, &block)
156
- prior = Signal.trap(signal) do
157
- block.call
158
- prior.call unless override
159
- end
160
- end
161
-
162
148
  def ensure_same_dependencies(spec, old_deps, new_deps)
163
149
  new_deps = new_deps.reject {|d| d.type == :development }
164
150
  old_deps = old_deps.reject {|d| d.type == :development }
@@ -253,7 +239,7 @@ module Bundler
253
239
  current = File.expand_path(SharedHelpers.pwd).tap{|x| x.untaint if RUBY_VERSION < "2.7" }
254
240
 
255
241
  until !File.directory?(current) || current == previous
256
- if ENV["BUNDLE_SPEC_RUN"]
242
+ if ENV["BUNDLER_SPEC_RUN"]
257
243
  # avoid stepping above the tmp directory when testing
258
244
  gemspec = if ENV["GEM_COMMAND"]
259
245
  # for Ruby Core
@@ -327,12 +313,11 @@ module Bundler
327
313
  end
328
314
 
329
315
  def clean_load_path
330
- bundler_lib = bundler_ruby_lib
331
-
332
316
  loaded_gem_paths = Bundler.rubygems.loaded_gem_paths
333
317
 
334
318
  $LOAD_PATH.reject! do |p|
335
- next if resolve_path(p).start_with?(bundler_lib)
319
+ resolved_path = resolve_path(p)
320
+ next if $LOADED_FEATURES.any? {|lf| lf.start_with?(resolved_path) }
336
321
  loaded_gem_paths.delete(p)
337
322
  end
338
323
  $LOAD_PATH.uniq!
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "shellwords"
4
-
5
3
  module Bundler
6
4
  class Source
7
5
  class Git
@@ -58,7 +56,6 @@ module Bundler
58
56
  @ref = ref
59
57
  @revision = revision
60
58
  @git = git
61
- raise GitNotInstalledError.new if allow? && !Bundler.git_present?
62
59
  end
63
60
 
64
61
  def revision
@@ -98,12 +95,12 @@ module Bundler
98
95
  SharedHelpers.filesystem_access(path.dirname) do |p|
99
96
  FileUtils.mkdir_p(p)
100
97
  end
101
- git_retry "clone", configured_uri, path.to_s, "--bare", "--no-hardlinks", "--quiet"
98
+ git_retry "clone", "--bare", "--no-hardlinks", "--quiet", "--", configured_uri, path.to_s
102
99
  return unless extra_ref
103
100
  end
104
101
 
105
102
  with_path do
106
- git_retry(*["fetch", "--force", "--quiet", "--tags", configured_uri, "refs/heads/*:refs/heads/*", extra_ref].compact, :dir => path)
103
+ git_retry(*["fetch", "--force", "--quiet", "--tags", "--", configured_uri, "refs/heads/*:refs/heads/*", extra_ref].compact, :dir => path)
107
104
  end
108
105
  end
109
106
 
@@ -210,7 +207,11 @@ module Bundler
210
207
  end
211
208
 
212
209
  def allow?
213
- @git ? @git.allow_git_ops? : true
210
+ allowed = @git ? @git.allow_git_ops? : true
211
+
212
+ raise GitNotInstalledError.new if allowed && !Bundler.git_present?
213
+
214
+ allowed
214
215
  end
215
216
 
216
217
  def with_path(&blk)
@@ -224,6 +225,7 @@ module Bundler
224
225
  end
225
226
 
226
227
  def check_allowed(command)
228
+ require "shellwords"
227
229
  command_with_no_credentials = URICredentialsFilter.credential_filtered_string("git #{command.shelljoin}", uri)
228
230
  raise GitNotAllowedError.new(command_with_no_credentials) unless allow?
229
231
  command_with_no_credentials
@@ -42,7 +42,7 @@ module Bundler
42
42
  %w[ref branch tag submodules].each do |opt|
43
43
  out << " #{opt}: #{options[opt]}\n" if options[opt]
44
44
  end
45
- out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
45
+ out << " glob: #{@glob}\n" unless default_glob?
46
46
  out << " specs:\n"
47
47
  end
48
48
 
@@ -75,12 +75,20 @@ module Bundler
75
75
  git_proxy.branch
76
76
  end
77
77
 
78
- rev = " (at #{at}@#{shortref_for_display(revision)})"
78
+ rev = "at #{at}@#{shortref_for_display(revision)}"
79
79
  rescue GitError
80
80
  ""
81
81
  end
82
82
 
83
- "#{@safe_uri}#{rev}"
83
+ specifiers = [rev, glob_for_display].compact
84
+ suffix =
85
+ if specifiers.any?
86
+ " (#{specifiers.join(", ")})"
87
+ else
88
+ ""
89
+ end
90
+
91
+ "#{@safe_uri}#{suffix}"
84
92
  end
85
93
 
86
94
  def name
@@ -282,6 +290,14 @@ module Bundler
282
290
  ref[0..11]
283
291
  end
284
292
 
293
+ def glob_for_display
294
+ default_glob? ? nil : "glob: #{@glob}"
295
+ end
296
+
297
+ def default_glob?
298
+ @glob == DEFAULT_GLOB
299
+ end
300
+
285
301
  def uri_hash
286
302
  if uri =~ %r{^\w+://(\w+@)?}
287
303
  # Downcase the domain component of the URI
@@ -291,7 +307,9 @@ module Bundler
291
307
  # If there is no URI scheme, assume it is an ssh/git URI
292
308
  input = uri
293
309
  end
294
- SharedHelpers.digest(:SHA1).hexdigest(input)
310
+ # We use SHA1 here for historical reason and to preserve backward compatibility.
311
+ # But a transition to a simpler mangling algorithm would be welcome.
312
+ Bundler::Digest.sha1(input)
295
313
  end
296
314
 
297
315
  def cached_revision
@@ -25,7 +25,7 @@ module Bundler
25
25
  s.loaded_from = File.expand_path("..", __FILE__)
26
26
  end
27
27
 
28
- if local_spec = Bundler.rubygems.find_name("bundler").find {|s| s.version.to_s == VERSION }
28
+ if local_spec = Bundler.rubygems.find_bundler(VERSION)
29
29
  idx << local_spec
30
30
  end
31
31
 
@@ -33,10 +33,6 @@ module Bundler
33
33
  end
34
34
  end
35
35
 
36
- def cached!; end
37
-
38
- def remote!; end
39
-
40
36
  def options
41
37
  {}
42
38
  end
@@ -35,7 +35,7 @@ module Bundler
35
35
  run_hooks(:post_build)
36
36
  end
37
37
 
38
- generate_bin unless spec.executables.nil? || spec.executables.empty?
38
+ generate_bin unless spec.executables.empty?
39
39
 
40
40
  run_hooks(:post_install)
41
41
  ensure
@@ -82,7 +82,9 @@ module Bundler
82
82
  end
83
83
 
84
84
  def install(spec, options = {})
85
- print_using_message "Using #{version_message(spec)} from #{self}"
85
+ using_message = "Using #{version_message(spec)} from #{self}"
86
+ using_message += " and installing its executables" unless spec.executables.empty?
87
+ print_using_message using_message
86
88
  generate_bin(spec, :disable_extensions => true)
87
89
  nil # no post-install message
88
90
  end
@@ -20,18 +20,38 @@ module Bundler
20
20
  @dependency_names = []
21
21
  @allow_remote = false
22
22
  @allow_cached = false
23
+ @allow_local = options["allow_local"] || false
23
24
  @caches = [cache_path, *Bundler.rubygems.gem_cache]
24
25
 
25
- Array(options["remotes"] || []).reverse_each {|r| add_remote(r) }
26
+ Array(options["remotes"]).reverse_each {|r| add_remote(r) }
27
+ end
28
+
29
+ def local_only!
30
+ @specs = nil
31
+ @allow_local = true
32
+ @allow_cached = false
33
+ @allow_remote = false
34
+ end
35
+
36
+ def local!
37
+ return if @allow_local
38
+
39
+ @specs = nil
40
+ @allow_local = true
26
41
  end
27
42
 
28
43
  def remote!
44
+ return if @allow_remote
45
+
29
46
  @specs = nil
30
47
  @allow_remote = true
31
48
  end
32
49
 
33
50
  def cached!
51
+ return if @allow_cached
52
+
34
53
  @specs = nil
54
+ @allow_local = true
35
55
  @allow_cached = true
36
56
  end
37
57
 
@@ -49,9 +69,17 @@ module Bundler
49
69
  o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty?
50
70
  end
51
71
 
72
+ def multiple_remotes?
73
+ @remotes.size > 1
74
+ end
75
+
76
+ def no_remotes?
77
+ @remotes.size == 0
78
+ end
79
+
52
80
  def can_lock?(spec)
53
- return super if Bundler.feature_flag.disable_multisource?
54
- spec.source.is_a?(Rubygems)
81
+ return super unless multiple_remotes?
82
+ include?(spec.source)
55
83
  end
56
84
 
57
85
  def options
@@ -73,12 +101,27 @@ module Bundler
73
101
  def to_s
74
102
  if remotes.empty?
75
103
  "locally installed gems"
76
- else
77
- remote_names = remotes.map(&:to_s).join(", ")
104
+ elsif @allow_remote && @allow_cached && @allow_local
105
+ "rubygems repository #{remote_names}, cached gems or installed locally"
106
+ elsif @allow_remote && @allow_local
78
107
  "rubygems repository #{remote_names} or installed locally"
108
+ elsif @allow_remote
109
+ "rubygems repository #{remote_names}"
110
+ elsif @allow_cached && @allow_local
111
+ "cached gems or installed locally"
112
+ else
113
+ "locally installed gems"
79
114
  end
80
115
  end
81
- alias_method :name, :to_s
116
+
117
+ def identifier
118
+ if remotes.empty?
119
+ "locally installed gems"
120
+ else
121
+ "rubygems repository #{remote_names}"
122
+ end
123
+ end
124
+ alias_method :name, :identifier
82
125
 
83
126
  def specs
84
127
  @specs ||= begin
@@ -87,7 +130,7 @@ module Bundler
87
130
  # small_idx.use large_idx.
88
131
  idx = @allow_remote ? remote_specs.dup : Index.new
89
132
  idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote
90
- idx.use(installed_specs, :override_dupes)
133
+ idx.use(installed_specs, :override_dupes) if @allow_local
91
134
  idx
92
135
  end
93
136
  end
@@ -96,7 +139,7 @@ module Bundler
96
139
  force = opts[:force]
97
140
  ensure_builtin_gems_cached = opts[:ensure_builtin_gems_cached]
98
141
 
99
- if ensure_builtin_gems_cached && builtin_gem?(spec)
142
+ if ensure_builtin_gems_cached && spec.default_gem?
100
143
  if !cached_path(spec)
101
144
  cached_built_in_gem(spec) unless spec.remote
102
145
  force = true
@@ -105,7 +148,7 @@ module Bundler
105
148
  end
106
149
  end
107
150
 
108
- if (installed?(spec) || Plugin.installed?(spec.name)) && !force
151
+ if installed?(spec) && !force
109
152
  print_using_message "Using #{version_message(spec)}"
110
153
  return nil # no post-install message
111
154
  end
@@ -123,7 +166,7 @@ module Bundler
123
166
  begin
124
167
  s = Bundler.rubygems.spec_from_gem(path, Bundler.settings["trust-policy"])
125
168
  spec.__swap__(s)
126
- rescue StandardError
169
+ rescue Gem::Package::FormatError
127
170
  Bundler.rm_rf(path)
128
171
  raise
129
172
  end
@@ -135,6 +178,7 @@ module Bundler
135
178
  Bundler.ui.confirm message
136
179
 
137
180
  path = cached_gem(spec)
181
+ raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
138
182
  if requires_sudo?
139
183
  install_path = Bundler.tmp(spec.full_name)
140
184
  bin_path = install_path.join("bin")
@@ -194,12 +238,8 @@ module Bundler
194
238
  end
195
239
 
196
240
  def cache(spec, custom_path = nil)
197
- if builtin_gem?(spec)
198
- cached_path = cached_built_in_gem(spec)
199
- else
200
- cached_path = cached_gem(spec)
201
- end
202
- raise GemNotFound, "Missing gem file '#{spec.full_name}.gem'." unless cached_path
241
+ cached_path = cached_gem(spec)
242
+ raise GemNotFound, "Missing gem file '#{spec.file_name}'." unless cached_path
203
243
  return if File.dirname(cached_path) == Bundler.app_cache.to_s
204
244
  Bundler.ui.info " * #{File.basename(cached_path)}"
205
245
  FileUtils.cp(cached_path, Bundler.app_cache(custom_path))
@@ -226,25 +266,16 @@ module Bundler
226
266
  @remotes.unshift(uri) unless @remotes.include?(uri)
227
267
  end
228
268
 
229
- def equivalent_remotes?(other_remotes)
230
- other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth))
231
- end
232
-
233
- def replace_remotes(other_remotes, allow_equivalent = false)
234
- return false if other_remotes == @remotes
235
-
236
- equivalent = allow_equivalent && equivalent_remotes?(other_remotes)
237
-
238
- @remotes = []
239
- other_remotes.reverse_each do |r|
240
- add_remote r.to_s
269
+ def spec_names
270
+ if @allow_remote && dependency_api_available?
271
+ remote_specs.spec_names
272
+ else
273
+ []
241
274
  end
242
-
243
- !equivalent
244
275
  end
245
276
 
246
277
  def unmet_deps
247
- if @allow_remote && api_fetchers.any?
278
+ if @allow_remote && dependency_api_available?
248
279
  remote_specs.unmet_dependency_names
249
280
  else
250
281
  []
@@ -260,7 +291,7 @@ module Bundler
260
291
 
261
292
  def double_check_for(unmet_dependency_names)
262
293
  return unless @allow_remote
263
- return unless api_fetchers.any?
294
+ return unless dependency_api_available?
264
295
 
265
296
  unmet_dependency_names = unmet_dependency_names.call
266
297
  unless unmet_dependency_names.nil?
@@ -282,21 +313,32 @@ module Bundler
282
313
  remote_specs.each do |spec|
283
314
  case spec
284
315
  when EndpointSpecification, Gem::Specification, StubSpecification, LazySpecification
285
- names.concat(spec.runtime_dependencies)
316
+ names.concat(spec.runtime_dependencies.map(&:name))
286
317
  when RemoteSpecification # from the full index
287
318
  return nil
288
319
  else
289
320
  raise "unhandled spec type (#{spec.inspect})"
290
321
  end
291
322
  end
292
- names.map!(&:name) if names
293
323
  names
294
324
  end
295
325
 
326
+ def dependency_api_available?
327
+ api_fetchers.any?
328
+ end
329
+
296
330
  protected
297
331
 
332
+ def remote_names
333
+ remotes.map(&:to_s).join(", ")
334
+ end
335
+
298
336
  def credless_remotes
299
- remotes.map(&method(:suppress_configured_credentials))
337
+ if Bundler.settings[:allow_deployment_source_credential_changes]
338
+ remotes.map(&method(:remove_auth))
339
+ else
340
+ remotes.map(&method(:suppress_configured_credentials))
341
+ end
300
342
  end
301
343
 
302
344
  def remotes_for_spec(spec)
@@ -311,14 +353,17 @@ module Bundler
311
353
  end
312
354
 
313
355
  def cached_gem(spec)
314
- cached_gem = cached_path(spec)
315
- unless cached_gem
316
- raise Bundler::GemNotFound, "Could not find #{spec.file_name} for installation"
356
+ if spec.default_gem?
357
+ cached_built_in_gem(spec)
358
+ else
359
+ cached_path(spec)
317
360
  end
318
- cached_gem
319
361
  end
320
362
 
321
363
  def cached_path(spec)
364
+ global_cache_path = download_cache_path(spec)
365
+ @caches << global_cache_path if global_cache_path
366
+
322
367
  possibilities = @caches.map {|p| "#{p}/#{spec.file_name}" }
323
368
  possibilities.find {|p| File.exist?(p) }
324
369
  end
@@ -365,16 +410,12 @@ module Bundler
365
410
 
366
411
  def cached_specs
367
412
  @cached_specs ||= begin
368
- idx = installed_specs.dup
413
+ idx = @allow_local ? installed_specs.dup : Index.new
369
414
 
370
415
  Dir["#{cache_path}/*.gem"].each do |gemfile|
371
416
  next if gemfile =~ /^bundler\-[\d\.]+?\.gem/
372
417
  s ||= Bundler.rubygems.spec_from_gem(gemfile)
373
418
  s.source = self
374
- if Bundler.rubygems.spec_missing_extensions?(s, false)
375
- Bundler.ui.debug "Source #{self} is ignoring #{s} because it is missing extensions"
376
- next
377
- end
378
419
  idx << s
379
420
  end
380
421
 
@@ -407,11 +448,11 @@ module Bundler
407
448
  def fetch_names(fetchers, dependency_names, index, override_dupes)
408
449
  fetchers.each do |f|
409
450
  if dependency_names
410
- Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug?
451
+ Bundler.ui.info "Fetching gem metadata from #{URICredentialsFilter.credential_filtered_uri(f.uri)}", Bundler.ui.debug?
411
452
  index.use f.specs_with_retry(dependency_names, self), override_dupes
412
453
  Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
413
454
  else
414
- Bundler.ui.info "Fetching source index from #{f.uri}"
455
+ Bundler.ui.info "Fetching source index from #{URICredentialsFilter.credential_filtered_uri(f.uri)}"
415
456
  index.use f.specs_with_retry(nil, self), override_dupes
416
457
  end
417
458
  end
@@ -422,19 +463,26 @@ module Bundler
422
463
 
423
464
  spec.fetch_platform
424
465
 
425
- download_path = requires_sudo? ? Bundler.tmp(spec.full_name) : rubygems_dir
426
- gem_path = "#{rubygems_dir}/cache/#{spec.full_name}.gem"
466
+ cache_path = download_cache_path(spec) || default_cache_path_for(rubygems_dir)
467
+ gem_path = "#{cache_path}/#{spec.file_name}"
427
468
 
428
- SharedHelpers.filesystem_access("#{download_path}/cache") do |p|
469
+ if requires_sudo?
470
+ download_path = Bundler.tmp(spec.full_name)
471
+ download_cache_path = default_cache_path_for(download_path)
472
+ else
473
+ download_cache_path = cache_path
474
+ end
475
+
476
+ SharedHelpers.filesystem_access(download_cache_path) do |p|
429
477
  FileUtils.mkdir_p(p)
430
478
  end
431
- download_gem(spec, download_path)
479
+ download_gem(spec, download_cache_path)
432
480
 
433
481
  if requires_sudo?
434
- SharedHelpers.filesystem_access("#{rubygems_dir}/cache") do |p|
482
+ SharedHelpers.filesystem_access(cache_path) do |p|
435
483
  Bundler.mkdir_p(p)
436
484
  end
437
- Bundler.sudo "mv #{download_path}/cache/#{spec.full_name}.gem #{gem_path}"
485
+ Bundler.sudo "mv #{download_cache_path}/#{spec.file_name} #{gem_path}"
438
486
  end
439
487
 
440
488
  gem_path
@@ -442,16 +490,8 @@ module Bundler
442
490
  Bundler.rm_rf(download_path) if requires_sudo?
443
491
  end
444
492
 
445
- def builtin_gem?(spec)
446
- # Ruby 2.1, where all included gems have this summary
447
- return true if spec.summary =~ /is bundled with Ruby/
448
-
449
- # Ruby 2.0, where gemspecs are stored in specifications/default/
450
- spec.loaded_from && spec.loaded_from.include?("specifications/default/")
451
- end
452
-
453
493
  def installed?(spec)
454
- installed_specs[spec].any?
494
+ installed_specs[spec].any? && !spec.deleted_gem?
455
495
  end
456
496
 
457
497
  def requires_sudo?
@@ -462,6 +502,10 @@ module Bundler
462
502
  Bundler.rubygems.gem_dir
463
503
  end
464
504
 
505
+ def default_cache_path_for(dir)
506
+ "#{dir}/cache"
507
+ end
508
+
465
509
  def cache_path
466
510
  Bundler.app_cache
467
511
  end
@@ -474,52 +518,13 @@ module Bundler
474
518
  # @param [Specification] spec
475
519
  # the spec we want to download or retrieve from the cache.
476
520
  #
477
- # @param [String] download_path
521
+ # @param [String] download_cache_path
478
522
  # the local directory the .gem will end up in.
479
523
  #
480
- def download_gem(spec, download_path)
481
- local_path = File.join(download_path, "cache/#{spec.full_name}.gem")
482
-
483
- if (cache_path = download_cache_path(spec)) && cache_path.file?
484
- SharedHelpers.filesystem_access(local_path) do
485
- FileUtils.cp(cache_path, local_path)
486
- end
487
- else
488
- uri = spec.remote.uri
489
- Bundler.ui.confirm("Fetching #{version_message(spec)}")
490
- rubygems_local_path = Bundler.rubygems.download_gem(spec, uri, download_path)
491
-
492
- # older rubygems return varying file:// variants depending on version
493
- rubygems_local_path = rubygems_local_path.gsub(/\Afile:/, "") unless Bundler.rubygems.provides?(">= 3.2.0.rc.2")
494
- rubygems_local_path = rubygems_local_path.gsub(%r{\A//}, "") if Bundler.rubygems.provides?("< 3.1.0")
495
-
496
- if rubygems_local_path != local_path
497
- SharedHelpers.filesystem_access(local_path) do
498
- FileUtils.mv(rubygems_local_path, local_path)
499
- end
500
- end
501
- cache_globally(spec, local_path)
502
- end
503
- end
504
-
505
- # Checks if the requested spec exists in the global cache. If it does
506
- # not, we create the relevant global cache subdirectory if it does not
507
- # exist and copy the spec from the local cache to the global cache.
508
- #
509
- # @param [Specification] spec
510
- # the spec we want to copy to the global cache.
511
- #
512
- # @param [String] local_cache_path
513
- # the local directory from which we want to copy the .gem.
514
- #
515
- def cache_globally(spec, local_cache_path)
516
- return unless cache_path = download_cache_path(spec)
517
- return if cache_path.exist?
518
-
519
- SharedHelpers.filesystem_access(cache_path.dirname, &:mkpath)
520
- SharedHelpers.filesystem_access(cache_path) do
521
- FileUtils.cp(local_cache_path, cache_path)
522
- end
524
+ def download_gem(spec, download_cache_path)
525
+ uri = spec.remote.uri
526
+ Bundler.ui.confirm("Fetching #{version_message(spec)}")
527
+ Bundler.rubygems.download_gem(spec, uri, download_cache_path)
523
528
  end
524
529
 
525
530
  # Returns the global cache path of the calling Rubygems::Source object.
@@ -538,7 +543,7 @@ module Bundler
538
543
  return unless remote = spec.remote
539
544
  return unless cache_slug = remote.cache_slug
540
545
 
541
- Bundler.user_cache.join("gems", cache_slug, spec.file_name)
546
+ Bundler.user_cache.join("gems", cache_slug)
542
547
  end
543
548
 
544
549
  def extension_cache_slug(spec)
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class Source
5
+ class RubygemsAggregate
6
+ attr_reader :source_map, :sources
7
+
8
+ def initialize(sources, source_map)
9
+ @sources = sources
10
+ @source_map = source_map
11
+
12
+ @index = build_index
13
+ end
14
+
15
+ def specs
16
+ @index
17
+ end
18
+
19
+ def identifier
20
+ to_s
21
+ end
22
+
23
+ def to_s
24
+ "any of the sources"
25
+ end
26
+
27
+ private
28
+
29
+ def build_index
30
+ Index.build do |idx|
31
+ dependency_names = source_map.pinned_spec_names
32
+
33
+ sources.all_sources.each do |source|
34
+ source.dependency_names = dependency_names - source_map.pinned_spec_names(source)
35
+ idx.add_source source.specs
36
+ dependency_names.concat(source.unmet_deps).uniq!
37
+ end
38
+
39
+ double_check_for_index(idx, dependency_names)
40
+ end
41
+ end
42
+
43
+ # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
44
+ # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
45
+ # but will not have found any versions of Bar from source B, which is a problem if the requested version
46
+ # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
47
+ # each spec we found, we add all possible versions from all sources to the index.
48
+ def double_check_for_index(idx, dependency_names)
49
+ pinned_names = source_map.pinned_spec_names
50
+
51
+ names = :names # do this so we only have to traverse to get dependency_names from the index once
52
+ unmet_dependency_names = lambda do
53
+ return names unless names == :names
54
+ new_names = sources.all_sources.map(&:dependency_names_to_double_check)
55
+ return names = nil if new_names.compact!
56
+ names = new_names.flatten(1).concat(dependency_names)
57
+ names.uniq!
58
+ names -= pinned_names
59
+ names
60
+ end
61
+
62
+ sources.all_sources.each do |source|
63
+ source.double_check_for(unmet_dependency_names)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end