bundler 2.1.4 → 2.2.17

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 (225) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1774 -1430
  3. data/README.md +6 -8
  4. data/bundler.gemspec +4 -4
  5. data/exe/bundle +3 -0
  6. data/lib/bundler.rb +33 -9
  7. data/lib/bundler/build_metadata.rb +3 -11
  8. data/lib/bundler/cli.rb +59 -23
  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 +2 -7
  12. data/lib/bundler/cli/clean.rb +1 -1
  13. data/lib/bundler/cli/common.rb +29 -2
  14. data/lib/bundler/cli/console.rb +1 -1
  15. data/lib/bundler/cli/doctor.rb +1 -1
  16. data/lib/bundler/cli/exec.rb +4 -4
  17. data/lib/bundler/cli/fund.rb +36 -0
  18. data/lib/bundler/cli/gem.rb +129 -28
  19. data/lib/bundler/cli/info.rb +15 -4
  20. data/lib/bundler/cli/init.rb +2 -2
  21. data/lib/bundler/cli/inject.rb +1 -1
  22. data/lib/bundler/cli/install.rb +13 -11
  23. data/lib/bundler/cli/issue.rb +2 -2
  24. data/lib/bundler/cli/list.rb +12 -10
  25. data/lib/bundler/cli/outdated.rb +88 -67
  26. data/lib/bundler/cli/plugin.rb +10 -0
  27. data/lib/bundler/cli/pristine.rb +5 -0
  28. data/lib/bundler/cli/show.rb +1 -1
  29. data/lib/bundler/cli/update.rb +3 -1
  30. data/lib/bundler/compact_index_client.rb +1 -1
  31. data/lib/bundler/compact_index_client/cache.rb +6 -14
  32. data/lib/bundler/compact_index_client/gem_parser.rb +28 -0
  33. data/lib/bundler/compact_index_client/updater.rb +13 -17
  34. data/lib/bundler/current_ruby.rb +1 -0
  35. data/lib/bundler/definition.rb +121 -131
  36. data/lib/bundler/dep_proxy.rb +16 -9
  37. data/lib/bundler/dependency.rb +3 -10
  38. data/lib/bundler/dsl.rb +40 -33
  39. data/lib/bundler/endpoint_specification.rb +1 -1
  40. data/lib/bundler/env.rb +1 -1
  41. data/lib/bundler/environment_preserver.rb +26 -2
  42. data/lib/bundler/errors.rb +1 -0
  43. data/lib/bundler/feature_flag.rb +0 -5
  44. data/lib/bundler/fetcher.rb +5 -4
  45. data/lib/bundler/fetcher/base.rb +1 -1
  46. data/lib/bundler/fetcher/compact_index.rb +1 -1
  47. data/lib/bundler/fetcher/downloader.rb +9 -5
  48. data/lib/bundler/fetcher/index.rb +3 -4
  49. data/lib/bundler/friendly_errors.rb +22 -13
  50. data/lib/bundler/gem_helper.rb +51 -18
  51. data/lib/bundler/gem_helpers.rb +36 -25
  52. data/lib/bundler/gem_version_promoter.rb +4 -4
  53. data/lib/bundler/graph.rb +1 -1
  54. data/lib/bundler/index.rb +12 -7
  55. data/lib/bundler/injector.rb +23 -5
  56. data/lib/bundler/inline.rb +3 -2
  57. data/lib/bundler/installer.rb +37 -49
  58. data/lib/bundler/installer/gem_installer.rb +3 -3
  59. data/lib/bundler/installer/parallel_installer.rb +46 -25
  60. data/lib/bundler/installer/standalone.rb +17 -2
  61. data/lib/bundler/lazy_specification.rb +45 -25
  62. data/lib/bundler/lockfile_generator.rb +1 -1
  63. data/lib/bundler/lockfile_parser.rb +4 -14
  64. data/lib/bundler/man/.document +1 -0
  65. data/{man → lib/bundler/man}/bundle-add.1 +1 -1
  66. data/{man/bundle-add.ronn → lib/bundler/man/bundle-add.1.ronn} +0 -0
  67. data/{man → lib/bundler/man}/bundle-binstubs.1 +5 -3
  68. data/{man/bundle-binstubs.ronn → lib/bundler/man/bundle-binstubs.1.ronn} +2 -4
  69. data/{man → lib/bundler/man}/bundle-cache.1 +1 -1
  70. data/{man/bundle-cache.ronn → lib/bundler/man/bundle-cache.1.ronn} +0 -0
  71. data/{man → lib/bundler/man}/bundle-check.1 +1 -1
  72. data/{man/bundle-check.ronn → lib/bundler/man/bundle-check.1.ronn} +0 -0
  73. data/{man → lib/bundler/man}/bundle-clean.1 +1 -1
  74. data/{man/bundle-clean.ronn → lib/bundler/man/bundle-clean.1.ronn} +0 -0
  75. data/{man → lib/bundler/man}/bundle-config.1 +42 -34
  76. data/{man/bundle-config.ronn → lib/bundler/man/bundle-config.1.ronn} +51 -43
  77. data/{man → lib/bundler/man}/bundle-doctor.1 +1 -1
  78. data/{man/bundle-doctor.ronn → lib/bundler/man/bundle-doctor.1.ronn} +0 -0
  79. data/{man → lib/bundler/man}/bundle-exec.1 +1 -1
  80. data/{man/bundle-exec.ronn → lib/bundler/man/bundle-exec.1.ronn} +0 -0
  81. data/{man → lib/bundler/man}/bundle-gem.1 +25 -3
  82. data/{man/bundle-gem.ronn → lib/bundler/man/bundle-gem.1.ronn} +30 -7
  83. data/{man → lib/bundler/man}/bundle-info.1 +1 -1
  84. data/{man/bundle-info.ronn → lib/bundler/man/bundle-info.1.ronn} +0 -0
  85. data/{man → lib/bundler/man}/bundle-init.1 +1 -1
  86. data/{man/bundle-init.ronn → lib/bundler/man/bundle-init.1.ronn} +0 -0
  87. data/{man → lib/bundler/man}/bundle-inject.1 +1 -1
  88. data/{man/bundle-inject.ronn → lib/bundler/man/bundle-inject.1.ronn} +0 -0
  89. data/{man → lib/bundler/man}/bundle-install.1 +30 -3
  90. data/{man/bundle-install.ronn → lib/bundler/man/bundle-install.1.ronn} +25 -3
  91. data/{man → lib/bundler/man}/bundle-list.1 +7 -7
  92. data/{man/bundle-list.ronn → lib/bundler/man/bundle-list.1.ronn} +6 -6
  93. data/{man → lib/bundler/man}/bundle-lock.1 +1 -1
  94. data/{man/bundle-lock.ronn → lib/bundler/man/bundle-lock.1.ronn} +0 -0
  95. data/{man → lib/bundler/man}/bundle-open.1 +1 -1
  96. data/{man/bundle-open.ronn → lib/bundler/man/bundle-open.1.ronn} +0 -0
  97. data/{man → lib/bundler/man}/bundle-outdated.1 +1 -1
  98. data/{man/bundle-outdated.ronn → lib/bundler/man/bundle-outdated.1.ronn} +0 -0
  99. data/{man → lib/bundler/man}/bundle-platform.1 +1 -1
  100. data/{man/bundle-platform.ronn → lib/bundler/man/bundle-platform.1.ronn} +0 -0
  101. data/{man → lib/bundler/man}/bundle-pristine.1 +1 -1
  102. data/{man/bundle-pristine.ronn → lib/bundler/man/bundle-pristine.1.ronn} +0 -0
  103. data/{man → lib/bundler/man}/bundle-remove.1 +1 -1
  104. data/{man/bundle-remove.ronn → lib/bundler/man/bundle-remove.1.ronn} +0 -0
  105. data/{man → lib/bundler/man}/bundle-show.1 +1 -1
  106. data/{man/bundle-show.ronn → lib/bundler/man/bundle-show.1.ronn} +0 -0
  107. data/{man → lib/bundler/man}/bundle-update.1 +1 -1
  108. data/{man/bundle-update.ronn → lib/bundler/man/bundle-update.1.ronn} +0 -0
  109. data/{man → lib/bundler/man}/bundle-viz.1 +1 -1
  110. data/{man/bundle-viz.ronn → lib/bundler/man/bundle-viz.1.ronn} +0 -0
  111. data/{man → lib/bundler/man}/bundle.1 +1 -1
  112. data/{man/bundle.ronn → lib/bundler/man/bundle.1.ronn} +0 -0
  113. data/{man → lib/bundler/man}/gemfile.5 +4 -4
  114. data/{man → lib/bundler/man}/gemfile.5.ronn +4 -4
  115. data/{man → lib/bundler/man}/index.txt +0 -0
  116. data/lib/bundler/mirror.rb +2 -2
  117. data/lib/bundler/plugin.rb +33 -7
  118. data/lib/bundler/plugin/api/source.rb +8 -1
  119. data/lib/bundler/plugin/dsl.rb +1 -1
  120. data/lib/bundler/plugin/index.rb +10 -1
  121. data/lib/bundler/plugin/installer.rb +9 -11
  122. data/lib/bundler/plugin/installer/rubygems.rb +1 -1
  123. data/lib/bundler/plugin/source_list.rb +5 -1
  124. data/lib/bundler/psyched_yaml.rb +0 -15
  125. data/lib/bundler/remote_specification.rb +5 -2
  126. data/lib/bundler/resolver.rb +133 -77
  127. data/lib/bundler/resolver/spec_group.rb +75 -48
  128. data/lib/bundler/retry.rb +2 -2
  129. data/lib/bundler/ruby_version.rb +1 -1
  130. data/lib/bundler/rubygems_ext.rb +69 -9
  131. data/lib/bundler/rubygems_gem_installer.rb +50 -9
  132. data/lib/bundler/rubygems_integration.rb +25 -60
  133. data/lib/bundler/runtime.rb +4 -14
  134. data/lib/bundler/settings.rb +107 -54
  135. data/lib/bundler/shared_helpers.rb +3 -3
  136. data/lib/bundler/similarity_detector.rb +1 -1
  137. data/lib/bundler/source.rb +7 -1
  138. data/lib/bundler/source/git.rb +24 -22
  139. data/lib/bundler/source/git/git_proxy.rb +82 -80
  140. data/lib/bundler/source/metadata.rb +0 -4
  141. data/lib/bundler/source/path.rb +10 -4
  142. data/lib/bundler/source/path/installer.rb +10 -10
  143. data/lib/bundler/source/rubygems.rb +45 -24
  144. data/lib/bundler/source/rubygems/remote.rb +1 -1
  145. data/lib/bundler/source_list.rb +31 -26
  146. data/lib/bundler/spec_set.rb +29 -17
  147. data/lib/bundler/stub_specification.rb +25 -7
  148. data/lib/bundler/templates/Gemfile +1 -1
  149. data/lib/bundler/templates/gems.rb +1 -1
  150. data/lib/bundler/templates/newgem/CHANGELOG.md.tt +5 -0
  151. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +57 -47
  152. data/lib/bundler/templates/newgem/Gemfile.tt +9 -1
  153. data/lib/bundler/templates/newgem/README.md.tt +6 -5
  154. data/lib/bundler/templates/newgem/Rakefile.tt +19 -5
  155. data/lib/bundler/templates/newgem/bin/console.tt +1 -0
  156. data/lib/bundler/templates/newgem/circleci/config.yml.tt +13 -0
  157. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +2 -0
  158. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +16 -0
  159. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +9 -0
  160. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +4 -2
  161. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +2 -0
  162. data/lib/bundler/templates/newgem/newgem.gemspec.tt +15 -7
  163. data/lib/bundler/templates/newgem/rubocop.yml.tt +13 -0
  164. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +2 -0
  165. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +2 -1
  166. data/lib/bundler/templates/newgem/test/{newgem_test.rb.tt → minitest/newgem_test.rb.tt} +2 -0
  167. data/lib/bundler/templates/newgem/test/{test_helper.rb.tt → minitest/test_helper.rb.tt} +2 -0
  168. data/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt +15 -0
  169. data/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt +6 -0
  170. data/lib/bundler/ui/shell.rb +5 -5
  171. data/lib/bundler/uri_credentials_filter.rb +3 -1
  172. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +0 -1
  173. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +7 -0
  174. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +34 -2
  175. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +2 -2
  176. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +11 -5
  177. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +3 -3
  178. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  179. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +12 -1
  180. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +49 -47
  181. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +82 -189
  182. data/lib/bundler/vendor/thor/lib/thor.rb +5 -13
  183. data/lib/bundler/vendor/thor/lib/thor/actions.rb +1 -1
  184. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +2 -1
  185. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +4 -2
  186. data/lib/bundler/vendor/thor/lib/thor/base.rb +9 -0
  187. data/lib/bundler/vendor/thor/lib/thor/error.rb +1 -1
  188. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +5 -1
  189. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +9 -8
  190. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +5 -2
  191. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +5 -1
  192. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  193. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +154 -0
  194. data/lib/bundler/vendored_persistent.rb +0 -7
  195. data/lib/bundler/vendored_tmpdir.rb +4 -0
  196. data/lib/bundler/version.rb +1 -1
  197. data/lib/bundler/worker.rb +1 -1
  198. data/lib/bundler/yaml_serializer.rb +1 -1
  199. metadata +71 -85
  200. data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +0 -26
  201. data/man/bundle-add.1.txt +0 -58
  202. data/man/bundle-binstubs.1.txt +0 -48
  203. data/man/bundle-cache.1.txt +0 -78
  204. data/man/bundle-check.1.txt +0 -33
  205. data/man/bundle-clean.1.txt +0 -26
  206. data/man/bundle-config.1.txt +0 -528
  207. data/man/bundle-doctor.1.txt +0 -44
  208. data/man/bundle-exec.1.txt +0 -178
  209. data/man/bundle-gem.1.txt +0 -91
  210. data/man/bundle-info.1.txt +0 -21
  211. data/man/bundle-init.1.txt +0 -34
  212. data/man/bundle-inject.1.txt +0 -32
  213. data/man/bundle-install.1.txt +0 -401
  214. data/man/bundle-list.1.txt +0 -43
  215. data/man/bundle-lock.1.txt +0 -93
  216. data/man/bundle-open.1.txt +0 -29
  217. data/man/bundle-outdated.1.txt +0 -131
  218. data/man/bundle-platform.1.txt +0 -57
  219. data/man/bundle-pristine.1.txt +0 -44
  220. data/man/bundle-remove.1.txt +0 -34
  221. data/man/bundle-show.1.txt +0 -27
  222. data/man/bundle-update.1.txt +0 -390
  223. data/man/bundle-viz.1.txt +0 -39
  224. data/man/bundle.1.txt +0 -116
  225. data/man/gemfile.5.txt +0 -649
