bundler 1.15.2 → 1.17.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (286) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +302 -0
  3. data/README.md +17 -8
  4. data/bundler.gemspec +25 -9
  5. data/exe/bundle +1 -1
  6. data/exe/bundle_ruby +4 -3
  7. data/lib/bundler/build_metadata.rb +53 -0
  8. data/lib/bundler/capistrano.rb +5 -0
  9. data/lib/bundler/cli/add.rb +15 -6
  10. data/lib/bundler/cli/binstubs.rb +17 -9
  11. data/lib/bundler/cli/cache.rb +5 -4
  12. data/lib/bundler/cli/check.rb +3 -5
  13. data/lib/bundler/cli/clean.rb +5 -6
  14. data/lib/bundler/cli/common.rb +11 -2
  15. data/lib/bundler/cli/config.rb +2 -1
  16. data/lib/bundler/cli/console.rb +2 -1
  17. data/lib/bundler/cli/doctor.rb +48 -1
  18. data/lib/bundler/cli/exec.rb +6 -5
  19. data/lib/bundler/cli/gem.rb +13 -8
  20. data/lib/bundler/cli/info.rb +0 -1
  21. data/lib/bundler/cli/init.rb +18 -6
  22. data/lib/bundler/cli/inject.rb +1 -0
  23. data/lib/bundler/cli/install.rb +64 -61
  24. data/lib/bundler/cli/issue.rb +1 -1
  25. data/lib/bundler/cli/list.rb +58 -0
  26. data/lib/bundler/cli/lock.rb +0 -1
  27. data/lib/bundler/cli/open.rb +2 -2
  28. data/lib/bundler/cli/outdated.rb +20 -9
  29. data/lib/bundler/cli/package.rb +9 -6
  30. data/lib/bundler/cli/platform.rb +1 -0
  31. data/lib/bundler/cli/plugin.rb +1 -0
  32. data/lib/bundler/cli/pristine.rb +20 -6
  33. data/lib/bundler/cli/remove.rb +18 -0
  34. data/lib/bundler/cli/show.rb +0 -1
  35. data/lib/bundler/cli/update.rb +35 -7
  36. data/lib/bundler/cli/viz.rb +1 -0
  37. data/lib/bundler/cli.rb +227 -89
  38. data/lib/bundler/compact_index_client/cache.rb +1 -2
  39. data/lib/bundler/compact_index_client/updater.rb +14 -4
  40. data/lib/bundler/compact_index_client.rb +1 -0
  41. data/lib/bundler/compatibility_guard.rb +14 -0
  42. data/lib/bundler/constants.rb +1 -0
  43. data/lib/bundler/current_ruby.rb +13 -5
  44. data/lib/bundler/definition.rb +192 -139
  45. data/lib/bundler/dep_proxy.rb +3 -1
  46. data/lib/bundler/dependency.rb +9 -9
  47. data/lib/bundler/deployment.rb +1 -1
  48. data/lib/bundler/deprecate.rb +15 -3
  49. data/lib/bundler/dsl.rb +115 -64
  50. data/lib/bundler/endpoint_specification.rb +10 -1
  51. data/lib/bundler/env.rb +90 -29
  52. data/lib/bundler/environment_preserver.rb +27 -6
  53. data/lib/bundler/errors.rb +1 -0
  54. data/lib/bundler/feature_flag.rb +46 -4
  55. data/lib/bundler/fetcher/base.rb +1 -0
  56. data/lib/bundler/fetcher/compact_index.rb +2 -11
  57. data/lib/bundler/fetcher/dependency.rb +2 -1
  58. data/lib/bundler/fetcher/downloader.rb +11 -5
  59. data/lib/bundler/fetcher/index.rb +3 -2
  60. data/lib/bundler/fetcher.rb +18 -11
  61. data/lib/bundler/friendly_errors.rb +6 -1
  62. data/lib/bundler/gem_helper.rb +19 -10
  63. data/lib/bundler/gem_helpers.rb +1 -0
  64. data/lib/bundler/gem_remote_fetcher.rb +1 -0
  65. data/lib/bundler/gem_tasks.rb +1 -0
  66. data/lib/bundler/gem_version_promoter.rb +17 -2
  67. data/lib/bundler/gemdeps.rb +1 -0
  68. data/lib/bundler/graph.rb +1 -0
  69. data/lib/bundler/index.rb +8 -8
  70. data/lib/bundler/injector.rb +192 -30
  71. data/lib/bundler/inline.rb +5 -7
  72. data/lib/bundler/installer/gem_installer.rb +11 -2
  73. data/lib/bundler/installer/parallel_installer.rb +78 -42
  74. data/lib/bundler/installer/standalone.rb +1 -0
  75. data/lib/bundler/installer.rb +138 -53
  76. data/lib/bundler/lazy_specification.rb +3 -2
  77. data/lib/bundler/lockfile_generator.rb +95 -0
  78. data/lib/bundler/lockfile_parser.rb +10 -4
  79. data/lib/bundler/match_platform.rb +1 -0
  80. data/lib/bundler/mirror.rb +8 -5
  81. data/lib/bundler/plugin/api/source.rb +9 -2
  82. data/lib/bundler/plugin/events.rb +61 -0
  83. data/lib/bundler/plugin/index.rb +7 -2
  84. data/lib/bundler/plugin/installer.rb +7 -6
  85. data/lib/bundler/plugin/source_list.rb +7 -8
  86. data/lib/bundler/plugin.rb +13 -5
  87. data/lib/bundler/process_lock.rb +24 -0
  88. data/lib/bundler/psyched_yaml.rb +10 -0
  89. data/lib/bundler/remote_specification.rb +1 -0
  90. data/lib/bundler/resolver/spec_group.rb +106 -0
  91. data/lib/bundler/resolver.rb +158 -195
  92. data/lib/bundler/retry.rb +1 -0
  93. data/lib/bundler/ruby_dsl.rb +1 -0
  94. data/lib/bundler/ruby_version.rb +2 -1
  95. data/lib/bundler/rubygems_ext.rb +5 -4
  96. data/lib/bundler/rubygems_gem_installer.rb +31 -1
  97. data/lib/bundler/rubygems_integration.rb +71 -32
  98. data/lib/bundler/runtime.rb +11 -9
  99. data/lib/bundler/settings/validator.rb +102 -0
  100. data/lib/bundler/settings.rb +200 -77
  101. data/lib/bundler/setup.rb +1 -0
  102. data/lib/bundler/shared_helpers.rb +131 -26
  103. data/lib/bundler/similarity_detector.rb +1 -0
  104. data/lib/bundler/source/gemspec.rb +1 -0
  105. data/lib/bundler/source/git/git_proxy.rb +21 -11
  106. data/lib/bundler/source/git.rb +24 -19
  107. data/lib/bundler/source/metadata.rb +62 -0
  108. data/lib/bundler/source/path/installer.rb +2 -0
  109. data/lib/bundler/source/path.rb +8 -8
  110. data/lib/bundler/source/rubygems/remote.rb +8 -2
  111. data/lib/bundler/source/rubygems.rb +161 -84
  112. data/lib/bundler/source.rb +36 -0
  113. data/lib/bundler/source_list.rb +75 -15
  114. data/lib/bundler/spec_set.rb +10 -5
  115. data/lib/bundler/ssl_certs/certificate_manager.rb +2 -1
  116. data/lib/bundler/stub_specification.rb +1 -0
  117. data/lib/bundler/templates/.document +1 -0
  118. data/lib/bundler/templates/Executable +12 -0
  119. data/lib/bundler/templates/Executable.bundler +105 -0
  120. data/lib/bundler/templates/Gemfile +1 -0
  121. data/lib/bundler/templates/gems.rb +8 -0
  122. data/lib/bundler/templates/newgem/README.md.tt +1 -1
  123. data/lib/bundler/templates/newgem/gitignore.tt +0 -1
  124. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -0
  125. data/lib/bundler/templates/newgem/newgem.gemspec.tt +12 -3
  126. data/lib/bundler/templates/newgem/rspec.tt +1 -0
  127. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +0 -2
  128. data/lib/bundler/templates/newgem/{.travis.yml.tt → travis.yml.tt} +2 -0
  129. data/lib/bundler/ui/rg_proxy.rb +1 -0
  130. data/lib/bundler/ui/shell.rb +17 -4
  131. data/lib/bundler/ui/silent.rb +1 -0
  132. data/lib/bundler/ui.rb +1 -0
  133. data/lib/bundler/uri_credentials_filter.rb +1 -0
  134. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1638 -0
  135. data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
  136. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +7 -0
  137. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +1 -0
  138. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +1 -0
  139. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -0
  140. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -0
  141. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -0
  142. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -0
  143. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +1 -0
  144. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -0
  145. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -0
  146. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +15 -4
  147. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -2
  148. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +75 -7
  149. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +2 -1
  150. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -0
  151. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +3 -1
  152. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +491 -148
  153. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +1 -0
  154. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +8 -4
  155. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +2 -0
  156. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  157. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +1 -0
  158. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +1 -0
  159. data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +9 -1
  160. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +45 -8
  161. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +9 -3
  162. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -3
  163. data/lib/bundler/vendor/thor/lib/thor/base.rb +27 -4
  164. data/lib/bundler/vendor/thor/lib/thor/command.rb +9 -7
  165. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +12 -0
  166. data/lib/bundler/vendor/thor/lib/thor/group.rb +1 -1
  167. data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +2 -0
  168. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +5 -5
  169. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +6 -5
  170. data/lib/bundler/vendor/thor/lib/thor/runner.rb +6 -4
  171. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +10 -9
  172. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  173. data/lib/bundler/vendor/thor/lib/thor.rb +25 -8
  174. data/lib/bundler/vendored_fileutils.rb +9 -0
  175. data/lib/bundler/vendored_molinillo.rb +1 -0
  176. data/lib/bundler/vendored_persistent.rb +35 -0
  177. data/lib/bundler/vendored_thor.rb +1 -0
  178. data/lib/bundler/version.rb +6 -2
  179. data/lib/bundler/version_ranges.rb +1 -0
  180. data/lib/bundler/vlad.rb +5 -0
  181. data/lib/bundler/worker.rb +1 -0
  182. data/lib/bundler/yaml_serializer.rb +3 -3
  183. data/lib/bundler.rb +86 -52
  184. data/man/bundle-add.1 +18 -3
  185. data/man/bundle-add.1.txt +26 -14
  186. data/man/bundle-add.ronn +13 -2
  187. data/man/bundle-binstubs.1 +11 -1
  188. data/man/bundle-binstubs.1.txt +33 -18
  189. data/man/bundle-binstubs.ronn +15 -1
  190. data/man/bundle-check.1 +4 -4
  191. data/man/bundle-check.1.txt +15 -14
  192. data/man/bundle-check.ronn +3 -3
  193. data/man/bundle-clean.1 +1 -1
  194. data/man/bundle-clean.1.txt +10 -10
  195. data/man/bundle-config.1 +129 -29
  196. data/man/bundle-config.1.txt +285 -174
  197. data/man/bundle-config.ronn +167 -88
  198. data/man/bundle-doctor.1 +44 -0
  199. data/man/bundle-doctor.1.txt +44 -0
  200. data/man/bundle-doctor.ronn +33 -0
  201. data/man/bundle-exec.1 +6 -3
  202. data/man/bundle-exec.1.txt +78 -71
  203. data/man/bundle-exec.ronn +10 -3
  204. data/man/bundle-gem.1 +3 -3
  205. data/man/bundle-gem.1.txt +40 -39
  206. data/man/bundle-gem.ronn +2 -1
  207. data/man/bundle-info.1 +1 -1
  208. data/man/bundle-info.1.txt +8 -8
  209. data/man/bundle-init.1 +9 -4
  210. data/man/bundle-init.1.txt +23 -13
  211. data/man/bundle-init.ronn +15 -4
  212. data/man/bundle-inject.1 +4 -4
  213. data/man/bundle-inject.1.txt +10 -10
  214. data/man/bundle-inject.ronn +3 -3
  215. data/man/bundle-install.1 +31 -28
  216. data/man/bundle-install.1.txt +205 -194
  217. data/man/bundle-install.ronn +44 -35
  218. data/man/bundle-list.1 +50 -0
  219. data/man/bundle-list.1.txt +43 -0
  220. data/man/bundle-list.ronn +33 -0
  221. data/man/bundle-lock.1 +1 -1
  222. data/man/bundle-lock.1.txt +47 -47
  223. data/man/bundle-lock.ronn +1 -1
  224. data/man/bundle-open.1 +1 -1
  225. data/man/bundle-open.1.txt +7 -7
  226. data/man/bundle-outdated.1 +7 -3
  227. data/man/bundle-outdated.1.txt +40 -36
  228. data/man/bundle-outdated.ronn +6 -2
  229. data/man/bundle-package.1 +6 -3
  230. data/man/bundle-package.1.txt +44 -39
  231. data/man/bundle-package.ronn +7 -2
  232. data/man/bundle-platform.1 +1 -1
  233. data/man/bundle-platform.1.txt +13 -13
  234. data/man/bundle-pristine.1 +21 -3
  235. data/man/bundle-pristine.1.txt +33 -10
  236. data/man/bundle-pristine.ronn +24 -3
  237. data/man/bundle-remove.1 +31 -0
  238. data/man/bundle-remove.1.txt +34 -0
  239. data/man/bundle-remove.ronn +23 -0
  240. data/man/bundle-show.1 +3 -3
  241. data/man/bundle-show.1.txt +14 -12
  242. data/man/bundle-show.ronn +3 -2
  243. data/man/bundle-update.1 +13 -9
  244. data/man/bundle-update.1.txt +133 -130
  245. data/man/bundle-update.ronn +21 -17
  246. data/man/bundle-viz.1 +7 -7
  247. data/man/bundle-viz.1.txt +17 -15
  248. data/man/bundle-viz.ronn +6 -6
  249. data/man/bundle.1 +31 -23
  250. data/man/bundle.1.txt +63 -57
  251. data/man/bundle.ronn +35 -29
  252. data/man/gemfile.5 +44 -8
  253. data/man/gemfile.5.ronn +54 -8
  254. data/man/gemfile.5.txt +218 -165
  255. data/man/index.txt +25 -15
  256. metadata +36 -36
  257. data/.codeclimate.yml +0 -25
  258. data/.gitignore +0 -18
  259. data/.rspec +0 -3
  260. data/.rubocop.yml +0 -131
  261. data/.rubocop_todo.yml +0 -418
  262. data/.travis.yml +0 -122
  263. data/CODE_OF_CONDUCT.md +0 -42
  264. data/CONTRIBUTING.md +0 -17
  265. data/Rakefile +0 -338
  266. data/bin/rake +0 -19
  267. data/bin/rspec +0 -15
  268. data/bin/rubocop +0 -17
  269. data/bin/with_rubygems +0 -39
  270. data/doc/README.md +0 -30
  271. data/doc/TROUBLESHOOTING.md +0 -64
  272. data/doc/contributing/BUG_TRIAGE.md +0 -36
  273. data/doc/contributing/COMMUNITY.md +0 -13
  274. data/doc/contributing/GETTING_HELP.md +0 -11
  275. data/doc/contributing/HOW_YOU_CAN_HELP.md +0 -27
  276. data/doc/contributing/ISSUES.md +0 -51
  277. data/doc/contributing/README.md +0 -38
  278. data/doc/development/NEW_FEATURES.md +0 -10
  279. data/doc/development/PULL_REQUESTS.md +0 -40
  280. data/doc/development/README.md +0 -19
  281. data/doc/development/RELEASING.md +0 -9
  282. data/doc/development/SETUP.md +0 -27
  283. data/doc/documentation/README.md +0 -29
  284. data/doc/documentation/VISION.md +0 -26
  285. data/doc/documentation/WRITING.md +0 -54
  286. data/task/release.rake +0 -116
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "uri"
3
4
  require "rubygems/user_interaction"
