bundler 2.2.16 → 2.4.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (280) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +971 -7
  3. data/README.md +4 -7
  4. data/bundler.gemspec +10 -13
  5. data/exe/bundle +12 -24
  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/add.rb +1 -1
  10. data/lib/bundler/cli/binstubs.rb +6 -2
  11. data/lib/bundler/cli/cache.rb +1 -1
  12. data/lib/bundler/cli/check.rb +5 -3
  13. data/lib/bundler/cli/common.rb +6 -2
  14. data/lib/bundler/cli/config.rb +10 -1
  15. data/lib/bundler/cli/console.rb +2 -2
  16. data/lib/bundler/cli/doctor.rb +22 -5
  17. data/lib/bundler/cli/exec.rb +1 -6
  18. data/lib/bundler/cli/gem.rb +147 -35
  19. data/lib/bundler/cli/info.rb +28 -7
  20. data/lib/bundler/cli/init.rb +6 -2
  21. data/lib/bundler/cli/install.rb +26 -58
  22. data/lib/bundler/cli/issue.rb +4 -3
  23. data/lib/bundler/cli/list.rb +7 -1
  24. data/lib/bundler/cli/lock.rb +11 -4
  25. data/lib/bundler/cli/open.rb +7 -6
  26. data/lib/bundler/cli/outdated.rb +23 -17
  27. data/lib/bundler/cli/platform.rb +8 -6
  28. data/lib/bundler/cli/remove.rb +1 -2
  29. data/lib/bundler/cli/show.rb +1 -1
  30. data/lib/bundler/cli/update.rb +17 -8
  31. data/lib/bundler/cli/viz.rb +1 -1
  32. data/lib/bundler/cli.rb +95 -65
  33. data/lib/bundler/compact_index_client/cache.rb +1 -10
  34. data/lib/bundler/compact_index_client/updater.rb +56 -43
  35. data/lib/bundler/compact_index_client.rb +2 -8
  36. data/lib/bundler/constants.rb +1 -1
  37. data/lib/bundler/current_ruby.rb +19 -6
  38. data/lib/bundler/definition.rb +386 -419
  39. data/lib/bundler/dependency.rb +24 -71
  40. data/lib/bundler/digest.rb +71 -0
  41. data/lib/bundler/dsl.rb +48 -63
  42. data/lib/bundler/endpoint_specification.rb +15 -13
  43. data/lib/bundler/env.rb +3 -3
  44. data/lib/bundler/environment_preserver.rb +7 -3
  45. data/lib/bundler/errors.rb +30 -14
  46. data/lib/bundler/feature_flag.rb +0 -5
  47. data/lib/bundler/fetcher/base.rb +6 -8
  48. data/lib/bundler/fetcher/compact_index.rb +21 -28
  49. data/lib/bundler/fetcher/dependency.rb +2 -6
  50. data/lib/bundler/fetcher/downloader.rb +12 -10
  51. data/lib/bundler/fetcher/index.rb +1 -29
  52. data/lib/bundler/fetcher.rb +35 -30
  53. data/lib/bundler/force_platform.rb +18 -0
  54. data/lib/bundler/friendly_errors.rb +26 -39
  55. data/lib/bundler/gem_helper.rb +10 -22
  56. data/lib/bundler/gem_helpers.rb +9 -2
  57. data/lib/bundler/gem_version_promoter.rb +53 -98
  58. data/lib/bundler/graph.rb +3 -3
  59. data/lib/bundler/index.rb +14 -57
  60. data/lib/bundler/injector.rb +20 -6
  61. data/lib/bundler/inline.rb +10 -22
  62. data/lib/bundler/installer/gem_installer.rb +16 -21
  63. data/lib/bundler/installer/parallel_installer.rb +4 -34
  64. data/lib/bundler/installer/standalone.rb +53 -17
  65. data/lib/bundler/installer.rb +26 -58
  66. data/lib/bundler/lazy_specification.rb +72 -55
  67. data/lib/bundler/lockfile_generator.rb +3 -3
  68. data/lib/bundler/lockfile_parser.rb +31 -45
  69. data/lib/bundler/man/bundle-add.1 +21 -5
  70. data/lib/bundler/man/bundle-add.1.ronn +16 -4
  71. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  72. data/lib/bundler/man/bundle-cache.1 +9 -3
  73. data/lib/bundler/man/bundle-cache.1.ronn +9 -2
  74. data/lib/bundler/man/bundle-check.1 +1 -1
  75. data/lib/bundler/man/bundle-clean.1 +2 -2
  76. data/lib/bundler/man/bundle-clean.1.ronn +1 -1
  77. data/lib/bundler/man/bundle-config.1 +50 -26
  78. data/lib/bundler/man/bundle-config.1.ronn +47 -32
  79. data/lib/bundler/man/bundle-console.1 +53 -0
  80. data/lib/bundler/man/bundle-console.1.ronn +44 -0
  81. data/lib/bundler/man/bundle-doctor.1 +1 -1
  82. data/lib/bundler/man/bundle-exec.1 +6 -6
  83. data/lib/bundler/man/bundle-exec.1.ronn +6 -6
  84. data/lib/bundler/man/bundle-gem.1 +37 -34
  85. data/lib/bundler/man/bundle-gem.1.ronn +21 -5
  86. data/lib/bundler/man/bundle-help.1 +13 -0
  87. data/lib/bundler/man/bundle-help.1.ronn +12 -0
  88. data/lib/bundler/man/bundle-info.1 +3 -3
  89. data/lib/bundler/man/bundle-info.1.ronn +3 -3
  90. data/lib/bundler/man/bundle-init.1 +5 -1
  91. data/lib/bundler/man/bundle-init.1.ronn +2 -0
  92. data/lib/bundler/man/bundle-inject.1 +5 -2
  93. data/lib/bundler/man/bundle-inject.1.ronn +3 -1
  94. data/lib/bundler/man/bundle-install.1 +6 -31
  95. data/lib/bundler/man/bundle-install.1.ronn +8 -31
  96. data/lib/bundler/man/bundle-list.1 +1 -1
  97. data/lib/bundler/man/bundle-lock.1 +1 -1
  98. data/lib/bundler/man/bundle-open.1 +22 -2
  99. data/lib/bundler/man/bundle-open.1.ronn +9 -1
  100. data/lib/bundler/man/bundle-outdated.1 +15 -18
  101. data/lib/bundler/man/bundle-outdated.1.ronn +13 -19
  102. data/lib/bundler/man/bundle-platform.1 +16 -6
  103. data/lib/bundler/man/bundle-platform.1.ronn +14 -7
  104. data/lib/bundler/man/bundle-plugin.1 +81 -0
  105. data/lib/bundler/man/bundle-plugin.1.ronn +59 -0
  106. data/lib/bundler/man/bundle-pristine.1 +1 -1
  107. data/lib/bundler/man/bundle-remove.1 +1 -1
  108. data/lib/bundler/man/bundle-show.1 +1 -1
  109. data/lib/bundler/man/bundle-update.1 +5 -5
  110. data/lib/bundler/man/bundle-update.1.ronn +5 -4
  111. data/lib/bundler/man/bundle-version.1 +35 -0
  112. data/lib/bundler/man/bundle-version.1.ronn +24 -0
  113. data/lib/bundler/man/bundle-viz.1 +4 -1
  114. data/lib/bundler/man/bundle-viz.1.ronn +2 -0
  115. data/lib/bundler/man/bundle.1 +15 -10
  116. data/lib/bundler/man/bundle.1.ronn +12 -7
  117. data/lib/bundler/man/gemfile.5 +131 -81
  118. data/lib/bundler/man/gemfile.5.ronn +111 -85
  119. data/lib/bundler/man/index.txt +4 -0
  120. data/lib/bundler/match_metadata.rb +13 -0
  121. data/lib/bundler/match_platform.rb +0 -1
  122. data/lib/bundler/match_remote_metadata.rb +29 -0
  123. data/lib/bundler/mirror.rb +5 -7
  124. data/lib/bundler/plugin/api/source.rb +17 -8
  125. data/lib/bundler/plugin/index.rb +9 -6
  126. data/lib/bundler/plugin/installer/git.rb +0 -4
  127. data/lib/bundler/plugin/installer/rubygems.rb +0 -8
  128. data/lib/bundler/plugin/installer.rb +9 -4
  129. data/lib/bundler/plugin.rb +30 -9
  130. data/lib/bundler/process_lock.rb +1 -1
  131. data/lib/bundler/remote_specification.rb +7 -5
  132. data/lib/bundler/resolver/base.rb +107 -0
  133. data/lib/bundler/resolver/candidate.rb +94 -0
  134. data/lib/bundler/resolver/incompatibility.rb +15 -0
  135. data/lib/bundler/resolver/package.rb +72 -0
  136. data/lib/bundler/resolver/root.rb +25 -0
  137. data/lib/bundler/resolver/spec_group.rb +42 -94
  138. data/lib/bundler/resolver.rb +331 -381
  139. data/lib/bundler/retry.rb +1 -1
  140. data/lib/bundler/ruby_dsl.rb +7 -1
  141. data/lib/bundler/ruby_version.rb +8 -21
  142. data/lib/bundler/rubygems_ext.rb +175 -34
  143. data/lib/bundler/rubygems_gem_installer.rb +46 -14
  144. data/lib/bundler/rubygems_integration.rb +57 -108
  145. data/lib/bundler/runtime.rb +20 -18
  146. data/lib/bundler/safe_marshal.rb +31 -0
  147. data/lib/bundler/self_manager.rb +168 -0
  148. data/lib/bundler/settings.rb +101 -30
  149. data/lib/bundler/setup.rb +5 -2
  150. data/lib/bundler/shared_helpers.rb +17 -32
  151. data/lib/bundler/source/git/git_proxy.rb +242 -77
  152. data/lib/bundler/source/git.rb +82 -41
  153. data/lib/bundler/source/metadata.rb +3 -4
  154. data/lib/bundler/source/path/installer.rb +1 -22
  155. data/lib/bundler/source/path.rb +7 -7
  156. data/lib/bundler/source/rubygems.rb +158 -212
  157. data/lib/bundler/source/rubygems_aggregate.rb +68 -0
  158. data/lib/bundler/source.rb +19 -5
  159. data/lib/bundler/source_list.rb +91 -52
  160. data/lib/bundler/source_map.rb +71 -0
  161. data/lib/bundler/spec_set.rb +69 -57
  162. data/lib/bundler/stub_specification.rb +5 -3
  163. data/lib/bundler/templates/Executable +3 -5
  164. data/lib/bundler/templates/Executable.bundler +11 -16
  165. data/lib/bundler/templates/Executable.standalone +4 -4
  166. data/lib/bundler/templates/Gemfile +0 -2
  167. data/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
  168. data/lib/bundler/templates/newgem/Gemfile.tt +8 -2
  169. data/lib/bundler/templates/newgem/README.md.tt +7 -11
  170. data/lib/bundler/templates/newgem/Rakefile.tt +27 -3
  171. data/lib/bundler/templates/newgem/bin/console.tt +0 -4
  172. data/lib/bundler/templates/newgem/circleci/config.yml.tt +12 -0
  173. data/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +15 -0
  174. data/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +10 -0
  175. data/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
  176. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +1 -1
  177. data/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +12 -0
  178. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +24 -3
  179. data/lib/bundler/templates/newgem/gitignore.tt +3 -0
  180. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +13 -4
  181. data/lib/bundler/templates/newgem/newgem.gemspec.tt +27 -18
  182. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  183. data/lib/bundler/templates/newgem/standard.yml.tt +3 -0
  184. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  185. data/lib/bundler/ui/rg_proxy.rb +1 -1
  186. data/lib/bundler/ui/shell.rb +36 -13
  187. data/lib/bundler/ui/silent.rb +21 -5
  188. data/lib/bundler/uri_normalizer.rb +23 -0
  189. data/lib/bundler/vendor/.document +1 -0
  190. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  191. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  192. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  193. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +56 -0
  194. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +41 -74
  195. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  196. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1351 -409
  197. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  198. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  199. data/lib/bundler/vendor/pub_grub/LICENSE.txt +21 -0
  200. data/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
  201. data/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +189 -0
  202. data/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
  203. data/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +150 -0
  204. data/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb +43 -0
  205. data/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
  206. data/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
  207. data/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb +19 -0
  208. data/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +60 -0
  209. data/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
  210. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
  211. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +129 -0
  212. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +411 -0
  213. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +248 -0
  214. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb +178 -0
  215. data/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +31 -0
  216. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  217. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +5 -5
  218. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -2
  219. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -2
  220. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  221. data/lib/bundler/vendor/thor/lib/thor/error.rb +9 -4
  222. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +19 -1
  223. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +23 -5
  224. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  225. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  226. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  227. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  228. data/lib/bundler/vendor/tsort/lib/tsort.rb +452 -0
  229. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  230. data/lib/bundler/vendor/uri/lib/uri/common.rb +76 -91
  231. data/lib/bundler/vendor/uri/lib/uri/file.rb +7 -1
  232. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +2 -2
  233. data/lib/bundler/vendor/uri/lib/uri/generic.rb +32 -13
  234. data/lib/bundler/vendor/uri/lib/uri/http.rb +40 -3
  235. data/lib/bundler/vendor/uri/lib/uri/https.rb +2 -2
  236. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +2 -2
  237. data/lib/bundler/vendor/uri/lib/uri/ldaps.rb +2 -1
  238. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +2 -3
  239. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +16 -23
  240. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +12 -18
  241. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  242. data/lib/bundler/vendor/uri/lib/uri/ws.rb +83 -0
  243. data/lib/bundler/vendor/uri/lib/uri/wss.rb +23 -0
  244. data/lib/bundler/vendor/uri/lib/uri.rb +3 -3
  245. data/lib/bundler/vendored_persistent.rb +1 -33
  246. data/lib/bundler/{vendored_molinillo.rb → vendored_pub_grub.rb} +1 -1
  247. data/lib/bundler/{vendored_tmpdir.rb → vendored_tsort.rb} +1 -1
  248. data/lib/bundler/version.rb +5 -1
  249. data/lib/bundler/worker.rb +24 -11
  250. data/lib/bundler.rb +66 -110
  251. metadata +70 -41
  252. data/lib/bundler/dep_proxy.rb +0 -55
  253. data/lib/bundler/gemdeps.rb +0 -29
  254. data/lib/bundler/psyched_yaml.rb +0 -22
  255. data/lib/bundler/templates/gems.rb +0 -8
  256. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +0 -5
  257. data/lib/bundler/templates/newgem/travis.yml.tt +0 -6
  258. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
  259. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
  260. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -88
  261. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
  262. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
  263. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
  264. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
  265. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
  266. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
  267. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
  268. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
  269. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -164
  270. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +0 -255
  271. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +0 -143
  272. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
  273. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +0 -112
  274. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +0 -67
  275. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +0 -839
  276. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +0 -46
  277. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +0 -58
  278. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +0 -11
  279. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +0 -154
  280. data/lib/bundler/version_ranges.rb +0 -122