@@ -87,7 +87,7 @@ module Bundler
87
87
  @parsed_checksums = true
88
88
  end
89
89
 
90
- private
90
+ private
91
91
 
92
92
  def update(local_path, remote_path)
93
93
  Bundler::CompactIndexClient.debug { "update(#{local_path}, #{remote_path})" }
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "gem_parser"
4
+
3
5
  module Bundler
4
6
  class CompactIndexClient
5
7
  class Cache
@@ -83,7 +85,7 @@ module Bundler
83
85
  gem_line ? parse_gem(gem_line) : nil
84
86
  end
85
87
 
86
- private
88
+ private
87
89
 
88
90
  def lines(path)
89
91
  return [] unless path.file?
@@ -92,19 +94,9 @@ module Bundler
92
94
  header ? lines[header + 1..-1] : lines
93
95
  end
94
96
 
95
- def parse_gem(string)
96
- version_and_platform, rest = string.split(" ", 2)
97
- version, platform = version_and_platform.split("-", 2)
98
- dependencies, requirements = rest.split("|", 2).map {|s| s.split(",") } if rest
99
- dependencies = dependencies ? dependencies.map {|d| parse_dependency(d) } : []
100
- requirements = requirements ? requirements.map {|r| parse_dependency(r) } : []
101
- [version, platform, dependencies, requirements]
102
- end
103
-
104
- def parse_dependency(string)
105
- dependency = string.split(":")
106
- dependency[-1] = dependency[-1].split("&") if dependency.size > 1
107
- dependency
97
+ def parse_gem(line)
98
+ @dependency_parser ||= GemParser.new
99
+ @dependency_parser.parse(line)
108
100
  end
