rubygems-update 2.7.10 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop.yml +66 -0
- data/.travis.yml +22 -18
- data/CONTRIBUTING.md +141 -0
- data/History.txt +291 -14
- data/MAINTAINERS.txt +1 -0
- data/Manifest.txt +13 -9
- data/POLICIES.md +92 -0
- data/README.md +47 -26
- data/Rakefile +47 -207
- data/{UPGRADING.rdoc → UPGRADING.md} +31 -32
- data/appveyor.yml +20 -45
- data/bin/gem +1 -2
- data/bin/update_rubygems +2 -3
- data/bundler/CHANGELOG.md +54 -0
- data/bundler/bundler.gemspec +7 -1
- data/bundler/lib/bundler.rb +26 -8
- data/bundler/lib/bundler/build_metadata.rb +2 -2
- data/bundler/lib/bundler/cli.rb +63 -21
- data/bundler/lib/bundler/cli/add.rb +15 -5
- data/bundler/lib/bundler/cli/binstubs.rb +8 -2
- data/bundler/lib/bundler/cli/doctor.rb +47 -1
- data/bundler/lib/bundler/cli/install.rb +8 -5
- data/bundler/lib/bundler/cli/list.rb +41 -5
- data/bundler/lib/bundler/cli/outdated.rb +7 -1
- data/bundler/lib/bundler/cli/pristine.rb +4 -0
- data/bundler/lib/bundler/cli/remove.rb +18 -0
- data/bundler/lib/bundler/definition.rb +15 -16
- data/bundler/lib/bundler/dependency.rb +2 -2
- data/bundler/lib/bundler/dsl.rb +19 -3
- data/bundler/lib/bundler/feature_flag.rb +7 -0
- data/bundler/lib/bundler/gem_version_promoter.rb +4 -2
- data/bundler/lib/bundler/injector.rb +168 -9
- data/bundler/lib/bundler/installer.rb +29 -6
- data/bundler/lib/bundler/installer/parallel_installer.rb +5 -0
- data/bundler/lib/bundler/plugin.rb +10 -3
- data/bundler/lib/bundler/plugin/events.rb +61 -0
- data/bundler/lib/bundler/resolver.rb +2 -2
- data/bundler/lib/bundler/runtime.rb +8 -2
- data/bundler/lib/bundler/settings.rb +24 -3
- data/bundler/lib/bundler/settings/validator.rb +23 -0
- data/bundler/lib/bundler/shared_helpers.rb +19 -3
- data/bundler/lib/bundler/source.rb +9 -9
- data/bundler/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -0
- data/bundler/lib/bundler/version.rb +1 -1
- data/bundler/man/bundle-add.ronn +13 -2
- data/bundler/man/bundle-config.ronn +21 -0
- data/bundler/man/bundle-install.ronn +1 -1
- data/bundler/man/bundle-list.ronn +19 -1
- data/bundler/man/bundle-outdated.ronn +4 -0
- data/bundler/man/bundle-remove.ronn +23 -0
- data/bundler/man/bundle-update.ronn +1 -1
- data/lib/rubygems.rb +70 -96
- data/lib/rubygems/available_set.rb +1 -1
- data/lib/rubygems/basic_specification.rb +12 -12
- data/lib/rubygems/bundler_version_finder.rb +3 -3
- data/lib/rubygems/command.rb +22 -15
- data/lib/rubygems/command_manager.rb +20 -11
- data/lib/rubygems/commands/build_command.rb +27 -8
- data/lib/rubygems/commands/cert_command.rb +45 -24
- data/lib/rubygems/commands/check_command.rb +1 -1
- data/lib/rubygems/commands/cleanup_command.rb +14 -7
- data/lib/rubygems/commands/contents_command.rb +14 -15
- data/lib/rubygems/commands/dependency_command.rb +17 -17
- data/lib/rubygems/commands/environment_command.rb +20 -1
- data/lib/rubygems/commands/fetch_command.rb +2 -3
- data/lib/rubygems/commands/generate_index_command.rb +2 -3
- data/lib/rubygems/commands/help_command.rb +12 -13
- data/lib/rubygems/commands/info_command.rb +33 -0
- data/lib/rubygems/commands/install_command.rb +21 -17
- data/lib/rubygems/commands/list_command.rb +0 -1
- data/lib/rubygems/commands/lock_command.rb +3 -4
- data/lib/rubygems/commands/open_command.rb +16 -10
- data/lib/rubygems/commands/owner_command.rb +20 -11
- data/lib/rubygems/commands/pristine_command.rb +23 -16
- data/lib/rubygems/commands/push_command.rb +17 -8
- data/lib/rubygems/commands/query_command.rb +24 -24
- data/lib/rubygems/commands/rdoc_command.rb +3 -4
- data/lib/rubygems/commands/search_command.rb +0 -1
- data/lib/rubygems/commands/server_command.rb +1 -2
- data/lib/rubygems/commands/setup_command.rb +78 -38
- data/lib/rubygems/commands/signin_command.rb +2 -1
- data/lib/rubygems/commands/signout_command.rb +2 -2
- data/lib/rubygems/commands/sources_command.rb +11 -12
- data/lib/rubygems/commands/specification_command.rb +7 -7
- data/lib/rubygems/commands/uninstall_command.rb +41 -19
- data/lib/rubygems/commands/unpack_command.rb +16 -7
- data/lib/rubygems/commands/update_command.rb +28 -23
- data/lib/rubygems/commands/which_command.rb +4 -5
- data/lib/rubygems/commands/yank_command.rb +1 -2
- data/lib/rubygems/compatibility.rb +1 -21
- data/lib/rubygems/config_file.rb +36 -36
- data/lib/rubygems/core_ext/kernel_require.rb +6 -6
- data/lib/rubygems/core_ext/kernel_warn.rb +45 -0
- data/lib/rubygems/defaults.rb +31 -12
- data/lib/rubygems/dependency.rb +14 -14
- data/lib/rubygems/dependency_installer.rb +29 -31
- data/lib/rubygems/dependency_list.rb +8 -9
- data/lib/rubygems/deprecate.rb +2 -3
- data/lib/rubygems/doctor.rb +5 -6
- data/lib/rubygems/errors.rb +3 -3
- data/lib/rubygems/exceptions.rb +11 -4
- data/lib/rubygems/ext.rb +0 -1
- data/lib/rubygems/ext/build_error.rb +0 -1
- data/lib/rubygems/ext/builder.rb +50 -23
- data/lib/rubygems/ext/cmake_builder.rb +2 -2
- data/lib/rubygems/ext/configure_builder.rb +2 -3
- data/lib/rubygems/ext/ext_conf_builder.rb +8 -7
- data/lib/rubygems/ext/rake_builder.rb +16 -18
- data/lib/rubygems/gem_runner.rb +2 -2
- data/lib/rubygems/gemcutter_utilities.rb +40 -13
- data/lib/rubygems/indexer.rb +19 -12
- data/lib/rubygems/install_default_message.rb +0 -1
- data/lib/rubygems/install_message.rb +0 -1
- data/lib/rubygems/install_update_options.rb +2 -28
- data/lib/rubygems/installer.rb +95 -75
- data/lib/rubygems/installer_test_case.rb +0 -14
- data/lib/rubygems/local_remote_options.rb +5 -4
- data/lib/rubygems/mock_gem_ui.rb +3 -4
- data/lib/rubygems/name_tuple.rb +4 -4
- data/lib/rubygems/package.rb +90 -73
- data/lib/rubygems/package/digest_io.rb +3 -4
- data/lib/rubygems/package/file_source.rb +3 -4
- data/lib/rubygems/package/io_source.rb +1 -2
- data/lib/rubygems/package/old.rb +8 -16
- data/lib/rubygems/package/source.rb +0 -1
- data/lib/rubygems/package/tar_header.rb +2 -2
- data/lib/rubygems/package/tar_reader.rb +2 -4
- data/lib/rubygems/package/tar_reader/entry.rb +20 -4
- data/lib/rubygems/package/tar_test_case.rb +2 -8
- data/lib/rubygems/package/tar_writer.rb +13 -15
- data/lib/rubygems/package_task.rb +0 -1
- data/lib/rubygems/path_support.rb +16 -6
- data/lib/rubygems/platform.rb +4 -5
- data/lib/rubygems/psych_tree.rb +1 -1
- data/lib/rubygems/rdoc.rb +0 -311
- data/lib/rubygems/remote_fetcher.rb +34 -48
- data/lib/rubygems/request.rb +16 -15
- data/lib/rubygems/request/connection_pools.rb +24 -13
- data/lib/rubygems/request/http_pool.rb +3 -4
- data/lib/rubygems/request/https_pool.rb +1 -3
- data/lib/rubygems/request_set.rb +52 -25
- data/lib/rubygems/request_set/gem_dependency_api.rb +36 -40
- data/lib/rubygems/request_set/lockfile.rb +12 -12
- data/lib/rubygems/request_set/lockfile/parser.rb +18 -29
- data/lib/rubygems/request_set/lockfile/tokenizer.rb +9 -9
- data/lib/rubygems/requirement.rb +16 -16
- data/lib/rubygems/resolver.rb +10 -15
- data/lib/rubygems/resolver/activation_request.rb +6 -6
- data/lib/rubygems/resolver/api_set.rb +5 -6
- data/lib/rubygems/resolver/api_specification.rb +2 -3
- data/lib/rubygems/resolver/best_set.rb +5 -6
- data/lib/rubygems/resolver/composed_set.rb +5 -6
- data/lib/rubygems/resolver/conflict.rb +5 -5
- data/lib/rubygems/resolver/current_set.rb +1 -2
- data/lib/rubygems/resolver/dependency_request.rb +4 -4
- data/lib/rubygems/resolver/git_set.rb +5 -6
- data/lib/rubygems/resolver/git_specification.rb +4 -5
- data/lib/rubygems/resolver/index_set.rb +5 -6
- data/lib/rubygems/resolver/index_specification.rb +3 -4
- data/lib/rubygems/resolver/installed_specification.rb +3 -4
- data/lib/rubygems/resolver/installer_set.rb +12 -12
- data/lib/rubygems/resolver/local_specification.rb +1 -2
- data/lib/rubygems/resolver/lock_set.rb +5 -6
- data/lib/rubygems/resolver/lock_specification.rb +7 -8
- data/lib/rubygems/resolver/requirement_list.rb +1 -1
- data/lib/rubygems/resolver/set.rb +2 -2
- data/lib/rubygems/resolver/source_set.rb +4 -5
- data/lib/rubygems/resolver/spec_specification.rb +1 -2
- data/lib/rubygems/resolver/specification.rb +10 -7
- data/lib/rubygems/resolver/stats.rb +1 -1
- data/lib/rubygems/resolver/vendor_set.rb +4 -5
- data/lib/rubygems/resolver/vendor_specification.rb +2 -3
- data/lib/rubygems/safe_yaml.rb +18 -10
- data/lib/rubygems/security.rb +21 -22
- data/lib/rubygems/security/policies.rb +1 -2
- data/lib/rubygems/security/policy.rb +25 -25
- data/lib/rubygems/security/signer.rb +72 -24
- data/lib/rubygems/security/trust_dir.rb +10 -10
- data/lib/rubygems/server.rb +21 -21
- data/lib/rubygems/source.rb +16 -25
- data/lib/rubygems/source/git.rb +9 -10
- data/lib/rubygems/source/installed.rb +3 -4
- data/lib/rubygems/source/local.rb +7 -7
- data/lib/rubygems/source/lock.rb +4 -4
- data/lib/rubygems/source/specific_file.rb +5 -5
- data/lib/rubygems/source/vendor.rb +2 -3
- data/lib/rubygems/source_list.rb +2 -2
- data/lib/rubygems/source_local.rb +0 -1
- data/lib/rubygems/spec_fetcher.rb +5 -6
- data/lib/rubygems/specification.rb +199 -536
- data/lib/rubygems/specification_policy.rb +407 -0
- data/lib/rubygems/stub_specification.rb +11 -15
- data/lib/rubygems/test_case.rb +141 -66
- data/lib/rubygems/test_utilities.rb +20 -35
- data/lib/rubygems/text.rb +6 -6
- data/lib/rubygems/uninstaller.rb +37 -26
- data/lib/rubygems/uri_formatter.rb +1 -2
- data/lib/rubygems/user_interaction.rb +38 -93
- data/lib/rubygems/util.rb +20 -14
- data/lib/rubygems/util/licenses.rb +27 -1
- data/lib/rubygems/util/list.rb +1 -1
- data/lib/rubygems/validator.rb +4 -5
- data/lib/rubygems/version.rb +15 -15
- data/lib/rubygems/version_option.rb +2 -3
- data/rubygems-update.gemspec +43 -0
- data/setup.rb +2 -8
- data/test/rubygems/rubygems_plugin.rb +0 -1
- data/test/rubygems/simple_gem.rb +1 -1
- data/test/rubygems/test_config.rb +7 -2
- data/test/rubygems/test_gem.rb +161 -130
- data/test/rubygems/test_gem_command.rb +0 -1
- data/test/rubygems/test_gem_command_manager.rb +8 -3
- data/test/rubygems/test_gem_commands_build_command.rb +219 -15
- data/test/rubygems/test_gem_commands_cert_command.rb +69 -8
- data/test/rubygems/test_gem_commands_check_command.rb +1 -1
- data/test/rubygems/test_gem_commands_cleanup_command.rb +27 -1
- data/test/rubygems/test_gem_commands_contents_command.rb +1 -2
- data/test/rubygems/test_gem_commands_dependency_command.rb +33 -34
- data/test/rubygems/test_gem_commands_environment_command.rb +1 -0
- data/test/rubygems/test_gem_commands_fetch_command.rb +0 -1
- data/test/rubygems/test_gem_commands_generate_index_command.rb +0 -1
- data/test/rubygems/test_gem_commands_help_command.rb +7 -4
- data/test/rubygems/test_gem_commands_info_command.rb +44 -0
- data/test/rubygems/test_gem_commands_install_command.rb +79 -12
- data/test/rubygems/test_gem_commands_lock_command.rb +0 -1
- data/test/rubygems/test_gem_commands_open_command.rb +29 -0
- data/test/rubygems/test_gem_commands_outdated_command.rb +0 -1
- data/test/rubygems/test_gem_commands_owner_command.rb +93 -57
- data/test/rubygems/test_gem_commands_pristine_command.rb +65 -30
- data/test/rubygems/test_gem_commands_push_command.rb +39 -0
- data/test/rubygems/test_gem_commands_query_command.rb +102 -100
- data/test/rubygems/test_gem_commands_search_command.rb +0 -1
- data/test/rubygems/test_gem_commands_server_command.rb +0 -1
- data/test/rubygems/test_gem_commands_setup_command.rb +39 -8
- data/test/rubygems/test_gem_commands_signin_command.rb +1 -1
- data/test/rubygems/test_gem_commands_sources_command.rb +0 -1
- data/test/rubygems/test_gem_commands_specification_command.rb +2 -3
- data/test/rubygems/test_gem_commands_stale_command.rb +3 -2
- data/test/rubygems/test_gem_commands_uninstall_command.rb +81 -7
- data/test/rubygems/test_gem_commands_unpack_command.rb +17 -1
- data/test/rubygems/test_gem_commands_update_command.rb +19 -2
- data/test/rubygems/test_gem_commands_which_command.rb +0 -1
- data/test/rubygems/test_gem_commands_yank_command.rb +0 -1
- data/test/rubygems/test_gem_config_file.rb +4 -2
- data/test/rubygems/test_gem_dependency.rb +0 -1
- data/test/rubygems/test_gem_dependency_installer.rb +8 -5
- data/test/rubygems/test_gem_dependency_list.rb +6 -7
- data/test/rubygems/test_gem_dependency_resolution_error.rb +0 -1
- data/test/rubygems/test_gem_doctor.rb +1 -2
- data/test/rubygems/test_gem_ext_builder.rb +10 -23
- data/test/rubygems/test_gem_ext_cmake_builder.rb +5 -4
- data/test/rubygems/test_gem_ext_configure_builder.rb +3 -3
- data/test/rubygems/test_gem_ext_ext_conf_builder.rb +8 -9
- data/test/rubygems/test_gem_ext_rake_builder.rb +20 -5
- data/test/rubygems/test_gem_gem_runner.rb +0 -1
- data/test/rubygems/test_gem_gemcutter_utilities.rb +32 -6
- data/test/rubygems/test_gem_impossible_dependencies_error.rb +0 -1
- data/test/rubygems/test_gem_indexer.rb +1 -2
- data/test/rubygems/test_gem_install_update_options.rb +1 -20
- data/test/rubygems/test_gem_installer.rb +69 -203
- data/test/rubygems/test_gem_local_remote_options.rb +3 -3
- data/test/rubygems/test_gem_name_tuple.rb +0 -1
- data/test/rubygems/test_gem_package.rb +59 -50
- data/test/rubygems/test_gem_package_old.rb +0 -1
- data/test/rubygems/test_gem_package_tar_header.rb +1 -2
- data/test/rubygems/test_gem_package_tar_reader.rb +0 -1
- data/test/rubygems/test_gem_package_tar_reader_entry.rb +11 -0
- data/test/rubygems/test_gem_package_tar_writer.rb +40 -7
- data/test/rubygems/test_gem_package_task.rb +2 -2
- data/test/rubygems/test_gem_path_support.rb +28 -11
- data/test/rubygems/test_gem_platform.rb +4 -5
- data/test/rubygems/test_gem_rdoc.rb +1 -2
- data/test/rubygems/test_gem_remote_fetcher.rb +111 -130
- data/test/rubygems/test_gem_request.rb +5 -5
- data/test/rubygems/test_gem_request_connection_pools.rb +24 -3
- data/test/rubygems/test_gem_request_set.rb +5 -5
- data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +2 -7
- data/test/rubygems/test_gem_request_set_lockfile.rb +1 -2
- data/test/rubygems/test_gem_request_set_lockfile_parser.rb +4 -9
- data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +1 -1
- data/test/rubygems/test_gem_requirement.rb +18 -4
- data/test/rubygems/test_gem_resolver.rb +13 -17
- data/test/rubygems/test_gem_resolver_activation_request.rb +0 -1
- data/test/rubygems/test_gem_resolver_api_set.rb +0 -1
- data/test/rubygems/test_gem_resolver_api_specification.rb +0 -1
- data/test/rubygems/test_gem_resolver_best_set.rb +0 -1
- data/test/rubygems/test_gem_resolver_composed_set.rb +0 -1
- data/test/rubygems/test_gem_resolver_conflict.rb +0 -1
- data/test/rubygems/test_gem_resolver_dependency_request.rb +0 -1
- data/test/rubygems/test_gem_resolver_git_set.rb +0 -1
- data/test/rubygems/test_gem_resolver_git_specification.rb +0 -1
- data/test/rubygems/test_gem_resolver_index_set.rb +0 -1
- data/test/rubygems/test_gem_resolver_index_specification.rb +0 -1
- data/test/rubygems/test_gem_resolver_installed_specification.rb +0 -1
- data/test/rubygems/test_gem_resolver_installer_set.rb +2 -3
- data/test/rubygems/test_gem_resolver_local_specification.rb +0 -1
- data/test/rubygems/test_gem_resolver_lock_set.rb +0 -1
- data/test/rubygems/test_gem_resolver_lock_specification.rb +0 -1
- data/test/rubygems/test_gem_resolver_requirement_list.rb +0 -1
- data/test/rubygems/test_gem_resolver_specification.rb +1 -2
- data/test/rubygems/test_gem_resolver_vendor_set.rb +0 -1
- data/test/rubygems/test_gem_resolver_vendor_specification.rb +0 -1
- data/test/rubygems/test_gem_security.rb +1 -3
- data/test/rubygems/test_gem_security_policy.rb +4 -5
- data/test/rubygems/test_gem_security_signer.rb +4 -3
- data/test/rubygems/test_gem_security_trust_dir.rb +1 -2
- data/test/rubygems/test_gem_server.rb +4 -4
- data/test/rubygems/test_gem_source.rb +0 -13
- data/test/rubygems/test_gem_source_fetch_problem.rb +0 -1
- data/test/rubygems/test_gem_source_git.rb +0 -1
- data/test/rubygems/test_gem_source_installed.rb +0 -1
- data/test/rubygems/test_gem_source_lock.rb +0 -1
- data/test/rubygems/test_gem_source_vendor.rb +0 -1
- data/test/rubygems/test_gem_spec_fetcher.rb +0 -1
- data/test/rubygems/test_gem_specification.rb +334 -198
- data/test/rubygems/test_gem_stream_ui.rb +13 -30
- data/test/rubygems/test_gem_stub_specification.rb +0 -2
- data/test/rubygems/test_gem_text.rb +4 -5
- data/test/rubygems/test_gem_uninstaller.rb +21 -1
- data/test/rubygems/test_gem_unsatisfiable_dependency_error.rb +0 -1
- data/test/rubygems/test_gem_uri_formatter.rb +0 -1
- data/test/rubygems/test_gem_util.rb +6 -11
- data/test/rubygems/test_gem_validator.rb +0 -1
- data/test/rubygems/test_gem_version.rb +11 -11
- data/test/rubygems/test_gem_version_option.rb +0 -1
- data/test/rubygems/test_remote_fetch_error.rb +0 -1
- data/test/rubygems/test_require.rb +67 -52
- data/util/CL2notes +1 -2
- data/util/ci +15 -12
- data/util/create_certs.rb +6 -7
- data/util/create_encrypted_key.rb +0 -1
- data/util/patch_with_prs.rb +1 -1
- data/util/rubocop +8 -0
- data/util/update_bundled_ca_certificates.rb +12 -13
- data/util/update_changelog.rb +1 -1
- metadata +61 -53
- data/.autotest +0 -71
- data/.document +0 -5
- data/CONTRIBUTING.rdoc +0 -130
- data/CVE-2013-4287.txt +0 -35
- data/CVE-2013-4363.txt +0 -45
- data/CVE-2015-3900.txt +0 -40
- data/POLICIES.rdoc +0 -74
- data/test/rubygems/fix_openssl_warnings.rb +0 -13
@@ -24,7 +24,7 @@ class Gem::Security::Policy
|
|
24
24
|
# Create a new Gem::Security::Policy object with the given mode and
|
25
25
|
# options.
|
26
26
|
|
27
|
-
def initialize
|
27
|
+
def initialize(name, policy = {}, opt = {})
|
28
28
|
require 'openssl'
|
29
29
|
|
30
30
|
@name = name
|
@@ -55,7 +55,7 @@ class Gem::Security::Policy
|
|
55
55
|
# Verifies each certificate in +chain+ has signed the following certificate
|
56
56
|
# and is valid for the given +time+.
|
57
57
|
|
58
|
-
def check_chain
|
58
|
+
def check_chain(chain, time)
|
59
59
|
raise Gem::Security::Exception, 'missing signing chain' unless chain
|
60
60
|
raise Gem::Security::Exception, 'empty signing chain' if chain.empty?
|
61
61
|
|
@@ -74,7 +74,7 @@ class Gem::Security::Policy
|
|
74
74
|
# Verifies that +data+ matches the +signature+ created by +public_key+ and
|
75
75
|
# the +digest+ algorithm.
|
76
76
|
|
77
|
-
def check_data
|
77
|
+
def check_data(public_key, digest, signature, data)
|
78
78
|
raise Gem::Security::Exception, "invalid signature" unless
|
79
79
|
public_key.verify digest.new, signature, data.digest
|
80
80
|
|
@@ -85,22 +85,22 @@ class Gem::Security::Policy
|
|
85
85
|
# Ensures that +signer+ is valid for +time+ and was signed by the +issuer+.
|
86
86
|
# If the +issuer+ is +nil+ no verification is performed.
|
87
87
|
|
88
|
-
def check_cert
|
88
|
+
def check_cert(signer, issuer, time)
|
89
89
|
raise Gem::Security::Exception, 'missing signing certificate' unless
|
90
90
|
signer
|
91
91
|
|
92
92
|
message = "certificate #{signer.subject}"
|
93
93
|
|
94
|
-
if not_before = signer.not_before and not_before > time
|
94
|
+
if not_before = signer.not_before and not_before > time
|
95
95
|
raise Gem::Security::Exception,
|
96
96
|
"#{message} not valid before #{not_before}"
|
97
97
|
end
|
98
98
|
|
99
|
-
if not_after = signer.not_after and not_after < time
|
99
|
+
if not_after = signer.not_after and not_after < time
|
100
100
|
raise Gem::Security::Exception, "#{message} not valid after #{not_after}"
|
101
101
|
end
|
102
102
|
|
103
|
-
if issuer and not signer.verify issuer.public_key
|
103
|
+
if issuer and not signer.verify issuer.public_key
|
104
104
|
raise Gem::Security::Exception,
|
105
105
|
"#{message} was not issued by #{issuer.subject}"
|
106
106
|
end
|
@@ -111,8 +111,8 @@ class Gem::Security::Policy
|
|
111
111
|
##
|
112
112
|
# Ensures the public key of +key+ matches the public key in +signer+
|
113
113
|
|
114
|
-
def check_key
|
115
|
-
unless signer and key
|
114
|
+
def check_key(signer, key)
|
115
|
+
unless signer and key
|
116
116
|
return true unless @only_signed
|
117
117
|
|
118
118
|
raise Gem::Security::Exception, 'missing key or signature'
|
@@ -129,7 +129,7 @@ class Gem::Security::Policy
|
|
129
129
|
# Ensures the root certificate in +chain+ is self-signed and valid for
|
130
130
|
# +time+.
|
131
131
|
|
132
|
-
def check_root
|
132
|
+
def check_root(chain, time)
|
133
133
|
raise Gem::Security::Exception, 'missing signing chain' unless chain
|
134
134
|
|
135
135
|
root = chain.first
|
@@ -148,7 +148,7 @@ class Gem::Security::Policy
|
|
148
148
|
# Ensures the root of +chain+ has a trusted certificate in +trust_dir+ and
|
149
149
|
# the digests of the two certificates match according to +digester+
|
150
150
|
|
151
|
-
def check_trust
|
151
|
+
def check_trust(chain, digester, trust_dir)
|
152
152
|
raise Gem::Security::Exception, 'missing signing chain' unless chain
|
153
153
|
|
154
154
|
root = chain.first
|
@@ -157,7 +157,7 @@ class Gem::Security::Policy
|
|
157
157
|
|
158
158
|
path = Gem::Security.trust_dir.cert_path root
|
159
159
|
|
160
|
-
unless File.exist? path
|
160
|
+
unless File.exist? path
|
161
161
|
message = "root cert #{root.subject} is not trusted".dup
|
162
162
|
|
163
163
|
message << " (root of signing cert #{chain.last.subject})" if
|
@@ -183,7 +183,7 @@ class Gem::Security::Policy
|
|
183
183
|
##
|
184
184
|
# Extracts the email or subject from +certificate+
|
185
185
|
|
186
|
-
def subject
|
186
|
+
def subject(certificate) # :nodoc:
|
187
187
|
certificate.extensions.each do |extension|
|
188
188
|
next unless extension.oid == 'subjectAltName'
|
189
189
|
|
@@ -196,9 +196,9 @@ class Gem::Security::Policy
|
|
196
196
|
def inspect # :nodoc:
|
197
197
|
("[Policy: %s - data: %p signer: %p chain: %p root: %p " +
|
198
198
|
"signed-only: %p trusted-only: %p]") % [
|
199
|
-
|
200
|
-
|
201
|
-
|
199
|
+
@name, @verify_chain, @verify_data, @verify_root, @verify_signer,
|
200
|
+
@only_signed, @only_trusted,
|
201
|
+
]
|
202
202
|
end
|
203
203
|
|
204
204
|
##
|
@@ -208,13 +208,13 @@ class Gem::Security::Policy
|
|
208
208
|
#
|
209
209
|
# If +key+ is given it is used to validate the signing certificate.
|
210
210
|
|
211
|
-
def verify
|
212
|
-
full_name = '(unknown)'
|
213
|
-
if signatures.empty?
|
214
|
-
if @only_signed
|
211
|
+
def verify(chain, key = nil, digests = {}, signatures = {},
|
212
|
+
full_name = '(unknown)')
|
213
|
+
if signatures.empty?
|
214
|
+
if @only_signed
|
215
215
|
raise Gem::Security::Exception,
|
216
216
|
"unsigned gems are not allowed by the #{name} policy"
|
217
|
-
elsif digests.empty?
|
217
|
+
elsif digests.empty?
|
218
218
|
# lack of signatures is irrelevant if there is nothing to check
|
219
219
|
# against
|
220
220
|
else
|
@@ -232,7 +232,7 @@ class Gem::Security::Policy
|
|
232
232
|
file_digests.values.first.name == Gem::Security::DIGEST_NAME
|
233
233
|
end
|
234
234
|
|
235
|
-
if @verify_data
|
235
|
+
if @verify_data
|
236
236
|
raise Gem::Security::Exception, 'no digests provided (probable bug)' if
|
237
237
|
signer_digests.nil? or signer_digests.empty?
|
238
238
|
else
|
@@ -249,9 +249,9 @@ class Gem::Security::Policy
|
|
249
249
|
|
250
250
|
check_root chain, time if @verify_root
|
251
251
|
|
252
|
-
if @only_trusted
|
252
|
+
if @only_trusted
|
253
253
|
check_trust chain, digester, trust_dir
|
254
|
-
elsif signatures.empty? and digests.empty?
|
254
|
+
elsif signatures.empty? and digests.empty?
|
255
255
|
# trust is irrelevant if there's no signatures to verify
|
256
256
|
else
|
257
257
|
alert_warning "#{subject signer} is not trusted for #{full_name}"
|
@@ -280,7 +280,7 @@ class Gem::Security::Policy
|
|
280
280
|
# Extracts the certificate chain from the +spec+ and calls #verify to ensure
|
281
281
|
# the signatures and certificate chain is valid according to the policy..
|
282
282
|
|
283
|
-
def verify_signatures
|
283
|
+
def verify_signatures(spec, digests, signatures)
|
284
284
|
chain = spec.cert_chain.map do |cert_pem|
|
285
285
|
OpenSSL::X509::Certificate.new cert_pem
|
286
286
|
end
|
@@ -2,8 +2,12 @@
|
|
2
2
|
##
|
3
3
|
# Basic OpenSSL-based package signing class.
|
4
4
|
|
5
|
+
require "rubygems/user_interaction"
|
6
|
+
|
5
7
|
class Gem::Security::Signer
|
6
8
|
|
9
|
+
include Gem::UserInteraction
|
10
|
+
|
7
11
|
##
|
8
12
|
# The chain of certificates for signing including the signing certificate
|
9
13
|
|
@@ -25,21 +29,54 @@ class Gem::Security::Signer
|
|
25
29
|
|
26
30
|
attr_reader :digest_name # :nodoc:
|
27
31
|
|
32
|
+
##
|
33
|
+
# Gem::Security::Signer options
|
34
|
+
|
35
|
+
attr_reader :options
|
36
|
+
|
37
|
+
DEFAULT_OPTIONS = {
|
38
|
+
expiration_length_days: 365
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
##
|
42
|
+
# Attemps to re-sign an expired cert with a given private key
|
43
|
+
def self.re_sign_cert(expired_cert, expired_cert_path, private_key)
|
44
|
+
return unless expired_cert.not_after < Time.now
|
45
|
+
|
46
|
+
expiry = expired_cert.not_after.strftime('%Y%m%d%H%M%S')
|
47
|
+
expired_cert_file = "#{File.basename(expired_cert_path)}.expired.#{expiry}"
|
48
|
+
new_expired_cert_path = File.join(Gem.user_home, ".gem", expired_cert_file)
|
49
|
+
|
50
|
+
Gem::Security.write(expired_cert, new_expired_cert_path)
|
51
|
+
|
52
|
+
re_signed_cert = Gem::Security.re_sign(
|
53
|
+
expired_cert,
|
54
|
+
private_key,
|
55
|
+
(Gem::Security::ONE_DAY * Gem.configuration.cert_expiration_length_days)
|
56
|
+
)
|
57
|
+
|
58
|
+
Gem::Security.write(re_signed_cert, expired_cert_path)
|
59
|
+
|
60
|
+
yield(expired_cert_path, new_expired_cert_path) if block_given?
|
61
|
+
end
|
62
|
+
|
28
63
|
##
|
29
64
|
# Creates a new signer with an RSA +key+ or path to a key, and a certificate
|
30
65
|
# +chain+ containing X509 certificates, encoding certificates or paths to
|
31
66
|
# certificates.
|
32
67
|
|
33
|
-
def initialize
|
68
|
+
def initialize(key, cert_chain, passphrase = nil, options = {})
|
34
69
|
@cert_chain = cert_chain
|
35
70
|
@key = key
|
71
|
+
@passphrase = passphrase
|
72
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
36
73
|
|
37
|
-
unless @key
|
74
|
+
unless @key
|
38
75
|
default_key = File.join Gem.default_key_path
|
39
76
|
@key = default_key if File.exist? default_key
|
40
77
|
end
|
41
78
|
|
42
|
-
unless @cert_chain
|
79
|
+
unless @cert_chain
|
43
80
|
default_cert = File.join Gem.default_cert_path
|
44
81
|
@cert_chain = [default_cert] if File.exist? default_cert
|
45
82
|
end
|
@@ -47,10 +84,12 @@ class Gem::Security::Signer
|
|
47
84
|
@digest_algorithm = Gem::Security::DIGEST_ALGORITHM
|
48
85
|
@digest_name = Gem::Security::DIGEST_NAME
|
49
86
|
|
50
|
-
@key
|
51
|
-
@
|
87
|
+
if @key && !@key.is_a?(OpenSSL::PKey::RSA)
|
88
|
+
@passphrase ||= ask_for_password("Enter PEM pass phrase:")
|
89
|
+
@key = OpenSSL::PKey::RSA.new(File.read(@key), @passphrase)
|
90
|
+
end
|
52
91
|
|
53
|
-
if @cert_chain
|
92
|
+
if @cert_chain
|
54
93
|
@cert_chain = @cert_chain.compact.map do |cert|
|
55
94
|
next cert if OpenSSL::X509::Certificate === cert
|
56
95
|
|
@@ -67,10 +106,10 @@ class Gem::Security::Signer
|
|
67
106
|
# Extracts the full name of +cert+. If the certificate has a subjectAltName
|
68
107
|
# this value is preferred, otherwise the subject is used.
|
69
108
|
|
70
|
-
def extract_name
|
109
|
+
def extract_name(cert) # :nodoc:
|
71
110
|
subject_alt_name = cert.extensions.find { |e| 'subjectAltName' == e.oid }
|
72
111
|
|
73
|
-
if subject_alt_name
|
112
|
+
if subject_alt_name
|
74
113
|
/\Aemail:/ =~ subject_alt_name.value
|
75
114
|
|
76
115
|
$' || subject_alt_name.value
|
@@ -99,13 +138,15 @@ class Gem::Security::Signer
|
|
99
138
|
##
|
100
139
|
# Sign data with given digest algorithm
|
101
140
|
|
102
|
-
def sign
|
141
|
+
def sign(data)
|
103
142
|
return unless @key
|
104
143
|
|
105
144
|
raise Gem::Security::Exception, 'no certs provided' if @cert_chain.empty?
|
106
145
|
|
107
|
-
if @cert_chain.length == 1 and @cert_chain.last.not_after < Time.now
|
108
|
-
re_sign_key
|
146
|
+
if @cert_chain.length == 1 and @cert_chain.last.not_after < Time.now
|
147
|
+
re_sign_key(
|
148
|
+
expiration_length: (Gem::Security::ONE_DAY * options[:expiration_length_days])
|
149
|
+
)
|
109
150
|
end
|
110
151
|
|
111
152
|
full_name = extract_name @cert_chain.last
|
@@ -121,6 +162,7 @@ class Gem::Security::Signer
|
|
121
162
|
# The key will be re-signed if:
|
122
163
|
# * The expired certificate is self-signed
|
123
164
|
# * The expired certificate is saved at ~/.gem/gem-public_cert.pem
|
165
|
+
# and the private key is saved at ~/.gem/gem-private_key.pem
|
124
166
|
# * There is no file matching the expiry date at
|
125
167
|
# ~/.gem/gem-public_cert.pem.expired.%Y%m%d%H%M%S
|
126
168
|
#
|
@@ -128,25 +170,32 @@ class Gem::Security::Signer
|
|
128
170
|
# be saved as ~/.gem/gem-public_cert.pem.expired.%Y%m%d%H%M%S where the
|
129
171
|
# expiry time (not after) is used for the timestamp.
|
130
172
|
|
131
|
-
def re_sign_key # :nodoc:
|
173
|
+
def re_sign_key(expiration_length: Gem::Security::ONE_YEAR) # :nodoc:
|
132
174
|
old_cert = @cert_chain.last
|
133
175
|
|
134
|
-
disk_cert_path = File.join
|
135
|
-
disk_cert = File.read
|
136
|
-
disk_key =
|
137
|
-
File.read File.join(Gem.default_key_path) rescue nil
|
176
|
+
disk_cert_path = File.join(Gem.default_cert_path)
|
177
|
+
disk_cert = File.read(disk_cert_path) rescue nil
|
138
178
|
|
139
|
-
|
140
|
-
|
179
|
+
disk_key_path = File.join(Gem.default_key_path)
|
180
|
+
disk_key =
|
181
|
+
OpenSSL::PKey::RSA.new(File.read(disk_key_path), @passphrase) rescue nil
|
182
|
+
|
183
|
+
return unless disk_key
|
184
|
+
|
185
|
+
if disk_key.to_pem == @key.to_pem && disk_cert == old_cert.to_pem
|
186
|
+
expiry = old_cert.not_after.strftime('%Y%m%d%H%M%S')
|
141
187
|
old_cert_file = "gem-public_cert.pem.expired.#{expiry}"
|
142
|
-
old_cert_path = File.join
|
188
|
+
old_cert_path = File.join(Gem.user_home, ".gem", old_cert_file)
|
143
189
|
|
144
|
-
unless File.exist?
|
145
|
-
Gem::Security.write
|
190
|
+
unless File.exist?(old_cert_path)
|
191
|
+
Gem::Security.write(old_cert, old_cert_path)
|
146
192
|
|
147
|
-
cert = Gem::Security.re_sign
|
193
|
+
cert = Gem::Security.re_sign(old_cert, @key, expiration_length)
|
148
194
|
|
149
|
-
Gem::Security.write
|
195
|
+
Gem::Security.write(cert, disk_cert_path)
|
196
|
+
|
197
|
+
alert("Your cert: #{disk_cert_path} has been auto re-signed with the key: #{disk_key_path}")
|
198
|
+
alert("Your expired cert will be located at: #{old_cert_path}")
|
150
199
|
|
151
200
|
@cert_chain = [cert]
|
152
201
|
end
|
@@ -154,4 +203,3 @@ class Gem::Security::Signer
|
|
154
203
|
end
|
155
204
|
|
156
205
|
end
|
157
|
-
|
@@ -11,7 +11,7 @@ class Gem::Security::TrustDir
|
|
11
11
|
DEFAULT_PERMISSIONS = {
|
12
12
|
:trust_dir => 0700,
|
13
13
|
:trusted_cert => 0600,
|
14
|
-
}
|
14
|
+
}.freeze
|
15
15
|
|
16
16
|
##
|
17
17
|
# The directory where trusted certificates will be stored.
|
@@ -22,7 +22,7 @@ class Gem::Security::TrustDir
|
|
22
22
|
# Creates a new TrustDir using +dir+ where the directory and file
|
23
23
|
# permissions will be checked according to +permissions+
|
24
24
|
|
25
|
-
def initialize
|
25
|
+
def initialize(dir, permissions = DEFAULT_PERMISSIONS)
|
26
26
|
@dir = dir
|
27
27
|
@permissions = permissions
|
28
28
|
|
@@ -32,7 +32,7 @@ class Gem::Security::TrustDir
|
|
32
32
|
##
|
33
33
|
# Returns the path to the trusted +certificate+
|
34
34
|
|
35
|
-
def cert_path
|
35
|
+
def cert_path(certificate)
|
36
36
|
name_path certificate.subject
|
37
37
|
end
|
38
38
|
|
@@ -59,7 +59,7 @@ class Gem::Security::TrustDir
|
|
59
59
|
# Returns the issuer certificate of the given +certificate+ if it exists in
|
60
60
|
# the trust directory.
|
61
61
|
|
62
|
-
def issuer_of
|
62
|
+
def issuer_of(certificate)
|
63
63
|
path = name_path certificate.issuer
|
64
64
|
|
65
65
|
return unless File.exist? path
|
@@ -70,7 +70,7 @@ class Gem::Security::TrustDir
|
|
70
70
|
##
|
71
71
|
# Returns the path to the trusted certificate with the given ASN.1 +name+
|
72
72
|
|
73
|
-
def name_path
|
73
|
+
def name_path(name)
|
74
74
|
digest = @digester.hexdigest name.to_s
|
75
75
|
|
76
76
|
File.join @dir, "cert-#{digest}.pem"
|
@@ -79,7 +79,7 @@ class Gem::Security::TrustDir
|
|
79
79
|
##
|
80
80
|
# Loads the given +certificate_file+
|
81
81
|
|
82
|
-
def load_certificate
|
82
|
+
def load_certificate(certificate_file)
|
83
83
|
pem = File.read certificate_file
|
84
84
|
|
85
85
|
OpenSSL::X509::Certificate.new pem
|
@@ -88,13 +88,14 @@ class Gem::Security::TrustDir
|
|
88
88
|
##
|
89
89
|
# Add a certificate to trusted certificate list.
|
90
90
|
|
91
|
-
def trust_cert
|
91
|
+
def trust_cert(certificate)
|
92
92
|
verify
|
93
93
|
|
94
94
|
destination = cert_path certificate
|
95
95
|
|
96
|
-
File.open destination, 'wb',
|
96
|
+
File.open destination, 'wb', 0600 do |io|
|
97
97
|
io.write certificate.to_pem
|
98
|
+
io.chmod(@permissions[:trusted_cert])
|
98
99
|
end
|
99
100
|
end
|
100
101
|
|
@@ -104,7 +105,7 @@ class Gem::Security::TrustDir
|
|
104
105
|
# permissions.
|
105
106
|
|
106
107
|
def verify
|
107
|
-
if File.exist? @dir
|
108
|
+
if File.exist? @dir
|
108
109
|
raise Gem::Security::Exception,
|
109
110
|
"trust directory #{@dir} is not a directory" unless
|
110
111
|
File.directory? @dir
|
@@ -116,4 +117,3 @@ class Gem::Security::TrustDir
|
|
116
117
|
end
|
117
118
|
|
118
119
|
end
|
119
|
-
|
data/lib/rubygems/server.rb
CHANGED
@@ -35,7 +35,7 @@ class Gem::Server
|
|
35
35
|
include ERB::Util
|
36
36
|
include Gem::UserInteraction
|
37
37
|
|
38
|
-
SEARCH = <<-ERB
|
38
|
+
SEARCH = <<-ERB.freeze
|
39
39
|
<form class="headerSearch" name="headerSearchForm" method="get" action="/rdoc">
|
40
40
|
<div id="search" style="float:right">
|
41
41
|
<label for="q">Filter/Search</label>
|
@@ -45,7 +45,7 @@ class Gem::Server
|
|
45
45
|
</form>
|
46
46
|
ERB
|
47
47
|
|
48
|
-
DOC_TEMPLATE = <<-'ERB'
|
48
|
+
DOC_TEMPLATE = <<-'ERB'.freeze
|
49
49
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
50
50
|
<!DOCTYPE html
|
51
51
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
@@ -129,7 +129,7 @@ class Gem::Server
|
|
129
129
|
ERB
|
130
130
|
|
131
131
|
# CSS is copy & paste from rdoc-style.css, RDoc V1.0.1 - 20041108
|
132
|
-
RDOC_CSS = <<-CSS
|
132
|
+
RDOC_CSS = <<-CSS.freeze
|
133
133
|
body {
|
134
134
|
font-family: Verdana,Arial,Helvetica,sans-serif;
|
135
135
|
font-size: 90%;
|
@@ -339,7 +339,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
339
339
|
.ruby-value { color: #7fffd4; background: transparent; }
|
340
340
|
CSS
|
341
341
|
|
342
|
-
RDOC_NO_DOCUMENTATION = <<-'ERB'
|
342
|
+
RDOC_NO_DOCUMENTATION = <<-'ERB'.freeze
|
343
343
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
344
344
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
345
345
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
@@ -373,7 +373,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
373
373
|
</html>
|
374
374
|
ERB
|
375
375
|
|
376
|
-
RDOC_SEARCH_TEMPLATE = <<-'ERB'
|
376
|
+
RDOC_SEARCH_TEMPLATE = <<-'ERB'.freeze
|
377
377
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
378
378
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
379
379
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
@@ -450,7 +450,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
450
450
|
@have_rdoc_4_plus = nil
|
451
451
|
end
|
452
452
|
|
453
|
-
def add_date
|
453
|
+
def add_date(res)
|
454
454
|
res['date'] = @spec_dirs.map do |spec_dir|
|
455
455
|
File.stat(spec_dir).mtime
|
456
456
|
end.max
|
@@ -462,8 +462,8 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
462
462
|
end
|
463
463
|
end
|
464
464
|
|
465
|
-
def doc_root
|
466
|
-
if have_rdoc_4_plus?
|
465
|
+
def doc_root(gem_name)
|
466
|
+
if have_rdoc_4_plus?
|
467
467
|
"/doc_root/#{u gem_name}/"
|
468
468
|
else
|
469
469
|
"/doc_root/#{u gem_name}/rdoc/index.html"
|
@@ -491,14 +491,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
491
491
|
|
492
492
|
specs = Marshal.dump specs
|
493
493
|
|
494
|
-
if req.path =~ /\.gz$/
|
494
|
+
if req.path =~ /\.gz$/
|
495
495
|
specs = Gem::Util.gzip specs
|
496
496
|
res['content-type'] = 'application/x-gzip'
|
497
497
|
else
|
498
498
|
res['content-type'] = 'application/octet-stream'
|
499
499
|
end
|
500
500
|
|
501
|
-
if req.request_method == 'HEAD'
|
501
|
+
if req.request_method == 'HEAD'
|
502
502
|
res['content-length'] = specs.length
|
503
503
|
else
|
504
504
|
res.body << specs
|
@@ -509,7 +509,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
509
509
|
# Creates server sockets based on the addresses option. If no addresses
|
510
510
|
# were given a server socket for all interfaces is created.
|
511
511
|
|
512
|
-
def listen
|
512
|
+
def listen(addresses = @addresses)
|
513
513
|
addresses = [nil] unless addresses
|
514
514
|
|
515
515
|
listeners = 0
|
@@ -529,14 +529,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
529
529
|
end
|
530
530
|
end
|
531
531
|
|
532
|
-
if @server.listeners.empty?
|
532
|
+
if @server.listeners.empty?
|
533
533
|
say "Unable to start a server."
|
534
534
|
say "Check for running servers or your --bind and --port arguments"
|
535
535
|
terminate_interaction 1
|
536
536
|
end
|
537
537
|
end
|
538
538
|
|
539
|
-
def prerelease_specs
|
539
|
+
def prerelease_specs(req, res)
|
540
540
|
reset_gems
|
541
541
|
|
542
542
|
res['content-type'] = 'application/x-gzip'
|
@@ -552,14 +552,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
552
552
|
|
553
553
|
specs = Marshal.dump specs
|
554
554
|
|
555
|
-
if req.path =~ /\.gz$/
|
555
|
+
if req.path =~ /\.gz$/
|
556
556
|
specs = Gem::Util.gzip specs
|
557
557
|
res['content-type'] = 'application/x-gzip'
|
558
558
|
else
|
559
559
|
res['content-type'] = 'application/octet-stream'
|
560
560
|
end
|
561
561
|
|
562
|
-
if req.request_method == 'HEAD'
|
562
|
+
if req.request_method == 'HEAD'
|
563
563
|
res['content-length'] = specs.length
|
564
564
|
else
|
565
565
|
res.body << specs
|
@@ -579,13 +579,13 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
579
579
|
|
580
580
|
selector = full_name.inspect
|
581
581
|
|
582
|
-
if specs.empty?
|
582
|
+
if specs.empty?
|
583
583
|
res.status = 404
|
584
584
|
res.body = "No gems found matching #{selector}"
|
585
|
-
elsif specs.length > 1
|
585
|
+
elsif specs.length > 1
|
586
586
|
res.status = 500
|
587
587
|
res.body = "Multiple gems found matching #{selector}"
|
588
|
-
elsif marshal_format
|
588
|
+
elsif marshal_format
|
589
589
|
res['content-type'] = 'application/x-deflate'
|
590
590
|
res.body << Gem.deflate(Marshal.dump(specs.first))
|
591
591
|
end
|
@@ -818,7 +818,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
818
818
|
'/gems' => '/cache/',
|
819
819
|
}
|
820
820
|
|
821
|
-
if have_rdoc_4_plus?
|
821
|
+
if have_rdoc_4_plus?
|
822
822
|
@server.mount '/doc_root', RDoc::Servlet, '/doc_root'
|
823
823
|
else
|
824
824
|
file_handlers['/doc_root'] = '/doc/'
|
@@ -851,14 +851,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
851
851
|
|
852
852
|
specs = Marshal.dump specs
|
853
853
|
|
854
|
-
if req.path =~ /\.gz$/
|
854
|
+
if req.path =~ /\.gz$/
|
855
855
|
specs = Gem::Util.gzip specs
|
856
856
|
res['content-type'] = 'application/x-gzip'
|
857
857
|
else
|
858
858
|
res['content-type'] = 'application/octet-stream'
|
859
859
|
end
|
860
860
|
|
861
|
-
if req.request_method == 'HEAD'
|
861
|
+
if req.request_method == 'HEAD'
|
862
862
|
res['content-length'] = specs.length
|
863
863
|
else
|
864
864
|
res.body << specs
|