bundler 2.2.11 → 2.3.26

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +721 -5
  3. data/README.md +1 -1
  4. data/bundler.gemspec +8 -11
  5. data/exe/bundle +7 -8
  6. data/exe/bundler +1 -1
  7. data/lib/bundler/.document +1 -0
  8. data/lib/bundler/build_metadata.rb +3 -3
  9. data/lib/bundler/cli/cache.rb +1 -1
  10. data/lib/bundler/cli/check.rb +4 -2
  11. data/lib/bundler/cli/common.rb +17 -3
  12. data/lib/bundler/cli/config.rb +10 -1
  13. data/lib/bundler/cli/doctor.rb +24 -5
  14. data/lib/bundler/cli/exec.rb +1 -6
  15. data/lib/bundler/cli/gem.rb +130 -26
  16. data/lib/bundler/cli/info.rb +27 -6
  17. data/lib/bundler/cli/init.rb +5 -1
  18. data/lib/bundler/cli/install.rb +23 -54
  19. data/lib/bundler/cli/issue.rb +4 -3
  20. data/lib/bundler/cli/list.rb +7 -1
  21. data/lib/bundler/cli/lock.rb +5 -1
  22. data/lib/bundler/cli/open.rb +1 -2
  23. data/lib/bundler/cli/outdated.rb +22 -14
  24. data/lib/bundler/cli/platform.rb +2 -2
  25. data/lib/bundler/cli/remove.rb +1 -2
  26. data/lib/bundler/cli/show.rb +1 -1
  27. data/lib/bundler/cli/update.rb +17 -8
  28. data/lib/bundler/cli.rb +51 -63
  29. data/lib/bundler/compact_index_client/cache.rb +0 -9
  30. data/lib/bundler/compact_index_client/updater.rb +26 -14
  31. data/lib/bundler/compact_index_client.rb +2 -8
  32. data/lib/bundler/current_ruby.rb +17 -6
  33. data/lib/bundler/definition.rb +260 -362
  34. data/lib/bundler/dependency.rb +23 -71
  35. data/lib/bundler/digest.rb +71 -0
  36. data/lib/bundler/dsl.rb +72 -76
  37. data/lib/bundler/endpoint_specification.rb +19 -13
  38. data/lib/bundler/env.rb +1 -1
  39. data/lib/bundler/environment_preserver.rb +4 -1
  40. data/lib/bundler/errors.rb +29 -3
  41. data/lib/bundler/feature_flag.rb +0 -5
  42. data/lib/bundler/fetcher/base.rb +6 -8
  43. data/lib/bundler/fetcher/compact_index.rb +10 -15
  44. data/lib/bundler/fetcher/downloader.rb +9 -6
  45. data/lib/bundler/fetcher/index.rb +0 -27
  46. data/lib/bundler/fetcher.rb +22 -23
  47. data/lib/bundler/friendly_errors.rb +26 -36
  48. data/lib/bundler/gem_helper.rb +21 -16
  49. data/lib/bundler/gem_helpers.rb +9 -2
  50. data/lib/bundler/gem_version_promoter.rb +14 -25
  51. data/lib/bundler/index.rb +11 -46
  52. data/lib/bundler/injector.rb +18 -4
  53. data/lib/bundler/inline.rb +4 -13
  54. data/lib/bundler/installer/gem_installer.rb +16 -21
  55. data/lib/bundler/installer/parallel_installer.rb +36 -15
  56. data/lib/bundler/installer/standalone.rb +42 -10
  57. data/lib/bundler/installer.rb +25 -41
  58. data/lib/bundler/lazy_specification.rb +52 -30
  59. data/lib/bundler/lockfile_generator.rb +2 -2
  60. data/lib/bundler/lockfile_parser.rb +18 -43
  61. data/lib/bundler/man/bundle-add.1 +21 -5
  62. data/lib/bundler/man/bundle-add.1.ronn +16 -4
  63. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  64. data/lib/bundler/man/bundle-cache.1 +7 -1
  65. data/lib/bundler/man/bundle-cache.1.ronn +7 -0
  66. data/lib/bundler/man/bundle-check.1 +1 -1
  67. data/lib/bundler/man/bundle-clean.1 +2 -2
  68. data/lib/bundler/man/bundle-clean.1.ronn +1 -1
  69. data/lib/bundler/man/bundle-config.1 +49 -22
  70. data/lib/bundler/man/bundle-config.1.ronn +49 -30
  71. data/lib/bundler/man/bundle-console.1 +53 -0
  72. data/lib/bundler/man/bundle-console.1.ronn +44 -0
  73. data/lib/bundler/man/bundle-doctor.1 +1 -1
  74. data/lib/bundler/man/bundle-exec.1 +2 -2
  75. data/lib/bundler/man/bundle-exec.1.ronn +1 -1
  76. data/lib/bundler/man/bundle-gem.1 +14 -1
  77. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  78. data/lib/bundler/man/bundle-help.1 +13 -0
  79. data/lib/bundler/man/bundle-help.1.ronn +12 -0
  80. data/lib/bundler/man/bundle-info.1 +1 -1
  81. data/lib/bundler/man/bundle-init.1 +1 -1
  82. data/lib/bundler/man/bundle-inject.1 +5 -2
  83. data/lib/bundler/man/bundle-inject.1.ronn +3 -1
  84. data/lib/bundler/man/bundle-install.1 +6 -2
  85. data/lib/bundler/man/bundle-install.1.ronn +8 -2
  86. data/lib/bundler/man/bundle-list.1 +1 -1
  87. data/lib/bundler/man/bundle-lock.1 +1 -1
  88. data/lib/bundler/man/bundle-open.1 +1 -1
  89. data/lib/bundler/man/bundle-outdated.1 +3 -10
  90. data/lib/bundler/man/bundle-outdated.1.ronn +1 -10
  91. data/lib/bundler/man/bundle-platform.1 +16 -6
  92. data/lib/bundler/man/bundle-platform.1.ronn +14 -7
  93. data/lib/bundler/man/bundle-plugin.1 +81 -0
  94. data/lib/bundler/man/bundle-plugin.1.ronn +59 -0
  95. data/lib/bundler/man/bundle-pristine.1 +1 -1
  96. data/lib/bundler/man/bundle-remove.1 +1 -1
  97. data/lib/bundler/man/bundle-show.1 +1 -1
  98. data/lib/bundler/man/bundle-update.1 +5 -5
  99. data/lib/bundler/man/bundle-update.1.ronn +5 -4
  100. data/lib/bundler/man/bundle-version.1 +35 -0
  101. data/lib/bundler/man/bundle-version.1.ronn +24 -0
  102. data/lib/bundler/man/bundle-viz.1 +4 -1
  103. data/lib/bundler/man/bundle-viz.1.ronn +2 -0
  104. data/lib/bundler/man/bundle.1 +15 -10
  105. data/lib/bundler/man/bundle.1.ronn +12 -7
  106. data/lib/bundler/man/gemfile.5 +117 -80
  107. data/lib/bundler/man/gemfile.5.ronn +105 -84
  108. data/lib/bundler/man/index.txt +4 -0
  109. data/lib/bundler/match_metadata.rb +13 -0
  110. data/lib/bundler/match_platform.rb +0 -1
  111. data/lib/bundler/match_remote_metadata.rb +29 -0
  112. data/lib/bundler/plugin/api/source.rb +24 -8
  113. data/lib/bundler/plugin/index.rb +4 -1
  114. data/lib/bundler/plugin/installer/git.rb +0 -4
  115. data/lib/bundler/plugin/installer/rubygems.rb +0 -4
  116. data/lib/bundler/plugin/installer.rb +10 -10
  117. data/lib/bundler/plugin/source_list.rb +4 -0
  118. data/lib/bundler/plugin.rb +30 -8
  119. data/lib/bundler/process_lock.rb +1 -1
  120. data/lib/bundler/remote_specification.rb +10 -4
  121. data/lib/bundler/resolver/base.rb +50 -0
  122. data/lib/bundler/resolver/spec_group.rb +31 -73
  123. data/lib/bundler/resolver.rb +193 -292
  124. data/lib/bundler/retry.rb +1 -1
  125. data/lib/bundler/ruby_dsl.rb +1 -1
  126. data/lib/bundler/ruby_version.rb +5 -18
  127. data/lib/bundler/rubygems_ext.rb +160 -26
  128. data/lib/bundler/rubygems_gem_installer.rb +86 -9
  129. data/lib/bundler/rubygems_integration.rb +46 -93
  130. data/lib/bundler/runtime.rb +18 -12
  131. data/lib/bundler/self_manager.rb +168 -0
  132. data/lib/bundler/settings.rb +98 -22
  133. data/lib/bundler/setup.rb +2 -2
  134. data/lib/bundler/shared_helpers.rb +15 -31
  135. data/lib/bundler/source/git/git_proxy.rb +8 -6
  136. data/lib/bundler/source/git.rb +29 -13
  137. data/lib/bundler/source/metadata.rb +3 -7
  138. data/lib/bundler/source/path/installer.rb +1 -1
  139. data/lib/bundler/source/path.rb +3 -1
  140. data/lib/bundler/source/rubygems.rb +199 -182
  141. data/lib/bundler/source/rubygems_aggregate.rb +68 -0
  142. data/lib/bundler/source.rb +24 -4
  143. data/lib/bundler/source_list.rb +104 -60
  144. data/lib/bundler/source_map.rb +71 -0
  145. data/lib/bundler/spec_set.rb +58 -52
  146. data/lib/bundler/stub_specification.rb +13 -3
  147. data/lib/bundler/templates/Executable +2 -4
  148. data/lib/bundler/templates/Executable.bundler +8 -8
  149. data/lib/bundler/templates/Executable.standalone +2 -4
  150. data/lib/bundler/templates/Gemfile +0 -2
  151. data/lib/bundler/templates/gems.rb +0 -3
  152. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  153. data/lib/bundler/templates/newgem/README.md.tt +8 -12
  154. data/lib/bundler/templates/newgem/Rakefile.tt +15 -2
  155. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +16 -7
  156. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +5 -4
  157. data/lib/bundler/templates/newgem/newgem.gemspec.tt +19 -17
  158. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  159. data/lib/bundler/templates/newgem/standard.yml.tt +3 -0
  160. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  161. data/lib/bundler/ui/shell.rb +1 -1
  162. data/lib/bundler/vendor/.document +1 -0
  163. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  164. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  165. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  166. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  167. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  168. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  169. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  170. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -3
  171. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +32 -26
  172. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  173. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -1
  174. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  175. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  176. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +5 -5
  177. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -2
  178. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -2
  179. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  180. data/lib/bundler/vendor/thor/lib/thor/error.rb +9 -4
  181. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +19 -1
  182. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +22 -4
  183. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  184. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  185. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  186. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +1 -1
  187. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  188. data/lib/bundler/vendor/tsort/lib/tsort.rb +452 -0
  189. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  190. data/lib/bundler/vendor/uri/lib/uri/common.rb +17 -80
  191. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -1
  192. data/lib/bundler/vendor/uri/lib/uri/generic.rb +5 -6
  193. data/lib/bundler/vendor/uri/lib/uri/http.rb +0 -1
  194. data/lib/bundler/vendor/uri/lib/uri/https.rb +0 -1
  195. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  196. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -1
  197. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +1 -14
  198. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +1 -12
  199. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  200. data/lib/bundler/vendor/uri/lib/uri/ws.rb +84 -0
  201. data/lib/bundler/vendor/uri/lib/uri/wss.rb +22 -0
  202. data/lib/bundler/vendor/uri/lib/uri.rb +0 -1
  203. data/lib/bundler/vendored_tsort.rb +4 -0
  204. data/lib/bundler/version.rb +1 -1
  205. data/lib/bundler/worker.rb +19 -4
  206. data/lib/bundler.rb +46 -39
  207. metadata +39 -12
  208. data/lib/bundler/dep_proxy.rb +0 -55
  209. data/lib/bundler/gemdeps.rb +0 -29
  210. data/lib/bundler/psyched_yaml.rb +0 -22
  211. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -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"