4
5
 
@@ -31,6 +32,7 @@ module Bundler
31
32
  end
32
33
 
33
34
  def cached!
35
+ @specs = nil
34
36
  @allow_cached = true
35
37
  end
36
38
 
@@ -49,6 +51,7 @@ module Bundler
49
51
  end
50
52
 
51
53
  def can_lock?(spec)
54
+ return super if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
52
55
  spec.source.is_a?(Rubygems)
53
56
  end
54
57
 
@@ -69,8 +72,12 @@ module Bundler
69
72
  end
70
73
 
71
74
  def to_s
72
- remote_names = remotes.map(&:to_s).join(", ")
73
- "rubygems repository #{remote_names}"
75
+ if remotes.empty?
76
+ "locally installed gems"
77
+ else
78
+ remote_names = remotes.map(&:to_s).join(", ")
79
+ "rubygems repository #{remote_names} or installed locally"
80
+ end
74
81
  end
75
82
  alias_method :name, :to_s
76
83
 
@@ -99,8 +106,8 @@ module Bundler
99
106
  end
100
107
  end
101
108
 
102
- if installed?(spec) && (!force || spec.name.eql?("bundler"))
103
- Bundler.ui.info "Using #{version_message(spec)}"
109
+ if installed?(spec) && !force
110
+ print_using_message "Using #{version_message(spec)}"
104
111
  return nil # no post-install message
