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.
- 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 +180 -0
- data/Manifest.txt +5 -3
- data/README.md +6 -0
- data/Rakefile +33 -7
- data/bundler/CHANGELOG.md +11 -0
- data/bundler/lib/bundler/build_metadata.rb +2 -2
- data/bundler/lib/bundler/rubygems_gem_installer.rb +7 -0
- data/bundler/lib/bundler/source/metadata.rb +2 -3
- data/bundler/lib/bundler/version.rb +1 -1
- data/bundler/man/bundle.ronn +3 -0
- data/lib/rubygems/command_manager.rb +12 -4
- data/lib/rubygems/commands/build_command.rb +28 -13
- data/lib/rubygems/commands/owner_command.rb +6 -1
- data/lib/rubygems/commands/push_command.rb +2 -0
- data/lib/rubygems/commands/setup_command.rb +14 -16
- 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 +14 -7
- data/lib/rubygems/install_update_options.rb +1 -1
- data/lib/rubygems/installer.rb +37 -15
- data/lib/rubygems/installer_test_case.rb +2 -2
- data/lib/rubygems/package/old.rb +1 -1
- data/lib/rubygems/package/tar_header.rb +11 -2
- data/lib/rubygems/package.rb +12 -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 +16 -5
- 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/rubygems.org/GlobalSignRootCA_R3.pem +21 -0
- data/lib/rubygems/stub_specification.rb +1 -2
- data/lib/rubygems/test_case.rb +23 -12
- data/lib/rubygems/uninstaller.rb +1 -1
- data/lib/rubygems/user_interaction.rb +4 -1
- data/lib/rubygems/util.rb +13 -1
- data/lib/rubygems.rb +8 -13
- 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 +55 -13
- 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 +191 -22
- data/test/rubygems/test_gem_package.rb +37 -0
- data/test/rubygems/test_gem_package_tar_header.rb +41 -0
- data/test/rubygems/test_gem_package_tar_writer.rb +3 -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_requirement.rb +6 -0
- data/test/rubygems/test_gem_security_policy.rb +1 -1
- data/test/rubygems/test_gem_specification.rb +32 -0
- data/test/rubygems/test_gem_stream_ui.rb +2 -2
- data/test/rubygems/test_gem_text.rb +5 -0
- data/test/rubygems/test_gem_uninstaller.rb +21 -2
- data/test/rubygems/test_gem_util.rb +25 -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 -10
- 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
- /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,
|
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]
|
@@ -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 =>
|
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 =>
|
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 =>
|
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
|
-
|
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"
|
@@ -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 =>
|
450
|
-
mkdir_p bin_dir, :mode =>
|
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
|
-
|
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
@@ -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
|
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
|
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
|
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
|
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
|
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", '--
|
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|
|
data/lib/rubygems/installer.rb
CHANGED
@@ -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 &&
|
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
|
-
|
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] &&
|
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',
|
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] &&
|
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
|
729
|
-
|
730
|
-
|
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
|
-
@"%~
|
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}
|
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
|
-
|
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, "
|
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
|
-
|
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
|
-
|
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 &&
|
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.
|
124
|
+
spec.bindir = bindir
|
125
125
|
|
126
126
|
exec_path = spec.bin_file "executable"
|
127
127
|
write_file exec_path do |io|
|
data/lib/rubygems/package/old.rb
CHANGED
@@ -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 &&
|
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 =>
|
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/package.rb
CHANGED
@@ -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 &&
|
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 ?
|
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
@@ -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
|