109
101
 
110
102
  def info_roots
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class CompactIndexClient
5
+ if defined?(Gem::Resolver::APISet::GemParser)
6
+ GemParser = Gem::Resolver::APISet::GemParser
7
+ else
8
+ class GemParser
9
+ def parse(line)
10
+ version_and_platform, rest = line.split(" ", 2)
11
+ version, platform = version_and_platform.split("-", 2)
12
+ dependencies, requirements = rest.split("|", 2).map {|s| s.split(",") } if rest
13
+ dependencies = dependencies ? dependencies.map {|d| parse_dependency(d) } : []
14
+ requirements = requirements ? requirements.map {|d| parse_dependency(d) } : []
15
+ [version, platform, dependencies, requirements]
16
+ end
17
+
18
+ private
19
+
20
+ def parse_dependency(string)
21
+ dependency = string.split(":")
22
+ dependency[-1] = dependency[-1].split("&") if dependency.size > 1
23
+ dependency
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "../vendored_fileutils"
4
- require "stringio"
5
- require "zlib"
6
4
 
7
5
  module Bundler
8
6
  class CompactIndexClient
@@ -22,13 +20,13 @@ module Bundler
22
20
 
23
21
  def initialize(fetcher)
24
22
  @fetcher = fetcher
25
- require "tmpdir"
23
+ require_relative "../vendored_tmpdir"
26
24
  end