@@ -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
@@ -7,6 +7,7 @@ module Bundler
7
7
  autoload :Metadata, File.expand_path("source/metadata", __dir__)
8
8
  autoload :Path, File.expand_path("source/path", __dir__)
9
9
  autoload :Rubygems, File.expand_path("source/rubygems", __dir__)
10
+ autoload :RubygemsAggregate, File.expand_path("source/rubygems_aggregate", __dir__)
10
11
 
11
12
  attr_accessor :dependency_names
12
13
 
@@ -14,13 +15,12 @@ module Bundler
14
15
  specs.unmet_dependency_names
15
16
  end
16
17
 
17
- def version_message(spec)
18
+ def version_message(spec, locked_spec = nil)
18
19
  message = "#{spec.name} #{spec.version}"
19
20
  message += " (#{spec.platform})" if spec.platform != Gem::Platform::RUBY && !spec.platform.nil?
20
21
 
21
- if Bundler.locked_gems
22
- locked_spec = Bundler.locked_gems.specs.find {|s| s.name == spec.name }
23
- locked_spec_version = locked_spec.version if locked_spec
22
+ if locked_spec
23
+ locked_spec_version = locked_spec.version
24
24
  if locked_spec_version && spec.version != locked_spec_version
25
25
  message += Bundler.ui.add_color(" (was #{locked_spec_version})", version_color(spec.version, locked_spec_version))
