rubygems-update 2.0.0.rc.1 → 2.0.0.rc.2
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.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +3 -0
- data.tar.gz.sig +0 -0
- data/History.txt +165 -3
- data/Manifest.txt +1 -0
- data/lib/rubygems.rb +19 -37
- data/lib/rubygems/commands/push_command.rb +18 -11
- data/lib/rubygems/compatibility.rb +5 -1
- data/lib/rubygems/config_file.rb +42 -1
- data/lib/rubygems/dependency_installer.rb +7 -8
- data/lib/rubygems/errors.rb +2 -1
- data/lib/rubygems/ext/builder.rb +13 -6
- data/lib/rubygems/gemcutter_utilities.rb +12 -4
- data/lib/rubygems/package.rb +10 -2
- data/lib/rubygems/package/old.rb +37 -6
- data/lib/rubygems/security/policy.rb +44 -10
- data/lib/rubygems/specification.rb +7 -1
- data/lib/rubygems/ssl_certs/.document +1 -0
- data/lib/rubygems/test_case.rb +19 -5
- data/test/rubygems/test_gem.rb +42 -2
- data/test/rubygems/test_gem_commands_push_command.rb +2 -1
- data/test/rubygems/test_gem_config_file.rb +98 -34
- data/test/rubygems/test_gem_dependency_installer.rb +34 -2
- data/test/rubygems/test_gem_gemcutter_utilities.rb +23 -4
- data/test/rubygems/test_gem_installer.rb +27 -0
- data/test/rubygems/test_gem_package.rb +54 -3
- data/test/rubygems/test_gem_package_old.rb +42 -0
- data/test/rubygems/test_gem_security_policy.rb +144 -32
- data/test/rubygems/test_gem_specification.rb +9 -0
- metadata +136 -165
- metadata.gz.sig +0 -0
@@ -46,6 +46,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
|
|
46
46
|
|
47
47
|
def send_battery
|
48
48
|
use_ui @ui do
|
49
|
+
@cmd.instance_variable_set :@host, @host
|
49
50
|
@cmd.send_gem(@path)
|
50
51
|
end
|
51
52
|
|
@@ -133,7 +134,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
|
|
133
134
|
end
|
134
135
|
|
135
136
|
def test_raises_error_with_no_arguments
|
136
|
-
def @cmd.sign_in; end
|
137
|
+
def @cmd.sign_in(*); end
|
137
138
|
assert_raises Gem::CommandLineError do
|
138
139
|
@cmd.execute
|
139
140
|
end
|
@@ -164,6 +164,38 @@ class TestGemConfigFile < Gem::TestCase
|
|
164
164
|
assert_equal 2048, @cfg.bulk_threshold
|
165
165
|
end
|
166
166
|
|
167
|
+
def test_check_credentials_permissions
|
168
|
+
skip 'chmod not supported' if win_platform?
|
169
|
+
|
170
|
+
@cfg.rubygems_api_key = 'x'
|
171
|
+
|
172
|
+
File.chmod 0644, @cfg.credentials_path
|
173
|
+
|
174
|
+
use_ui @ui do
|
175
|
+
assert_raises Gem::MockGemUi::TermError do
|
176
|
+
@cfg.load_api_keys
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
assert_empty @ui.output
|
181
|
+
|
182
|
+
expected = <<-EXPECTED
|
183
|
+
ERROR: Your gem push credentials file located at:
|
184
|
+
|
185
|
+
\t#{@cfg.credentials_path}
|
186
|
+
|
187
|
+
has file permissions of 0644 but 0600 is required.
|
188
|
+
|
189
|
+
You should reset your credentials at:
|
190
|
+
|
191
|
+
\thttps://rubygems.org/profile/edit
|
192
|
+
|
193
|
+
if you believe they were disclosed to a third party.
|
194
|
+
EXPECTED
|
195
|
+
|
196
|
+
assert_equal expected, @ui.error
|
197
|
+
end
|
198
|
+
|
167
199
|
def test_handle_arguments
|
168
200
|
args = %w[--backtrace --bunch --of --args here]
|
169
201
|
|
@@ -215,6 +247,32 @@ class TestGemConfigFile < Gem::TestCase
|
|
215
247
|
assert_equal true, @cfg.backtrace
|
216
248
|
end
|
217
249
|
|
250
|
+
def test_load_api_keys
|
251
|
+
temp_cred = File.join Gem.user_home, '.gem', 'credentials'
|
252
|
+
FileUtils.mkdir File.dirname(temp_cred)
|
253
|
+
File.open temp_cred, 'w', 0600 do |fp|
|
254
|
+
fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97"
|
255
|
+
fp.puts ":other: a5fdbb6ba150cbb83aad2bb2fede64c"
|
256
|
+
end
|
257
|
+
|
258
|
+
util_config_file
|
259
|
+
|
260
|
+
assert_equal({:rubygems => '701229f217cdf23b1344c7b4b54ca97',
|
261
|
+
:other => 'a5fdbb6ba150cbb83aad2bb2fede64c'}, @cfg.api_keys)
|
262
|
+
end
|
263
|
+
|
264
|
+
def test_load_api_keys_bad_permission
|
265
|
+
skip 'chmod not supported' if win_platform?
|
266
|
+
|
267
|
+
@cfg.rubygems_api_key = 'x'
|
268
|
+
|
269
|
+
File.chmod 0644, @cfg.credentials_path
|
270
|
+
|
271
|
+
assert_raises Gem::MockGemUi::TermError do
|
272
|
+
@cfg.load_api_keys
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
218
276
|
def test_really_verbose
|
219
277
|
assert_equal false, @cfg.really_verbose
|
220
278
|
|
@@ -227,6 +285,46 @@ class TestGemConfigFile < Gem::TestCase
|
|
227
285
|
assert_equal true, @cfg.really_verbose
|
228
286
|
end
|
229
287
|
|
288
|
+
def test_rubygems_api_key_equals
|
289
|
+
@cfg.rubygems_api_key = 'x'
|
290
|
+
|
291
|
+
assert_equal 'x', @cfg.rubygems_api_key
|
292
|
+
|
293
|
+
expected = {
|
294
|
+
:rubygems_api_key => 'x',
|
295
|
+
}
|
296
|
+
|
297
|
+
assert_equal expected, YAML.load_file(@cfg.credentials_path)
|
298
|
+
|
299
|
+
unless win_platform? then
|
300
|
+
stat = File.stat @cfg.credentials_path
|
301
|
+
|
302
|
+
assert_equal 0600, stat.mode & 0600
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_rubygems_api_key_equals_bad_permission
|
307
|
+
skip 'chmod not supported' if win_platform?
|
308
|
+
|
309
|
+
@cfg.rubygems_api_key = 'x'
|
310
|
+
|
311
|
+
File.chmod 0644, @cfg.credentials_path
|
312
|
+
|
313
|
+
assert_raises Gem::MockGemUi::TermError do
|
314
|
+
@cfg.rubygems_api_key = 'y'
|
315
|
+
end
|
316
|
+
|
317
|
+
expected = {
|
318
|
+
:rubygems_api_key => 'x',
|
319
|
+
}
|
320
|
+
|
321
|
+
assert_equal expected, YAML.load_file(@cfg.credentials_path)
|
322
|
+
|
323
|
+
stat = File.stat @cfg.credentials_path
|
324
|
+
|
325
|
+
assert_equal 0644, stat.mode & 0644
|
326
|
+
end
|
327
|
+
|
230
328
|
def test_write
|
231
329
|
@cfg.backtrace = true
|
232
330
|
@cfg.update_sources = false
|
@@ -287,40 +385,6 @@ class TestGemConfigFile < Gem::TestCase
|
|
287
385
|
assert_equal %w[http://even-more-gems.example.com], Gem.sources
|
288
386
|
end
|
289
387
|
|
290
|
-
def test_load_rubygems_api_key_from_credentials
|
291
|
-
temp_cred = File.join Gem.user_home, '.gem', 'credentials'
|
292
|
-
FileUtils.mkdir File.dirname(temp_cred)
|
293
|
-
File.open temp_cred, 'w' do |fp|
|
294
|
-
fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97"
|
295
|
-
end
|
296
|
-
|
297
|
-
util_config_file
|
298
|
-
|
299
|
-
assert_equal "701229f217cdf23b1344c7b4b54ca97", @cfg.rubygems_api_key
|
300
|
-
end
|
301
|
-
|
302
|
-
def test_load_api_keys_from_config
|
303
|
-
temp_cred = File.join Gem.user_home, '.gem', 'credentials'
|
304
|
-
FileUtils.mkdir File.dirname(temp_cred)
|
305
|
-
File.open temp_cred, 'w' do |fp|
|
306
|
-
fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97"
|
307
|
-
fp.puts ":other: a5fdbb6ba150cbb83aad2bb2fede64c"
|
308
|
-
end
|
309
|
-
|
310
|
-
util_config_file
|
311
|
-
|
312
|
-
assert_equal({:rubygems => '701229f217cdf23b1344c7b4b54ca97',
|
313
|
-
:other => 'a5fdbb6ba150cbb83aad2bb2fede64c'}, @cfg.api_keys)
|
314
|
-
end
|
315
|
-
|
316
|
-
def test_save_credentials_file_with_strict_permissions
|
317
|
-
util_config_file
|
318
|
-
FileUtils.mkdir File.dirname(@cfg.credentials_path)
|
319
|
-
@cfg.rubygems_api_key = '701229f217cdf23b1344c7b4b54ca97'
|
320
|
-
mode = 0100600 & (~File.umask)
|
321
|
-
assert_equal mode, File.stat(@cfg.credentials_path).mode unless win_platform?
|
322
|
-
end
|
323
|
-
|
324
388
|
def test_ignore_invalid_config_file
|
325
389
|
File.open @temp_conf, 'w' do |fp|
|
326
390
|
fp.puts "some-non-yaml-hash-string"
|
@@ -500,16 +500,21 @@ class TestGemDependencyInstaller < Gem::TestCase
|
|
500
500
|
util_setup_gems
|
501
501
|
|
502
502
|
FileUtils.mv @a1_gem, @tempdir
|
503
|
+
FileUtils.mv @b1_gem, @tempdir
|
504
|
+
|
505
|
+
inst = Gem::Installer.new @a1.file_name
|
506
|
+
inst.install
|
507
|
+
|
503
508
|
gemhome2 = File.join @tempdir, 'gemhome2'
|
504
509
|
Dir.mkdir gemhome2
|
505
510
|
inst = nil
|
506
511
|
|
507
512
|
Dir.chdir @tempdir do
|
508
513
|
inst = Gem::DependencyInstaller.new :install_dir => gemhome2
|
509
|
-
inst.install '
|
514
|
+
inst.install 'b'
|
510
515
|
end
|
511
516
|
|
512
|
-
assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
|
517
|
+
assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
|
513
518
|
|
514
519
|
assert File.exist?(File.join(gemhome2, 'specifications', @a1.spec_name))
|
515
520
|
assert File.exist?(File.join(gemhome2, 'cache', @a1.file_name))
|
@@ -794,6 +799,19 @@ class TestGemDependencyInstaller < Gem::TestCase
|
|
794
799
|
assert_equal Gem::Source.new(@gem_repo), s.source
|
795
800
|
end
|
796
801
|
|
802
|
+
def test_find_spec_by_name_and_version_bad_gem
|
803
|
+
FileUtils.touch 'rdoc.gem'
|
804
|
+
|
805
|
+
inst = Gem::DependencyInstaller.new
|
806
|
+
|
807
|
+
e = assert_raises Gem::Package::FormatError do
|
808
|
+
inst.find_spec_by_name_and_version 'rdoc.gem'
|
809
|
+
end
|
810
|
+
|
811
|
+
full_path = File.join @tempdir, 'rdoc.gem'
|
812
|
+
assert_equal "package metadata is missing in #{full_path}", e.message
|
813
|
+
end
|
814
|
+
|
797
815
|
def test_find_spec_by_name_and_version_directory
|
798
816
|
Dir.mkdir 'rdoc'
|
799
817
|
|
@@ -808,6 +826,20 @@ class TestGemDependencyInstaller < Gem::TestCase
|
|
808
826
|
e.message
|
809
827
|
end
|
810
828
|
|
829
|
+
def test_find_spec_by_name_and_version_file
|
830
|
+
FileUtils.touch 'rdoc'
|
831
|
+
|
832
|
+
inst = Gem::DependencyInstaller.new
|
833
|
+
|
834
|
+
e = assert_raises Gem::SpecificGemNotFoundException do
|
835
|
+
inst.find_spec_by_name_and_version 'rdoc'
|
836
|
+
end
|
837
|
+
|
838
|
+
assert_equal "Could not find a valid gem 'rdoc' (>= 0) " +
|
839
|
+
"locally or in a repository",
|
840
|
+
e.message
|
841
|
+
end
|
842
|
+
|
811
843
|
def test_find_gems_with_sources_local
|
812
844
|
util_setup_gems
|
813
845
|
|
@@ -77,9 +77,24 @@ class TestGemGemcutterUtilities < Gem::TestCase
|
|
77
77
|
|
78
78
|
def test_sign_in_with_host
|
79
79
|
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
|
80
|
+
|
81
|
+
util_sign_in [api_key, 200, 'OK'], 'http://example.com', :param
|
82
|
+
|
83
|
+
assert_match "Enter your http://example.com credentials.",
|
84
|
+
@sign_in_ui.output
|
85
|
+
assert @fetcher.last_request["authorization"]
|
86
|
+
assert_match %r{Signed in.}, @sign_in_ui.output
|
87
|
+
|
88
|
+
credentials = YAML.load_file Gem.configuration.credentials_path
|
89
|
+
assert_equal api_key, credentials[:rubygems_api_key]
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_sign_in_with_host_ENV
|
93
|
+
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
|
80
94
|
util_sign_in [api_key, 200, 'OK'], 'http://example.com'
|
81
95
|
|
82
|
-
assert_match
|
96
|
+
assert_match "Enter your http://example.com credentials.",
|
97
|
+
@sign_in_ui.output
|
83
98
|
assert @fetcher.last_request["authorization"]
|
84
99
|
assert_match %r{Signed in.}, @sign_in_ui.output
|
85
100
|
|
@@ -125,14 +140,14 @@ class TestGemGemcutterUtilities < Gem::TestCase
|
|
125
140
|
assert_match %r{Access Denied.}, @sign_in_ui.output
|
126
141
|
end
|
127
142
|
|
128
|
-
def util_sign_in response, host = nil
|
143
|
+
def util_sign_in response, host = nil, style = :ENV
|
129
144
|
skip 'Always uses $stdin on windows' if Gem.win_platform?
|
130
145
|
|
131
146
|
email = 'you@example.com'
|
132
147
|
password = 'secret'
|
133
148
|
|
134
149
|
if host
|
135
|
-
ENV['RUBYGEMS_HOST'] = host
|
150
|
+
ENV['RUBYGEMS_HOST'] = host if style == :ENV
|
136
151
|
else
|
137
152
|
host = Gem.host
|
138
153
|
end
|
@@ -144,7 +159,11 @@ class TestGemGemcutterUtilities < Gem::TestCase
|
|
144
159
|
@sign_in_ui = Gem::MockGemUi.new "#{email}\n#{password}\n"
|
145
160
|
|
146
161
|
use_ui @sign_in_ui do
|
147
|
-
|
162
|
+
if style == :param then
|
163
|
+
@cmd.sign_in host
|
164
|
+
else
|
165
|
+
@cmd.sign_in
|
166
|
+
end
|
148
167
|
end
|
149
168
|
end
|
150
169
|
|
@@ -964,6 +964,33 @@ load Gem.bin_path('a', 'executable', version)
|
|
964
964
|
assert_match %r|I am a shiny gem!|, @ui.output
|
965
965
|
end
|
966
966
|
|
967
|
+
def test_install_extension_and_script
|
968
|
+
@spec.extensions << "extconf.rb"
|
969
|
+
write_file File.join(@tempdir, "extconf.rb") do |io|
|
970
|
+
io.write <<-RUBY
|
971
|
+
require "mkmf"
|
972
|
+
create_makefile("#{@spec.name}")
|
973
|
+
RUBY
|
974
|
+
end
|
975
|
+
|
976
|
+
rb = File.join("lib", "#{@spec.name}.rb")
|
977
|
+
@spec.files += [rb]
|
978
|
+
write_file File.join(@tempdir, rb) do |io|
|
979
|
+
io.write <<-RUBY
|
980
|
+
# #{@spec.name}.rb
|
981
|
+
RUBY
|
982
|
+
end
|
983
|
+
|
984
|
+
assert !File.exist?(File.join(@spec.gem_dir, rb))
|
985
|
+
use_ui @ui do
|
986
|
+
path = Gem::Package.build @spec
|
987
|
+
|
988
|
+
@installer = Gem::Installer.new path
|
989
|
+
@installer.install
|
990
|
+
end
|
991
|
+
assert File.exist?(File.join(@spec.gem_dir, rb))
|
992
|
+
end
|
993
|
+
|
967
994
|
def test_installation_satisfies_dependency_eh
|
968
995
|
quick_spec 'a'
|
969
996
|
|
@@ -429,10 +429,17 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
429
429
|
|
430
430
|
digest = OpenSSL::Digest::SHA1.new
|
431
431
|
digest << metadata_gz
|
432
|
-
checksum = "#{digest.name}\t#{digest.hexdigest}\n"
|
433
432
|
|
434
|
-
|
435
|
-
|
433
|
+
checksums = {
|
434
|
+
'SHA1' => {
|
435
|
+
'metadata.gz' => digest.hexdigest,
|
436
|
+
},
|
437
|
+
}
|
438
|
+
|
439
|
+
tar.add_file 'checksums.yaml.gz', 0444 do |io|
|
440
|
+
Zlib::GzipWriter.wrap io do |gz_io|
|
441
|
+
gz_io.write YAML.dump checksums
|
442
|
+
end
|
436
443
|
end
|
437
444
|
|
438
445
|
tar.add_file 'data.tar.gz', 0444 do |io|
|
@@ -499,6 +506,50 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
499
506
|
|
500
507
|
assert_equal 'unsigned gems are not allowed by the High Security policy',
|
501
508
|
e.message
|
509
|
+
|
510
|
+
refute package.instance_variable_get(:@spec), '@spec must not be loaded'
|
511
|
+
assert_empty package.instance_variable_get(:@files), '@files must empty'
|
512
|
+
end
|
513
|
+
|
514
|
+
def test_verify_security_policy_checksum_missing
|
515
|
+
@spec.cert_chain = [PUBLIC_CERT.to_pem]
|
516
|
+
@spec.signing_key = PRIVATE_KEY
|
517
|
+
|
518
|
+
build = Gem::Package.new @gem
|
519
|
+
build.spec = @spec
|
520
|
+
build.setup_signer
|
521
|
+
|
522
|
+
FileUtils.mkdir 'lib'
|
523
|
+
FileUtils.touch 'lib/code.rb'
|
524
|
+
|
525
|
+
open @gem, 'wb' do |gem_io|
|
526
|
+
Gem::Package::TarWriter.new gem_io do |gem|
|
527
|
+
build.add_metadata gem
|
528
|
+
build.add_contents gem
|
529
|
+
|
530
|
+
# write bogus data.tar.gz to foil signature
|
531
|
+
bogus_data = Gem.gzip 'hello'
|
532
|
+
gem.add_file_simple 'data.tar.gz', 0444, bogus_data.length do |io|
|
533
|
+
io.write bogus_data
|
534
|
+
end
|
535
|
+
|
536
|
+
# pre rubygems 2.0 gems do not add checksums
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
541
|
+
|
542
|
+
package = Gem::Package.new @gem
|
543
|
+
package.security_policy = Gem::Security::HighSecurity
|
544
|
+
|
545
|
+
e = assert_raises Gem::Security::Exception do
|
546
|
+
package.verify
|
547
|
+
end
|
548
|
+
|
549
|
+
assert_equal 'invalid signature', e.message
|
550
|
+
|
551
|
+
refute package.instance_variable_get(:@spec), '@spec must not be loaded'
|
552
|
+
assert_empty package.instance_variable_get(:@files), '@files must empty'
|
502
553
|
end
|
503
554
|
|
504
555
|
def test_verify_truncate
|
@@ -18,6 +18,14 @@ class TestGemPackageOld < Gem::TestCase
|
|
18
18
|
assert_equal %w[lib/foo.rb lib/test.rb lib/test/wow.rb], @package.contents
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_contents_security_policy
|
22
|
+
@package.security_policy = Gem::Security::AlmostNoSecurity
|
23
|
+
|
24
|
+
assert_raises Gem::Security::Exception do
|
25
|
+
@package.contents
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
21
29
|
def test_extract_files
|
22
30
|
@package.extract_files @destination
|
23
31
|
|
@@ -29,9 +37,43 @@ class TestGemPackageOld < Gem::TestCase
|
|
29
37
|
assert_equal mask, File.stat(extracted).mode unless win_platform?
|
30
38
|
end
|
31
39
|
|
40
|
+
def test_extract_files_security_policy
|
41
|
+
@package.security_policy = Gem::Security::AlmostNoSecurity
|
42
|
+
|
43
|
+
assert_raises Gem::Security::Exception do
|
44
|
+
@package.extract_files @destination
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
32
48
|
def test_spec
|
33
49
|
assert_equal 'testing', @package.spec.name
|
34
50
|
end
|
35
51
|
|
52
|
+
def test_spec_security_policy
|
53
|
+
@package.security_policy = Gem::Security::AlmostNoSecurity
|
54
|
+
|
55
|
+
assert_raises Gem::Security::Exception do
|
56
|
+
@package.spec
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_verify
|
61
|
+
assert @package.verify
|
62
|
+
|
63
|
+
@package.security_policy = Gem::Security::NoSecurity
|
64
|
+
|
65
|
+
assert @package.verify
|
66
|
+
|
67
|
+
@package.security_policy = Gem::Security::AlmostNoSecurity
|
68
|
+
|
69
|
+
e = assert_raises Gem::Security::Exception do
|
70
|
+
@package.verify
|
71
|
+
end
|
72
|
+
|
73
|
+
assert_equal 'old format gems do not contain signatures ' +
|
74
|
+
'and cannot be verified',
|
75
|
+
e.message
|
76
|
+
end
|
77
|
+
|
36
78
|
end
|
37
79
|
|