bundler 2.2.26 → 2.3.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +501 -1
  3. data/README.md +1 -1
  4. data/bundler.gemspec +6 -8
  5. data/exe/bundle +7 -8
  6. data/exe/bundler +1 -1
  7. data/lib/bundler/.document +1 -0
  8. data/lib/bundler/build_metadata.rb +3 -3
  9. data/lib/bundler/cli/check.rb +1 -1
  10. data/lib/bundler/cli/common.rb +3 -2
  11. data/lib/bundler/cli/config.rb +10 -1
  12. data/lib/bundler/cli/doctor.rb +12 -3
  13. data/lib/bundler/cli/gem.rb +98 -9
  14. data/lib/bundler/cli/info.rb +27 -6
  15. data/lib/bundler/cli/init.rb +5 -1
  16. data/lib/bundler/cli/install.rb +13 -30
  17. data/lib/bundler/cli/issue.rb +4 -3
  18. data/lib/bundler/cli/outdated.rb +12 -3
  19. data/lib/bundler/cli/platform.rb +2 -2
  20. data/lib/bundler/cli/remove.rb +1 -2
  21. data/lib/bundler/cli/show.rb +1 -1
  22. data/lib/bundler/cli/update.rb +8 -4
  23. data/lib/bundler/cli.rb +23 -19
  24. data/lib/bundler/compact_index_client/cache.rb +0 -9
  25. data/lib/bundler/compact_index_client/updater.rb +16 -8
  26. data/lib/bundler/compact_index_client.rb +2 -8
  27. data/lib/bundler/current_ruby.rb +16 -6
  28. data/lib/bundler/definition.rb +204 -217
  29. data/lib/bundler/dependency.rb +23 -71
  30. data/lib/bundler/digest.rb +71 -0
  31. data/lib/bundler/dsl.rb +28 -45
  32. data/lib/bundler/endpoint_specification.rb +19 -13
  33. data/lib/bundler/env.rb +1 -1
  34. data/lib/bundler/environment_preserver.rb +4 -1
  35. data/lib/bundler/errors.rb +28 -2
  36. data/lib/bundler/feature_flag.rb +0 -1
  37. data/lib/bundler/fetcher/base.rb +6 -8
  38. data/lib/bundler/fetcher/compact_index.rb +9 -14
  39. data/lib/bundler/fetcher/index.rb +0 -26
  40. data/lib/bundler/fetcher.rb +20 -22
  41. data/lib/bundler/friendly_errors.rb +26 -34
  42. data/lib/bundler/gem_helper.rb +7 -18
  43. data/lib/bundler/gem_helpers.rb +9 -2
  44. data/lib/bundler/gem_version_promoter.rb +14 -25
  45. data/lib/bundler/index.rb +10 -40
  46. data/lib/bundler/injector.rb +16 -2
  47. data/lib/bundler/inline.rb +2 -12
  48. data/lib/bundler/installer/gem_installer.rb +13 -5
  49. data/lib/bundler/installer/standalone.rb +30 -3
  50. data/lib/bundler/installer.rb +18 -29
  51. data/lib/bundler/lazy_specification.rb +52 -35
  52. data/lib/bundler/lockfile_generator.rb +2 -2
  53. data/lib/bundler/lockfile_parser.rb +12 -10
  54. data/lib/bundler/man/bundle-add.1 +21 -5
  55. data/lib/bundler/man/bundle-add.1.ronn +16 -4
  56. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  57. data/lib/bundler/man/bundle-cache.1 +7 -1
  58. data/lib/bundler/man/bundle-cache.1.ronn +7 -0
  59. data/lib/bundler/man/bundle-check.1 +1 -1
  60. data/lib/bundler/man/bundle-clean.1 +2 -2
  61. data/lib/bundler/man/bundle-clean.1.ronn +1 -1
  62. data/lib/bundler/man/bundle-config.1 +33 -14
  63. data/lib/bundler/man/bundle-config.1.ronn +30 -18
  64. data/lib/bundler/man/bundle-console.1 +53 -0
  65. data/lib/bundler/man/bundle-console.1.ronn +44 -0
  66. data/lib/bundler/man/bundle-doctor.1 +1 -1
  67. data/lib/bundler/man/bundle-exec.1 +2 -2
  68. data/lib/bundler/man/bundle-exec.1.ronn +1 -1
  69. data/lib/bundler/man/bundle-gem.1 +14 -1
  70. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  71. data/lib/bundler/man/bundle-help.1 +13 -0
  72. data/lib/bundler/man/bundle-help.1.ronn +12 -0
  73. data/lib/bundler/man/bundle-info.1 +1 -1
  74. data/lib/bundler/man/bundle-init.1 +1 -1
  75. data/lib/bundler/man/bundle-inject.1 +5 -2
  76. data/lib/bundler/man/bundle-inject.1.ronn +3 -1
  77. data/lib/bundler/man/bundle-install.1 +6 -2
  78. data/lib/bundler/man/bundle-install.1.ronn +8 -2
  79. data/lib/bundler/man/bundle-list.1 +1 -1
  80. data/lib/bundler/man/bundle-lock.1 +1 -1
  81. data/lib/bundler/man/bundle-open.1 +1 -1
  82. data/lib/bundler/man/bundle-outdated.1 +3 -10
  83. data/lib/bundler/man/bundle-outdated.1.ronn +1 -10
  84. data/lib/bundler/man/bundle-platform.1 +16 -6
  85. data/lib/bundler/man/bundle-platform.1.ronn +14 -7
  86. data/lib/bundler/man/bundle-plugin.1 +81 -0
  87. data/lib/bundler/man/bundle-plugin.1.ronn +59 -0
  88. data/lib/bundler/man/bundle-pristine.1 +1 -1
  89. data/lib/bundler/man/bundle-remove.1 +1 -1
  90. data/lib/bundler/man/bundle-show.1 +1 -1
  91. data/lib/bundler/man/bundle-update.1 +2 -2
  92. data/lib/bundler/man/bundle-update.1.ronn +2 -1
  93. data/lib/bundler/man/bundle-version.1 +35 -0
  94. data/lib/bundler/man/bundle-version.1.ronn +24 -0
  95. data/lib/bundler/man/bundle-viz.1 +4 -1
  96. data/lib/bundler/man/bundle-viz.1.ronn +2 -0
  97. data/lib/bundler/man/bundle.1 +15 -10
  98. data/lib/bundler/man/bundle.1.ronn +12 -7
  99. data/lib/bundler/man/gemfile.5 +117 -80
  100. data/lib/bundler/man/gemfile.5.ronn +105 -84
  101. data/lib/bundler/man/index.txt +4 -0
  102. data/lib/bundler/match_metadata.rb +13 -0
  103. data/lib/bundler/match_platform.rb +0 -1
  104. data/lib/bundler/match_remote_metadata.rb +29 -0
  105. data/lib/bundler/plugin/api/source.rb +4 -9
  106. data/lib/bundler/plugin/installer/git.rb +0 -4
  107. data/lib/bundler/plugin/installer/rubygems.rb +0 -4
  108. data/lib/bundler/plugin/installer.rb +3 -1
  109. data/lib/bundler/plugin.rb +25 -6
  110. data/lib/bundler/process_lock.rb +1 -1
  111. data/lib/bundler/remote_specification.rb +10 -4
  112. data/lib/bundler/resolver/base.rb +50 -0
  113. data/lib/bundler/resolver/spec_group.rb +31 -49
  114. data/lib/bundler/resolver.rb +183 -192
  115. data/lib/bundler/ruby_dsl.rb +1 -1
  116. data/lib/bundler/ruby_version.rb +5 -18
  117. data/lib/bundler/rubygems_ext.rb +138 -20
  118. data/lib/bundler/rubygems_gem_installer.rb +42 -16
  119. data/lib/bundler/rubygems_integration.rb +42 -90
  120. data/lib/bundler/runtime.rb +2 -3
  121. data/lib/bundler/self_manager.rb +168 -0
  122. data/lib/bundler/settings.rb +13 -4
  123. data/lib/bundler/shared_helpers.rb +15 -24
  124. data/lib/bundler/source/git/git_proxy.rb +7 -4
  125. data/lib/bundler/source/git.rb +29 -13
  126. data/lib/bundler/source/metadata.rb +3 -3
  127. data/lib/bundler/source/path.rb +1 -1
  128. data/lib/bundler/source/rubygems.rb +148 -161
  129. data/lib/bundler/source/rubygems_aggregate.rb +1 -1
  130. data/lib/bundler/source.rb +6 -5
  131. data/lib/bundler/source_list.rb +15 -29
  132. data/lib/bundler/source_map.rb +15 -2
  133. data/lib/bundler/spec_set.rb +52 -32
  134. data/lib/bundler/stub_specification.rb +5 -3
  135. data/lib/bundler/templates/Executable +2 -4
  136. data/lib/bundler/templates/Executable.bundler +2 -2
  137. data/lib/bundler/templates/Executable.standalone +2 -4
  138. data/lib/bundler/templates/Gemfile +0 -2
  139. data/lib/bundler/templates/gems.rb +0 -3
  140. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  141. data/lib/bundler/templates/newgem/README.md.tt +3 -9
  142. data/lib/bundler/templates/newgem/Rakefile.tt +15 -2
  143. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +5 -4
  144. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +5 -4
  145. data/lib/bundler/templates/newgem/newgem.gemspec.tt +16 -16
  146. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  147. data/lib/bundler/templates/newgem/standard.yml.tt +3 -0
  148. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  149. data/lib/bundler/ui/shell.rb +1 -1
  150. data/lib/bundler/vendor/.document +1 -0
  151. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  152. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  153. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  154. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  155. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  156. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  157. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  158. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -3
  159. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +32 -26
  160. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  161. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  162. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  163. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +6 -6
  164. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -2
  165. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -2
  166. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  167. data/lib/bundler/vendor/thor/lib/thor/error.rb +9 -4
  168. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +19 -1
  169. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +22 -4
  170. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  171. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  172. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  173. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  174. data/lib/bundler/vendor/tsort/lib/tsort.rb +452 -0
  175. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  176. data/lib/bundler/vendor/uri/lib/uri/common.rb +17 -80
  177. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -1
  178. data/lib/bundler/vendor/uri/lib/uri/generic.rb +5 -6
  179. data/lib/bundler/vendor/uri/lib/uri/http.rb +0 -1
  180. data/lib/bundler/vendor/uri/lib/uri/https.rb +0 -1
  181. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  182. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -1
  183. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +1 -14
  184. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +1 -12
  185. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  186. data/lib/bundler/vendor/uri/lib/uri/ws.rb +84 -0
  187. data/lib/bundler/vendor/uri/lib/uri/wss.rb +22 -0
  188. data/lib/bundler/vendor/uri/lib/uri.rb +0 -1
  189. data/lib/bundler/vendored_tsort.rb +4 -0
  190. data/lib/bundler/version.rb +1 -1
  191. data/lib/bundler/worker.rb +2 -2
  192. data/lib/bundler.rb +40 -29
  193. metadata +37 -12
  194. data/lib/bundler/dep_proxy.rb +0 -55
  195. data/lib/bundler/gemdeps.rb +0 -29
  196. data/lib/bundler/psyched_yaml.rb +0 -22
  197. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class Resolver