26
26
  end
@@ -35,10 +35,16 @@ module Bundler
35
35
 
36
36
  def local!; end
37
37
 
38
+ def local_only!; end
39
+
38
40
  def cached!; end
39
41
 
40
42
  def remote!; end
41
43
 
44
+ def add_dependency_names(names)
45
+ @dependency_names = Array(dependency_names) | Array(names)
46
+ end
47
+
42
48
  # it's possible that gems from one source depend on gems from some
43
49
  # other source, so now we download gemspecs and iterate over those
44
50
  # dependencies, looking for gems we don't have info on yet.
@@ -48,6 +54,10 @@ module Bundler
48
54
  specs.dependency_names
49
55
  end
50
56
 
57
+ def spec_names
58
+ specs.spec_names
59
+ end
60
+
51
61
  def include?(other)
52
62
  other == self
53
63
  end
@@ -56,6 +66,10 @@ module Bundler
56
66
  "#<#{self.class}:0x#{object_id} #{self}>"
57
67
  end
58
68
 
69
+ def identifier
70
+ to_s
71
+ end
72
+
59
73
  def path?
60
74
  instance_of?(Bundler::Source::Path)
61
75
  end
@@ -86,7 +100,7 @@ module Bundler
86
100
  end
87
101
 
88
102
  def print_using_message(message)