27
25
 
28
26
  def update(local_path, remote_path, retrying = nil)
29
27
  headers = {}
30
28
 
31
- Dir.mktmpdir("bundler-compact-index-") do |local_temp_dir|
29
+ Bundler::Dir.mktmpdir("bundler-compact-index-") do |local_temp_dir|
32
30
  local_temp_path = Pathname.new(local_temp_dir).join(local_path.basename)
33
31
 
34
32
  # first try to fetch any new bytes on the existing file
@@ -45,29 +43,27 @@ module Bundler
45
43
  else
46
44
  "bytes=#{local_temp_path.size}-"
47
45
  end
48
- else
49
- # Fastly ignores Range when Accept-Encoding: gzip is set
50
- headers["Accept-Encoding"] = "gzip"
51
46
  end
52
47
 
53
48
  response = @fetcher.call(remote_path, headers)
54
49
  return nil if response.is_a?(Net::HTTPNotModified)
55
50
 
56
51
  content = response.body
57
- if response["Content-Encoding"] == "gzip"
58
- content = Zlib::GzipReader.new(StringIO.new(content)).read
59
- end
60
52
 
61
- SharedHelpers.filesystem_access(local_temp_path) do
53
+ etag = (response["ETag"] || "").gsub(%r{\AW/}, "")
54
+ correct_response = SharedHelpers.filesystem_access(local_temp_path) do
62
55
  if response.is_a?(Net::HTTPPartialContent) && local_temp_path.size.nonzero?
63
56
  local_temp_path.open("a") {|f| f << slice_body(content, 1..-1) }
57
+
58
+ etag_for(local_temp_path) == etag
64
59
  else
65
- local_temp_path.open("w") {|f| f << content }
60
+ local_temp_path.open("wb") {|f| f << content }
61
+
62
+ etag.length.zero? || etag_for(local_temp_path) == etag
66
63
  end
67
64
  end
68
65
 
69
- response_etag = (response["ETag"] || "").gsub(%r{\AW/}, "")
70
- if etag_for(local_temp_path) == response_etag
66
+ if correct_response
71
67
  SharedHelpers.filesystem_access(local_path) do
72
68
  FileUtils.mv(local_temp_path, local_path)
73
69
  end