114
+ end
115
+ end
116
+
117
+ def identifier
118
+ if remotes.empty?
119
+ "locally installed gems"
120
+ else
121
+ "rubygems repository #{remote_names}"
79
122
  end
80
123
  end
81
- alias_method :name, :to_s
124
+ alias_method :name, :identifier
82
125
 
83
126
  def specs
84
127
  @specs ||= begin
@@ -87,106 +130,109 @@ 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
94
137
 
95
- def install(spec, opts = {})
96
- force = opts[:force]
97
- ensure_builtin_gems_cached = opts[:ensure_builtin_gems_cached]
138
+ def install(spec, options = {})
139
+ force = options[:force]
140
+ ensure_builtin_gems_cached = options[:ensure_builtin_gems_cached]
98
141
 
99
- if ensure_builtin_gems_cached && builtin_gem?(spec)
100
- if !cached_path(spec)
101
- cached_built_in_gem(spec) unless spec.remote
102
- force = true
103
- else
104
- spec.loaded_from = loaded_from(spec)
105
- end
142
+ if ensure_builtin_gems_cached && spec.default_gem? && !cached_path(spec)
143
+ cached_built_in_gem(spec) unless spec.remote
144
+ force = true
106
145
  end
107
146
 
108
- if (installed?(spec) || Plugin.installed?(spec.name)) && !force
147
+ if installed?(spec) && !force
109
148
  print_using_message "Using #{version_message(spec)}"