89
- if !message.include?("(was ") && Bundler.feature_flag.suppress_install_using_messages?
103
+ if !message.include?("(was ")
90
104
  Bundler.ui.debug message
91
105
  else
92
106
  Bundler.ui.info message
@@ -21,15 +21,24 @@ module Bundler
21
21
  @rubygems_sources = []
22
22
  @metadata_source = Source::Metadata.new
23
23
 
24
- @disable_multisource = true
24
+ @merged_gem_lockfile_sections = false
25
25
  end
26
26
 
27
- def disable_multisource?
28
- @disable_multisource
27
+ def merged_gem_lockfile_sections?
28
+ @merged_gem_lockfile_sections
29
29
  end
30
30
 
31
- def merged_gem_lockfile_sections!
32
- @disable_multisource = false
31
+ def merged_gem_lockfile_sections!(replacement_source)
32
+ @merged_gem_lockfile_sections = true
33
+ @global_rubygems_source = replacement_source
34
+ end
35
+
36
+ def aggregate_global_source?
37
+ global_rubygems_source.multiple_remotes?
38
+ end
39
+
40
+ def implicit_global_source?
41
+ global_rubygems_source.no_remotes?
33
42
  end
34
43
 
35
44
  def add_path_source(options = {})
@@ -49,18 +58,17 @@ module Bundler
49
58
  end
