bundler 1.15.4 → 1.16.0.pre.1

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 (251) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +43 -0
  3. data/README.md +12 -7
  4. data/exe/bundle +1 -1
  5. data/exe/bundle_ruby +4 -3
  6. data/lib/bundler.rb +47 -37
  7. data/lib/bundler/build_metadata.rb +38 -0
  8. data/lib/bundler/capistrano.rb +5 -0
  9. data/lib/bundler/cli.rb +155 -67
  10. data/lib/bundler/cli/add.rb +0 -1
  11. data/lib/bundler/cli/binstubs.rb +9 -7
  12. data/lib/bundler/cli/cache.rb +5 -4
  13. data/lib/bundler/cli/check.rb +3 -5
  14. data/lib/bundler/cli/clean.rb +5 -6
  15. data/lib/bundler/cli/common.rb +11 -2
  16. data/lib/bundler/cli/config.rb +2 -1
  17. data/lib/bundler/cli/console.rb +2 -1
  18. data/lib/bundler/cli/doctor.rb +1 -0
  19. data/lib/bundler/cli/exec.rb +2 -1
  20. data/lib/bundler/cli/gem.rb +3 -2
  21. data/lib/bundler/cli/info.rb +0 -1
  22. data/lib/bundler/cli/init.rb +17 -6
  23. data/lib/bundler/cli/inject.rb +1 -0
  24. data/lib/bundler/cli/install.rb +61 -61
  25. data/lib/bundler/cli/issue.rb +1 -1
  26. data/lib/bundler/cli/list.rb +22 -0
  27. data/lib/bundler/cli/lock.rb +0 -1
  28. data/lib/bundler/cli/open.rb +2 -2
  29. data/lib/bundler/cli/outdated.rb +13 -8
  30. data/lib/bundler/cli/package.rb +9 -6
  31. data/lib/bundler/cli/platform.rb +1 -0
  32. data/lib/bundler/cli/plugin.rb +1 -0
  33. data/lib/bundler/cli/pristine.rb +9 -2
  34. data/lib/bundler/cli/show.rb +0 -1
  35. data/lib/bundler/cli/update.rb +31 -5
  36. data/lib/bundler/cli/viz.rb +1 -0
  37. data/lib/bundler/compact_index_client.rb +1 -0
  38. data/lib/bundler/compact_index_client/cache.rb +1 -0
  39. data/lib/bundler/compact_index_client/updater.rb +3 -2
  40. data/lib/bundler/compatibility_guard.rb +14 -0
  41. data/lib/bundler/constants.rb +1 -0
  42. data/lib/bundler/current_ruby.rb +5 -4
  43. data/lib/bundler/definition.rb +140 -95
  44. data/lib/bundler/dep_proxy.rb +2 -0
  45. data/lib/bundler/dependency.rb +6 -7
  46. data/lib/bundler/deployment.rb +1 -1
  47. data/lib/bundler/deprecate.rb +1 -0
  48. data/lib/bundler/dsl.rb +97 -62
  49. data/lib/bundler/endpoint_specification.rb +9 -0
  50. data/lib/bundler/env.rb +63 -27
  51. data/lib/bundler/environment_preserver.rb +26 -6
  52. data/lib/bundler/errors.rb +1 -0
  53. data/lib/bundler/feature_flag.rb +39 -4
  54. data/lib/bundler/fetcher.rb +15 -8
  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 +1 -0
  58. data/lib/bundler/fetcher/downloader.rb +1 -0
  59. data/lib/bundler/fetcher/index.rb +1 -0
  60. data/lib/bundler/friendly_errors.rb +2 -1
  61. data/lib/bundler/gem_helper.rb +14 -9
  62. data/lib/bundler/gem_helpers.rb +1 -0
  63. data/lib/bundler/gem_remote_fetcher.rb +1 -0
  64. data/lib/bundler/gem_tasks.rb +1 -0
  65. data/lib/bundler/gem_version_promoter.rb +1 -0
  66. data/lib/bundler/gemdeps.rb +1 -0
  67. data/lib/bundler/graph.rb +1 -0
  68. data/lib/bundler/index.rb +15 -8
  69. data/lib/bundler/injector.rb +25 -22
  70. data/lib/bundler/inline.rb +5 -7
  71. data/lib/bundler/installer.rb +93 -45
  72. data/lib/bundler/installer/gem_installer.rb +2 -0
  73. data/lib/bundler/installer/parallel_installer.rb +73 -42
  74. data/lib/bundler/installer/standalone.rb +1 -0
  75. data/lib/bundler/lazy_specification.rb +2 -1
  76. data/lib/bundler/lockfile_generator.rb +95 -0
  77. data/lib/bundler/lockfile_parser.rb +10 -4
  78. data/lib/bundler/match_platform.rb +1 -0
  79. data/lib/bundler/mirror.rb +6 -3
  80. data/lib/bundler/plugin.rb +1 -0
  81. data/lib/bundler/plugin/api/source.rb +8 -0
  82. data/lib/bundler/plugin/installer.rb +7 -6
  83. data/lib/bundler/plugin/source_list.rb +7 -8
  84. data/lib/bundler/process_lock.rb +24 -0
  85. data/lib/bundler/psyched_yaml.rb +1 -0
  86. data/lib/bundler/remote_specification.rb +1 -0
  87. data/lib/bundler/resolver.rb +138 -191
  88. data/lib/bundler/resolver/spec_group.rb +111 -0
  89. data/lib/bundler/retry.rb +1 -0
  90. data/lib/bundler/ruby_dsl.rb +1 -0
  91. data/lib/bundler/ruby_version.rb +1 -0
  92. data/lib/bundler/rubygems_ext.rb +5 -4
  93. data/lib/bundler/rubygems_gem_installer.rb +23 -0
  94. data/lib/bundler/rubygems_integration.rb +56 -27
  95. data/lib/bundler/runtime.rb +3 -5
  96. data/lib/bundler/settings.rb +177 -76
  97. data/lib/bundler/settings/validator.rb +79 -0
  98. data/lib/bundler/setup.rb +1 -0
  99. data/lib/bundler/shared_helpers.rb +86 -26
  100. data/lib/bundler/similarity_detector.rb +1 -0
  101. data/lib/bundler/source.rb +32 -0
  102. data/lib/bundler/source/gemspec.rb +1 -0
  103. data/lib/bundler/source/git.rb +21 -16
  104. data/lib/bundler/source/git/git_proxy.rb +14 -10
  105. data/lib/bundler/source/metadata.rb +63 -0
  106. data/lib/bundler/source/path.rb +8 -8
  107. data/lib/bundler/source/path/installer.rb +2 -0
  108. data/lib/bundler/source/rubygems.rb +131 -84
  109. data/lib/bundler/source/rubygems/remote.rb +3 -0
  110. data/lib/bundler/source_list.rb +75 -15
  111. data/lib/bundler/spec_set.rb +2 -1
  112. data/lib/bundler/ssl_certs/certificate_manager.rb +2 -1
  113. data/lib/bundler/stub_specification.rb +1 -0
  114. data/lib/bundler/templates/Executable +4 -0
  115. data/lib/bundler/templates/Executable.bundler +105 -0
  116. data/lib/bundler/templates/Gemfile +1 -0
  117. data/lib/bundler/templates/gems.rb +8 -0
  118. data/lib/bundler/templates/newgem/README.md.tt +1 -1
  119. data/lib/bundler/templates/newgem/gitignore.tt +0 -1
  120. data/lib/bundler/templates/newgem/newgem.gemspec.tt +4 -1
  121. data/lib/bundler/templates/newgem/rspec.tt +1 -0
  122. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +0 -2
  123. data/lib/bundler/ui.rb +1 -0
  124. data/lib/bundler/ui/rg_proxy.rb +1 -0
  125. data/lib/bundler/ui/shell.rb +15 -4
  126. data/lib/bundler/ui/silent.rb +1 -0
  127. data/lib/bundler/uri_credentials_filter.rb +1 -0
  128. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1638 -0
  129. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +2 -0
  130. data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
  131. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +7 -0
  132. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +1 -0
  133. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -2
  134. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +1 -0
  135. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -0
  136. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -0
  137. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -0
  138. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -0
  139. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +1 -0
  140. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -0
  141. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -0
  142. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +3 -2
  143. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +69 -6
  144. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +2 -1
  145. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -0
  146. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +3 -1
  147. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +487 -148
  148. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +1 -0
  149. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +8 -4
  150. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  151. data/lib/bundler/vendored_fileutils.rb +9 -0
  152. data/lib/bundler/vendored_molinillo.rb +1 -0
  153. data/lib/bundler/vendored_persistent.rb +34 -0
  154. data/lib/bundler/vendored_thor.rb +1 -0
  155. data/lib/bundler/version.rb +6 -2
  156. data/lib/bundler/version_ranges.rb +1 -0
  157. data/lib/bundler/vlad.rb +5 -0
  158. data/lib/bundler/worker.rb +1 -0
  159. data/lib/bundler/yaml_serializer.rb +3 -3
  160. data/man/bundle-add.1 +43 -0
  161. data/man/bundle-add.1.txt +40 -0
  162. data/man/bundle-binstubs.1 +40 -0
  163. data/man/bundle-binstubs.1.txt +48 -0
  164. data/man/bundle-binstubs.ronn +14 -0
  165. data/man/bundle-check.1 +31 -0
  166. data/man/bundle-check.1.txt +32 -0
  167. data/man/bundle-clean.1 +24 -0
  168. data/man/bundle-clean.1.txt +26 -0
  169. data/man/bundle-config.1 +455 -0
  170. data/man/bundle-config.1.txt +491 -0
  171. data/man/bundle-config.ronn +133 -79
  172. data/man/bundle-exec.1 +165 -0
  173. data/man/bundle-exec.1.txt +178 -0
  174. data/man/bundle-exec.ronn +7 -0
  175. data/man/bundle-gem.1 +80 -0
  176. data/man/bundle-gem.1.txt +91 -0
  177. data/man/bundle-gem.ronn +2 -1
  178. data/man/bundle-info.1 +20 -0
  179. data/man/bundle-info.1.txt +21 -0
  180. data/man/bundle-init.1 +20 -0
  181. data/man/bundle-init.1.txt +24 -0
  182. data/man/bundle-inject.1 +33 -0
  183. data/man/bundle-inject.1.txt +32 -0
  184. data/man/bundle-install.1 +305 -0
  185. data/man/bundle-install.1.txt +385 -0
  186. data/man/bundle-install.ronn +32 -32
  187. data/man/bundle-list.1 +20 -0
  188. data/man/bundle-list.1.txt +21 -0
  189. data/man/bundle-list.ronn +15 -0
  190. data/man/bundle-lock.1 +84 -0
  191. data/man/bundle-lock.1.txt +93 -0
  192. data/man/bundle-open.1 +32 -0
  193. data/man/bundle-open.1.txt +29 -0
  194. data/man/bundle-outdated.1 +151 -0
  195. data/man/bundle-outdated.1.txt +127 -0
  196. data/man/bundle-outdated.ronn +1 -1
  197. data/man/bundle-package.1 +55 -0
  198. data/man/bundle-package.1.txt +79 -0
  199. data/man/bundle-package.ronn +5 -0
  200. data/man/bundle-platform.1 +61 -0
  201. data/man/bundle-platform.1.txt +57 -0
  202. data/man/bundle-pristine.1 +34 -0
  203. data/man/bundle-pristine.1.txt +44 -0
  204. data/man/bundle-pristine.ronn +24 -3
  205. data/man/bundle-show.1 +23 -0
  206. data/man/bundle-show.1.txt +25 -0
  207. data/man/bundle-update.1 +390 -0
  208. data/man/bundle-update.1.txt +386 -0
  209. data/man/bundle-update.ronn +2 -2
  210. data/man/bundle-viz.1 +39 -0
  211. data/man/bundle-viz.1.txt +38 -0
  212. data/man/bundle-viz.ronn +5 -5
  213. data/man/bundle.1 +132 -0
  214. data/man/bundle.1.txt +113 -0
  215. data/man/bundle.ronn +5 -2
  216. data/man/gemfile.5 +679 -0
  217. data/man/gemfile.5.ronn +31 -0
  218. data/man/gemfile.5.txt +636 -0
  219. data/man/index.txt +23 -0
  220. metadata +21 -36
  221. data/.codeclimate.yml +0 -25
  222. data/.gitignore +0 -18
  223. data/.rspec +0 -3
  224. data/.rubocop.yml +0 -131
  225. data/.rubocop_todo.yml +0 -418
  226. data/.travis.yml +0 -122
  227. data/CODE_OF_CONDUCT.md +0 -42
  228. data/CONTRIBUTING.md +0 -17
  229. data/Rakefile +0 -338
  230. data/bin/rake +0 -19
  231. data/bin/rspec +0 -15
  232. data/bin/rubocop +0 -17
  233. data/bin/with_rubygems +0 -39
  234. data/bundler.gemspec +0 -48
  235. data/doc/README.md +0 -30
  236. data/doc/TROUBLESHOOTING.md +0 -64
  237. data/doc/contributing/BUG_TRIAGE.md +0 -36
  238. data/doc/contributing/COMMUNITY.md +0 -13
  239. data/doc/contributing/GETTING_HELP.md +0 -11
  240. data/doc/contributing/HOW_YOU_CAN_HELP.md +0 -27
  241. data/doc/contributing/ISSUES.md +0 -51
  242. data/doc/contributing/README.md +0 -38
  243. data/doc/development/NEW_FEATURES.md +0 -10
  244. data/doc/development/PULL_REQUESTS.md +0 -40
  245. data/doc/development/README.md +0 -19
  246. data/doc/development/RELEASING.md +0 -9
  247. data/doc/development/SETUP.md +0 -27
  248. data/doc/documentation/README.md +0 -29
  249. data/doc/documentation/VISION.md +0 -26
  250. data/doc/documentation/WRITING.md +0 -54
  251. data/task/release.rake +0 -116
