rubygems-update 0.9.2 → 0.9.3

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.

Files changed (53) hide show
  1. data/ChangeLog +60 -0
  2. data/lib/rubygems.rb +18 -15
  3. data/lib/rubygems/builder.rb +29 -23
  4. data/lib/rubygems/{cmd_manager.rb → command_manager.rb} +35 -24
  5. data/lib/rubygems/commands/build_command.rb +57 -0
  6. data/lib/rubygems/commands/cert_command.rb +83 -0
  7. data/lib/rubygems/commands/check_command.rb +74 -0
  8. data/lib/rubygems/commands/cleanup_command.rb +75 -0
  9. data/lib/rubygems/commands/contents_command.rb +66 -0
  10. data/lib/rubygems/commands/dependency_command.rb +105 -0
  11. data/lib/rubygems/commands/environment_command.rb +59 -0
  12. data/lib/rubygems/commands/help_command.rb +82 -0
  13. data/lib/rubygems/commands/install_command.rb +139 -0
  14. data/lib/rubygems/commands/list_command.rb +33 -0
  15. data/lib/rubygems/commands/outdated_command.rb +21 -0
  16. data/lib/rubygems/commands/pristine_command.rb +103 -0
  17. data/lib/rubygems/commands/query_command.rb +86 -0
  18. data/lib/rubygems/commands/rdoc_command.rb +75 -0
  19. data/lib/rubygems/commands/search_command.rb +35 -0
  20. data/lib/rubygems/commands/sources_command.rb +73 -0
  21. data/lib/rubygems/commands/specification_command.rb +58 -0
  22. data/lib/rubygems/commands/uninstall_command.rb +51 -0
  23. data/lib/rubygems/commands/unpack_command.rb +76 -0
  24. data/lib/rubygems/commands/update_command.rb +102 -0
  25. data/lib/rubygems/digest/digest_adapter.rb +40 -0
  26. data/lib/rubygems/digest/md5.rb +20 -0
  27. data/lib/rubygems/digest/sha1.rb +17 -0
  28. data/lib/rubygems/digest/sha2.rb +17 -0
  29. data/lib/rubygems/format.rb +1 -1
  30. data/lib/rubygems/gem_commands.rb +6 -1407
  31. data/lib/rubygems/gem_runner.rb +2 -2
  32. data/lib/rubygems/installer.rb +13 -5
  33. data/lib/rubygems/open-uri.rb +2 -2
  34. data/lib/rubygems/package.rb +13 -14
  35. data/lib/rubygems/rubygems_version.rb +1 -1
  36. data/lib/rubygems/source_index.rb +4 -4
  37. data/lib/rubygems/specification.rb +5 -0
  38. data/lib/rubygems/validator.rb +8 -8
  39. data/setup.rb +806 -588
  40. data/test/gemutilities.rb +2 -2
  41. data/test/test_builder.rb +15 -0
  42. data/test/test_check_command.rb +1 -1
  43. data/test/test_command.rb +1 -1
  44. data/test/test_gem_digest.rb +44 -0
  45. data/test/test_gem_outdated_command.rb +2 -1
  46. data/test/test_gem_sources_command.rb +11 -6
  47. data/test/test_installer.rb +1 -1
  48. data/test/test_open_uri.rb +14 -0
  49. data/test/test_parse_commands.rb +25 -25
  50. data/test/test_process_commands.rb +5 -5
  51. data/test/test_specific_extras.rb +1 -1
  52. data/test/test_validator.rb +3 -3
  53. metadata +30 -4