50
59
 
51
60
  def add_rubygems_source(options = {})
52
- add_source_to_list Source::Rubygems.new(options), @rubygems_sources
61
+ new_source = Source::Rubygems.new(options)
62
+ return @global_rubygems_source if @global_rubygems_source == new_source
63
+
64
+ add_source_to_list new_source, @rubygems_sources
53
65
  end
54
66
 
55
67
  def add_plugin_source(source, options = {})
56
68
  add_source_to_list Plugin.source(source).new(options), @plugin_sources
57
69
  end
58
70
 
59
- def global_rubygems_source=(uri)
60
- @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri, "allow_local" => true)
61
- end
62
-
63
- def add_rubygems_remote(uri)
71
+ def add_global_rubygems_remote(uri)
64
72
  global_rubygems_source.add_remote(uri)
65
73
  global_rubygems_source
66
74
  end
@@ -70,7 +78,11 @@ module Bundler
70
78
  end
71
79
 
72
80
  def rubygems_sources
73
- @rubygems_sources + [global_rubygems_source]
81
+ non_global_rubygems_sources + [global_rubygems_source]
82
+ end
83
+
84
+ def non_global_rubygems_sources
85
+ @rubygems_sources
74
86
  end
75
87
 
76
88
  def rubygems_remotes
@@ -81,36 +93,51 @@ module Bundler
81
93
  path_sources + git_sources + plugin_sources + rubygems_sources + [metadata_source]
82
94
  end
83
95
 
96
+ def non_default_explicit_sources
97
+ all_sources - [default_source, metadata_source]
98
+ end
99
+
84
100
  def get(source)
85
- source_list_for(source).find {|s| equal_source?(source, s) || equivalent_source?(source, s) }
101
+ source_list_for(source).find {|s| equivalent_source?(source, s) }
86
102
  end
87
103
 
88
104
  def lock_sources
89
- lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
90
- if disable_multisource?
91
- lock_sources + rubygems_sources.sort_by(&:to_s).uniq
105
+ lock_other_sources + lock_rubygems_sources
106
+ end
107
+
108
+ def lock_other_sources
109
+ (path_sources + git_sources + plugin_sources).sort_by(&:identifier)
110
+ end
111
+
112
+ def lock_rubygems_sources
113
+ if merged_gem_lockfile_sections?
114
+ [combine_rubygems_sources]
92
115
  else
93
- lock_sources << combine_rubygems_sources
116
+ rubygems_sources.sort_by(&:identifier)
94
117
  end
95
118
  end
96
119
 
97
120
  # Returns true if there are changes
98
121
  def replace_sources!(replacement_sources)
99
- return true if replacement_sources.empty?
122
+ return false if replacement_sources.empty?
100
123
 
101
- [path_sources, git_sources, plugin_sources].each do |source_list|
102
- source_list.map! do |source|
103
- replacement_sources.find {|s| s == source } || source
104
- end
105
- end
124
+ @rubygems_sources, @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
125
+ @global_rubygems_source = global_replacement_source(replacement_sources)
106
126
 
107
- replacement_rubygems = !disable_multisource? &&
108
- replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
109
- @global_rubygems_source = replacement_rubygems if replacement_rubygems
127
+ different_sources?(lock_sources, replacement_sources)
128
+ end
110
129
 
111
- return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
130
+ # Returns true if there are changes
131
+ def expired_sources?(replacement_sources)
132
+ return false if replacement_sources.empty?
112
133
 
113
- false
134
+ lock_sources = dup_with_replaced_sources(replacement_sources).lock_sources
135
+
136
+ different_sources?(lock_sources, replacement_sources)
137
+ end
138
+
139
+ def local_only!
140
+ all_sources.each(&:local_only!)
114
141
  end
115
142
 
116
143
  def cached!
@@ -123,6 +150,38 @@ module Bundler
123
150
 
124
151
  private
125
152
 
153
+ def dup_with_replaced_sources(replacement_sources)
154
+ new_source_list = dup
155
+ new_source_list.replace_sources!(replacement_sources)
156
+ new_source_list
157
+ end
158
+
159
+ def map_sources(replacement_sources)
160
+ rubygems, git, plugin = [@rubygems_sources, @git_sources, @plugin_sources].map do |sources|
161
+ sources.map do |source|
162
+ replacement_sources.find {|s| s == source } || source
163
+ end
164
+ end
165
+
166
+ path = @path_sources.map do |source|
167
+ replacement_sources.find {|s| s == (source.is_a?(Source::Gemspec) ? source.as_path_source : source) } || source
168
+ end
169
+
170
+ [rubygems, path, git, plugin]
171
+ end
172
+
173
+ def global_replacement_source(replacement_sources)
174
+ replacement_source = replacement_sources.find {|s| s == global_rubygems_source }
175
+ return global_rubygems_source unless replacement_source
176
+
177
+ replacement_source.local!
178
+ replacement_source
179
+ end
180
+
181
+ def different_sources?(lock_sources, replacement_sources)
182
+ !equivalent_sources?(lock_sources, replacement_sources)
183
+ end
184
+
126
185
  def rubygems_aggregate_class