@@ -75,7 +71,7 @@ module Bundler
75
71
  end
76
72
 
77
73
  if retrying
78
- raise MisMatchedChecksumError.new(remote_path, response_etag, etag_for(local_temp_path))
74
+ raise MisMatchedChecksumError.new(remote_path, etag, etag_for(local_temp_path))
79
75
  end
80
76
 
81
77
  update(local_path, remote_path, :retrying)
@@ -100,11 +96,11 @@ module Bundler
100
96
 
101
97
  def checksum_for_file(path)
102
98
  return nil unless path.file?
103
- # This must use IO.read instead of Digest.file().hexdigest
99
+ # This must use File.read instead of Digest.file().hexdigest
104
100
  # because we need to preserve \n line endings on windows when calculating
105
101
  # the checksum
106
102
  SharedHelpers.filesystem_access(path, :read) do
107
- SharedHelpers.digest(:MD5).hexdigest(IO.read(path))
103
+ SharedHelpers.digest(:MD5).hexdigest(File.read(path))
108
104
  end
109
105
  end
110
106
  end
@@ -20,6 +20,7 @@ module Bundler
20
20
  2.5
21
21
  2.6
22
22
  2.7
23
+ 3.0
23
24
  ].freeze
24
25
 
25
26
  KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "lockfile_parser"
4
- require "set"
5
4
 
6
5
  module Bundler
7
6
  class Definition
@@ -77,6 +76,7 @@ module Bundler
77
76
  @locked_bundler_version = nil
78
77
  @locked_ruby_version = nil
79
78
  @locked_specs_incomplete_for_platform = false
79
+ @new_platform = nil
80
80
 
81
81
  if lockfile && File.exist?(lockfile)
82
82
  @lockfile_contents = Bundler.read_file(lockfile)
@@ -106,6 +106,17 @@ module Bundler
106
106
  @locked_platforms = []
107
107
  end
108
108
 
109
+ @locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
110
+ @disable_multisource = @locked_gem_sources.all?(&:disable_multisource?)
111
+
112
+ unless @disable_multisource
113
+ msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. You should run `bundle update` or generate your lockfile from scratch."
114
+
115
+ Bundler::SharedHelpers.major_deprecation 2, msg
116
+
117
+ @sources.merged_gem_lockfile_sections!
118
+ end
119
+
109
120
  @unlock[:gems] ||= []
110
121
  @unlock[:sources] ||= []
111
122
  @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@@ -113,7 +124,7 @@ module Bundler
113
124
  end
114
125
  @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
115
126
 
116
- add_current_platform unless Bundler.frozen_bundle?
127
+ add_current_platform unless current_ruby_platform_locked? || Bundler.frozen_bundle?
117
128
 
118
129
  converge_path_sources_to_gemspec_sources
119
130
  @path_changes = converge_paths
@@ -145,17 +156,19 @@ module Bundler
145
156
  end
146
157
  end
147
158
 
159
+ def disable_multisource?
160
+ @disable_multisource
161
+ end
162
+
148
163
  def resolve_with_cache!
149
- raise "Specs already loaded" if @specs
150
164
  sources.cached!
151
- specs
165
+ resolve
152
166
  end
153
167
 
154
168
  def resolve_remotely!
155
- raise "Specs already loaded" if @specs
156
169
  @remote = true
157
170
  sources.remote!
158
- specs
171
+ resolve
159
172
  end
160
173
 
161
174
  # For given dependency list returns a SpecSet with Gemspec of all the required
@@ -172,10 +185,10 @@ module Bundler
172
185
  gem_name, gem_version = extract_gem_info(e)
173
186
  locked_gem = @locked_specs[gem_name].last
174
187
  raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
175
- raise GemNotFound, "Your bundle is locked to #{locked_gem}, but that version could not " \
176
- "be found in any of the sources listed in your Gemfile. If you haven't changed sources, " \
177
- "that means the author of #{locked_gem} has removed it. You'll need to update your bundle " \
178
- "to a version other than #{locked_gem} that hasn't been removed in order to install."
188
+ raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
189
+ "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
190
+ "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
191
+ "removed in order to install."
179
192
  end
180
193
  unless specs["bundler"].any?
181
194
  bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
@@ -194,10 +207,6 @@ module Bundler
194
207
  @locked_specs - specs
195
208
  end
196
209
 
197
- def new_platform?
198
- @new_platform
199
- end
200
-
201
210
  def missing_specs
202
211
  missing = []
203
212
  resolve.materialize(requested_dependencies, missing)
@@ -227,16 +236,29 @@ module Bundler
227
236
  end
228
237
  end
229
238
 
239
+ def requested_dependencies
240
+ groups = requested_groups
241
+ groups.map!(&:to_sym)
242
+ dependencies_for(groups)
243
+ end
244
+
230
245
  def current_dependencies
231
- dependencies.select(&:should_include?)
246
+ dependencies.select do |d|
247
+ d.should_include? && !d.gem_platforms(@platforms).empty?
248
+ end
232
249
  end
233
250
 
234
251
  def specs_for(groups)
