rubygems-update 3.0.3 → 3.0.9
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/.rubocop.yml +1 -0
- data/.travis.yml +2 -0
- data/CODE_OF_CONDUCT.md +10 -8
- data/CONTRIBUTING.md +7 -0
- data/History.txt +152 -0
- data/Manifest.txt +5 -3
- data/README.md +6 -0
- data/Rakefile +27 -7
- data/bundler/lib/bundler/build_metadata.rb +2 -2
- data/lib/rubygems.rb +7 -12
- data/lib/rubygems/command_manager.rb +6 -0
- data/lib/rubygems/commands/build_command.rb +28 -13
- data/lib/rubygems/commands/owner_command.rb +2 -0
- data/lib/rubygems/commands/push_command.rb +2 -0
- data/lib/rubygems/commands/setup_command.rb +9 -11
- data/lib/rubygems/commands/uninstall_command.rb +16 -6
- data/lib/rubygems/commands/which_command.rb +1 -3
- data/lib/rubygems/defaults.rb +1 -8
- data/lib/rubygems/dependency.rb +1 -1
- data/lib/rubygems/dependency_installer.rb +1 -2
- data/lib/rubygems/dependency_list.rb +1 -1
- data/lib/rubygems/exceptions.rb +0 -4
- data/lib/rubygems/gemcutter_utilities.rb +9 -5
- data/lib/rubygems/installer.rb +8 -5
- data/lib/rubygems/installer_test_case.rb +2 -2
- data/lib/rubygems/package/tar_header.rb +11 -2
- data/lib/rubygems/rdoc.rb +2 -2
- data/lib/rubygems/remote_fetcher.rb +15 -54
- data/lib/rubygems/request.rb +1 -1
- data/lib/rubygems/request_set/gem_dependency_api.rb +11 -10
- data/lib/rubygems/requirement.rb +0 -4
- data/lib/rubygems/resolver.rb +4 -1
- data/lib/rubygems/s3_uri_signer.rb +183 -0
- data/lib/rubygems/security_option.rb +0 -1
- data/lib/rubygems/specification.rb +21 -23
- data/lib/rubygems/ssl_certs/{index.rubygems.org → rubygems.org}/GlobalSignRootCA.pem +0 -0
- data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem +21 -0
- data/lib/rubygems/stub_specification.rb +1 -2
- data/lib/rubygems/test_case.rb +22 -12
- data/lib/rubygems/uninstaller.rb +1 -1
- data/lib/rubygems/util.rb +12 -0
- data/rubygems-update.gemspec +1 -1
- data/test/rubygems/ca_cert.pem +74 -65
- data/test/rubygems/client.pem +103 -45
- data/test/rubygems/ssl_cert.pem +78 -17
- data/test/rubygems/ssl_key.pem +25 -13
- data/test/rubygems/test_bundled_ca.rb +8 -5
- data/test/rubygems/test_gem.rb +45 -11
- data/test/rubygems/test_gem_bundler_version_finder.rb +4 -0
- data/test/rubygems/test_gem_command_manager.rb +10 -0
- data/test/rubygems/test_gem_commands_build_command.rb +1 -0
- data/test/rubygems/test_gem_commands_push_command.rb +15 -0
- data/test/rubygems/test_gem_commands_setup_command.rb +11 -7
- data/test/rubygems/test_gem_commands_uninstall_command.rb +80 -1
- data/test/rubygems/test_gem_ext_cmake_builder.rb +1 -1
- data/test/rubygems/test_gem_indexer.rb +15 -8
- data/test/rubygems/test_gem_installer.rb +85 -22
- data/test/rubygems/test_gem_package_tar_header.rb +41 -0
- data/test/rubygems/test_gem_rdoc.rb +1 -135
- data/test/rubygems/test_gem_remote_fetcher.rb +133 -14
- data/test/rubygems/test_gem_request.rb +4 -4
- data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +80 -57
- data/test/rubygems/test_gem_security_policy.rb +1 -1
- data/test/rubygems/test_gem_specification.rb +29 -0
- data/test/rubygems/test_gem_stream_ui.rb +2 -2
- data/test/rubygems/test_gem_uninstaller.rb +21 -2
- data/test/rubygems/test_gem_util.rb +8 -0
- data/util/ci +6 -1
- data/util/cops/deprecations.rb +52 -0
- data/util/create_certs.sh +27 -0
- data/util/create_encrypted_key.rb +4 -4
- data/util/update_bundled_ca_certificates.rb +1 -3
- metadata +12 -57
- data/bundler/man/bundle-add.1 +0 -58
- data/bundler/man/bundle-binstubs.1 +0 -40
- data/bundler/man/bundle-check.1 +0 -31
- data/bundler/man/bundle-clean.1 +0 -24
- data/bundler/man/bundle-config.1 +0 -497
- data/bundler/man/bundle-doctor.1 +0 -44
- data/bundler/man/bundle-exec.1 +0 -165
- data/bundler/man/bundle-gem.1 +0 -80
- data/bundler/man/bundle-info.1 +0 -20
- data/bundler/man/bundle-init.1 +0 -25
- data/bundler/man/bundle-inject.1 +0 -33
- data/bundler/man/bundle-install.1 +0 -308
- data/bundler/man/bundle-list.1 +0 -50
- data/bundler/man/bundle-lock.1 +0 -84
- data/bundler/man/bundle-open.1 +0 -32
- data/bundler/man/bundle-outdated.1 +0 -155
- data/bundler/man/bundle-package.1 +0 -55
- data/bundler/man/bundle-platform.1 +0 -61
- data/bundler/man/bundle-pristine.1 +0 -34
- data/bundler/man/bundle-remove.1 +0 -31
- data/bundler/man/bundle-show.1 +0 -23
- data/bundler/man/bundle-update.1 +0 -394
- data/bundler/man/bundle-viz.1 +0 -39
- data/bundler/man/bundle.1 +0 -136
- data/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +0 -23
- data/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +0 -25
|
@@ -15,6 +15,8 @@ https://rubygems.org) and adds it to the index.
|
|
|
15
15
|
|
|
16
16
|
The gem can be removed from the index and deleted from the server using the yank
|
|
17
17
|
command. For further discussion see the help for the yank command.
|
|
18
|
+
|
|
19
|
+
The push command will use ~/.gem/credentials to authenticate to a server, but you can use the RubyGems environment variable GEM_HOST_API_KEY to set the api key to authenticate.
|
|
18
20
|
EOF
|
|
19
21
|
end
|
|
20
22
|
|
|
@@ -128,7 +128,7 @@ By default, this RubyGems will install gem as:
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
module MakeDirs
|
|
131
|
-
def mkdir_p(path,
|
|
131
|
+
def mkdir_p(path, **opts)
|
|
132
132
|
super
|
|
133
133
|
(@mkdirs ||= []) << path
|
|
134
134
|
end
|
|
@@ -164,7 +164,7 @@ By default, this RubyGems will install gem as:
|
|
|
164
164
|
|
|
165
165
|
remove_old_lib_files lib_dir
|
|
166
166
|
|
|
167
|
-
install_default_bundler_gem
|
|
167
|
+
install_default_bundler_gem bin_dir
|
|
168
168
|
|
|
169
169
|
if mode = options[:dir_mode]
|
|
170
170
|
@mkdirs.uniq!
|
|
@@ -240,14 +240,13 @@ By default, this RubyGems will install gem as:
|
|
|
240
240
|
prog_mode = options[:prog_mode] || 0755
|
|
241
241
|
|
|
242
242
|
executables = { 'gem' => 'bin' }
|
|
243
|
-
executables['bundler'] = 'bundler/exe' if Gem::USE_BUNDLER_FOR_GEMDEPS
|
|
244
243
|
executables.each do |tool, path|
|
|
245
244
|
say "Installing #{tool} executable" if @verbose
|
|
246
245
|
|
|
247
246
|
Dir.chdir path do
|
|
248
247
|
bin_files = Dir['*']
|
|
249
248
|
|
|
250
|
-
bin_files -= %w[update_rubygems
|
|
249
|
+
bin_files -= %w[update_rubygems]
|
|
251
250
|
|
|
252
251
|
bin_files.each do |bin_file|
|
|
253
252
|
bin_file_formatted = if options[:format_executable]
|
|
@@ -382,7 +381,7 @@ By default, this RubyGems will install gem as:
|
|
|
382
381
|
return false
|
|
383
382
|
end
|
|
384
383
|
|
|
385
|
-
def install_default_bundler_gem
|
|
384
|
+
def install_default_bundler_gem(bin_dir)
|
|
386
385
|
return unless Gem::USE_BUNDLER_FOR_GEMDEPS
|
|
387
386
|
|
|
388
387
|
specs_dir = Gem::Specification.default_specifications_dir
|
|
@@ -427,13 +426,12 @@ By default, this RubyGems will install gem as:
|
|
|
427
426
|
cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_bin_dir, e)
|
|
428
427
|
end
|
|
429
428
|
|
|
430
|
-
|
|
431
|
-
require 'rubygems/installer'
|
|
429
|
+
require 'rubygems/installer'
|
|
432
430
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
431
|
+
Dir.chdir("bundler") do
|
|
432
|
+
built_gem = Gem::Package.build(bundler_spec)
|
|
433
|
+
installer = Gem::Installer.at(built_gem, env_shebang: options[:env_shebang], install_as_default: true, bin_dir: bin_dir, wrappers: true)
|
|
434
|
+
installer.install
|
|
437
435
|
end
|
|
438
436
|
|
|
439
437
|
say "Bundler #{bundler_spec.version} installed"
|
|
@@ -148,10 +148,13 @@ that is a dependency of an existing gem. You can use the
|
|
|
148
148
|
|
|
149
149
|
def uninstall_specific
|
|
150
150
|
deplist = Gem::DependencyList.new
|
|
151
|
+
original_gem_version = {}
|
|
151
152
|
|
|
152
153
|
get_all_gem_names_and_versions.each do |name, version|
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
original_gem_version[name] = version || options[:version]
|
|
155
|
+
|
|
156
|
+
gem_specs = Gem::Specification.find_all_by_name(name, original_gem_version[name])
|
|
157
|
+
|
|
155
158
|
say("Gem '#{name}' is not installed") if gem_specs.empty?
|
|
156
159
|
gem_specs.each do |spec|
|
|
157
160
|
deplist.add spec
|
|
@@ -160,16 +163,23 @@ that is a dependency of an existing gem. You can use the
|
|
|
160
163
|
|
|
161
164
|
deps = deplist.strongly_connected_components.flatten.reverse
|
|
162
165
|
|
|
166
|
+
gems_to_uninstall = {}
|
|
167
|
+
|
|
163
168
|
deps.each do |dep|
|
|
164
|
-
|
|
165
|
-
|
|
169
|
+
unless gems_to_uninstall[dep.name]
|
|
170
|
+
gems_to_uninstall[dep.name] = true
|
|
171
|
+
|
|
172
|
+
unless original_gem_version[dep.name] == Gem::Requirement.default
|
|
173
|
+
options[:version] = dep.version
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
uninstall_gem(dep.name)
|
|
177
|
+
end
|
|
166
178
|
end
|
|
167
179
|
end
|
|
168
180
|
|
|
169
181
|
def uninstall_gem(gem_name)
|
|
170
182
|
uninstall(gem_name)
|
|
171
|
-
rescue Gem::InstallError
|
|
172
|
-
nil
|
|
173
183
|
rescue Gem::GemNotInHomeException => e
|
|
174
184
|
spec = e.spec
|
|
175
185
|
alert("In order to remove #{spec.name}, please execute:\n" +
|
|
@@ -52,13 +52,11 @@ requiring to see why it does not behave as you expect.
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
# TODO: this is totally redundant and stupid
|
|
56
55
|
paths = find_paths arg, dirs
|
|
57
56
|
|
|
58
57
|
if paths.empty?
|
|
59
58
|
alert_error "Can't find Ruby library file or shared library #{arg}"
|
|
60
|
-
|
|
61
|
-
found &&= false
|
|
59
|
+
found = false
|
|
62
60
|
else
|
|
63
61
|
say paths
|
|
64
62
|
end
|
data/lib/rubygems/defaults.rb
CHANGED
|
@@ -122,15 +122,8 @@ module Gem
|
|
|
122
122
|
end
|
|
123
123
|
end
|
|
124
124
|
|
|
125
|
-
##
|
|
126
|
-
# A wrapper around RUBY_ENGINE const that may not be defined
|
|
127
|
-
|
|
128
125
|
def self.ruby_engine
|
|
129
|
-
|
|
130
|
-
RUBY_ENGINE
|
|
131
|
-
else
|
|
132
|
-
'ruby'
|
|
133
|
-
end
|
|
126
|
+
RUBY_ENGINE
|
|
134
127
|
end
|
|
135
128
|
|
|
136
129
|
##
|
data/lib/rubygems/dependency.rb
CHANGED
|
@@ -281,7 +281,7 @@ class Gem::Dependency
|
|
|
281
281
|
requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
|
|
282
282
|
}.map(&:to_spec)
|
|
283
283
|
|
|
284
|
-
Gem::BundlerVersionFinder.filter!(matches) if name == "bundler".freeze
|
|
284
|
+
Gem::BundlerVersionFinder.filter!(matches) if name == "bundler".freeze && !requirement.specific?
|
|
285
285
|
|
|
286
286
|
if platform_only
|
|
287
287
|
matches.reject! { |spec|
|
|
@@ -213,9 +213,8 @@ class Gem::DependencyInstaller
|
|
|
213
213
|
|
|
214
214
|
if consider_remote?
|
|
215
215
|
begin
|
|
216
|
-
#
|
|
216
|
+
# This is pulled from #spec_for_dependency to allow
|
|
217
217
|
# us to filter tuples before fetching specs.
|
|
218
|
-
#
|
|
219
218
|
tuples, errors = Gem::SpecFetcher.fetcher.search_for_dependency dep
|
|
220
219
|
|
|
221
220
|
if best_only && !tuples.empty?
|
|
@@ -134,7 +134,7 @@ class Gem::DependencyList
|
|
|
134
134
|
end
|
|
135
135
|
|
|
136
136
|
##
|
|
137
|
-
#
|
|
137
|
+
# It is ok to remove a gemspec from the dependency list?
|
|
138
138
|
#
|
|
139
139
|
# If removing the gemspec creates breaks a currently ok dependency, then it
|
|
140
140
|
# is NOT ok to remove the gemspec.
|
data/lib/rubygems/exceptions.rb
CHANGED
|
@@ -7,6 +7,8 @@ require 'rubygems/text'
|
|
|
7
7
|
|
|
8
8
|
module Gem::GemcutterUtilities
|
|
9
9
|
|
|
10
|
+
ERROR_CODE = 1
|
|
11
|
+
|
|
10
12
|
include Gem::Text
|
|
11
13
|
|
|
12
14
|
# TODO: move to Gem::Command
|
|
@@ -41,7 +43,9 @@ module Gem::GemcutterUtilities
|
|
|
41
43
|
# The API key from the command options or from the user's configuration.
|
|
42
44
|
|
|
43
45
|
def api_key
|
|
44
|
-
if
|
|
46
|
+
if ENV["GEM_HOST_API_KEY"]
|
|
47
|
+
ENV["GEM_HOST_API_KEY"]
|
|
48
|
+
elsif options[:key]
|
|
45
49
|
verify_api_key options[:key]
|
|
46
50
|
elsif Gem.configuration.api_keys.key?(host)
|
|
47
51
|
Gem.configuration.api_keys[host]
|
|
@@ -79,7 +83,7 @@ module Gem::GemcutterUtilities
|
|
|
79
83
|
self.host = host if host
|
|
80
84
|
unless self.host
|
|
81
85
|
alert_error "You must specify a gem server"
|
|
82
|
-
terminate_interaction
|
|
86
|
+
terminate_interaction(ERROR_CODE)
|
|
83
87
|
end
|
|
84
88
|
|
|
85
89
|
if allowed_push_host
|
|
@@ -88,7 +92,7 @@ module Gem::GemcutterUtilities
|
|
|
88
92
|
|
|
89
93
|
unless (host_uri.scheme == allowed_host_uri.scheme) && (host_uri.host == allowed_host_uri.host)
|
|
90
94
|
alert_error "#{self.host.inspect} is not allowed by the gemspec, which only allows #{allowed_push_host.inspect}"
|
|
91
|
-
terminate_interaction
|
|
95
|
+
terminate_interaction(ERROR_CODE)
|
|
92
96
|
end
|
|
93
97
|
end
|
|
94
98
|
|
|
@@ -148,7 +152,7 @@ module Gem::GemcutterUtilities
|
|
|
148
152
|
Gem.configuration.api_keys[key]
|
|
149
153
|
else
|
|
150
154
|
alert_error "No such API key. Please add it to your configuration (done automatically on initial `gem push`)."
|
|
151
|
-
terminate_interaction
|
|
155
|
+
terminate_interaction(ERROR_CODE)
|
|
152
156
|
end
|
|
153
157
|
end
|
|
154
158
|
|
|
@@ -172,7 +176,7 @@ module Gem::GemcutterUtilities
|
|
|
172
176
|
message = "#{error_prefix}: #{message}" if error_prefix
|
|
173
177
|
|
|
174
178
|
say clean_text(message)
|
|
175
|
-
terminate_interaction
|
|
179
|
+
terminate_interaction(ERROR_CODE)
|
|
176
180
|
end
|
|
177
181
|
end
|
|
178
182
|
|
data/lib/rubygems/installer.rb
CHANGED
|
@@ -320,8 +320,11 @@ class Gem::Installer
|
|
|
320
320
|
build_extensions
|
|
321
321
|
write_build_info_file
|
|
322
322
|
run_post_build_hooks
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
generate_bin
|
|
323
326
|
|
|
324
|
-
|
|
327
|
+
unless @options[:install_as_default]
|
|
325
328
|
write_spec
|
|
326
329
|
write_cache_file
|
|
327
330
|
end
|
|
@@ -799,7 +802,7 @@ TEXT
|
|
|
799
802
|
# stub & ruby.exe withing same folder. Portable
|
|
800
803
|
<<-TEXT
|
|
801
804
|
@ECHO OFF
|
|
802
|
-
@"%~
|
|
805
|
+
@"%~dp0#{ruby_exe}" "%~dpn0" %*
|
|
803
806
|
TEXT
|
|
804
807
|
elsif bindir.downcase.start_with? rb_topdir.downcase
|
|
805
808
|
# stub within ruby folder, but not standard bin. Portable
|
|
@@ -809,14 +812,14 @@ TEXT
|
|
|
809
812
|
rel = to.relative_path_from from
|
|
810
813
|
<<-TEXT
|
|
811
814
|
@ECHO OFF
|
|
812
|
-
@"%~dp0#{rel}
|
|
815
|
+
@"%~dp0#{rel}/#{ruby_exe}" "%~dpn0" %*
|
|
813
816
|
TEXT
|
|
814
817
|
else
|
|
815
818
|
# outside ruby folder, maybe -user-install or bundler. Portable, but ruby
|
|
816
819
|
# is dependent on PATH
|
|
817
820
|
<<-TEXT
|
|
818
821
|
@ECHO OFF
|
|
819
|
-
|
|
822
|
+
@#{ruby_exe} "%~dpn0" %*
|
|
820
823
|
TEXT
|
|
821
824
|
end
|
|
822
825
|
end
|
|
@@ -857,7 +860,7 @@ TEXT
|
|
|
857
860
|
# without the full gem installed.
|
|
858
861
|
|
|
859
862
|
def extract_bin
|
|
860
|
-
@package.extract_files gem_dir, "
|
|
863
|
+
@package.extract_files gem_dir, "#{spec.bindir}/*"
|
|
861
864
|
end
|
|
862
865
|
|
|
863
866
|
##
|
|
@@ -119,9 +119,9 @@ class Gem::InstallerTestCase < Gem::TestCase
|
|
|
119
119
|
# The executable is also written to the bin dir in @tmpdir and the installed
|
|
120
120
|
# gem directory for +spec+.
|
|
121
121
|
|
|
122
|
-
def util_make_exec(spec = @spec, shebang = "#!/usr/bin/ruby")
|
|
122
|
+
def util_make_exec(spec = @spec, shebang = "#!/usr/bin/ruby", bindir = "bin")
|
|
123
123
|
spec.executables = %w[executable]
|
|
124
|
-
spec.
|
|
124
|
+
spec.bindir = bindir
|
|
125
125
|
|
|
126
126
|
exec_path = spec.bin_file "executable"
|
|
127
127
|
write_file exec_path do |io|
|
|
@@ -107,8 +107,8 @@ class Gem::Package::TarHeader
|
|
|
107
107
|
|
|
108
108
|
new :name => fields.shift,
|
|
109
109
|
:mode => strict_oct(fields.shift),
|
|
110
|
-
:uid =>
|
|
111
|
-
:gid =>
|
|
110
|
+
:uid => oct_or_256based(fields.shift),
|
|
111
|
+
:gid => oct_or_256based(fields.shift),
|
|
112
112
|
:size => strict_oct(fields.shift),
|
|
113
113
|
:mtime => strict_oct(fields.shift),
|
|
114
114
|
:checksum => strict_oct(fields.shift),
|
|
@@ -130,6 +130,15 @@ class Gem::Package::TarHeader
|
|
|
130
130
|
raise ArgumentError, "#{str.inspect} is not an octal string"
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
+
def self.oct_or_256based(str)
|
|
134
|
+
# \x80 flags a positive 256-based number
|
|
135
|
+
# \ff flags a negative 256-based number
|
|
136
|
+
# In case we have a match, parse it as a signed binary value
|
|
137
|
+
# in big-endian order, except that the high-order bit is ignored.
|
|
138
|
+
return str.unpack('N2').last if str =~ /\A[\x80\xff]/n
|
|
139
|
+
strict_oct(str)
|
|
140
|
+
end
|
|
141
|
+
|
|
133
142
|
##
|
|
134
143
|
# Creates a new TarHeader using +vals+
|
|
135
144
|
|
data/lib/rubygems/rdoc.rb
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'rubygems'
|
|
3
3
|
require 'rubygems/request'
|
|
4
|
+
require 'rubygems/request/connection_pools'
|
|
5
|
+
require 'rubygems/s3_uri_signer'
|
|
4
6
|
require 'rubygems/uri_formatter'
|
|
5
7
|
require 'rubygems/user_interaction'
|
|
6
|
-
require 'rubygems/request/connection_pools'
|
|
7
8
|
require 'resolv'
|
|
8
9
|
|
|
9
10
|
##
|
|
@@ -173,7 +174,7 @@ class Gem::RemoteFetcher
|
|
|
173
174
|
path = source_uri.path
|
|
174
175
|
path = File.dirname(path) if File.extname(path) == '.gem'
|
|
175
176
|
|
|
176
|
-
remote_gem_path = correct_for_windows_path(File.join(path, 'gems', gem_file_name))
|
|
177
|
+
remote_gem_path = Gem::Util.correct_for_windows_path(File.join(path, 'gems', gem_file_name))
|
|
177
178
|
|
|
178
179
|
FileUtils.cp(remote_gem_path, local_gem_path)
|
|
179
180
|
rescue Errno::EACCES
|
|
@@ -210,7 +211,7 @@ class Gem::RemoteFetcher
|
|
|
210
211
|
# File Fetcher. Dispatched by +fetch_path+. Use it instead.
|
|
211
212
|
|
|
212
213
|
def fetch_file(uri, *_)
|
|
213
|
-
Gem.read_binary correct_for_windows_path uri.path
|
|
214
|
+
Gem.read_binary Gem::Util.correct_for_windows_path uri.path
|
|
214
215
|
end
|
|
215
216
|
|
|
216
217
|
##
|
|
@@ -275,7 +276,7 @@ class Gem::RemoteFetcher
|
|
|
275
276
|
rescue Timeout::Error
|
|
276
277
|
raise UnknownHostError.new('timed out', uri.to_s)
|
|
277
278
|
rescue IOError, SocketError, SystemCallError,
|
|
278
|
-
|
|
279
|
+
*(OpenSSL::SSL::SSLError if defined?(OpenSSL)) => e
|
|
279
280
|
if e.message =~ /getaddrinfo/
|
|
280
281
|
raise UnknownHostError.new('no such name', uri.to_s)
|
|
281
282
|
else
|
|
@@ -284,10 +285,19 @@ class Gem::RemoteFetcher
|
|
|
284
285
|
end
|
|
285
286
|
|
|
286
287
|
def fetch_s3(uri, mtime = nil, head = false)
|
|
287
|
-
|
|
288
|
+
begin
|
|
289
|
+
public_uri = s3_uri_signer(uri).sign
|
|
290
|
+
rescue Gem::S3URISigner::ConfigurationError, Gem::S3URISigner::InstanceProfileError => e
|
|
291
|
+
raise FetchError.new(e.message, "s3://#{uri.host}")
|
|
292
|
+
end
|
|
288
293
|
fetch_https public_uri, mtime, head
|
|
289
294
|
end
|
|
290
295
|
|
|
296
|
+
# we have our own signing code here to avoid a dependency on the aws-sdk gem
|
|
297
|
+
def s3_uri_signer(uri)
|
|
298
|
+
Gem::S3URISigner.new(uri)
|
|
299
|
+
end
|
|
300
|
+
|
|
291
301
|
##
|
|
292
302
|
# Downloads +uri+ to +path+ if necessary. If no path is given, it just
|
|
293
303
|
# passes the data.
|
|
@@ -317,14 +327,6 @@ class Gem::RemoteFetcher
|
|
|
317
327
|
response['content-length'].to_i
|
|
318
328
|
end
|
|
319
329
|
|
|
320
|
-
def correct_for_windows_path(path)
|
|
321
|
-
if path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':'
|
|
322
|
-
path[1..-1]
|
|
323
|
-
else
|
|
324
|
-
path
|
|
325
|
-
end
|
|
326
|
-
end
|
|
327
|
-
|
|
328
330
|
##
|
|
329
331
|
# Performs a Net::HTTP request of type +request_class+ on +uri+ returning
|
|
330
332
|
# a Net::HTTP response object. request maintains a table of persistent
|
|
@@ -349,31 +351,6 @@ class Gem::RemoteFetcher
|
|
|
349
351
|
@pools.each_value {|pool| pool.close_all}
|
|
350
352
|
end
|
|
351
353
|
|
|
352
|
-
protected
|
|
353
|
-
|
|
354
|
-
# we have our own signing code here to avoid a dependency on the aws-sdk gem
|
|
355
|
-
# fortunately, a simple GET request isn't too complex to sign properly
|
|
356
|
-
def sign_s3_url(uri, expiration = nil)
|
|
357
|
-
require 'base64'
|
|
358
|
-
require 'openssl'
|
|
359
|
-
|
|
360
|
-
id, secret = s3_source_auth uri
|
|
361
|
-
|
|
362
|
-
expiration ||= s3_expiration
|
|
363
|
-
canonical_path = "/#{uri.host}#{uri.path}"
|
|
364
|
-
payload = "GET\n\n\n#{expiration}\n#{canonical_path}"
|
|
365
|
-
digest = OpenSSL::HMAC.digest('sha1', secret, payload)
|
|
366
|
-
# URI.escape is deprecated, and there isn't yet a replacement that does quite what we want
|
|
367
|
-
signature = Base64.encode64(digest).gsub("\n", '').gsub(/[\+\/=]/) { |c| BASE64_URI_TRANSLATE[c] }
|
|
368
|
-
URI.parse("https://#{uri.host}.s3.amazonaws.com#{uri.path}?AWSAccessKeyId=#{id}&Expires=#{expiration}&Signature=#{signature}")
|
|
369
|
-
end
|
|
370
|
-
|
|
371
|
-
def s3_expiration
|
|
372
|
-
(Time.now + 3600).to_i # one hour from now
|
|
373
|
-
end
|
|
374
|
-
|
|
375
|
-
BASE64_URI_TRANSLATE = { '+' => '%2B', '/' => '%2F', '=' => '%3D' }.freeze
|
|
376
|
-
|
|
377
354
|
private
|
|
378
355
|
|
|
379
356
|
def proxy_for(proxy, uri)
|
|
@@ -386,20 +363,4 @@ class Gem::RemoteFetcher
|
|
|
386
363
|
end
|
|
387
364
|
end
|
|
388
365
|
|
|
389
|
-
def s3_source_auth(uri)
|
|
390
|
-
return [uri.user, uri.password] if uri.user && uri.password
|
|
391
|
-
|
|
392
|
-
s3_source = Gem.configuration[:s3_source] || Gem.configuration['s3_source']
|
|
393
|
-
host = uri.host
|
|
394
|
-
raise FetchError.new("no s3_source key exists in .gemrc", "s3://#{host}") unless s3_source
|
|
395
|
-
|
|
396
|
-
auth = s3_source[host] || s3_source[host.to_sym]
|
|
397
|
-
raise FetchError.new("no key for host #{host} in s3_source in .gemrc", "s3://#{host}") unless auth
|
|
398
|
-
|
|
399
|
-
id = auth[:id] || auth['id']
|
|
400
|
-
secret = auth[:secret] || auth['secret']
|
|
401
|
-
raise FetchError.new("s3_source for #{host} missing id or secret", "s3://#{host}") unless id and secret
|
|
402
|
-
|
|
403
|
-
[id, secret]
|
|
404
|
-
end
|
|
405
366
|
end
|