127
186
  Source::Rubygems
128
187
  end
@@ -149,7 +208,7 @@ module Bundler
149
208
  def warn_on_git_protocol(source)
150
209
  return if Bundler.settings["git.allow_insecure"]
151
210
 
152
- if source.uri =~ /^git\:/
211
+ if /^git\:/.match?(source.uri)
153
212
  Bundler.ui.warn "The git source `#{source.uri}` uses the `git` protocol, " \
154
213
  "which transmits data without encryption. Disable this warning with " \
155
214
  "`bundle config set --local git.allow_insecure true`, or switch to the `https` " \
@@ -157,32 +216,12 @@ module Bundler
157
216
  end
158
217
  end
159
218
 
160
- def equal_sources?(lock_sources, replacement_sources)
161
- lock_sources.sort_by(&:to_s) == replacement_sources.sort_by(&:to_s)
162
- end
163
-
164
- def equal_source?(source, other_source)
165
- source == other_source
166
- end
167
-
168
- def equivalent_source?(source, other_source)
169
- return false unless Bundler.settings[:allow_deployment_source_credential_changes] && source.is_a?(Source::Rubygems)
170
-
171
- equivalent_rubygems_sources?([source], [other_source])
172
- end
173
-
174
219
  def equivalent_sources?(lock_sources, replacement_sources)
175
- return false unless Bundler.settings[:allow_deployment_source_credential_changes]
176
-
177
- lock_rubygems_sources, lock_other_sources = lock_sources.partition {|s| s.is_a?(Source::Rubygems) }
178
- replacement_rubygems_sources, replacement_other_sources = replacement_sources.partition {|s| s.is_a?(Source::Rubygems) }
179
-
180
- equivalent_rubygems_sources?(lock_rubygems_sources, replacement_rubygems_sources) && equal_sources?(lock_other_sources, replacement_other_sources)
220
+ lock_sources.sort_by(&:identifier) == replacement_sources.sort_by(&:identifier)
181
221
  end
182
222
 
183
- def equivalent_rubygems_sources?(lock_sources, replacement_sources)
184
- actual_remotes = replacement_sources.map(&:remotes).flatten.uniq
185
- lock_sources.all? {|s| s.equivalent_remotes?(actual_remotes) }
223
+ def equivalent_source?(source, other_source)
224
+ source == other_source
186
225
  end
187
226
  end
188
227
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class SourceMap
5
+ attr_reader :sources, :dependencies, :locked_specs
6
+
7
+ def initialize(sources, dependencies, locked_specs)
8
+ @sources = sources
9
+ @dependencies = dependencies
10
+ @locked_specs = locked_specs
11
+ end
12
+
13
+ def pinned_spec_names(skip = nil)
14
+ direct_requirements.reject {|_, source| source == skip }.keys
15
+ end
16
+
17
+ def all_requirements
18
+ requirements = direct_requirements.dup
19
+
20
+ unmet_deps = sources.non_default_explicit_sources.map do |source|
21
+ (source.spec_names - pinned_spec_names).each do |indirect_dependency_name|
22
+ previous_source = requirements[indirect_dependency_name]
23
+ if previous_source.nil?
24
+ requirements[indirect_dependency_name] = source
25
+ else
26
+ no_ambiguous_sources = Bundler.feature_flag.bundler_3_mode?
27
+
28
+ msg = ["The gem '#{indirect_dependency_name}' was found in multiple relevant sources."]
29
+ msg.concat [previous_source, source].map {|s| " * #{s}" }.sort
30
+ msg << "You #{no_ambiguous_sources ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
31
+ msg = msg.join("\n")
32
+
33
+ raise SecurityError, msg if no_ambiguous_sources
34
+ Bundler.ui.warn "Warning: #{msg}"
35
+ end
36
+ end
37
+
38
+ source.unmet_deps
39
+ end
40
+
41
+ sources.default_source.add_dependency_names(unmet_deps.flatten - requirements.keys)
42
+
43
+ requirements
44
+ end
45
+
46
+ def direct_requirements
47
+ @direct_requirements ||= begin
48
+ requirements = {}
49
+ default = sources.default_source
50
+ dependencies.each do |dep|
51
+ dep_source = dep.source || default
52
+ dep_source.add_dependency_names(dep.name)
53
+ requirements[dep.name] = dep_source
54
+ end
55
+ requirements
56
+ end
57
+ end
58
+
59
+ def locked_requirements
60
+ @locked_requirements ||= begin
61
+ requirements = {}
62
+ locked_specs.each do |locked_spec|
63
+ source = locked_spec.source
64
+ source.add_dependency_names(locked_spec.name)
65
+ requirements[locked_spec.name] = source
66
+ end
67
+ requirements
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,56 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "tsort"
3
+ require_relative "vendored_tsort"
4
4
 