@@ -90,7 +90,7 @@ module Bundler
90
90
  send("parse_#{@state}", line)
91
91
  end
92
92
  end
93
- @sources << @rubygems_aggregate
93
+ @sources << @rubygems_aggregate unless Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
94
94
  @specs = @specs.values.sort_by(&:identifier)
95
95
  warn_for_outdated_bundler_version
96
96
  rescue ArgumentError => e
@@ -141,10 +141,16 @@ module Bundler
141
141
  @sources << @current_source
142
142
  end
143
143
  when GEM
144
- Array(@opts["remote"]).each do |url|
145
- @rubygems_aggregate.add_remote(url)
144
+ if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
145
+ @opts["remotes"] = @opts.delete("remote")
146
+ @current_source = TYPES[@type].from_lock(@opts)
147
+ @sources << @current_source
148
+ else
149
+ Array(@opts["remote"]).each do |url|
150
+ @rubygems_aggregate.add_remote(url)
151
+ end
152
+ @current_source = @rubygems_aggregate
146
153
  end
147
- @current_source = @rubygems_aggregate
148
154
  when PLUGIN
149
155
  @current_source = Plugin.source_from_lock(@opts)
150
156
  @sources << @current_source
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "bundler/gem_helpers"
3
4
 
4
5
  module Bundler
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "socket"
3
4
 
