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.

@@ -57,13 +57,13 @@ class Gem::DependencyInstaller
57
57
  # :build_args:: See Gem::Installer::new
58
58
 
59
59
  def initialize(options = {})
60
- if options[:install_dir] then
61
- @gem_home = options[:install_dir]
60
+ @install_dir = options[:install_dir] || Gem.dir
62
61
 
63
- # HACK shouldn't change the global settings
64
- Gem::Specification.dirs = @gem_home
65
- Gem.ensure_gem_subdirectories @gem_home
66
- options[:install_dir] = @gem_home # FIX: because we suck and reuse below
62
+ if options[:install_dir] then
63
+ # HACK shouldn't change the global settings, needed for -i behavior
64
+ # maybe move to the install command? See also github #442
65
+ Gem::Specification.dirs = @install_dir
66
+ Gem.ensure_gem_subdirectories @install_dir
67
67
  end
68
68
 
69
69
  options = DEFAULT_OPTIONS.merge options
@@ -91,7 +91,6 @@ class Gem::DependencyInstaller
91
91
  @installed_gems = []
92
92
  @toplevel_specs = nil
93
93
 
94
- @install_dir = options[:install_dir] || Gem.dir
95
94
  @cache_dir = options[:cache_dir] || @install_dir
96
95
 
97
96
  # Set with any errors that SpecFetcher finds while search through
@@ -260,7 +259,7 @@ class Gem::DependencyInstaller
260
259
  set = Gem::AvailableSet.new
261
260
 
262
261
  if consider_local?
263
- if File.file? gem_name then
262
+ if gem_name =~ /\.gem$/ and File.file? gem_name then
264
263
  src = Gem::Source::SpecificFile.new(gem_name)
265
264
  set.add src.spec, src
266
265
  else
@@ -1,8 +1,9 @@
1
- ##
1
+ #--
2
2
  # This file contains all the various exceptions and other errors that are used
3
3
  # inside of RubyGems.
4
4
  #
5
5
  # DOC: Confirm _all_
6
+ #++
6
7
 
7
8
  module Gem
8
9
  ##
@@ -19,6 +19,7 @@ class Gem::Ext::Builder
19
19
  mf = Gem.read_binary 'Makefile'
20
20
  mf = mf.gsub(/^RUBYARCHDIR\s*=\s*\$[^$]*/, "RUBYARCHDIR = #{dest_path}")
21
21
  mf = mf.gsub(/^RUBYLIBDIR\s*=\s*\$[^$]*/, "RUBYLIBDIR = #{dest_path}")
22
+ mf = mf.gsub(/\s*\S+\.time$/, "")
22
23
 
23
24
  File.open('Makefile', 'wb') {|f| f.print mf}
24
25
 
@@ -42,12 +43,18 @@ class Gem::Ext::Builder
42
43
  def self.run(command, results, command_name = nil)
43
44
  verbose = Gem.configuration.really_verbose
44
45
 
45
- if verbose
46
- puts(command)
47
- system(command)
48
- else
49
- results << command
50
- results << `#{command} #{redirector}`
46
+ begin
47
+ # TODO use Process.spawn when ruby 1.8 support is dropped.
48
+ rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
49
+ if verbose
50
+ puts(command)
51
+ system(command)
52
+ else
53
+ results << command
54
+ results << `#{command} #{redirector}`
55
+ end
56
+ ensure
57
+ ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
51
58
  end
52
59
 
53
60
  unless $?.success? then
@@ -27,17 +27,25 @@ module Gem::GemcutterUtilities
27
27
  end
28
28
  end
29
29
 
30
- def sign_in
30
+ def sign_in sign_in_host = self.host
31
31
  return if Gem.configuration.rubygems_api_key
32
32
 