5
5
  module Bundler
6
6
  class SpecSet
7
7
  include Enumerable
8
8
  include TSort
9
9
 
10
- def initialize(specs)
10
+ attr_reader :incomplete_specs
11
+
12
+ def initialize(specs, incomplete_specs = [])
11
13
  @specs = specs
14
+ @incomplete_specs = incomplete_specs
12
15
  end
13
16
 
14
- def for(dependencies, skip = [], check = false, match_current_platform = false, raise_on_missing = true)
15
- handled = []
16
- deps = dependencies.dup
17
+ def for(dependencies, check = false, platforms = [nil])
18
+ handled = ["bundler"].product(platforms).map {|k| [k, true] }.to_h
19
+ deps = dependencies.product(platforms)
17
20
  specs = []
18
- skip += ["bundler"]
19
21
 
20
22
  loop do
21
23
  break unless dep = deps.shift
22
- next if handled.include?(dep) || skip.include?(dep.name)
23
24
 
24
- handled << dep
25
+ name = dep[0].name
26
+ platform = dep[1]
27
+ incomplete = false
28
+
29
+ key = [name, platform]
30
+ next if handled.key?(key)
25
31
 
26
- specs_for_dep = spec_for_dependency(dep, match_current_platform)
32
+ handled[key] = true
33
+
34
+ specs_for_dep = specs_for_dependency(*dep)
27
35
  if specs_for_dep.any?
28
- specs += specs_for_dep
36
+ specs.concat(specs_for_dep)
29
37
 
30
38
  specs_for_dep.first.dependencies.each do |d|
31
39
  next if d.type == :development
32
- d = DepProxy.get_proxy(d, dep.__platform) unless match_current_platform
33
- deps << d
40
+ incomplete = true if d.name != "bundler" && lookup[d.name].empty?
41
+ deps << [d, dep[1]]
34
42
  end
35
- elsif check
36
- return false
37
- elsif raise_on_missing
38
- others = lookup[dep.name] if match_current_platform
39
- message = "Unable to find a spec satisfying #{dep} in the set. Perhaps the lockfile is corrupted?"
40
- message += " Found #{others.join(", ")} that did not match the current platform." if others && !others.empty?
41
- raise GemNotFound, message
43
+ else
44
+ incomplete = true
42
45
  end
43
- end
44
46
 
45
- if spec = lookup["bundler"].first
46
- specs << spec
47
+ if incomplete && check
48
+ @incomplete_specs += lookup[name].any? ? lookup[name] : [LazySpecification.new(name, nil, nil)]
49
+ end
47
50
  end
48
51
 
49
- check ? true : SpecSet.new(specs)
50
- end
51
-
52
- def valid_for?(deps)
53
- self.for(deps, [], true)
52
+ specs.uniq
54
53
  end
55
54
 
56
55
  def [](key)
@@ -64,6 +63,12 @@ module Bundler
64
63
  @sorted = nil
65
64
  end
66
65
 
66
+ def delete(specs)
67
+ specs.each {|spec| @specs.delete(spec) }
68
+ @lookup = nil
69
+ @sorted = nil
70
+ end
71
+
67
72
  def sort!
68
73
  self
69
74
  end
@@ -76,41 +81,39 @@ module Bundler
76
81
  lookup.dup
77
82
  end
78
83
 
79
- def materialize(deps, missing_specs = nil)
80
- materialized = self.for(deps, [], false, true, !missing_specs).to_a
81
- deps = materialized.map(&:name).uniq
82
- materialized.map! do |s|
83
- next s unless s.is_a?(LazySpecification)
84
- s.source.dependency_names = deps if s.source.respond_to?(:dependency_names=)
85
- s.source.local!
86
- spec = s.__materialize__
87
- unless spec
88
- unless missing_specs
89
- raise GemNotFound, "Could not find #{s.full_name} in any of the sources"
90
- end
91
- missing_specs << s
92
- end
93
- spec
94
- end
95
- SpecSet.new(missing_specs ? materialized.compact : materialized)
84
+ def materialize(deps)
85
+ materialized = self.for(deps, true)
86
+
87
+ SpecSet.new(materialized, incomplete_specs)
96
88
  end
97
89
 
98
90
  # Materialize for all the specs in the spec set, regardless of what platform they're for