@@ -0,0 +1,51 @@
1
+ module Gem
2
+ module Commands
3
+ class UninstallCommand < Command
4
+ include VersionOption
5
+ include CommandAids
6
+
7
+ def initialize
8
+ super('uninstall', 'Uninstall gems from the local repository',
9
+ { :version => "> 0" })
10
+
11
+ add_option('-a', '--[no-]all',
12
+ 'Uninstall all matching versions'
13
+ ) do |value, options|
14
+ options[:all] = value
15
+ end
16
+
17
+ add_option('-i', '--[no-]ignore-dependencies',
18
+ 'Ignore dependency requirements while',
19
+ 'uninstalling') do |value, options|
20
+ options[:ignore] = value
21
+ end
22
+
23
+ add_option('-x', '--[no-]executables',
24
+ 'Uninstall applicable executables without',
25
+ 'confirmation') do |value, options|
26
+ options[:executables] = value
27
+ end
28
+
29
+ add_version_option('uninstall')
30
+ end
31
+
32
+ def defaults_str
33
+ "--version '> 0' --no-force"
34
+ end
35
+
36
+ def usage
37
+ "#{program_name} GEMNAME [GEMNAME ...]"
38
+ end
39
+
40
+ def arguments
41
+ "GEMNAME name of gem to uninstall"
42
+ end
43
+
44
+ def execute
45
+ get_all_gem_names.each do |gem_name|
46
+ Gem::Uninstaller.new(gem_name, options).uninstall
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,76 @@
1
+ module Gem
2
+ module Commands
3
+ class UnpackCommand < Command
4
+ include VersionOption
5
+ include CommandAids
6
+
7
+ def initialize
8
+ super(
9
+ 'unpack',
10
+ 'Unpack an installed gem to the current directory',
11
+ { :version => '> 0' }
12
+ )
13
+ add_version_option('unpack')
14
+ end
15
+
16
+ def defaults_str
17
+ "--version '> 0'"
18
+ end
19
+
20
+ def usage
21
+ "#{program_name} GEMNAME"
22
+ end
23
+
24
+ def arguments
25
+ "GEMNAME Name of the gem to unpack"
26
+ end
27
+
28
+ # TODO: allow, e.g., 'gem unpack rake-0.3.1'. Find a general
29
+ # solution for this, so that it works for uninstall as well. (And
30
+ # check other commands at the same time.)
31
+ def execute
32
+ gemname = get_one_gem_name
33
+ path = get_path(gemname, options[:version])
34
+ if path
35
+ require 'fileutils'
36
+ target_dir = File.basename(path).sub(/\.gem$/, '')
37
+ FileUtils.mkdir_p target_dir
38
+ Installer.new(path).unpack(File.expand_path(target_dir))
39
+ say "Unpacked gem: '#{target_dir}'"
40
+ else
41
+ alert_error "Gem '#{gemname}' not installed."
42
+ end
43
+ end
44
+
45
+ # Return the full path to the cached gem file matching the given
46
+ # name and version requirement. Returns 'nil' if no match.
47
+ # Example:
48
+ #
49
+ # get_path('rake', '> 0.4') # -> '/usr/lib/ruby/gems/1.8/cache/rake-0.4.2.gem'
50
+ # get_path('rake', '< 0.1') # -> nil
51
+ # get_path('rak') # -> nil (exact name required)
52
+ #
53
+ # TODO: This should be refactored so that it's a general service.
54
+ # I don't think any of our existing classes are the right place
55
+ # though. Just maybe 'Cache'?
56
+ #
57
+ # TODO: It just uses Gem.dir for now. What's an easy way to get
58
+ # the list of source directories?
59
+ #
60
+ def get_path(gemname, version_req)
61
+ return gemname if gemname =~ /\.gem$/i
62
+ specs = SourceIndex.from_installed_gems.search(gemname, version_req)
63
+ selected = specs.sort_by { |s| s.version }.last
64
+ return nil if selected.nil?
65
+ # We expect to find (basename).gem in the 'cache' directory.
66
+ # Furthermore, the name match must be exact (ignoring case).
67
+ if gemname =~ /^#{selected.name}$/i
68
+ filename = selected.full_name + '.gem'
69
+ return File.join(Gem.dir, 'cache', filename)
70
+ else
71
+ return nil
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,102 @@
1
+ module Gem
2
+ module Commands
3
+ class UpdateCommand < Command
4
+ include InstallUpdateOptions
5
+
6
+ def initialize
7
+ super(
8
+ 'update',
9
+ 'Update the named gem (or all installed gems) in the local repository',
10
+ {
11
+ :generate_rdoc => true,
12
+ :generate_ri => true,
13
+ :force => false,
14
+ :test => false,
15
+ :install_dir => Gem.dir
16
+ })
17
+ add_install_update_options
18
+ add_option('--system',
19
+ 'Update the RubyGems system software') do |value, options|
20
+ options[:system] = value
21
+ end
22
+ end
23
+
24
+ def defaults_str
25
+ "--rdoc --ri --no-force --no-test\n" +
26
+ "--install-dir #{Gem.dir}"
27
+ end
28
+
29
+ def arguments
30
+ "GEMNAME(s) name of gem(s) to update"
31
+ end
32
+
33
+ def execute
34
+ if options[:system]
35
+ say "Updating RubyGems..."
36
+ if ! options[:args].empty?
37
+ fail "No gem names are allowed with the --system option"
38
+ end
39
+ options[:args] = ["rubygems-update"]
40
+ else
41
+ say "Updating installed gems..."
42
+ end
43
+ hig = highest_installed_gems = {}
44
+ Gem::SourceIndex.from_installed_gems.each do |name, spec|
45
+ if hig[spec.name].nil? or hig[spec.name].version < spec.version
46
+ hig[spec.name] = spec
47
+ end
48
+ end
49
+ remote_gemspecs = Gem::SourceInfoCache.search(//)
50
+ gems_to_update = if(options[:args].empty?) then
51
+ which_to_update(highest_installed_gems, remote_gemspecs)
52
+ else
53
+ options[:args]
54
+ end
55
+ options[:domain] = :remote # install from remote source
56
+ install_command = command_manager['install']
57
+ gems_to_update.uniq.sort.each do |name|
58
+ say "Attempting remote update of #{name}"
59
+ options[:args] = [name]
60
+ install_command.merge_options(options)
61
+ install_command.execute
62
+ end
63
+ if gems_to_update.include?("rubygems-update")
64
+ latest_ruby_gem = remote_gemspecs.select { |s|
65
+ s.name == 'rubygems-update'
66
+ }.sort_by { |s|
67
+ s.version
68
+ }.last
69
+ say "Updating version of RubyGems to #{latest_ruby_gem.version}"
70
+ do_rubygems_update(latest_ruby_gem.version.to_s)
71
+ end
72
+ if(options[:system]) then
73
+ say "RubyGems system software updated"
74
+ else
75
+ say "Gems: [#{gems_to_update.uniq.sort.collect{|g| g.to_s}.join(', ')}] updated"
76
+ end
77
+ end
78
+
79
+ def do_rubygems_update(version_string)
80
+ update_dir = File.join(Gem.dir, "gems", "rubygems-update-#{version_string}")
81
+ Dir.chdir(update_dir) do
82
+ puts "Installing RubyGems #{version_string}"
83
+ system "#{Gem.ruby} setup.rb"
84
+ end
85
+ end
86
+
87
+ def which_to_update(highest_installed_gems, remote_gemspecs)
88
+ result = []
89
+ highest_installed_gems.each do |l_name, l_spec|
90
+ highest_remote_gem =
91
+ remote_gemspecs.select { |spec| spec.name == l_name }.
92
+ sort_by { |spec| spec.version }.
93
+ last
94
+ if highest_remote_gem and l_spec.version < highest_remote_gem.version
95
+ result << l_name
96
+ end
97
+ end
98
+ result
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
4
+ # All rights reserved.
5
+ # See LICENSE.txt for permissions.
6
+ #++
7
+
8
+ module Gem
9
+
10
+ # There is an incompatibility between the way Ruby 1.8.5 and 1.8.6
11
+ # handles digests. This DigestAdapter will take a pre-1.8.6 digest
12
+ # and adapt it to the 1.8.6 API.
13
+ #
14
+ # Note that only the digest and hexdigest methods are adapted,
15
+ # since these are the only functions used by Gems.
16
+ #
17
+ class DigestAdapter
18
+
19
+ # Initialize a digest adapter.
20
+ def initialize(digest_class)
21
+ @digest_class = digest_class
22
+ end
23
+
24
+ # Return a new digester. Since we are only implementing the stateless
25
+ # methods, we will return ourself as the instance.
26
+ def new
27
+ self
28
+ end
29
+
30
+ # Return the digest of +string+ as a hex string.
31
+ def hexdigest(string)
32
+ @digest_class.new(string).hexdigest
33
+ end
34
+
35
+ # Return the digest of +string+ as a binary string.
36
+ def digest(string)
37
+ @digest_class.new(string).digest
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
4
+ # All rights reserved.
5
+ # See LICENSE.txt for permissions.
6
+ #++
7
+
8
+ require 'digest/md5'
9
+
10
+ module Gem
11
+ if RUBY_VERSION >= '1.8.6'
12
+ MD5 = Digest::MD5
13
+ else
14
+ require 'rubygems/digest/digest_adapter'
15
+ MD5 = DigestAdapter.new(Digest::MD5)
16
+ def MD5.md5(string)
17
+ self.hexdigest(string)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
4
+ # All rights reserved.
5
+ # See LICENSE.txt for permissions.
6
+ #++
7
+
8
+ require 'digest/sha1'
9
+
10
+ module Gem
11
+ if RUBY_VERSION >= '1.8.6'
12
+ SHA1 = Digest::SHA1
13
+ else
14
+ require 'rubygems/digest/digest_adapter'
15
+ SHA1 = DigestAdapter.new(Digest::SHA1)
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
4
+ # All rights reserved.
5
+ # See LICENSE.txt for permissions.
6
+ #++
7
+
8
+ require 'digest/sha2'
9
+
10
+ module Gem
11
+ if RUBY_VERSION >= '1.8.6'
12
+ SHA256 = Digest::SHA256
13
+ else
14
+ require 'rubygems/digest/digest_adapter'
15
+ SHA256 = DigestAdapter.new(Digest::SHA256)
16
+ end
17
+ end
@@ -34,7 +34,7 @@ module Gem
34
34
  #
35
35
  def self.from_file_by_path(file_path, security_policy = nil)
36
36
  unless File.exist?(file_path)
37
- raise Gem::Exception, "Cannot load gem at [#{file_path}]"
37
+ raise Gem::Exception, "Cannot load gem at [#{file_path}] in #{Dir.pwd}"
38
38
  end
39
39
  require 'fileutils'
40
40
  # check for old version gem
@@ -11,6 +11,7 @@ require 'rubygems/command'
11
11
  module Gem
12
12
 
13
13
  class CommandLineError < Gem::Exception; end
14
+ module Commands; end # This is where Commands will be placed in the namespace
14
15
 
15
16
  ####################################################################
16
17
  # The following mixin methods aid in the retrieving of information
@@ -186,1414 +187,12 @@ module Gem
186
187
  end
187
188
 
188
189
  end
189
-
190
- ####################################################################
191
- # Gem install command.
192
- #
193
- class InstallCommand < Command
194
- include CommandAids
195
- include VersionOption
196
- include LocalRemoteOptions
197
- include InstallUpdateOptions
198
-
199
- def initialize
200
- super(
201
- 'install',
202
- 'Install a gem into the local repository',
203
- {
204
- :domain => :both,
205
- :generate_rdoc => true,
206
- :generate_ri => true,
207
- :force => false,
208
- :test => false,
209
- :wrappers => true,
210
- :version => "> 0",
211
- :install_dir => Gem.dir,
212
- :security_policy => nil,
213
- })
214
- add_version_option('install')
215
- add_local_remote_options
216
- add_install_update_options
217
- end
218
-
219
- def usage
220
- "#{program_name} GEMNAME [options]
221
- or: #{program_name} GEMNAME [options] -- --build-flags"
222
- end
223
-
224
- def arguments
225
- "GEMNAME name of gem to install"
226
- end
227
-
228
- def defaults_str
229
- "--both --version '> 0' --rdoc --ri --no-force --no-test\n" +
230
- "--install-dir #{Gem.dir}"
231
- end
232
-
233
- def execute
234
- ENV['GEM_PATH'] = options[:install_dir]
235
- if(options[:args].empty?)
236
- fail Gem::CommandLineError,
237
- "Please specify a gem name on the command line (e.g. gem build GEMNAME)"
238
- end
239
- options[:args].each do |gem_name|
240
- if local?
241
- begin
242
- entries = []
243
- if(File.exist?(gem_name) && !File.directory?(gem_name))
244
- entries << gem_name
245
- else
246
- filepattern = gem_name + "*.gem"
247
- entries = Dir[filepattern]
248
- end
249
- unless entries.size > 0
250
- if options[:domain] == :local
251
- alert_error "Local gem file not found: #{filepattern}"
252
- end
253
- else
254
- result = Gem::Installer.new(entries.last, options).install(options[:force], options[:install_dir])
255
- installed_gems = [result].flatten
256
- say "Successfully installed #{installed_gems[0].name}, " +
257
- "version #{installed_gems[0].version}" if installed_gems
258
- end
259
- rescue LocalInstallationError => e
260
- say " -> Local installation can't proceed: #{e.message}"
261
- rescue Gem::LoadError => e
262
- say " -> Local installation can't proceed due to LoadError: #{e.message}"
263
- rescue Gem::InstallError => e
264
- raise "Error instaling #{gem_name}:\n\t#{e.message}"
265
- rescue => e
266
- # TODO: Fix this handle to allow the error to propagate to
267
- # the top level handler. Examine the other errors as
268
- # well. This implementation here looks suspicious to me --
269
- # JimWeirich (4/Jan/05)
270
- alert_error "Error installing gem #{gem_name}[.gem]: #{e.message}"
271
- return
272
- end
273
- end
274
-
275
- if remote? && installed_gems.nil?
276
- installer = Gem::RemoteInstaller.new(options)
277
- installed_gems = installer.install(
278
- gem_name,
279
- options[:version],
280
- options[:force],
281
- options[:install_dir])
282
- if installed_gems
283
- installed_gems.compact!
284
- installed_gems.each do |spec|
285
- say "Successfully installed #{spec.full_name}"
286
- end
287
- end
288
- end
289
-
290
- unless installed_gems
291
- alert_error "Could not install a local " +
292
- "or remote copy of the gem: #{gem_name}"
293
- terminate_interaction(1)
294
- end
295
-
296
- # NOTE: *All* of the RI documents must be generated first.
297
- # For some reason, RI docs cannot be generated after any RDoc
298
- # documents are generated.
299
-
300
- if options[:generate_ri]
301
- installed_gems.each do |gem|
302
- Gem::DocManager.new(gem, options[:rdoc_args]).generate_ri
303
- end
304
- end
305
-
306
- if options[:generate_rdoc]
307
- installed_gems.each do |gem|
308
- Gem::DocManager.new(gem, options[:rdoc_args]).generate_rdoc
309
- end
310
- end
311
-
312
- if options[:test]
313
- installed_gems.each do |spec|
314
- gem_spec = Gem::SourceIndex.from_installed_gems.search(spec.name, spec.version.version).first
315
- result = Gem::Validator.new.unit_test(gem_spec)
316
- unless result.passed?
317
- unless ask_yes_no("...keep Gem?", true) then
318
- Gem::Uninstaller.new(spec.name, spec.version.version).uninstall
319
- end
320
- end
321
- end
322
- end
323
- end
324
- end
325
-
326
- end
327
-
328
- ####################################################################
329
- class OutdatedCommand < Command
330
-
331
- def initialize
332
- super 'outdated', 'Display all gems that need updates'
333
- end
334
-
335
- def execute
336
- locals = Gem::SourceIndex.from_installed_gems
337
- locals.outdated.each do |name|
338
- local = locals.search(/^#{name}$/).last
339
- remote = Gem::SourceInfoCache.search(/^#{name}$/).last
340
- say "#{local.name} (#{local.version} < #{remote.version})"
341
- end
342
- end
343
-
344
- end
345
-
346
- ####################################################################
347
- class SourcesCommand < Command
348
-
349
- def initialize
350
- super 'sources', 'Manage the sources RubyGems will search forgems'
351
-
352
- add_option '-a', '--add SOURCE_URI', 'Add source' do |value, options|
353
- options[:add] = value
354
- end
355
-
356
- add_option '-l', '--list', 'List sources' do |value, options|
357
- options[:list] = value
358
- end
359
-
360
- add_option '-r', '--remove SOURCE_URI', 'Remove source' do |value, options|
361
- options[:remove] = value
362
- end
363
- end
364
-
365
- def defaults_str
366
- '--list'
367
- end
368
-
369
- def execute
370
- if options[:add] then
371
- source_uri = options[:add]
372
-
373
- sice = Gem::SourceInfoCacheEntry.new nil, nil
374
- begin
375
- sice.refresh source_uri
376
- rescue ArgumentError
377
- say "#{source_uri} is not a URI"
378
- rescue Gem::RemoteFetcher::FetchError => e
379
- say "Error fetching #{source_uri}:\n\t#{e.message}"
380
- else
381
- Gem::SourceInfoCache.cache_data[source_uri] = sice
382
- Gem::SourceInfoCache.cache.update
383
- Gem::SourceInfoCache.cache.flush
384
-
385
- say "#{source_uri} added to sources"
386
- end
387
- end
388
-
389
- if options[:remove] then
390
- source_uri = options[:remove]
391
-
392
- unless Gem::SourceInfoCache.cache_data.include? source_uri then
393
- say "source #{source_uri} not present in cache"
394
- else
395
- Gem::SourceInfoCache.cache_data.delete source_uri
396
- Gem::SourceInfoCache.cache.update
397
- Gem::SourceInfoCache.cache.flush
398
- say "#{source_uri} removed from sources"
399
- end
400
- end
401
-
402
- if options[:list] or not (options[:add] or options[:remove]) then
403
- say "*** CURRENT SOURCES ***"
404
- say
405
-
406
- Gem::SourceInfoCache.cache_data.keys.each do |source_uri|
407
- say source_uri
408
- end
409
- end
410
- end
411
-
412
- end
413
-
414
- ####################################################################
415
- class UninstallCommand < Command
416
- include VersionOption
417
- include CommandAids
418
-
419
- def initialize
420
- super('uninstall', 'Uninstall gems from the local repository',
421
- { :version => "> 0" })
422
-
423
- add_option('-a', '--[no-]all',
424
- 'Uninstall all matching versions'
425
- ) do |value, options|
426
- options[:all] = value
427
- end
428
-
429
- add_option('-i', '--[no-]ignore-dependencies',
430
- 'Ignore dependency requirements while',
431
- 'uninstalling') do |value, options|
432
- options[:ignore] = value
433
- end
434
-
435
- add_option('-x', '--[no-]executables',
436
- 'Uninstall applicable executables without',
437
- 'confirmation') do |value, options|
438
- options[:executables] = value
439
- end
440
-
441
- add_version_option('uninstall')
442
- end
443
-
444
- def defaults_str
445
- "--version '> 0' --no-force"
446
- end
447
-
448
- def usage
449
- "#{program_name} GEMNAME [GEMNAME ...]"
450
- end
451
-
452
- def arguments
453
- "GEMNAME name of gem to uninstall"
454
- end
455
-
456
- def execute
457
- get_all_gem_names.each do |gem_name|
458
- Gem::Uninstaller.new(gem_name, options).uninstall
459
- end
460
- end
461
- end
462
-
463
- ####################################################################
464
- class CertCommand < Command
465
- include CommandAids
466
-
467
- def initialize
468
- super(
469
- 'cert',
470
- 'Adjust RubyGems certificate settings',
471
- {
472
- })
473
-
474
- add_option('-a', '--add CERT', 'Add a trusted certificate.') do |value, options|
475
- cert = OpenSSL::X509::Certificate.new(File.read(value))
476
- Gem::Security.add_trusted_cert(cert)
477
- puts "Added #{cert.subject.to_s}"
478
- end
479
-
480
- add_option('-l', '--list', 'List trusted certificates.') do |value, options|
481
- glob_str = File::join(Gem::Security::OPT[:trust_dir], '*.pem')
482
- Dir::glob(glob_str) do |path|
483
- cert = OpenSSL::X509::Certificate.new(File.read(path))
484
- # this could proably be formatted more gracefully
485
- puts cert.subject.to_s
486
- end
487
- end
488
-
489
- add_option('-r', '--remove STRING',
490
- 'Remove trusted certificates containing',
491
- 'STRING.') do |value, options|
492
- trust_dir = Gem::Security::OPT[:trust_dir]
493
- glob_str = File::join(trust_dir, '*.pem')
494
-
495
- Dir::glob(glob_str) do |path|
496
- cert = OpenSSL::X509::Certificate.new(File.read(path))
497
- if cert.subject.to_s.downcase.index(value)
498
- puts "Removing '#{cert.subject.to_s}'"
499
- File.unlink(path)
500
- end
501
- end
502
- end
503
-
504
- add_option('-b', '--build EMAIL_ADDR',
505
- 'Build private key and self-signed',
506
- 'certificate for EMAIL_ADDR.') do |value, options|
507
- vals = Gem::Security::build_self_signed_cert(value)
508
- File::chmod(0600, vals[:key_path])
509
- puts "Public Cert: #{vals[:cert_path]}",
510
- "Private Key: #{vals[:key_path]}",
511
- "Don't forget to move the key file to somewhere private..."
512
- end
513
-
514
- add_option('-C', '--certificate CERT',
515
- 'Certificate for --sign command.') do |value, options|
516
- cert = OpenSSL::X509::Certificate.new(File.read(value))
517
- Gem::Security::OPT[:issuer_cert] = cert
518
- end
519
-
520
- add_option('-K', '--private-key KEY',
521
- 'Private key for --sign command.') do |value, options|
522
- key = OpenSSL::PKey::RSA.new(File.read(value))
523
- Gem::Security::OPT[:issuer_key] = key
524
- end
525
-
526
-
527
- add_option('-s', '--sign NEWCERT',
528
- 'Sign a certificate with my key and',
529
- 'certificate.') do |value, options|
530
- cert = OpenSSL::X509::Certificate.new(File.read(value))
531
- my_cert = Gem::Security::OPT[:issuer_cert]
532
- my_key = Gem::Security::OPT[:issuer_key]
533
- cert = Gem::Security.sign_cert(cert, my_key, my_cert)
534
- File::open(value, 'wb') { |file| file.write(cert.to_pem) }
535
- end
536
-
537
- end
538
-
539
- def execute
540
- end
541
- end
542
-
543
- ####################################################################
544
- class DependencyCommand < Command
545
- include VersionOption
546
- include CommandAids
547
-
548
- def initialize
549
- super('dependency',
550
- 'Show the dependencies of an installed gem',
551
- {:version=>"> 0"})
552
- add_version_option('dependency')
553
- add_option('-r', '--[no-]reverse-dependencies',
554
- 'Include reverse dependencies in the output'
555
- ) do |value, options|
556
- options[:reverse_dependencies] = value
557
- end
558
- add_option('-p', '--pipe', "Pipe Format (name --version ver)") do |value, options|
559
- options[:pipe_format] = value
560
- end
561
- end
562
-
563
- def defaults_str
564
- "--version '> 0' --no-reverse"
565
- end
566
-
567
- def usage
568
- "#{program_name} GEMNAME"
569
- end
570
-
571
- def arguments
572
- "GEMNAME name of gems to show"
573
- end
574
-
575
- def execute
576
- specs = {}
577
- srcindex = SourceIndex.from_installed_gems
578
- options[:args] << '.' if options[:args].empty?
579
- options[:args].each do |name|
580
- speclist = srcindex.search(name, options[:version])
581
- if speclist.empty?
582
- say "No match found for #{name} (#{options[:version]})"
583
- else
584
- speclist.each do |spec|
585
- specs[spec.full_name] = spec
586
- end
587
- end
588
- end
589
- reverse = Hash.new { |h, k| h[k] = [] }
590
- if options[:reverse_dependencies]
591
- specs.values.each do |spec|
592
- reverse[spec.full_name] = find_reverse_dependencies(spec, srcindex)
593
- end
594
- end
595
- if options[:pipe_format]
596
- specs.values.sort.each do |spec|
597
- unless spec.dependencies.empty?
598
- spec.dependencies.each do |dep|
599
- puts "#{dep.name} --version '#{dep.version_requirements}'"
600
- end
601
- end
602
- end
603
- else
604
- response = ''
605
- specs.values.sort.each do |spec|
606
- response << print_dependencies(spec)
607
- unless reverse[spec.full_name].empty?
608
- response << " Used by\n"
609
- reverse[spec.full_name].each do |sp, dep|
610
- response << " #{sp} (#{dep})\n"
611
- end
612
- end
613
- response << "\n"
614
- end
615
- say response
616
- end
617
- end
618
-
619
- def print_dependencies(spec, level = 0)
620
- response = ''
621
- response << ' ' * level + "Gem #{spec.full_name}\n"
622
- unless spec.dependencies.empty?
623
- # response << ' ' * level + " Requires\n"
624
- spec.dependencies.each do |dep|
625
- response << ' ' * level + " #{dep}\n"
626
- end
627
- end
628
- response
629
- end
630
-
631
- # Retuns list of [specification, dep] that are satisfied by spec.
632
- def find_reverse_dependencies(spec, srcindex)
633
- result = []
634
- srcindex.each do |name, sp|
635
- sp.dependencies.each do |dep|
636
- if spec.name == dep.name &&
637
- dep.version_requirements.satisfied_by?(spec.version)
638
- result << [sp.full_name, dep]
639
- end
640
- end
641
- end
642
- result
643
- end
644
-
645
- end
646
-
647
- ####################################################################
648
- class CheckCommand < Command
649
- include CommandAids
650
-
651
- def initialize
652
- super('check', 'Check installed gems',
653
- {:verify => false, :alien => false})
654
-
655
- add_option('-v', '--verify FILE',
656
- 'Verify gem file against its internal',
657
- 'checksum') do |value, options|
658
- options[:verify] = value
659
- end
660
-
661
- add_option('-a', '--alien', "Report 'unmanaged' or rogue files in the",
662
- "gem repository") do |value, options|
663
- options[:alien] = true
664
- end
665
-
666
- add_option('-t', '--test', "Run unit tests for gem") do |value, options|
667
- options[:test] = true
668
- end
669
-
670
- add_option('-V', '--version',
671
- "Specify version for which to run unit tests") do |value, options|
672
- options[:version] = value
673
- end
674
- end
675
-
676
- def execute
677
- if options[:test]
678
- version = options[:version] || "> 0.0.0"
679
- gem_spec = Gem::SourceIndex.from_installed_gems.search(get_one_gem_name, version).first
680
- Gem::Validator.new.unit_test(gem_spec)
681
- end
682
- if options[:alien]
683
- say "Performing the 'alien' operation"
684
- Gem::Validator.new.alien.each do |key, val|
685
- if(val.size > 0)
686
- say "#{key} has #{val.size} problems"
687
- val.each do |error_entry|
688
- say "\t#{error_entry.path}:"
689
- say "\t#{error_entry.problem}"
690
- say
691
- end
692
- else
693
- say "#{key} is error-free"
694
- end
695
- say
696
- end
697
- end
698
- if options[:verify]
699
- gem_name = options[:verify]
700
- unless gem_name
701
- alert_error "Must specify a .gem file with --verify NAME"
702
- return
703
- end
704
- unless File.exist?(gem_name)
705
- alert_error "Unknown file: #{gem_name}."
706
- return
707
- end
708
- say "Verifying gem: '#{gem_name}'"
709
- begin
710
- Gem::Validator.new.verify_gem_file(gem_name)
711
- rescue Exception => e
712
- alert_error "#{gem_name} is invalid."
713
- end
714
- end
715
- end
716
-
717
- end # class
718
-
719
- ####################################################################
720
- class BuildCommand < Command
721
- include CommandAids
722
-
723
- def initialize
724
- super('build', 'Build a gem from a gemspec')
725
- end
726
-
727
- def usage
728
- "#{program_name} GEMSPEC_FILE"
729
- end
730
-
731
- def arguments
732
- "GEMSPEC_FILE name of gemspec file used to build the gem"
733
- end
734
-
735
- def execute
736
- gemspec = get_one_gem_name
737
- if File.exist?(gemspec)
738
- specs = load_gemspecs(gemspec)
739
- specs.each do |spec|
740
- Gem::Builder.new(spec).build
741
- end
742
- return
743
- else
744
- alert_error "Gemspec file not found: #{gemspec}"
745
- end
746
- end
747
-
748
- def load_gemspecs(filename)
749
- if yaml?(filename)
750
- require 'yaml'
751
- result = []
752
- open(filename) do |f|
753
- begin
754
- while spec = Gem::Specification.from_yaml(f)
755
- result << spec
756
- end
757
- rescue EndOfYAMLException => e
758
- # OK
759
- end
760
- end
761
- else
762
- result = [Gem::Specification.load(filename)]
763
- end
764
- result
765
- end
766
-
767
- def yaml?(filename)
768
- line = open(filename) { |f| line = f.gets }
769
- result = line =~ %r{^--- *!ruby/object:Gem::Specification}
770
- result
771
- end
772
-
773
- end
774
-
775
- ####################################################################
776
- class QueryCommand < Command
777
- include LocalRemoteOptions
778
-
779
- def initialize(name='query', summary='Query gem information in local or remote repositories')
780
- super(name,
781
- summary,
782
- {:name=>/.*/, :domain=>:local, :details=>false}
783
- )
784
- add_option('-n', '--name-matches REGEXP', 'Name of gem(s) to query on matches the provided REGEXP') do |value, options|
785
- options[:name] = /#{value}/i
786
- end
787
- add_option('-d', '--[no-]details', 'Display detailed information of gem(s)') do |value, options|
788
- options[:details] = value
789
- end
790
- add_local_remote_options
791
- end
792
-
793
- def defaults_str
794
- "--local --name-matches '.*' --no-details"
795
- end
796
-
797
- def execute
798
- if local?
799
- say
800
- say "*** LOCAL GEMS ***"
801
- output_query_results(Gem::cache.search(options[:name]))
802
- end
803
- if remote?
804
- say
805
- say "*** REMOTE GEMS ***"
806
- output_query_results(Gem::SourceInfoCache.search(options[:name]))
807
- end
808
- end
809
-
810
- private
811
-
812
- def output_query_results(gemspecs)
813
- gem_list_with_version = {}
814
- gemspecs.flatten.each do |gemspec|
815
- gem_list_with_version[gemspec.name] ||= []
816
- gem_list_with_version[gemspec.name] << gemspec
817
- end
818
-
819
- gem_list_with_version = gem_list_with_version.sort do |first, second|
820
- first[0].downcase <=> second[0].downcase
821
- end
822
- gem_list_with_version.each do |gem_name, list_of_matching|
823
- say
824
- list_of_matching = list_of_matching.sort_by { |x| x.version }.reverse
825
- seen_versions = []
826
- list_of_matching.delete_if do |item|
827
- if(seen_versions.member?(item.version))
828
- true
829
- else
830
- seen_versions << item.version
831
- false
832
- end
833
- end
834
- say "#{gem_name} (#{list_of_matching.map{|gem| gem.version.to_s}.join(", ")})"
835
- say format_text(list_of_matching[0].summary, 68, 4)
836
- end
837
- end
838
-
839
- ##
840
- # Used for wrapping and indenting text
841
- #
842
- def format_text(text, wrap, indent=0)
843
- result = []
844
- pattern = Regexp.new("^(.{0,#{wrap}})[ \n]")
845
- work = text.dup
846
- while work.length > wrap
847
- if work =~ pattern
848
- result << $1
849
- work.slice!(0, $&.length)
850
- else
851
- result << work.slice!(0, wrap)
852
- end
853
- end
854
- result << work if work.length.nonzero?
855
- result.join("\n").gsub(/^/, " " * indent)
856
- end
190
+ def self.load_commands(*command_names)
191
+ command_names.each{|name|
192
+ require "rubygems/commands/#{name}_command"
193
+ }
857
194
  end
858
-
859
- ####################################################################
860
- class ListCommand < QueryCommand
861
- include CommandAids
862
-
863
- def initialize
864
- super(
865
- 'list',
866
- 'Display all gems whose name starts with STRING'
867
- )
868
- remove_option('--name-matches')
869
- end
870
-
871
- def defaults_str
872
- "--local --no-details"
873
- end
874
-
875
- def usage
876
- "#{program_name} [STRING]"
877
- end
878
-
879
- def arguments
880
- "STRING start of gem name to look for"
881
- end
882
-
883
- def execute
884
- string = get_one_optional_argument || ''
885
- options[:name] = /^#{string}/i
886
- super
887
- end
888
- end
889
-
890
- ####################################################################
891
- class SearchCommand < QueryCommand
892
- include CommandAids
893
-
894
- def initialize
895
- super(
896
- 'search',
897
- 'Display all gems whose name contains STRING'
898
- )
899
- remove_option('--name-matches')
900
- end
901
-
902
- def defaults_str
903
- "--local --no-details"
904
- end
905
-
906
- def usage
907
- "#{program_name} [STRING]"
908
- end
909
-
910
- def arguments
911
- "STRING fragment of gem name to look for"
912
- end
913
-
914
- def execute
915
- string = get_one_optional_argument
916
- options[:name] = /#{string}/i
917
- super
918
- end
919
- end
920
-
921
- ####################################################################
922
- class UpdateCommand < Command
923
- include InstallUpdateOptions
924
-
925
- def initialize
926
- super(
927
- 'update',
928
- 'Update the named gem (or all installed gems) in the local repository',
929
- {
930
- :generate_rdoc => true,
931
- :generate_ri => true,
932
- :force => false,
933
- :test => false,
934
- :install_dir => Gem.dir
935
- })
936
- add_install_update_options
937
- add_option('--system',
938
- 'Update the RubyGems system software') do |value, options|
939
- options[:system] = value
940
- end
941
- end
942
-
943
- def defaults_str
944
- "--rdoc --ri --no-force --no-test\n" +
945
- "--install-dir #{Gem.dir}"
946
- end
947
-
948
- def arguments
949
- "GEMNAME(s) name of gem(s) to update"
950
- end
951
-
952
- def execute
953
- if options[:system]
954
- say "Updating RubyGems..."
955
- if ! options[:args].empty?
956
- fail "No gem names are allowed with the --system option"
957
- end
958
- options[:args] = ["rubygems-update"]
959
- else
960
- say "Updating installed gems..."
961
- end
962
- hig = highest_installed_gems = {}
963
- Gem::SourceIndex.from_installed_gems.each do |name, spec|
964
- if hig[spec.name].nil? or hig[spec.name].version < spec.version
965
- hig[spec.name] = spec
966
- end
967
- end
968
- remote_gemspecs = Gem::SourceInfoCache.search(//)
969
- gems_to_update = if(options[:args].empty?) then
970
- which_to_update(highest_installed_gems, remote_gemspecs)
971
- else
972
- options[:args]
973
- end
974
- options[:domain] = :remote # install from remote source
975
- install_command = command_manager['install']
976
- gems_to_update.uniq.sort.each do |name|
977
- say "Attempting remote update of #{name}"
978
- options[:args] = [name]
979
- install_command.merge_options(options)
980
- install_command.execute
981
- end
982
- if gems_to_update.include?("rubygems-update")
983
- latest_ruby_gem = remote_gemspecs.select { |s|
984
- s.name == 'rubygems-update'
985
- }.sort_by { |s|
986
- s.version
987
- }.last
988
- say "Updating version of RubyGems to #{latest_ruby_gem.version}"
989
- do_rubygems_update(latest_ruby_gem.version.to_s)
990
- end
991
- if(options[:system]) then
992
- say "RubyGems system software updated"
993
- else
994
- say "Gems: [#{gems_to_update.uniq.sort.collect{|g| g.to_s}.join(', ')}] updated"
995
- end
996
- end
997
-
998
- def do_rubygems_update(version_string)
999
- update_dir = File.join(Gem.dir, "gems", "rubygems-update-#{version_string}")
1000
- Dir.chdir(update_dir) do
1001
- puts "Installing RubyGems #{version_string}"
1002
- system "#{Gem.ruby} setup.rb"
1003
- end
1004
- end
1005
-
1006
- def which_to_update(highest_installed_gems, remote_gemspecs)
1007
- result = []
1008
- highest_installed_gems.each do |l_name, l_spec|
1009
- highest_remote_gem =
1010
- remote_gemspecs.select { |spec| spec.name == l_name }.
1011
- sort_by { |spec| spec.version }.
1012
- last
1013
- if highest_remote_gem and l_spec.version < highest_remote_gem.version
1014
- result << l_name
1015
- end
1016
- end
1017
- result
1018
- end
1019
- end
1020
-
1021
- ####################################################################
1022
- class CleanupCommand < Command
1023
- def initialize
1024
- super(
1025
- 'cleanup',
1026
- 'Clean up old versions of installed gems in the local repository',
1027
- {
1028
- :force => false,
1029
- :test => false,
1030
- :install_dir => Gem.dir
1031
- })
1032
- add_option('-d', '--dryrun', "") do |value, options|
1033
- options[:dryrun] = true
1034
- end
1035
- end
1036
-
1037
- def defaults_str
1038
- "--no-dryrun"
1039
- end
1040
-
1041
- def arguments
1042
- "GEMNAME(s) name of gem(s) to cleanup"
1043
- end
1044
-
1045
- def execute
1046
- say "Cleaning up installed gems..."
1047
- srcindex = Gem::SourceIndex.from_installed_gems
1048
- primary_gems = {}
1049
- srcindex.each do |name, spec|
1050
- if primary_gems[spec.name].nil? or primary_gems[spec.name].version < spec.version
1051
- primary_gems[spec.name] = spec
1052
- end
1053
- end
1054
- gems_to_cleanup = []
1055
- if ! options[:args].empty?
1056
- options[:args].each do |gem_name|
1057
- specs = Gem.cache.search(/^#{gem_name}$/i)
1058
- specs.each do |spec|
1059
- gems_to_cleanup << spec
1060
- end
1061
- end
1062
- else
1063
- srcindex.each do |name, spec|
1064
- gems_to_cleanup << spec
1065
- end
1066
- end
1067
- gems_to_cleanup = gems_to_cleanup.select { |spec|
1068
- primary_gems[spec.name].version != spec.version
1069
- }
1070
- uninstall_command = command_manager['uninstall']
1071
- deplist = DependencyList.new
1072
- gems_to_cleanup.uniq.each do |spec| deplist.add(spec) end
1073
- deplist.dependency_order.each do |spec|
1074
- if options[:dryrun]
1075
- say "Dry Run Mode: Would uninstall #{spec.full_name}"
1076
- else
1077
- say "Attempting uninstall on #{spec.full_name}"
1078
- options[:args] = [spec.name]
1079
- options[:version] = "= #{spec.version}"
1080
- options[:executables] = true
1081
- uninstall_command.merge_options(options)
1082
- begin
1083
- uninstall_command.execute
1084
- rescue Gem::DependencyRemovalException => ex
1085
- say "Unable to uninstall #{spec.full_name} ... continuing with remaining gems"
1086
- end
1087
- end
1088
- end
1089
- say "Clean Up Complete"
1090
- end
1091
- end
1092
-
1093
- ####################################################################
1094
- class PristineCommand < Command
1095
- include VersionOption
1096
- include CommandAids
1097
- def initialize
1098
- super('pristine',
1099
- 'Restores gem directories to pristine condition from files located in the gem cache',
1100
- {
1101
- :version => "> 0.0.0"
1102
- })
1103
- add_option('--all',
1104
- 'Restore all installed gems to pristine', 'condition'
1105
- ) do |value, options|
1106
- options[:all] = value
1107
- end
1108
- add_version_option('restore to', 'pristine condition')
1109
- end
1110
-
1111
- def defaults_str
1112
- "--all"
1113
- end
1114
-
1115
- def usage
1116
- "#{program_name} [args]"
1117
- end
1118
-
1119
- def arguments
1120
- "GEMNAME The gem to restore to pristine condition (unless --all)"
1121
- end
1122
-
1123
- def execute
1124
- say "Restoring gem(s) to pristine condition..."
1125
- if options[:all]
1126
- all_gems = true
1127
- specs = Gem::SourceIndex.from_installed_gems.collect do |name, spec|
1128
- spec
1129
- end
1130
- else
1131
- all_gems = false
1132
- gem_name = get_one_gem_name
1133
- specs = Gem::SourceIndex.from_installed_gems.search(gem_name, options[:version])
1134
- end
1135
-
1136
- if specs.empty?
1137
- fail "Failed to find gem #{gem_name} #{options[:version]} to restore to pristine condition"
1138
- end
1139
- install_dir = Gem.dir # TODO use installer option
1140
- raise Gem::FilePermissionError.new(install_dir) unless File.writable?(install_dir)
1141
-
1142
- gems_were_pristine = true
1143
-
1144
- specs.each do |spec|
1145
- installer = Gem::Installer.new nil, :wrappers => true # HACK ugly TODO use installer option
1146
-
1147
- gem_file = File.join(install_dir, "cache", "#{spec.full_name}.gem")
1148
- security_policy = nil # TODO use installer option
1149
- format = Gem::Format.from_file_by_path(gem_file, security_policy)
1150
- target_directory = File.join(install_dir, "gems", format.spec.full_name).untaint
1151
- pristine_files = format.file_entries.collect {|data| data[0]["path"]}
1152
- file_map = {}
1153
- format.file_entries.each {|entry, file_data| file_map[entry["path"]] = file_data}
1154
- require 'fileutils'
1155
-
1156
- Dir.chdir target_directory do
1157
- deployed_files = Dir.glob(File.join("**", "*")) +
1158
- Dir.glob(File.join("**", ".*"))
1159
- to_redeploy = (pristine_files - deployed_files).collect {|path| path.untaint}
1160
- if to_redeploy.length > 0
1161
- gems_were_pristine = false
1162
- say "Restoring #{to_redeploy.length} file#{to_redeploy.length == 1 ? "" : "s"} to #{spec.full_name}..."
1163
- to_redeploy.each do |path|
1164
- say " #{path}"
1165
- FileUtils.mkdir_p File.dirname(path)
1166
- File.open(path, "wb") do |out|
1167
- out.write file_map[path]
1168
- end
1169
- end
1170
- end
1171
- end
1172
-
1173
- installer.generate_bin spec, install_dir
1174
- end
1175
-
1176
- say "Rebuilt all bin stubs"
1177
-
1178
- if gems_were_pristine
1179
- if all_gems
1180
- say "All installed gem files are already in pristine condition"
1181
- else
1182
- say "#{specs[0].full_name} is already in pristine condition"
1183
- end
1184
- else
1185
- if all_gems
1186
- say "All installed gem files restored to pristine condition"
1187
- else
1188
- say "#{specs[0].full_name} restored to pristine condition"
1189
- end
1190
- end
1191
- end
1192
- end
1193
-
1194
- ####################################################################
1195
- class RDocCommand < Command
1196
- include VersionOption
1197
- include CommandAids
1198
-
1199
- def initialize
1200
- super('rdoc',
1201
- 'Generates RDoc for pre-installed gems',
1202
- {
1203
- :version => "> 0.0.0",
1204
- :include_rdoc => true,
1205
- :include_ri => true,
1206
- })
1207
- add_option('--all',
1208
- 'Generate RDoc/RI documentation for all',
1209
- 'installed gems') do |value, options|
1210
- options[:all] = value
1211
- end
1212
- add_option('--[no-]rdoc',
1213
- 'Include RDoc generated documents') do
1214
- |value, options|
1215
- options[:include_rdoc] = value
1216
- end
1217
- add_option('--[no-]ri',
1218
- 'Include RI generated documents'
1219
- ) do |value, options|
1220
- options[:include_ri] = value
1221
- end
1222
- add_version_option('rdoc')
1223
- end
1224
-
1225
- def defaults_str
1226
- "--version '> 0.0.0' --rdoc --ri"
1227
- end
1228
-
1229
- def usage
1230
- "#{program_name} [args]"
1231
- end
1232
-
1233
- def arguments
1234
- "GEMNAME The gem to generate RDoc for (unless --all)"
1235
- end
1236
-
1237
- def execute
1238
- if options[:all]
1239
- specs = Gem::SourceIndex.from_installed_gems.collect { |name, spec|
1240
- spec
1241
- }
1242
- else
1243
- gem_name = get_one_gem_name
1244
- specs = Gem::SourceIndex.from_installed_gems.search(
1245
- gem_name, options[:version])
1246
- end
1247
-
1248
- if specs.empty?
1249
- fail "Failed to find gem #{gem_name} to generate RDoc for #{options[:version]}"
1250
- end
1251
- if options[:include_ri]
1252
- specs.each do |spec|
1253
- Gem::DocManager.new(spec).generate_ri
1254
- end
1255
- end
1256
- if options[:include_rdoc]
1257
- specs.each do |spec|
1258
- Gem::DocManager.new(spec).generate_rdoc
1259
- end
1260
- end
1261
-
1262
- true
1263
- end
1264
- end
1265
-
1266
- ####################################################################
1267
- class EnvironmentCommand < Command
1268
- include CommandAids
1269
-
1270
- def initialize
1271
- super('environment', 'Display information about the RubyGems environment')
1272
- end
1273
-
1274
- def usage
1275
- "#{program_name} [args]"
1276
- end
1277
-
1278
- def arguments
1279
- args = <<-EOF
1280
- packageversion display the package version
1281
- gemdir display the path where gems are installed
1282
- gempath display path used to search for gems
1283
- version display the gem format version
1284
- remotesources display the remote gem servers
1285
- <omitted> display everything
1286
- EOF
1287
- return args.gsub(/^\s+/, '')
1288
- end
1289
-
1290
- def execute
1291
- out = ''
1292
- arg = options[:args][0]
1293
- if begins?("packageversion", arg)
1294
- out = Gem::RubyGemsPackageVersion.to_s
1295
- elsif begins?("version", arg)
1296
- out = Gem::RubyGemsVersion.to_s
1297
- elsif begins?("gemdir", arg)
1298
- out = Gem.dir
1299
- elsif begins?("gempath", arg)
1300
- Gem.path.collect { |p| out << "#{p}\n" }
1301
- elsif begins?("remotesources", arg)
1302
- require 'sources'
1303
- out << Gem.sources.join("\n") << "\n"
1304
- elsif arg
1305
- fail Gem::CommandLineError, "Unknown enviroment option [#{arg}]"
1306
- else
1307
- out = "RubyGems Environment:\n"
1308
- out << " - VERSION: #{Gem::RubyGemsVersion} (#{Gem::RubyGemsPackageVersion})\n"
1309
- out << " - INSTALLATION DIRECTORY: #{Gem.dir}\n"
1310
- out << " - GEM PATH:\n"
1311
- Gem.path.collect { |p| out << " - #{p}\n" }
1312
- out << " - REMOTE SOURCES:\n"
1313
- require 'sources'
1314
- Gem.sources.collect do |s|
1315
- out << " - #{s}\n"
1316
- end
1317
- end
1318
- say out
1319
- true
1320
- end
1321
- end
1322
-
1323
- ####################################################################
1324
- class SpecificationCommand < Command
1325
- include VersionOption
1326
- include LocalRemoteOptions
1327
- include CommandAids
1328
-
1329
- def initialize
1330
- super('specification', 'Display gem specification (in yaml)',
1331
- {:domain=>:local, :version=>"> 0.0.0"})
1332
- add_version_option('examine')
1333
- add_local_remote_options
1334
- add_option('--all', 'Output specifications for all versions of',
1335
- 'the gem') do |value, options|
1336
- options[:all] = true
1337
- end
1338
- end
1339
-
1340
- def defaults_str
1341
- "--local --version '(latest)'"
1342
- end
1343
-
1344
- def usage
1345
- "#{program_name} GEMFILE"
1346
- end
1347
-
1348
- def arguments
1349
- "GEMFILE Name of a .gem file to examine"
1350
- end
1351
-
1352
- def execute
1353
- if local?
1354
- gem = get_one_gem_name
1355
- gem_specs = Gem::SourceIndex.from_installed_gems.search(gem, options[:version])
1356
- unless gem_specs.empty?
1357
- require 'yaml'
1358
- output = lambda { |spec| say spec.to_yaml; say "\n" }
1359
- if options[:all]
1360
- gem_specs.each(&output)
1361
- else
1362
- spec = gem_specs.sort_by { |spec| spec.version }.last
1363
- output[spec]
1364
- end
1365
- else
1366
- alert_error "Unknown gem #{gem}"
1367
- end
1368
- end
1369
-
1370
- if remote?
1371
- say "(Remote 'info' operation is not yet implemented.)"
1372
- # NOTE: when we do implement remote info, make sure we don't
1373
- # duplicate huge swabs of local data. If it's the same, just
1374
- # say it's the same.
1375
- end
1376
- end
1377
- end
1378
-
1379
- ####################################################################
1380
- class UnpackCommand < Command
1381
- include VersionOption
1382
- include CommandAids
1383
-
1384
- def initialize
1385
- super(
1386
- 'unpack',
1387
- 'Unpack an installed gem to the current directory',
1388
- { :version => '> 0' }
1389
- )
1390
- add_version_option('unpack')
1391
- end
1392
-
1393
- def defaults_str
1394
- "--version '> 0'"
1395
- end
1396
-
1397
- def usage
1398
- "#{program_name} GEMNAME"
1399
- end
1400
-
1401
- def arguments
1402
- "GEMNAME Name of the gem to unpack"
1403
- end
1404
-
1405
- # TODO: allow, e.g., 'gem unpack rake-0.3.1'. Find a general
1406
- # solution for this, so that it works for uninstall as well. (And
1407
- # check other commands at the same time.)
1408
- def execute
1409
- gemname = get_one_gem_name
1410
- path = get_path(gemname, options[:version])
1411
- if path
1412
- require 'fileutils'
1413
- target_dir = File.basename(path).sub(/\.gem$/, '')
1414
- FileUtils.mkdir_p target_dir
1415
- Installer.new(path).unpack(File.expand_path(target_dir))
1416
- say "Unpacked gem: '#{target_dir}'"
1417
- else
1418
- alert_error "Gem '#{gemname}' not installed."
1419
- end
1420
- end
1421
-
1422
- # Return the full path to the cached gem file matching the given
1423
- # name and version requirement. Returns 'nil' if no match.
1424
- # Example:
1425
- #
1426
- # get_path('rake', '> 0.4') # -> '/usr/lib/ruby/gems/1.8/cache/rake-0.4.2.gem'
1427
- # get_path('rake', '< 0.1') # -> nil
1428
- # get_path('rak') # -> nil (exact name required)
1429
- #
1430
- # TODO: This should be refactored so that it's a general service.
1431
- # I don't think any of our existing classes are the right place
1432
- # though. Just maybe 'Cache'?
1433
- #
1434
- # TODO: It just uses Gem.dir for now. What's an easy way to get
1435
- # the list of source directories?
1436
- #
1437
- def get_path(gemname, version_req)
1438
- return gemname if gemname =~ /\.gem$/i
1439
- specs = SourceIndex.from_installed_gems.search(gemname, version_req)
1440
- selected = specs.sort_by { |s| s.version }.last
1441
- return nil if selected.nil?
1442
- # We expect to find (basename).gem in the 'cache' directory.
1443
- # Furthermore, the name match must be exact (ignoring case).
1444
- if gemname =~ /^#{selected.name}$/i
1445
- filename = selected.full_name + '.gem'
1446
- return File.join(Gem.dir, 'cache', filename)
1447
- else
1448
- return nil
1449
- end
1450
- end
1451
- end
1452
-
1453
- ####################################################################
1454
- class HelpCommand < Command
1455
- include CommandAids
1456
-
1457
- def initialize
1458
- super('help', "Provide help on the 'gem' command")
1459
- end
1460
-
1461
- def usage
1462
- "#{program_name} ARGUMENT"
1463
- end
1464
-
1465
- def arguments
1466
- args = <<-EOF
1467
- commands List all 'gem' commands
1468
- examples Show examples of 'gem' usage
1469
- <command> Show specific help for <command>
1470
- EOF
1471
- return args.gsub(/^\s+/, '')
1472
- end
1473
-
1474
- def execute
1475
- arg = options[:args][0]
1476
- if begins?("commands", arg)
1477
- out = []
1478
- out << "GEM commands are:"
1479
- out << nil
1480
-
1481
- margin_width = 4
1482
- desc_width = command_manager.command_names.collect {|n| n.size}.max + 4
1483
- summary_width = 80 - margin_width - desc_width
1484
- wrap_indent = ' ' * (margin_width + desc_width)
1485
- format = "#{' ' * margin_width}%-#{desc_width}s%s"
1486
-
1487
- command_manager.command_names.each do |cmd_name|
1488
- summary = command_manager[cmd_name].summary
1489
- summary = wrap(summary, summary_width).split "\n"
1490
- out << sprintf(format, cmd_name, summary.shift)
1491
- until summary.empty? do
1492
- out << "#{wrap_indent}#{summary.shift}"
1493
- end
1494
- end
1495
-
1496
- out << nil
1497
- out << "For help on a particular command, use 'gem help COMMAND'."
1498
- out << nil
1499
- out << "Commands may be abbreviated, so long as they are unambiguous."
1500
- out << "e.g. 'gem i rake' is short for 'gem install rake'."
1501
-
1502
- say out.join("\n")
1503
-
1504
- elsif begins?("options", arg)
1505
- say Gem::HELP
1506
- elsif begins?("examples", arg)
1507
- say Gem::EXAMPLES
1508
- elsif options[:help]
1509
- command = command_manager[options[:help]]
1510
- if command
1511
- # help with provided command
1512
- command.invoke("--help")
1513
- else
1514
- alert_error "Unknown command #{options[:help]}. Try 'gem help commands'"
1515
- end
1516
- elsif arg
1517
- possibilities = command_manager.find_command_possibilities(arg.downcase)
1518
- if possibilities.size == 1
1519
- command = command_manager[possibilities.first]
1520
- command.invoke("--help")
1521
- elsif possibilities.size > 1
1522
- alert_warning "Ambiguous command #{arg} (#{possibilities.join(', ')})"
1523
- else
1524
- alert_warning "Unknown command #{arg}. Try gem help commands"
1525
- end
1526
- else
1527
- say Gem::HELP
1528
- end
1529
- end
1530
- end
1531
-
1532
- ####################################################################
1533
- class ContentsCommand < Command
1534
- include CommandAids
1535
- include VersionOption
1536
- def initialize
1537
- super(
1538
- 'contents',
1539
- 'Display the contents of the installed gems',
1540
- { :list => true, :specdirs => [] })
1541
-
1542
- add_version_option('contents')
1543
-
1544
- add_option("-l","--list",'List the files inside a Gem') do |v,o|
1545
- o[:list] = true
1546
- end
1547
-
1548
- add_option('-s','--spec-dir a,b,c', Array, "Search for gems under specific paths") do |v,o|
1549
- o[:specdirs] = v
1550
- end
1551
-
1552
- add_option('-V','--verbose','Be verbose when showing status') do |v,o|
1553
- o[:verbose] = v
1554
- end
1555
- end
1556
-
1557
- def execute(io=STDOUT)
1558
- if options[:list]
1559
- version = options[:version] || "> 0.0.0"
1560
- gem = get_one_gem_name
1561
-
1562
- s = options[:specdirs].map do |i|
1563
- [i, File.join(i,"specifications")]
1564
- end.flatten
1565
-
1566
- if s.empty?
1567
- s = Gem::SourceIndex.installed_spec_directories
1568
- path_kind = "default gem paths"
1569
- system = true
1570
- else
1571
- path_kind = "specified path"
1572
- system = false
1573
- end
1574
-
1575
- si = Gem::SourceIndex.from_gems_in(*s)
1576
-
1577
- gem_spec = si.search(gem, version).last
1578
- unless gem_spec
1579
- io.puts "Unable to find gem '#{gem}' in #{path_kind}"
1580
- if options[:verbose]
1581
- io.puts "\nDirectories searched:"
1582
- s.each do |p|
1583
- io.puts p
1584
- end
1585
- end
1586
- return
1587
- end
1588
- # show the list of files.
1589
- gem_spec.files.each do |f|
1590
- io.puts File.join(gem_spec.full_gem_path, f)
1591
- end
1592
- end
1593
- end
1594
- end
1595
-
1596
- end # module
195
+ end
1597
196
 
1598
197
  ######################################################################
1599
198
  # Documentation Constants