4
5
  module Bundler
@@ -37,7 +38,7 @@ module Bundler
37
38
  mirror = if config.all?
38
39
  @all
39
40
  else
40
- (@mirrors[config.uri] = @mirrors[config.uri] || Mirror.new)
41
+ @mirrors[config.uri] ||= Mirror.new
41
42
  end
42
43
  config.update_mirror(mirror)
43
44
  end
@@ -45,7 +46,9 @@ module Bundler
45
46
  private
46
47
 
47
48
  def fetch_valid_mirror_for(uri)
48
- mirror = (@mirrors[URI(uri.to_s.downcase)] || @mirrors[URI(uri.to_s).host] || Mirror.new(uri)).validate!(@prober)
49
+ downcased = uri.to_s.downcase
50
+ mirror = @mirrors[downcased] || @mirrors[URI(downcased).host] || Mirror.new(uri)
51
+ mirror.validate!(@prober)
49
52
  mirror = Mirror.new(uri) unless mirror.valid?
50
53
  mirror
51
54
  end
@@ -117,7 +120,7 @@ module Bundler
117
120
 
118
121
  def initialize(config_line, value)
119
122
  uri, fallback =
120
- config_line.match(%r{^mirror\.(all|.+?)(\.fallback_timeout)?\/?$}).captures
123
+ config_line.match(%r{\Amirror\.(all|.+?)(\.fallback_timeout)?\/?\z}).captures
121
124
  @fallback = !fallback.nil?