235
- deps = dependencies.select {|d| (d.groups & groups).any? }
236
- deps.delete_if {|d| !d.should_include? }
252
+ deps = dependencies_for(groups)
237
253
  specs.for(expand_dependencies(deps))
238
254
  end
239
255
 
256
+ def dependencies_for(groups)
257
+ current_dependencies.reject do |d|
258
+ (d.groups & groups).empty?
259
+ end
260
+ end
261
+
240
262
  # Resolve all the dependencies specified in Gemfile. It ensures that
241
263
  # dependencies that have been already resolved via locked file and are fresh
242
264
  # are reused when resolving dependencies
@@ -245,22 +267,18 @@ module Bundler
245
267
  def resolve
246
268
  @resolve ||= begin
247
269
  last_resolve = converge_locked_specs
248
- resolve =
249
- if Bundler.frozen_bundle?
250
- Bundler.ui.debug "Frozen, using resolution from the lockfile"
251
- last_resolve
252
- elsif !unlocking? && nothing_changed?
253
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
254
- last_resolve
255
- else
256
- # Run a resolve against the locally available gems
257
- Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
258
- last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
259
- end
260
-
261
- # filter out gems that _can_ be installed on multiple platforms, but don't need
262
- # to be
263
- resolve.for(expand_dependencies(dependencies, true), [], false, false, false)
270
+ if Bundler.frozen_bundle?
271
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
272
+ last_resolve
273
+ elsif !unlocking? && nothing_changed?
274
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
275
+ last_resolve
276
+ else
277
+ # Run a resolve against the locally available gems
278
+ Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
279
+ expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
280
+ Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
281
+ end
264
282
  end
265
283
  end
266
284
 
@@ -312,10 +330,6 @@ module Bundler
312
330
  sources.rubygems_sources.any? {|s| s.remotes.any? }
313
331
  end
314
332
 
315
- def has_local_dependencies?
316
- !sources.path_sources.empty? || !sources.git_sources.empty?
317
- end
318
-
319
333
  def spec_git_paths
320
334
  sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
321
335
  end
@@ -396,12 +410,10 @@ module Bundler
396
410
  "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."
397
411
 
398
412
  unless explicit_flag
399
- suggested_command = if Bundler.settings.locations("frozen")[:global]
413
+ suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any?
400
414
  "bundle config unset frozen"
401
415
  elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
402
416
  "bundle config unset deployment"
403
- else
404
- "bundle install --no-deployment"
405
417
  end
406
418
  msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
407
419
  "freeze \nby running `#{suggested_command}`."
@@ -450,9 +462,9 @@ module Bundler
450
462
  @locked_deps.each {|name, d| both_sources[name][1] = d.source }
451
463
 
452
464
  both_sources.each do |name, (dep, lock_source)|
453
- next unless (dep.nil? && !lock_source.nil?) || (!dep.nil? && !lock_source.nil? && !lock_source.can_lock?(dep))
465
+ next if lock_source.nil? || (dep && lock_source.can_lock?(dep))
454
466
  gemfile_source_name = (dep && dep.source) || "no specified source"
455
- lockfile_source_name = lock_source || "no specified source"
467
+ lockfile_source_name = lock_source
456
468
  changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
457
469
  end
458
470
 
@@ -497,15 +509,11 @@ module Bundler
497
509
  end
498
510
 
499
511
  def validate_platforms!
500
- return if @platforms.any? do |bundle_platform|
501
- Bundler.rubygems.platforms.any? do |local_platform|
502
- MatchPlatform.platforms_match?(bundle_platform, local_platform)
503
- end
504
- end
512
+ return if current_platform_locked?
505
513
 
506
514
  raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
507
- "but your local platforms are #{Bundler.rubygems.platforms.map(&:to_s)}, and " \
508
- "there's no compatible match between those two lists."
515
+ "but your local platform is #{Bundler.local_platform}. " \
516
+ "Add the current platform to the lockfile with `bundle lock --add-platform #{Bundler.local_platform}` and try again."
509
517
  end
510
518
 
511
519
  def add_platform(platform)
@@ -518,8 +526,10 @@ module Bundler
518
526
  raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
519
527
  end
520
528
 
521
- def add_current_platform
522
- current_platforms.each {|platform| add_platform(platform) }
529
+ def most_specific_locked_platform
530
+ @platforms.min_by do |bundle_platform|
531
+ platform_specificity_match(bundle_platform, local_platform)
532
+ end
523
533
  end
524
534
 
525
535
  def find_resolved_spec(current_spec)
@@ -533,6 +543,9 @@ module Bundler
533
543
  attr_reader :sources
534
544
  private :sources
535
545
 
546
+ attr_reader :locked_gem_sources
547
+ private :locked_gem_sources
548
+
536
549
  def nothing_changed?
537
550
  !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
538
551
  end
@@ -541,16 +554,24 @@ module Bundler
541
554
  @unlocking
542
555
  end
543
556
 
544
- private
557
+ private
558
+
559
+ def current_ruby_platform_locked?
560
+ return false unless generic_local_platform == Gem::Platform::RUBY
561
+
562
+ current_platform_locked?
563
+ end
545
564
 
