bundler-clone 4.0.15
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 +7 -0
- data/CHANGELOG.md +5670 -0
- data/LICENSE.md +22 -0
- data/README.md +58 -0
- data/bundler.gemspec +46 -0
- data/exe/bundle +29 -0
- data/exe/bundler +4 -0
- data/lib/bundler/.document +1 -0
- data/lib/bundler/build_metadata.rb +44 -0
- data/lib/bundler/capistrano.rb +4 -0
- data/lib/bundler/checksum.rb +270 -0
- data/lib/bundler/ci_detector.rb +75 -0
- data/lib/bundler/cli/add.rb +62 -0
- data/lib/bundler/cli/binstubs.rb +57 -0
- data/lib/bundler/cli/cache.rb +32 -0
- data/lib/bundler/cli/check.rb +40 -0
- data/lib/bundler/cli/clean.rb +25 -0
- data/lib/bundler/cli/common.rb +161 -0
- data/lib/bundler/cli/config.rb +208 -0
- data/lib/bundler/cli/console.rb +47 -0
- data/lib/bundler/cli/doctor/diagnose.rb +167 -0
- data/lib/bundler/cli/doctor/ssl.rb +249 -0
- data/lib/bundler/cli/doctor.rb +33 -0
- data/lib/bundler/cli/exec.rb +114 -0
- data/lib/bundler/cli/fund.rb +36 -0
- data/lib/bundler/cli/gem.rb +493 -0
- data/lib/bundler/cli/info.rb +83 -0
- data/lib/bundler/cli/init.rb +51 -0
- data/lib/bundler/cli/install.rb +127 -0
- data/lib/bundler/cli/issue.rb +41 -0
- data/lib/bundler/cli/list.rb +97 -0
- data/lib/bundler/cli/lock.rb +94 -0
- data/lib/bundler/cli/open.rb +29 -0
- data/lib/bundler/cli/outdated.rb +337 -0
- data/lib/bundler/cli/platform.rb +48 -0
- data/lib/bundler/cli/plugin.rb +39 -0
- data/lib/bundler/cli/pristine.rb +64 -0
- data/lib/bundler/cli/remove.rb +17 -0
- data/lib/bundler/cli/show.rb +71 -0
- data/lib/bundler/cli/update.rb +125 -0
- data/lib/bundler/cli.rb +829 -0
- data/lib/bundler/compact_index_client/cache.rb +96 -0
- data/lib/bundler/compact_index_client/cache_file.rb +148 -0
- data/lib/bundler/compact_index_client/parser.rb +87 -0
- data/lib/bundler/compact_index_client/updater.rb +105 -0
- data/lib/bundler/compact_index_client.rb +92 -0
- data/lib/bundler/constants.rb +14 -0
- data/lib/bundler/current_ruby.rb +94 -0
- data/lib/bundler/definition.rb +1304 -0
- data/lib/bundler/dependency.rb +151 -0
- data/lib/bundler/deployment.rb +6 -0
- data/lib/bundler/deprecate.rb +44 -0
- data/lib/bundler/digest.rb +71 -0
- data/lib/bundler/dsl.rb +642 -0
- data/lib/bundler/endpoint_specification.rb +184 -0
- data/lib/bundler/env.rb +148 -0
- data/lib/bundler/environment_preserver.rb +69 -0
- data/lib/bundler/errors.rb +277 -0
- data/lib/bundler/feature_flag.rb +20 -0
- data/lib/bundler/fetcher/base.rb +55 -0
- data/lib/bundler/fetcher/compact_index.rb +133 -0
- data/lib/bundler/fetcher/dependency.rb +85 -0
- data/lib/bundler/fetcher/downloader.rb +116 -0
- data/lib/bundler/fetcher/gem_remote_fetcher.rb +24 -0
- data/lib/bundler/fetcher/index.rb +25 -0
- data/lib/bundler/fetcher.rb +365 -0
- data/lib/bundler/force_platform.rb +16 -0
- data/lib/bundler/friendly_errors.rb +127 -0
- data/lib/bundler/gem_helper.rb +237 -0
- data/lib/bundler/gem_tasks.rb +7 -0
- data/lib/bundler/gem_version_promoter.rb +147 -0
- data/lib/bundler/index.rb +203 -0
- data/lib/bundler/injector.rb +284 -0
- data/lib/bundler/inline.rb +106 -0
- data/lib/bundler/installer/gem_installer.rb +88 -0
- data/lib/bundler/installer/parallel_installer.rb +280 -0
- data/lib/bundler/installer/standalone.rb +113 -0
- data/lib/bundler/installer.rb +241 -0
- data/lib/bundler/lazy_specification.rb +270 -0
- data/lib/bundler/lockfile_generator.rb +119 -0
- data/lib/bundler/lockfile_parser.rb +328 -0
- data/lib/bundler/man/.document +1 -0
- data/lib/bundler/man/bundle-add.1 +79 -0
- data/lib/bundler/man/bundle-add.1.ronn +92 -0
- data/lib/bundler/man/bundle-binstubs.1 +30 -0
- data/lib/bundler/man/bundle-binstubs.1.ronn +42 -0
- data/lib/bundler/man/bundle-cache.1 +56 -0
- data/lib/bundler/man/bundle-cache.1.ronn +95 -0
- data/lib/bundler/man/bundle-check.1 +21 -0
- data/lib/bundler/man/bundle-check.1.ronn +26 -0
- data/lib/bundler/man/bundle-clean.1 +17 -0
- data/lib/bundler/man/bundle-clean.1.ronn +18 -0
- data/lib/bundler/man/bundle-config.1 +339 -0
- data/lib/bundler/man/bundle-config.1.ronn +455 -0
- data/lib/bundler/man/bundle-console.1 +33 -0
- data/lib/bundler/man/bundle-console.1.ronn +39 -0
- data/lib/bundler/man/bundle-doctor.1 +69 -0
- data/lib/bundler/man/bundle-doctor.1.ronn +77 -0
- data/lib/bundler/man/bundle-env.1 +9 -0
- data/lib/bundler/man/bundle-env.1.ronn +10 -0
- data/lib/bundler/man/bundle-exec.1 +104 -0
- data/lib/bundler/man/bundle-exec.1.ronn +150 -0
- data/lib/bundler/man/bundle-fund.1 +22 -0
- data/lib/bundler/man/bundle-fund.1.ronn +25 -0
- data/lib/bundler/man/bundle-gem.1 +107 -0
- data/lib/bundler/man/bundle-gem.1.ronn +150 -0
- data/lib/bundler/man/bundle-help.1 +9 -0
- data/lib/bundler/man/bundle-help.1.ronn +12 -0
- data/lib/bundler/man/bundle-info.1 +17 -0
- data/lib/bundler/man/bundle-info.1.ronn +21 -0
- data/lib/bundler/man/bundle-init.1 +20 -0
- data/lib/bundler/man/bundle-init.1.ronn +32 -0
- data/lib/bundler/man/bundle-install.1 +178 -0
- data/lib/bundler/man/bundle-install.1.ronn +314 -0
- data/lib/bundler/man/bundle-issue.1 +45 -0
- data/lib/bundler/man/bundle-issue.1.ronn +37 -0
- data/lib/bundler/man/bundle-licenses.1 +9 -0
- data/lib/bundler/man/bundle-licenses.1.ronn +10 -0
- data/lib/bundler/man/bundle-list.1 +40 -0
- data/lib/bundler/man/bundle-list.1.ronn +41 -0
- data/lib/bundler/man/bundle-lock.1 +75 -0
- data/lib/bundler/man/bundle-lock.1.ronn +115 -0
- data/lib/bundler/man/bundle-open.1 +32 -0
- data/lib/bundler/man/bundle-open.1.ronn +28 -0
- data/lib/bundler/man/bundle-outdated.1 +106 -0
- data/lib/bundler/man/bundle-outdated.1.ronn +117 -0
- data/lib/bundler/man/bundle-platform.1 +49 -0
- data/lib/bundler/man/bundle-platform.1.ronn +49 -0
- data/lib/bundler/man/bundle-plugin.1 +76 -0
- data/lib/bundler/man/bundle-plugin.1.ronn +84 -0
- data/lib/bundler/man/bundle-pristine.1 +23 -0
- data/lib/bundler/man/bundle-pristine.1.ronn +34 -0
- data/lib/bundler/man/bundle-remove.1 +15 -0
- data/lib/bundler/man/bundle-remove.1.ronn +16 -0
- data/lib/bundler/man/bundle-show.1 +16 -0
- data/lib/bundler/man/bundle-show.1.ronn +21 -0
- data/lib/bundler/man/bundle-update.1 +284 -0
- data/lib/bundler/man/bundle-update.1.ronn +367 -0
- data/lib/bundler/man/bundle-version.1 +22 -0
- data/lib/bundler/man/bundle-version.1.ronn +24 -0
- data/lib/bundler/man/bundle.1 +93 -0
- data/lib/bundler/man/bundle.1.ronn +107 -0
- data/lib/bundler/man/gemfile.5 +503 -0
- data/lib/bundler/man/gemfile.5.ronn +586 -0
- data/lib/bundler/man/index.txt +31 -0
- data/lib/bundler/match_metadata.rb +30 -0
- data/lib/bundler/match_platform.rb +42 -0
- data/lib/bundler/match_remote_metadata.rb +29 -0
- data/lib/bundler/materialization.rb +59 -0
- data/lib/bundler/mirror.rb +221 -0
- data/lib/bundler/plugin/api/source.rb +330 -0
- data/lib/bundler/plugin/api.rb +81 -0
- data/lib/bundler/plugin/dsl.rb +53 -0
- data/lib/bundler/plugin/events.rb +85 -0
- data/lib/bundler/plugin/index.rb +203 -0
- data/lib/bundler/plugin/installer/git.rb +34 -0
- data/lib/bundler/plugin/installer/path.rb +26 -0
- data/lib/bundler/plugin/installer/rubygems.rb +19 -0
- data/lib/bundler/plugin/installer.rb +123 -0
- data/lib/bundler/plugin/source_list.rb +31 -0
- data/lib/bundler/plugin/unloaded_source.rb +25 -0
- data/lib/bundler/plugin.rb +387 -0
- data/lib/bundler/process_lock.rb +20 -0
- data/lib/bundler/remote_specification.rb +126 -0
- data/lib/bundler/resolver/base.rb +127 -0
- data/lib/bundler/resolver/candidate.rb +85 -0
- data/lib/bundler/resolver/incompatibility.rb +15 -0
- data/lib/bundler/resolver/package.rb +95 -0
- data/lib/bundler/resolver/root.rb +25 -0
- data/lib/bundler/resolver/spec_group.rb +74 -0
- data/lib/bundler/resolver/strategy.rb +43 -0
- data/lib/bundler/resolver.rb +603 -0
- data/lib/bundler/retry.rb +92 -0
- data/lib/bundler/ruby_dsl.rb +67 -0
- data/lib/bundler/ruby_version.rb +135 -0
- data/lib/bundler/rubygems_ext.rb +503 -0
- data/lib/bundler/rubygems_gem_installer.rb +206 -0
- data/lib/bundler/rubygems_integration.rb +456 -0
- data/lib/bundler/runtime.rb +331 -0
- data/lib/bundler/safe_marshal.rb +31 -0
- data/lib/bundler/self_manager.rb +197 -0
- data/lib/bundler/settings/validator.rb +86 -0
- data/lib/bundler/settings.rb +585 -0
- data/lib/bundler/setup.rb +39 -0
- data/lib/bundler/shared_helpers.rb +392 -0
- data/lib/bundler/source/gemspec.rb +19 -0
- data/lib/bundler/source/git/git_proxy.rb +509 -0
- data/lib/bundler/source/git.rb +451 -0
- data/lib/bundler/source/metadata.rb +67 -0
- data/lib/bundler/source/path/installer.rb +53 -0
- data/lib/bundler/source/path.rb +256 -0
- data/lib/bundler/source/rubygems/remote.rb +86 -0
- data/lib/bundler/source/rubygems.rb +606 -0
- data/lib/bundler/source/rubygems_aggregate.rb +71 -0
- data/lib/bundler/source.rb +120 -0
- data/lib/bundler/source_list.rb +240 -0
- data/lib/bundler/source_map.rb +72 -0
- data/lib/bundler/spec_set.rb +390 -0
- data/lib/bundler/stub_specification.rb +147 -0
- data/lib/bundler/templates/.document +1 -0
- data/lib/bundler/templates/Executable +16 -0
- data/lib/bundler/templates/Executable.standalone +14 -0
- data/lib/bundler/templates/Gemfile +5 -0
- data/lib/bundler/templates/newgem/CHANGELOG.md.tt +5 -0
- data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +10 -0
- data/lib/bundler/templates/newgem/Cargo.toml.tt +13 -0
- data/lib/bundler/templates/newgem/Gemfile.tt +24 -0
- data/lib/bundler/templates/newgem/LICENSE.txt.tt +21 -0
- data/lib/bundler/templates/newgem/README.md.tt +49 -0
- data/lib/bundler/templates/newgem/Rakefile.tt +72 -0
- data/lib/bundler/templates/newgem/bin/console.tt +11 -0
- data/lib/bundler/templates/newgem/bin/setup.tt +8 -0
- data/lib/bundler/templates/newgem/circleci/config.yml.tt +37 -0
- data/lib/bundler/templates/newgem/exe/newgem.tt +3 -0
- data/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +22 -0
- data/lib/bundler/templates/newgem/ext/newgem/build.rs.tt +5 -0
- data/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +10 -0
- data/lib/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt +11 -0
- data/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
- data/lib/bundler/templates/newgem/ext/newgem/go.mod.tt +5 -0
- data/lib/bundler/templates/newgem/ext/newgem/newgem-go.c.tt +2 -0
- data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +9 -0
- data/lib/bundler/templates/newgem/ext/newgem/newgem.go.tt +31 -0
- data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +6 -0
- data/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +23 -0
- data/lib/bundler/templates/newgem/github/workflows/build-gems.yml.tt +69 -0
- data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +48 -0
- data/lib/bundler/templates/newgem/gitignore.tt +23 -0
- data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +27 -0
- data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +9 -0
- data/lib/bundler/templates/newgem/lib/newgem.rb.tt +15 -0
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +58 -0
- data/lib/bundler/templates/newgem/rspec.tt +3 -0
- data/lib/bundler/templates/newgem/rubocop.yml.tt +8 -0
- data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
- data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +19 -0
- data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +15 -0
- data/lib/bundler/templates/newgem/standard.yml.tt +3 -0
- data/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt +6 -0
- data/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +19 -0
- data/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt +15 -0
- data/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt +6 -0
- data/lib/bundler/ui/rg_proxy.rb +19 -0
- data/lib/bundler/ui/shell.rb +191 -0
- data/lib/bundler/ui/silent.rb +96 -0
- data/lib/bundler/ui.rb +9 -0
- data/lib/bundler/uri_credentials_filter.rb +43 -0
- data/lib/bundler/uri_normalizer.rb +23 -0
- data/lib/bundler/vendor/.document +1 -0
- data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +227 -0
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +3 -0
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +56 -0
- data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +230 -0
- data/lib/bundler/vendor/fileutils/COPYING +56 -0
- data/lib/bundler/vendor/fileutils/lib/fileutils.rb +2701 -0
- data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +41 -0
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +65 -0
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +80 -0
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1153 -0
- 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 +169 -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 +61 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb +42 -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 +423 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +236 -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/securerandom/COPYING +56 -0
- data/lib/bundler/vendor/securerandom/lib/securerandom.rb +102 -0
- data/lib/bundler/vendor/thor/LICENSE.md +20 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +105 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +61 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +108 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +143 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +407 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +130 -0
- data/lib/bundler/vendor/thor/lib/thor/actions.rb +340 -0
- data/lib/bundler/vendor/thor/lib/thor/base.rb +825 -0
- data/lib/bundler/vendor/thor/lib/thor/command.rb +151 -0
- data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +107 -0
- data/lib/bundler/vendor/thor/lib/thor/error.rb +106 -0
- data/lib/bundler/vendor/thor/lib/thor/group.rb +292 -0
- data/lib/bundler/vendor/thor/lib/thor/invocation.rb +178 -0
- data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +37 -0
- data/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
- data/lib/bundler/vendor/thor/lib/thor/line_editor.rb +17 -0
- data/lib/bundler/vendor/thor/lib/thor/nested_context.rb +29 -0
- data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +86 -0
- data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +195 -0
- data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +178 -0
- data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +294 -0
- data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
- data/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +72 -0
- data/lib/bundler/vendor/thor/lib/thor/runner.rb +335 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +384 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +112 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/column_printer.rb +29 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +81 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb +118 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/terminal.rb +42 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/wrapped_printer.rb +38 -0
- data/lib/bundler/vendor/thor/lib/thor/shell.rb +81 -0
- data/lib/bundler/vendor/thor/lib/thor/util.rb +285 -0
- data/lib/bundler/vendor/thor/lib/thor/version.rb +3 -0
- data/lib/bundler/vendor/thor/lib/thor.rb +674 -0
- data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
- data/lib/bundler/vendor/tsort/lib/tsort.rb +455 -0
- data/lib/bundler/vendor/uri/COPYING +56 -0
- data/lib/bundler/vendor/uri/lib/uri/common.rb +922 -0
- data/lib/bundler/vendor/uri/lib/uri/file.rb +100 -0
- data/lib/bundler/vendor/uri/lib/uri/ftp.rb +267 -0
- data/lib/bundler/vendor/uri/lib/uri/generic.rb +1592 -0
- data/lib/bundler/vendor/uri/lib/uri/http.rb +137 -0
- data/lib/bundler/vendor/uri/lib/uri/https.rb +23 -0
- data/lib/bundler/vendor/uri/lib/uri/ldap.rb +261 -0
- data/lib/bundler/vendor/uri/lib/uri/ldaps.rb +22 -0
- data/lib/bundler/vendor/uri/lib/uri/mailto.rb +293 -0
- data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +547 -0
- data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +206 -0
- data/lib/bundler/vendor/uri/lib/uri/version.rb +6 -0
- data/lib/bundler/vendor/uri/lib/uri/ws.rb +83 -0
- data/lib/bundler/vendor/uri/lib/uri/wss.rb +23 -0
- data/lib/bundler/vendor/uri/lib/uri.rb +104 -0
- data/lib/bundler/vendored_fileutils.rb +4 -0
- data/lib/bundler/vendored_net_http.rb +23 -0
- data/lib/bundler/vendored_persistent.rb +11 -0
- data/lib/bundler/vendored_pub_grub.rb +4 -0
- data/lib/bundler/vendored_securerandom.rb +12 -0
- data/lib/bundler/vendored_thor.rb +8 -0
- data/lib/bundler/vendored_timeout.rb +12 -0
- data/lib/bundler/vendored_tsort.rb +4 -0
- data/lib/bundler/vendored_uri.rb +21 -0
- data/lib/bundler/version.rb +21 -0
- data/lib/bundler/vlad.rb +4 -0
- data/lib/bundler/worker.rb +125 -0
- data/lib/bundler/yaml_serializer.rb +98 -0
- data/lib/bundler.rb +691 -0
- metadata +409 -0
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
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
|
+
#
|
|
9
|
+
class Resolver
|
|
10
|
+
require_relative "vendored_pub_grub"
|
|
11
|
+
require_relative "resolver/base"
|
|
12
|
+
require_relative "resolver/candidate"
|
|
13
|
+
require_relative "resolver/incompatibility"
|
|
14
|
+
require_relative "resolver/root"
|
|
15
|
+
require_relative "resolver/strategy"
|
|
16
|
+
|
|
17
|
+
def initialize(base, gem_version_promoter, most_specific_locked_platform = nil)
|
|
18
|
+
@source_requirements = base.source_requirements
|
|
19
|
+
@base = base
|
|
20
|
+
@gem_version_promoter = gem_version_promoter
|
|
21
|
+
@most_specific_locked_platform = most_specific_locked_platform
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def start
|
|
25
|
+
@requirements = @base.requirements
|
|
26
|
+
@packages = @base.packages
|
|
27
|
+
|
|
28
|
+
root, logger = setup_solver
|
|
29
|
+
|
|
30
|
+
Bundler.ui.info "Resolving dependencies...", true
|
|
31
|
+
|
|
32
|
+
solve_versions(root: root, logger: logger)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def setup_solver
|
|
36
|
+
root = Resolver::Root.new(name_for_explicit_dependency_source)
|
|
37
|
+
root_version = Resolver::Candidate.new(0)
|
|
38
|
+
|
|
39
|
+
@all_specs = Hash.new do |specs, name|
|
|
40
|
+
source = source_for(name)
|
|
41
|
+
matches = source.specs.search(name)
|
|
42
|
+
|
|
43
|
+
# Don't bother to check for circular deps when no dependency API are
|
|
44
|
+
# available, since it's too slow to be usable. That edge case won't work
|
|
45
|
+
# but resolution other than that should work fine and reasonably fast.
|
|
46
|
+
if source.respond_to?(:dependency_api_available?) && source.dependency_api_available?
|
|
47
|
+
matches = filter_invalid_self_dependencies(matches, name)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
specs[name] = matches.sort_by {|s| [s.version, s.platform.to_s] }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
@all_versions = Hash.new do |candidates, package|
|
|
54
|
+
candidates[package] = all_versions_for(package)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
@sorted_versions = Hash.new do |candidates, package|
|
|
58
|
+
candidates[package] = filtered_versions_for(package).sort
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
@sorted_versions[root] = [root_version]
|
|
62
|
+
|
|
63
|
+
root_dependencies = prepare_dependencies(@requirements, @packages)
|
|
64
|
+
|
|
65
|
+
@cached_dependencies = Hash.new do |dependencies, package|
|
|
66
|
+
dependencies[package] = Hash.new do |versions, version|
|
|
67
|
+
versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
@cached_dependencies[root] = { root_version => root_dependencies }
|
|
72
|
+
|
|
73
|
+
logger = Bundler::UI::Shell.new
|
|
74
|
+
logger.level = debug? ? "debug" : "warn"
|
|
75
|
+
|
|
76
|
+
[root, logger]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def solve_versions(root:, logger:)
|
|
80
|
+
solver = PubGrub::VersionSolver.new(source: self, root: root, strategy: Strategy.new(self), logger: logger)
|
|
81
|
+
result = solver.solve
|
|
82
|
+
resolved_specs = result.flat_map {|package, version| version.to_specs(package, @most_specific_locked_platform) }
|
|
83
|
+
SpecSet.new(resolved_specs).specs_with_additional_variants_from(@base.locked_specs)
|
|
84
|
+
rescue PubGrub::SolveFailure => e
|
|
85
|
+
incompatibility = e.incompatibility
|
|
86
|
+
|
|
87
|
+
names_to_unlock, names_to_allow_prereleases_for, names_to_allow_remote_specs_for, extended_explanation = find_names_to_relax(incompatibility)
|
|
88
|
+
|
|
89
|
+
names_to_relax = names_to_unlock + names_to_allow_prereleases_for + names_to_allow_remote_specs_for
|
|
90
|
+
|
|
91
|
+
if names_to_relax.any?
|
|
92
|
+
if names_to_unlock.any?
|
|
93
|
+
Bundler.ui.debug "Found conflicts with locked dependencies. Will retry with #{names_to_unlock.join(", ")} unlocked...", true
|
|
94
|
+
|
|
95
|
+
@base.unlock_names(names_to_unlock)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if names_to_allow_prereleases_for.any?
|
|
99
|
+
Bundler.ui.debug "Found conflicts with dependencies with prereleases. Will retry considering prereleases for #{names_to_allow_prereleases_for.join(", ")}...", true
|
|
100
|
+
|
|
101
|
+
@base.include_prereleases(names_to_allow_prereleases_for)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
if names_to_allow_remote_specs_for.any?
|
|
105
|
+
Bundler.ui.debug "Found conflicts with local versions of #{names_to_allow_remote_specs_for.join(", ")}. Will retry considering remote versions...", true
|
|
106
|
+
|
|
107
|
+
@base.include_remote_specs(names_to_allow_remote_specs_for)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
root, logger = setup_solver
|
|
111
|
+
|
|
112
|
+
Bundler.ui.debug "Retrying resolution...", true
|
|
113
|
+
retry
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
explanation = e.message
|
|
117
|
+
|
|
118
|
+
if extended_explanation
|
|
119
|
+
explanation << "\n\n"
|
|
120
|
+
explanation << extended_explanation
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
raise SolveFailure.new(explanation)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def find_names_to_relax(incompatibility)
|
|
127
|
+
names_to_unlock = []
|
|
128
|
+
names_to_allow_prereleases_for = []
|
|
129
|
+
names_to_allow_remote_specs_for = []
|
|
130
|
+
extended_explanation = nil
|
|
131
|
+
|
|
132
|
+
while incompatibility.conflict?
|
|
133
|
+
cause = incompatibility.cause
|
|
134
|
+
incompatibility = cause.incompatibility
|
|
135
|
+
|
|
136
|
+
incompatibility.terms.each do |term|
|
|
137
|
+
package = term.package
|
|
138
|
+
name = package.name
|
|
139
|
+
|
|
140
|
+
if base_requirements[name]
|
|
141
|
+
names_to_unlock << name
|
|
142
|
+
elsif package.ignores_prereleases? && @all_specs[name].any? {|s| s.version.prerelease? }
|
|
143
|
+
names_to_allow_prereleases_for << name
|
|
144
|
+
elsif package.prefer_local? && @all_specs[name].any? {|s| !s.is_a?(StubSpecification) }
|
|
145
|
+
names_to_allow_remote_specs_for << name
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
|
|
149
|
+
next unless no_versions_incompat
|
|
150
|
+
|
|
151
|
+
extended_explanation = no_versions_incompat.extended_explanation
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
[names_to_unlock.uniq, names_to_allow_prereleases_for.uniq, names_to_allow_remote_specs_for.uniq, extended_explanation]
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def parse_dependency(package, dependency)
|
|
159
|
+
range = if repository_for(package).is_a?(Source::Gemspec)
|
|
160
|
+
PubGrub::VersionRange.any
|
|
161
|
+
else
|
|
162
|
+
requirement_to_range(dependency)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
PubGrub::VersionConstraint.new(package, range: range)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def versions_for(package, range = VersionRange.any)
|
|
169
|
+
range.select_versions(@sorted_versions[package])
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def no_versions_incompatibility_for(package, unsatisfied_term)
|
|
173
|
+
cause = PubGrub::Incompatibility::NoVersions.new(unsatisfied_term)
|
|
174
|
+
name = package.name
|
|
175
|
+
constraint = unsatisfied_term.constraint
|
|
176
|
+
constraint_string = constraint.constraint_string
|
|
177
|
+
requirements = constraint_string.split(" OR ").map {|req| Gem::Requirement.new(req.split(",")) }
|
|
178
|
+
|
|
179
|
+
if name == "bundler" && bundler_pinned_to_current_version?
|
|
180
|
+
custom_explanation = "the current Bundler version (#{Bundler::VERSION}) does not satisfy #{constraint}"
|
|
181
|
+
extended_explanation = bundler_not_found_message(requirements)
|
|
182
|
+
else
|
|
183
|
+
specs_matching_other_platforms = filter_matching_specs(@all_specs[name], requirements)
|
|
184
|
+
|
|
185
|
+
platforms_explanation = specs_matching_other_platforms.any? ? " for any resolution platforms (#{package.platforms.join(", ")})" : ""
|
|
186
|
+
custom_explanation = "#{constraint} could not be found in #{repository_for(package)}#{platforms_explanation}"
|
|
187
|
+
if hint = cooldown_hint(specs_matching_other_platforms)
|
|
188
|
+
custom_explanation += " (#{hint})"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
label = "#{name} (#{constraint_string})"
|
|
192
|
+
extended_explanation = other_specs_matching_message(specs_matching_other_platforms, label) if specs_matching_other_platforms.any?
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
Incompatibility.new([unsatisfied_term], cause: cause, custom_explanation: custom_explanation, extended_explanation: extended_explanation)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def debug?
|
|
199
|
+
ENV["BUNDLER_DEBUG_RESOLVER"] ||
|
|
200
|
+
ENV["BUNDLER_DEBUG_RESOLVER_TREE"] ||
|
|
201
|
+
ENV["DEBUG_RESOLVER"] ||
|
|
202
|
+
ENV["DEBUG_RESOLVER_TREE"] ||
|
|
203
|
+
false
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def incompatibilities_for(package, version)
|
|
207
|
+
package_deps = @cached_dependencies[package]
|
|
208
|
+
sorted_versions = @sorted_versions[package]
|
|
209
|
+
package_deps[version].map do |dep_package, dep_constraint|
|
|
210
|
+
low = high = sorted_versions.index(version)
|
|
211
|
+
|
|
212
|
+
# find version low such that all >= low share the same dep
|
|
213
|
+
while low > 0 && package_deps[sorted_versions[low - 1]][dep_package] == dep_constraint
|
|
214
|
+
low -= 1
|
|
215
|
+
end
|
|
216
|
+
low =
|
|
217
|
+
if low == 0
|
|
218
|
+
nil
|
|
219
|
+
else
|
|
220
|
+
sorted_versions[low]
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# find version high such that all < high share the same dep
|
|
224
|
+
while high < sorted_versions.length && package_deps[sorted_versions[high]][dep_package] == dep_constraint
|
|
225
|
+
high += 1
|
|
226
|
+
end
|
|
227
|
+
high =
|
|
228
|
+
if high == sorted_versions.length
|
|
229
|
+
nil
|
|
230
|
+
else
|
|
231
|
+
sorted_versions[high]
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
range = PubGrub::VersionRange.new(min: low, max: high, include_min: !low.nil?)
|
|
235
|
+
|
|
236
|
+
self_constraint = PubGrub::VersionConstraint.new(package, range: range)
|
|
237
|
+
|
|
238
|
+
dep_term = PubGrub::Term.new(dep_constraint, false)
|
|
239
|
+
self_term = PubGrub::Term.new(self_constraint, true)
|
|
240
|
+
|
|
241
|
+
custom_explanation = if dep_package.meta? && package.root?
|
|
242
|
+
"current #{dep_package} version is #{dep_constraint.constraint_string}"
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
PubGrub::Incompatibility.new([self_term, dep_term], cause: :dependency, custom_explanation: custom_explanation)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def all_versions_for(package)
|
|
250
|
+
name = package.name
|
|
251
|
+
results = (@base[name] + filter_specs(@all_specs[name], package)).uniq {|spec| [spec.version.hash, spec.platform] }
|
|
252
|
+
|
|
253
|
+
if name == "bundler" && !bundler_pinned_to_current_version?
|
|
254
|
+
bundler_spec = Gem.loaded_specs["bundler"]
|
|
255
|
+
results << bundler_spec if bundler_spec
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
locked_requirement = base_requirements[name]
|
|
259
|
+
results = filter_matching_specs(results, locked_requirement) if locked_requirement
|
|
260
|
+
|
|
261
|
+
results.group_by(&:version).reduce([]) do |groups, (version, specs)|
|
|
262
|
+
platform_specs = package.platform_specs(specs)
|
|
263
|
+
|
|
264
|
+
# If package is a top-level dependency,
|
|
265
|
+
# candidate is only valid if there are matching versions for all resolution platforms.
|
|
266
|
+
#
|
|
267
|
+
# If package is not a top-level deependency,
|
|
268
|
+
# then it's not necessary that it has matching versions for all platforms, since it may have been introduced only as
|
|
269
|
+
# a dependency for a platform specific variant, so it will only need to have a valid version for that platform.
|
|
270
|
+
#
|
|
271
|
+
if package.top_level?
|
|
272
|
+
next groups if platform_specs.any?(&:empty?)
|
|
273
|
+
else
|
|
274
|
+
next groups if platform_specs.all?(&:empty?)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
ruby_specs = MatchPlatform.select_best_platform_match(specs, Gem::Platform::RUBY)
|
|
278
|
+
ruby_group = Resolver::SpecGroup.new(ruby_specs)
|
|
279
|
+
|
|
280
|
+
unless ruby_group.empty?
|
|
281
|
+
platform_specs.each do |s|
|
|
282
|
+
ruby_group.merge(Resolver::SpecGroup.new(s))
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
groups << Resolver::Candidate.new(version, group: ruby_group, priority: -1)
|
|
286
|
+
next groups if package.force_ruby_platform?
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
platform_group = Resolver::SpecGroup.new(platform_specs.flatten.uniq)
|
|
290
|
+
next groups if platform_group == ruby_group
|
|
291
|
+
|
|
292
|
+
groups << Resolver::Candidate.new(version, group: platform_group, priority: 1)
|
|
293
|
+
|
|
294
|
+
groups
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def source_for(name)
|
|
299
|
+
@source_requirements[name] || @source_requirements[:default]
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def default_bundler_source
|
|
303
|
+
@source_requirements[:default_bundler]
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def bundler_pinned_to_current_version?
|
|
307
|
+
!default_bundler_source.nil?
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def name_for_explicit_dependency_source
|
|
311
|
+
Bundler.default_gemfile.basename.to_s
|
|
312
|
+
rescue StandardError
|
|
313
|
+
"Gemfile"
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def raise_incomplete!(incomplete_specs)
|
|
317
|
+
raise_not_found!(@base.get_package(incomplete_specs.first.name))
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def sort_versions_by_preferred(package, versions)
|
|
321
|
+
@gem_version_promoter.sort_versions(package, versions)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
private
|
|
325
|
+
|
|
326
|
+
def raise_not_found!(package)
|
|
327
|
+
name = package.name
|
|
328
|
+
source = source_for(name)
|
|
329
|
+
specs = @all_specs[name]
|
|
330
|
+
matching_part = name
|
|
331
|
+
requirement_label = SharedHelpers.pretty_dependency(package.dependency)
|
|
332
|
+
cache_message = begin
|
|
333
|
+
" or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
|
|
334
|
+
rescue GemfileNotFound
|
|
335
|
+
nil
|
|
336
|
+
end
|
|
337
|
+
specs_matching_requirement = filter_matching_specs(specs, package.dependency.requirement)
|
|
338
|
+
|
|
339
|
+
not_found_message = if specs_matching_requirement.any?
|
|
340
|
+
specs = specs_matching_requirement
|
|
341
|
+
matching_part = requirement_label
|
|
342
|
+
platforms = package.platforms
|
|
343
|
+
|
|
344
|
+
if platforms.size == 1
|
|
345
|
+
"Could not find gem '#{requirement_label}' with platform '#{platforms.first}'"
|
|
346
|
+
else
|
|
347
|
+
"Could not find gems matching '#{requirement_label}' valid for all resolution platforms (#{platforms.join(", ")})"
|
|
348
|
+
end
|
|
349
|
+
else
|
|
350
|
+
"Could not find gem '#{requirement_label}'"
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
message = String.new("#{not_found_message} in #{source}#{cache_message}.\n")
|
|
354
|
+
|
|
355
|
+
if specs.any?
|
|
356
|
+
message << "\n#{other_specs_matching_message(specs, matching_part)}"
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
if hint = cooldown_hint(specs_matching_requirement)
|
|
360
|
+
message << "\n\n#{hint}."
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
if specs_matching_requirement.any? && (hint = platform_mismatch_hint)
|
|
364
|
+
message << "\n\n#{hint}"
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
raise GemNotFound, message
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def platform_mismatch_hint
|
|
371
|
+
locked_platforms = Bundler.locked_gems&.platforms
|
|
372
|
+
return unless locked_platforms
|
|
373
|
+
|
|
374
|
+
local_platform = Bundler.local_platform
|
|
375
|
+
return if locked_platforms.include?(local_platform)
|
|
376
|
+
return if locked_platforms.any? {|p| p == Gem::Platform::RUBY }
|
|
377
|
+
|
|
378
|
+
"Your current platform (#{local_platform}) is not included in the lockfile's platforms (#{locked_platforms.join(", ")}). " \
|
|
379
|
+
"Add the current platform to the lockfile with\n`bundle lock --add-platform #{local_platform}` and try again."
|
|
380
|
+
rescue GemfileNotFound
|
|
381
|
+
nil
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def filtered_versions_for(package)
|
|
385
|
+
@gem_version_promoter.filter_versions(package, @all_versions[package])
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def raise_all_versions_filtered_out!(package)
|
|
389
|
+
level = @gem_version_promoter.level
|
|
390
|
+
name = package.name
|
|
391
|
+
locked_version = package.locked_version
|
|
392
|
+
requirement = package.dependency
|
|
393
|
+
|
|
394
|
+
raise GemNotFound,
|
|
395
|
+
"#{name} is locked to #{locked_version}, while Gemfile is requesting #{requirement}. " \
|
|
396
|
+
"--strict --#{level} was specified, but there are no #{level} level upgrades from #{locked_version} satisfying #{requirement}, so version solving has failed"
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
def filter_matching_specs(specs, requirements)
|
|
400
|
+
Array(requirements).flat_map do |requirement|
|
|
401
|
+
specs.select {| spec| requirement_satisfied_by?(requirement, spec) }
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def filter_specs(specs, package)
|
|
406
|
+
filter_remote_specs(filter_cooldown(filter_prereleases(specs, package)), package)
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def filter_prereleases(specs, package)
|
|
410
|
+
return specs unless package.ignores_prereleases? && specs.size > 1
|
|
411
|
+
|
|
412
|
+
specs.reject {|s| s.version.prerelease? }
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def filter_cooldown(specs)
|
|
416
|
+
return specs if specs.empty?
|
|
417
|
+
excluded_versions = cooldown_excluded_versions(specs)
|
|
418
|
+
return specs if excluded_versions.empty?
|
|
419
|
+
specs.reject {|s| excluded_versions.include?([s.name, s.version]) }
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def cooldown_excluded_versions(specs)
|
|
423
|
+
excluded = {}
|
|
424
|
+
specs.each do |spec|
|
|
425
|
+
next unless cooldown_excluded?(spec)
|
|
426
|
+
excluded[[spec.name, spec.version]] = true
|
|
427
|
+
end
|
|
428
|
+
excluded
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def cooldown_hint(specs)
|
|
432
|
+
excluded_versions = cooldown_excluded_versions(specs)
|
|
433
|
+
return nil if excluded_versions.empty?
|
|
434
|
+
"#{excluded_versions.size} version#{"s" if excluded_versions.size > 1} excluded by the cooldown setting; pass `--cooldown 0` to bypass"
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
def cooldown_excluded?(spec)
|
|
438
|
+
return false unless spec.respond_to?(:created_at) && spec.created_at
|
|
439
|
+
return false unless spec.respond_to?(:remote) && spec.remote
|
|
440
|
+
return false if locked_by_lockfile?(spec)
|
|
441
|
+
days = spec.remote.effective_cooldown
|
|
442
|
+
return false if days.nil? || days <= 0
|
|
443
|
+
(cooldown_now - spec.created_at) < (days * 86_400)
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# A version already written to the lockfile has been adopted, and cooldown
|
|
447
|
+
# only governs the adoption of *new* versions, so it must never retract one
|
|
448
|
+
# the lockfile already pins. Keying this off the locked specs rather than the
|
|
449
|
+
# prevent-downgrade floor matters because that floor is absent on resolutions
|
|
450
|
+
# that re-pick a gem from scratch: the auxiliary full update run to compute
|
|
451
|
+
# `--update` targets, and the from-scratch retries after a conflict unlocks a
|
|
452
|
+
# gem. In those passes the locked version is the only candidate, so filtering
|
|
453
|
+
# it out makes an unrelated operation impossible whenever every published
|
|
454
|
+
# version matching the requirement sits inside the cooldown window.
|
|
455
|
+
#
|
|
456
|
+
# Gems named on a `bundle update GEM` command are the exception: the user
|
|
457
|
+
# asked to move them, so they stay subject to cooldown and a locked-but-fresh
|
|
458
|
+
# release is pushed back to an older one (or fails loudly when none exists).
|
|
459
|
+
def locked_by_lockfile?(spec)
|
|
460
|
+
return false unless defined?(@base) && @base
|
|
461
|
+
return false if @base.explicitly_unlocked?(spec.name)
|
|
462
|
+
@base.locked_specs[spec.name].any? {|locked| locked.version == spec.version }
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def cooldown_now
|
|
466
|
+
@cooldown_now ||= Time.now
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def filter_remote_specs(specs, package)
|
|
470
|
+
if package.prefer_local?
|
|
471
|
+
local_specs = specs.select {|s| s.is_a?(StubSpecification) }
|
|
472
|
+
|
|
473
|
+
if local_specs.empty?
|
|
474
|
+
package.consider_remote_versions!
|
|
475
|
+
specs
|
|
476
|
+
else
|
|
477
|
+
local_specs
|
|
478
|
+
end
|
|
479
|
+
else
|
|
480
|
+
specs
|
|
481
|
+
end
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
# Ignore versions that depend on themselves incorrectly
|
|
485
|
+
def filter_invalid_self_dependencies(specs, name)
|
|
486
|
+
specs.reject do |s|
|
|
487
|
+
s.dependencies.any? {|d| d.name == name && !d.requirement.satisfied_by?(s.version) }
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def requirement_satisfied_by?(requirement, spec)
|
|
492
|
+
requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
def repository_for(package)
|
|
496
|
+
source_for(package.name)
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
def base_requirements
|
|
500
|
+
@base.base_requirements
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
def prepare_dependencies(requirements, packages)
|
|
504
|
+
to_dependency_hash(requirements, packages).filter_map do |dep_package, dep_constraint|
|
|
505
|
+
name = dep_package.name
|
|
506
|
+
|
|
507
|
+
next [dep_package, dep_constraint] if name == "bundler"
|
|
508
|
+
|
|
509
|
+
dep_range = dep_constraint.range
|
|
510
|
+
versions = versions_for(dep_package, dep_range)
|
|
511
|
+
if versions.empty?
|
|
512
|
+
if dep_package.ignores_prereleases? || dep_package.prefer_local?
|
|
513
|
+
@all_versions.delete(dep_package)
|
|
514
|
+
@sorted_versions.delete(dep_package)
|
|
515
|
+
end
|
|
516
|
+
dep_package.consider_prereleases! if dep_package.ignores_prereleases?
|
|
517
|
+
dep_package.consider_remote_versions! if dep_package.prefer_local?
|
|
518
|
+
versions = versions_for(dep_package, dep_range)
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
if versions.empty? && select_all_versions(dep_package, dep_range).any?
|
|
522
|
+
raise_all_versions_filtered_out!(dep_package)
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
next [dep_package, dep_constraint] unless versions.empty?
|
|
526
|
+
|
|
527
|
+
next unless dep_package.current_platform?
|
|
528
|
+
|
|
529
|
+
raise_not_found!(dep_package)
|
|
530
|
+
end.to_h
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
def select_all_versions(package, range)
|
|
534
|
+
range.select_versions(@all_versions[package])
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def other_specs_matching_message(specs, requirement)
|
|
538
|
+
message = String.new("The source contains the following gems matching '#{requirement}':\n")
|
|
539
|
+
message << specs.map {|s| " * #{s.full_name}" }.join("\n")
|
|
540
|
+
message
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
def requirement_to_range(requirement)
|
|
544
|
+
ranges = requirement.requirements.map do |(op, version)|
|
|
545
|
+
ver = Resolver::Candidate.new(version, priority: -1)
|
|
546
|
+
platform_ver = Resolver::Candidate.new(version, priority: 1)
|
|
547
|
+
|
|
548
|
+
case op
|
|
549
|
+
when "~>"
|
|
550
|
+
name = "~> #{ver}"
|
|
551
|
+
bump = Resolver::Candidate.new(version.bump.to_s + ".A")
|
|
552
|
+
PubGrub::VersionRange.new(name: name, min: ver, max: bump, include_min: true)
|
|
553
|
+
when ">"
|
|
554
|
+
PubGrub::VersionRange.new(min: platform_ver)
|
|
555
|
+
when ">="
|
|
556
|
+
PubGrub::VersionRange.new(min: ver, include_min: true)
|
|
557
|
+
when "<"
|
|
558
|
+
PubGrub::VersionRange.new(max: ver)
|
|
559
|
+
when "<="
|
|
560
|
+
PubGrub::VersionRange.new(max: platform_ver, include_max: true)
|
|
561
|
+
when "="
|
|
562
|
+
PubGrub::VersionRange.new(min: ver, max: platform_ver, include_min: true, include_max: true)
|
|
563
|
+
when "!="
|
|
564
|
+
PubGrub::VersionRange.new(min: ver, max: platform_ver, include_min: true, include_max: true).invert
|
|
565
|
+
else
|
|
566
|
+
raise "bad version specifier: #{op}"
|
|
567
|
+
end
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
ranges.inject(&:intersect)
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
def to_dependency_hash(dependencies, packages)
|
|
574
|
+
dependencies.inject({}) do |deps, dep|
|
|
575
|
+
package = packages[dep.name]
|
|
576
|
+
|
|
577
|
+
current_req = deps[package]
|
|
578
|
+
new_req = parse_dependency(package, dep.requirement)
|
|
579
|
+
|
|
580
|
+
deps[package] = if current_req
|
|
581
|
+
current_req.intersect(new_req)
|
|
582
|
+
else
|
|
583
|
+
new_req
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
deps
|
|
587
|
+
end
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
def bundler_not_found_message(conflict_dependencies)
|
|
591
|
+
candidate_specs = filter_matching_specs(default_bundler_source.specs.search("bundler"), conflict_dependencies)
|
|
592
|
+
|
|
593
|
+
if candidate_specs.any?
|
|
594
|
+
target_version = candidate_specs.last.version
|
|
595
|
+
new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ")
|
|
596
|
+
"Your bundle requires a different version of Bundler than the one you're running.\n" \
|
|
597
|
+
"Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n"
|
|
598
|
+
else
|
|
599
|
+
"Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
|
|
600
|
+
end
|
|
601
|
+
end
|
|
602
|
+
end
|
|
603
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Bundler
|
|
4
|
+
# General purpose class for retrying code that may fail
|
|
5
|
+
class Retry
|
|
6
|
+
attr_accessor :name, :total_runs, :current_run
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
attr_accessor :default_base_delay
|
|
10
|
+
|
|
11
|
+
def default_attempts
|
|
12
|
+
default_retries + 1
|
|
13
|
+
end
|
|
14
|
+
alias_method :attempts, :default_attempts
|
|
15
|
+
|
|
16
|
+
def default_retries
|
|
17
|
+
Bundler.settings[:retry]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Set default base delay for exponential backoff
|
|
22
|
+
self.default_base_delay = 1.0
|
|
23
|
+
|
|
24
|
+
def initialize(name, exceptions = nil, retries = self.class.default_retries, opts = {})
|
|
25
|
+
@name = name
|
|
26
|
+
@retries = retries
|
|
27
|
+
@exceptions = Array(exceptions) || []
|
|
28
|
+
@total_runs = @retries + 1 # will run once, then upto attempts.times
|
|
29
|
+
@base_delay = opts[:base_delay] || self.class.default_base_delay
|
|
30
|
+
@max_delay = opts[:max_delay] || 60.0
|
|
31
|
+
@jitter = opts[:jitter] || 0.5
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def attempt(&block)
|
|
35
|
+
@current_run = 0
|
|
36
|
+
@failed = false
|
|
37
|
+
@error = nil
|
|
38
|
+
run(&block) while keep_trying?
|
|
39
|
+
@result
|
|
40
|
+
end
|
|
41
|
+
alias_method :attempts, :attempt
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def run(&block)
|
|
46
|
+
@failed = false
|
|
47
|
+
@current_run += 1
|
|
48
|
+
@result = block.call
|
|
49
|
+
rescue StandardError => e
|
|
50
|
+
fail_attempt(e)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def fail_attempt(e)
|
|
54
|
+
@failed = true
|
|
55
|
+
if last_attempt? || @exceptions.any? {|k| e.is_a?(k) }
|
|
56
|
+
Bundler.ui.info "" unless Bundler.ui.debug?
|
|
57
|
+
raise e
|
|
58
|
+
end
|
|
59
|
+
if name
|
|
60
|
+
Bundler.ui.info "" unless Bundler.ui.debug? # Add new line in case dots preceded this
|
|
61
|
+
Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", true
|
|
62
|
+
end
|
|
63
|
+
backoff_sleep if @base_delay > 0
|
|
64
|
+
true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def backoff_sleep
|
|
68
|
+
# Exponential backoff: delay = base_delay * 2^(attempt - 1)
|
|
69
|
+
# Add jitter to prevent thundering herd: random value between 0 and jitter seconds
|
|
70
|
+
delay = @base_delay * (2**(@current_run - 1))
|
|
71
|
+
delay = [@max_delay, delay].min
|
|
72
|
+
jitter_amount = rand * @jitter
|
|
73
|
+
total_delay = delay + jitter_amount
|
|
74
|
+
Bundler.ui.debug "Sleeping for #{total_delay.round(2)} seconds before retry"
|
|
75
|
+
sleep(total_delay)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def sleep(duration)
|
|
79
|
+
Kernel.sleep(duration)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def keep_trying?
|
|
83
|
+
return true if current_run.zero?
|
|
84
|
+
return false if last_attempt?
|
|
85
|
+
true if @failed
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def last_attempt?
|
|
89
|
+
current_run >= total_runs
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|