122
125
  @all = false
123
126
  if uri == "all"
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "bundler/plugin/api"
3
4
 
4
5
  module Bundler
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "uri"
3
4
  require "digest/sha1"
4
5
 
@@ -293,6 +294,13 @@ module Bundler
293
294
  def bundler_plugin_api_source?
294
295
  true
295
296
  end
297
+
298
+ # @private
299
+ # This API on source might not be stable, and for now we expect plugins
300
+ # to download all specs in `#specs`, so we implement the method for
301
+ # compatibility purposes and leave it undocumented (and don't support)
302
+ # overriding it)
303
+ def double_check_for(*); end
296
304
  end
297
305
  end
298
306
  end
@@ -13,12 +13,13 @@ module Bundler
13
13
 
14
14
  def install(names, options)
15
15
  version = options[:version] || [">= 0"]
16
-
17
- if options[:git]
18
- install_git(names, version, options)
19
- else
20
- sources = options[:source] || Bundler.rubygems.sources
21
- install_rubygems(names, version, sources)
16
+ Bundler.settings.temporary(:lockfile_uses_separate_rubygems_sources => false, :disable_multisource => false) do
17
+ if options[:git]
18
+ install_git(names, version, options)
19
+ else
20
+ sources = options[:source] || Bundler.rubygems.sources
21
+ install_rubygems(names, version, sources)
22
+ end
22
23
  end
