bundler 2.3.26 → 2.4.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +228 -1
- data/README.md +3 -6
- data/bundler.gemspec +2 -2
- data/exe/bundle +1 -4
- data/lib/bundler/build_metadata.rb +2 -2
- data/lib/bundler/cli/add.rb +1 -1
- data/lib/bundler/cli/binstubs.rb +5 -1
- data/lib/bundler/cli/check.rb +1 -1
- data/lib/bundler/cli/common.rb +1 -0
- data/lib/bundler/cli/console.rb +2 -2
- data/lib/bundler/cli/doctor.rb +4 -6
- data/lib/bundler/cli/gem.rb +62 -40
- data/lib/bundler/cli/init.rb +2 -2
- data/lib/bundler/cli/install.rb +2 -3
- data/lib/bundler/cli/lock.rb +8 -5
- data/lib/bundler/cli/open.rb +6 -4
- data/lib/bundler/cli/outdated.rb +1 -3
- data/lib/bundler/cli/viz.rb +1 -1
- data/lib/bundler/cli.rb +45 -2
- data/lib/bundler/compact_index_client/cache.rb +1 -1
- data/lib/bundler/compact_index_client/updater.rb +40 -39
- data/lib/bundler/constants.rb +1 -1
- data/lib/bundler/current_ruby.rb +2 -0
- data/lib/bundler/definition.rb +99 -51
- data/lib/bundler/dependency.rb +13 -12
- data/lib/bundler/digest.rb +1 -1
- data/lib/bundler/dsl.rb +3 -3
- data/lib/bundler/endpoint_specification.rb +0 -4
- data/lib/bundler/env.rb +1 -1
- data/lib/bundler/environment_preserver.rb +3 -2
- data/lib/bundler/errors.rb +1 -11
- data/lib/bundler/fetcher/compact_index.rb +9 -11
- data/lib/bundler/fetcher/dependency.rb +2 -6
- data/lib/bundler/fetcher/downloader.rb +2 -5
- data/lib/bundler/fetcher.rb +4 -8
- data/lib/bundler/force_platform.rb +18 -0
- data/lib/bundler/friendly_errors.rb +0 -3
- data/lib/bundler/gem_version_promoter.rb +52 -86
- data/lib/bundler/graph.rb +3 -3
- data/lib/bundler/index.rb +7 -15
- data/lib/bundler/injector.rb +2 -2
- data/lib/bundler/inline.rb +8 -10
- data/lib/bundler/installer/parallel_installer.rb +3 -33
- data/lib/bundler/installer/standalone.rb +12 -8
- data/lib/bundler/installer.rb +9 -23
- data/lib/bundler/lazy_specification.rb +42 -42
- data/lib/bundler/lockfile_generator.rb +1 -1
- data/lib/bundler/lockfile_parser.rb +16 -16
- data/lib/bundler/man/bundle-add.1 +1 -1
- data/lib/bundler/man/bundle-binstubs.1 +1 -1
- data/lib/bundler/man/bundle-cache.1 +3 -3
- data/lib/bundler/man/bundle-cache.1.ronn +2 -2
- data/lib/bundler/man/bundle-check.1 +1 -1
- data/lib/bundler/man/bundle-clean.1 +1 -1
- data/lib/bundler/man/bundle-config.1 +2 -2
- data/lib/bundler/man/bundle-config.1.ronn +1 -1
- data/lib/bundler/man/bundle-console.1 +1 -1
- data/lib/bundler/man/bundle-doctor.1 +1 -1
- data/lib/bundler/man/bundle-exec.1 +5 -5
- data/lib/bundler/man/bundle-exec.1.ronn +5 -5
- data/lib/bundler/man/bundle-gem.1 +27 -37
- data/lib/bundler/man/bundle-gem.1.ronn +5 -5
- data/lib/bundler/man/bundle-help.1 +1 -1
- data/lib/bundler/man/bundle-info.1 +1 -1
- data/lib/bundler/man/bundle-init.1 +5 -1
- data/lib/bundler/man/bundle-init.1.ronn +2 -0
- data/lib/bundler/man/bundle-inject.1 +1 -1
- data/lib/bundler/man/bundle-install.1 +1 -30
- data/lib/bundler/man/bundle-install.1.ronn +0 -29
- data/lib/bundler/man/bundle-list.1 +1 -1
- data/lib/bundler/man/bundle-lock.1 +1 -1
- data/lib/bundler/man/bundle-open.1 +22 -2
- data/lib/bundler/man/bundle-open.1.ronn +9 -1
- data/lib/bundler/man/bundle-outdated.1 +1 -1
- data/lib/bundler/man/bundle-platform.1 +2 -2
- data/lib/bundler/man/bundle-platform.1.ronn +1 -1
- data/lib/bundler/man/bundle-plugin.1 +1 -1
- data/lib/bundler/man/bundle-pristine.1 +1 -1
- data/lib/bundler/man/bundle-remove.1 +1 -1
- data/lib/bundler/man/bundle-show.1 +1 -1
- data/lib/bundler/man/bundle-update.1 +1 -1
- data/lib/bundler/man/bundle-version.1 +1 -1
- data/lib/bundler/man/bundle-viz.1 +1 -1
- data/lib/bundler/man/bundle.1 +1 -1
- data/lib/bundler/man/gemfile.5 +1 -1
- data/lib/bundler/mirror.rb +5 -7
- data/lib/bundler/plugin/index.rb +4 -4
- data/lib/bundler/plugin/installer/rubygems.rb +0 -4
- data/lib/bundler/plugin/installer.rb +5 -2
- data/lib/bundler/plugin.rb +1 -1
- data/lib/bundler/remote_specification.rb +2 -6
- data/lib/bundler/resolver/base.rb +72 -15
- data/lib/bundler/resolver/candidate.rb +94 -0
- data/lib/bundler/resolver/incompatibility.rb +15 -0
- data/lib/bundler/resolver/package.rb +72 -0
- data/lib/bundler/resolver/root.rb +25 -0
- data/lib/bundler/resolver/spec_group.rb +26 -36
- data/lib/bundler/resolver.rb +311 -278
- data/lib/bundler/ruby_version.rb +1 -1
- data/lib/bundler/rubygems_ext.rb +16 -9
- data/lib/bundler/rubygems_gem_installer.rb +4 -2
- data/lib/bundler/rubygems_integration.rb +10 -14
- data/lib/bundler/runtime.rb +1 -5
- data/lib/bundler/safe_marshal.rb +31 -0
- data/lib/bundler/settings.rb +1 -7
- data/lib/bundler/setup.rb +4 -1
- data/lib/bundler/shared_helpers.rb +2 -1
- data/lib/bundler/source/git/git_proxy.rb +214 -69
- data/lib/bundler/source/git.rb +17 -18
- data/lib/bundler/source/metadata.rb +0 -1
- data/lib/bundler/source/path/installer.rb +1 -22
- data/lib/bundler/source/path.rb +6 -6
- data/lib/bundler/source/rubygems.rb +19 -77
- data/lib/bundler/source_list.rb +8 -2
- data/lib/bundler/spec_set.rb +22 -14
- data/lib/bundler/templates/Executable +1 -1
- data/lib/bundler/templates/Executable.bundler +5 -10
- data/lib/bundler/templates/Executable.standalone +2 -0
- data/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
- data/lib/bundler/templates/newgem/Gemfile.tt +3 -0
- data/lib/bundler/templates/newgem/README.md.tt +6 -4
- data/lib/bundler/templates/newgem/Rakefile.tt +12 -1
- data/lib/bundler/templates/newgem/bin/console.tt +0 -4
- data/lib/bundler/templates/newgem/circleci/config.yml.tt +12 -0
- data/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +15 -0
- data/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +10 -0
- data/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
- data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +1 -1
- data/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +12 -0
- data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +10 -0
- data/lib/bundler/templates/newgem/gitignore.tt +3 -0
- data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +8 -0
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +8 -2
- data/lib/bundler/ui/shell.rb +35 -12
- data/lib/bundler/ui/silent.rb +21 -5
- data/lib/bundler/uri_normalizer.rb +23 -0
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +3 -3
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -1
- data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +3 -1
- data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1350 -408
- data/lib/bundler/vendor/net-http-persistent/README.rdoc +1 -1
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
- data/lib/bundler/vendor/pub_grub/LICENSE.txt +21 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +189 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +150 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb +43 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb +19 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +60 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +129 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +411 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +243 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb +178 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +31 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +1 -1
- data/lib/bundler/vendor/uri/lib/uri/common.rb +64 -16
- data/lib/bundler/vendor/uri/lib/uri/file.rb +7 -1
- data/lib/bundler/vendor/uri/lib/uri/ftp.rb +2 -1
- data/lib/bundler/vendor/uri/lib/uri/generic.rb +27 -7
- data/lib/bundler/vendor/uri/lib/uri/http.rb +40 -2
- data/lib/bundler/vendor/uri/lib/uri/https.rb +2 -1
- data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
- data/lib/bundler/vendor/uri/lib/uri/ldaps.rb +2 -1
- data/lib/bundler/vendor/uri/lib/uri/mailto.rb +2 -2
- data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +13 -7
- data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +10 -5
- data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
- data/lib/bundler/vendor/uri/lib/uri/ws.rb +1 -2
- data/lib/bundler/vendor/uri/lib/uri/wss.rb +2 -1
- data/lib/bundler/vendor/uri/lib/uri.rb +3 -2
- data/lib/bundler/vendored_persistent.rb +1 -33
- data/lib/bundler/{vendored_tmpdir.rb → vendored_pub_grub.rb} +1 -1
- data/lib/bundler/version.rb +5 -1
- data/lib/bundler/worker.rb +5 -7
- data/lib/bundler.rb +17 -69
- metadata +35 -33
- data/lib/bundler/templates/gems.rb +0 -5
- data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +0 -5
- data/lib/bundler/templates/newgem/travis.yml.tt +0 -6
- data/lib/bundler/vendor/molinillo/LICENSE +0 -9
- data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
- data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -88
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -164
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +0 -255
- data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +0 -149
- data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
- data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +0 -112
- data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +0 -67
- data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +0 -839
- data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +0 -46
- data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +0 -58
- data/lib/bundler/vendor/molinillo/lib/molinillo.rb +0 -11
- data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +0 -154
- data/lib/bundler/vendored_molinillo.rb +0 -4
- data/lib/bundler/version_ranges.rb +0 -122
data/lib/bundler/resolver.rb
CHANGED
|
@@ -1,380 +1,413 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Bundler
|
|
4
|
+
#
|
|
5
|
+
# This class implements the interface needed by PubGrub for resolution. It is
|
|
6
|
+
# equivalent to the `PubGrub::BasicPackageSource` class provided by PubGrub by
|
|
7
|
+
# default and used by the most simple PubGrub consumers.
|
|
8
|
+
#
|
|
4
9
|
class Resolver
|
|
5
|
-
require_relative "
|
|
10
|
+
require_relative "vendored_pub_grub"
|
|
6
11
|
require_relative "resolver/base"
|
|
7
|
-
require_relative "resolver/
|
|
12
|
+
require_relative "resolver/candidate"
|
|
13
|
+
require_relative "resolver/incompatibility"
|
|
14
|
+
require_relative "resolver/root"
|
|
8
15
|
|
|
9
16
|
include GemHelpers
|
|
10
17
|
|
|
11
|
-
def initialize(
|
|
12
|
-
@source_requirements = source_requirements
|
|
13
|
-
@base =
|
|
14
|
-
@resolver = Molinillo::Resolver.new(self, self)
|
|
15
|
-
@results_for = {}
|
|
16
|
-
@search_for = {}
|
|
17
|
-
@platforms = platforms
|
|
18
|
-
@resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
|
|
18
|
+
def initialize(base, gem_version_promoter)
|
|
19
|
+
@source_requirements = base.source_requirements
|
|
20
|
+
@base = base
|
|
19
21
|
@gem_version_promoter = gem_version_promoter
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
def start
|
|
23
|
-
@
|
|
24
|
+
def start
|
|
25
|
+
@requirements = @base.requirements
|
|
26
|
+
@packages = @base.packages
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
remove_from_candidates(spec)
|
|
27
|
-
end
|
|
28
|
+
root, logger = setup_solver
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
Bundler.ui.info "Resolving dependencies...", true
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
map(&:payload).
|
|
34
|
-
reject {|sg| sg.name.end_with?("\0") }.
|
|
35
|
-
map(&:to_specs).
|
|
36
|
-
flatten
|
|
32
|
+
solve_versions(:root => root, :logger => logger)
|
|
33
|
+
end
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
def setup_solver
|
|
36
|
+
root = Resolver::Root.new(name_for_explicit_dependency_source)
|
|
37
|
+
root_version = Resolver::Candidate.new(0)
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
@all_specs = Hash.new do |specs, name|
|
|
40
|
+
specs[name] = source_for(name).specs.search(name).reject do |s|
|
|
41
|
+
s.dependencies.any? {|d| d.name == name && !d.requirement.satisfied_by?(s.version) } # ignore versions that depend on themselves incorrectly
|
|
42
|
+
end.sort_by {|s| [s.version, s.platform.to_s] }
|
|
44
43
|
end
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
@sorted_versions = Hash.new do |candidates, package|
|
|
46
|
+
candidates[package] = if package.root?
|
|
47
|
+
[root_version]
|
|
48
|
+
else
|
|
49
|
+
all_versions_for(package).sort
|
|
50
|
+
end
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
raise VersionConflict.new(conflicts.keys.uniq, message)
|
|
54
|
-
rescue Molinillo::CircularDependencyError => e
|
|
55
|
-
names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
|
|
56
|
-
raise CyclicDependencyError, "Your bundle requires gems that depend" \
|
|
57
|
-
" on each other, creating an infinite loop. Please remove" \
|
|
58
|
-
" #{names.count > 1 ? "either " : ""}#{names.join(" or ")}" \
|
|
59
|
-
" and try again."
|
|
60
|
-
end
|
|
53
|
+
root_dependencies = prepare_dependencies(@requirements, @packages)
|
|
61
54
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
debug_info = debug_info.inspect unless debug_info.is_a?(String)
|
|
72
|
-
puts debug_info.split("\n").map {|s| depth == 0 ? "BUNDLER: #{s}" : "BUNDLER(#{depth}): #{s}" }
|
|
73
|
-
end
|
|
55
|
+
@cached_dependencies = Hash.new do |dependencies, package|
|
|
56
|
+
dependencies[package] = if package.root?
|
|
57
|
+
{ root_version => root_dependencies }
|
|
58
|
+
else
|
|
59
|
+
Hash.new do |versions, version|
|
|
60
|
+
versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
74
64
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
@debug_mode =
|
|
78
|
-
ENV["BUNDLER_DEBUG_RESOLVER"] ||
|
|
79
|
-
ENV["BUNDLER_DEBUG_RESOLVER_TREE"] ||
|
|
80
|
-
ENV["DEBUG_RESOLVER"] ||
|
|
81
|
-
ENV["DEBUG_RESOLVER_TREE"] ||
|
|
82
|
-
false
|
|
83
|
-
end
|
|
65
|
+
logger = Bundler::UI::Shell.new
|
|
66
|
+
logger.level = debug? ? "debug" : "warn"
|
|
84
67
|
|
|
85
|
-
|
|
86
|
-
Bundler.ui.info "Resolving dependencies...", debug?
|
|
68
|
+
[root, logger]
|
|
87
69
|
end
|
|
88
70
|
|
|
89
|
-
def
|
|
90
|
-
|
|
91
|
-
|
|
71
|
+
def solve_versions(root:, logger:)
|
|
72
|
+
solver = PubGrub::VersionSolver.new(:source => self, :root => root, :logger => logger)
|
|
73
|
+
result = solver.solve
|
|
74
|
+
result.map {|package, version| version.to_specs(package) }.flatten.uniq
|
|
75
|
+
rescue PubGrub::SolveFailure => e
|
|
76
|
+
incompatibility = e.incompatibility
|
|
92
77
|
|
|
93
|
-
|
|
94
|
-
Bundler.ui.info ".", false unless debug?
|
|
95
|
-
end
|
|
78
|
+
names_to_unlock, names_to_allow_prereleases_for, extended_explanation = find_names_to_relax(incompatibility)
|
|
96
79
|
|
|
97
|
-
|
|
80
|
+
names_to_relax = names_to_unlock + names_to_allow_prereleases_for
|
|
98
81
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
82
|
+
if names_to_relax.any?
|
|
83
|
+
if names_to_unlock.any?
|
|
84
|
+
Bundler.ui.debug "Found conflicts with locked dependencies. Will retry with #{names_to_unlock.join(", ")} unlocked...", true
|
|
102
85
|
|
|
103
|
-
|
|
104
|
-
|
|
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
|
|
121
|
-
end
|
|
86
|
+
@base.unlock_names(names_to_unlock)
|
|
87
|
+
end
|
|
122
88
|
|
|
123
|
-
|
|
89
|
+
if names_to_allow_prereleases_for.any?
|
|
90
|
+
Bundler.ui.debug "Found conflicts with dependencies with prereleases. Will retrying considering prereleases for #{names_to_allow_prereleases_for.join(", ")}...", true
|
|
124
91
|
|
|
125
|
-
|
|
126
|
-
|
|
92
|
+
@base.include_prereleases(names_to_allow_prereleases_for)
|
|
93
|
+
end
|
|
127
94
|
|
|
128
|
-
|
|
129
|
-
groups << spec_group
|
|
95
|
+
root, logger = setup_solver
|
|
130
96
|
|
|
131
|
-
|
|
132
|
-
|
|
97
|
+
Bundler.ui.debug "Retrying resolution...", true
|
|
98
|
+
retry
|
|
133
99
|
end
|
|
134
|
-
end
|
|
135
100
|
|
|
136
|
-
|
|
137
|
-
source_for(dependency.name).specs
|
|
138
|
-
end
|
|
101
|
+
explanation = e.message
|
|
139
102
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
103
|
+
if extended_explanation
|
|
104
|
+
explanation << "\n\n"
|
|
105
|
+
explanation << extended_explanation
|
|
106
|
+
end
|
|
143
107
|
|
|
144
|
-
|
|
145
|
-
@results_for[dependency] ||= index_for(dependency).search(dependency)
|
|
108
|
+
raise SolveFailure.new(explanation)
|
|
146
109
|
end
|
|
147
110
|
|
|
148
|
-
def
|
|
149
|
-
|
|
150
|
-
|
|
111
|
+
def find_names_to_relax(incompatibility)
|
|
112
|
+
names_to_unlock = []
|
|
113
|
+
names_to_allow_prereleases_for = []
|
|
114
|
+
extended_explanation = nil
|
|
151
115
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
"Gemfile"
|
|
156
|
-
end
|
|
116
|
+
while incompatibility.conflict?
|
|
117
|
+
cause = incompatibility.cause
|
|
118
|
+
incompatibility = cause.incompatibility
|
|
157
119
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
120
|
+
incompatibility.terms.each do |term|
|
|
121
|
+
package = term.package
|
|
122
|
+
name = package.name
|
|
123
|
+
|
|
124
|
+
if base_requirements[name]
|
|
125
|
+
names_to_unlock << name
|
|
126
|
+
elsif package.ignores_prereleases?
|
|
127
|
+
names_to_allow_prereleases_for << name
|
|
128
|
+
end
|
|
161
129
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
@base[name].any? ? 0 : 1,
|
|
168
|
-
vertex.payload ? 0 : 1,
|
|
169
|
-
vertex.root? ? 0 : 1,
|
|
170
|
-
amount_constrained(dependency),
|
|
171
|
-
conflicts[name] ? 0 : 1,
|
|
172
|
-
vertex.payload ? 0 : search_for(dependency).count,
|
|
173
|
-
]
|
|
130
|
+
no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
|
|
131
|
+
next unless no_versions_incompat
|
|
132
|
+
|
|
133
|
+
extended_explanation = no_versions_incompat.extended_explanation
|
|
134
|
+
end
|
|
174
135
|
end
|
|
136
|
+
|
|
137
|
+
[names_to_unlock.uniq, names_to_allow_prereleases_for.uniq, extended_explanation]
|
|
175
138
|
end
|
|
176
139
|
|
|
177
|
-
|
|
140
|
+
def parse_dependency(package, dependency)
|
|
141
|
+
range = if repository_for(package).is_a?(Source::Gemspec)
|
|
142
|
+
PubGrub::VersionRange.any
|
|
143
|
+
else
|
|
144
|
+
requirement_to_range(dependency)
|
|
145
|
+
end
|
|
178
146
|
|
|
179
|
-
|
|
180
|
-
@base.base_requirements
|
|
147
|
+
PubGrub::VersionConstraint.new(package, :range => range)
|
|
181
148
|
end
|
|
182
149
|
|
|
183
|
-
def
|
|
184
|
-
@
|
|
150
|
+
def versions_for(package, range=VersionRange.any)
|
|
151
|
+
versions = range.select_versions(@sorted_versions[package])
|
|
152
|
+
|
|
153
|
+
sort_versions(package, versions)
|
|
185
154
|
end
|
|
186
155
|
|
|
187
|
-
def
|
|
188
|
-
|
|
156
|
+
def no_versions_incompatibility_for(package, unsatisfied_term)
|
|
157
|
+
cause = PubGrub::Incompatibility::NoVersions.new(unsatisfied_term)
|
|
158
|
+
name = package.name
|
|
159
|
+
constraint = unsatisfied_term.constraint
|
|
160
|
+
constraint_string = constraint.constraint_string
|
|
161
|
+
requirements = constraint_string.split(" OR ").map {|req| Gem::Requirement.new(req.split(",")) }
|
|
162
|
+
|
|
163
|
+
if name == "bundler"
|
|
164
|
+
custom_explanation = "the current Bundler version (#{Bundler::VERSION}) does not satisfy #{constraint}"
|
|
165
|
+
extended_explanation = bundler_not_found_message(requirements)
|
|
166
|
+
else
|
|
167
|
+
specs_matching_other_platforms = filter_matching_specs(@all_specs[name], requirements)
|
|
189
168
|
|
|
190
|
-
|
|
191
|
-
|
|
169
|
+
platforms_explanation = specs_matching_other_platforms.any? ? " for any resolution platforms (#{package.platforms.join(", ")})" : ""
|
|
170
|
+
custom_explanation = "#{constraint} could not be found in #{repository_for(package)}#{platforms_explanation}"
|
|
192
171
|
|
|
193
|
-
|
|
172
|
+
label = "#{name} (#{constraint_string})"
|
|
173
|
+
extended_explanation = other_specs_matching_message(specs_matching_other_platforms, label) if specs_matching_other_platforms.any?
|
|
194
174
|
end
|
|
195
175
|
|
|
196
|
-
|
|
176
|
+
Incompatibility.new([unsatisfied_term], :cause => cause, :custom_explanation => custom_explanation, :extended_explanation => extended_explanation)
|
|
197
177
|
end
|
|
198
178
|
|
|
199
|
-
def
|
|
200
|
-
|
|
201
|
-
|
|
179
|
+
def debug?
|
|
180
|
+
ENV["BUNDLER_DEBUG_RESOLVER"] ||
|
|
181
|
+
ENV["BUNDLER_DEBUG_RESOLVER_TREE"] ||
|
|
182
|
+
ENV["DEBUG_RESOLVER"] ||
|
|
183
|
+
ENV["DEBUG_RESOLVER_TREE"] ||
|
|
184
|
+
false
|
|
202
185
|
end
|
|
203
186
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
# before dependencies that are unconstrained
|
|
210
|
-
def amount_constrained(dependency)
|
|
211
|
-
@amount_constrained ||= {}
|
|
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
|
|
187
|
+
def incompatibilities_for(package, version)
|
|
188
|
+
package_deps = @cached_dependencies[package]
|
|
189
|
+
sorted_versions = @sorted_versions[package]
|
|
190
|
+
package_deps[version].map do |dep_package, dep_constraint|
|
|
191
|
+
low = high = sorted_versions.index(version)
|
|
216
192
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
193
|
+
# find version low such that all >= low share the same dep
|
|
194
|
+
while low > 0 && package_deps[sorted_versions[low - 1]][dep_package] == dep_constraint
|
|
195
|
+
low -= 1
|
|
196
|
+
end
|
|
197
|
+
low =
|
|
198
|
+
if low == 0
|
|
199
|
+
nil
|
|
200
|
+
else
|
|
201
|
+
sorted_versions[low]
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# find version high such that all < high share the same dep
|
|
205
|
+
while high < sorted_versions.length && package_deps[sorted_versions[high]][dep_package] == dep_constraint
|
|
206
|
+
high += 1
|
|
207
|
+
end
|
|
208
|
+
high =
|
|
209
|
+
if high == sorted_versions.length
|
|
210
|
+
nil
|
|
211
|
+
else
|
|
212
|
+
sorted_versions[high]
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
range = PubGrub::VersionRange.new(:min => low, :max => high, :include_min => true)
|
|
216
|
+
|
|
217
|
+
self_constraint = PubGrub::VersionConstraint.new(package, :range => range)
|
|
218
|
+
|
|
219
|
+
dep_term = PubGrub::Term.new(dep_constraint, false)
|
|
220
|
+
self_term = PubGrub::Term.new(self_constraint, true)
|
|
221
|
+
|
|
222
|
+
custom_explanation = if dep_package.meta? && package.root?
|
|
223
|
+
"current #{dep_package} version is #{dep_constraint.constraint_string}"
|
|
223
224
|
end
|
|
225
|
+
|
|
226
|
+
PubGrub::Incompatibility.new([self_term, dep_term], :cause => :dependency, :custom_explanation => custom_explanation)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def all_versions_for(package)
|
|
231
|
+
name = package.name
|
|
232
|
+
results = (@base[name] + filter_prereleases(@all_specs[name], package)).uniq {|spec| [spec.version.hash, spec.platform] }
|
|
233
|
+
locked_requirement = base_requirements[name]
|
|
234
|
+
results = filter_matching_specs(results, locked_requirement) if locked_requirement
|
|
235
|
+
|
|
236
|
+
versions = results.group_by(&:version).reduce([]) do |groups, (version, specs)|
|
|
237
|
+
platform_specs = package.platforms.flat_map {|platform| select_best_platform_match(specs, platform) }
|
|
238
|
+
next groups if platform_specs.empty?
|
|
239
|
+
|
|
240
|
+
ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
|
|
241
|
+
groups << Resolver::Candidate.new(version, :specs => ruby_specs) if ruby_specs.any?
|
|
242
|
+
|
|
243
|
+
next groups if platform_specs == ruby_specs || package.force_ruby_platform?
|
|
244
|
+
|
|
245
|
+
groups << Resolver::Candidate.new(version, :specs => platform_specs)
|
|
246
|
+
|
|
247
|
+
groups
|
|
224
248
|
end
|
|
249
|
+
|
|
250
|
+
sort_versions(package, versions)
|
|
225
251
|
end
|
|
226
252
|
|
|
227
|
-
def
|
|
228
|
-
|
|
229
|
-
|
|
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?
|
|
253
|
+
def source_for(name)
|
|
254
|
+
@source_requirements[name] || @source_requirements[:default]
|
|
255
|
+
end
|
|
234
256
|
|
|
235
|
-
|
|
236
|
-
|
|
257
|
+
def name_for_explicit_dependency_source
|
|
258
|
+
Bundler.default_gemfile.basename.to_s
|
|
259
|
+
rescue StandardError
|
|
260
|
+
"Gemfile"
|
|
237
261
|
end
|
|
238
262
|
|
|
239
|
-
def
|
|
240
|
-
|
|
263
|
+
def raise_not_found!(package)
|
|
264
|
+
name = package.name
|
|
265
|
+
source = source_for(name)
|
|
266
|
+
specs = @all_specs[name]
|
|
241
267
|
matching_part = name
|
|
242
|
-
requirement_label = SharedHelpers.pretty_dependency(
|
|
268
|
+
requirement_label = SharedHelpers.pretty_dependency(package.dependency)
|
|
243
269
|
cache_message = begin
|
|
244
270
|
" or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
|
|
245
271
|
rescue GemfileNotFound
|
|
246
272
|
nil
|
|
247
273
|
end
|
|
248
|
-
specs_matching_requirement = specs.
|
|
274
|
+
specs_matching_requirement = filter_matching_specs(specs, package.dependency.requirement)
|
|
249
275
|
|
|
250
276
|
if specs_matching_requirement.any?
|
|
251
277
|
specs = specs_matching_requirement
|
|
252
278
|
matching_part = requirement_label
|
|
253
|
-
platforms =
|
|
279
|
+
platforms = package.platforms
|
|
254
280
|
platform_label = platforms.size == 1 ? "platform '#{platforms.first}" : "platforms '#{platforms.join("', '")}"
|
|
255
281
|
requirement_label = "#{requirement_label}' with #{platform_label}"
|
|
256
282
|
end
|
|
257
283
|
|
|
258
|
-
message = String.new("Could not find gem '#{requirement_label}'
|
|
284
|
+
message = String.new("Could not find gem '#{requirement_label}' in #{source}#{cache_message}.\n")
|
|
259
285
|
|
|
260
286
|
if specs.any?
|
|
261
|
-
message << "\
|
|
262
|
-
message << specs.map {|s| " * #{s.full_name}" }.join("\n")
|
|
287
|
+
message << "\n#{other_specs_matching_message(specs, matching_part)}"
|
|
263
288
|
end
|
|
264
289
|
|
|
265
|
-
message
|
|
290
|
+
raise GemNotFound, message
|
|
266
291
|
end
|
|
267
292
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
293
|
+
private
|
|
294
|
+
|
|
295
|
+
def filter_matching_specs(specs, requirements)
|
|
296
|
+
Array(requirements).flat_map do |requirement|
|
|
297
|
+
specs.select {| spec| requirement_satisfied_by?(requirement, spec) }
|
|
298
|
+
end
|
|
299
|
+
end
|
|
271
300
|
|
|
272
|
-
|
|
273
|
-
|
|
301
|
+
def filter_prereleases(specs, package)
|
|
302
|
+
return specs unless package.ignores_prereleases? && specs.size > 1
|
|
303
|
+
|
|
304
|
+
specs.reject {|s| s.version.prerelease? }
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def requirement_satisfied_by?(requirement, spec)
|
|
308
|
+
requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def sort_versions(package, versions)
|
|
312
|
+
if versions.size > 1
|
|
313
|
+
@gem_version_promoter.sort_versions(package, versions).reverse
|
|
274
314
|
else
|
|
275
|
-
|
|
276
|
-
deps = conflict.requirement_trees.map(&:last).flatten(1)
|
|
277
|
-
!Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
|
|
278
|
-
end
|
|
315
|
+
versions
|
|
279
316
|
end
|
|
317
|
+
end
|
|
280
318
|
|
|
281
|
-
|
|
319
|
+
def repository_for(package)
|
|
320
|
+
source_for(package.name)
|
|
321
|
+
end
|
|
282
322
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
323
|
+
def base_requirements
|
|
324
|
+
@base.base_requirements
|
|
325
|
+
end
|
|
286
326
|
|
|
287
|
-
|
|
288
|
-
|
|
327
|
+
def prepare_dependencies(requirements, packages)
|
|
328
|
+
to_dependency_hash(requirements, packages).map do |dep_package, dep_constraint|
|
|
329
|
+
name = dep_package.name
|
|
289
330
|
|
|
290
|
-
|
|
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)
|
|
331
|
+
next [dep_package, dep_constraint] if name == "bundler"
|
|
297
332
|
|
|
298
|
-
|
|
333
|
+
versions = versions_for(dep_package, dep_constraint.range)
|
|
334
|
+
if versions.empty? && dep_package.ignores_prereleases?
|
|
335
|
+
@sorted_versions.delete(dep_package)
|
|
336
|
+
dep_package.consider_prereleases!
|
|
337
|
+
versions = versions_for(dep_package, dep_constraint.range)
|
|
338
|
+
end
|
|
339
|
+
next [dep_package, dep_constraint] unless versions.empty?
|
|
299
340
|
|
|
300
|
-
|
|
301
|
-
end
|
|
341
|
+
next unless dep_package.current_platform?
|
|
302
342
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
|
343
|
+
raise_not_found!(dep_package)
|
|
344
|
+
end.compact.to_h
|
|
345
|
+
end
|
|
338
346
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
other_bundler_required = !conflict_requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
|
345
|
-
|
|
346
|
-
if other_bundler_required
|
|
347
|
-
o << "\n\n"
|
|
348
|
-
|
|
349
|
-
candidate_specs = source_for(:default_bundler).specs.search(conflict_dependency)
|
|
350
|
-
if candidate_specs.any?
|
|
351
|
-
target_version = candidate_specs.last.version
|
|
352
|
-
new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ")
|
|
353
|
-
o << "Your bundle requires a different version of Bundler than the one you're running.\n"
|
|
354
|
-
o << "Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n"
|
|
355
|
-
else
|
|
356
|
-
o << "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
|
|
357
|
-
end
|
|
358
|
-
end
|
|
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)
|
|
361
|
-
elsif !conflict.existing
|
|
362
|
-
o << "\n"
|
|
363
|
-
|
|
364
|
-
relevant_source = conflict.requirement.source || source_for(name)
|
|
365
|
-
|
|
366
|
-
extra_message = if trees.first.size > 1
|
|
367
|
-
", which is required by gem '#{SharedHelpers.pretty_dependency(trees.first[-2])}',"
|
|
368
|
-
else
|
|
369
|
-
""
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
o << gem_not_found_message(name, conflict.requirement, relevant_source, extra_message)
|
|
373
|
-
end
|
|
347
|
+
def other_specs_matching_message(specs, requirement)
|
|
348
|
+
message = String.new("The source contains the following gems matching '#{requirement}':\n")
|
|
349
|
+
message << specs.map {|s| " * #{s.full_name}" }.join("\n")
|
|
350
|
+
message
|
|
351
|
+
end
|
|
374
352
|
|
|
375
|
-
|
|
353
|
+
def requirement_to_range(requirement)
|
|
354
|
+
ranges = requirement.requirements.map do |(op, version)|
|
|
355
|
+
ver = Resolver::Candidate.new(version).generic!
|
|
356
|
+
platform_ver = Resolver::Candidate.new(version).platform_specific!
|
|
357
|
+
|
|
358
|
+
case op
|
|
359
|
+
when "~>"
|
|
360
|
+
name = "~> #{ver}"
|
|
361
|
+
bump = Resolver::Candidate.new(version.bump.to_s + ".A")
|
|
362
|
+
PubGrub::VersionRange.new(:name => name, :min => ver, :max => bump, :include_min => true)
|
|
363
|
+
when ">"
|
|
364
|
+
PubGrub::VersionRange.new(:min => platform_ver)
|
|
365
|
+
when ">="
|
|
366
|
+
PubGrub::VersionRange.new(:min => ver, :include_min => true)
|
|
367
|
+
when "<"
|
|
368
|
+
PubGrub::VersionRange.new(:max => ver)
|
|
369
|
+
when "<="
|
|
370
|
+
PubGrub::VersionRange.new(:max => platform_ver, :include_max => true)
|
|
371
|
+
when "="
|
|
372
|
+
PubGrub::VersionRange.new(:min => ver, :max => platform_ver, :include_min => true, :include_max => true)
|
|
373
|
+
when "!="
|
|
374
|
+
PubGrub::VersionRange.new(:min => ver, :max => platform_ver, :include_min => true, :include_max => true).invert
|
|
375
|
+
else
|
|
376
|
+
raise "bad version specifier: #{op}"
|
|
376
377
|
end
|
|
377
|
-
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
ranges.inject(&:intersect)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def to_dependency_hash(dependencies, packages)
|
|
384
|
+
dependencies.inject({}) do |deps, dep|
|
|
385
|
+
package = packages[dep.name]
|
|
386
|
+
|
|
387
|
+
current_req = deps[package]
|
|
388
|
+
new_req = parse_dependency(package, dep.requirement)
|
|
389
|
+
|
|
390
|
+
deps[package] = if current_req
|
|
391
|
+
current_req.intersect(new_req)
|
|
392
|
+
else
|
|
393
|
+
new_req
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
deps
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def bundler_not_found_message(conflict_dependencies)
|
|
401
|
+
candidate_specs = filter_matching_specs(source_for(:default_bundler).specs.search("bundler"), conflict_dependencies)
|
|
402
|
+
|
|
403
|
+
if candidate_specs.any?
|
|
404
|
+
target_version = candidate_specs.last.version
|
|
405
|
+
new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ")
|
|
406
|
+
"Your bundle requires a different version of Bundler than the one you're running.\n" \
|
|
407
|
+
"Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n"
|
|
408
|
+
else
|
|
409
|
+
"Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
|
|
410
|
+
end
|
|
378
411
|
end
|
|
379
412
|
end
|
|
380
413
|
end
|