110
149
  return nil # no post-install message
111
150
  end
112
151
 
113
- # Download the gem to get the spec, because some specs that are returned
114
- # by rubygems.org are broken and wrong.
115
152
  if spec.remote
116
153
  # Check for this spec from other sources
117
- uris = [spec.remote.anonymized_uri]
118
- uris += remotes_for_spec(spec).map(&:anonymized_uri)
119
- uris.uniq!
154
+ uris = [spec.remote, *remotes_for_spec(spec)].map(&:anonymized_uri).uniq
120
155
  Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1
156
+ end
157
+
158
+ path = fetch_gem_if_possible(spec, options[:previous_spec])
159
+ raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
160
+
161
+ return if Bundler.settings[:no_install]
162
+
163
+ if requires_sudo?
164
+ install_path = Bundler.tmp(spec.full_name)
165
+ bin_path = install_path.join("bin")
166
+ else
167
+ install_path = rubygems_dir
168
+ bin_path = Bundler.system_bindir
169
+ end
170
+
171
+ Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
172
+
173
+ require_relative "../rubygems_gem_installer"
174
+
175
+ installer = Bundler::RubyGemsGemInstaller.at(
176
+ path,
177
+ :security_policy => Bundler.rubygems.security_policies[Bundler.settings["trust-policy"]],
178
+ :install_dir => install_path.to_s,
179
+ :bin_dir => bin_path.to_s,
180
+ :ignore_dependencies => true,
181
+ :wrappers => true,
182
+ :env_shebang => true,
183
+ :build_args => options[:build_args],
184
+ :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
185
+ :bundler_extension_cache_path => extension_cache_path(spec)
186
+ )
121
187
 