33
- say "Enter your RubyGems.org credentials."
34
- say "Don't have an account yet? Create one at http://rubygems.org/sign_up"
33
+ pretty_host = if Gem::DEFAULT_HOST == sign_in_host then
34
+ 'RubyGems.org'
35
+ else
36
+ sign_in_host
37
+ end
38
+
39
+ say "Enter your #{pretty_host} credentials."
40
+ say "Don't have an account yet? " +
41
+ "Create one at https://#{sign_in_host}/sign_up"
35
42
 
36
43
  email = ask " Email: "
37
44
  password = ask_for_password "Password: "
38
45
  say "\n"
39
46
 
40
- response = rubygems_api_request :get, "api/v1/api_key" do |request|
47
+ response = rubygems_api_request(:get, "api/v1/api_key",
48
+ sign_in_host) do |request|
41
49
  request.basic_auth email, password
42
50
  end
43
51
 
@@ -277,9 +277,13 @@ EOM
277
277
  # the security policy.
278
278
 
279
279
  def digest entry # :nodoc:
280
- return unless @checksums
280
+ algorithms = if @checksums then
281
+ @checksums.keys
282
+ else
283
+ [Gem::Security::DIGEST_NAME]
284
+ end
281
285
 
282
- @checksums.each_key do |algorithm|
286
+ algorithms.each do |algorithm|
283
287
  digester = OpenSSL::Digest.new algorithm
284
288
 
285
289
  digester << entry.read(16384) until entry.eof?
@@ -473,6 +477,10 @@ EOM
473
477
  @security_policy
474
478
 
475
479
  true
480
+ rescue Gem::Security::Exception
481
+ @spec = nil
482
+ @files = []
483
+ raise
476
484
  rescue Errno::ENOENT => e
477
485
  raise Gem::Package::FormatError.new e.message
478
486
  rescue Gem::Package::TarInvalidError => e
@@ -23,15 +23,18 @@ class Gem::Package::Old < Gem::Package
23
23
  require 'zlib'
24
24
  Gem.load_yaml
25
25
 
26
- @gem = gem
27
- @contents = nil
28
- @spec = nil
26
+ @contents = nil
27
+ @gem = gem
28
+ @security_policy = nil
29
+ @spec = nil
29
30
  end
30
31
 
31
32
  ##
32
33
  # A list of file names contained in this gem
33
34
 
34
35
  def contents
36
+ verify
37
+
35
38
  return @contents if @contents
36
39
 
37
40
  open @gem, 'rb' do |io|
@@ -46,6 +49,8 @@ class Gem::Package::Old < Gem::Package
46
49
  # Extracts the files in this package into +destination_dir+
47
50
 
48
51
  def extract_files destination_dir
52
+ verify
53
+
49
54
  errstr = "Error reading files from gem"
50
55
 
51
56
  open @gem, 'rb' do |io|
@@ -125,6 +130,8 @@ class Gem::Package::Old < Gem::Package
125
130
  # The specification for this gem
126
131
 
127
132
  def spec
133
+ verify
134
+
128
135
  return @spec if @spec
129
136
 
130
137
  yaml = ''
@@ -136,12 +143,36 @@ class Gem::Package::Old < Gem::Package
136
143
  end
137
144
  end
138
145
 
139
- @spec = Gem::Specification.from_yaml yaml
140
- rescue YAML::SyntaxError => e
141
- raise Gem::Exception, "Failed to parse gem specification out of gem file"
146
+ yaml_error = if RUBY_VERSION < '1.9' then
147
+ YAML::ParseError
148
+ elsif YAML::ENGINE.yamler == 'syck' then
149
+ YAML::ParseError
150
+ else
151
+ YAML::SyntaxError
152
+ end
153
+
154
+ begin
155
+ @spec = Gem::Specification.from_yaml yaml
156
+ rescue yaml_error => e
157
+ raise Gem::Exception, "Failed to parse gem specification out of gem file"
158
+ end
142
159
  rescue ArgumentError => e
143
160
  raise Gem::Exception, "Failed to parse gem specification out of gem file"