105
112
  end
106
113
 
@@ -131,6 +138,8 @@ module Bundler
131
138
  bin_path = Bundler.system_bindir
132
139
  end
133
140
 
141
+ Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
142
+
134
143
  installed_spec = nil
135
144
  Bundler.rubygems.preserve_paths do
136
145
  installed_spec = Bundler::RubyGemsGemInstaller.at(
@@ -141,7 +150,8 @@ module Bundler
141
150
  :wrappers => true,
142
151
  :env_shebang => true,
143
152
  :build_args => opts[:build_args],
144
- :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum
153
+ :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
154
+ :bundler_extension_cache_path => extension_cache_path(spec)
145
155
  ).install
146
156
  end
147
157
  spec.full_gem_path = installed_spec.full_gem_path
@@ -212,13 +222,21 @@ module Bundler
212
222
  @remotes.unshift(uri) unless @remotes.include?(uri)
213
223
  end
214
224
 
215
- def replace_remotes(other_remotes)
225
+ def equivalent_remotes?(other_remotes)
226
+ other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth))
227
+ end
228
+
229
+ def replace_remotes(other_remotes, allow_equivalent = false)
216
230
  return false if other_remotes == @remotes
217
231
 
232
+ equivalent = allow_equivalent && equivalent_remotes?(other_remotes)
233
+
218
234
  @remotes = []
