rubygems-update 3.0.4 → 3.0.5
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/History.txt +53 -0
- data/Manifest.txt +3 -1
- data/Rakefile +7 -5
- data/bundler/lib/bundler/build_metadata.rb +1 -1
- data/lib/rubygems.rb +6 -12
- data/lib/rubygems/commands/environment_command.rb +0 -3
- data/lib/rubygems/commands/push_command.rb +2 -0
- 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_installer.rb +1 -2
- data/lib/rubygems/exceptions.rb +0 -4
- data/lib/rubygems/gemcutter_utilities.rb +9 -5
- data/lib/rubygems/installer.rb +1 -1
- data/lib/rubygems/installer_test_case.rb +2 -2
- data/lib/rubygems/package/tar_header.rb +11 -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 +3 -5
- data/lib/rubygems/s3_uri_signer.rb +175 -0
- data/lib/rubygems/security_option.rb +0 -1
- data/lib/rubygems/specification.rb +0 -1
- data/lib/rubygems/stub_specification.rb +1 -2
- data/lib/rubygems/test_case.rb +8 -4
- data/lib/rubygems/util.rb +12 -0
- data/rubygems-update.gemspec +1 -1
- data/test/rubygems/test_gem.rb +6 -3
- data/test/rubygems/test_gem_commands_environment_command.rb +0 -11
- data/test/rubygems/test_gem_commands_push_command.rb +15 -0
- data/test/rubygems/test_gem_commands_uninstall_command.rb +80 -1
- data/test/rubygems/test_gem_indexer.rb +8 -8
- data/test/rubygems/test_gem_installer.rb +48 -17
- data/test/rubygems/test_gem_package_tar_header.rb +41 -0
- 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 +20 -30
- data/test/rubygems/test_gem_util.rb +8 -0
- data/util/cops/deprecations.rb +52 -0
- data/util/create_certs.sh +27 -0
- metadata +5 -3
- data/lib/rubygems/compatibility.rb +0 -40
data/lib/rubygems/request.rb
CHANGED
@@ -782,7 +782,7 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
|
|
782
782
|
# You may also provide +engine:+ and +engine_version:+ options to restrict
|
783
783
|
# this gem dependencies file to a particular ruby engine and its engine
|
784
784
|
# version. This matching is performed by using the RUBY_ENGINE and
|
785
|
-
#
|
785
|
+
# RUBY_ENGINE_VERSION constants.
|
786
786
|
|
787
787
|
def ruby(version, options = {})
|
788
788
|
engine = options[:engine]
|
@@ -809,11 +809,9 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
|
|
809
809
|
end
|
810
810
|
|
811
811
|
if engine_version
|
812
|
-
|
813
|
-
|
814
|
-
if engine_version != my_engine_version
|
812
|
+
if engine_version != RUBY_ENGINE_VERSION
|
815
813
|
message =
|
816
|
-
"Your Ruby engine version is #{Gem.ruby_engine} #{
|
814
|
+
"Your Ruby engine version is #{Gem.ruby_engine} #{RUBY_ENGINE_VERSION}, " +
|
817
815
|
"but your #{gem_deps_file} requires #{engine} #{engine_version}"
|
818
816
|
|
819
817
|
raise Gem::RubyVersionMismatch, message
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'digest'
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
##
|
6
|
+
# S3URISigner implements AWS SigV4 for S3 Source to avoid a dependency on the aws-sdk-* gems
|
7
|
+
# More on AWS SigV4: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
|
8
|
+
class Gem::S3URISigner
|
9
|
+
|
10
|
+
class ConfigurationError < Gem::Exception
|
11
|
+
|
12
|
+
def initialize(message)
|
13
|
+
super message
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s # :nodoc:
|
17
|
+
"#{super}"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class InstanceProfileError < Gem::Exception
|
23
|
+
|
24
|
+
def initialize(message)
|
25
|
+
super message
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s # :nodoc:
|
29
|
+
"#{super}"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_accessor :uri
|
35
|
+
|
36
|
+
def initialize(uri)
|
37
|
+
@uri = uri
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Signs S3 URI using query-params according to the reference: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
|
42
|
+
def sign(expiration = 86400)
|
43
|
+
s3_config = fetch_s3_config
|
44
|
+
|
45
|
+
current_time = Time.now.utc
|
46
|
+
date_time = current_time.strftime("%Y%m%dT%H%m%SZ")
|
47
|
+
date = date_time[0,8]
|
48
|
+
|
49
|
+
credential_info = "#{date}/#{s3_config.region}/s3/aws4_request"
|
50
|
+
canonical_host = "#{uri.host}.s3.#{s3_config.region}.amazonaws.com"
|
51
|
+
|
52
|
+
query_params = generate_canonical_query_params(s3_config, date_time, credential_info, expiration)
|
53
|
+
canonical_request = generate_canonical_request(canonical_host, query_params)
|
54
|
+
string_to_sign = generate_string_to_sign(date_time, credential_info, canonical_request)
|
55
|
+
signature = generate_signature(s3_config, date, string_to_sign)
|
56
|
+
|
57
|
+
URI.parse("https://#{canonical_host}#{uri.path}?#{query_params}&X-Amz-Signature=#{signature}")
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
S3Config = Struct.new :access_key_id, :secret_access_key, :security_token, :region
|
63
|
+
|
64
|
+
def generate_canonical_query_params(s3_config, date_time, credential_info, expiration)
|
65
|
+
canonical_params = {}
|
66
|
+
canonical_params["X-Amz-Algorithm"] = "AWS4-HMAC-SHA256"
|
67
|
+
canonical_params["X-Amz-Credential"] = "#{s3_config.access_key_id}/#{credential_info}"
|
68
|
+
canonical_params["X-Amz-Date"] = date_time
|
69
|
+
canonical_params["X-Amz-Expires"] = expiration.to_s
|
70
|
+
canonical_params["X-Amz-SignedHeaders"] = "host"
|
71
|
+
canonical_params["X-Amz-Security-Token"] = s3_config.security_token if s3_config.security_token
|
72
|
+
|
73
|
+
# Sorting is required to generate proper signature
|
74
|
+
canonical_params.sort.to_h.map do |key, value|
|
75
|
+
"#{base64_uri_escape(key)}=#{base64_uri_escape(value)}"
|
76
|
+
end.join("&")
|
77
|
+
end
|
78
|
+
|
79
|
+
def generate_canonical_request(canonical_host, query_params)
|
80
|
+
[
|
81
|
+
"GET",
|
82
|
+
uri.path,
|
83
|
+
query_params,
|
84
|
+
"host:#{canonical_host}",
|
85
|
+
"", # empty params
|
86
|
+
"host",
|
87
|
+
"UNSIGNED-PAYLOAD",
|
88
|
+
].join("\n")
|
89
|
+
end
|
90
|
+
|
91
|
+
def generate_string_to_sign(date_time, credential_info, canonical_request)
|
92
|
+
[
|
93
|
+
"AWS4-HMAC-SHA256",
|
94
|
+
date_time,
|
95
|
+
credential_info,
|
96
|
+
Digest::SHA256.hexdigest(canonical_request)
|
97
|
+
].join("\n")
|
98
|
+
end
|
99
|
+
|
100
|
+
def generate_signature(s3_config, date, string_to_sign)
|
101
|
+
date_key = OpenSSL::HMAC.digest("sha256", "AWS4" + s3_config.secret_access_key, date)
|
102
|
+
date_region_key = OpenSSL::HMAC.digest("sha256", date_key, s3_config.region)
|
103
|
+
date_region_service_key = OpenSSL::HMAC.digest("sha256", date_region_key, "s3")
|
104
|
+
signing_key = OpenSSL::HMAC.digest("sha256", date_region_service_key, "aws4_request")
|
105
|
+
OpenSSL::HMAC.hexdigest("sha256", signing_key, string_to_sign)
|
106
|
+
end
|
107
|
+
|
108
|
+
##
|
109
|
+
# Extracts S3 configuration for S3 bucket
|
110
|
+
def fetch_s3_config
|
111
|
+
return S3Config.new(uri.user, uri.password, nil, "us-east-1") if uri.user && uri.password
|
112
|
+
|
113
|
+
s3_source = Gem.configuration[:s3_source] || Gem.configuration["s3_source"]
|
114
|
+
host = uri.host
|
115
|
+
raise ConfigurationError.new("no s3_source key exists in .gemrc") unless s3_source
|
116
|
+
|
117
|
+
auth = s3_source[host] || s3_source[host.to_sym]
|
118
|
+
raise ConfigurationError.new("no key for host #{host} in s3_source in .gemrc") unless auth
|
119
|
+
|
120
|
+
provider = auth[:provider] || auth["provider"]
|
121
|
+
case provider
|
122
|
+
when "env"
|
123
|
+
id = ENV["AWS_ACCESS_KEY_ID"]
|
124
|
+
secret = ENV["AWS_SECRET_ACCESS_KEY"]
|
125
|
+
security_token = ENV["AWS_SESSION_TOKEN"]
|
126
|
+
when "instance_profile"
|
127
|
+
credentials = ec2_metadata_credentials_json
|
128
|
+
id = credentials["AccessKeyId"]
|
129
|
+
secret = credentials["SecretAccessKey"]
|
130
|
+
security_token = credentials["Token"]
|
131
|
+
else
|
132
|
+
id = auth[:id] || auth["id"]
|
133
|
+
secret = auth[:secret] || auth["secret"]
|
134
|
+
security_token = auth[:security_token] || auth["security_token"]
|
135
|
+
end
|
136
|
+
|
137
|
+
raise ConfigurationError.new("s3_source for #{host} missing id or secret") unless id && secret
|
138
|
+
|
139
|
+
region = auth[:region] || auth["region"] || "us-east-1"
|
140
|
+
S3Config.new(id, secret, security_token, region)
|
141
|
+
end
|
142
|
+
|
143
|
+
def base64_uri_escape(str)
|
144
|
+
str.gsub(/[\+\/=\n]/, BASE64_URI_TRANSLATE)
|
145
|
+
end
|
146
|
+
|
147
|
+
def ec2_metadata_credentials_json
|
148
|
+
require 'net/http'
|
149
|
+
require 'rubygems/request'
|
150
|
+
require 'rubygems/request/connection_pools'
|
151
|
+
require 'json'
|
152
|
+
|
153
|
+
metadata_uri = URI(EC2_METADATA_CREDENTIALS)
|
154
|
+
@request_pool ||= create_request_pool(metadata_uri)
|
155
|
+
request = Gem::Request.new(metadata_uri, Net::HTTP::Get, nil, @request_pool)
|
156
|
+
response = request.fetch
|
157
|
+
|
158
|
+
case response
|
159
|
+
when Net::HTTPOK then
|
160
|
+
JSON.parse(response.body)
|
161
|
+
else
|
162
|
+
raise InstanceProfileError.new("Unable to fetch AWS credentials from #{metadata_uri}: #{response.message} #{response.code}")
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def create_request_pool(uri)
|
167
|
+
proxy_uri = Gem::Request.proxy_uri(Gem::Request.get_proxy_from_env(uri.scheme))
|
168
|
+
certs = Gem::Request.get_cert_files
|
169
|
+
Gem::Request::ConnectionPools.new(proxy_uri, certs).pool_for(uri)
|
170
|
+
end
|
171
|
+
|
172
|
+
BASE64_URI_TRANSLATE = { "+" => "%2B", "/" => "%2F", "=" => "%3D", "\n" => "" }.freeze
|
173
|
+
EC2_METADATA_CREDENTIALS = "http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance".freeze
|
174
|
+
|
175
|
+
end
|
@@ -110,8 +110,7 @@ class Gem::StubSpecification < Gem::BasicSpecification
|
|
110
110
|
begin
|
111
111
|
saved_lineno = $.
|
112
112
|
|
113
|
-
|
114
|
-
open loaded_from, OPEN_MODE do |file|
|
113
|
+
File.open loaded_from, OPEN_MODE do |file|
|
115
114
|
begin
|
116
115
|
file.readline # discard encoding line
|
117
116
|
stubline = file.readline.chomp
|
data/lib/rubygems/test_case.rb
CHANGED
@@ -140,6 +140,12 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni
|
|
140
140
|
assert File.exist?(path), msg
|
141
141
|
end
|
142
142
|
|
143
|
+
def assert_directory_exists(path, msg = nil)
|
144
|
+
msg = message(msg) { "Expected path '#{path}' to be a directory" }
|
145
|
+
assert_path_exists path
|
146
|
+
assert File.directory?(path), msg
|
147
|
+
end
|
148
|
+
|
143
149
|
##
|
144
150
|
# Sets the ENABLE_SHARED entry in RbConfig::CONFIG to +value+ and restores
|
145
151
|
# the original value when the block ends
|
@@ -256,6 +262,7 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni
|
|
256
262
|
@orig_gem_env_requirements = ENV.to_hash
|
257
263
|
|
258
264
|
ENV['GEM_VENDOR'] = nil
|
265
|
+
ENV['GEMRC'] = nil
|
259
266
|
ENV['SOURCE_DATE_EPOCH'] = nil
|
260
267
|
|
261
268
|
@current_dir = Dir.pwd
|
@@ -746,7 +753,7 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni
|
|
746
753
|
# Removes all installed gems from +@gemhome+.
|
747
754
|
|
748
755
|
def util_clear_gems
|
749
|
-
FileUtils.rm_rf File.join(@gemhome, "gems")
|
756
|
+
FileUtils.rm_rf File.join(@gemhome, "gems")
|
750
757
|
FileUtils.mkdir File.join(@gemhome, "gems")
|
751
758
|
FileUtils.rm_rf File.join(@gemhome, "specifications")
|
752
759
|
FileUtils.mkdir File.join(@gemhome, "specifications")
|
@@ -931,9 +938,6 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni
|
|
931
938
|
# location are returned.
|
932
939
|
|
933
940
|
def util_gem(name, version, deps = nil, &block)
|
934
|
-
# TODO: deprecate
|
935
|
-
raise "deps or block, not both" if deps and block
|
936
|
-
|
937
941
|
if deps
|
938
942
|
block = proc do |s|
|
939
943
|
# Since Hash#each is unordered in 1.8, sort
|
data/lib/rubygems/util.rb
CHANGED
@@ -128,4 +128,16 @@ module Gem::Util
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
+
##
|
132
|
+
# Corrects +path+ (usually returned by `URI.parse().path` on Windows), that
|
133
|
+
# comes with a leading slash.
|
134
|
+
|
135
|
+
def self.correct_for_windows_path(path)
|
136
|
+
if path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':'
|
137
|
+
path[1..-1]
|
138
|
+
else
|
139
|
+
path
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
131
143
|
end
|
data/rubygems-update.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "rubygems-update"
|
5
|
-
s.version = "3.0.
|
5
|
+
s.version = "3.0.5"
|
6
6
|
s.authors = ["Jim Weirich", "Chad Fowler", "Eric Hodel", "Luis Lavena", "Aaron Patterson", "Samuel Giddins", "André Arko", "Evan Phoenix", "Hiroshi SHIBATA"]
|
7
7
|
s.email = ["", "", "drbrain@segment7.net", "luislavena@gmail.com", "aaron@tenderlovemaking.com", "segiddins@segiddins.me", "andre@arko.net", "evan@phx.io", "hsbt@ruby-lang.org"]
|
8
8
|
|
data/test/rubygems/test_gem.rb
CHANGED
@@ -156,7 +156,7 @@ class TestGem < Gem::TestCase
|
|
156
156
|
end
|
157
157
|
|
158
158
|
def assert_self_install_permissions
|
159
|
-
mask =
|
159
|
+
mask = win_platform? ? 0700 : 0777
|
160
160
|
options = {
|
161
161
|
:dir_mode => 0500,
|
162
162
|
:prog_mode => 0510,
|
@@ -195,6 +195,9 @@ class TestGem < Gem::TestCase
|
|
195
195
|
'gems/foo-1/bin/foo.cmd' => prog_mode,
|
196
196
|
'gems/foo-1/data/foo.txt' => data_mode,
|
197
197
|
}
|
198
|
+
# below is for intermittent errors on Appveyor & Travis 2019-01,
|
199
|
+
# see https://github.com/rubygems/rubygems/pull/2568
|
200
|
+
sleep 0.2
|
198
201
|
result = {}
|
199
202
|
Dir.chdir @gemhome do
|
200
203
|
expected.each_key do |n|
|
@@ -541,7 +544,7 @@ class TestGem < Gem::TestCase
|
|
541
544
|
|
542
545
|
Gem.ensure_gem_subdirectories @gemhome, 0750
|
543
546
|
|
544
|
-
|
547
|
+
assert_directory_exists File.join(@gemhome, "cache")
|
545
548
|
|
546
549
|
assert_equal 0750, File::Stat.new(@gemhome).mode & 0777
|
547
550
|
assert_equal 0750, File::Stat.new(File.join(@gemhome, "cache")).mode & 0777
|
@@ -570,7 +573,7 @@ class TestGem < Gem::TestCase
|
|
570
573
|
|
571
574
|
Gem.ensure_gem_subdirectories gemdir
|
572
575
|
|
573
|
-
|
576
|
+
assert_directory_exists util_cache_dir
|
574
577
|
end
|
575
578
|
|
576
579
|
unless win_platform? || Process.uid.zero? # only for FS that support write protection
|
@@ -90,17 +90,6 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
|
|
90
90
|
assert_equal '', @ui.error
|
91
91
|
end
|
92
92
|
|
93
|
-
def test_execute_packageversion
|
94
|
-
@cmd.send :handle_options, %w[packageversion]
|
95
|
-
|
96
|
-
use_ui @ui do
|
97
|
-
@cmd.execute
|
98
|
-
end
|
99
|
-
|
100
|
-
assert_equal "#{Gem::RubyGemsPackageVersion}\n", @ui.output
|
101
|
-
assert_equal '', @ui.error
|
102
|
-
end
|
103
|
-
|
104
93
|
def test_execute_remotesources
|
105
94
|
orig_sources = Gem.sources.dup
|
106
95
|
Gem.sources.replace %w[http://gems.example.com]
|
@@ -199,6 +199,21 @@ class TestGemCommandsPushCommand < Gem::TestCase
|
|
199
199
|
send_battery
|
200
200
|
end
|
201
201
|
|
202
|
+
def test_sending_gem_with_env_var_api_key
|
203
|
+
@host = "http://privategemserver.example"
|
204
|
+
|
205
|
+
@spec, @path = util_gem "freebird", "1.0.1" do |spec|
|
206
|
+
spec.metadata['allowed_push_host'] = @host
|
207
|
+
end
|
208
|
+
|
209
|
+
@api_key = "PRIVKEY"
|
210
|
+
ENV["GEM_HOST_API_KEY"] = "PRIVKEY"
|
211
|
+
|
212
|
+
@response = "Successfully registered gem: freebird (1.0.1)"
|
213
|
+
@fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, 'OK']
|
214
|
+
send_battery
|
215
|
+
end
|
216
|
+
|
202
217
|
def test_sending_gem_to_allowed_push_host_with_basic_credentials
|
203
218
|
@sanitized_host = "http://privategemserver.example"
|
204
219
|
@host = "http://user:password@privategemserver.example"
|
@@ -192,6 +192,62 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
|
|
192
192
|
assert File.exist? File.join(@gemhome, 'bin', 'executable')
|
193
193
|
end
|
194
194
|
|
195
|
+
def test_uninstall_selection
|
196
|
+
ui = Gem::MockGemUi.new "1\n"
|
197
|
+
|
198
|
+
util_make_gems
|
199
|
+
|
200
|
+
list = Gem::Specification.find_all_by_name 'a'
|
201
|
+
|
202
|
+
@cmd.options[:args] = ['a']
|
203
|
+
|
204
|
+
use_ui ui do
|
205
|
+
@cmd.execute
|
206
|
+
end
|
207
|
+
|
208
|
+
updated_list = Gem::Specification.find_all_by_name('a')
|
209
|
+
assert_equal list.length - 1, updated_list.length
|
210
|
+
|
211
|
+
assert_match ' 1. a-1', ui.output
|
212
|
+
assert_match ' 2. a-2', ui.output
|
213
|
+
assert_match ' 3. a-3.a', ui.output
|
214
|
+
assert_match ' 4. All versions', ui.output
|
215
|
+
assert_match 'uninstalled a-1', ui.output
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_uninstall_selection_multiple_gems
|
219
|
+
ui = Gem::MockGemUi.new "1\n"
|
220
|
+
|
221
|
+
util_make_gems
|
222
|
+
|
223
|
+
a_list = Gem::Specification.find_all_by_name('a')
|
224
|
+
b_list = Gem::Specification.find_all_by_name('b')
|
225
|
+
list = a_list + b_list
|
226
|
+
|
227
|
+
@cmd.options[:args] = ['a', 'b']
|
228
|
+
|
229
|
+
use_ui ui do
|
230
|
+
@cmd.execute
|
231
|
+
end
|
232
|
+
|
233
|
+
updated_a_list = Gem::Specification.find_all_by_name('a')
|
234
|
+
updated_b_list = Gem::Specification.find_all_by_name('b')
|
235
|
+
updated_list = updated_a_list + updated_b_list
|
236
|
+
|
237
|
+
assert_equal list.length - 2, updated_list.length
|
238
|
+
|
239
|
+
out = ui.output.split("\n")
|
240
|
+
assert_match 'uninstalled b-2', out.shift
|
241
|
+
assert_match '', out.shift
|
242
|
+
assert_match 'Select gem to uninstall:', out.shift
|
243
|
+
assert_match ' 1. a-1', out.shift
|
244
|
+
assert_match ' 2. a-2', out.shift
|
245
|
+
assert_match ' 3. a-3.a', out.shift
|
246
|
+
assert_match ' 4. All versions', out.shift
|
247
|
+
assert_match 'uninstalled a-1', out.shift
|
248
|
+
assert_empty out
|
249
|
+
end
|
250
|
+
|
195
251
|
def test_execute_with_force_and_without_version_uninstalls_everything
|
196
252
|
ui = Gem::MockGemUi.new "y\n"
|
197
253
|
|
@@ -246,7 +302,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
|
|
246
302
|
gemhome2 = "#{@gemhome}2"
|
247
303
|
|
248
304
|
a_4, = util_gem 'a', 4
|
249
|
-
install_gem a_4
|
305
|
+
install_gem a_4
|
250
306
|
|
251
307
|
Gem::Specification.dirs = [@gemhome, gemhome2]
|
252
308
|
|
@@ -264,6 +320,29 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
|
|
264
320
|
assert_equal %w[default-1], Gem::Specification.all_names.sort
|
265
321
|
end
|
266
322
|
|
323
|
+
def test_execute_outside_gem_home
|
324
|
+
ui = Gem::MockGemUi.new "y\n"
|
325
|
+
|
326
|
+
gemhome2 = "#{@gemhome}2"
|
327
|
+
|
328
|
+
a_4, = util_gem 'a', 4
|
329
|
+
install_gem a_4 , :install_dir => gemhome2
|
330
|
+
|
331
|
+
Gem::Specification.dirs = [@gemhome, gemhome2]
|
332
|
+
|
333
|
+
assert_includes Gem::Specification.all_names, 'a-4'
|
334
|
+
|
335
|
+
@cmd.options[:args] = ['a:4']
|
336
|
+
|
337
|
+
e = assert_raises Gem::InstallError do
|
338
|
+
use_ui ui do
|
339
|
+
@cmd.execute
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
assert_includes e.message, "a is not installed in GEM_HOME"
|
344
|
+
end
|
345
|
+
|
267
346
|
def test_handle_options
|
268
347
|
@cmd.handle_options %w[]
|
269
348
|
|