144
161
  end
145
162
 
163
+ ##
164
+ # Raises an exception if a security policy that verifies data is active.
165
+ # Old format gems cannot be verified as signed.
166
+
167
+ def verify
168
+ return true unless @security_policy
169
+
170
+ raise Gem::Security::Exception,
171
+ 'old format gems do not contain signatures and cannot be verified' if
172
+ @security_policy.verify_data
173
+
174
+ true
175
+ end
176
+
146
177
  end
147
178
 
@@ -49,13 +49,18 @@ class Gem::Security::Policy
49
49
  # and is valid for the given +time+.
50
50
 
51
51
  def check_chain chain, time
52
- chain.each_cons 2 do |issuer, cert|
53
- check_cert cert, issuer, time
54
- end
52
+ raise Gem::Security::Exception, 'missing signing chain' unless chain
53
+ raise Gem::Security::Exception, 'empty signing chain' if chain.empty?
55
54
 
56
- true
57
- rescue Gem::Security::Exception => e
58
- raise Gem::Security::Exception, "invalid signing chain: #{e.message}"
55
+ begin
56
+ chain.each_cons 2 do |issuer, cert|
57
+ check_cert cert, issuer, time
58
+ end
59
+
60
+ true
61
+ rescue Gem::Security::Exception => e
62
+ raise Gem::Security::Exception, "invalid signing chain: #{e.message}"
63
+ end
59
64
  end
60
65
 
61
66
  ##
@@ -74,6 +79,9 @@ class Gem::Security::Policy
74
79
  # If the +issuer+ is +nil+ no verification is performed.
75
80
 
76
81
  def check_cert signer, issuer, time
82
+ raise Gem::Security::Exception, 'missing signing certificate' unless
83
+ signer
84
+
77
85
  message = "certificate #{signer.subject}"
78
86
 
79
87
  if not_before = signer.not_before and not_before > time then
@@ -97,6 +105,12 @@ class Gem::Security::Policy
97
105
  # Ensures the public key of +key+ matches the public key in +signer+
98
106
 
99
107
  def check_key signer, key
108
+ unless signer and key then
109
+ return true unless @only_signed
110
+
111
+ raise Gem::Security::Exception, 'missing key or signature'
112
+ end
113
+
100
114
  raise Gem::Security::Exception,
101
115
  "certificate #{signer.subject} does not match the signing key" unless
102
116
  signer.public_key.to_pem == key.public_key.to_pem
@@ -109,8 +123,12 @@ class Gem::Security::Policy
109
123
  # +time+.
110
124
 
111
125
  def check_root chain, time
126
+ raise Gem::Security::Exception, 'missing signing chain' unless chain
127
+
112
128
  root = chain.first
113
129
 
130
+ raise Gem::Security::Exception, 'missing root certificate' unless root
131
+
114
132
  raise Gem::Security::Exception,
115
133
  "root certificate #{root.subject} is not self-signed " +
116
134
  "(issuer #{root.issuer})" if
@@ -124,8 +142,12 @@ class Gem::Security::Policy
124
142
  # the digests of the two certificates match according to +digester+
125
143
 
126
144
  def check_trust chain, digester, trust_dir
145
+ raise Gem::Security::Exception, 'missing signing chain' unless chain
146
+
127
147
  root = chain.first
128
148
 
149
+ raise Gem::Security::Exception, 'missing root certificate' unless root
150
+
129
151
  path = Gem::Security.trust_dir.cert_path root
130
152
 
131
153
  unless File.exist? path then
@@ -152,8 +174,8 @@ class Gem::Security::Policy
152
174
  end
153
175
 
154
176
  def inspect # :nodoc:
155
- "[Policy: %s - data: %p signer: %p chain: %p root: %p " +
156
- "signed-only: %p trusted-only: %p]" % [
177
+ ("[Policy: %s - data: %p signer: %p chain: %p root: %p " +
178
+ "signed-only: %p trusted-only: %p]") % [
157
179
  @name, @verify_chain, @verify_data, @verify_root, @verify_signer,
158
180
  @only_signed, @only_trusted,
159
181
  ]
@@ -177,11 +199,16 @@ class Gem::Security::Policy
177
199
  trust_dir = opt[:trust_dir]
178
200
  time = Time.now
179
201
 
180
- signer_digests = digests.find do |algorithm, file_digests|
202
+ _, signer_digests = digests.find do |algorithm, file_digests|
181
203
  file_digests.values.first.name == Gem::Security::DIGEST_NAME
182
204
  end
183
205
 
184
- signer_digests = digests.values.first || {}
206
+ if @verify_data then
207
+ raise Gem::Security::Exception, 'no digests provided (probable bug)' if
208
+ signer_digests.nil? or signer_digests.empty?
209
+ else
210
+ signer_digests = {}
211
+ end
185
212
 
186
213
  signer = chain.last
187
214
 
@@ -195,6 +222,13 @@ class Gem::Security::Policy
195
222
 
196
223
  check_trust chain, digester, trust_dir if @only_trusted
197
224
 
225
+ signatures.each do |file, _|
226
+ digest = signer_digests[file]
227
+
228
+ raise Gem::Security::Exception, "missing digest for #{file}" unless
229
+ digest
230
+ end
231
+
198
232
  signer_digests.each do |file, digest|
199
233
  signature = signatures[file]
200
234
 
@@ -656,6 +656,12 @@ class Gem::Specification
656
656
 
657
657
  @@all = specs.values
658
658
 
659
+ # After a reset, make sure already loaded specs
660
+ # are still marked as activated.
661
+ specs = {}
662
+ Gem.loaded_specs.each_value{|s| specs[s] = true}
663
+ @@all.each{|s| s.activated = true if specs[s]}
664
+
659
665
  _resort!
660
666
  end
661
667
  @@all
@@ -898,7 +904,7 @@ class Gem::Specification
898
904
  raise Gem::Exception, "YAML data doesn't evaluate to gem specification"
899
905
  end
900
906
 
901
- spec.instance_eval { @specification_version ||= NONEXISTENT_SPECIFICATION_VERSION }
907
+ spec.specification_version ||= NONEXISTENT_SPECIFICATION_VERSION
902
908
  spec.reset_nil_attributes_to_default
903
909
 
904
910
  spec
@@ -0,0 +1 @@
1
+ # Ignore all files in this directory
@@ -118,8 +118,8 @@ class Gem::TestCase < MiniTest::Unit::TestCase
118
118
  @current_dir = Dir.pwd
119
119
  @ui = Gem::MockGemUi.new
120
120
 
121
- # Need to do this in the project because $SAFE fucks up _everything_
122
- tmpdir = File.expand_path("tmp/test")
121
+ tmpdir = File.expand_path Dir.tmpdir
122
+ tmpdir.untaint
123
123
 
124
124
  if ENV['KEEP_FILES'] then
125
125
  @tempdir = File.join(tmpdir, "test_rubygems_#{$$}.#{Time.now.to_i}")
@@ -127,11 +127,25 @@ class Gem::TestCase < MiniTest::Unit::TestCase
127
127
  @tempdir = File.join(tmpdir, "test_rubygems_#{$$}")
128
128
  end
129
129
  @tempdir.untaint
130
+
131
+ FileUtils.mkdir_p @tempdir
132
+
133
+ # This makes the tempdir consistent on OS X.
134
+ # File.expand_path Dir.tmpdir #=> "/var/..."
135
+ # Dir.chdir Dir.tmpdir do File.expand_path '.' end #=> "/private/var/..."
136
+ # TODO use File#realpath above instead of #expand_path once 1.8 support is
137
+ # dropped.
138
+ Dir.chdir @tempdir do
139
+ @tempdir = File.expand_path '.'
140
+ @tempdir.untaint
141
+ end
142
+
130
143
  @gemhome = File.join @tempdir, 'gemhome'
131
144
  @userhome = File.join @tempdir, 'userhome'
132
145
 
133
- @orig_ruby = if ruby = ENV['RUBY'] then
134
- Gem.class_eval { ruby, @ruby = @ruby, ruby.dup }
146
+ @orig_ruby = if ENV['RUBY'] then
147
+ ruby = Gem.instance_variable_get :@ruby
148
+ Gem.instance_variable_set :@ruby, ENV['RUBY']
135
149
  ruby
136
150
  end
137
151
 
@@ -251,7 +265,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
251
265
  ENV['GEM_PATH'] = @orig_gem_path
252
266
 
253
267
  _ = @orig_ruby
254
- Gem.class_eval { @ruby = _ } if _
268
+ Gem.instance_variable_set :@ruby, @orig_ruby if @orig_ruby
255
269
 
256
270
  if @orig_ENV_HOME then
257
271
  ENV['HOME'] = @orig_ENV_HOME
@@ -667,6 +667,25 @@ class TestGem < Gem::TestCase
667
667
  assert_equal %w[http://rubygems.org/], Gem.default_sources
668
668
  end
669
669
 
670
+ def test_self_detect_gemdeps
671
+ rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
672
+
673
+ FileUtils.mkdir_p 'detect/a/b'
674
+ FileUtils.mkdir_p 'detect/a/Isolate'
675
+
676
+ FileUtils.touch 'detect/Isolate'
677
+
678
+ begin
679
+ Dir.chdir 'detect/a/b'
680
+
681
+ assert_empty Gem.detect_gemdeps
682
+ ensure
683
+ Dir.chdir @tempdir
684
+ end
685
+ ensure
686
+ ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
687
+ end
688
+
670
689
  def test_self_dir
671
690
  assert_equal @gemhome, Gem.dir
672
691
  end
@@ -959,6 +978,27 @@ class TestGem < Gem::TestCase
959
978
  assert_includes Gem::Specification.all_names, @a1.full_name
960
979
  end
961
980
 
981
+ def test_self_refresh_keeps_loaded_specs_activated
982
+ util_make_gems
983
+
984
+ a1_spec = @a1.spec_file
985
+ moved_path = File.join @tempdir, File.basename(a1_spec)
986
+
987
+ FileUtils.mv a1_spec, moved_path
988
+
989
+ Gem.refresh
990
+
991
+ s = Gem::Specification.first
992
+ s.activate
993
+
994
+ Gem.refresh
995
+
996
+ Gem::Specification.each{|spec| assert spec.activated? if spec == s}
997
+
998
+ Gem.loaded_specs.delete(s)
999
+ Gem.refresh
1000
+ end
1001
+
962
1002
  def test_self_ruby_escaping_spaces_in_path
963
1003
  orig_ruby = Gem.ruby
964
1004
  orig_bindir = Gem::ConfigMap[:bindir]
@@ -1436,7 +1476,7 @@ class TestGem < Gem::TestCase
1436
1476
  ENV['GEM_PATH'] = path
1437
1477
  ENV['RUBYGEMS_GEMDEPS'] = "-"
1438
1478
 
1439
- out = `#{Gem.ruby.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"`
1479
+ out = `#{Gem.ruby.dup.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"`
1440
1480
 
1441
1481
  assert_equal '["a-1", "b-1", "c-1"]', out.strip
1442
1482
  end
@@ -1468,7 +1508,7 @@ class TestGem < Gem::TestCase
1468
1508
 
1469
1509
  Dir.mkdir "sub1"
1470
1510
  out = Dir.chdir "sub1" do
1471
- `#{Gem.ruby.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"`
1511
+ `#{Gem.ruby.dup.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"`
1472
1512
  end
1473
1513
 
1474
1514
  Dir.rmdir "sub1"