546
- def current_platforms
547
- current_platform = Bundler.local_platform
548
- [].tap do |platforms|
549
- platforms << current_platform if Bundler.feature_flag.specific_platform?
550
- platforms << generic(current_platform)
565
+ def current_platform_locked?
566
+ @platforms.any? do |bundle_platform|
567
+ MatchPlatform.platforms_match?(bundle_platform, Bundler.local_platform)
551
568
  end
552
569
  end
553
570
 
571
+ def add_current_platform
572
+ add_platform(local_platform)
573
+ end
574
+
554
575
  def change_reason
555
576
  if unlocking?
556
577
  unlock_reason = @unlock.reject {|_k, v| Array(v).empty? }.map do |k, v|
@@ -589,7 +610,7 @@ module Bundler
589
610
  deps_for_source = @dependencies.select {|s| s.source == source }
590
611
  locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
591
612
 
592
- Set.new(deps_for_source) != Set.new(locked_deps_for_source)
613
+ deps_for_source.uniq.sort != locked_deps_for_source.sort
593
614
  end
594
615
 
595
616
  def specs_for_source_changed?(source)
@@ -649,21 +670,20 @@ module Bundler
649
670
  end
650
671
 
651
672
  def converge_rubygems_sources
652
- return false if Bundler.feature_flag.disable_multisource?
673
+ return false if disable_multisource?
653
674
 
654
- changes = false
675
+ return false if locked_gem_sources.empty?
655
676
 
656
- # Get the RubyGems sources from the Gemfile.lock
657
- locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
658
677
  # Get the RubyGems remotes from the Gemfile
659
678
  actual_remotes = sources.rubygems_remotes
679
+ return false if actual_remotes.empty?
680
+
681
+ changes = false
660
682
 
661
683
  # If there is a RubyGems source in both
662
- if !locked_gem_sources.empty? && !actual_remotes.empty?
663
- locked_gem_sources.each do |locked_gem|
664
- # Merge the remotes from the Gemfile into the Gemfile.lock
665
- changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
666
- end
684
+ locked_gem_sources.each do |locked_gem|
685
+ # Merge the remotes from the Gemfile into the Gemfile.lock
686
+ changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
667
687
  end
668
688
 
669
689
  changes
@@ -706,9 +726,6 @@ module Bundler
706
726
  elsif dep.source
707
727
  dep.source = sources.get(dep.source)
708
728
  end
709
- if dep.source.is_a?(Source::Gemspec)
710
- dep.platforms.concat(@platforms.map {|p| Dependency::REVERSE_PLATFORM_MAP[p] }.flatten(1)).uniq!
711
- end
712
729
  end
713
730
 
714
731
  changes = false
@@ -806,11 +823,6 @@ module Bundler
806
823
  # commonly happens if the version changed in the gemspec
807
824
  next unless new_spec
808
825
 
809
- new_runtime_deps = new_spec.dependencies.select {|d| d.type != :development }
810
- old_runtime_deps = s.dependencies.select {|d| d.type != :development }
811
- # If the dependencies of the path source have changed and locked spec can't satisfy new dependencies, unlock it
812
- next unless new_runtime_deps.sort == old_runtime_deps.sort || new_runtime_deps.all? {|d| satisfies_locked_spec?(d) }
813
-
814
826
  s.dependencies.replace(new_spec.dependencies)
815
827
  end
816
828
 
@@ -818,7 +830,7 @@ module Bundler
818
830
  end
819
831
 
820
832
  resolve = SpecSet.new(converged)
821
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(deps), @unlock[:gems], true, true)
833
+ @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), @unlock[:gems], true, true)
822
834
  resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false)
823
835
  diff = nil
824
836
 
@@ -846,21 +858,9 @@ module Bundler
846
858
  @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
847
859
  end
848
860
 
849
- # This list of dependencies is only used in #resolve, so it's OK to add
850
- # the metadata dependencies here
851
- def expanded_dependencies
852
- @expanded_dependencies ||= begin
853
- expand_dependencies(dependencies + metadata_dependencies, @remote)
854
- end
855
- end
856
-
857
861
  def metadata_dependencies
858
862
  @metadata_dependencies ||= begin