122
- path = fetch_gem(spec)
123
- begin
124
- s = Bundler.rubygems.spec_from_gem(path, Bundler.settings["trust-policy"])
125
- spec.__swap__(s)
126
- rescue StandardError
188
+ if spec.remote
189
+ s = begin
190
+ installer.spec
191
+ rescue Gem::Package::FormatError
127
192
  Bundler.rm_rf(path)
128
193
  raise
194
+ rescue Gem::Security::Exception => e
195
+ raise SecurityError,
196
+ "The gem #{File.basename(path, ".gem")} can't be installed because " \
197
+ "the security policy didn't allow it, with the message: #{e.message}"
129
198
  end
199
+
200
+ spec.__swap__(s)
130
201
  end
131
202
 
132
- unless Bundler.settings[:no_install]
133
- message = "Installing #{version_message(spec)}"
134
- message += " with native extensions" if spec.extensions.any?
135
- Bundler.ui.confirm message
203
+ message = "Installing #{version_message(spec, options[:previous_spec])}"
204
+ message += " with native extensions" if spec.extensions.any?
205
+ Bundler.ui.confirm message
136
206
 
137
- path = cached_gem(spec)
138
- if requires_sudo?
139
- install_path = Bundler.tmp(spec.full_name)
140
- bin_path = install_path.join("bin")
141
- else
142
- install_path = rubygems_dir
143
- bin_path = Bundler.system_bindir
144
- end
207
+ installed_spec = installer.install
208
+
209
+ spec.full_gem_path = installed_spec.full_gem_path
210
+ spec.loaded_from = installed_spec.loaded_from
145
211
 
