rubygems-update 3.0.0 → 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.
Files changed (89) 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 +180 -0
  7. data/Manifest.txt +5 -3
  8. data/README.md +6 -0
  9. data/Rakefile +33 -7
  10. data/bundler/CHANGELOG.md +11 -0
  11. data/bundler/lib/bundler/build_metadata.rb +2 -2
  12. data/bundler/lib/bundler/rubygems_gem_installer.rb +7 -0
  13. data/bundler/lib/bundler/source/metadata.rb +2 -3
  14. data/bundler/lib/bundler/version.rb +1 -1
  15. data/bundler/man/bundle.ronn +3 -0
  16. data/lib/rubygems/command_manager.rb +12 -4
  17. data/lib/rubygems/commands/build_command.rb +28 -13
  18. data/lib/rubygems/commands/owner_command.rb +6 -1
  19. data/lib/rubygems/commands/push_command.rb +2 -0
  20. data/lib/rubygems/commands/setup_command.rb +14 -16
  21. data/lib/rubygems/commands/uninstall_command.rb +16 -6
  22. data/lib/rubygems/commands/which_command.rb +1 -3
  23. data/lib/rubygems/defaults.rb +1 -8
  24. data/lib/rubygems/dependency.rb +1 -1
  25. data/lib/rubygems/dependency_installer.rb +1 -2
  26. data/lib/rubygems/dependency_list.rb +1 -1
  27. data/lib/rubygems/exceptions.rb +0 -4
  28. data/lib/rubygems/gemcutter_utilities.rb +14 -7
  29. data/lib/rubygems/install_update_options.rb +1 -1
  30. data/lib/rubygems/installer.rb +37 -15
  31. data/lib/rubygems/installer_test_case.rb +2 -2
  32. data/lib/rubygems/package/old.rb +1 -1
  33. data/lib/rubygems/package/tar_header.rb +11 -2
  34. data/lib/rubygems/package.rb +12 -2
  35. data/lib/rubygems/rdoc.rb +2 -2
  36. data/lib/rubygems/remote_fetcher.rb +15 -54
  37. data/lib/rubygems/request.rb +1 -1
  38. data/lib/rubygems/request_set/gem_dependency_api.rb +11 -10
  39. data/lib/rubygems/requirement.rb +16 -5
  40. data/lib/rubygems/resolver.rb +4 -1
  41. data/lib/rubygems/s3_uri_signer.rb +183 -0
  42. data/lib/rubygems/security_option.rb +0 -1
  43. data/lib/rubygems/specification.rb +21 -23
  44. data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem +21 -0
  45. data/lib/rubygems/stub_specification.rb +1 -2
  46. data/lib/rubygems/test_case.rb +23 -12
  47. data/lib/rubygems/uninstaller.rb +1 -1
  48. data/lib/rubygems/user_interaction.rb +4 -1
  49. data/lib/rubygems/util.rb +13 -1
  50. data/lib/rubygems.rb +8 -13
  51. data/rubygems-update.gemspec +1 -1
  52. data/test/rubygems/ca_cert.pem +74 -65
  53. data/test/rubygems/client.pem +103 -45
  54. data/test/rubygems/ssl_cert.pem +78 -17
  55. data/test/rubygems/ssl_key.pem +25 -13
  56. data/test/rubygems/test_bundled_ca.rb +8 -5
  57. data/test/rubygems/test_gem.rb +55 -13
  58. data/test/rubygems/test_gem_bundler_version_finder.rb +4 -0
  59. data/test/rubygems/test_gem_command_manager.rb +10 -0
  60. data/test/rubygems/test_gem_commands_build_command.rb +1 -0
  61. data/test/rubygems/test_gem_commands_push_command.rb +15 -0
  62. data/test/rubygems/test_gem_commands_setup_command.rb +11 -7
  63. data/test/rubygems/test_gem_commands_uninstall_command.rb +80 -1
  64. data/test/rubygems/test_gem_ext_cmake_builder.rb +1 -1
  65. data/test/rubygems/test_gem_indexer.rb +15 -8
  66. data/test/rubygems/test_gem_installer.rb +191 -22
  67. data/test/rubygems/test_gem_package.rb +37 -0
  68. data/test/rubygems/test_gem_package_tar_header.rb +41 -0
  69. data/test/rubygems/test_gem_package_tar_writer.rb +3 -0
  70. data/test/rubygems/test_gem_rdoc.rb +1 -135
  71. data/test/rubygems/test_gem_remote_fetcher.rb +133 -14
  72. data/test/rubygems/test_gem_request.rb +4 -4
  73. data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +80 -57
  74. data/test/rubygems/test_gem_requirement.rb +6 -0
  75. data/test/rubygems/test_gem_security_policy.rb +1 -1
  76. data/test/rubygems/test_gem_specification.rb +32 -0
  77. data/test/rubygems/test_gem_stream_ui.rb +2 -2
  78. data/test/rubygems/test_gem_text.rb +5 -0
  79. data/test/rubygems/test_gem_uninstaller.rb +21 -2
  80. data/test/rubygems/test_gem_util.rb +25 -0
  81. data/util/ci +6 -1
  82. data/util/cops/deprecations.rb +52 -0
  83. data/util/create_certs.sh +27 -0
  84. data/util/create_encrypted_key.rb +4 -4
  85. data/util/update_bundled_ca_certificates.rb +1 -3
  86. metadata +12 -10
  87. data/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +0 -23
  88. data/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +0 -25
  89. /data/lib/rubygems/ssl_certs/{index.rubygems.org → rubygems.org}/GlobalSignRootCA.pem +0 -0