219
235
  other_remotes.reverse_each do |r|
220
236
  add_remote r.to_s
221
237
  end
238
+
239
+ !equivalent
222
240
  end
223
241
 
224
242
  def unmet_deps
@@ -236,6 +254,41 @@ module Bundler
236
254
  end
237
255
  end
238
256
 
257
+ def double_check_for(unmet_dependency_names)
258
+ return unless @allow_remote
259
+ return unless api_fetchers.any?
260
+
261
+ unmet_dependency_names = unmet_dependency_names.call
262
+ unless unmet_dependency_names.nil?
263
+ if api_fetchers.size <= 1
264
+ # can't do this when there are multiple fetchers because then we might not fetch from _all_
265
+ # of them
266
+ unmet_dependency_names -= remote_specs.spec_names # avoid re-fetching things we've already gotten
267
+ end
268
+ return if unmet_dependency_names.empty?
269
+ end
270
+
271
+ Bundler.ui.debug "Double checking for #{unmet_dependency_names || "all specs (due to the size of the request)"} in #{self}"
272
+
273
+ fetch_names(api_fetchers, unmet_dependency_names, specs, false)
274
+ end
275
+
276
+ def dependency_names_to_double_check
277
+ names = []
278
+ remote_specs.each do |spec|
279
+ case spec
280
+ when EndpointSpecification, Gem::Specification, StubSpecification, LazySpecification
281
+ names.concat(spec.runtime_dependencies)
282
+ when RemoteSpecification # from the full index
283
+ return nil
284
+ else
285
+ raise "unhandled spec type (#{spec.inspect})"
286
+ end
287
+ end
288
+ names.map!(&:name) if names
289
+ names
290
+ end
291
+
239
292
  protected