146
- Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
147
-
148
- require_relative "../rubygems_gem_installer"
149
-
150
- installed_spec = Bundler::RubyGemsGemInstaller.at(
151
- path,
152
- :install_dir => install_path.to_s,
153
- :bin_dir => bin_path.to_s,
154
- :ignore_dependencies => true,
155
- :wrappers => true,
156
- :env_shebang => true,
157
- :build_args => opts[:build_args],
158
- :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
159
- :bundler_extension_cache_path => extension_cache_path(spec)
160
- ).install
161
- spec.full_gem_path = installed_spec.full_gem_path
162
-
163
- # SUDO HAX
164
- if requires_sudo?
165
- Bundler.rubygems.repository_subdirectories.each do |name|
166
- src = File.join(install_path, name, "*")
167
- dst = File.join(rubygems_dir, name)
168
- if name == "extensions" && Dir.glob(src).any?
169
- src = File.join(src, "*/*")
170
- ext_src = Dir.glob(src).first
171
- ext_src.gsub!(src[0..-6], "")
172
- dst = File.dirname(File.join(dst, ext_src))
173
- end
174
- SharedHelpers.filesystem_access(dst) do |p|
175
- Bundler.mkdir_p(p)
176
- end
177
- Bundler.sudo "cp -R #{src} #{dst}" if Dir[src].any?
212
+ # SUDO HAX
213
+ if requires_sudo?
214
+ Bundler.rubygems.repository_subdirectories.each do |name|
215
+ src = File.join(install_path, name, "*")
216
+ dst = File.join(rubygems_dir, name)
217
+ if name == "extensions" && Dir.glob(src).any?
218
+ src = File.join(src, "*/*")
219
+ ext_src = Dir.glob(src).first
220
+ ext_src.gsub!(src[0..-6], "")
221
+ dst = File.dirname(File.join(dst, ext_src))
178
222
  end
223
+ SharedHelpers.filesystem_access(dst) do |p|
224
+ Bundler.mkdir_p(p)
225
+ end
226
+ Bundler.sudo "cp -R #{src} #{dst}" if Dir[src].any?
227
+ end
179
228
 
180
- spec.executables.each do |exe|
181
- SharedHelpers.filesystem_access(Bundler.system_bindir) do |p|
182
- Bundler.mkdir_p(p)
183
- end
184
- Bundler.sudo "cp -R #{install_path}/bin/#{exe} #{Bundler.system_bindir}/"
229
+ spec.executables.each do |exe|
230
+ SharedHelpers.filesystem_access(Bundler.system_bindir) do |p|
231
+ Bundler.mkdir_p(p)
185
232
  end
233
+ Bundler.sudo "cp -R #{install_path}/bin/#{exe} #{Bundler.system_bindir}/"
186
234
  end
187
- installed_spec.loaded_from = loaded_from(spec)
188
235
  end
189
- spec.loaded_from = loaded_from(spec)
190
236
 
191
237
  spec.post_install_message
192
238
  ensure
@@ -194,12 +240,8 @@ module Bundler
194
240
  end
195
241
 
196
242
  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
243
+ cached_path = Bundler.settings[:cache_all_platforms] ? fetch_gem_if_possible(spec) : cached_gem(spec)
244
+ raise GemNotFound, "Missing gem file '#{spec.file_name}'." unless cached_path
203
245
  return if File.dirname(cached_path) == Bundler.app_cache.to_s
204
246
  Bundler.ui.info " * #{File.basename(cached_path)}"
205
247
  FileUtils.cp(cached_path, Bundler.app_cache(custom_path))
@@ -226,25 +268,16 @@ module Bundler
226
268
  @remotes.unshift(uri) unless @remotes.include?(uri)
227
269
  end
228
270
 
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
271
+ def spec_names
272
+ if @allow_remote && dependency_api_available?
273
+ remote_specs.spec_names
274
+ else
275
+ []
241
276
  end
242
-
243
- !equivalent
244
277
  end
245
278
 