@@ -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]
@@ -312,7 +311,7 @@ By default, this RubyGems will install gem as:
312
311
  dest_file = File.join dest_dir, file
313
312
  dest_dir = File.dirname dest_file
314
313
  unless File.directory? dest_dir
315
- mkdir_p dest_dir, :mode => 0700
314
+ mkdir_p dest_dir, :mode => 0755
316
315
  end
317
316
 
318
317
  install file, dest_file, :mode => options[:data_mode] || 0644
@@ -382,12 +381,12 @@ 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
389
388
  specs_dir = File.join(options[:destdir], specs_dir) unless Gem.win_platform?
390
- mkdir_p specs_dir, :mode => 0700
389
+ mkdir_p specs_dir, :mode => 0755
391
390
 
392
391
  # Workaround for non-git environment.
393
392
  gemspec = File.open('bundler/bundler.gemspec', 'rb'){|f| f.read.gsub(/`git ls-files -z`/, "''") }
@@ -422,18 +421,17 @@ By default, this RubyGems will install gem as:
422
421
 
423
422
  bundler_bin_dir = bundler_spec.bin_dir
424
423
  bundler_bin_dir = File.join(options[:destdir], bundler_bin_dir) unless Gem.win_platform?
425
- mkdir_p bundler_bin_dir, :mode => 0700
424
+ mkdir_p bundler_bin_dir, :mode => 0755
426
425
  bundler_spec.executables.each do |e|
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"
@@ -446,8 +444,8 @@ By default, this RubyGems will install gem as:
446
444
  lib_dir, bin_dir = generate_default_dirs(install_destdir)
447
445
  end
448
446
 
449
- mkdir_p lib_dir, :mode => 0700
450
- mkdir_p bin_dir, :mode => 0700
447
+ mkdir_p lib_dir, :mode => 0755
448
+ mkdir_p bin_dir, :mode => 0755
451
449
 
452
450
  return lib_dir, bin_dir
453
451
  end
@@ -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
 
@@ -1,11 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
  require 'rubygems/remote_fetcher'
3
+ require 'rubygems/text'
3
4
 
4
5
  ##
5
6
  # Utility methods for using the RubyGems API.
6
7
 
7
8
  module Gem::GemcutterUtilities
8
9
 
10
+ ERROR_CODE = 1
11
+
12
+ include Gem::Text
13
+
9
14
  # TODO: move to Gem::Command
10
15
  OptionParser.accept Symbol do |value|
11
16
  value.to_sym
@@ -38,7 +43,9 @@ module Gem::GemcutterUtilities
38
43
  # The API key from the command options or from the user's configuration.
39
44
 
40
45
  def api_key
41
- if options[:key]
46
+ if ENV["GEM_HOST_API_KEY"]
47
+ ENV["GEM_HOST_API_KEY"]
48
+ elsif options[:key]
42
49
  verify_api_key options[:key]
43
50
  elsif Gem.configuration.api_keys.key?(host)
44
51
  Gem.configuration.api_keys[host]
@@ -76,7 +83,7 @@ module Gem::GemcutterUtilities
76
83
  self.host = host if host
77
84
  unless self.host
78
85
  alert_error "You must specify a gem server"
79
- terminate_interaction 1 # TODO: question this
86
+ terminate_interaction(ERROR_CODE)
80
87
  end
81
88
 
82
89
  if allowed_push_host
@@ -85,7 +92,7 @@ module Gem::GemcutterUtilities
85
92
 
86
93
  unless (host_uri.scheme == allowed_host_uri.scheme) && (host_uri.host == allowed_host_uri.host)
87
94
  alert_error "#{self.host.inspect} is not allowed by the gemspec, which only allows #{allowed_push_host.inspect}"
88
- terminate_interaction 1
95
+ terminate_interaction(ERROR_CODE)
89
96
  end
90
97
  end
91
98
 
@@ -145,7 +152,7 @@ module Gem::GemcutterUtilities
145
152
  Gem.configuration.api_keys[key]
