rubygems-update 3.0.3 → 3.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.travis.yml +2 -0
  4. data/CODE_OF_CONDUCT.md +10 -8
  5. data/CONTRIBUTING.md +7 -0
  6. data/History.txt +152 -0
  7. data/Manifest.txt +5 -3
  8. data/README.md +6 -0
  9. data/Rakefile +27 -7
  10. data/bundler/lib/bundler/build_metadata.rb +2 -2
  11. data/lib/rubygems.rb +7 -12
  12. data/lib/rubygems/command_manager.rb +6 -0
  13. data/lib/rubygems/commands/build_command.rb +28 -13
  14. data/lib/rubygems/commands/owner_command.rb +2 -0
  15. data/lib/rubygems/commands/push_command.rb +2 -0
  16. data/lib/rubygems/commands/setup_command.rb +9 -11
  17. data/lib/rubygems/commands/uninstall_command.rb +16 -6
  18. data/lib/rubygems/commands/which_command.rb +1 -3
  19. data/lib/rubygems/defaults.rb +1 -8
  20. data/lib/rubygems/dependency.rb +1 -1
  21. data/lib/rubygems/dependency_installer.rb +1 -2
  22. data/lib/rubygems/dependency_list.rb +1 -1
  23. data/lib/rubygems/exceptions.rb +0 -4
  24. data/lib/rubygems/gemcutter_utilities.rb +9 -5
  25. data/lib/rubygems/installer.rb +8 -5
  26. data/lib/rubygems/installer_test_case.rb +2 -2
  27. data/lib/rubygems/package/tar_header.rb +11 -2
  28. data/lib/rubygems/rdoc.rb +2 -2
  29. data/lib/rubygems/remote_fetcher.rb +15 -54
  30. data/lib/rubygems/request.rb +1 -1
  31. data/lib/rubygems/request_set/gem_dependency_api.rb +11 -10
  32. data/lib/rubygems/requirement.rb +0 -4
  33. data/lib/rubygems/resolver.rb +4 -1
  34. data/lib/rubygems/s3_uri_signer.rb +183 -0
  35. data/lib/rubygems/security_option.rb +0 -1
  36. data/lib/rubygems/specification.rb +21 -23
  37. data/lib/rubygems/ssl_certs/{index.rubygems.org → rubygems.org}/GlobalSignRootCA.pem +0 -0
  38. data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem +21 -0
  39. data/lib/rubygems/stub_specification.rb +1 -2
  40. data/lib/rubygems/test_case.rb +22 -12
  41. data/lib/rubygems/uninstaller.rb +1 -1
  42. data/lib/rubygems/util.rb +12 -0
  43. data/rubygems-update.gemspec +1 -1
  44. data/test/rubygems/ca_cert.pem +74 -65
  45. data/test/rubygems/client.pem +103 -45
  46. data/test/rubygems/ssl_cert.pem +78 -17
  47. data/test/rubygems/ssl_key.pem +25 -13
  48. data/test/rubygems/test_bundled_ca.rb +8 -5
  49. data/test/rubygems/test_gem.rb +45 -11
  50. data/test/rubygems/test_gem_bundler_version_finder.rb +4 -0
  51. data/test/rubygems/test_gem_command_manager.rb +10 -0
  52. data/test/rubygems/test_gem_commands_build_command.rb +1 -0
  53. data/test/rubygems/test_gem_commands_push_command.rb +15 -0
  54. data/test/rubygems/test_gem_commands_setup_command.rb +11 -7
  55. data/test/rubygems/test_gem_commands_uninstall_command.rb +80 -1
  56. data/test/rubygems/test_gem_ext_cmake_builder.rb +1 -1
  57. data/test/rubygems/test_gem_indexer.rb +15 -8
  58. data/test/rubygems/test_gem_installer.rb +85 -22
  59. data/test/rubygems/test_gem_package_tar_header.rb +41 -0
  60. data/test/rubygems/test_gem_rdoc.rb +1 -135
  61. data/test/rubygems/test_gem_remote_fetcher.rb +133 -14
  62. data/test/rubygems/test_gem_request.rb +4 -4
  63. data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +80 -57
  64. data/test/rubygems/test_gem_security_policy.rb +1 -1
  65. data/test/rubygems/test_gem_specification.rb +29 -0
  66. data/test/rubygems/test_gem_stream_ui.rb +2 -2
  67. data/test/rubygems/test_gem_uninstaller.rb +21 -2
  68. data/test/rubygems/test_gem_util.rb +8 -0
  69. data/util/ci +6 -1
  70. data/util/cops/deprecations.rb +52 -0
  71. data/util/create_certs.sh +27 -0
  72. data/util/create_encrypted_key.rb +4 -4
  73. data/util/update_bundled_ca_certificates.rb +1 -3
  74. metadata +12 -57
  75. data/bundler/man/bundle-add.1 +0 -58
  76. data/bundler/man/bundle-binstubs.1 +0 -40
  77. data/bundler/man/bundle-check.1 +0 -31
  78. data/bundler/man/bundle-clean.1 +0 -24
  79. data/bundler/man/bundle-config.1 +0 -497
  80. data/bundler/man/bundle-doctor.1 +0 -44
  81. data/bundler/man/bundle-exec.1 +0 -165
  82. data/bundler/man/bundle-gem.1 +0 -80
  83. data/bundler/man/bundle-info.1 +0 -20
  84. data/bundler/man/bundle-init.1 +0 -25
  85. data/bundler/man/bundle-inject.1 +0 -33
  86. data/bundler/man/bundle-install.1 +0 -308
  87. data/bundler/man/bundle-list.1 +0 -50
  88. data/bundler/man/bundle-lock.1 +0 -84
  89. data/bundler/man/bundle-open.1 +0 -32
  90. data/bundler/man/bundle-outdated.1 +0 -155
  91. data/bundler/man/bundle-package.1 +0 -55
  92. data/bundler/man/bundle-platform.1 +0 -61
  93. data/bundler/man/bundle-pristine.1 +0 -34
  94. data/bundler/man/bundle-remove.1 +0 -31
  95. data/bundler/man/bundle-show.1 +0 -23
  96. data/bundler/man/bundle-update.1 +0 -394
  97. data/bundler/man/bundle-viz.1 +0 -39
  98. data/bundler/man/bundle.1 +0 -136
  99. data/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +0 -23
  100. data/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +0 -25