246
279
  def unmet_deps
247
- if @allow_remote && api_fetchers.any?
280
+ if @allow_remote && dependency_api_available?
248
281
  remote_specs.unmet_dependency_names
249
282
  else
250
283
  []
@@ -260,7 +293,7 @@ module Bundler
260
293
 
261
294
  def double_check_for(unmet_dependency_names)
262
295
  return unless @allow_remote
263
- return unless api_fetchers.any?
296
+ return unless dependency_api_available?
264
297
 
265
298
  unmet_dependency_names = unmet_dependency_names.call
266
299
  unless unmet_dependency_names.nil?
@@ -282,21 +315,32 @@ module Bundler
282
315
  remote_specs.each do |spec|
283
316
  case spec
284
317
  when EndpointSpecification, Gem::Specification, StubSpecification, LazySpecification
285
- names.concat(spec.runtime_dependencies)
318
+ names.concat(spec.runtime_dependencies.map(&:name))
286
319
  when RemoteSpecification # from the full index
287
320
  return nil
288
321
  else
289
322
  raise "unhandled spec type (#{spec.inspect})"
290
323
  end
291
324
  end
292
- names.map!(&:name) if names
293
325
  names
294
326
  end
295
327
 
328
+ def dependency_api_available?
329
+ api_fetchers.any?
330
+ end
331
+
296
332
  protected
297
333
 
334
+ def remote_names
335
+ remotes.map(&:to_s).join(", ")
336
+ end
337
+
298
338
  def credless_remotes
299
- remotes.map(&method(:suppress_configured_credentials))
339
+ if Bundler.settings[:allow_deployment_source_credential_changes]
340
+ remotes.map(&method(:remove_auth))
341
+ else
342
+ remotes.map(&method(:suppress_configured_credentials))
343
+ end
300
344
  end
301
345
 
302
346
  def remotes_for_spec(spec)
@@ -306,23 +350,26 @@ module Bundler
306
350
  end
307
351
  end
308
352
 
309
- def loaded_from(spec)
310
- "#{rubygems_dir}/specifications/#{spec.full_name}.gemspec"
311
- end
312
-
313
353
  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"
354
+ if spec.default_gem?
355
+ cached_built_in_gem(spec)
356
+ else
357
+ cached_path(spec)
317
358
  end
318
- cached_gem
319
359
  end
320
360
 
321
361
  def cached_path(spec)
322
- possibilities = @caches.map {|p| "#{p}/#{spec.file_name}" }
362
+ global_cache_path = download_cache_path(spec)
363
+ @caches << global_cache_path if global_cache_path
364
+
365
+ possibilities = @caches.map {|p| package_path(p, spec) }
323
366
  possibilities.find {|p| File.exist?(p) }
324
367
  end
325
368
 
369
+ def package_path(cache_path, spec)
370
+ "#{cache_path}/#{spec.file_name}"
371
+ end
372
+
326
373
  def normalize_uri(uri)
327
374
  uri = uri.to_s
328
375
  uri = "#{uri}/" unless uri =~ %r{/$}
@@ -365,16 +412,12 @@ module Bundler
365
412
 
366
413
  def cached_specs
367
414
  @cached_specs ||= begin
368
- idx = installed_specs.dup
415
+ idx = @allow_local ? installed_specs.dup : Index.new
369
416
 
370
417
  Dir["#{cache_path}/*.gem"].each do |gemfile|
371
418
  next if gemfile =~ /^bundler\-[\d\.]+?\.gem/
372
419
  s ||= Bundler.rubygems.spec_from_gem(gemfile)
373
420
  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
421
  idx << s
379
422
  end
380
423
 
@@ -407,34 +450,48 @@ module Bundler
407
450
  def fetch_names(fetchers, dependency_names, index, override_dupes)
408
451
  fetchers.each do |f|
409
452
  if dependency_names
410
- Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug?
453
+ Bundler.ui.info "Fetching gem metadata from #{URICredentialsFilter.credential_filtered_uri(f.uri)}", Bundler.ui.debug?
411
454
  index.use f.specs_with_retry(dependency_names, self), override_dupes
412
455
  Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
413
456
  else