99
91
  # This is in contrast to how for does platform filtering (and specifically different from how `materialize` calls `for` only for the current platform)
100
92
  # @return [Array<Gem::Specification>]
101
93
  def materialized_for_all_platforms
102
- names = @specs.map(&:name).uniq
103
94
  @specs.map do |s|
104
95
  next s unless s.is_a?(LazySpecification)
105
- s.source.dependency_names = names if s.source.respond_to?(:dependency_names=)
106
- s.source.local!
107
96
  s.source.remote!
108
- spec = s.__materialize__
97
+ spec = s.materialize_for_installation
109
98
  raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
110
99
  spec
111
100
  end
112
101
  end
113
102
 
103
+ def incomplete_ruby_specs?(deps)
104
+ return false if @specs.empty?
105
+
106
+ @incomplete_specs = []
107
+
108
+ self.for(deps, true, [Gem::Platform::RUBY])
109
+
110
+ @incomplete_specs.any?
111
+ end
112
+
113
+ def missing_specs
114
+ @specs.select {|s| s.is_a?(LazySpecification) }
115
+ end
116
+
114
117
  def merge(set)
115
118
  arr = sorted.dup
116
119
  set.each do |set_spec|
@@ -121,10 +124,20 @@ module Bundler
121
124
  SpecSet.new(arr)
122
125
  end
123
126
 
127
+ def -(other)
128
+ SpecSet.new(to_a - other.to_a)
129
+ end
130
+
124
131
  def find_by_name_and_platform(name, platform)
125
132
  @specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
126
133
  end
127
134
 
135
+ def delete_by_name(name)
136
+ @specs.reject! {|spec| spec.name == name }
137
+ @lookup = nil
138
+ @sorted = nil
139
+ end
140
+
128
141
  def what_required(spec)
129
142
  unless req = find {|s| s.dependencies.any? {|d| d.type == :runtime && d.name == spec.name } }
130
143
  return [spec]
@@ -162,7 +175,7 @@ module Bundler
162
175
  cgems = extract_circular_gems(error)
163
176
  raise CyclicDependencyError, "Your bundle requires gems that depend" \
164
177
  " on each other, creating an infinite loop. Please remove either" \
165
- " gem '#{cgems[1]}' or gem '#{cgems[0]}' and try again."
178
+ " gem '#{cgems[0]}' or gem '#{cgems[1]}' and try again."
166
179
  end
167
180
  end
168
181
 
@@ -173,7 +186,7 @@ module Bundler
173
186
  def lookup
174
187
  @lookup ||= begin
175
188
  lookup = Hash.new {|h, k| h[k] = [] }
176
- Index.sort_specs(@specs).reverse_each do |s|
189
+ @specs.each do |s|
177
190
  lookup[s.name] << s
178
191
  end
179
192
  lookup
@@ -185,13 +198,12 @@ module Bundler
185
198
  @specs.sort_by(&:name).each {|s| yield s }
186
199
  end
187
200
 
188
- def spec_for_dependency(dep, match_current_platform)
189
- specs_for_platforms = lookup[dep.name]
190
- if match_current_platform
191
- GemHelpers.select_best_platform_match(specs_for_platforms, Bundler.local_platform)
192
- else
193
- GemHelpers.select_best_platform_match(specs_for_platforms, dep.__platform)
194
- end
201
+ def specs_for_dependency(dep, platform)
202
+ specs_for_name = lookup[dep.name]
203
+ target_platform = dep.force_ruby_platform ? Gem::Platform::RUBY : (platform || Bundler.local_platform)
204
+ matching_specs = GemHelpers.select_best_platform_match(specs_for_name, target_platform)
205
+ matching_specs.map!(&:materialize_for_installation).compact! if platform.nil?
206
+ matching_specs
195
207
  end
196
208
 
197
209
  def tsort_each_child(s)
@@ -64,9 +64,11 @@ module Bundler
64
64
  end
65
65
 
66
66
  def full_gem_path
67
- # deleted gems can have their stubs return nil, so in that case grab the
68
- # expired path from the full spec
69
- stub.full_gem_path || method_missing(:full_gem_path)
67
+ stub.full_gem_path
68
+ end
69
+
70
+ def full_gem_path=(path)
71
+ stub.full_gem_path = path
70
72
  end
71
73
 
72
74
  def full_require_paths
@@ -8,14 +8,12 @@
8
8
  # this file is here to facilitate running it.
9
9
  #
10
10
 
11
- require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../<%= relative_gemfile_path %>",
13
- Pathname.new(__FILE__).realpath)
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("<%= relative_gemfile_path %>", __dir__)
14
12
 
15
- bundle_binstub = File.expand_path("../bundle", __FILE__)
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
16
14
 
17
15
  if File.file?(bundle_binstub)
18
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
19
17
  load(bundle_binstub)
20
18
  else
21
19
  abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.