240
293
 
241
294
  def credless_remotes
@@ -276,7 +329,7 @@ module Bundler
276
329
  end
277
330
 
278
331
  def suppress_configured_credentials(remote)
279
- remote_nouser = remote.dup.tap {|uri| uri.user = uri.password = nil }.to_s
332
+ remote_nouser = remove_auth(remote)
280
333
  if remote.userinfo && remote.userinfo == Bundler.settings[remote_nouser]
281
334
  remote_nouser
282
335
  else
@@ -284,15 +337,18 @@ module Bundler
284
337
  end
285
338
  end
286
339
 
340
+ def remove_auth(remote)
341
+ if remote.user || remote.password
342
+ remote.dup.tap {|uri| uri.user = uri.password = nil }.to_s
343
+ else
344
+ remote.to_s
345
+ end
346
+ end
347
+
287
348
  def installed_specs
288
- @installed_specs ||= begin
289
- idx = Index.new
290
- have_bundler = false
349
+ @installed_specs ||= Index.build do |idx|
291
350
  Bundler.rubygems.all_specs.reverse_each do |spec|
292
- if spec.name == "bundler"
293
- next unless spec.version.to_s == VERSION
294
- have_bundler = true
295
- end
351
+ next if spec.name == "bundler"
296
352
  spec.source = self
297
353
  if Bundler.rubygems.spec_missing_extensions?(spec, false)
298
354
  Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions"
@@ -300,23 +356,6 @@ module Bundler
300
356
  end
301
357
  idx << spec
302
358
  end
303
-
304
- # Always have bundler locally
305
- unless have_bundler
306
- # We're running bundler directly from the source
307
- # so, let's create a fake gemspec for it (it's a path)
308
- # gemspec
309
- bundler = Gem::Specification.new do |s|
310
- s.name = "bundler"
311
- s.version = VERSION
312
- s.platform = Gem::Platform::RUBY
313
- s.source = self
314
- s.authors = ["bundler team"]
315
- s.loaded_from = File.expand_path("..", __FILE__)
316
- end
317
- idx << bundler
318
- end
319
- idx
320
359
  end
321
360
  end
322
361
 
@@ -334,9 +373,9 @@ module Bundler
334
373
  end
335
374
  idx << s
336
375
  end
337
- end
338
376
 
339
- idx
377
+ idx
378
+ end
340
379
  end
341
380
 
342
381
  def api_fetchers
@@ -348,71 +387,36 @@ module Bundler
348
387
  index_fetchers = fetchers - api_fetchers
349
388
 
350
389
  # gather lists from non-api sites
351
- index_fetchers.each do |f|
352
- Bundler.ui.info "Fetching source index from #{f.uri}"
353
- idx.use f.specs_with_retry(nil, self)
354
- end
390
+ fetch_names(index_fetchers, nil, idx, false)
355
391
 
356
392
  # because ensuring we have all the gems we need involves downloading
357
393
  # the gemspecs of those gems, if the non-api sites contain more than
358
- # about 100 gems, we treat all sites as non-api for speed.
394
+ # about 500 gems, we treat all sites as non-api for speed.
359
395
  allow_api = idx.size < API_REQUEST_LIMIT && dependency_names.size < API_REQUEST_LIMIT
360
396
  Bundler.ui.debug "Need to query more than #{API_REQUEST_LIMIT} gems." \
361
397
  " Downloading full index instead..." unless allow_api
362
398
 
363
- if allow_api
364
- api_fetchers.each do |f|
365
- Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug?
366
- idx.use f.specs_with_retry(dependency_names, self)
367
- Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
368
- end
369
-
370
- # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
371
- # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
372
- # but will not have found any versions of Bar from source B, which is a problem if the requested version
373
- # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
374
- # each spec we found, we add all possible versions from all sources to the index.
375
- loop do
376
- idxcount = idx.size
377
- api_fetchers.each do |f|
378
- Bundler.ui.info "Fetching version metadata from #{f.uri}", Bundler.ui.debug?
379
- idx.use f.specs_with_retry(idx.dependency_names, self), true
380
- Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
381
- end
382
- break if idxcount == idx.size
383
- end
384
-
385
- if api_fetchers.any?
386
- # it's possible that gems from one source depend on gems from some
387
- # other source, so now we download gemspecs and iterate over those
388
- # dependencies, looking for gems we don't have info on yet.
389
- unmet = idx.unmet_dependency_names
390
-
391
- # if there are any cross-site gems we missed, get them now
392
- api_fetchers.each do |f|
393
- Bundler.ui.info "Fetching dependency metadata from #{f.uri}", Bundler.ui.debug?
394
- idx.use f.specs_with_retry(unmet, self)
395
- Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
396
- end if unmet.any?
397
- else
398
- allow_api = false
399
- end
400
- end
399
+ fetch_names(api_fetchers, allow_api && dependency_names, idx, false)
400
+ end
401
+ end
401
402
 