5
+ class Base
6
+ def initialize(base, additional_base_requirements)
7
+ @base = base
8
+ @additional_base_requirements = additional_base_requirements
9
+ end
10
+
11
+ def [](name)
12
+ @base[name]
13
+ end
14
+
15
+ def delete(spec)
16
+ @base.delete(spec)
17
+ end
18
+
19
+ def base_requirements
20
+ @base_requirements ||= build_base_requirements
21
+ end
22
+
23
+ def unlock_deps(deps)
24
+ exact, lower_bound = deps.partition(&:specific?)
25
+
26
+ exact.each do |exact_dep|
27
+ @base.delete_by_name_and_version(exact_dep.name, exact_dep.requirement.requirements.first.last)
28
+ end
29
+
30
+ lower_bound.each do |lower_bound_dep|
31
+ @additional_base_requirements.delete(lower_bound_dep)
32
+ end
33
+
34
+ @base_requirements = nil
35
+ end
36
+
37
+ private
38
+
39
+ def build_base_requirements
40
+ base_requirements = {}
41
+ @base.each do |ls|
42
+ dep = Dependency.new(ls.name, ls.version)
43
+ base_requirements[ls.name] = dep
44
+ end
45
+ @additional_base_requirements.each {|d| base_requirements[d.name] = d }
46
+ base_requirements
47
+ end
48
+ end
49
+ end
50
+ end
@@ -4,41 +4,25 @@ module Bundler
4
4
  class Resolver