@@ -63,6 +63,8 @@ permission to.
63
63
  end
64
64
 
65
65
  def show_owners(name)
66
+ Gem.load_yaml
67
+
66
68
  response = rubygems_api_request :get, "api/v1/gems/#{name}/owners.yaml" do |request|
67
69
  request.add_field "Authorization", api_key
68
70
  end
@@ -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, *opts)
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 bundler bundle_ruby]
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
- if Gem.win_platform?
431
- require 'rubygems/installer'
429
+ require 'rubygems/installer'
432
430
 
433
- installer = Gem::Installer.for_spec bundler_spec
434
- bundler_spec.executables.each do |e|
435
- installer.generate_windows_script e, bundler_spec.bin_dir
436
- end
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
- requirement = Array(version || options[:version])
154
- gem_specs = Gem::Specification.find_all_by_name(name, *requirement)
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
- options[:version] = dep.version
165
- uninstall_gem(dep.name)
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
@@ -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
- if defined? RUBY_ENGINE
130
- RUBY_ENGINE
131
- else
132
- 'ruby'
133
- end
126
+ RUBY_ENGINE
134
127
  end
135
128
 
136
129
  ##
@@ -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
- # TODO this is pulled from #spec_for_dependency to allow
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
- # Is is ok to remove a gemspec from the dependency list?
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.
@@ -1,8 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # TODO: the documentation in here is terrible.
3
- #
4
- # Each exception needs a brief description and the scenarios where it is
5
- # likely to be raised
6
2
 
7
3
  require 'rubygems/deprecate'
8
4
 
@@ -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 options[:key]
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 1 # TODO: question this
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 1
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 1 # TODO: question this
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 1 # TODO: question this
179
+ terminate_interaction(ERROR_CODE)
176
180
  end
177
181
  end
178
182
 
@@ -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
- generate_bin
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
- @"%~dp0ruby.exe" "%~dpn0" %*
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}/ruby.exe" "%~dpn0" %*
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
- @ruby.exe "%~dpn0" %*
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, "bin/*"
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.files << 'bin/executable'
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 => strict_oct(fields.shift),
111
- :gid => strict_oct(fields.shift),
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
@@ -18,7 +18,7 @@ begin
18
18
  module Gem
19
19
  RDoc = ::RDoc::RubygemsHook
20
20
  end
21
+
22
+ Gem.done_installing(&Gem::RDoc.method(:generation_hook))
21
23
  rescue LoadError
22
24
  end
23
-
24
- Gem.done_installing(&Gem::RDoc.method(:generation_hook))
@@ -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
- *(OpenSSL::SSL::SSLError if defined?(OpenSSL)) => e
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
- public_uri = sign_s3_url(uri)
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