rubygems-update 4.0.21 → 4.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +590 -53
- data/CONTRIBUTING.md +66 -5
- data/MIT.txt +4 -3
- data/Manifest.txt +332 -375
- data/README.md +26 -6
- data/bundler.gemspec +63 -0
- data/doc/POLICIES.md +147 -0
- data/doc/UPGRADING.md +4 -4
- data/{bundler/lib → lib}/bundler/build_metadata.rb +2 -2
- data/{bundler/lib → lib}/bundler/checksum.rb +40 -25
- data/{bundler/lib → lib}/bundler/ci_detector.rb +1 -1
- data/{bundler/lib → lib}/bundler/cli/add.rb +3 -4
- data/{bundler/lib → lib}/bundler/cli/cache.rb +4 -0
- data/{bundler/lib → lib}/bundler/cli/clean.rb +5 -0
- data/{bundler/lib → lib}/bundler/cli/common.rb +37 -1
- data/{bundler/lib → lib}/bundler/cli/config.rb +4 -2
- data/{bundler/lib → lib}/bundler/cli/gem.rb +0 -17
- data/{bundler/lib → lib}/bundler/cli/install.rb +4 -5
- data/{bundler/lib → lib}/bundler/cli/lock.rb +1 -2
- data/{bundler/lib → lib}/bundler/cli/outdated.rb +8 -3
- data/{bundler/lib → lib}/bundler/cli/pristine.rb +2 -1
- data/{bundler/lib → lib}/bundler/cli/update.rb +21 -12
- data/{bundler/lib → lib}/bundler/cli.rb +14 -11
- data/{bundler/lib → lib}/bundler/definition.rb +61 -24
- data/{bundler/lib → lib}/bundler/dependency.rb +4 -0
- data/{bundler/lib → lib}/bundler/dsl.rb +77 -11
- data/{bundler/lib → lib}/bundler/endpoint_specification.rb +51 -14
- data/{bundler/lib → lib}/bundler/env.rb +7 -24
- data/{bundler/lib → lib}/bundler/errors.rb +34 -5
- data/{bundler/lib → lib}/bundler/fetcher/compact_index.rb +14 -5
- data/lib/bundler/fetcher/connection_pools.rb +150 -0
- data/{bundler/lib → lib}/bundler/fetcher/downloader.rb +31 -16
- data/{bundler/lib → lib}/bundler/fetcher.rb +8 -47
- data/{bundler/lib → lib}/bundler/injector.rb +3 -3
- data/{bundler/lib → lib}/bundler/inline.rb +44 -4
- data/{bundler/lib → lib}/bundler/installer/parallel_installer.rb +25 -30
- data/{bundler/lib → lib}/bundler/installer.rb +20 -6
- data/{bundler/lib → lib}/bundler/lazy_specification.rb +44 -17
- data/{bundler/lib → lib}/bundler/lockfile_generator.rb +24 -2
- data/{bundler/lib → lib}/bundler/lockfile_parser.rb +43 -5
- data/{bundler/lib → lib}/bundler/man/bundle-add.1 +7 -4
- data/{bundler/lib → lib}/bundler/man/bundle-add.1.ronn +8 -4
- data/{bundler/lib → lib}/bundler/man/bundle-binstubs.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-cache.1 +2 -2
- data/{bundler/lib → lib}/bundler/man/bundle-cache.1.ronn +2 -2
- data/{bundler/lib → lib}/bundler/man/bundle-check.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-clean.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-config.1 +38 -6
- data/{bundler/lib → lib}/bundler/man/bundle-config.1.ronn +143 -10
- data/{bundler/lib → lib}/bundler/man/bundle-console.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-doctor.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-env.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-exec.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-fund.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-gem.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-help.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-info.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-init.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-install.1 +2 -2
- data/{bundler/lib → lib}/bundler/man/bundle-install.1.ronn +4 -4
- data/{bundler/lib → lib}/bundler/man/bundle-issue.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-licenses.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-list.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-lock.1 +3 -3
- data/{bundler/lib → lib}/bundler/man/bundle-lock.1.ronn +5 -5
- data/{bundler/lib → lib}/bundler/man/bundle-open.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-outdated.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-platform.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-plugin.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-pristine.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-remove.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-show.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle-update.1 +3 -3
- data/{bundler/lib → lib}/bundler/man/bundle-update.1.ronn +3 -5
- data/{bundler/lib → lib}/bundler/man/bundle-version.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/bundle.1 +1 -1
- data/{bundler/lib → lib}/bundler/man/gemfile.5 +45 -1
- data/{bundler/lib → lib}/bundler/man/gemfile.5.ronn +53 -0
- data/lib/bundler/match_metadata.rb +50 -0
- data/{bundler/lib → lib}/bundler/match_platform.rb +25 -2
- data/lib/bundler/match_remote_metadata.rb +44 -0
- data/{bundler/lib → lib}/bundler/materialization.rb +2 -1
- data/lib/bundler/override.rb +69 -0
- data/{bundler/lib → lib}/bundler/plugin/dsl.rb +3 -5
- data/{bundler/lib → lib}/bundler/plugin/events.rb +55 -13
- data/{bundler/lib → lib}/bundler/plugin/index.rb +87 -11
- data/{bundler/lib → lib}/bundler/plugin/installer/path.rb +1 -1
- data/{bundler/lib → lib}/bundler/plugin/installer.rb +13 -5
- data/{bundler/lib → lib}/bundler/plugin.rb +58 -30
- data/{bundler/lib → lib}/bundler/remote_specification.rb +6 -3
- data/{bundler/lib → lib}/bundler/resolver/base.rb +2 -1
- data/{bundler/lib → lib}/bundler/resolver/incompatibility.rb +1 -1
- data/{bundler/lib → lib}/bundler/resolver.rb +73 -23
- data/{bundler/lib → lib}/bundler/ruby_version.rb +0 -2
- data/{bundler/lib → lib}/bundler/rubygems_ext.rb +71 -1
- data/{bundler/lib → lib}/bundler/rubygems_gem_installer.rb +41 -2
- data/{bundler/lib → lib}/bundler/rubygems_integration.rb +7 -2
- data/{bundler/lib → lib}/bundler/runtime.rb +69 -2
- data/{bundler/lib → lib}/bundler/self_manager.rb +9 -15
- data/{bundler/lib → lib}/bundler/settings.rb +373 -30
- data/{bundler/lib → lib}/bundler/shared_helpers.rb +2 -1
- data/{bundler/lib → lib}/bundler/source/git/git_proxy.rb +2 -10
- data/{bundler/lib → lib}/bundler/source/git.rb +15 -6
- data/{bundler/lib → lib}/bundler/source/path/installer.rb +1 -1
- data/{bundler/lib → lib}/bundler/source/rubygems/remote.rb +10 -5
- data/{bundler/lib → lib}/bundler/source/rubygems.rb +48 -12
- data/{bundler/lib → lib}/bundler/spec_set.rb +16 -4
- data/{bundler/lib → lib}/bundler/stub_specification.rb +2 -1
- data/{bundler/lib → lib}/bundler/templates/newgem/Gemfile.tt +4 -4
- data/{bundler/lib → lib}/bundler/templates/newgem/newgem.gemspec.tt +3 -3
- data/{bundler/lib → lib}/bundler/templates/newgem/spec/newgem_spec.rb.tt +1 -1
- data/{bundler/lib → lib}/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +1 -1
- data/{bundler/lib → lib}/bundler/ui/shell.rb +0 -4
- data/{bundler/lib → lib}/bundler/ui/silent.rb +0 -4
- data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +35 -2
- data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/base.rb +2 -1
- data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/basic.rb +14 -6
- data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/color.rb +2 -0
- data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/version.rb +1 -1
- data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor.rb +34 -1
- data/lib/bundler/vendored_pub_grub.rb +7 -0
- data/lib/bundler/vendored_securerandom.rb +15 -0
- data/lib/bundler/vendored_uri.rb +21 -0
- data/{bundler/lib → lib}/bundler/version.rb +1 -1
- data/{bundler/lib → lib}/bundler/worker.rb +3 -2
- data/{bundler/lib → lib}/bundler.rb +1 -1
- data/lib/rubygems/basic_specification.rb +15 -14
- data/lib/rubygems/bundler_settings.rb +137 -0
- data/lib/rubygems/bundler_version_finder.rb +13 -55
- data/lib/rubygems/ci_detector.rb +1 -1
- data/lib/rubygems/commands/build_command.rb +8 -1
- data/lib/rubygems/commands/cert_command.rb +9 -7
- data/lib/rubygems/commands/contents_command.rb +1 -1
- data/lib/rubygems/commands/dependency_command.rb +15 -3
- data/lib/rubygems/commands/environment_command.rb +1 -0
- data/lib/rubygems/commands/exec_command.rb +3 -0
- data/lib/rubygems/commands/fetch_command.rb +1 -1
- data/lib/rubygems/commands/help_command.rb +3 -1
- data/lib/rubygems/commands/install_command.rb +13 -3
- data/lib/rubygems/commands/lock_command.rb +2 -2
- data/lib/rubygems/commands/outdated_command.rb +77 -2
- data/lib/rubygems/commands/owner_command.rb +1 -1
- data/lib/rubygems/commands/push_command.rb +159 -21
- data/lib/rubygems/commands/setup_command.rb +20 -23
- data/lib/rubygems/commands/signin_command.rb +3 -1
- data/lib/rubygems/commands/signout_command.rb +26 -6
- data/lib/rubygems/commands/specification_command.rb +1 -1
- data/lib/rubygems/commands/uninstall_command.rb +1 -1
- data/lib/rubygems/commands/update_command.rb +84 -2
- data/lib/rubygems/commands/yank_command.rb +10 -7
- data/lib/rubygems/compact_index_client/cache.rb +122 -0
- data/lib/rubygems/compact_index_client/cache_file.rb +147 -0
- data/lib/rubygems/compact_index_client/http_fetcher.rb +88 -0
- data/lib/rubygems/compact_index_client/parser.rb +90 -0
- data/lib/rubygems/compact_index_client/updater.rb +113 -0
- data/lib/rubygems/compact_index_client.rb +111 -0
- data/lib/rubygems/config_file.rb +304 -22
- data/lib/rubygems/content_address.rb +194 -0
- data/lib/rubygems/cooldown.rb +173 -0
- data/lib/rubygems/cooldown_option.rb +27 -0
- data/lib/rubygems/cooldown_settings.rb +57 -0
- data/lib/rubygems/credential_store/native/linux.rb +97 -0
- data/lib/rubygems/credential_store/native/macos.rb +88 -0
- data/lib/rubygems/credential_store/native/windows.rb +130 -0
- data/lib/rubygems/credential_store.rb +332 -0
- data/lib/rubygems/defaults.rb +9 -0
- data/lib/rubygems/dependency_installer.rb +15 -0
- data/lib/rubygems/doctor.rb +23 -6
- data/lib/rubygems/exceptions.rb +11 -43
- data/lib/rubygems/ext/builder.rb +70 -5
- data/lib/rubygems/ext/cargo_builder.rb +0 -9
- data/lib/rubygems/ext/ext_conf_builder.rb +8 -15
- data/lib/rubygems/gemcutter_utilities.rb +44 -2
- data/lib/rubygems/install_update_options.rb +16 -0
- data/lib/rubygems/installer.rb +90 -11
- data/lib/rubygems/installer_uninstaller_utils.rb +24 -3
- data/lib/rubygems/name_tuple.rb +55 -18
- data/lib/rubygems/package/old.rb +1 -1
- data/lib/rubygems/package.rb +200 -47
- data/lib/rubygems/package_task.rb +2 -2
- data/lib/rubygems/platform.rb +2 -2
- data/lib/rubygems/query_utils.rb +84 -24
- data/lib/rubygems/remote_fetcher.rb +65 -17
- data/lib/rubygems/request/connection_pools.rb +3 -0
- data/lib/rubygems/request_set/gem_dependency_api.rb +1 -1
- data/lib/rubygems/request_set/lockfile.rb +0 -2
- data/lib/rubygems/request_set.rb +105 -17
- data/lib/rubygems/resolver/api_set.rb +14 -26
- data/lib/rubygems/resolver/api_specification.rb +56 -15
- data/lib/rubygems/resolver/incompatibility.rb +10 -0
- data/lib/rubygems/resolver/index_specification.rb +6 -4
- data/lib/rubygems/resolver/installer_set.rb +2 -2
- data/lib/rubygems/resolver/lock_specification.rb +5 -1
- data/lib/rubygems/resolver/spec_specification.rb +4 -0
- data/lib/rubygems/resolver/specification.rb +16 -1
- data/lib/rubygems/resolver/strategy.rb +44 -0
- data/lib/rubygems/resolver.rb +471 -145
- data/lib/rubygems/safe_marshal.rb +2 -1
- data/lib/rubygems/safe_yaml.rb +20 -3
- data/lib/rubygems/security/policy.rb +11 -3
- data/lib/rubygems/security/signer.rb +15 -7
- data/lib/rubygems/security.rb +111 -17
- data/lib/rubygems/source/local.rb +7 -2
- data/lib/rubygems/source.rb +270 -23
- data/lib/rubygems/spec_fetcher.rb +47 -12
- data/lib/rubygems/specification.rb +76 -32
- data/lib/rubygems/specification_policy.rb +33 -6
- data/lib/rubygems/specification_record.rb +41 -2
- data/lib/rubygems/stub_specification.rb +39 -16
- data/lib/rubygems/uninstaller.rb +2 -0
- data/lib/rubygems/util/atomic_file_writer.rb +109 -0
- data/lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb +2 -1
- data/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb +5 -6
- data/lib/rubygems/vendor/net-http/lib/net/http/header.rb +8 -4
- data/lib/rubygems/vendor/net-http/lib/net/http/requests.rb +15 -1
- data/lib/rubygems/vendor/net-http/lib/net/http/response.rb +2 -1
- data/lib/rubygems/vendor/net-http/lib/net/http/responses.rb +68 -0
- data/lib/rubygems/vendor/net-http/lib/net/http.rb +60 -49
- data/lib/rubygems/vendor/optparse/lib/optparse.rb +23 -30
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/assignment.rb +1 -1
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +7 -7
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/failure_writer.rb +1 -1
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/incompatibility.rb +4 -4
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/package.rb +1 -1
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/partial_solution.rb +1 -1
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/rubygems.rb +3 -3
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/solve_failure.rb +1 -1
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/static_package_source.rb +3 -3
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/strategy.rb +2 -2
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/term.rb +1 -1
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version.rb +1 -1
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version_constraint.rb +3 -3
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version_range.rb +1 -1
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version_solver.rb +2 -2
- data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version_union.rb +1 -1
- data/lib/rubygems/vendor/pub_grub/lib/pub_grub.rb +57 -0
- data/lib/rubygems/vendor/resolv/lib/resolv.rb +3508 -0
- data/lib/rubygems/vendor/securerandom/lib/securerandom.rb +4 -0
- data/lib/rubygems/vendor/timeout/lib/timeout.rb +190 -77
- data/lib/rubygems/vendor/uri/lib/uri.rb +4 -0
- data/{bundler/lib/bundler → lib/rubygems}/vendored_pub_grub.rb +0 -1
- data/lib/rubygems/version.rb +129 -111
- data/lib/rubygems/version_option.rb +14 -0
- data/lib/rubygems/yaml_serializer.rb +853 -71
- data/lib/rubygems.rb +45 -11
- data/rubygems-update.gemspec +3 -4
- data/setup.rb +1 -0
- metadata +365 -410
- data/bundler/CHANGELOG.md +0 -5784
- data/bundler/LICENSE.md +0 -22
- data/bundler/README.md +0 -58
- data/bundler/bundler.gemspec +0 -46
- data/bundler/lib/bundler/compact_index_client/cache.rb +0 -107
- data/bundler/lib/bundler/compact_index_client/cache_file.rb +0 -148
- data/bundler/lib/bundler/compact_index_client/parser.rb +0 -87
- data/bundler/lib/bundler/compact_index_client/updater.rb +0 -105
- data/bundler/lib/bundler/compact_index_client.rb +0 -92
- data/bundler/lib/bundler/match_metadata.rb +0 -30
- data/bundler/lib/bundler/match_remote_metadata.rb +0 -29
- data/bundler/lib/bundler/vendor/connection_pool/LICENSE +0 -20
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +0 -227
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +0 -3
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -56
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +0 -230
- data/bundler/lib/bundler/vendor/net-http-persistent/README.rdoc +0 -82
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +0 -41
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +0 -65
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +0 -80
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +0 -1153
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +0 -31
- data/bundler/lib/bundler/vendor/securerandom/lib/securerandom.rb +0 -102
- data/bundler/lib/bundler/vendor/uri/COPYING +0 -56
- data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +0 -922
- data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +0 -100
- data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -267
- data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +0 -1592
- data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +0 -137
- data/bundler/lib/bundler/vendor/uri/lib/uri/https.rb +0 -23
- data/bundler/lib/bundler/vendor/uri/lib/uri/ldap.rb +0 -261
- data/bundler/lib/bundler/vendor/uri/lib/uri/ldaps.rb +0 -22
- data/bundler/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -293
- data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +0 -547
- data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +0 -206
- data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +0 -6
- data/bundler/lib/bundler/vendor/uri/lib/uri/ws.rb +0 -83
- data/bundler/lib/bundler/vendor/uri/lib/uri/wss.rb +0 -23
- data/bundler/lib/bundler/vendor/uri/lib/uri.rb +0 -104
- data/bundler/lib/bundler/vendored_persistent.rb +0 -11
- data/bundler/lib/bundler/vendored_securerandom.rb +0 -12
- data/bundler/lib/bundler/vendored_uri.rb +0 -21
- data/bundler/lib/bundler/yaml_serializer.rb +0 -98
- data/doc/rubygems/CONTRIBUTING.md +0 -231
- data/doc/rubygems/POLICIES.md +0 -60
- data/lib/rubygems/request_set/lockfile/parser.rb +0 -344
- data/lib/rubygems/request_set/lockfile/tokenizer.rb +0 -122
- data/lib/rubygems/resolver/conflict.rb +0 -146
- data/lib/rubygems/resolver/stats.rb +0 -46
- data/lib/rubygems/util/list.rb +0 -40
- data/lib/rubygems/vendor/molinillo/LICENSE +0 -9
- data/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
- data/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -88
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -164
- data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb +0 -255
- data/lib/rubygems/vendor/molinillo/lib/molinillo/errors.rb +0 -149
- data/lib/rubygems/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
- data/lib/rubygems/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +0 -112
- data/lib/rubygems/vendor/molinillo/lib/molinillo/modules/ui.rb +0 -67
- data/lib/rubygems/vendor/molinillo/lib/molinillo/resolution.rb +0 -839
- data/lib/rubygems/vendor/molinillo/lib/molinillo/resolver.rb +0 -46
- data/lib/rubygems/vendor/molinillo/lib/molinillo/state.rb +0 -58
- data/lib/rubygems/vendor/molinillo/lib/molinillo.rb +0 -11
- data/lib/rubygems/vendored_molinillo.rb +0 -3
- /data/{bundler/exe → exe}/bundle +0 -0
- /data/{bundler/exe → exe}/bundler +0 -0
- /data/{bundler/lib → lib}/bundler/.document +0 -0
- /data/{bundler/lib → lib}/bundler/capistrano.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/binstubs.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/check.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/console.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/doctor/diagnose.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/doctor/ssl.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/doctor.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/exec.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/fund.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/info.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/init.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/issue.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/list.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/open.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/platform.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/plugin.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/remove.rb +0 -0
- /data/{bundler/lib → lib}/bundler/cli/show.rb +0 -0
- /data/{bundler/lib → lib}/bundler/constants.rb +0 -0
- /data/{bundler/lib → lib}/bundler/current_ruby.rb +0 -0
- /data/{bundler/lib → lib}/bundler/deployment.rb +0 -0
- /data/{bundler/lib → lib}/bundler/deprecate.rb +0 -0
- /data/{bundler/lib → lib}/bundler/digest.rb +0 -0
- /data/{bundler/lib → lib}/bundler/environment_preserver.rb +0 -0
- /data/{bundler/lib → lib}/bundler/feature_flag.rb +0 -0
- /data/{bundler/lib → lib}/bundler/fetcher/base.rb +0 -0
- /data/{bundler/lib → lib}/bundler/fetcher/dependency.rb +0 -0
- /data/{bundler/lib → lib}/bundler/fetcher/gem_remote_fetcher.rb +0 -0
- /data/{bundler/lib → lib}/bundler/fetcher/index.rb +0 -0
- /data/{bundler/lib → lib}/bundler/force_platform.rb +0 -0
- /data/{bundler/lib → lib}/bundler/friendly_errors.rb +0 -0
- /data/{bundler/lib → lib}/bundler/gem_helper.rb +0 -0
- /data/{bundler/lib → lib}/bundler/gem_tasks.rb +0 -0
- /data/{bundler/lib → lib}/bundler/gem_version_promoter.rb +0 -0
- /data/{bundler/lib → lib}/bundler/index.rb +0 -0
- /data/{bundler/lib → lib}/bundler/installer/gem_installer.rb +0 -0
- /data/{bundler/lib → lib}/bundler/installer/standalone.rb +0 -0
- /data/{bundler/lib → lib}/bundler/man/.document +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-binstubs.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-check.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-clean.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-console.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-doctor.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-env.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-exec.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-fund.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-gem.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-help.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-info.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-init.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-issue.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-licenses.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-list.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-open.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-outdated.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-platform.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-plugin.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-pristine.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-remove.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-show.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle-version.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/bundle.1.ronn +0 -0
- /data/{bundler/lib → lib}/bundler/man/index.txt +0 -0
- /data/{bundler/lib → lib}/bundler/mirror.rb +0 -0
- /data/{bundler/lib → lib}/bundler/plugin/api/source.rb +0 -0
- /data/{bundler/lib → lib}/bundler/plugin/api.rb +0 -0
- /data/{bundler/lib → lib}/bundler/plugin/installer/git.rb +0 -0
- /data/{bundler/lib → lib}/bundler/plugin/installer/rubygems.rb +0 -0
- /data/{bundler/lib → lib}/bundler/plugin/source_list.rb +0 -0
- /data/{bundler/lib → lib}/bundler/plugin/unloaded_source.rb +0 -0
- /data/{bundler/lib → lib}/bundler/process_lock.rb +0 -0
- /data/{bundler/lib → lib}/bundler/resolver/candidate.rb +0 -0
- /data/{bundler/lib → lib}/bundler/resolver/package.rb +0 -0
- /data/{bundler/lib → lib}/bundler/resolver/root.rb +0 -0
- /data/{bundler/lib → lib}/bundler/resolver/spec_group.rb +0 -0
- /data/{bundler/lib → lib}/bundler/resolver/strategy.rb +0 -0
- /data/{bundler/lib → lib}/bundler/retry.rb +0 -0
- /data/{bundler/lib → lib}/bundler/ruby_dsl.rb +0 -0
- /data/{bundler/lib → lib}/bundler/safe_marshal.rb +0 -0
- /data/{bundler/lib → lib}/bundler/settings/validator.rb +0 -0
- /data/{bundler/lib → lib}/bundler/setup.rb +0 -0
- /data/{bundler/lib → lib}/bundler/source/gemspec.rb +0 -0
- /data/{bundler/lib → lib}/bundler/source/metadata.rb +0 -0
- /data/{bundler/lib → lib}/bundler/source/path.rb +0 -0
- /data/{bundler/lib → lib}/bundler/source/rubygems_aggregate.rb +0 -0
- /data/{bundler/lib → lib}/bundler/source.rb +0 -0
- /data/{bundler/lib → lib}/bundler/source_list.rb +0 -0
- /data/{bundler/lib → lib}/bundler/source_map.rb +0 -0
- /data/{bundler/lib → lib}/bundler/templates/.document +0 -0
- /data/{bundler/lib → lib}/bundler/templates/Executable +0 -0
- /data/{bundler/lib → lib}/bundler/templates/Executable.standalone +0 -0
- /data/{bundler/lib → lib}/bundler/templates/Gemfile +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/CHANGELOG.md.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/Cargo.toml.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/LICENSE.txt.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/README.md.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/Rakefile.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/bin/console.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/bin/setup.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/circleci/config.yml.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/exe/newgem.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/build.rs.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/go.mod.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/newgem-go.c.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/newgem.c.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/newgem.go.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/newgem.h.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/github/workflows/build-gems.yml.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/github/workflows/main.yml.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/gitignore.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/gitlab-ci.yml.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/lib/newgem/version.rb.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/lib/newgem.rb.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/rspec.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/rubocop.yml.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/sig/newgem.rbs.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/spec/spec_helper.rb.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/standard.yml.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/test/minitest/test_helper.rb.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt +0 -0
- /data/{bundler/lib → lib}/bundler/templates/newgem/test/test-unit/test_helper.rb.tt +0 -0
- /data/{bundler/lib → lib}/bundler/ui/rg_proxy.rb +0 -0
- /data/{bundler/lib → lib}/bundler/ui.rb +0 -0
- /data/{bundler/lib → lib}/bundler/uri_credentials_filter.rb +0 -0
- /data/{bundler/lib → lib}/bundler/uri_normalizer.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/.document +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/fileutils/COPYING +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/fileutils/lib/fileutils.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/LICENSE.md +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/create_file.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/create_link.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/directory.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/command.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/error.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/group.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/invocation.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/line_editor/basic.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/line_editor/readline.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/line_editor.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/nested_context.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser/argument.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser/arguments.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser/option.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser/options.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/rake_compat.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/runner.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/column_printer.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/html.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/table_printer.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/terminal.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/wrapped_printer.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/util.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendored_fileutils.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendored_net_http.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendored_thor.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendored_timeout.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vendored_tsort.rb +0 -0
- /data/{bundler/lib → lib}/bundler/vlad.rb +0 -0
- /data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/LICENSE.txt +0 -0
- /data/{bundler/lib/bundler/vendor/securerandom → lib/rubygems/vendor/resolv}/COPYING +0 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "cooldown_settings"
|
|
4
|
+
require_relative "user_interaction"
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Applies a cooldown period to remote gem versions as a supply chain attack
|
|
8
|
+
# mitigation. When a cooldown of N days is configured, gem versions
|
|
9
|
+
# published within the last N days are not considered for installation or
|
|
10
|
+
# update. Versions whose publish time is unknown are never excluded, so
|
|
11
|
+
# sources that do not provide publish times keep working.
|
|
12
|
+
#
|
|
13
|
+
# The cooldown period comes from the <tt>--cooldown DAYS</tt> option when
|
|
14
|
+
# given, and 0 there disables the cooldown. Without the option the
|
|
15
|
+
# <tt>:cooldown:</tt> setting in the gemrc file and Bundler's own cooldown
|
|
16
|
+
# setting both apply and the longer of the two wins, so a 0 in either of them
|
|
17
|
+
# disables nothing while the other names a period.
|
|
18
|
+
|
|
19
|
+
class Gem::Cooldown
|
|
20
|
+
##
|
|
21
|
+
# The cooldown period in days.
|
|
22
|
+
|
|
23
|
+
attr_reader :days
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# Creates a Cooldown from the command line +options+. The --cooldown
|
|
27
|
+
# option wins outright, so <tt>--cooldown 0</tt> bypasses the cooldown
|
|
28
|
+
# however the two tools are configured. Without it the :cooldown: gemrc
|
|
29
|
+
# setting and Bundler's cooldown setting are both read and the longer of
|
|
30
|
+
# the two applies, so a cooldown configured for only one of them still
|
|
31
|
+
# covers gem commands.
|
|
32
|
+
|
|
33
|
+
def self.from_options(options)
|
|
34
|
+
days = options[:cooldown]
|
|
35
|
+
return new(days) unless days.nil?
|
|
36
|
+
|
|
37
|
+
require_relative "bundler_settings"
|
|
38
|
+
|
|
39
|
+
new Gem::CooldownSettings.combine(warn_unless_valid(Gem.configuration.cooldown, "the gemrc file"),
|
|
40
|
+
warn_unless_valid(Gem::BundlerSettings["cooldown"], "Bundler's configuration"))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def initialize(days, now: Time.now)
|
|
44
|
+
invalid = Gem::CooldownSettings.invalid?(days)
|
|
45
|
+
|
|
46
|
+
@days = Gem::CooldownSettings.days(days) || 0
|
|
47
|
+
@now = now
|
|
48
|
+
|
|
49
|
+
Gem::Cooldown.warn_invalid_days(days, "the cooldown setting") if invalid
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# True when a cooldown period is configured.
|
|
54
|
+
|
|
55
|
+
def active?
|
|
56
|
+
@days > 0
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
##
|
|
60
|
+
# True when a gem version published at +created_at+ must not be
|
|
61
|
+
# considered. Versions with an unknown publish time (+nil+) are kept.
|
|
62
|
+
|
|
63
|
+
def skip?(created_at)
|
|
64
|
+
return false unless active?
|
|
65
|
+
return false unless created_at
|
|
66
|
+
|
|
67
|
+
(@now - created_at) < @days * 86_400
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# Number of days until a gem version published at +created_at+ leaves
|
|
72
|
+
# the cooldown period, rounded up and at least 1.
|
|
73
|
+
|
|
74
|
+
def remaining_days(created_at)
|
|
75
|
+
remaining = @days * 86_400 - (@now - created_at)
|
|
76
|
+
|
|
77
|
+
[(remaining / 86_400.0).ceil, 1].max
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
##
|
|
81
|
+
# Reports, per gem, the newest version the cooldown kept out of a
|
|
82
|
+
# completed installation or update. +entries+ are hashes with :name,
|
|
83
|
+
# :version, :resolved and :available_in_days keys; when several entries
|
|
84
|
+
# name the same gem only the newest version is shown.
|
|
85
|
+
|
|
86
|
+
def self.output_skipped_summary(entries)
|
|
87
|
+
return if entries.nil? || entries.empty?
|
|
88
|
+
|
|
89
|
+
newest = {}
|
|
90
|
+
entries.each do |entry|
|
|
91
|
+
current = newest[entry[:name]]
|
|
92
|
+
newest[entry[:name]] = entry if current.nil? || entry[:version] > current[:version]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
ui = Gem::DefaultUserInteraction.ui
|
|
96
|
+
ui.say "The following gem versions were skipped by the cooldown setting:"
|
|
97
|
+
newest.values.sort_by {|entry| entry[:name] }.each do |entry|
|
|
98
|
+
days = entry[:available_in_days]
|
|
99
|
+
ui.say " * #{entry[:name]} #{entry[:version]} (available in #{days} #{days == 1 ? "day" : "days"}), resolved #{entry[:resolved]} instead"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Matches an ISO 8601 time zone designator at the end of a timestamp.
|
|
104
|
+
TIME_ZONE_SUFFIX = /(?:Z|z|[+-]\d{2}(?::?\d{2})?)\z/ # :nodoc:
|
|
105
|
+
private_constant :TIME_ZONE_SUFFIX
|
|
106
|
+
|
|
107
|
+
# Matches the four-digit year an ISO 8601 timestamp starts with.
|
|
108
|
+
# Time.iso8601 also accepts a year of any length, and one far enough
|
|
109
|
+
# away overflows the Float arithmetic behind #remaining_days.
|
|
110
|
+
FOUR_DIGIT_YEAR = /\A\d{4}-/ # :nodoc:
|
|
111
|
+
private_constant :FOUR_DIGIT_YEAR
|
|
112
|
+
|
|
113
|
+
##
|
|
114
|
+
# Parses a +created_at+ timestamp from the compact index. A timestamp
|
|
115
|
+
# without a time zone offset is read as UTC, because reading it as local
|
|
116
|
+
# time would shift the cooldown window by the environment's offset.
|
|
117
|
+
# Returns nil for anything unparsable, including a year outside four
|
|
118
|
+
# digits, so the cooldown fails open.
|
|
119
|
+
|
|
120
|
+
def self.parse_created_at(value)
|
|
121
|
+
return unless value.is_a?(String) && value.match?(FOUR_DIGIT_YEAR)
|
|
122
|
+
|
|
123
|
+
require "time"
|
|
124
|
+
begin
|
|
125
|
+
Time.iso8601(value.match?(TIME_ZONE_SUFFIX) ? value : "#{value}Z")
|
|
126
|
+
rescue ArgumentError
|
|
127
|
+
nil
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
##
|
|
132
|
+
# Warns once per process that +source+ did not provide publish times, so
|
|
133
|
+
# the cooldown cannot be applied to gems from it.
|
|
134
|
+
|
|
135
|
+
def self.warn_missing_created_at(source)
|
|
136
|
+
return if @warned
|
|
137
|
+
@warned = true
|
|
138
|
+
|
|
139
|
+
Gem::DefaultUserInteraction.ui.alert_warning \
|
|
140
|
+
"#{source.uri} does not provide gem publish times, the cooldown period does not apply to gems from this source"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def self.reset_warned_missing_created_at # :nodoc:
|
|
144
|
+
@warned = nil
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Returns +value+, warning first when it is configured but cannot be read
|
|
148
|
+
# as a number of days.
|
|
149
|
+
|
|
150
|
+
def self.warn_unless_valid(value, source) # :nodoc:
|
|
151
|
+
warn_invalid_days(value, source) if Gem::CooldownSettings.invalid?(value)
|
|
152
|
+
|
|
153
|
+
value
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Warns that a configured cooldown value cannot be read as a non-negative
|
|
157
|
+
# integer, so it does not apply. The --cooldown option is validated by the
|
|
158
|
+
# option parser; this catches the config file paths. Both the gemrc and
|
|
159
|
+
# Bundler settings feed one resolution, so each source gets its own warning
|
|
160
|
+
# rather than the first one silencing the other.
|
|
161
|
+
|
|
162
|
+
def self.warn_invalid_days(value, source) # :nodoc:
|
|
163
|
+
@warned_invalid_days ||= []
|
|
164
|
+
return if @warned_invalid_days.include?(source)
|
|
165
|
+
@warned_invalid_days << source
|
|
166
|
+
|
|
167
|
+
Gem::DefaultUserInteraction.ui.alert_warning Gem::CooldownSettings.invalid_message(value, source)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def self.reset_warned_invalid_days # :nodoc:
|
|
171
|
+
@warned_invalid_days = nil
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "cooldown"
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Mixin methods for the cooldown option for Gem::Commands.
|
|
7
|
+
|
|
8
|
+
module Gem::CooldownOption
|
|
9
|
+
##
|
|
10
|
+
# Add the --cooldown option to the option parser.
|
|
11
|
+
|
|
12
|
+
def add_cooldown_option(group = nil)
|
|
13
|
+
args = [group, "--cooldown DAYS", Integer,
|
|
14
|
+
"Do not use gem versions published within",
|
|
15
|
+
"the last DAYS days (0 disables the cooldown,",
|
|
16
|
+
"overriding the gemrc and Bundler settings)"].compact
|
|
17
|
+
|
|
18
|
+
add_option(*args) do |value, options|
|
|
19
|
+
if value.negative?
|
|
20
|
+
raise Gem::OptionParser::InvalidArgument,
|
|
21
|
+
"#{value} (expected a non-negative integer number of days; use 0 to disable the cooldown)"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
options[:cooldown] = value
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Skip reloading when an identical copy (e.g. the one shipped inside the Bundler
|
|
4
|
+
# gem) was already required from a different path, to avoid redefinition warnings.
|
|
5
|
+
return if defined?(Gem::CooldownSettings)
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# The rules RubyGems and Bundler share for reading a configured cooldown
|
|
9
|
+
# period. Bundler ships a copy of this file, so it deliberately has no
|
|
10
|
+
# requires: none of the rest of RubyGems is guaranteed to be around it.
|
|
11
|
+
|
|
12
|
+
module Gem::CooldownSettings
|
|
13
|
+
##
|
|
14
|
+
# +value+ read as a number of days, or nil when it is absent or cannot be
|
|
15
|
+
# read as a non-negative integer. A gemrc entry and a Bundler config entry
|
|
16
|
+
# are both arbitrary YAML, so either can be any type at all.
|
|
17
|
+
|
|
18
|
+
def self.days(value)
|
|
19
|
+
return if value.nil?
|
|
20
|
+
|
|
21
|
+
# Base 10 explicitly: a leading zero is how a user writes a small number
|
|
22
|
+
# of days, not a request for octal.
|
|
23
|
+
days = Integer(value.to_s, 10, exception: false)
|
|
24
|
+
|
|
25
|
+
days if days && !days.negative?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# True when +value+ is configured but cannot be read as a number of days.
|
|
30
|
+
|
|
31
|
+
def self.invalid?(value)
|
|
32
|
+
!value.nil? && days(value).nil?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# The cooldown that applies when RubyGems and Bundler are configured
|
|
37
|
+
# separately: the longest of +values+, so a cooldown configured for only
|
|
38
|
+
# one of the two tools protects both. Returns nil when none of them is
|
|
39
|
+
# usable.
|
|
40
|
+
#
|
|
41
|
+
# A configured 0 takes part like any other value rather than switching the
|
|
42
|
+
# cooldown off, which leaves <tt>--cooldown 0</tt> as the way to bypass a
|
|
43
|
+
# cooldown that the other tool configures.
|
|
44
|
+
|
|
45
|
+
def self.combine(*values)
|
|
46
|
+
values.filter_map {|value| days(value) }.max
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# +source+ names where the value came from, since RubyGems and Bundler now
|
|
50
|
+
# each read the other's setting and the same complaint from either of them
|
|
51
|
+
# is otherwise impossible to trace back to a file.
|
|
52
|
+
|
|
53
|
+
def self.invalid_message(value, source) # :nodoc:
|
|
54
|
+
"Invalid cooldown value #{value.inspect} in #{source}, so it is ignored. " \
|
|
55
|
+
"Expected a non-negative integer number of days."
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
|
|
5
|
+
class Gem::CredentialStore; end unless defined?(Gem::CredentialStore)
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Stores credentials in the Secret Service API (GNOME Keyring, KWallet,
|
|
9
|
+
# ...) via the +secret-tool+ command line tool from libsecret.
|
|
10
|
+
|
|
11
|
+
class Gem::CredentialStore::LinuxBackend
|
|
12
|
+
# secret-tool prints an item's attributes to stderr, one per line.
|
|
13
|
+
ACCOUNT_ATTRIBUTE = /^attribute\.account = (.*)$/
|
|
14
|
+
def self.available?
|
|
15
|
+
return @available if defined?(@available)
|
|
16
|
+
|
|
17
|
+
@available = ENV["PATH"].to_s.split(File::PATH_SEPARATOR).any? do |dir|
|
|
18
|
+
File.executable?(File.join(dir, "secret-tool"))
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Clears the memoized #available? result. Intended for tests only.
|
|
24
|
+
|
|
25
|
+
def self.reset!
|
|
26
|
+
remove_instance_variable(:@available) if defined?(@available)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.get(service, account)
|
|
30
|
+
out, err, status = Open3.capture3(
|
|
31
|
+
"secret-tool", "lookup", "service", service, "account", account
|
|
32
|
+
)
|
|
33
|
+
# secret-tool exits 1 with nothing on stderr when the entry is simply
|
|
34
|
+
# absent. Anything else is a real failure.
|
|
35
|
+
unless status.success?
|
|
36
|
+
return nil if status.exitstatus == 1 && err.to_s.strip.empty?
|
|
37
|
+
|
|
38
|
+
raise "secret-tool exited with #{status.exitstatus}: #{err.strip}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
secret = out.chomp
|
|
42
|
+
secret.empty? ? nil : secret
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.set(service, account, secret)
|
|
46
|
+
_out, status = Open3.capture2(
|
|
47
|
+
"secret-tool", "store", "--label=RubyGems", "service", service, "account", account,
|
|
48
|
+
stdin_data: secret
|
|
49
|
+
)
|
|
50
|
+
status.success?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# secret-tool writes attributes to stderr and secrets to stdout, so accounts
|
|
54
|
+
# are read from stderr. Discarding stdout also keeps a secret containing a
|
|
55
|
+
# newline from being mistaken for an attribute line.
|
|
56
|
+
def self.list(service)
|
|
57
|
+
_out, err, status = Open3.capture3(
|
|
58
|
+
"secret-tool", "search", "--all", "service", service
|
|
59
|
+
)
|
|
60
|
+
return [] unless status.success?
|
|
61
|
+
|
|
62
|
+
err.scan(ACCOUNT_ATTRIBUTE).flatten.uniq
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.delete(service, account)
|
|
66
|
+
_out, err, status = Open3.capture3(
|
|
67
|
+
"secret-tool", "clear", "service", service, "account", account
|
|
68
|
+
)
|
|
69
|
+
return cleared?(service, account) if status.success?
|
|
70
|
+
|
|
71
|
+
# secret-tool clear exits 1 with no stderr when nothing matched.
|
|
72
|
+
status.exitstatus == 1 && err.to_s.strip.empty?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.delete_all(service)
|
|
76
|
+
_out, err, status = Open3.capture3(
|
|
77
|
+
"secret-tool", "clear", "service", service
|
|
78
|
+
)
|
|
79
|
+
return cleared?(service) if status.success?
|
|
80
|
+
|
|
81
|
+
status.exitstatus == 1 && err.to_s.strip.empty?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# libsecret clears only unlocked items and reports no error for the ones it
|
|
85
|
+
# skipped, so a locked keyring answers a clear with success while keeping
|
|
86
|
+
# every secret. search exits zero either way, so its output is the answer.
|
|
87
|
+
def self.cleared?(service, account = nil)
|
|
88
|
+
_out, err, status = Open3.capture3(
|
|
89
|
+
"secret-tool", "search", "--all", "service", service
|
|
90
|
+
)
|
|
91
|
+
return false unless status.success?
|
|
92
|
+
|
|
93
|
+
remaining = err.scan(ACCOUNT_ATTRIBUTE).flatten
|
|
94
|
+
account ? !remaining.include?(account) : remaining.empty?
|
|
95
|
+
end
|
|
96
|
+
private_class_method :cleared?
|
|
97
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
|
|
5
|
+
class Gem::CredentialStore; end unless defined?(Gem::CredentialStore)
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Stores credentials in the macOS Keychain via the +security+ command line
|
|
9
|
+
# tool. +security+ has no way to read a password from stdin as raw bytes
|
|
10
|
+
# for +add-generic-password+, so #set uses +security -i+ (batch/interactive
|
|
11
|
+
# mode, one tokenized command per stdin line) to keep the secret off argv
|
|
12
|
+
# and out of +ps+ output.
|
|
13
|
+
#
|
|
14
|
+
# A newline would start a second command in the +security -i+ batch, and
|
|
15
|
+
# +security find-generic-password -w+ prints any non-printable byte back as a
|
|
16
|
+
# hex string rather than the original value, so a non-ASCII secret would
|
|
17
|
+
# round-trip corrupted. Those are the limits Gem::CredentialStore#set enforces
|
|
18
|
+
# for every backend, so the caller falls back to file storage rather than
|
|
19
|
+
# storing something that cannot be read back.
|
|
20
|
+
|
|
21
|
+
class Gem::CredentialStore::MacOSBackend
|
|
22
|
+
NOT_FOUND_STATUS = 44
|
|
23
|
+
|
|
24
|
+
def self.get(service, account)
|
|
25
|
+
out, err, status = Open3.capture3(
|
|
26
|
+
"security", "find-generic-password", "-a", account, "-s", service, "-w"
|
|
27
|
+
)
|
|
28
|
+
# A locked keychain and an absent entry both yield no secret, but only the
|
|
29
|
+
# second one is ordinary.
|
|
30
|
+
unless status.success?
|
|
31
|
+
return nil if status.exitstatus == NOT_FOUND_STATUS
|
|
32
|
+
|
|
33
|
+
raise "security exited with #{status.exitstatus}: #{err.strip}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
secret = out.chomp
|
|
37
|
+
secret.empty? ? nil : secret
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.set(service, account, secret)
|
|
41
|
+
command = "add-generic-password -U -a #{quote(account)} -s #{quote(service)} -w #{quote(secret)}\n"
|
|
42
|
+
_out, err, status = Open3.capture3("security", "-i", stdin_data: command)
|
|
43
|
+
return true if status.success?
|
|
44
|
+
|
|
45
|
+
# Raise rather than return false so the reason reaches the user. The
|
|
46
|
+
# wrapper turns it back into false after reporting it.
|
|
47
|
+
raise "security exited with #{status.exitstatus}: #{err.strip}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# security has no "list by service" subcommand, so this reads the dump, which
|
|
51
|
+
# never reports the secrets.
|
|
52
|
+
def self.list(service)
|
|
53
|
+
out, status = Open3.capture2("security", "dump-keychain", err: File::NULL)
|
|
54
|
+
return [] unless status.success?
|
|
55
|
+
|
|
56
|
+
out.split(/^keychain: /).filter_map do |entry|
|
|
57
|
+
next unless entry[/^\s*"svce"<blob>="(.*)"$/, 1] == service
|
|
58
|
+
|
|
59
|
+
entry[/^\s*"acct"<blob>="(.*)"$/, 1]
|
|
60
|
+
end.uniq
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.delete(service, account)
|
|
64
|
+
_out, status = Open3.capture2(
|
|
65
|
+
"security", "delete-generic-password", "-a", account, "-s", service,
|
|
66
|
+
err: File::NULL
|
|
67
|
+
)
|
|
68
|
+
status.success? || status.exitstatus == NOT_FOUND_STATUS
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# security deletes one entry per call, so keep going until it reports there
|
|
72
|
+
# is nothing left (exit 44). Other services are untouched.
|
|
73
|
+
def self.delete_all(service)
|
|
74
|
+
loop do
|
|
75
|
+
_out, status = Open3.capture2(
|
|
76
|
+
"security", "delete-generic-password", "-s", service,
|
|
77
|
+
err: File::NULL
|
|
78
|
+
)
|
|
79
|
+
return true if status.exitstatus == NOT_FOUND_STATUS
|
|
80
|
+
return false unless status.success?
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self.quote(value)
|
|
85
|
+
%("#{value.gsub("\\", "\\\\\\\\").gsub('"', '\\"')}")
|
|
86
|
+
end
|
|
87
|
+
private_class_method :quote
|
|
88
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
|
|
5
|
+
class Gem::CredentialStore; end unless defined?(Gem::CredentialStore)
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Stores credentials in the Windows Credential Manager via the
|
|
9
|
+
# +Windows.Security.Credentials.PasswordVault+ WinRT API, driven from
|
|
10
|
+
# PowerShell. Account/service/secret values are passed as environment
|
|
11
|
+
# variables rather than interpolated into the script text, so no quoting
|
|
12
|
+
# scheme is needed and values cannot break out of the script.
|
|
13
|
+
#
|
|
14
|
+
# Windows PowerShell is used rather than PowerShell 7 (+pwsh+) because the
|
|
15
|
+
# WinRT projection used here is not reliably available under pwsh. It is
|
|
16
|
+
# spawned as +powershell+ rather than +powershell.exe+, the way this codebase
|
|
17
|
+
# spawns +git+, so PATHEXT resolves it. That also lets the tests put a shim
|
|
18
|
+
# ahead of it on Windows, where a file with a shebang is not executable.
|
|
19
|
+
|
|
20
|
+
class Gem::CredentialStore::WindowsBackend
|
|
21
|
+
LOAD_VAULT_TYPE = <<~POWERSHELL
|
|
22
|
+
$ErrorActionPreference = 'Stop'
|
|
23
|
+
[void][Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
|
|
24
|
+
POWERSHELL
|
|
25
|
+
private_constant :LOAD_VAULT_TYPE
|
|
26
|
+
|
|
27
|
+
def self.get(service, account)
|
|
28
|
+
script = <<~POWERSHELL
|
|
29
|
+
#{LOAD_VAULT_TYPE}
|
|
30
|
+
$vault = New-Object Windows.Security.Credentials.PasswordVault
|
|
31
|
+
$credential = $vault.Retrieve($env:RUBYGEMS_CRED_SERVICE, $env:RUBYGEMS_CRED_ACCOUNT)
|
|
32
|
+
# Emitting into the pipeline would send the string through PowerShell's
|
|
33
|
+
# formatter, which wraps at the host width and would corrupt a secret.
|
|
34
|
+
[Console]::Out.Write($credential.Password)
|
|
35
|
+
POWERSHELL
|
|
36
|
+
|
|
37
|
+
out, err, status = run(script, service, account)
|
|
38
|
+
# An absent credential is ordinary. Any other failure is not, so raise and
|
|
39
|
+
# let the wrapper report why rather than authenticating without one.
|
|
40
|
+
unless status.success?
|
|
41
|
+
return nil if missing_credential?(err)
|
|
42
|
+
|
|
43
|
+
raise "powershell exited with #{status.exitstatus}: #{err.strip}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
secret = out.chomp
|
|
47
|
+
secret.empty? ? nil : secret
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.set(service, account, secret)
|
|
51
|
+
script = <<~POWERSHELL
|
|
52
|
+
#{LOAD_VAULT_TYPE}
|
|
53
|
+
$vault = New-Object Windows.Security.Credentials.PasswordVault
|
|
54
|
+
try {
|
|
55
|
+
$existing = $vault.Retrieve($env:RUBYGEMS_CRED_SERVICE, $env:RUBYGEMS_CRED_ACCOUNT)
|
|
56
|
+
$vault.Remove($existing)
|
|
57
|
+
} catch {}
|
|
58
|
+
$credential = New-Object Windows.Security.Credentials.PasswordCredential($env:RUBYGEMS_CRED_SERVICE, $env:RUBYGEMS_CRED_ACCOUNT, $env:RUBYGEMS_CRED_SECRET)
|
|
59
|
+
$vault.Add($credential)
|
|
60
|
+
POWERSHELL
|
|
61
|
+
|
|
62
|
+
_out, err, status = run(script, service, account, secret)
|
|
63
|
+
return true if status.success?
|
|
64
|
+
|
|
65
|
+
# Raise so the reason reaches the user; see MacOSBackend.set.
|
|
66
|
+
raise "powershell exited with #{status.exitstatus}: #{err.strip}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.delete(service, account)
|
|
70
|
+
script = <<~POWERSHELL
|
|
71
|
+
#{LOAD_VAULT_TYPE}
|
|
72
|
+
$vault = New-Object Windows.Security.Credentials.PasswordVault
|
|
73
|
+
$credential = $vault.Retrieve($env:RUBYGEMS_CRED_SERVICE, $env:RUBYGEMS_CRED_ACCOUNT)
|
|
74
|
+
$vault.Remove($credential)
|
|
75
|
+
POWERSHELL
|
|
76
|
+
|
|
77
|
+
_out, err, status = run(script, service, account)
|
|
78
|
+
status.success? || missing_credential?(err)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# FindAllByResource raises when the resource has no entries, which is an
|
|
82
|
+
# empty list rather than an error.
|
|
83
|
+
def self.list(service)
|
|
84
|
+
script = <<~POWERSHELL
|
|
85
|
+
#{LOAD_VAULT_TYPE}
|
|
86
|
+
$vault = New-Object Windows.Security.Credentials.PasswordVault
|
|
87
|
+
try {
|
|
88
|
+
$vault.FindAllByResource($env:RUBYGEMS_CRED_SERVICE) | ForEach-Object {
|
|
89
|
+
[Console]::Out.WriteLine($_.UserName)
|
|
90
|
+
}
|
|
91
|
+
} catch {
|
|
92
|
+
if (-not ($_.Exception.Message -match 'not found|0x80070490')) { throw }
|
|
93
|
+
}
|
|
94
|
+
POWERSHELL
|
|
95
|
+
|
|
96
|
+
out, _err, status = run(script, service, nil)
|
|
97
|
+
return [] unless status.success?
|
|
98
|
+
|
|
99
|
+
out.split("\n").map(&:chomp).reject(&:empty?).uniq
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def self.delete_all(service)
|
|
103
|
+
script = <<~POWERSHELL
|
|
104
|
+
#{LOAD_VAULT_TYPE}
|
|
105
|
+
$vault = New-Object Windows.Security.Credentials.PasswordVault
|
|
106
|
+
try {
|
|
107
|
+
$vault.FindAllByResource($env:RUBYGEMS_CRED_SERVICE) | ForEach-Object { $vault.Remove($_) }
|
|
108
|
+
} catch {
|
|
109
|
+
if (-not ($_.Exception.Message -match 'not found|0x80070490')) { throw }
|
|
110
|
+
}
|
|
111
|
+
POWERSHELL
|
|
112
|
+
|
|
113
|
+
_out, err, status = run(script, service, nil)
|
|
114
|
+
status.success? || missing_credential?(err)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def self.run(script, service, account, secret = nil)
|
|
118
|
+
env = { "RUBYGEMS_CRED_SERVICE" => service, "RUBYGEMS_CRED_ACCOUNT" => account }
|
|
119
|
+
env["RUBYGEMS_CRED_SECRET"] = secret if secret
|
|
120
|
+
|
|
121
|
+
Open3.capture3(env, "powershell", "-NoProfile", "-NonInteractive", "-Command", "-", stdin_data: script)
|
|
122
|
+
end
|
|
123
|
+
private_class_method :run
|
|
124
|
+
|
|
125
|
+
def self.missing_credential?(message)
|
|
126
|
+
text = message.to_s.downcase
|
|
127
|
+
text.include?("element not found") || text.include?("0x80070490") || text.include?("could not be found")
|
|
128
|
+
end
|
|
129
|
+
private_class_method :missing_credential?
|
|
130
|
+
end
|