5
5
  class SpecGroup
6
6
  attr_accessor :name, :version, :source
7
- attr_accessor :activated_platforms
7
+ attr_accessor :activated_platforms, :force_ruby_platform
8
8
 
9
- def self.create_for(specs, all_platforms, specific_platform)
10
- specific_platform_specs = specs[specific_platform]
11
- return unless specific_platform_specs.any?
12
-
13
- platforms = all_platforms.select {|p| specs[p].any? }
14
-
15
- new(specific_platform_specs.first, specs, platforms)
16
- end
17
-
18
- def initialize(exemplary_spec, specs, relevant_platforms)
19
- @exemplary_spec = exemplary_spec
20
- @name = exemplary_spec.name
21
- @version = exemplary_spec.version
22
- @source = exemplary_spec.source
9
+ def initialize(specs, relevant_platforms)
10
+ @exemplary_spec = specs.first
11
+ @name = @exemplary_spec.name
12
+ @version = @exemplary_spec.version
13
+ @source = @exemplary_spec.source
23
14
 
24
15
  @activated_platforms = relevant_platforms
25
- @dependencies = Hash.new do |dependencies, platforms|
26
- dependencies[platforms] = dependencies_for(platforms)
27
- end
28
16
  @specs = specs
29
17
  end
30
18
 