414
- Bundler.ui.info "Fetching source index from #{f.uri}"
457
+ Bundler.ui.info "Fetching source index from #{URICredentialsFilter.credential_filtered_uri(f.uri)}"
415
458
  index.use f.specs_with_retry(nil, self), override_dupes
416
459
  end
417
460
  end
418
461
  end
419
462
 
420
- def fetch_gem(spec)
421
- return false unless spec.remote
463
+ def fetch_gem_if_possible(spec, previous_spec = nil)
464
+ if spec.remote
465
+ fetch_gem(spec, previous_spec)
466
+ else
467
+ cached_gem(spec)
468
+ end
469
+ end
422
470
 
471
+ def fetch_gem(spec, previous_spec = nil)
423
472
  spec.fetch_platform
424
473
 
425
- download_path = requires_sudo? ? Bundler.tmp(spec.full_name) : rubygems_dir
426
- gem_path = "#{rubygems_dir}/cache/#{spec.full_name}.gem"
474
+ cache_path = download_cache_path(spec) || default_cache_path_for(rubygems_dir)
475
+ gem_path = package_path(cache_path, spec)
476
+ return gem_path if File.exist?(gem_path)
427
477
 
428
- SharedHelpers.filesystem_access("#{download_path}/cache") do |p|
478
+ if requires_sudo?
479
+ download_path = Bundler.tmp(spec.full_name)
480
+ download_cache_path = default_cache_path_for(download_path)
481
+ else
482
+ download_cache_path = cache_path
483
+ end
484
+
485
+ SharedHelpers.filesystem_access(download_cache_path) do |p|
429
486
  FileUtils.mkdir_p(p)
430
487
  end
431
- download_gem(spec, download_path)
488
+ download_gem(spec, download_cache_path, previous_spec)
432
489
 
433
490
  if requires_sudo?
434
- SharedHelpers.filesystem_access("#{rubygems_dir}/cache") do |p|
491
+ SharedHelpers.filesystem_access(cache_path) do |p|
435
492
  Bundler.mkdir_p(p)
436
493
  end
437
- Bundler.sudo "mv #{download_path}/cache/#{spec.full_name}.gem #{gem_path}"
494
+ Bundler.sudo "mv #{package_path(download_cache_path, spec)} #{gem_path}"
438
495
  end
439
496
 
440
497
  gem_path
@@ -442,16 +499,8 @@ module Bundler
442
499
  Bundler.rm_rf(download_path) if requires_sudo?
443
500
  end
444
501
 
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
502
  def installed?(spec)
454
- installed_specs[spec].any?
503
+ installed_specs[spec].any? && !spec.deleted_gem?
455
504
  end
456
505
 
457
506
  def requires_sudo?
@@ -459,7 +508,11 @@ module Bundler
459
508
  end
460
509
 
461
510
  def rubygems_dir
462
- Bundler.rubygems.gem_dir
511
+ Bundler.bundle_path
512
+ end
513
+
514
+ def default_cache_path_for(dir)
515
+ "#{dir}/cache"
463
516
  end
464
517
 
465
518
  def cache_path
@@ -474,52 +527,16 @@ module Bundler
474
527
  # @param [Specification] spec
475
528
  # the spec we want to download or retrieve from the cache.
476
529
  #
477
- # @param [String] download_path
530
+ # @param [String] download_cache_path
478
531
  # the local directory the .gem will end up in.
479
532
  #
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.
533
+ # @param [Specification] previous_spec
534
+ # the spec previously locked
514
535
  #
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
536
+ def download_gem(spec, download_cache_path, previous_spec = nil)
537
+ uri = spec.remote.uri
538
+ Bundler.ui.confirm("Fetching #{version_message(spec, previous_spec)}")
539
+ Bundler.rubygems.download_gem(spec, uri, download_cache_path)
523
540
  end
524
541
 
525
542
  # Returns the global cache path of the calling Rubygems::Source object.
@@ -538,7 +555,7 @@ module Bundler
538
555
  return unless remote = spec.remote
539
556
  return unless cache_slug = remote.cache_slug
540
557
 
541
- Bundler.user_cache.join("gems", cache_slug, spec.file_name)
558
+ Bundler.user_cache.join("gems", cache_slug)
542
559
  end
543
560
 
544
561
  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