402
- unless allow_api
403
- api_fetchers.each do |f|
404
- Bundler.ui.info "Fetching source index from #{f.uri}"
405
- idx.use f.specs_with_retry(nil, self)
406
- end
403
+ def fetch_names(fetchers, dependency_names, index, override_dupes)
404
+ fetchers.each do |f|
405
+ if dependency_names
406
+ Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug?
407
+ index.use f.specs_with_retry(dependency_names, self), override_dupes
408
+ Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
409
+ else
410
+ Bundler.ui.info "Fetching source index from #{f.uri}"
411
+ index.use f.specs_with_retry(nil, self), override_dupes
407
412
  end
408
413
  end
409
414
  end
410
415
 
411
416
  def fetch_gem(spec)
412
417
  return false unless spec.remote
413
- uri = spec.remote.uri
418
+
414
419
  spec.fetch_platform
415
- Bundler.ui.confirm("Fetching #{version_message(spec)}")
416
420
 
417
421
  download_path = requires_sudo? ? Bundler.tmp(spec.full_name) : rubygems_dir
418
422
  gem_path = "#{rubygems_dir}/cache/#{spec.full_name}.gem"
@@ -420,7 +424,7 @@ module Bundler
420
424
  SharedHelpers.filesystem_access("#{download_path}/cache") do |p|
421
425
  FileUtils.mkdir_p(p)
422
426
  end
423
- Bundler.rubygems.download_gem(spec, uri, download_path)
427
+ download_gem(spec, download_path)
424
428
 
425
429
  if requires_sudo?
426
430
  SharedHelpers.filesystem_access("#{rubygems_dir}/cache") do |p|
@@ -457,6 +461,79 @@ module Bundler
457
461
  def cache_path
458
462
  Bundler.app_cache
459
463
  end
464
+
465
+ private
466
+
467
+ # Checks if the requested spec exists in the global cache. If it does,
468
+ # we copy it to the download path, and if it does not, we download it.
469
+ #
470
+ # @param [Specification] spec
471
+ # the spec we want to download or retrieve from the cache.
472
+ #
473
+ # @param [String] download_path
474
+ # the local directory the .gem will end up in.
475
+ #
476
+ def download_gem(spec, download_path)
477
+ local_path = File.join(download_path, "cache/#{spec.full_name}.gem")
478
+
479
+ if (cache_path = download_cache_path(spec)) && cache_path.file?
480
+ SharedHelpers.filesystem_access(local_path) do
481
+ FileUtils.cp(cache_path, local_path)
482
+ end
483
+ else
484
+ uri = spec.remote.uri
485
+ Bundler.ui.confirm("Fetching #{version_message(spec)}")
486
+ rubygems_local_path = Bundler.rubygems.download_gem(spec, uri, download_path)
487
+ if rubygems_local_path != local_path
488
+ FileUtils.mv(rubygems_local_path, local_path)
489
+ end
490
+ cache_globally(spec, local_path)
491
+ end
492
+ end
493
+
494
+ # Checks if the requested spec exists in the global cache. If it does
495
+ # not, we create the relevant global cache subdirectory if it does not
496
+ # exist and copy the spec from the local cache to the global cache.
497
+ #
498
+ # @param [Specification] spec
499
+ # the spec we want to copy to the global cache.
500
+ #
501
+ # @param [String] local_cache_path
502
+ # the local directory from which we want to copy the .gem.
503
+ #
504
+ def cache_globally(spec, local_cache_path)
505
+ return unless cache_path = download_cache_path(spec)
506
+ return if cache_path.exist?
507
+
508
+ SharedHelpers.filesystem_access(cache_path.dirname, &:mkpath)
509
+ SharedHelpers.filesystem_access(cache_path) do
510
+ FileUtils.cp(local_cache_path, cache_path)
511
+ end
512
+ end
513
+
514
+ # Returns the global cache path of the calling Rubygems::Source object.
515
+ #
516
+ # Note that the Source determines the path's subdirectory. We use this
517
+ # subdirectory in the global cache path so that gems with the same name
518
+ # -- and possibly different versions -- from different sources are saved
519
+ # to their respective subdirectories and do not override one another.
520
+ #
521
+ # @param [Gem::Specification] specification
522
+ #
523
+ # @return [Pathname] The global cache path.
524
+ #
525
+ def download_cache_path(spec)
526
+ return unless Bundler.feature_flag.global_gem_cache?
527
+ return unless remote = spec.remote
528
+ return unless cache_slug = remote.cache_slug
529
+
530
+ Bundler.user_cache.join("gems", cache_slug, spec.file_name)
531
+ end
532
+
533
+ def extension_cache_slug(spec)
534
+ return unless remote = spec.remote
535
+ remote.cache_slug
536
+ end
460
537
  end
461
538
  end
462
539
  end
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bundler
3
4
  class Source
4
5
  autoload :Gemspec, "bundler/source/gemspec"
5
6
  autoload :Git, "bundler/source/git"
7
+ autoload :Metadata, "bundler/source/metadata"
6
8
  autoload :Path, "bundler/source/path"