146
153
  else
147
154
  alert_error "No such API key. Please add it to your configuration (done automatically on initial `gem push`)."
148
- terminate_interaction 1 # TODO: question this
155
+ terminate_interaction(ERROR_CODE)
149
156
  end
150
157
  end
151
158
 
@@ -162,14 +169,14 @@ module Gem::GemcutterUtilities
162
169
  if block_given?
163
170
  yield response
164
171
  else
165
- say response.body
172
+ say clean_text(response.body)
166
173
  end
167
174
  else
168
175
  message = response.body
169
176
  message = "#{error_prefix}: #{message}" if error_prefix
170
177
 
171
- say message
172
- terminate_interaction 1 # TODO: question this
178
+ say clean_text(message)
179
+ terminate_interaction(ERROR_CODE)
173
180
  end
174
181
  end
175
182
 
@@ -30,7 +30,7 @@ module Gem::InstallUpdateOptions
30
30
  options[:bin_dir] = File.expand_path(value)
31
31
  end
32
32
 
33
- add_option(:"Install/Update", '--[no-]document [TYPES]', Array,
33
+ add_option(:"Install/Update", '--document [TYPES]', Array,
34
34
  'Generate documentation for installed gems',
35
35
  'List the documentation types you wish to',
36
36
  'generate. For example: rdoc,ri') do |value, options|
@@ -309,7 +309,7 @@ class Gem::Installer
309
309
  FileUtils.rm_rf spec.extension_dir
310
310
 
311
311
  dir_mode = options[:dir_mode]
312
- FileUtils.mkdir_p gem_dir, :mode => dir_mode && 0700
312
+ FileUtils.mkdir_p gem_dir, :mode => dir_mode && 0755
313
313
 
314
314
  if @options[:install_as_default]
315
315
  extract_bin
@@ -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
@@ -481,7 +484,7 @@ class Gem::Installer
481
484
  return if spec.executables.nil? or spec.executables.empty?
482
485
 
483
486
  begin
484
- Dir.mkdir @bin_dir, *[options[:dir_mode] && 0700].compact
487
+ Dir.mkdir @bin_dir, *[options[:dir_mode] && 0755].compact
485
488
  rescue SystemCallError
486
489
  raise unless File.directory? @bin_dir
487
490
  end
@@ -525,7 +528,7 @@ class Gem::Installer
525
528
 
526
529
  FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
527
530
 
528
- File.open bin_script_path, 'wb', 0700 do |file|
531
+ File.open bin_script_path, 'wb', 0755 do |file|
529
532
  file.print app_script_text(filename)
530
533
  file.chmod(options[:prog_mode] || 0755)
531
534
  end
@@ -720,14 +723,31 @@ class Gem::Installer
720
723
  end
721
724
 
722
725
  def verify_gem_home(unpack = false) # :nodoc:
723
- FileUtils.mkdir_p gem_home, :mode => options[:dir_mode] && 0700
726
+ FileUtils.mkdir_p gem_home, :mode => options[:dir_mode] && 0755
724
727
  raise Gem::FilePermissionError, gem_home unless
725
728
  unpack or File.writable?(gem_home)
726
729
  end
727
730
 
728
- def verify_spec_name
729
- return if spec.name =~ Gem::Specification::VALID_NAME_PATTERN
730
- raise Gem::InstallError, "#{spec} has an invalid name"
731
+ def verify_spec
732
+ unless spec.name =~ Gem::Specification::VALID_NAME_PATTERN
733
+ raise Gem::InstallError, "#{spec} has an invalid name"
734
+ end
735
+
736
+ if spec.raw_require_paths.any?{|path| path =~ /\R/ }
737
+ raise Gem::InstallError, "#{spec} has an invalid require_paths"
738
+ end
739
+
740
+ if spec.extensions.any?{|ext| ext =~ /\R/ }
741
+ raise Gem::InstallError, "#{spec} has an invalid extensions"
742
+ end
743
+
744
+ unless spec.specification_version.to_s =~ /\A\d+\z/
745
+ raise Gem::InstallError, "#{spec} has an invalid specification_version"
746
+ end
747
+
748
+ if spec.dependencies.any? {|dep| dep.type =~ /\R/ || dep.name =~ /\R/ }
749
+ raise Gem::InstallError, "#{spec} has an invalid dependencies"
750
+ end
731
751
  end
732
752
 
733
753
  ##
@@ -782,7 +802,7 @@ TEXT
782
802
  # stub & ruby.exe withing same folder. Portable
783
803
  <<-TEXT
784
804
  @ECHO OFF
785
- @"%~dp0ruby.exe" "%~dpn0" %*
805
+ @"%~dp0#{ruby_exe}" "%~dpn0" %*
786
806
  TEXT
787
807
  elsif bindir.downcase.start_with? rb_topdir.downcase
788
808
  # stub within ruby folder, but not standard bin. Portable
@@ -792,14 +812,14 @@ TEXT
792
812
  rel = to.relative_path_from from
793
813
  <<-TEXT
794
814
  @ECHO OFF
795
- @"%~dp0#{rel}/ruby.exe" "%~dpn0" %*
815
+ @"%~dp0#{rel}/#{ruby_exe}" "%~dpn0" %*
796
816
  TEXT
797
817
  else
798
818
  # outside ruby folder, maybe -user-install or bundler. Portable, but ruby
799
819
  # is dependent on PATH
800
820
  <<-TEXT
801
821
  @ECHO OFF
802
- @ruby.exe "%~dpn0" %*
822
+ @#{ruby_exe} "%~dpn0" %*
803
823
  TEXT
804
824
  end
805
825
  end
@@ -840,7 +860,7 @@ TEXT
840
860
  # without the full gem installed.
841
861
 
842
862
  def extract_bin
843
- @package.extract_files gem_dir, "bin/*"
863
+ @package.extract_files gem_dir, "#{spec.bindir}/*"
844
864
  end
845
865
 
846
866
  ##
@@ -876,9 +896,11 @@ TEXT
876
896
  def pre_install_checks
877
897
  verify_gem_home options[:unpack]
878
898
 
879
- ensure_loadable_spec
899
+ # The name and require_paths must be verified first, since it could contain
900
+ # ruby code that would be eval'ed in #ensure_loadable_spec
901
+ verify_spec
880
902
 
881
- verify_spec_name
903
+ ensure_loadable_spec
882
904
 
883
905
  if options[:install_as_default]
884
906
  Gem.ensure_default_gem_subdirectories gem_home
@@ -905,7 +927,7 @@ TEXT
905
927
  build_info_dir = File.join gem_home, 'build_info'
906
928
 
907
929
  dir_mode = options[:dir_mode]
908
- FileUtils.mkdir_p build_info_dir, :mode => dir_mode && 0700
930
+ FileUtils.mkdir_p build_info_dir, :mode => dir_mode && 0755
909
931
 
910
932
  build_info_file = File.join build_info_dir, "#{spec.full_name}.info"
911
933
 
@@ -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|
@@ -78,7 +78,7 @@ class Gem::Package::Old < Gem::Package
78
78
 
79
79
  FileUtils.rm_rf destination
80
80
 
81
- FileUtils.mkdir_p File.dirname(destination), :mode => dir_mode && 0700
81
+ FileUtils.mkdir_p File.dirname(destination), :mode => dir_mode && 0755
82
82
 
83
83
  File.open destination, 'wb', file_mode(entry['mode']) do |out|
84
84
  out.write file_data
@@ -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
 
@@ -357,7 +357,7 @@ EOM
357
357
  def extract_files(destination_dir, pattern = "*")
358
358
  verify unless @spec
359
359
 
360
- FileUtils.mkdir_p destination_dir, :mode => dir_mode && 0700
360
+ FileUtils.mkdir_p destination_dir, :mode => dir_mode && 0755
361
361
 
362
362
  @gem.with_read_io do |io|
363
363
  reader = Gem::Package::TarReader.new io
@@ -394,7 +394,7 @@ EOM
394
394
  FileUtils.rm_rf destination
395
395
 
396
396
  mkdir_options = {}
397
- mkdir_options[:mode] = dir_mode ? 0700 : (entry.header.mode if entry.directory?)
397
+ mkdir_options[:mode] = dir_mode ? 0755 : (entry.header.mode if entry.directory?)
398
398
  mkdir =
399
399
  if entry.directory?
400
400
  destination
@@ -456,6 +456,16 @@ EOM
456
456
  raise Gem::Package::PathError.new(destination, destination_dir) unless
457
457
  destination.start_with? destination_dir + '/'
458
458
 
459
+ begin
460
+ real_destination = File.expand_path(File.realpath(destination))
461
+ rescue
462
+ # it's fine if the destination doesn't exist, because rm -rf'ing it can't cause any damage
463
+ nil
464
+ else
465
+ raise Gem::Package::PathError.new(real_destination, destination_dir) unless
466
+ real_destination.start_with? destination_dir + '/'
467
+ end
468
+
459
469
  destination.untaint
460
470
  destination
461
471
  end
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
@@ -283,7 +283,7 @@ class Gem::Request
283
283
  end
284
284
  ua << ")"
285
285
 
286
- ua << " #{RUBY_ENGINE}" if defined?(RUBY_ENGINE) and RUBY_ENGINE != 'ruby'
286
+ ua << " #{RUBY_ENGINE}" if RUBY_ENGINE != 'ruby'
287
287
 
288
288
  ua
289
289
  end