31
19
  def to_specs
32
- activated_platforms.map do |p|
33
- specs = @specs[p]
34
- next unless specs.any?
35
-
36
- specs.map do |s|
37
- lazy_spec = LazySpecification.new(name, version, s.platform, source)
38
- lazy_spec.dependencies.replace s.dependencies
39
- lazy_spec
40
- end
41
- end.flatten.compact.uniq
20
+ @specs.map do |s|
21
+ lazy_spec = LazySpecification.new(name, version, s.platform, source)
22
+ lazy_spec.force_ruby_platform = force_ruby_platform
23
+ lazy_spec.dependencies.replace s.dependencies
24
+ lazy_spec
25
+ end
42
26
  end
43
27
 
44
28
  def to_s
@@ -47,7 +31,9 @@ module Bundler
47
31
  end
48
32
 
49
33
  def dependencies_for_activated_platforms
50
- @dependencies[activated_platforms]
34
+ @dependencies_for_activated_platforms ||= @specs.map do |spec|
35
+ __dependencies(spec) + metadata_dependencies(spec)
36
+ end.flatten.uniq
51
37
  end
52
38
 
53
39
  def ==(other)
@@ -78,32 +64,28 @@ module Bundler
78
64
 
79
65
  private
80
66
 
81
- def dependencies_for(platforms)
82
- platforms.map do |platform|
83
- __dependencies(platform) + metadata_dependencies(platform)
84
- end.flatten
85
- end
86
-
87
- def __dependencies(platform)
67
+ def __dependencies(spec)
88
68
  dependencies = []
89
- @specs[platform].first.dependencies.each do |dep|
69
+ spec.dependencies.each do |dep|
90
70
  next if dep.type == :development
91
- dependencies << DepProxy.get_proxy(dep, platform)
71
+ dependencies << Dependency.new(dep.name, dep.requirement)
92
72
  end
93
73
  dependencies
94
74
  end
95
75
 