7
9
  autoload :Rubygems, "bundler/source/rubygems"
8
10
 
@@ -31,6 +33,15 @@ module Bundler
31
33
  spec.source == self
32
34
  end
33
35
 
36
+ # it's possible that gems from one source depend on gems from some
37
+ # other source, so now we download gemspecs and iterate over those
38
+ # dependencies, looking for gems we don't have info on yet.
39
+ def double_check_for(*); end
40
+
41
+ def dependency_names_to_double_check
42
+ specs.dependency_names
43
+ end
44
+
34
45
  def include?(other)
35
46
  other == self
36
47
  end
@@ -39,6 +50,19 @@ module Bundler
39
50
  "#<#{self.class}:0x#{object_id} #{self}>"
40
51
  end
41
52
 
53
+ def path?
54
+ instance_of?(Bundler::Source::Path)
55
+ end
56
+
57
+ def extension_cache_path(spec)
58
+ return unless Bundler.feature_flag.global_gem_cache?
59
+ return unless source_slug = extension_cache_slug(spec)
60
+ Bundler.user_cache.join(
61
+ "extensions", Gem::Platform.local.to_s, Bundler.ruby_scope,
62
+ source_slug, spec.full_name
63
+ )
64
+ end
65
+
42
66
  private
43
67
 
44
68
  def version_color(spec_version, locked_spec_version)
@@ -54,5 +78,17 @@ module Bundler
54
78
  def earlier_version?(spec_version, locked_spec_version)
55
79
  Gem::Version.new(spec_version) < Gem::Version.new(locked_spec_version)
56
80
  end
81
+
82
+ def print_using_message(message)
83
+ if !message.include?("(was ") && Bundler.feature_flag.suppress_install_using_messages?
84
+ Bundler.ui.debug message
85
+ else
86
+ Bundler.ui.info message
87
+ end
88
+ end
89
+
90
+ def extension_cache_slug(_)
91
+ nil
92
+ end
57
93
  end
58
94
  end
@@ -1,16 +1,21 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bundler
3
4
  class SourceList
4
5
  attr_reader :path_sources,
5
6
  :git_sources,
6
- :plugin_sources
7
+ :plugin_sources,
8
+ :global_rubygems_source,
9
+ :metadata_source
7
10
 
8
11
  def initialize
9
- @path_sources = []
10
- @git_sources = []
11
- @plugin_sources = []
12
- @rubygems_aggregate = Source::Rubygems.new
13
- @rubygems_sources = []
12
+ @path_sources = []
13
+ @git_sources = []
14
+ @plugin_sources = []
15
+ @global_rubygems_source = nil
16
+ @rubygems_aggregate = rubygems_aggregate_class.new
17
+ @rubygems_sources = []
18
+ @metadata_source = Source::Metadata.new
14
19
  end
15
20
 
16
21
  def add_path_source(options = {})
@@ -35,13 +40,28 @@ module Bundler
35
40
  add_source_to_list Plugin.source(source).new(options), @plugin_sources
36
41
  end
37
42
 
43
+ def global_rubygems_source=(uri)
44
+ if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
45
+ @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
46
+ end
47
+ add_rubygems_remote(uri)
48
+ end
49
+
38
50
  def add_rubygems_remote(uri)
51
+ if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
52
+ return if Bundler.feature_flag.disable_multisource?
53
+ raise InvalidOption, "`lockfile_uses_separate_rubygems_sources` cannot be set without `disable_multisource` being set"
54
+ end
39
55
  @rubygems_aggregate.add_remote(uri)
40
56
  @rubygems_aggregate
41
57
  end
42
58
 
59
+ def default_source
60
+ global_rubygems_source || @rubygems_aggregate
61
+ end
62
+
43
63
  def rubygems_sources
44
- @rubygems_sources + [@rubygems_aggregate]
64
+ @rubygems_sources + [default_source]
45
65
  end
46
66
 
47
67
  def rubygems_remotes
@@ -49,18 +69,25 @@ module Bundler
49
69
  end
50
70
 
51
71
  def all_sources
52
- path_sources + git_sources + plugin_sources + rubygems_sources
72
+ path_sources + git_sources + plugin_sources + rubygems_sources + [metadata_source]
53
73
  end
54
74
 
55
75
  def get(source)
56
- source_list_for(source).find {|s| source == s }
76
+ source_list_for(source).find {|s| equal_source?(source, s) || equivalent_source?(source, s) }
57
77
  end
58
78
 
59
79
  def lock_sources
60
- lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
61
- lock_sources << combine_rubygems_sources
80
+ if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
81
+ [[default_source], @rubygems_sources, git_sources, path_sources, plugin_sources].map do |sources|
82
+ sources.sort_by(&:to_s)
83
+ end.flatten(1)
84
+ else
85
+ lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
86
+ lock_sources << combine_rubygems_sources
87
+ end
62
88
  end
63
89
 
90
+ # Returns true if there are changes
64
91
  def replace_sources!(replacement_sources)
65
92
  return true if replacement_sources.empty?
66
93
 