23
24
  end
24
25
 
@@ -5,13 +5,6 @@ module Bundler
5
5
  # approptiate options to be used with Source classes for plugin installation
6
6
  module Plugin
7
7
  class SourceList < Bundler::SourceList
8
- def initialize
9
- @path_sources = []
10
- @git_sources = []
11
- @rubygems_aggregate = Plugin::Installer::Rubygems.new
12
- @rubygems_sources = []
13
- end
14
-
15
8
  def add_git_source(options = {})
16
9
  add_source_to_list Plugin::Installer::Git.new(options), git_sources
17
10
  end
@@ -21,7 +14,13 @@ module Bundler
21
14
  end
22
15
 
23
16
  def all_sources
24
- path_sources + git_sources + rubygems_sources
17
+ path_sources + git_sources + rubygems_sources + [metadata_source]
18
+ end
19
+
20
+ private
21
+
22
+ def rubygems_aggregate_class
23
+ Plugin::Installer::Rubygems
25
24
  end
26
25
  end
27
26
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class ProcessLock
5
+ def self.lock(bundle_path = Bundler.bundle_path)
6
+ lock_file_path = File.join(bundle_path, "bundler.lock")
7
+ has_lock = false
8
+
9
+ File.open(lock_file_path, "w") do |f|
10
+ f.flock(File::LOCK_EX)
11
+ has_lock = true
12
+ yield
13
+ f.flock(File::LOCK_UN)
14
+ end
15
+ rescue Errno::EACCES, Errno::ENOLCK
16
+ # In the case the user does not have access to
17
+ # create the lock file or is using NFS where
18
+ # locks are not available we skip locking.
19
+ yield
20
+ ensure
21
+ FileUtils.rm_f(lock_file_path) if has_lock
22
+ end
23
+ end
24
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Psych could be a gem, so try to ask for it
3
4
  begin
4
5
  gem "psych"
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "uri"
3
4
 
4
5
  module Bundler
@@ -1,178 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bundler
3
4
  class Resolver
4
5
  require "bundler/vendored_molinillo"