859
- ruby_versions = concat_ruby_version_requirements(@ruby_version)
860
- if ruby_versions.empty? || !@ruby_version.exact?
861
- concat_ruby_version_requirements(RubyVersion.system)
862
- concat_ruby_version_requirements(locked_ruby_version_object) unless @unlock[:ruby]
863
- end
863
+ ruby_versions = ruby_version_requirements(@ruby_version)
864
864
  [
865
865
  Dependency.new("Ruby\0", ruby_versions),
866
866
  Dependency.new("RubyGems\0", Gem::VERSION),
@@ -868,49 +868,37 @@ module Bundler
868
868
  end
869
869
  end
870
870
 
871
- def concat_ruby_version_requirements(ruby_version, ruby_versions = [])
872
- return ruby_versions unless ruby_version
871
+ def ruby_version_requirements(ruby_version)
872
+ return [] unless ruby_version
873
873
  if ruby_version.patchlevel
874
- ruby_versions << ruby_version.to_gem_version_with_patchlevel
874
+ [ruby_version.to_gem_version_with_patchlevel]
875
875
  else
876
- ruby_versions.concat(ruby_version.versions.map do |version|
876
+ ruby_version.versions.map do |version|
877
877
  requirement = Gem::Requirement.new(version)
878
878
  if requirement.exact?
879
879
  "~> #{version}.0"
880
880
  else
881
881
  requirement
882
882
  end
883
- end)
883
+ end
884
884
  end
885
885
  end
886
886
 
887
887
  def expand_dependencies(dependencies, remote = false)
888
- sorted_platforms = Resolver.sort_platforms(@platforms)
889
888
  deps = []
890
889
  dependencies.each do |dep|
891
890
  dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
892
- next if !remote && !dep.current_platform?
893
- platforms = dep.gem_platforms(sorted_platforms)
894
- if platforms.empty? && !Bundler.settings[:disable_platform_warnings]
895
- mapped_platforms = dep.expanded_platforms
896
- Bundler.ui.warn \
897
- "The dependency #{dep} will be unused by any of the platforms Bundler is installing for. " \
898
- "Bundler is installing for #{@platforms.join ", "} but the dependency " \
899
- "is only for #{mapped_platforms.join ", "}. " \
900
- "To add those platforms to the bundle, " \
901
- "run `bundle lock --add-platform #{mapped_platforms.join " "}`."
902
- end
903
- platforms.each do |p|
904
- deps << DepProxy.new(dep, p) if remote || p == generic_local_platform
905
- end
891
+ next unless remote || dep.current_platform?
892
+ target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform])
893
+ deps += expand_dependency_with_platforms(dep, target_platforms)
906
894
  end
907
895
  deps
908
896
  end
909
897
 
910
- def requested_dependencies
911
- groups = requested_groups
912
- groups.map!(&:to_sym)
913
- dependencies.reject {|d| !d.should_include? || (d.groups & groups).empty? }
898
+ def expand_dependency_with_platforms(dep, platforms)
899
+ platforms.map do |p|
900
+ DepProxy.get_proxy(dep, p)
901
+ end
914
902
  end
915
903
 
916
904
  def source_requirements
@@ -920,29 +908,18 @@ module Bundler
920
908
  # Record the specs available in each gem's source, so that those
921
909
  # specs will be available later when the resolver knows where to
922
910
  # look for that gemspec (or its dependencies)
923
- default = sources.default_source
924
- source_requirements = { :default => default }
925
- default = nil unless Bundler.feature_flag.disable_multisource?
926
- dependencies.each do |dep|
927
- next unless source = dep.source || default
928
- source_requirements[dep.name] = source
929
- end
911
+ source_requirements = { :default => sources.default_source }.merge(dependency_source_requirements)
930
912
  metadata_dependencies.each do |dep|
931
913
  source_requirements[dep.name] = sources.metadata_source
932
914
  end
915
+ source_requirements[:global] = index unless Bundler.feature_flag.disable_multisource?
916
+ source_requirements[:default_bundler] = source_requirements["bundler"] || source_requirements[:default]
933
917
  source_requirements["bundler"] = sources.metadata_source # needs to come last to override
934
918
  source_requirements
935
919
  end
936
920
 
937
921
  def pinned_spec_names(skip = nil)
938
- pinned_names = []
939
- default = Bundler.feature_flag.disable_multisource? && sources.default_source
940
- @dependencies.each do |dep|
941
- next unless dep_source = dep.source || default
942
- next if dep_source == skip
943
- pinned_names << dep.name
944
- end
945
- pinned_names
922
+ dependency_source_requirements.reject {|_, source| source == skip }.keys
946
923
  end
947
924
 
948
925
  def requested_groups
@@ -980,15 +957,16 @@ module Bundler
980
957
  end
981
958
 
982
959
  def additional_base_requirements_for_resolve
983
- return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions?
960
+ return [] unless @locked_gems
984
961
  dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
985
962
  @locked_gems.specs.reduce({}) do |requirements, locked_spec|
986
963
  name = locked_spec.name
987
964
  dependency = dependencies_by_name[name]
965
+ next requirements unless dependency
988
966
  next requirements if @locked_gems.dependencies[name] != dependency
989
- next requirements if dependency && dependency.source.is_a?(Source::Path)
967
+ next requirements if dependency.source.is_a?(Source::Path)
990
968
  dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
991
- requirements[name] = DepProxy.new(dep, locked_spec.platform)
969
+ requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
992
970
  requirements
993
971
  end.values
994
972
  end
@@ -998,5 +976,17 @@ module Bundler
998
976
 
999
977
  Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
1000
978
  end
979
+
980
+ def dependency_source_requirements
981
+ @dependency_source_requirements ||= begin
982
+ source_requirements = {}
983
+ default = sources.default_source
984
+ dependencies.each do |dep|
985
+ dep_source = dep.source || default
986
+ source_requirements[dep.name] = dep_source
987
+ end
988
+ source_requirements
989
+ end
990
+ end
1001
991
  end
1002
992
  end