@@ -70,13 +97,14 @@ module Bundler
70
97
  end
71
98
  end
72
99
 
73
- replacement_rubygems =
100
+ replacement_rubygems = !Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? &&
74
101
  replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
75
102
  @rubygems_aggregate = replacement_rubygems if replacement_rubygems
76
103
 
77
- # Return true if there were changes
78
- lock_sources.to_set != replacement_sources.to_set ||
79
- rubygems_remotes.to_set != replacement_rubygems.remotes.to_set
104
+ return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
105
+ return true if replacement_rubygems && rubygems_remotes.to_set != replacement_rubygems.remotes.to_set
106
+
107
+ false
80
108
  end
81
109
 
82
110
  def cached!
@@ -93,6 +121,10 @@ module Bundler
93
121
 
94
122
  private
95
123
 
124
+ def rubygems_aggregate_class
125
+ Source::Rubygems
126
+ end
127
+
96
128
  def add_source_to_list(source, list)
97
129
  list.unshift(source).uniq!
98
130
  source
@@ -122,5 +154,33 @@ module Bundler
122
154
  "protocol to keep your data secure."
123
155
  end
124
156
  end
157
+
158
+ def equal_sources?(lock_sources, replacement_sources)
159
+ lock_sources.to_set == replacement_sources.to_set
160
+ end
161
+
162
+ def equal_source?(source, other_source)
163
+ source == other_source
164
+ end
165
+
166
+ def equivalent_source?(source, other_source)
167
+ return false unless Bundler.settings[:allow_deployment_source_credential_changes] && source.is_a?(Source::Rubygems)
168
+
169
+ equivalent_rubygems_sources?([source], [other_source])
170
+ end
171
+
172
+ def equivalent_sources?(lock_sources, replacement_sources)
173
+ return false unless Bundler.settings[:allow_deployment_source_credential_changes]
174
+
175
+ lock_rubygems_sources, lock_other_sources = lock_sources.partition {|s| s.is_a?(Source::Rubygems) }
176
+ replacement_rubygems_sources, replacement_other_sources = replacement_sources.partition {|s| s.is_a?(Source::Rubygems) }
177
+
178
+ equivalent_rubygems_sources?(lock_rubygems_sources, replacement_rubygems_sources) && equal_sources?(lock_other_sources, replacement_other_sources)
179
+ end
180
+
181
+ def equivalent_rubygems_sources?(lock_sources, replacement_sources)
182
+ actual_remotes = replacement_sources.map(&:remotes).flatten.uniq
183
+ lock_sources.all? {|s| s.equivalent_remotes?(actual_remotes) }
184
+ end
125
185
  end
126
186
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "tsort"
3
4
  require "forwardable"
4
5
  require "set"
@@ -36,7 +37,10 @@ module Bundler
36
37
  elsif check
37
38
  return false
38
39
  elsif raise_on_missing
39
- raise "Unable to find a spec satisfying #{dep} in the set. Perhaps the lockfile is corrupted?"
40
+ others = lookup[dep.name] if match_current_platform
41
+ message = "Unable to find a spec satisfying #{dep} in the set. Perhaps the lockfile is corrupted?"
42
+ message += " Found #{others.join(", ")} that did not match the current platform." if others && !others.empty?
43
+ raise GemNotFound, message
40
44
  end
41
45
  end
42
46
 
@@ -76,7 +80,7 @@ module Bundler
76
80
  end
77
81
 
78
82
  def materialize(deps, missing_specs = nil)
79
- materialized = self.for(deps, [], false, true, missing_specs).to_a
83
+ materialized = self.for(deps, [], false, true, !missing_specs).to_a
80
84
  deps = materialized.map(&:name).uniq
81
85
  materialized.map! do |s|
82
86
  next s unless s.is_a?(LazySpecification)
@@ -109,9 +113,10 @@ module Bundler
109
113
 
110
114
  def merge(set)
111
115
  arr = sorted.dup
112
- set.each do |s|
113
- next if arr.any? {|s2| s2.name == s.name && s2.version == s.version && s2.platform == s.platform }
114
- arr << s
116
+ set.each do |set_spec|
117
+ full_name = set_spec.full_name
118
+ next if arr.any? {|spec| spec.full_name == full_name }
119
+ arr << set_spec
115
120
  end
116
121
  SpecSet.new(arr)
117
122
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require "fileutils"
2
+
3
+ require "bundler/vendored_fileutils"
3
4
  require "net/https"
4
5
  require "openssl"
5
6
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "bundler/remote_specification"
3
4
 
4
5
  module Bundler
@@ -0,0 +1 @@
1
+ # Ignore all files in this directory
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env <%= Bundler.settings[:shebang] || RbConfig::CONFIG["ruby_install_name"] %>
2
2
  # frozen_string_literal: true
3
+
3
4
  #
4
5
  # This file was generated by Bundler.
5
6
  #
@@ -11,6 +12,17 @@ require "pathname"
11
12
  ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../<%= relative_gemfile_path %>",
12
13
  Pathname.new(__FILE__).realpath)
13
14
 
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
14
26
  require "rubygems"
15
27
  require "bundler/setup"
16
28