5
-
6
- class Molinillo::VersionConflict
7
- def printable_dep(dep)
8
- if dep.is_a?(Bundler::Dependency)
9
- DepProxy.new(dep, dep.platforms.join(", ")).to_s.strip
10
- else
11
- dep.to_s
12
- end
13
- end
14
-
15
- def message
16
- conflicts.sort.reduce(String.new) do |o, (name, conflict)|
17
- o << %(\nBundler could not find compatible versions for gem "#{name}":\n)
18
- if conflict.locked_requirement
19
- o << %( In snapshot (#{Bundler.default_lockfile.basename}):\n)
20
- o << %( #{printable_dep(conflict.locked_requirement)}\n)
21
- o << %(\n)
22
- end
23
- o << %( In Gemfile:\n)
24
- trees = conflict.requirement_trees
25
-
26
- maximal = 1.upto(trees.size).map do |size|
27
- trees.map(&:last).flatten(1).combination(size).to_a
28
- end.flatten(1).select do |deps|
29
- Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
30
- end.min_by(&:size)
31
- trees.reject! {|t| !maximal.include?(t.last) } if maximal
32
-
33
- o << trees.sort_by {|t| t.reverse.map(&:name) }.map do |tree|
34
- t = String.new
35
- depth = 2
36
- tree.each do |req|
37
- t << " " * depth << req.to_s
38
- unless tree.last == req
39
- if spec = conflict.activated_by_name[req.name]
40
- t << %( was resolved to #{spec.version}, which)
41
- end
42
- t << %( depends on)
43
- end
44
- t << %(\n)
45
- depth += 1
46
- end
47
- t
48
- end.join("\n")
49
-
50
- if name == "bundler"
51
- o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
52
- other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new Bundler::VERSION)
53
- end
54
-
55
- if name == "bundler" && other_bundler_required
56
- o << "\n"
57
- o << "This Gemfile requires a different version of Bundler.\n"
58
- o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
59
- end
60
- if conflict.locked_requirement
61
- o << "\n"
62
- o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
63
- o << %(the gems in your Gemfile, which may resolve the conflict.\n)
64
- elsif !conflict.existing
65
- o << "\n"
66
- if conflict.requirement_trees.first.size > 1
67
- o << "Could not find gem '#{conflict.requirement}', which is required by "
68
- o << "gem '#{conflict.requirement_trees.first[-2]}', in any of the sources."
69
- else
70
- o << "Could not find gem '#{conflict.requirement}' in any of the sources\n"
71
- end
72
- end
73
- o
74
- end.strip
75
- end
76
- end
77
-
78
- class SpecGroup < Array
79
- include GemHelpers
80
-
81
- attr_reader :activated
82
-
83
- def initialize(a)
84
- super
85
- @required_by = []
86
- @activated_platforms = []
87
- @dependencies = nil
88
- @specs = Hash.new do |specs, platform|
89
- specs[platform] = select_best_platform_match(self, platform)
90
- end
91
- end
92
-
93
- def initialize_copy(o)
94
- super
95
- @activated_platforms = o.activated.dup
96
- end
97
-
98
- def to_specs
99
- @activated_platforms.map do |p|
100
- next unless s = @specs[p]
101
- lazy_spec = LazySpecification.new(name, version, s.platform, source)
102
- lazy_spec.dependencies.replace s.dependencies
103
- lazy_spec
104
- end.compact
105
- end
106
-
107
- def activate_platform!(platform)
108
- return unless for?(platform)
109
- return if @activated_platforms.include?(platform)
110
- @activated_platforms << platform
111
- end
112
-
113
- def name
114
- @name ||= first.name
115
- end
116
-
117
- def version
118
- @version ||= first.version
119
- end
120
-
121
- def source
122
- @source ||= first.source
123
- end
124
-
125
- def for?(platform)
126
- spec = @specs[platform]
127
- !spec.nil?
128
- end
129
-
130
- def to_s
131
- "#{name} (#{version})"
132
- end
133
-
134
- def dependencies_for_activated_platforms
135
- dependencies = @activated_platforms.map {|p| __dependencies[p] }
136
- metadata_dependencies = @activated_platforms.map do |platform|
137
- metadata_dependencies(@specs[platform], platform)
138
- end
139
- dependencies.concat(metadata_dependencies).flatten
140
- end
141
-
142
- def platforms_for_dependency_named(dependency)
143
- __dependencies.select {|_, deps| deps.map(&:name).include? dependency }.keys
144
- end
145
-
146
- private
147
-
148
- def __dependencies
149
- @dependencies = Hash.new do |dependencies, platform|
150
- dependencies[platform] = []
151
- if spec = @specs[platform]
152
- spec.dependencies.each do |dep|
153
- next if dep.type == :development
154
- dependencies[platform] << DepProxy.new(dep, platform)
155
- end
156
- end
157
- dependencies[platform]
158
- end
159
- end
160
-
161
- def metadata_dependencies(spec, platform)
162
- return [] unless spec
163
- # Only allow endpoint specifications since they won't hit the network to
164
- # fetch the full gemspec when calling required_ruby_version
165
- return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
166
- dependencies = []
167
- if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
168
- dependencies << DepProxy.new(Gem::Dependency.new("ruby\0", spec.required_ruby_version), platform)
169
- end
170
- if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
171
- dependencies << DepProxy.new(Gem::Dependency.new("rubygems\0", spec.required_rubygems_version), platform)
172
- end
173
- dependencies
174
- end
175
- end
6
+ require "bundler/resolver/spec_group"
176
7
 
177
8
  # Figures out the best possible configuration of gems that satisfies
178
9
  # the list of passed dependencies and any child dependencies without
@@ -206,6 +37,7 @@ module Bundler
206
37
  additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
207
38
  @platforms = platforms
208
39
  @gem_version_promoter = gem_version_promoter
40
+ @allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts?
209
41
  end
210
42
 
211
43
  def start(requirements)
@@ -215,7 +47,8 @@ module Bundler
215
47
  reject {|sg| sg.name.end_with?("\0") }.
216
48
  map(&:to_specs).flatten
217
49
  rescue Molinillo::VersionConflict => e
218
- raise VersionConflict.new(e.conflicts.keys.uniq, e.message)
50
+ message = version_conflict_message(e)
51
+ raise VersionConflict.new(e.conflicts.keys.uniq, message)
219
52
  rescue Molinillo::CircularDependencyError => e
220
53
  names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
221
54
  raise CyclicDependencyError, "Your bundle requires gems that depend" \
@@ -281,7 +114,9 @@ module Bundler
281
114
  end
282
115
  nested.reduce([]) do |groups, (version, specs)|
283
116
  next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
284
- groups << SpecGroup.new(specs)
117
+ spec_group = SpecGroup.new(specs)
118
+ spec_group.ignores_bundler_dependencies = @allow_bundler_dependency_conflicts
119
+ groups << spec_group
285
120
  end
286
121
  else
287
122
  []
@@ -298,7 +133,22 @@ module Bundler
298
133
  end
299
134
 
300
135
  def index_for(dependency)
301
- @source_requirements[dependency.name] || @index
136
+ source = @source_requirements[dependency.name]
137
+ if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
138
+ Index.build do |idx|
139
+ if source
140
+ idx.add_source source.specs
141
+ elsif dependency.all_sources
142
+ dependency.all_sources.each {|s| idx.add_source(s.specs) if s }
143
+ else
144
+ idx.add_source @source_requirements[:default].specs
145
+ end
146
+ end
147
+ elsif source
148
+ source.specs
149
+ else
150
+ @index
151
+ end
302
152
  end
303
153
 
304
154
  def name_for(dependency)
@@ -319,12 +169,27 @@ module Bundler
319
169
 
320
170
  def requirement_satisfied_by?(requirement, activated, spec)
321
171
  return false unless requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
172
+ if spec.version.prerelease? && !requirement.prerelease? && search_for(requirement).any? {|sg| !sg.version.prerelease? }
173
+ vertex = activated.vertex_named(spec.name)
174
+ return false if vertex.requirements.none?(&:prerelease?)
175
+ end
322
176
  spec.activate_platform!(requirement.__platform) if !@platforms || @platforms.include?(requirement.__platform)
323
177
  true
324
178
  end
325
179
 
180
+ def relevant_sources_for_vertex(vertex)
181
+ if vertex.root?
182
+ [@source_requirements[vertex.name]]
183
+ elsif Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
184
+ vertex.recursive_predecessors.map do |v|
185
+ @source_requirements[v.name]
186
+ end << @source_requirements[:default]
187
+ end
188
+ end
189
+
326
190
  def sort_dependencies(dependencies, activated, conflicts)
327
191
  dependencies.sort_by do |dependency|
192
+ dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name))
328
193
  name = name_for(dependency)
329
194
  [
330
195
  @base_dg.vertex_named(name) ? 0 : 1,
@@ -332,10 +197,23 @@ module Bundler
332
197
  amount_constrained(dependency),
333
198
  conflicts[name] ? 0 : 1,
334
199
  activated.vertex_named(name).payload ? 0 : search_for(dependency).count,
200
+ self.class.platform_sort_key(dependency.__platform),
335
201
  ]
336
202
  end
337
203
  end
338
204
 
205
+ # Sort platforms from most general to most specific
206
+ def self.sort_platforms(platforms)
207
+ platforms.sort_by do |platform|
208
+ platform_sort_key(platform)
209
+ end
210
+ end
211
+
212
+ def self.platform_sort_key(platform)
213
+ return ["", "", ""] if Gem::Platform::RUBY == platform
214
+ platform.to_a.map {|part| part || "" }
215
+ end
216
+
339
217
  private
340
218
 
341
219
  # returns an integer \in (-\infty, 0]
@@ -364,32 +242,34 @@ module Bundler
364
242
 
365
243
  def verify_gemfile_dependencies_are_found!(requirements)
366
244
  requirements.each do |requirement|
367
- next if requirement.name == "bundler"
245
+ name = requirement.name
246
+ next if name == "bundler"
368
247
  next unless search_for(requirement).empty?
369
- if (base = @base[requirement.name]) && !base.empty?
248
+
249
+ cache_message = begin
250
+ " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
251
+ rescue GemfileNotFound
252
+ nil
253
+ end
254
+
255
+ if (base = @base[name]) && !base.empty?
370
256
  version = base.first.version
371
257
  message = "You have requested:\n" \
372
- " #{requirement.name} #{requirement.requirement}\n\n" \
373
- "The bundle currently has #{requirement.name} locked at #{version}.\n" \
374
- "Try running `bundle update #{requirement.name}`\n\n" \
258
+ " #{name} #{requirement.requirement}\n\n" \
259
+ "The bundle currently has #{name} locked at #{version}.\n" \
260
+ "Try running `bundle update #{name}`\n\n" \
375
261
  "If you are updating multiple gems in your Gemfile at once,\n" \
376
262
  "try passing them all to `bundle update`"
377
- elsif requirement.source
378
- name = requirement.name
379
- specs = @source_requirements[name][name]
263
+ elsif source = @source_requirements[name]
264
+ specs = source.specs[name]
380
265
  versions_with_platforms = specs.map {|s| [s.version, s.platform] }
381
- message = String.new("Could not find gem '#{requirement}' in #{requirement.source}.\n")
266
+ message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n")
382
267
  message << if versions_with_platforms.any?
383
- "Source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}"
268
+ "The source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}"
384
269
  else
385
- "Source does not contain any versions of '#{requirement}'"
270
+ "The source does not contain any versions of '#{name}'"
386
271
  end
387
272
  else
388
- cache_message = begin
389
- " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
390
- rescue GemfileNotFound
391
- nil
392
- end
393
273
  message = "Could not find gem '#{requirement}' in any of the gem sources " \
394
274
  "listed in your Gemfile#{cache_message}."
395
275
  end
@@ -402,9 +282,76 @@ module Bundler
402
282
  version = vwp.first
403
283
  platform = vwp.last
404
284
  version_platform_str = String.new(version.to_s)
405
- version_platform_str << " #{platform}" unless platform.nil?
285
+ version_platform_str << " #{platform}" unless platform.nil? || platform == Gem::Platform::RUBY
286
+ version_platform_str
406
287
  end
407
288
  version_platform_strs.join(", ")
408
289
  end
290
+
291
+ def version_conflict_message(e)
292
+ e.message_with_trees(
293
+ :solver_name => "Bundler",
294
+ :possibility_type => "gem",
295
+ :reduce_trees => lambda do |trees|
296
+ maximal = 1.upto(trees.size).map do |size|
297
+ trees.map(&:last).flatten(1).combination(size).to_a
298
+ end.flatten(1).select do |deps|
299
+ Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
300
+ end.min_by(&:size)
301
+ trees.reject! {|t| !maximal.include?(t.last) } if maximal
302
+
303
+ trees = trees.sort_by {|t| t.flatten.map(&:to_s) }
304
+ trees.uniq! {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
305
+
306
+ trees.sort_by {|t| t.reverse.map(&:name) }
307
+ end,
308
+ :printable_requirement => lambda {|req| SharedHelpers.pretty_dependency(req) },
309
+ :additional_message_for_conflict => lambda do |o, name, conflict|
310
+ if name == "bundler"
311
+ o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
312
+ other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new Bundler::VERSION)
313
+ end
314
+
315
+ if name == "bundler" && other_bundler_required
316
+ o << "\n"
317
+ o << "This Gemfile requires a different version of Bundler.\n"
318
+ o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
319
+ end
320
+ if conflict.locked_requirement
321
+ o << "\n"
322
+ o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
323
+ o << %(the gems in your Gemfile, which may resolve the conflict.\n)
324
+ elsif !conflict.existing
325
+ o << "\n"
326
+
327
+ relevant_sources = if conflict.requirement.source
328
+ [conflict.requirement.source]
329
+ elsif conflict.requirement.all_sources
330
+ conflict.requirement.all_sources
331
+ elsif Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
332
+ # every conflict should have an explicit group of sources when we
333
+ # enforce strict pinning
334
+ raise "no source set for #{conflict}"
335
+ else
336
+ []
337
+ end.compact.map(&:to_s).uniq.sort
338
+
339
+ o << "Could not find gem '#{SharedHelpers.pretty_dependency(conflict.requirement)}'"
340
+ if conflict.requirement_trees.first.size > 1
341
+ o << ", which is required by "
342
+ o << "gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
343
+ end
344
+ o << " "
345
+
346
+ o << if relevant_sources.empty?
347
+ "in any of the sources.\n"
348
+ else
349
+ "in any of the relevant sources:\n #{relevant_sources * "\n "}\n"
350
+ end
351
+ end
352
+ end,
353
+ :version_for_spec => lambda {|spec| spec.version }
354
+ )
355
+ end
409
356
  end
410
357
  end