rubygems-update 2.6.14 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +10 -7
- data/CONTRIBUTING.rdoc +53 -54
- data/History.txt +173 -9
- data/Manifest.txt +39 -11
- data/POLICIES.rdoc +3 -3
- data/README.md +72 -0
- data/Rakefile +30 -5
- data/appveyor.yml +29 -1
- data/bin/gem +1 -1
- data/bin/update_rubygems +2 -2
- data/bundler/CHANGELOG.md +269 -9
- data/bundler/CODE_OF_CONDUCT.md +1 -1
- data/bundler/CONTRIBUTING.md +10 -29
- data/bundler/README.md +22 -10
- data/bundler/exe/bundle +5 -7
- data/bundler/exe/bundle_ruby +4 -3
- data/bundler/lib/bundler.rb +94 -74
- data/bundler/lib/bundler/build_metadata.rb +36 -0
- data/bundler/lib/bundler/capistrano.rb +5 -0
- data/bundler/lib/bundler/cli.rb +229 -66
- data/bundler/lib/bundler/cli/add.rb +25 -0
- data/bundler/lib/bundler/cli/binstubs.rb +9 -7
- data/bundler/lib/bundler/cli/cache.rb +5 -4
- data/bundler/lib/bundler/cli/check.rb +3 -5
- data/bundler/lib/bundler/cli/clean.rb +5 -6
- data/bundler/lib/bundler/cli/common.rb +18 -2
- data/bundler/lib/bundler/cli/config.rb +26 -7
- data/bundler/lib/bundler/cli/console.rb +2 -1
- data/bundler/lib/bundler/cli/doctor.rb +1 -0
- data/bundler/lib/bundler/cli/exec.rb +3 -2
- data/bundler/lib/bundler/cli/gem.rb +36 -15
- data/bundler/lib/bundler/cli/info.rb +50 -0
- data/bundler/lib/bundler/cli/init.rb +20 -7
- data/bundler/lib/bundler/cli/inject.rb +13 -4
- data/bundler/lib/bundler/cli/install.rb +61 -77
- data/bundler/lib/bundler/cli/issue.rb +40 -0
- data/bundler/lib/bundler/cli/list.rb +22 -0
- data/bundler/lib/bundler/cli/lock.rb +4 -2
- data/bundler/lib/bundler/cli/open.rb +2 -2
- data/bundler/lib/bundler/cli/outdated.rb +30 -28
- data/bundler/lib/bundler/cli/package.rb +9 -6
- data/bundler/lib/bundler/cli/platform.rb +1 -0
- data/bundler/lib/bundler/cli/plugin.rb +1 -0
- data/bundler/lib/bundler/cli/pristine.rb +43 -0
- data/bundler/lib/bundler/cli/show.rb +1 -1
- data/bundler/lib/bundler/cli/update.rb +32 -11
- data/bundler/lib/bundler/cli/viz.rb +5 -1
- data/bundler/lib/bundler/compact_index_client.rb +1 -0
- data/bundler/lib/bundler/compact_index_client/cache.rb +1 -2
- data/bundler/lib/bundler/compact_index_client/updater.rb +26 -7
- data/bundler/lib/bundler/compatibility_guard.rb +14 -0
- data/bundler/lib/bundler/constants.rb +1 -0
- data/bundler/lib/bundler/current_ruby.rb +8 -7
- data/bundler/lib/bundler/definition.rb +231 -159
- data/bundler/lib/bundler/dep_proxy.rb +2 -0
- data/bundler/lib/bundler/dependency.rb +6 -7
- data/bundler/lib/bundler/deployment.rb +1 -1
- data/bundler/lib/bundler/deprecate.rb +14 -3
- data/bundler/lib/bundler/dsl.rb +103 -62
- data/bundler/lib/bundler/endpoint_specification.rb +12 -2
- data/bundler/lib/bundler/env.rb +97 -36
- data/bundler/lib/bundler/environment_preserver.rb +27 -6
- data/bundler/lib/bundler/errors.rb +3 -1
- data/bundler/lib/bundler/feature_flag.rb +39 -4
- data/bundler/lib/bundler/fetcher.rb +15 -8
- data/bundler/lib/bundler/fetcher/base.rb +1 -0
- data/bundler/lib/bundler/fetcher/compact_index.rb +2 -12
- data/bundler/lib/bundler/fetcher/dependency.rb +2 -1
- data/bundler/lib/bundler/fetcher/downloader.rb +4 -2
- data/bundler/lib/bundler/fetcher/index.rb +1 -0
- data/bundler/lib/bundler/friendly_errors.rb +5 -2
- data/bundler/lib/bundler/gem_helper.rb +23 -9
- data/bundler/lib/bundler/gem_helpers.rb +1 -0
- data/bundler/lib/bundler/gem_remote_fetcher.rb +1 -0
- data/bundler/lib/bundler/gem_tasks.rb +1 -0
- data/bundler/lib/bundler/gem_version_promoter.rb +1 -0
- data/bundler/lib/bundler/gemdeps.rb +1 -0
- data/bundler/lib/bundler/graph.rb +1 -0
- data/bundler/lib/bundler/index.rb +19 -11
- data/bundler/lib/bundler/injector.rb +51 -27
- data/bundler/lib/bundler/inline.rb +10 -10
- data/bundler/lib/bundler/installer.rb +104 -50
- data/bundler/lib/bundler/installer/gem_installer.rb +5 -2
- data/bundler/lib/bundler/installer/parallel_installer.rb +91 -42
- data/bundler/lib/bundler/installer/standalone.rb +1 -0
- data/bundler/lib/bundler/lazy_specification.rb +17 -4
- data/bundler/lib/bundler/lockfile_generator.rb +95 -0
- data/bundler/lib/bundler/lockfile_parser.rb +49 -35
- data/bundler/lib/bundler/match_platform.rb +1 -0
- data/bundler/lib/bundler/mirror.rb +8 -3
- data/bundler/lib/bundler/plugin.rb +6 -1
- data/bundler/lib/bundler/plugin/api/source.rb +16 -3
- data/bundler/lib/bundler/plugin/index.rb +2 -0
- data/bundler/lib/bundler/plugin/installer.rb +7 -6
- data/bundler/lib/bundler/plugin/source_list.rb +7 -8
- data/bundler/lib/bundler/process_lock.rb +24 -0
- data/bundler/lib/bundler/psyched_yaml.rb +10 -0
- data/bundler/lib/bundler/remote_specification.rb +25 -1
- data/bundler/lib/bundler/resolver.rb +171 -192
- data/bundler/lib/bundler/resolver/spec_group.rb +111 -0
- data/bundler/lib/bundler/retry.rb +1 -0
- data/bundler/lib/bundler/ruby_dsl.rb +1 -0
- data/bundler/lib/bundler/ruby_version.rb +6 -1
- data/bundler/lib/bundler/rubygems_ext.rb +18 -8
- data/bundler/lib/bundler/rubygems_gem_installer.rb +25 -2
- data/bundler/lib/bundler/rubygems_integration.rb +157 -66
- data/bundler/lib/bundler/runtime.rb +28 -18
- data/bundler/lib/bundler/settings.rb +202 -87
- data/bundler/lib/bundler/settings/validator.rb +79 -0
- data/bundler/lib/bundler/setup.rb +4 -7
- data/bundler/lib/bundler/shared_helpers.rb +129 -25
- data/bundler/lib/bundler/similarity_detector.rb +1 -0
- data/bundler/lib/bundler/source.rb +53 -1
- data/bundler/lib/bundler/source/gemspec.rb +1 -0
- data/bundler/lib/bundler/source/git.rb +49 -21
- data/bundler/lib/bundler/source/git/git_proxy.rb +17 -12
- data/bundler/lib/bundler/source/metadata.rb +63 -0
- data/bundler/lib/bundler/source/path.rb +38 -17
- data/bundler/lib/bundler/source/path/installer.rb +4 -2
- data/bundler/lib/bundler/source/rubygems.rb +154 -82
- data/bundler/lib/bundler/source/rubygems/remote.rb +8 -1
- data/bundler/lib/bundler/source_list.rb +75 -15
- data/bundler/lib/bundler/spec_set.rb +34 -21
- data/bundler/lib/bundler/ssl_certs/certificate_manager.rb +2 -1
- data/bundler/lib/bundler/stub_specification.rb +86 -2
- data/bundler/lib/bundler/templates/Executable +5 -1
- data/bundler/lib/bundler/templates/Executable.bundler +105 -0
- data/bundler/lib/bundler/templates/Executable.standalone +5 -5
- data/bundler/lib/bundler/templates/Gemfile +3 -0
- data/bundler/lib/bundler/templates/gems.rb +8 -0
- data/bundler/lib/bundler/templates/newgem/Gemfile.tt +4 -2
- data/bundler/lib/bundler/templates/newgem/LICENSE.txt.tt +1 -1
- data/bundler/lib/bundler/templates/newgem/README.md.tt +14 -8
- data/bundler/lib/bundler/templates/newgem/Rakefile.tt +5 -5
- data/bundler/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +4 -4
- data/bundler/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +3 -3
- data/bundler/lib/bundler/templates/newgem/gitignore.tt +0 -1
- data/bundler/lib/bundler/templates/newgem/lib/newgem.rb.tt +6 -6
- data/bundler/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +4 -4
- data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +13 -10
- data/bundler/lib/bundler/templates/newgem/rspec.tt +1 -0
- data/bundler/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +0 -2
- data/bundler/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +3 -0
- data/bundler/lib/bundler/templates/newgem/test/newgem_test.rb.tt +1 -1
- data/bundler/lib/bundler/templates/newgem/test/test_helper.rb.tt +3 -3
- data/bundler/lib/bundler/ui.rb +1 -0
- data/bundler/lib/bundler/ui/rg_proxy.rb +1 -0
- data/bundler/lib/bundler/ui/shell.rb +24 -10
- data/bundler/lib/bundler/ui/silent.rb +12 -1
- data/bundler/lib/bundler/uri_credentials_filter.rb +1 -0
- data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +1638 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo.rb +2 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +7 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +16 -5
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +10 -2
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +5 -4
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +69 -6
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +2 -1
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +3 -1
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +501 -138
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +1 -0
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +8 -4
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +3 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor.rb +46 -21
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions.rb +24 -22
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +2 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +2 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +2 -2
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +16 -8
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +66 -18
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +17 -15
- data/bundler/lib/bundler/vendor/thor/lib/thor/base.rb +55 -32
- data/bundler/lib/bundler/vendor/thor/lib/thor/command.rb +13 -11
- data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +21 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +7 -5
- data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +94 -63
- data/bundler/lib/bundler/vendor/thor/lib/thor/error.rb +3 -3
- data/bundler/lib/bundler/vendor/thor/lib/thor/group.rb +13 -13
- data/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb +4 -5
- data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +2 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +4 -7
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +16 -16
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/option.rb +42 -21
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/options.rb +13 -10
- data/bundler/lib/bundler/vendor/thor/lib/thor/runner.rb +31 -29
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +49 -33
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/color.rb +1 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/html.rb +4 -4
- data/bundler/lib/bundler/vendor/thor/lib/thor/util.rb +8 -7
- data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
- data/bundler/lib/bundler/vendored_fileutils.rb +9 -0
- data/bundler/lib/bundler/vendored_molinillo.rb +1 -0
- data/bundler/lib/bundler/vendored_persistent.rb +35 -0
- data/bundler/lib/bundler/vendored_thor.rb +6 -2
- data/bundler/lib/bundler/version.rb +19 -2
- data/bundler/lib/bundler/version_ranges.rb +76 -0
- data/bundler/lib/bundler/vlad.rb +5 -0
- data/bundler/lib/bundler/worker.rb +3 -1
- data/bundler/lib/bundler/yaml_serializer.rb +3 -3
- data/bundler/man/bundle-add.ronn +29 -0
- data/bundler/man/bundle-binstubs.ronn +14 -0
- data/bundler/man/bundle-check.ronn +26 -0
- data/bundler/man/bundle-clean.ronn +18 -0
- data/bundler/man/bundle-config.ronn +180 -60
- data/bundler/man/bundle-exec.ronn +7 -0
- data/bundler/man/bundle-gem.ronn +3 -2
- data/bundler/man/bundle-info.ronn +17 -0
- data/bundler/man/bundle-init.ronn +18 -0
- data/bundler/man/bundle-inject.ronn +22 -0
- data/bundler/man/bundle-install.ronn +32 -32
- data/bundler/man/bundle-list.ronn +15 -0
- data/bundler/man/bundle-open.ronn +19 -0
- data/bundler/man/bundle-outdated.ronn +1 -1
- data/bundler/man/bundle-package.ronn +5 -0
- data/bundler/man/bundle-pristine.ronn +34 -0
- data/bundler/man/bundle-show.ronn +20 -0
- data/bundler/man/bundle-update.ronn +6 -3
- data/bundler/man/bundle-viz.ronn +30 -0
- data/bundler/man/bundle.ronn +11 -20
- data/bundler/man/gemfile.5.ronn +55 -64
- data/lib/rubygems.rb +79 -36
- data/lib/rubygems/basic_specification.rb +8 -4
- data/lib/rubygems/bundler_version_finder.rb +112 -0
- data/lib/rubygems/command.rb +1 -1
- data/lib/rubygems/command_manager.rb +3 -1
- data/lib/rubygems/commands/cert_command.rb +31 -6
- data/lib/rubygems/commands/cleanup_command.rb +1 -1
- data/lib/rubygems/commands/help_command.rb +1 -1
- data/lib/rubygems/commands/owner_command.rb +3 -1
- data/lib/rubygems/commands/pristine_command.rb +11 -8
- data/lib/rubygems/commands/push_command.rb +2 -1
- data/lib/rubygems/commands/query_command.rb +13 -14
- data/lib/rubygems/commands/setup_command.rb +124 -69
- data/lib/rubygems/commands/signin_command.rb +33 -0
- data/lib/rubygems/commands/signout_command.rb +33 -0
- data/lib/rubygems/commands/uninstall_command.rb +4 -3
- data/lib/rubygems/commands/unpack_command.rb +16 -4
- data/lib/rubygems/commands/update_command.rb +1 -1
- data/lib/rubygems/commands/which_command.rb +1 -1
- data/lib/rubygems/commands/yank_command.rb +4 -11
- data/lib/rubygems/config_file.rb +13 -24
- data/lib/rubygems/core_ext/kernel_require.rb +10 -9
- data/lib/rubygems/dependency.rb +2 -0
- data/lib/rubygems/dependency_installer.rb +4 -0
- data/lib/rubygems/errors.rb +3 -0
- data/lib/rubygems/exceptions.rb +6 -0
- data/lib/rubygems/ext/builder.rb +1 -1
- data/lib/rubygems/ext/ext_conf_builder.rb +2 -4
- data/lib/rubygems/ext/rake_builder.rb +1 -1
- data/lib/rubygems/gem_runner.rb +5 -1
- data/lib/rubygems/install_update_options.rb +5 -28
- data/lib/rubygems/installer.rb +12 -7
- data/lib/rubygems/installer_test_case.rb +6 -3
- data/lib/rubygems/package/old.rb +1 -1
- data/lib/rubygems/request.rb +1 -1
- data/lib/rubygems/request_set.rb +20 -3
- data/lib/rubygems/request_set/gem_dependency_api.rb +3 -3
- data/lib/rubygems/requirement.rb +5 -1
- data/lib/rubygems/resolver.rb +24 -3
- data/lib/rubygems/resolver/installer_set.rb +4 -6
- data/lib/rubygems/safe_yaml.rb +4 -1
- data/lib/rubygems/security.rb +10 -3
- data/lib/rubygems/security_option.rb +43 -0
- data/lib/rubygems/server.rb +4 -12
- data/lib/rubygems/source.rb +7 -4
- data/lib/rubygems/source/git.rb +2 -1
- data/lib/rubygems/source/local.rb +38 -35
- data/lib/rubygems/source/lock.rb +4 -1
- data/lib/rubygems/source_local.rb +3 -1
- data/lib/rubygems/source_specific_file.rb +3 -2
- data/lib/rubygems/spec_fetcher.rb +7 -3
- data/lib/rubygems/specification.rb +281 -231
- data/lib/rubygems/stub_specification.rb +2 -3
- data/lib/rubygems/test_case.rb +14 -1
- data/lib/rubygems/user_interaction.rb +15 -13
- data/lib/rubygems/util.rb +6 -17
- data/lib/rubygems/version.rb +17 -3
- data/lib/rubygems/version_option.rb +6 -1
- data/setup.rb +1 -1
- data/test/rubygems/private3072_key.pem +40 -0
- data/test/rubygems/public3072_cert.pem +25 -0
- data/test/rubygems/test_config.rb +1 -1
- data/test/rubygems/test_gem.rb +72 -14
- data/test/rubygems/test_gem_bundler_version_finder.rb +125 -0
- data/test/rubygems/test_gem_command.rb +1 -1
- data/test/rubygems/test_gem_commands_build_command.rb +27 -1
- data/test/rubygems/test_gem_commands_cert_command.rb +64 -0
- data/test/rubygems/test_gem_commands_install_command.rb +35 -2
- data/test/rubygems/test_gem_commands_pristine_command.rb +1 -1
- data/test/rubygems/test_gem_commands_query_command.rb +19 -0
- data/test/rubygems/test_gem_commands_setup_command.rb +17 -0
- data/test/rubygems/test_gem_commands_signin_command.rb +95 -0
- data/test/rubygems/test_gem_commands_signout_command.rb +37 -0
- data/test/rubygems/test_gem_commands_sources_command.rb +1 -1
- data/test/rubygems/test_gem_commands_uninstall_command.rb +12 -0
- data/test/rubygems/test_gem_commands_update_command.rb +1 -1
- data/test/rubygems/test_gem_commands_which_command.rb +3 -3
- data/test/rubygems/test_gem_dependency.rb +28 -0
- data/test/rubygems/test_gem_ext_builder.rb +2 -2
- data/test/rubygems/test_gem_ext_rake_builder.rb +2 -2
- data/test/rubygems/test_gem_install_update_options.rb +2 -1
- data/test/rubygems/test_gem_installer.rb +29 -27
- data/test/rubygems/test_gem_package.rb +5 -5
- data/test/rubygems/test_gem_remote_fetcher.rb +2 -2
- data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +3 -3
- data/test/rubygems/test_gem_requirement.rb +6 -0
- data/test/rubygems/test_gem_resolver.rb +26 -0
- data/test/rubygems/test_gem_resolver_conflict.rb +1 -1
- data/test/rubygems/test_gem_security.rb +5 -0
- data/test/rubygems/test_gem_security_policy.rb +24 -24
- data/test/rubygems/test_gem_security_signer.rb +6 -6
- data/test/rubygems/test_gem_security_trust_dir.rb +2 -2
- data/test/rubygems/test_gem_server.rb +18 -1
- data/test/rubygems/test_gem_source.rb +9 -0
- data/test/rubygems/test_gem_spec_fetcher.rb +20 -0
- data/test/rubygems/test_gem_specification.rb +85 -10
- data/test/rubygems/test_gem_stream_ui.rb +6 -6
- data/test/rubygems/test_gem_stub_specification.rb +19 -1
- data/test/rubygems/test_gem_util.rb +1 -0
- data/test/rubygems/test_gem_version.rb +28 -7
- data/test/rubygems/test_gem_version_option.rb +15 -0
- data/test/rubygems/test_kernel.rb +30 -0
- data/test/rubygems/test_require.rb +44 -0
- metadata +47 -46
- data/README.rdoc +0 -54
- data/bundler/DEVELOPMENT.md +0 -150
- data/bundler/ISSUES.md +0 -117
- data/bundler/lib/bundler/postit_trampoline.rb +0 -73
- data/bundler/lib/bundler/vendor/postit/lib/postit.rb +0 -15
- data/bundler/lib/bundler/vendor/postit/lib/postit/environment.rb +0 -44
- data/bundler/lib/bundler/vendor/postit/lib/postit/installer.rb +0 -28
- data/bundler/lib/bundler/vendor/postit/lib/postit/parser.rb +0 -21
- data/bundler/lib/bundler/vendor/postit/lib/postit/setup.rb +0 -12
- data/bundler/lib/bundler/vendor/postit/lib/postit/version.rb +0 -3
- data/bundler/man/index.txt +0 -8
@@ -1,4 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/vendor/molinillo/lib/molinillo/compatibility'
|
2
4
|
require 'bundler/vendor/molinillo/lib/molinillo/gem_metadata'
|
3
5
|
require 'bundler/vendor/molinillo/lib/molinillo/errors'
|
4
6
|
require 'bundler/vendor/molinillo/lib/molinillo/resolver'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bundler::Molinillo
|
4
|
+
# Hacks needed for old Ruby versions.
|
5
|
+
module Compatibility
|
6
|
+
module_function
|
7
|
+
|
8
|
+
if [].respond_to?(:flat_map)
|
9
|
+
# Flat map
|
10
|
+
# @param [Enumerable] enum an enumerable object
|
11
|
+
# @block the block to flat-map with
|
12
|
+
# @return The enum, flat-mapped
|
13
|
+
def flat_map(enum, &blk)
|
14
|
+
enum.flat_map(&blk)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
# Flat map
|
18
|
+
# @param [Enumerable] enum an enumerable object
|
19
|
+
# @block the block to flat-map with
|
20
|
+
# @return The enum, flat-mapped
|
21
|
+
def flat_map(enum, &blk)
|
22
|
+
enum.map(&blk).flatten(1)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Bundler::Molinillo
|
3
4
|
# @!visibility private
|
4
5
|
module Delegates
|
@@ -45,6 +46,12 @@ module Bundler::Molinillo
|
|
45
46
|
current_state = state || Bundler::Molinillo::ResolutionState.empty
|
46
47
|
current_state.conflicts
|
47
48
|
end
|
49
|
+
|
50
|
+
# (see Bundler::Molinillo::ResolutionState#unused_unwind_options)
|
51
|
+
def unused_unwind_options
|
52
|
+
current_state = state || Bundler::Molinillo::ResolutionState.empty
|
53
|
+
current_state.unused_unwind_options
|
54
|
+
end
|
48
55
|
end
|
49
56
|
end
|
50
57
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'set'
|
3
4
|
require 'tsort'
|
4
5
|
|
@@ -98,18 +99,27 @@ module Bundler::Molinillo
|
|
98
99
|
"#{self.class}:#{vertices.values.inspect}"
|
99
100
|
end
|
100
101
|
|
102
|
+
# @param [Hash] options options for dot output.
|
101
103
|
# @return [String] Returns a dot format representation of the graph
|
102
|
-
def to_dot
|
104
|
+
def to_dot(options = {})
|
105
|
+
edge_label = options.delete(:edge_label)
|
106
|
+
raise ArgumentError, "Unknown options: #{options.keys}" unless options.empty?
|
107
|
+
|
103
108
|
dot_vertices = []
|
104
109
|
dot_edges = []
|
105
110
|
vertices.each do |n, v|
|
106
111
|
dot_vertices << " #{n} [label=\"{#{n}|#{v.payload}}\"]"
|
107
112
|
v.outgoing_edges.each do |e|
|
108
|
-
|
113
|
+
label = edge_label ? edge_label.call(e) : e.requirement
|
114
|
+
dot_edges << " #{e.origin.name} -> #{e.destination.name} [label=#{label.to_s.dump}]"
|
109
115
|
end
|
110
116
|
end
|
117
|
+
|
118
|
+
dot_vertices.uniq!
|
111
119
|
dot_vertices.sort!
|
120
|
+
dot_edges.uniq!
|
112
121
|
dot_edges.sort!
|
122
|
+
|
113
123
|
dot = dot_vertices.unshift('digraph G {').push('') + dot_edges.push('}')
|
114
124
|
dot.join("\n")
|
115
125
|
end
|
@@ -123,7 +133,8 @@ module Bundler::Molinillo
|
|
123
133
|
vertices.each do |name, vertex|
|
124
134
|
other_vertex = other.vertex_named(name)
|
125
135
|
return false unless other_vertex
|
126
|
-
return false unless
|
136
|
+
return false unless vertex.payload == other_vertex.payload
|
137
|
+
return false unless other_vertex.successors.to_set == vertex.successors.to_set
|
127
138
|
end
|
128
139
|
end
|
129
140
|
|
@@ -137,8 +148,8 @@ module Bundler::Molinillo
|
|
137
148
|
vertex = add_vertex(name, payload, root)
|
138
149
|
vertex.explicit_requirements << requirement if root
|
139
150
|
parent_names.each do |parent_name|
|
140
|
-
|
141
|
-
add_edge(
|
151
|
+
parent_vertex = vertex_named(parent_name)
|
152
|
+
add_edge(parent_vertex, vertex, requirement)
|
142
153
|
end
|
143
154
|
vertex
|
144
155
|
end
|
data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action'
|
3
4
|
module Bundler::Molinillo
|
4
5
|
class DependencyGraph
|
@@ -23,8 +24,8 @@ module Bundler::Molinillo
|
|
23
24
|
# (see Action#down)
|
24
25
|
def down(graph)
|
25
26
|
edge = make_edge(graph)
|
26
|
-
edge.origin.outgoing_edges
|
27
|
-
edge.destination.incoming_edges
|
27
|
+
delete_first(edge.origin.outgoing_edges, edge)
|
28
|
+
delete_first(edge.destination.incoming_edges, edge)
|
28
29
|
end
|
29
30
|
|
30
31
|
# @!group AddEdgeNoCircular
|
@@ -53,6 +54,13 @@ module Bundler::Molinillo
|
|
53
54
|
@destination = destination
|
54
55
|
@requirement = requirement
|
55
56
|
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def delete_first(array, item)
|
61
|
+
return unless index = array.index(item)
|
62
|
+
array.delete_at(index)
|
63
|
+
end
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular'
|
3
4
|
require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex'
|
4
5
|
require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge'
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Bundler::Molinillo
|
3
4
|
class DependencyGraph
|
4
5
|
# A vertex in a {DependencyGraph} that encapsulates a {#name} and a
|
@@ -10,7 +11,7 @@ module Bundler::Molinillo
|
|
10
11
|
# @return [Object] the payload the vertex holds
|
11
12
|
attr_accessor :payload
|
12
13
|
|
13
|
-
# @return [
|
14
|
+
# @return [Array<Object>] the explicit requirements that required
|
14
15
|
# this vertex
|
15
16
|
attr_reader :explicit_requirements
|
16
17
|
|
@@ -32,7 +33,7 @@ module Bundler::Molinillo
|
|
32
33
|
# @return [Array<Object>] all of the requirements that required
|
33
34
|
# this vertex
|
34
35
|
def requirements
|
35
|
-
incoming_edges.map(&:requirement) + explicit_requirements
|
36
|
+
(incoming_edges.map(&:requirement) + explicit_requirements).uniq
|
36
37
|
end
|
37
38
|
|
38
39
|
# @return [Array<Edge>] the edges of {#graph} that have `self` as their
|
@@ -53,7 +54,7 @@ module Bundler::Molinillo
|
|
53
54
|
# {#descendent?}
|
54
55
|
def recursive_predecessors
|
55
56
|
vertices = predecessors
|
56
|
-
vertices +=
|
57
|
+
vertices += Compatibility.flat_map(vertices, &:recursive_predecessors)
|
57
58
|
vertices.uniq!
|
58
59
|
vertices
|
59
60
|
end
|
@@ -68,7 +69,7 @@ module Bundler::Molinillo
|
|
68
69
|
# {#ancestor?}
|
69
70
|
def recursive_successors
|
70
71
|
vertices = successors
|
71
|
-
vertices +=
|
72
|
+
vertices += Compatibility.flat_map(vertices, &:recursive_successors)
|
72
73
|
vertices.uniq!
|
73
74
|
vertices
|
74
75
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Bundler::Molinillo
|
3
4
|
# An error that occurred during the resolution process
|
4
5
|
class ResolverError < StandardError; end
|
@@ -41,11 +42,11 @@ module Bundler::Molinillo
|
|
41
42
|
attr_reader :dependencies
|
42
43
|
|
43
44
|
# Initializes a new error with the given circular vertices.
|
44
|
-
# @param [Array<DependencyGraph::Vertex>]
|
45
|
+
# @param [Array<DependencyGraph::Vertex>] vertices the vertices in the dependency
|
45
46
|
# that caused the error
|
46
|
-
def initialize(
|
47
|
-
super "There is a circular dependency between #{
|
48
|
-
@dependencies =
|
47
|
+
def initialize(vertices)
|
48
|
+
super "There is a circular dependency between #{vertices.map(&:name).join(' and ')}"
|
49
|
+
@dependencies = vertices.map { |vertex| vertex.payload.possibilities.last }.to_set
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
@@ -55,11 +56,16 @@ module Bundler::Molinillo
|
|
55
56
|
# resolution to fail
|
56
57
|
attr_reader :conflicts
|
57
58
|
|
59
|
+
# @return [SpecificationProvider] the specification provider used during
|
60
|
+
# resolution
|
61
|
+
attr_reader :specification_provider
|
62
|
+
|
58
63
|
# Initializes a new error with the given version conflicts.
|
59
64
|
# @param [{String => Resolution::Conflict}] conflicts see {#conflicts}
|
60
|
-
|
65
|
+
# @param [SpecificationProvider] specification_provider see {#specification_provider}
|
66
|
+
def initialize(conflicts, specification_provider)
|
61
67
|
pairs = []
|
62
|
-
conflicts.values.flatten
|
68
|
+
Compatibility.flat_map(conflicts.values.flatten, &:requirements).each do |conflicting|
|
63
69
|
conflicting.each do |source, conflict_requirements|
|
64
70
|
conflict_requirements.each do |c|
|
65
71
|
pairs << [c, source]
|
@@ -69,7 +75,64 @@ module Bundler::Molinillo
|
|
69
75
|
|
70
76
|
super "Unable to satisfy the following requirements:\n\n" \
|
71
77
|
"#{pairs.map { |r, d| "- `#{r}` required by `#{d}`" }.join("\n")}"
|
78
|
+
|
72
79
|
@conflicts = conflicts
|
80
|
+
@specification_provider = specification_provider
|
81
|
+
end
|
82
|
+
|
83
|
+
require 'bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider'
|
84
|
+
include Delegates::SpecificationProvider
|
85
|
+
|
86
|
+
# @return [String] An error message that includes requirement trees,
|
87
|
+
# which is much more detailed & customizable than the default message
|
88
|
+
# @param [Hash] opts the options to create a message with.
|
89
|
+
# @option opts [String] :solver_name The user-facing name of the solver
|
90
|
+
# @option opts [String] :possibility_type The generic name of a possibility
|
91
|
+
# @option opts [Proc] :reduce_trees A proc that reduced the list of requirement trees
|
92
|
+
# @option opts [Proc] :printable_requirement A proc that pretty-prints requirements
|
93
|
+
# @option opts [Proc] :additional_message_for_conflict A proc that appends additional
|
94
|
+
# messages for each conflict
|
95
|
+
# @option opts [Proc] :version_for_spec A proc that returns the version number for a
|
96
|
+
# possibility
|
97
|
+
def message_with_trees(opts = {})
|
98
|
+
solver_name = opts.delete(:solver_name) { self.class.name.split('::').first }
|
99
|
+
possibility_type = opts.delete(:possibility_type) { 'possibility named' }
|
100
|
+
reduce_trees = opts.delete(:reduce_trees) { proc { |trees| trees.uniq.sort_by(&:to_s) } }
|
101
|
+
printable_requirement = opts.delete(:printable_requirement) { proc { |req| req.to_s } }
|
102
|
+
additional_message_for_conflict = opts.delete(:additional_message_for_conflict) { proc {} }
|
103
|
+
version_for_spec = opts.delete(:version_for_spec) { proc(&:to_s) }
|
104
|
+
|
105
|
+
conflicts.sort.reduce(''.dup) do |o, (name, conflict)|
|
106
|
+
o << %(\n#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":\n)
|
107
|
+
if conflict.locked_requirement
|
108
|
+
o << %( In snapshot (#{name_for_locking_dependency_source}):\n)
|
109
|
+
o << %( #{printable_requirement.call(conflict.locked_requirement)}\n)
|
110
|
+
o << %(\n)
|
111
|
+
end
|
112
|
+
o << %( In #{name_for_explicit_dependency_source}:\n)
|
113
|
+
trees = reduce_trees.call(conflict.requirement_trees)
|
114
|
+
|
115
|
+
o << trees.map do |tree|
|
116
|
+
t = ''.dup
|
117
|
+
depth = 2
|
118
|
+
tree.each do |req|
|
119
|
+
t << ' ' * depth << req.to_s
|
120
|
+
unless tree.last == req
|
121
|
+
if spec = conflict.activated_by_name[name_for(req)]
|
122
|
+
t << %( was resolved to #{version_for_spec.call(spec)}, which)
|
123
|
+
end
|
124
|
+
t << %( depends on)
|
125
|
+
end
|
126
|
+
t << %(\n)
|
127
|
+
depth += 1
|
128
|
+
end
|
129
|
+
t
|
130
|
+
end.join("\n")
|
131
|
+
|
132
|
+
additional_message_for_conflict.call(o, name, conflict)
|
133
|
+
|
134
|
+
o
|
135
|
+
end.strip
|
73
136
|
end
|
74
137
|
end
|
75
138
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Bundler::Molinillo
|
3
4
|
# Conveys information about the resolution process to a user.
|
4
5
|
module UI
|
@@ -48,7 +49,8 @@ module Bundler::Molinillo
|
|
48
49
|
if debug?
|
49
50
|
debug_info = yield
|
50
51
|
debug_info = debug_info.inspect unless debug_info.is_a?(String)
|
51
|
-
|
52
|
+
debug_info = debug_info.split("\n").map { |s| ":#{depth.to_s.rjust 4}: #{s}" }
|
53
|
+
output.puts debug_info
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Bundler::Molinillo
|
3
4
|
class Resolver
|
4
5
|
# A specific resolution from a given {Resolver}
|
@@ -8,22 +9,125 @@ module Bundler::Molinillo
|
|
8
9
|
# @attr [{String,Nil=>[Object]}] requirements the requirements that caused the conflict
|
9
10
|
# @attr [Object, nil] existing the existing spec that was in conflict with
|
10
11
|
# the {#possibility}
|
11
|
-
# @attr [Object]
|
12
|
-
# to a conflict
|
12
|
+
# @attr [Object] possibility_set the set of specs that was unable to be
|
13
|
+
# activated due to a conflict.
|
13
14
|
# @attr [Object] locked_requirement the relevant locking requirement.
|
14
15
|
# @attr [Array<Array<Object>>] requirement_trees the different requirement
|
15
16
|
# trees that led to every requirement for the conflicting name.
|
16
17
|
# @attr [{String=>Object}] activated_by_name the already-activated specs.
|
18
|
+
# @attr [Object] underlying_error an error that has occurred during resolution, and
|
19
|
+
# will be raised at the end of it if no resolution is found.
|
17
20
|
Conflict = Struct.new(
|
18
21
|
:requirement,
|
19
22
|
:requirements,
|
20
23
|
:existing,
|
21
|
-
:
|
24
|
+
:possibility_set,
|
22
25
|
:locked_requirement,
|
23
26
|
:requirement_trees,
|
24
|
-
:activated_by_name
|
27
|
+
:activated_by_name,
|
28
|
+
:underlying_error
|
29
|
+
)
|
30
|
+
|
31
|
+
class Conflict
|
32
|
+
# @return [Object] a spec that was unable to be activated due to a conflict
|
33
|
+
def possibility
|
34
|
+
possibility_set && possibility_set.latest_version
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# A collection of possibility states that share the same dependencies
|
39
|
+
# @attr [Array] dependencies the dependencies for this set of possibilities
|
40
|
+
# @attr [Array] possibilities the possibilities
|
41
|
+
PossibilitySet = Struct.new(:dependencies, :possibilities)
|
42
|
+
|
43
|
+
class PossibilitySet
|
44
|
+
# String representation of the possibility set, for debugging
|
45
|
+
def to_s
|
46
|
+
"[#{possibilities.join(', ')}]"
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Object] most up-to-date dependency in the possibility set
|
50
|
+
def latest_version
|
51
|
+
possibilities.last
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Details of the state to unwind to when a conflict occurs, and the cause of the unwind
|
56
|
+
# @attr [Integer] state_index the index of the state to unwind to
|
57
|
+
# @attr [Object] state_requirement the requirement of the state we're unwinding to
|
58
|
+
# @attr [Array] requirement_tree for the requirement we're relaxing
|
59
|
+
# @attr [Array] conflicting_requirements the requirements that combined to cause the conflict
|
60
|
+
# @attr [Array] requirement_trees for the conflict
|
61
|
+
# @attr [Array] requirements_unwound_to_instead array of unwind requirements that were chosen over this unwind
|
62
|
+
UnwindDetails = Struct.new(
|
63
|
+
:state_index,
|
64
|
+
:state_requirement,
|
65
|
+
:requirement_tree,
|
66
|
+
:conflicting_requirements,
|
67
|
+
:requirement_trees,
|
68
|
+
:requirements_unwound_to_instead
|
25
69
|
)
|
26
70
|
|
71
|
+
class UnwindDetails
|
72
|
+
include Comparable
|
73
|
+
|
74
|
+
# We compare UnwindDetails when choosing which state to unwind to. If
|
75
|
+
# two options have the same state_index we prefer the one most
|
76
|
+
# removed from a requirement that caused the conflict. Both options
|
77
|
+
# would unwind to the same state, but a `grandparent` option will
|
78
|
+
# filter out fewer of its possibilities after doing so - where a state
|
79
|
+
# is both a `parent` and a `grandparent` to requirements that have
|
80
|
+
# caused a conflict this is the correct behaviour.
|
81
|
+
# @param [UnwindDetail] other UnwindDetail to be compared
|
82
|
+
# @return [Integer] integer specifying ordering
|
83
|
+
def <=>(other)
|
84
|
+
if state_index > other.state_index
|
85
|
+
1
|
86
|
+
elsif state_index == other.state_index
|
87
|
+
reversed_requirement_tree_index <=> other.reversed_requirement_tree_index
|
88
|
+
else
|
89
|
+
-1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [Integer] index of state requirement in reversed requirement tree
|
94
|
+
# (the conflicting requirement itself will be at position 0)
|
95
|
+
def reversed_requirement_tree_index
|
96
|
+
@reversed_requirement_tree_index ||=
|
97
|
+
if state_requirement
|
98
|
+
requirement_tree.reverse.index(state_requirement)
|
99
|
+
else
|
100
|
+
999_999
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# @return [Boolean] where the requirement of the state we're unwinding
|
105
|
+
# to directly caused the conflict. Note: in this case, it is
|
106
|
+
# impossible for the state we're unwinding to to be a parent of
|
107
|
+
# any of the other conflicting requirements (or we would have
|
108
|
+
# circularity)
|
109
|
+
def unwinding_to_primary_requirement?
|
110
|
+
requirement_tree.last == state_requirement
|
111
|
+
end
|
112
|
+
|
113
|
+
# @return [Array] array of sub-dependencies to avoid when choosing a
|
114
|
+
# new possibility for the state we've unwound to. Only relevant for
|
115
|
+
# non-primary unwinds
|
116
|
+
def sub_dependencies_to_avoid
|
117
|
+
@requirements_to_avoid ||=
|
118
|
+
requirement_trees.map do |tree|
|
119
|
+
index = tree.index(state_requirement)
|
120
|
+
tree[index + 1] if index
|
121
|
+
end.compact
|
122
|
+
end
|
123
|
+
|
124
|
+
# @return [Array] array of all the requirements that led to the need for
|
125
|
+
# this unwind
|
126
|
+
def all_requirements
|
127
|
+
@all_requirements ||= requirement_trees.flatten(1)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
27
131
|
# @return [SpecificationProvider] the provider that knows about
|
28
132
|
# dependencies, requirements, specifications, versions, etc.
|
29
133
|
attr_reader :specification_provider
|
@@ -52,7 +156,7 @@ module Bundler::Molinillo
|
|
52
156
|
@base = base
|
53
157
|
@states = []
|
54
158
|
@iteration_counter = 0
|
55
|
-
@
|
159
|
+
@parents_of = Hash.new { |h, k| h[k] = [] }
|
56
160
|
end
|
57
161
|
|
58
162
|
# Resolves the {#original_requested} dependencies into a full dependency
|
@@ -64,7 +168,7 @@ module Bundler::Molinillo
|
|
64
168
|
start_resolution
|
65
169
|
|
66
170
|
while state
|
67
|
-
break
|
171
|
+
break if !state.requirement && state.requirements.empty?
|
68
172
|
indicate_progress
|
69
173
|
if state.respond_to?(:pop_possibility_state) # DependencyState
|
70
174
|
debug(depth) { "Creating possibility state for #{requirement} (#{possibilities.count} remaining)" }
|
@@ -78,7 +182,7 @@ module Bundler::Molinillo
|
|
78
182
|
process_topmost_state
|
79
183
|
end
|
80
184
|
|
81
|
-
|
185
|
+
resolve_activated_specs
|
82
186
|
ensure
|
83
187
|
end_resolution
|
84
188
|
end
|
@@ -105,10 +209,23 @@ module Bundler::Molinillo
|
|
105
209
|
|
106
210
|
handle_missing_or_push_dependency_state(initial_state)
|
107
211
|
|
108
|
-
debug { "Starting resolution (#{@started_at})" }
|
212
|
+
debug { "Starting resolution (#{@started_at})\nUser-requested dependencies: #{original_requested}" }
|
109
213
|
resolver_ui.before_resolution
|
110
214
|
end
|
111
215
|
|
216
|
+
def resolve_activated_specs
|
217
|
+
activated.vertices.each do |_, vertex|
|
218
|
+
next unless vertex.payload
|
219
|
+
|
220
|
+
latest_version = vertex.payload.possibilities.reverse_each.find do |possibility|
|
221
|
+
vertex.requirements.all? { |req| requirement_satisfied_by?(req, activated, possibility) }
|
222
|
+
end
|
223
|
+
|
224
|
+
activated.set_payload(vertex.name, latest_version)
|
225
|
+
end
|
226
|
+
activated.freeze
|
227
|
+
end
|
228
|
+
|
112
229
|
# Ends the resolution process
|
113
230
|
# @return [void]
|
114
231
|
def end_resolution
|
@@ -136,9 +253,12 @@ module Bundler::Molinillo
|
|
136
253
|
if possibility
|
137
254
|
attempt_to_activate
|
138
255
|
else
|
139
|
-
create_conflict
|
140
|
-
unwind_for_conflict
|
256
|
+
create_conflict
|
257
|
+
unwind_for_conflict
|
141
258
|
end
|
259
|
+
rescue CircularDependencyError => underlying_error
|
260
|
+
create_conflict(underlying_error)
|
261
|
+
unwind_for_conflict
|
142
262
|
end
|
143
263
|
|
144
264
|
# @return [Object] the current possibility that the resolution is trying
|
@@ -158,7 +278,10 @@ module Bundler::Molinillo
|
|
158
278
|
# @return [DependencyState] the initial state for the resolution
|
159
279
|
def initial_state
|
160
280
|
graph = DependencyGraph.new.tap do |dg|
|
161
|
-
original_requested.each
|
281
|
+
original_requested.each do |requested|
|
282
|
+
vertex = dg.add_vertex(name_for(requested), nil, true)
|
283
|
+
vertex.explicit_requirements << requested
|
284
|
+
end
|
162
285
|
dg.tag(:initial_state)
|
163
286
|
end
|
164
287
|
|
@@ -169,52 +292,287 @@ module Bundler::Molinillo
|
|
169
292
|
requirements,
|
170
293
|
graph,
|
171
294
|
initial_requirement,
|
172
|
-
initial_requirement
|
295
|
+
possibilities_for_requirement(initial_requirement, graph),
|
173
296
|
0,
|
174
|
-
{}
|
297
|
+
{},
|
298
|
+
[]
|
175
299
|
)
|
176
300
|
end
|
177
301
|
|
178
302
|
# Unwinds the states stack because a conflict has been encountered
|
179
303
|
# @return [void]
|
180
304
|
def unwind_for_conflict
|
181
|
-
|
305
|
+
details_for_unwind = build_details_for_unwind
|
306
|
+
unwind_options = unused_unwind_options
|
307
|
+
debug(depth) { "Unwinding for conflict: #{requirement} to #{details_for_unwind.state_index / 2}" }
|
182
308
|
conflicts.tap do |c|
|
183
|
-
sliced_states = states.slice!((
|
184
|
-
|
309
|
+
sliced_states = states.slice!((details_for_unwind.state_index + 1)..-1)
|
310
|
+
raise_error_unless_state(c)
|
185
311
|
activated.rewind_to(sliced_states.first || :initial_state) if sliced_states
|
186
312
|
state.conflicts = c
|
313
|
+
state.unused_unwind_options = unwind_options
|
314
|
+
filter_possibilities_after_unwind(details_for_unwind)
|
187
315
|
index = states.size - 1
|
188
|
-
@
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
#
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
316
|
+
@parents_of.each { |_, a| a.reject! { |i| i >= index } }
|
317
|
+
state.unused_unwind_options.reject! { |uw| uw.state_index >= index }
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
# Raises a VersionConflict error, or any underlying error, if there is no
|
322
|
+
# current state
|
323
|
+
# @return [void]
|
324
|
+
def raise_error_unless_state(conflicts)
|
325
|
+
return if state
|
326
|
+
|
327
|
+
error = conflicts.values.map(&:underlying_error).compact.first
|
328
|
+
raise error || VersionConflict.new(conflicts, specification_provider)
|
329
|
+
end
|
330
|
+
|
331
|
+
# @return [UnwindDetails] Details of the nearest index to which we could unwind
|
332
|
+
def build_details_for_unwind
|
333
|
+
# Get the possible unwinds for the current conflict
|
334
|
+
current_conflict = conflicts[name]
|
335
|
+
binding_requirements = binding_requirements_for_conflict(current_conflict)
|
336
|
+
unwind_details = unwind_options_for_requirements(binding_requirements)
|
337
|
+
|
338
|
+
last_detail_for_current_unwind = unwind_details.sort.last
|
339
|
+
current_detail = last_detail_for_current_unwind
|
340
|
+
|
341
|
+
# Look for past conflicts that could be unwound to affect the
|
342
|
+
# requirement tree for the current conflict
|
343
|
+
relevant_unused_unwinds = unused_unwind_options.select do |alternative|
|
344
|
+
intersecting_requirements =
|
345
|
+
last_detail_for_current_unwind.all_requirements &
|
346
|
+
alternative.requirements_unwound_to_instead
|
347
|
+
next if intersecting_requirements.empty?
|
348
|
+
# Find the highest index unwind whilst looping through
|
349
|
+
current_detail = alternative if alternative > current_detail
|
350
|
+
alternative
|
351
|
+
end
|
352
|
+
|
353
|
+
# Add the current unwind options to the `unused_unwind_options` array.
|
354
|
+
# The "used" option will be filtered out during `unwind_for_conflict`.
|
355
|
+
state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 }
|
356
|
+
|
357
|
+
# Update the requirements_unwound_to_instead on any relevant unused unwinds
|
358
|
+
relevant_unused_unwinds.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
|
359
|
+
unwind_details.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
|
360
|
+
|
361
|
+
current_detail
|
362
|
+
end
|
363
|
+
|
364
|
+
# @param [Array<Object>] array of requirements that combine to create a conflict
|
365
|
+
# @return [Array<UnwindDetails>] array of UnwindDetails that have a chance
|
366
|
+
# of resolving the passed requirements
|
367
|
+
def unwind_options_for_requirements(binding_requirements)
|
368
|
+
unwind_details = []
|
369
|
+
|
370
|
+
trees = []
|
371
|
+
binding_requirements.reverse_each do |r|
|
372
|
+
partial_tree = [r]
|
373
|
+
trees << partial_tree
|
374
|
+
unwind_details << UnwindDetails.new(-1, nil, partial_tree, binding_requirements, trees, [])
|
375
|
+
|
376
|
+
# If this requirement has alternative possibilities, check if any would
|
377
|
+
# satisfy the other requirements that created this conflict
|
378
|
+
requirement_state = find_state_for(r)
|
379
|
+
if conflict_fixing_possibilities?(requirement_state, binding_requirements)
|
380
|
+
unwind_details << UnwindDetails.new(
|
381
|
+
states.index(requirement_state),
|
382
|
+
r,
|
383
|
+
partial_tree,
|
384
|
+
binding_requirements,
|
385
|
+
trees,
|
386
|
+
[]
|
387
|
+
)
|
388
|
+
end
|
389
|
+
|
390
|
+
# Next, look at the parent of this requirement, and check if the requirement
|
391
|
+
# could have been avoided if an alternative PossibilitySet had been chosen
|
392
|
+
parent_r = parent_of(r)
|
393
|
+
next if parent_r.nil?
|
394
|
+
partial_tree.unshift(parent_r)
|
395
|
+
requirement_state = find_state_for(parent_r)
|
396
|
+
if requirement_state.possibilities.any? { |set| !set.dependencies.include?(r) }
|
397
|
+
unwind_details << UnwindDetails.new(
|
398
|
+
states.index(requirement_state),
|
399
|
+
parent_r,
|
400
|
+
partial_tree,
|
401
|
+
binding_requirements,
|
402
|
+
trees,
|
403
|
+
[]
|
404
|
+
)
|
405
|
+
end
|
406
|
+
|
407
|
+
# Finally, look at the grandparent and up of this requirement, looking
|
408
|
+
# for any possibilities that wouldn't create their parent requirement
|
409
|
+
grandparent_r = parent_of(parent_r)
|
410
|
+
until grandparent_r.nil?
|
411
|
+
partial_tree.unshift(grandparent_r)
|
412
|
+
requirement_state = find_state_for(grandparent_r)
|
413
|
+
if requirement_state.possibilities.any? { |set| !set.dependencies.include?(parent_r) }
|
414
|
+
unwind_details << UnwindDetails.new(
|
415
|
+
states.index(requirement_state),
|
416
|
+
grandparent_r,
|
417
|
+
partial_tree,
|
418
|
+
binding_requirements,
|
419
|
+
trees,
|
420
|
+
[]
|
421
|
+
)
|
422
|
+
end
|
423
|
+
parent_r = grandparent_r
|
424
|
+
grandparent_r = parent_of(parent_r)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
unwind_details
|
429
|
+
end
|
430
|
+
|
431
|
+
# @param [DependencyState] state
|
432
|
+
# @param [Array] array of requirements
|
433
|
+
# @return [Boolean] whether or not the given state has any possibilities
|
434
|
+
# that could satisfy the given requirements
|
435
|
+
def conflict_fixing_possibilities?(state, binding_requirements)
|
436
|
+
return false unless state
|
437
|
+
|
438
|
+
state.possibilities.any? do |possibility_set|
|
439
|
+
possibility_set.possibilities.any? do |poss|
|
440
|
+
possibility_satisfies_requirements?(poss, binding_requirements)
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
# Filter's a state's possibilities to remove any that would not fix the
|
446
|
+
# conflict we've just rewound from
|
447
|
+
# @param [UnwindDetails] details of the conflict just unwound from
|
448
|
+
# @return [void]
|
449
|
+
def filter_possibilities_after_unwind(unwind_details)
|
450
|
+
return unless state && !state.possibilities.empty?
|
451
|
+
|
452
|
+
if unwind_details.unwinding_to_primary_requirement?
|
453
|
+
filter_possibilities_for_primary_unwind(unwind_details)
|
454
|
+
else
|
455
|
+
filter_possibilities_for_parent_unwind(unwind_details)
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
# Filter's a state's possibilities to remove any that would not satisfy
|
460
|
+
# the requirements in the conflict we've just rewound from
|
461
|
+
# @param [UnwindDetails] details of the conflict just unwound from
|
462
|
+
# @return [void]
|
463
|
+
def filter_possibilities_for_primary_unwind(unwind_details)
|
464
|
+
unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
|
465
|
+
unwinds_to_state << unwind_details
|
466
|
+
unwind_requirement_sets = unwinds_to_state.map(&:conflicting_requirements)
|
467
|
+
|
468
|
+
state.possibilities.reject! do |possibility_set|
|
469
|
+
possibility_set.possibilities.none? do |poss|
|
470
|
+
unwind_requirement_sets.any? do |requirements|
|
471
|
+
possibility_satisfies_requirements?(poss, requirements)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
# @param [Object] possibility a single possibility
|
478
|
+
# @param [Array] requirements an array of requirements
|
479
|
+
# @return [Boolean] whether the possibility satisfies all of the
|
480
|
+
# given requirements
|
481
|
+
def possibility_satisfies_requirements?(possibility, requirements)
|
482
|
+
name = name_for(possibility)
|
483
|
+
|
484
|
+
activated.tag(:swap)
|
485
|
+
activated.set_payload(name, possibility) if activated.vertex_named(name)
|
486
|
+
satisfied = requirements.all? { |r| requirement_satisfied_by?(r, activated, possibility) }
|
487
|
+
activated.rewind_to(:swap)
|
488
|
+
|
489
|
+
satisfied
|
490
|
+
end
|
491
|
+
|
492
|
+
# Filter's a state's possibilities to remove any that would (eventually)
|
493
|
+
# create a requirement in the conflict we've just rewound from
|
494
|
+
# @param [UnwindDetails] details of the conflict just unwound from
|
495
|
+
# @return [void]
|
496
|
+
def filter_possibilities_for_parent_unwind(unwind_details)
|
497
|
+
unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
|
498
|
+
unwinds_to_state << unwind_details
|
499
|
+
|
500
|
+
primary_unwinds = unwinds_to_state.select(&:unwinding_to_primary_requirement?).uniq
|
501
|
+
parent_unwinds = unwinds_to_state.uniq - primary_unwinds
|
502
|
+
|
503
|
+
allowed_possibility_sets = Compatibility.flat_map(primary_unwinds) do |unwind|
|
504
|
+
states[unwind.state_index].possibilities.select do |possibility_set|
|
505
|
+
possibility_set.possibilities.any? do |poss|
|
506
|
+
possibility_satisfies_requirements?(poss, unwind.conflicting_requirements)
|
205
507
|
end
|
206
|
-
r = parent_of(r)
|
207
508
|
end
|
208
509
|
end
|
209
510
|
|
210
|
-
|
511
|
+
requirements_to_avoid = Compatibility.flat_map(parent_unwinds, &:sub_dependencies_to_avoid)
|
512
|
+
|
513
|
+
state.possibilities.reject! do |possibility_set|
|
514
|
+
!allowed_possibility_sets.include?(possibility_set) &&
|
515
|
+
(requirements_to_avoid - possibility_set.dependencies).empty?
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
# @param [Conflict] conflict
|
520
|
+
# @return [Array] minimal array of requirements that would cause the passed
|
521
|
+
# conflict to occur.
|
522
|
+
def binding_requirements_for_conflict(conflict)
|
523
|
+
return [conflict.requirement] if conflict.possibility.nil?
|
524
|
+
|
525
|
+
possible_binding_requirements = conflict.requirements.values.flatten(1).uniq
|
526
|
+
|
527
|
+
# When there’s a `CircularDependency` error the conflicting requirement
|
528
|
+
# (the one causing the circular) won’t be `conflict.requirement`
|
529
|
+
# (which won’t be for the right state, because we won’t have created it,
|
530
|
+
# because it’s circular).
|
531
|
+
# We need to make sure we have that requirement in the conflict’s list,
|
532
|
+
# otherwise we won’t be able to unwind properly, so we just return all
|
533
|
+
# the requirements for the conflict.
|
534
|
+
return possible_binding_requirements if conflict.underlying_error
|
535
|
+
|
536
|
+
possibilities = search_for(conflict.requirement)
|
537
|
+
|
538
|
+
# If all the requirements together don't filter out all possibilities,
|
539
|
+
# then the only two requirements we need to consider are the initial one
|
540
|
+
# (where the dependency's version was first chosen) and the last
|
541
|
+
if binding_requirement_in_set?(nil, possible_binding_requirements, possibilities)
|
542
|
+
return [conflict.requirement, requirement_for_existing_name(name_for(conflict.requirement))].compact
|
543
|
+
end
|
544
|
+
|
545
|
+
# Loop through the possible binding requirements, removing each one
|
546
|
+
# that doesn't bind. Use a `reverse_each` as we want the earliest set of
|
547
|
+
# binding requirements, and don't use `reject!` as we wish to refine the
|
548
|
+
# array *on each iteration*.
|
549
|
+
binding_requirements = possible_binding_requirements.dup
|
550
|
+
possible_binding_requirements.reverse_each do |req|
|
551
|
+
next if req == conflict.requirement
|
552
|
+
unless binding_requirement_in_set?(req, binding_requirements, possibilities)
|
553
|
+
binding_requirements -= [req]
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
binding_requirements
|
558
|
+
end
|
559
|
+
|
560
|
+
# @param [Object] requirement we wish to check
|
561
|
+
# @param [Array] array of requirements
|
562
|
+
# @param [Array] array of possibilities the requirements will be used to filter
|
563
|
+
# @return [Boolean] whether or not the given requirement is required to filter
|
564
|
+
# out all elements of the array of possibilities.
|
565
|
+
def binding_requirement_in_set?(requirement, possible_binding_requirements, possibilities)
|
566
|
+
possibilities.any? do |poss|
|
567
|
+
possibility_satisfies_requirements?(poss, possible_binding_requirements - [requirement])
|
568
|
+
end
|
211
569
|
end
|
212
570
|
|
213
571
|
# @return [Object] the requirement that led to `requirement` being added
|
214
572
|
# to the list of requirements.
|
215
573
|
def parent_of(requirement)
|
216
574
|
return unless requirement
|
217
|
-
return unless index = @
|
575
|
+
return unless index = @parents_of[requirement].last
|
218
576
|
return unless parent_state = @states[index]
|
219
577
|
parent_state.requirement
|
220
578
|
end
|
@@ -222,7 +580,8 @@ module Bundler::Molinillo
|
|
222
580
|
# @return [Object] the requirement that led to a version of a possibility
|
223
581
|
# with the given name being activated.
|
224
582
|
def requirement_for_existing_name(name)
|
225
|
-
return nil unless activated.vertex_named(name)
|
583
|
+
return nil unless vertex = activated.vertex_named(name)
|
584
|
+
return nil unless vertex.payload
|
226
585
|
states.find { |s| s.name == name }.requirement
|
227
586
|
end
|
228
587
|
|
@@ -230,18 +589,12 @@ module Bundler::Molinillo
|
|
230
589
|
# `requirement`.
|
231
590
|
def find_state_for(requirement)
|
232
591
|
return nil unless requirement
|
233
|
-
states.
|
234
|
-
end
|
235
|
-
|
236
|
-
# @return [Boolean] whether or not the given state has any possibilities
|
237
|
-
# left.
|
238
|
-
def state_any?(state)
|
239
|
-
state && state.possibilities.any?
|
592
|
+
states.find { |i| requirement == i.requirement }
|
240
593
|
end
|
241
594
|
|
242
595
|
# @return [Conflict] a {Conflict} that reflects the failure to activate
|
243
596
|
# the {#possibility} in conjunction with the current {#state}
|
244
|
-
def create_conflict
|
597
|
+
def create_conflict(underlying_error = nil)
|
245
598
|
vertex = activated.vertex_named(name)
|
246
599
|
locked_requirement = locked_requirement_named(name)
|
247
600
|
|
@@ -250,18 +603,21 @@ module Bundler::Molinillo
|
|
250
603
|
requirements[name_for_explicit_dependency_source] = vertex.explicit_requirements
|
251
604
|
end
|
252
605
|
requirements[name_for_locking_dependency_source] = [locked_requirement] if locked_requirement
|
253
|
-
vertex.incoming_edges.each
|
606
|
+
vertex.incoming_edges.each do |edge|
|
607
|
+
(requirements[edge.origin.payload.latest_version] ||= []).unshift(edge.requirement)
|
608
|
+
end
|
254
609
|
|
255
610
|
activated_by_name = {}
|
256
|
-
activated.each { |v| activated_by_name[v.name] = v.payload if v.payload }
|
611
|
+
activated.each { |v| activated_by_name[v.name] = v.payload.latest_version if v.payload }
|
257
612
|
conflicts[name] = Conflict.new(
|
258
613
|
requirement,
|
259
614
|
requirements,
|
260
|
-
vertex.payload,
|
615
|
+
vertex.payload && vertex.payload.latest_version,
|
261
616
|
possibility,
|
262
617
|
locked_requirement,
|
263
618
|
requirement_trees,
|
264
|
-
activated_by_name
|
619
|
+
activated_by_name,
|
620
|
+
underlying_error
|
265
621
|
)
|
266
622
|
end
|
267
623
|
|
@@ -311,97 +667,48 @@ module Bundler::Molinillo
|
|
311
667
|
# @return [void]
|
312
668
|
def attempt_to_activate
|
313
669
|
debug(depth) { 'Attempting to activate ' + possibility.to_s }
|
314
|
-
|
315
|
-
if
|
316
|
-
debug(depth) { "Found existing spec (#{
|
317
|
-
|
670
|
+
existing_vertex = activated.vertex_named(name)
|
671
|
+
if existing_vertex.payload
|
672
|
+
debug(depth) { "Found existing spec (#{existing_vertex.payload})" }
|
673
|
+
attempt_to_filter_existing_spec(existing_vertex)
|
318
674
|
else
|
319
|
-
|
675
|
+
latest = possibility.latest_version
|
676
|
+
# use reject!(!satisfied) for 1.8.7 compatibility
|
677
|
+
possibility.possibilities.reject! do |possibility|
|
678
|
+
!requirement_satisfied_by?(requirement, activated, possibility)
|
679
|
+
end
|
680
|
+
if possibility.latest_version.nil?
|
681
|
+
# ensure there's a possibility for better error messages
|
682
|
+
possibility.possibilities << latest if latest
|
683
|
+
create_conflict
|
684
|
+
unwind_for_conflict
|
685
|
+
else
|
686
|
+
activate_new_spec
|
687
|
+
end
|
320
688
|
end
|
321
689
|
end
|
322
690
|
|
323
|
-
# Attempts to
|
324
|
-
# already been activated)
|
691
|
+
# Attempts to update the existing vertex's `PossibilitySet` with a filtered version
|
325
692
|
# @return [void]
|
326
|
-
def
|
327
|
-
|
328
|
-
if
|
693
|
+
def attempt_to_filter_existing_spec(vertex)
|
694
|
+
filtered_set = filtered_possibility_set(vertex)
|
695
|
+
if !filtered_set.possibilities.empty?
|
696
|
+
activated.set_payload(name, filtered_set)
|
329
697
|
new_requirements = requirements.dup
|
330
698
|
push_state_for_requirements(new_requirements, false)
|
331
699
|
else
|
332
|
-
return if attempt_to_swap_possibility
|
333
700
|
create_conflict
|
334
|
-
debug(depth) { "Unsatisfied by existing spec (#{
|
701
|
+
debug(depth) { "Unsatisfied by existing spec (#{vertex.payload})" }
|
335
702
|
unwind_for_conflict
|
336
703
|
end
|
337
704
|
end
|
338
705
|
|
339
|
-
#
|
340
|
-
#
|
341
|
-
# @
|
342
|
-
|
343
|
-
|
344
|
-
vertex
|
345
|
-
activated.set_payload(name, possibility)
|
346
|
-
if !vertex.requirements.
|
347
|
-
all? { |r| requirement_satisfied_by?(r, activated, possibility) } ||
|
348
|
-
!new_spec_satisfied?
|
349
|
-
activated.rewind_to(:swap)
|
350
|
-
return
|
351
|
-
end
|
352
|
-
fixup_swapped_children(vertex)
|
353
|
-
activate_spec
|
354
|
-
end
|
355
|
-
|
356
|
-
# Ensures there are no orphaned successors to the given {vertex}.
|
357
|
-
# @param [DependencyGraph::Vertex] vertex the vertex to fix up.
|
358
|
-
# @return [void]
|
359
|
-
def fixup_swapped_children(vertex)
|
360
|
-
payload = vertex.payload
|
361
|
-
deps = dependencies_for(payload).group_by(&method(:name_for))
|
362
|
-
vertex.outgoing_edges.each do |outgoing_edge|
|
363
|
-
@parent_of[outgoing_edge.requirement] = states.size - 1
|
364
|
-
succ = outgoing_edge.destination
|
365
|
-
matching_deps = Array(deps[succ.name])
|
366
|
-
if matching_deps.empty? && !succ.root? && succ.predecessors.to_a == [vertex]
|
367
|
-
debug(depth) { "Removing orphaned spec #{succ.name} after swapping #{name}" }
|
368
|
-
succ.requirements.each { |r| @parent_of.delete(r) }
|
369
|
-
|
370
|
-
removed_names = activated.detach_vertex_named(succ.name).map(&:name)
|
371
|
-
requirements.delete_if do |r|
|
372
|
-
# the only removed vertices are those with no other requirements,
|
373
|
-
# so it's safe to delete only based upon name here
|
374
|
-
removed_names.include?(name_for(r))
|
375
|
-
end
|
376
|
-
elsif !matching_deps.include?(outgoing_edge.requirement)
|
377
|
-
activated.delete_edge(outgoing_edge)
|
378
|
-
requirements.delete(outgoing_edge.requirement)
|
379
|
-
end
|
380
|
-
end
|
381
|
-
end
|
382
|
-
|
383
|
-
# Attempts to activate the current {#possibility} (given that it hasn't
|
384
|
-
# already been activated)
|
385
|
-
# @return [void]
|
386
|
-
def attempt_to_activate_new_spec
|
387
|
-
if new_spec_satisfied?
|
388
|
-
activate_spec
|
389
|
-
else
|
390
|
-
create_conflict
|
391
|
-
unwind_for_conflict
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
# @return [Boolean] whether the current spec is satisfied as a new
|
396
|
-
# possibility.
|
397
|
-
def new_spec_satisfied?
|
398
|
-
locked_requirement = locked_requirement_named(name)
|
399
|
-
requested_spec_satisfied = requirement_satisfied_by?(requirement, activated, possibility)
|
400
|
-
locked_spec_satisfied = !locked_requirement ||
|
401
|
-
requirement_satisfied_by?(locked_requirement, activated, possibility)
|
402
|
-
debug(depth) { 'Unsatisfied by requested spec' } unless requested_spec_satisfied
|
403
|
-
debug(depth) { 'Unsatisfied by locked spec' } unless locked_spec_satisfied
|
404
|
-
requested_spec_satisfied && locked_spec_satisfied
|
706
|
+
# Generates a filtered version of the existing vertex's `PossibilitySet` using the
|
707
|
+
# current state's `requirement`
|
708
|
+
# @param [Object] existing vertex
|
709
|
+
# @return [PossibilitySet] filtered possibility set
|
710
|
+
def filtered_possibility_set(vertex)
|
711
|
+
PossibilitySet.new(vertex.payload.dependencies, vertex.payload.possibilities & possibility.possibilities)
|
405
712
|
end
|
406
713
|
|
407
714
|
# @param [String] requirement_name the spec name to search for
|
@@ -415,24 +722,25 @@ module Bundler::Molinillo
|
|
415
722
|
# Add the current {#possibility} to the dependency graph of the current
|
416
723
|
# {#state}
|
417
724
|
# @return [void]
|
418
|
-
def
|
725
|
+
def activate_new_spec
|
419
726
|
conflicts.delete(name)
|
420
|
-
debug(depth) {
|
727
|
+
debug(depth) { "Activated #{name} at #{possibility}" }
|
421
728
|
activated.set_payload(name, possibility)
|
422
729
|
require_nested_dependencies_for(possibility)
|
423
730
|
end
|
424
731
|
|
425
732
|
# Requires the dependencies that the recently activated spec has
|
426
|
-
# @param [Object]
|
733
|
+
# @param [Object] activated_possibility the PossibilitySet that has just been
|
427
734
|
# activated
|
428
735
|
# @return [void]
|
429
|
-
def require_nested_dependencies_for(
|
430
|
-
nested_dependencies = dependencies_for(
|
736
|
+
def require_nested_dependencies_for(possibility_set)
|
737
|
+
nested_dependencies = dependencies_for(possibility_set.latest_version)
|
431
738
|
debug(depth) { "Requiring nested dependencies (#{nested_dependencies.join(', ')})" }
|
432
739
|
nested_dependencies.each do |d|
|
433
|
-
activated.add_child_vertex(name_for(d), nil, [name_for(
|
740
|
+
activated.add_child_vertex(name_for(d), nil, [name_for(possibility_set.latest_version)], d)
|
434
741
|
parent_index = states.size - 1
|
435
|
-
@
|
742
|
+
parents = @parents_of[d]
|
743
|
+
parents << parent_index if parents.empty?
|
436
744
|
end
|
437
745
|
|
438
746
|
push_state_for_requirements(requirements + nested_dependencies, !nested_dependencies.empty?)
|
@@ -444,20 +752,75 @@ module Bundler::Molinillo
|
|
444
752
|
# @return [void]
|
445
753
|
def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated)
|
446
754
|
new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort
|
447
|
-
new_requirement =
|
755
|
+
new_requirement = nil
|
756
|
+
loop do
|
757
|
+
new_requirement = new_requirements.shift
|
758
|
+
break if new_requirement.nil? || states.none? { |s| s.requirement == new_requirement }
|
759
|
+
end
|
448
760
|
new_name = new_requirement ? name_for(new_requirement) : ''.freeze
|
449
|
-
possibilities =
|
761
|
+
possibilities = possibilities_for_requirement(new_requirement)
|
450
762
|
handle_missing_or_push_dependency_state DependencyState.new(
|
451
763
|
new_name, new_requirements, new_activated,
|
452
|
-
new_requirement, possibilities, depth, conflicts.dup
|
764
|
+
new_requirement, possibilities, depth, conflicts.dup, unused_unwind_options.dup
|
453
765
|
)
|
454
766
|
end
|
455
767
|
|
768
|
+
# Checks a proposed requirement with any existing locked requirement
|
769
|
+
# before generating an array of possibilities for it.
|
770
|
+
# @param [Object] the proposed requirement
|
771
|
+
# @return [Array] possibilities
|
772
|
+
def possibilities_for_requirement(requirement, activated = self.activated)
|
773
|
+
return [] unless requirement
|
774
|
+
if locked_requirement_named(name_for(requirement))
|
775
|
+
return locked_requirement_possibility_set(requirement, activated)
|
776
|
+
end
|
777
|
+
|
778
|
+
group_possibilities(search_for(requirement))
|
779
|
+
end
|
780
|
+
|
781
|
+
# @param [Object] the proposed requirement
|
782
|
+
# @return [Array] possibility set containing only the locked requirement, if any
|
783
|
+
def locked_requirement_possibility_set(requirement, activated = self.activated)
|
784
|
+
all_possibilities = search_for(requirement)
|
785
|
+
locked_requirement = locked_requirement_named(name_for(requirement))
|
786
|
+
|
787
|
+
# Longwinded way to build a possibilities array with either the locked
|
788
|
+
# requirement or nothing in it. Required, since the API for
|
789
|
+
# locked_requirement isn't guaranteed.
|
790
|
+
locked_possibilities = all_possibilities.select do |possibility|
|
791
|
+
requirement_satisfied_by?(locked_requirement, activated, possibility)
|
792
|
+
end
|
793
|
+
|
794
|
+
group_possibilities(locked_possibilities)
|
795
|
+
end
|
796
|
+
|
797
|
+
# Build an array of PossibilitySets, with each element representing a group of
|
798
|
+
# dependency versions that all have the same sub-dependency version constraints
|
799
|
+
# and are contiguous.
|
800
|
+
# @param [Array] an array of possibilities
|
801
|
+
# @return [Array] an array of possibility sets
|
802
|
+
def group_possibilities(possibilities)
|
803
|
+
possibility_sets = []
|
804
|
+
current_possibility_set = nil
|
805
|
+
|
806
|
+
possibilities.reverse_each do |possibility|
|
807
|
+
dependencies = dependencies_for(possibility)
|
808
|
+
if current_possibility_set && current_possibility_set.dependencies == dependencies
|
809
|
+
current_possibility_set.possibilities.unshift(possibility)
|
810
|
+
else
|
811
|
+
possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility]))
|
812
|
+
current_possibility_set = possibility_sets.first
|
813
|
+
end
|
814
|
+
end
|
815
|
+
|
816
|
+
possibility_sets
|
817
|
+
end
|
818
|
+
|
456
819
|
# Pushes a new {DependencyState}.
|
457
820
|
# If the {#specification_provider} says to
|
458
821
|
# {SpecificationProvider#allow_missing?} that particular requirement, and
|
459
822
|
# there are no possibilities for that requirement, then `state` is not
|
460
|
-
# pushed, and the
|
823
|
+
# pushed, and the vertex in {#activated} is removed, and we continue
|
461
824
|
# resolving the remaining requirements.
|
462
825
|
# @param [DependencyState] state
|
463
826
|
# @return [void]
|