96
- def metadata_dependencies(platform)
97
- spec = @specs[platform].first
98
- return [] unless spec.is_a?(Gem::Specification)
99
- dependencies = []
100
- if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
101
- dependencies << DepProxy.get_proxy(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
102
- end
103
- if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
104
- dependencies << DepProxy.get_proxy(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
105
- end
106
- dependencies
76
+ def metadata_dependencies(spec)
77
+ return [] if spec.is_a?(LazySpecification)
78
+
79
+ [
80
+ metadata_dependency("Ruby", spec.required_ruby_version),
81
+ metadata_dependency("RubyGems", spec.required_rubygems_version),
82
+ ].compact
83
+ end
84
+
85
+ def metadata_dependency(name, requirement)
86
+ return if requirement.nil? || requirement.none?
87
+
88
+ Dependency.new("#{name}\0", requirement)
107
89
  end
108
90
  end
109
91
  end
@@ -3,60 +3,54 @@
3
3
  module Bundler
4
4
  class Resolver
5
5
  require_relative "vendored_molinillo"
6
+ require_relative "resolver/base"
6
7
  require_relative "resolver/spec_group"
7
8
 
8
9
  include GemHelpers
9
10
 
10
- # Figures out the best possible configuration of gems that satisfies
11
- # the list of passed dependencies and any child dependencies without
12
- # causing any gem activation errors.
13
- #
14
- # ==== Parameters
15
- # *dependencies<Gem::Dependency>:: The list of dependencies to resolve
16
- #
17
- # ==== Returns
18
- # <GemBundle>,nil:: If the list of dependencies can be resolved, a
19
- # collection of gemspecs is returned. Otherwise, nil is returned.
20
- def self.resolve(requirements, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
21
- base = SpecSet.new(base) unless base.is_a?(SpecSet)
22
- resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
23
- result = resolver.start(requirements)
24
- SpecSet.new(SpecSet.new(result).for(requirements.reject{|dep| dep.name.end_with?("\0") }))
25
- end
26
-
27
11
  def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
28
12
  @source_requirements = source_requirements
29
- @base = base
13
+ @base = Resolver::Base.new(base, additional_base_requirements)
30
14
  @resolver = Molinillo::Resolver.new(self, self)
15
+ @results_for = {}
31
16
  @search_for = {}
32
- @base_dg = Molinillo::DependencyGraph.new
33
- aggregate_global_source = @source_requirements[:default].is_a?(Source::RubygemsAggregate)
34
- @base.each do |ls|
35
- dep = Dependency.new(ls.name, ls.version)
36
- ls.source = source_for(ls.name) unless aggregate_global_source
37
- @base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true)
38
- end
39
- additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
40
- @platforms = platforms.reject {|p| p != Gem::Platform::RUBY && (platforms - [p]).any? {|pl| generic(pl) == p } }
17
+ @platforms = platforms
41
18
  @resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
42
19
  @gem_version_promoter = gem_version_promoter
43
- @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
44
20
  end
45
21
 
46
- def start(requirements)
47
- @gem_version_promoter.prerelease_specified = @prerelease_specified = {}
48
- requirements.each {|dep| @prerelease_specified[dep.name] ||= dep.prerelease? }
22
+ def start(requirements, exclude_specs: [])
23
+ @metadata_requirements, regular_requirements = requirements.partition {|dep| dep.name.end_with?("\0") }
24
+
25
+ exclude_specs.each do |spec|
26
+ remove_from_candidates(spec)
27
+ end
28
+
29
+ requirements.each {|dep| prerelease_specified[dep.name] ||= dep.prerelease? }
49
30
 
50
31
  verify_gemfile_dependencies_are_found!(requirements)
51
- dg = @resolver.resolve(requirements, @base_dg)
52
- dg.
32
+ result = @resolver.resolve(requirements).
53
33
  map(&:payload).
54
34
  reject {|sg| sg.name.end_with?("\0") }.
55
35
  map(&:to_specs).
56
36
  flatten
37
+
38
+ SpecSet.new(SpecSet.new(result).for(regular_requirements, false, @platforms))
57
39
  rescue Molinillo::VersionConflict => e
40
+ conflicts = e.conflicts
41
+
42
+ deps_to_unlock = conflicts.values.inject([]) do |deps, conflict|
43
+ deps |= conflict.requirement_trees.flatten.map {|req| base_requirements[req.name] }.compact
44
+ end
45
+
46
+ if deps_to_unlock.any?
47
+ @base.unlock_deps(deps_to_unlock)
48
+ reset_spec_cache
49
+ retry
50
+ end
51
+
58
52
  message = version_conflict_message(e)
59
- raise VersionConflict.new(e.conflicts.keys.uniq, message)
53
+ raise VersionConflict.new(conflicts.keys.uniq, message)
60
54
  rescue Molinillo::CircularDependencyError => e
61
55
  names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
62
56
  raise CyclicDependencyError, "Your bundle requires gems that depend" \
@@ -106,60 +100,35 @@ module Bundler
106
100
  specification.dependencies_for_activated_platforms
107
101
  end
108
102
 
109
- def search_for(dependency_proxy)
110
- platform = dependency_proxy.__platform
111
- dependency = dependency_proxy.dep
112
- name = dependency.name
113
- @search_for[dependency_proxy] ||= begin
114
- results = results_for(dependency, @base[name])
115
-
116
- if vertex = @base_dg.vertex_named(name)
117
- locked_requirement = vertex.payload.requirement
118
- end
119
-
120
- if !@prerelease_specified[name] && (!@use_gvp || locked_requirement.nil?)
121
- # Move prereleases to the beginning of the list, so they're considered
122
- # last during resolution.
123
- pre, results = results.partition {|spec| spec.version.prerelease? }
124
- results = pre + results
125
- end
126
-
127
- spec_groups = if results.any?
128
- nested = []
129
- results.each do |spec|
130
- version, specs = nested.last
131
- if version == spec.version
132
- specs << spec
133
- else
134
- nested << [spec.version, [spec]]
135
- end
103
+ def search_for(dependency)
104
+ @search_for[dependency] ||= begin
105
+ name = dependency.name
106
+ locked_results = @base[name].select {|spec| requirement_satisfied_by?(dependency, nil, spec) }
107
+ locked_requirement = base_requirements[name]
108
+ results = results_for(dependency) + locked_results
109
+ results = results.select {|spec| requirement_satisfied_by?(locked_requirement, nil, spec) } if locked_requirement
110
+ dep_platforms = dependency.gem_platforms(@platforms)
111
+
112
+ @gem_version_promoter.sort_versions(dependency, results).group_by(&:version).reduce([]) do |groups, (_, specs)|
113
+ relevant_platforms = dep_platforms.select {|platform| specs.any? {|spec| spec.match_platform(platform) } }
114
+ next groups unless relevant_platforms.any?
115
+
116
+ ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
117
+ if ruby_specs.any?
118
+ spec_group_ruby = SpecGroup.new(ruby_specs, [Gem::Platform::RUBY])
119
+ spec_group_ruby.force_ruby_platform = dependency.force_ruby_platform
120
+ groups << spec_group_ruby
136
121
  end
137
- nested.reduce([]) do |groups, (version, specs)|
138
- next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
139
-
140
- specs_by_platform = Hash.new do |current_specs, current_platform|
141
- current_specs[current_platform] = select_best_platform_match(specs, current_platform)
142
- end
143
122
 
144
- spec_group_ruby = SpecGroup.create_for(specs_by_platform, [Gem::Platform::RUBY], Gem::Platform::RUBY)
145
- groups << spec_group_ruby if spec_group_ruby
123
+ next groups if @resolving_only_for_ruby || dependency.force_ruby_platform
146
124
 
147
- next groups if @resolving_only_for_ruby
125
+ platform_specs = relevant_platforms.flat_map {|platform| select_best_platform_match(specs, platform) }
126
+ next groups if platform_specs == ruby_specs
148
127
 
149
- spec_group = SpecGroup.create_for(specs_by_platform, @platforms, platform)
150
- groups << spec_group if spec_group
128
+ spec_group = SpecGroup.new(platform_specs, relevant_platforms)
129
+ groups << spec_group
151
130
 
152
- groups
153
- end
154
- else
155
- []
156
- end
157
- # GVP handles major itself, but it's still a bit risky to trust it with it
158
- # until we get it settled with new behavior. For 2.x it can take over all cases.
159
- if !@use_gvp
160
- spec_groups
161
- else
162
- @gem_version_promoter.sort_versions(dependency, spec_groups)
131
+ groups
163
132
  end
164
133
  end
165
134
  end
@@ -172,8 +141,8 @@ module Bundler
172
141
  @source_requirements[name] || @source_requirements[:default]
173
142
  end
174
143
 
175
- def results_for(dependency, base)
176
- index_for(dependency).search(dependency, base)
144
+ def results_for(dependency)
145
+ @results_for[dependency] ||= index_for(dependency).search(dependency)
177
146
  end
178
147
 
179
148
  def name_for(dependency)
@@ -186,43 +155,51 @@ module Bundler
186
155
  "Gemfile"
187
156
  end
188
157
 
189
- def name_for_locking_dependency_source
190
- Bundler.default_lockfile.basename.to_s
191
- rescue StandardError
192
- "Gemfile.lock"
193
- end
194
-
195
158
  def requirement_satisfied_by?(requirement, activated, spec)
196
159
  requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
197
160
  end
198
161
 
199
- def dependencies_equal?(dependencies, other_dependencies)
200
- dependencies.map(&:dep) == other_dependencies.map(&:dep)
201
- end
202
-
203
162
  def sort_dependencies(dependencies, activated, conflicts)
204
163
  dependencies.sort_by do |dependency|
205
164
  name = name_for(dependency)
206
165
  vertex = activated.vertex_named(name)
207
166
  [
208
- @base_dg.vertex_named(name) ? 0 : 1,
167
+ @base[name].any? ? 0 : 1,
209
168
  vertex.payload ? 0 : 1,
210
169
  vertex.root? ? 0 : 1,
211
170
  amount_constrained(dependency),
212
171
  conflicts[name] ? 0 : 1,
213
172
  vertex.payload ? 0 : search_for(dependency).count,
214
- self.class.platform_sort_key(dependency.__platform),
215
173
  ]
216
174
  end
217
175
  end
218
176
 
219
- def self.platform_sort_key(platform)
220
- # Prefer specific platform to not specific platform
221
- return ["99-LAST", "", "", ""] if Gem::Platform::RUBY == platform
222
- ["00", *platform.to_a.map {|part| part || "" }]
177
+ private
178
+
179
+ def base_requirements
180
+ @base.base_requirements
223
181
  end
224
182
 
225
- private
183
+ def prerelease_specified
184
+ @gem_version_promoter.prerelease_specified
185
+ end
186
+
187
+ def remove_from_candidates(spec)
188
+ @base.delete(spec)
189
+
190
+ @results_for.keys.each do |dep|
191
+ next unless dep.name == spec.name
192
+
193
+ @results_for[dep].reject {|s| s.name == spec.name && s.version == spec.version }
194
+ end
195
+
196
+ reset_spec_cache
197
+ end
198
+
199
+ def reset_spec_cache
200
+ @search_for = {}
201
+ @gem_version_promoter.reset
202
+ end
226
203
 
227
204
  # returns an integer \in (-\infty, 0]
228
205
  # a number closer to 0 means the dependency is less constraining
@@ -232,62 +209,60 @@ module Bundler
232
209
  # before dependencies that are unconstrained
233
210
  def amount_constrained(dependency)
234
211
  @amount_constrained ||= {}
235
- @amount_constrained[dependency.name] ||= begin
236
- if (base = @base[dependency.name]) && !base.empty?
237
- dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1
238
- else
239
- all = index_for(dependency).search(dependency.name).size
212
+ @amount_constrained[dependency.name] ||= if (base = @base[dependency.name]) && !base.empty?
213
+ dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1
214
+ else
215
+ all = index_for(dependency).search(dependency.name).size
240
216
 
241
- if all <= 1
242
- all - 1_000_000
243
- else
244
- search = search_for(dependency)
245
- search = @prerelease_specified[dependency.name] ? search.count : search.count {|s| !s.version.prerelease? }
246
- search - all
247
- end
217
+ if all <= 1
218
+ all - 1_000_000
219
+ else
220
+ search = search_for(dependency)
221
+ search = prerelease_specified[dependency.name] ? search.count : search.count {|s| !s.version.prerelease? }
222
+ search - all
248
223
  end
249
224
  end
250
225
  end
251
226
 
252
227
  def verify_gemfile_dependencies_are_found!(requirements)
253
- requirements.each do |requirement|
228
+ requirements.map! do |requirement|
254
229
  name = requirement.name
255
- next if name == "bundler"
256
- next unless search_for(requirement).empty?
257
-
258
- if (base = @base[name]) && !base.empty?
259
- version = base.first.version
260
- message = "You have requested:\n" \
261
- " #{name} #{requirement.requirement}\n\n" \
262
- "The bundle currently has #{name} locked at #{version}.\n" \
263
- "Try running `bundle update #{name}`\n\n" \
264
- "If you are updating multiple gems in your Gemfile at once,\n" \
265
- "try passing them all to `bundle update`"
266
- else
267
- source = source_for(name)
268
- specs = source.specs.search(name)
269
- versions_with_platforms = specs.map {|s| [s.version, s.platform] }
270
- cache_message = begin
271
- " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
272
- rescue GemfileNotFound
273
- nil
274
- end
275
- message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source.to_err}#{cache_message}.\n")
276
- message << "The source contains the following versions of '#{name}': #{formatted_versions_with_platforms(versions_with_platforms)}" if versions_with_platforms.any?
277
- end
278
- raise GemNotFound, message
279
- end
230
+ next requirement if name == "bundler"
231
+ next if requirement.gem_platforms(@platforms).empty?
232
+ next requirement unless search_for(requirement).empty?
233
+ next unless requirement.current_platform?
234
+
235
+ raise GemNotFound, gem_not_found_message(name, requirement, source_for(name))
236
+ end.compact!
280
237
  end
281
238
 
282
- def formatted_versions_with_platforms(versions_with_platforms)
283
- version_platform_strs = versions_with_platforms.map do |vwp|
284
- version = vwp.first
285
- platform = vwp.last
286
- version_platform_str = String.new(version.to_s)
287
- version_platform_str << " #{platform}" unless platform.nil? || platform == Gem::Platform::RUBY
288
- version_platform_str
239
+ def gem_not_found_message(name, requirement, source, extra_message = "")
240
+ specs = source.specs.search(name).sort_by {|s| [s.version, s.platform.to_s] }
241
+ matching_part = name
242
+ requirement_label = SharedHelpers.pretty_dependency(requirement)
243
+ cache_message = begin
244
+ " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
245
+ rescue GemfileNotFound
246
+ nil
247
+ end
248
+ specs_matching_requirement = specs.select {| spec| requirement.matches_spec?(spec) }
249
+
250
+ if specs_matching_requirement.any?
251
+ specs = specs_matching_requirement
252
+ matching_part = requirement_label
253
+ platforms = requirement.gem_platforms(@platforms)
254
+ platform_label = platforms.size == 1 ? "platform '#{platforms.first}" : "platforms '#{platforms.join("', '")}"
255
+ requirement_label = "#{requirement_label}' with #{platform_label}"
256
+ end
257
+
258
+ message = String.new("Could not find gem '#{requirement_label}'#{extra_message} in #{source}#{cache_message}.\n")
259
+
260
+ if specs.any?
261
+ message << "\nThe source contains the following gems matching '#{matching_part}':\n"
262
+ message << specs.map {|s| " * #{s.full_name}" }.join("\n")
289
263
  end
290
- version_platform_strs.join(", ")
264
+
265
+ message
291
266
  end
292
267
 
293
268
  def version_conflict_message(e)
@@ -305,29 +280,62 @@ module Bundler
305
280
 
306
281
  e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty?
307
282
 
308
- solver_name = "Bundler"
309
- possibility_type = "gem"
310
283
  e.message_with_trees(
311
- :solver_name => solver_name,
312
- :possibility_type => possibility_type,
313
- :reduce_trees => lambda do |trees|
284
+ :full_message_for_conflict => lambda do |name, conflict|
285
+ trees = conflict.requirement_trees
286
+
314
287
  # called first, because we want to reduce the amount of work required to find maximal empty sets
315
288
  trees = trees.uniq {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
316
289
 
317
290
  # bail out if tree size is too big for Array#combination to make any sense
318
- return trees if trees.size > 15
319
- maximal = 1.upto(trees.size).map do |size|
320
- trees.map(&:last).flatten(1).combination(size).to_a
321
- end.flatten(1).select do |deps|
322
- Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
323
- end.min_by(&:size)
324
-
325
- trees.reject! {|t| !maximal.include?(t.last) } if maximal
326
-
327
- trees.sort_by {|t| t.reverse.map(&:name) }
328
- end,
329
- :printable_requirement => lambda {|req| SharedHelpers.pretty_dependency(req) },
330
- :additional_message_for_conflict => lambda do |o, name, conflict|
291
+ if trees.size <= 15
292
+ maximal = 1.upto(trees.size).map do |size|
293
+ trees.map(&:last).flatten(1).combination(size).to_a
294
+ end.flatten(1).select do |deps|
295
+ Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
296
+ end.min_by(&:size)
297
+
298
+ trees.reject! {|t| !maximal.include?(t.last) } if maximal
299
+
300
+ trees.sort_by! {|t| t.reverse.map(&:name) }
301
+ end
302
+
303
+ if trees.size > 1 || name == "bundler"
304
+ o = if name.end_with?("\0")
305
+ String.new("Bundler found conflicting requirements for the #{name} version:")
306
+ else
307
+ String.new("Bundler could not find compatible versions for gem \"#{name}\":")
308
+ end
309
+ o << %(\n)
310
+ o << %( In #{name_for_explicit_dependency_source}:\n)
311
+ o << trees.map do |tree|
312
+ t = "".dup
313
+ depth = 2
314
+
315
+ base_tree = tree.first
316
+ base_tree_name = base_tree.name
317
+
318
+ if base_tree_name.end_with?("\0")
319
+ t = nil
320
+ else
321
+ tree.each do |req|
322
+ t << " " * depth << SharedHelpers.pretty_dependency(req)
323
+ unless tree.last == req
324
+ if spec = conflict.activated_by_name[req.name]
325
+ t << %( was resolved to #{spec.version}, which)
326
+ end
327
+ t << %( depends on)
328
+ end
329
+ t << %(\n)
330
+ depth += 1
331
+ end
332
+ end
333
+ t
334
+ end.compact.join("\n")
335
+ else
336
+ o = String.new
337
+ end
338
+
331
339
  if name == "bundler"
332
340
  o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
333
341
 
@@ -348,40 +356,23 @@ module Bundler
348
356
  o << "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
349
357
  end
350
358
  end
351
- elsif conflict.locked_requirement
352
- o << "\n"
353
- o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
354
- o << %(the gems in your Gemfile, which may resolve the conflict.\n)
359
+ elsif name.end_with?("\0")
360
+ o << %(\n Current #{name} version:\n #{SharedHelpers.pretty_dependency(@metadata_requirements.find {|req| req.name == name })}\n\n)
355
361
  elsif !conflict.existing
356
362
  o << "\n"
357
363
 
358
364
  relevant_source = conflict.requirement.source || source_for(name)
359
365
 
360
- metadata_requirement = name.end_with?("\0")
361
-
362
- o << "Could not find gem '" unless metadata_requirement
363
- o << SharedHelpers.pretty_dependency(conflict.requirement)
364
- o << "'" unless metadata_requirement
365
- if conflict.requirement_trees.first.size > 1
366
- o << ", which is required by "
367
- o << "gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
368
- end
369
- o << " "
370
-
371
- o << if metadata_requirement
372
- "is not available in #{relevant_source}"
366
+ extra_message = if trees.first.size > 1
367
+ ", which is required by gem '#{SharedHelpers.pretty_dependency(trees.first[-2])}',"
373
368
  else
374
- "in #{relevant_source.to_err}.\n"
369
+ ""
375
370
  end
371
+
372
+ o << gem_not_found_message(name, conflict.requirement, relevant_source, extra_message)
376
373
  end
377
- end,
378
- :version_for_spec => lambda {|spec| spec.version },
379
- :incompatible_version_message_for_conflict => lambda do |name, _conflict|
380
- if name.end_with?("\0")
381
- %(#{solver_name} found conflicting requirements for the #{name} version:)
382
- else
383
- %(#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":)
384
- end
374
+
375
+ o
385
376
  end
386
377
  )
387
378
  end
@@ -9,7 +9,7 @@ module Bundler
9
9
  raise GemfileError, "Please define :engine" if options[:engine_version] && options[:engine].nil?
10
10
 
11
11
  if options[:engine] == "ruby" && options[:engine_version] &&
12
- ruby_version != Array(options[:engine_version])
12
+ ruby_version != Array(options[:engine_version])
13
13
  raise GemfileEvalError, "ruby_version must match the :engine_version for MRI"
14
14
  end
15
15
  @ruby_version = RubyVersion.new(ruby_version, options[:patchlevel], options[:engine], options[:engine_version])