rubygems-update 0.8.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 (96) hide show
  1. data/ChangeLog +2335 -0
  2. data/README +54 -0
  3. data/Rakefile +293 -0
  4. data/Releases +98 -0
  5. data/TODO +7 -0
  6. data/bin/gem +11 -0
  7. data/bin/gem_server +111 -0
  8. data/bin/generate_yaml_index.rb +58 -0
  9. data/bin/update_rubygems +18 -0
  10. data/doc/doc.css +73 -0
  11. data/doc/makedoc.rb +4 -0
  12. data/examples/application/an-app.gemspec +26 -0
  13. data/examples/application/bin/myapp +3 -0
  14. data/examples/application/lib/somefunctionality.rb +3 -0
  15. data/gemspecs/README +4 -0
  16. data/gemspecs/cgikit-1.1.0.gemspec +18 -0
  17. data/gemspecs/jabber4r.gemspec +26 -0
  18. data/gemspecs/linguistics.gemspec +22 -0
  19. data/gemspecs/ook.gemspec +21 -0
  20. data/gemspecs/progressbar.gemspec +22 -0
  21. data/gemspecs/redcloth.gemspec +22 -0
  22. data/gemspecs/rublog.gemspec +23 -0
  23. data/gemspecs/ruby-doom.gemspec +21 -0
  24. data/gemspecs/rubyjdwp.gemspec +21 -0
  25. data/gemspecs/statistics.gemspec +21 -0
  26. data/lib/rubygems.rb +353 -0
  27. data/lib/rubygems/builder.rb +54 -0
  28. data/lib/rubygems/cmd_manager.rb +127 -0
  29. data/lib/rubygems/command.rb +191 -0
  30. data/lib/rubygems/config_file.rb +57 -0
  31. data/lib/rubygems/doc_manager.rb +94 -0
  32. data/lib/rubygems/format.rb +65 -0
  33. data/lib/rubygems/gem_commands.rb +925 -0
  34. data/lib/rubygems/gem_runner.rb +23 -0
  35. data/lib/rubygems/installer.rb +621 -0
  36. data/lib/rubygems/loadpath_manager.rb +108 -0
  37. data/lib/rubygems/old_format.rb +150 -0
  38. data/lib/rubygems/open-uri.rb +604 -0
  39. data/lib/rubygems/package.rb +740 -0
  40. data/lib/rubygems/remote_installer.rb +499 -0
  41. data/lib/rubygems/rubygems_version.rb +6 -0
  42. data/lib/rubygems/source_index.rb +130 -0
  43. data/lib/rubygems/specification.rb +613 -0
  44. data/lib/rubygems/user_interaction.rb +176 -0
  45. data/lib/rubygems/validator.rb +148 -0
  46. data/lib/rubygems/version.rb +279 -0
  47. data/lib/ubygems.rb +4 -0
  48. data/pkgs/sources/lib/sources.rb +6 -0
  49. data/pkgs/sources/sources.gemspec +14 -0
  50. data/post-install.rb +75 -0
  51. data/redist/session.gem +433 -0
  52. data/scripts/buildtests.rb +25 -0
  53. data/scripts/gemdoc.rb +62 -0
  54. data/scripts/runtest.rb +17 -0
  55. data/scripts/specdoc.rb +164 -0
  56. data/setup.rb +1360 -0
  57. data/test/bogussources.rb +5 -0
  58. data/test/data/legacy/keyedlist-0.4.0.ruby +11 -0
  59. data/test/data/legacy/keyedlist-0.4.0.yaml +16 -0
  60. data/test/data/lib/code.rb +1 -0
  61. data/test/data/one/README.one +1 -0
  62. data/test/data/one/lib/one.rb +3 -0
  63. data/test/data/one/one.gemspec +17 -0
  64. data/test/data/one/one.yaml +40 -0
  65. data/test/functional.rb +145 -0
  66. data/test/gemenvironment.rb +45 -0
  67. data/test/gemutilities.rb +18 -0
  68. data/test/insure_session.rb +46 -0
  69. data/test/mock/gems/gems/sources-0.0.1/lib/sources.rb +5 -0
  70. data/test/mock/gems/specifications/sources-0.0.1.gemspec +8 -0
  71. data/test/mockgemui.rb +45 -0
  72. data/test/onegem.rb +23 -0
  73. data/test/simple_gem.rb +66 -0
  74. data/test/test_builder.rb +13 -0
  75. data/test/test_cached_fetcher.rb +60 -0
  76. data/test/test_check_command.rb +28 -0
  77. data/test/test_command.rb +130 -0
  78. data/test/test_configfile.rb +36 -0
  79. data/test/test_format.rb +70 -0
  80. data/test/test_gemloadpaths.rb +45 -0
  81. data/test/test_gempaths.rb +115 -0
  82. data/test/test_loadmanager.rb +40 -0
  83. data/test/test_local_cache.rb +157 -0
  84. data/test/test_package.rb +600 -0
  85. data/test/test_parse_commands.rb +179 -0
  86. data/test/test_process_commands.rb +21 -0
  87. data/test/test_remote_fetcher.rb +162 -0
  88. data/test/test_remote_installer.rb +154 -0
  89. data/test/test_source_index.rb +58 -0
  90. data/test/test_specification.rb +286 -0
  91. data/test/test_validator.rb +53 -0
  92. data/test/test_version_comparison.rb +204 -0
  93. data/test/testgem.rc +6 -0
  94. data/test/user_capture.rb +1 -0
  95. data/test/yaml_data.rb +59 -0
  96. metadata +151 -0
@@ -0,0 +1,65 @@
1
+ require 'rubygems/package'
2
+
3
+ module Gem
4
+
5
+ ##
6
+ # The format class knows the guts of the RubyGem .gem file format
7
+ # and provides the capability to read gem files
8
+ #
9
+ class Format
10
+ attr_accessor :spec, :file_entries, :gem_path
11
+ extend Gem::UserInteraction
12
+
13
+ ##
14
+ # Constructs an instance of a Format object, representing the gem's
15
+ # data structure.
16
+ #
17
+ # gem:: [String] The file name of the gem
18
+ #
19
+ def initialize(gem_path)
20
+ @gem_path = gem_path
21
+ end
22
+
23
+ ##
24
+ # Reads the named gem file and returns a Format object, representing
25
+ # the data from the gem file
26
+ #
27
+ # file_path:: [String] Path to the gem file
28
+ #
29
+ def self.from_file_by_path(file_path)
30
+ unless File.exist?(file_path)
31
+ raise Gem::Exception, "Cannot load gem at [#{file_path}]"
32
+ end
33
+ require 'fileutils'
34
+ # check for old version gem
35
+ if File.read(file_path, 20).include?("MD5SUM =")
36
+ #alert_warning "Gem #{file_path} is in old format."
37
+ require 'rubygems/old_format'
38
+ return OldFormat.from_file_by_path(file_path)
39
+ else
40
+ f = File.open(file_path, 'rb')
41
+ return from_io(f, file_path)
42
+ end
43
+ end
44
+
45
+ ##
46
+ # Reads a gem from an io stream and returns a Format object, representing
47
+ # the data from the gem file
48
+ #
49
+ # io:: [IO] Stream from which to read the gem
50
+ #
51
+ def self.from_io(io, gem_path="(io)")
52
+ format = self.new(gem_path)
53
+ Package.open_from_io(io) do |pkg|
54
+ format.spec = pkg.metadata
55
+ format.file_entries = []
56
+ pkg.each do |entry|
57
+ format.file_entries << [{"size", entry.size, "mode", entry.mode,
58
+ "path", entry.full_name}, entry.read]
59
+ end
60
+ end
61
+ format
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,925 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Gem
4
+
5
+ class CommandLineError < Gem::Exception; end
6
+
7
+ module CommandAids
8
+ def get_one_gem_name
9
+ args = options[:args]
10
+ if args.nil? or args.empty?
11
+ fail Gem::CommandLineError,
12
+ "Please specify a gem name on the command line (e.g. gem build GEMNAME)"
13
+ end
14
+ if args.size > 1
15
+ fail Gem::CommandLineError,
16
+ "Too many gem names (#{args.join(', ')}); please specify only one"
17
+ end
18
+ args.first
19
+ end
20
+
21
+ def get_one_optional_argument
22
+ args = options[:args] || []
23
+ args.first
24
+ end
25
+
26
+ def begins?(long, short)
27
+ return false if short.nil?
28
+ long[0, short.length] == short
29
+ end
30
+ end
31
+
32
+ module LocalRemoteOptions
33
+ def add_local_remote_options
34
+ add_option('-l', '--local', 'Restrict operations to the LOCAL domain (default)') do |value, options|
35
+ options[:domain] = :local
36
+ end
37
+ add_option('-r', '--remote', 'Restrict operations to the REMOTE domain') do |value, options|
38
+ options[:domain] = :remote
39
+ end
40
+ add_option('-b', '--both', 'Allow LOCAL and REMOTE operations') do |value, options|
41
+ options[:domain] = :both
42
+ end
43
+ end
44
+
45
+ def local?
46
+ options[:domain] == :local || options[:domain] == :both
47
+ end
48
+
49
+ def remote?
50
+ options[:domain] == :remote || options[:domain] == :both
51
+ end
52
+ end
53
+
54
+ module InstallUpdateOptions
55
+ def add_install_update_options
56
+ add_option('-i', '--install-dir DIR', '') do |value, options|
57
+ options[:install_dir] = value
58
+ end
59
+ add_option('-d', '--[no-]rdoc', 'Generate RDoc documentation for the gem on install') do |value, options|
60
+ options[:generate_rdoc] = value
61
+ end
62
+ add_option('-f', '--[no-]force', 'Force gem to install, bypassing dependency checks') do |value, options|
63
+ options[:force] = value
64
+ end
65
+ add_option('-t', '--[no-]test', 'Run unit tests prior to installation') do |value, options|
66
+ options[:test] = value
67
+ end
68
+ end
69
+
70
+ def install_update_defaults_str
71
+ '--rdoc --no-force --no-test'
72
+ end
73
+ end
74
+
75
+ module VersionOption
76
+ def add_version_option(taskname)
77
+ add_option('-v', '--version VERSION', "Specify version of gem to #{taskname}") do |value, options|
78
+ options[:version] = value
79
+ end
80
+ end
81
+ end
82
+
83
+ ####################################################################
84
+ class InstallCommand < Command
85
+ include CommandAids
86
+ include VersionOption
87
+ include LocalRemoteOptions
88
+ include InstallUpdateOptions
89
+
90
+ def initialize
91
+ super(
92
+ 'install',
93
+ 'Install a gem into the local repository',
94
+ {
95
+ :domain => :both,
96
+ :generate_rdoc => true,
97
+ :force => false,
98
+ :test => false,
99
+ :version => "> 0",
100
+ :install_dir => Gem.dir
101
+ })
102
+ add_version_option('install')
103
+ add_local_remote_options
104
+ add_install_update_options
105
+ end
106
+
107
+
108
+ def usage
109
+ "#{program_name} GEMNAME"
110
+ end
111
+
112
+ def arguments
113
+ "GEMNAME name of gem to install"
114
+ end
115
+
116
+ def defaults_str
117
+ "--both --version '> 0' --rdoc --no-force --no-test\n" +
118
+ "--install-dir #{Gem.dir}"
119
+ end
120
+
121
+ def execute
122
+ ENV['GEM_PATH'] = options[:install_dir]
123
+ # TODO: If a dependency isn't met, first check to see if it's in
124
+ # the install list
125
+ if(options[:args].empty?)
126
+ fail Gem::CommandLineError,
127
+ "Please specify a gem name on the command line (e.g. gem build GEMNAME)"
128
+ end
129
+ options[:args].each do |gem_name|
130
+ if local?
131
+ begin
132
+ say "Attempting local installation of '#{gem_name}'"
133
+ entries = []
134
+ if(File.exist?(gem_name) && !File.directory?(gem_name))
135
+ entries << gem_name
136
+ else
137
+ filepattern = gem_name + "*.gem"
138
+ entries = Dir[filepattern]
139
+ end
140
+ unless entries.size > 0
141
+ if options[:domain] == :both
142
+ say "Local gem file not found: #{filepattern}"
143
+ else
144
+ alert_error "Local gem file not found: #{filepattern}"
145
+ end
146
+ else
147
+ result = Gem::Installer.new(entries.last).install(options[:force], options[:install_dir])
148
+ installed_gems = [result].flatten
149
+ say "Successfully installed #{installed_gems[0].name}, version #{installed_gems[0].version}" if installed_gems
150
+ end
151
+ rescue LocalInstallationError => e
152
+ say " -> Local installation can't proceed: #{e.message}"
153
+ rescue Gem::LoadError => e
154
+ say " -> Local installation can't proceed due to LoadError: #{e.message}"
155
+ rescue => e
156
+ alert_error "Error installing gem #{gem_name}[.gem]: #{e.message}"
157
+ return
158
+ end
159
+ end
160
+
161
+ if remote? && installed_gems.nil?
162
+ say "Attempting remote installation of '#{gem_name}'"
163
+ installer = Gem::RemoteInstaller.new(options[:http_proxy])
164
+ installed_gems = installer.install(gem_name, options[:version], options[:force], options[:install_dir])
165
+ say "Successfully installed #{installed_gems[0].name}, version #{installed_gems[0].version}" if installed_gems
166
+ end
167
+
168
+ unless installed_gems
169
+ alert_error "Could not install a local or remote copy of the gem: #{gem_name}"
170
+ terminate_interaction(1)
171
+ end
172
+
173
+ if options[:generate_rdoc]
174
+ installed_gems.each do |gem|
175
+ Gem::DocManager.new(gem, options[:rdoc_args]).generate_rdoc
176
+ end
177
+ # TODO: catch exceptions and inform user that doc generation was not successful.
178
+ end
179
+ if options[:test]
180
+ installed_gems.each do |spec|
181
+ gem_spec = Gem::SourceIndex.from_installed_gems.search(spec.name, spec.version.version).first
182
+ result = Gem::Validator.new.unit_test(gem_spec)
183
+ unless result.passed?
184
+ unless ask_yes_no("...keep Gem?", true) then
185
+ Gem::Uninstaller.new(spec.name, spec.version.version).uninstall
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ end
194
+
195
+ ####################################################################
196
+ class UninstallCommand < Command
197
+ include VersionOption
198
+ include CommandAids
199
+
200
+ def initialize
201
+ super('uninstall', 'Uninstall a gem from the local repository', {:version=>"> 0"})
202
+ add_version_option('uninstall')
203
+ end
204
+
205
+ def defaults_str
206
+ "--version '> 0'"
207
+ end
208
+
209
+ def usage
210
+ "#{program_name} GEMNAME"
211
+ end
212
+
213
+ def arguments
214
+ "GEMNAME name of gem to uninstall"
215
+ end
216
+
217
+ def execute
218
+ gem_name = get_one_gem_name
219
+ say "Attempting to uninstall gem '#{gem_name}'"
220
+ Gem::Uninstaller.new(gem_name, options[:version]).uninstall
221
+ end
222
+ end
223
+
224
+ ####################################################################
225
+ class CheckCommand < Command
226
+ include CommandAids
227
+
228
+ def initialize
229
+ super('check', 'Check installed gems', {:verify => false, :alien => false})
230
+ add_option('-v', '--verify FILE', 'Verify gem file against its internal checksum') do |value, options|
231
+ options[:verify] = value
232
+ end
233
+ add_option('-a', '--alien', "Report 'unmanaged' or rogue files in the gem repository") do |value, options|
234
+ options[:alien] = true
235
+ end
236
+ add_option('-t', '--test', "Run unit tests for gem") do |value, options|
237
+ options[:test] = true
238
+ end
239
+ add_option('-V', '--version', "Specify version for which to run unit tests") do |value, options|
240
+ options[:version] = value
241
+ end
242
+ end
243
+
244
+ def execute
245
+ if options[:test]
246
+ version = options[:version] || "> 0.0.0"
247
+ gem_spec = Gem::SourceIndex.from_installed_gems.search(get_one_gem_name, version).first
248
+ Gem::Validator.new.unit_test(gem_spec)
249
+ end
250
+ if options[:alien]
251
+ say "Performing the 'alien' operation"
252
+ Gem::Validator.new.alien.each do |key, val|
253
+ if(val.size > 0)
254
+ say "#{key} has #{val.size} problems"
255
+ val.each do |error_entry|
256
+ say "\t#{error_entry.path}:"
257
+ say "\t#{error_entry.problem}"
258
+ say
259
+ end
260
+ else
261
+ say "#{key} is error-free"
262
+ end
263
+ say
264
+ end
265
+ end
266
+ if options[:verify]
267
+ gem_name = options[:verify]
268
+ unless gem_name
269
+ alert_error "Must specifiy a .gem file with --verify NAME"
270
+ return
271
+ end
272
+ unless File.exist?(gem_name)
273
+ alert_error "Unknown file: #{gem_name}."
274
+ return
275
+ end
276
+ say "Verifying gem: '#{gem_name}'"
277
+ begin
278
+ Gem::Validator.new.verify_gem_file(gem_name)
279
+ rescue Exception => e
280
+ alert_error "#{gem_name} is invalid."
281
+ end
282
+ end
283
+ end
284
+
285
+ end # class
286
+
287
+ ####################################################################
288
+ class BuildCommand < Command
289
+ include CommandAids
290
+
291
+ def initialize
292
+ super('build', 'Build a gem from a gemspec')
293
+ end
294
+
295
+ def usage
296
+ "#{program_name} GEMSPEC_FILE"
297
+ end
298
+
299
+ def arguments
300
+ "GEMSPEC_FILE name of gemspec file used to build the gem"
301
+ end
302
+
303
+ def execute
304
+ gemspec = get_one_gem_name
305
+ if File.exist?(gemspec)
306
+ say "Attempting to build gem spec '#{gemspec}'"
307
+ specs = load_gemspecs(gemspec)
308
+ specs.each do |spec|
309
+ Gem::Builder.new(spec).build
310
+ end
311
+ return
312
+ else
313
+ alert_error "Gemspec file not found: #{gemspec}"
314
+ end
315
+ end
316
+
317
+ def load_gemspecs(filename)
318
+ if yaml?(filename)
319
+ require 'yaml'
320
+ result = []
321
+ open(filename) do |f|
322
+ begin
323
+ while spec = Gem::Specification.from_yaml(f)
324
+ result << spec
325
+ end
326
+ rescue EndOfYAMLException => e
327
+ # OK
328
+ end
329
+ end
330
+ else
331
+ result = [Gem::Specification.load(filename)]
332
+ end
333
+ result
334
+ end
335
+
336
+ def yaml?(filename)
337
+ line = open(filename) { |f| line = f.gets }
338
+ result = line =~ %r{^--- *!ruby/object:Gem::Specification}
339
+ result
340
+ end
341
+
342
+ end
343
+
344
+ ####################################################################
345
+ class QueryCommand < Command
346
+ include LocalRemoteOptions
347
+
348
+ def initialize(name='query', summary='Query gem information in local or remote repositories')
349
+ super(name,
350
+ summary,
351
+ {:name=>/.*/, :domain=>:local, :details=>false}
352
+ )
353
+ add_option('-n', '--name-matches REGEXP', 'Name of gem(s) to query on maches the provided REGEXP') do |value, options|
354
+ options[:name] = /#{value}/i
355
+ end
356
+ add_option('-d', '--[no-]details', 'Display detailed information of gem(s)') do |value, options|
357
+ options[:details] = value
358
+ end
359
+ add_local_remote_options
360
+ end
361
+
362
+ def defaults_str
363
+ "--local --name-matches '.*' --no-details"
364
+ end
365
+
366
+ def execute
367
+ if local?
368
+ say
369
+ say "*** LOCAL GEMS ***"
370
+ output_query_results(Gem::cache.search(options[:name]))
371
+ end
372
+ if remote?
373
+ say
374
+ say "*** REMOTE GEMS ***"
375
+ begin
376
+ output_query_results(Gem::RemoteInstaller.new(options[:http_proxy]).search(options[:name]))
377
+ rescue Gem::RemoteSourceException => e
378
+ alert_error e.to_s
379
+ end
380
+ end
381
+ end
382
+
383
+ private
384
+
385
+ def output_query_results(gemspecs)
386
+ gem_list_with_version = {}
387
+ gemspecs.flatten.each do |gemspec|
388
+ gem_list_with_version[gemspec.name] ||= []
389
+ gem_list_with_version[gemspec.name] << gemspec
390
+ end
391
+
392
+ gem_list_with_version = gem_list_with_version.sort do |first, second|
393
+ first[0].downcase <=> second[0].downcase
394
+ end
395
+ gem_list_with_version.each do |gem_name, list_of_matching|
396
+ say
397
+ list_of_matching = list_of_matching.sort_by { |x| x.version }.reverse
398
+ seen_versions = []
399
+ list_of_matching.delete_if do |item|
400
+ if(seen_versions.member?(item.version))
401
+ true
402
+ else
403
+ seen_versions << item.version
404
+ false
405
+ end
406
+ end
407
+ say "#{gem_name} (#{list_of_matching.map{|gem| gem.version.to_s}.join(", ")})"
408
+ say format_text(list_of_matching[0].summary, 68, 4)
409
+ end
410
+ end
411
+
412
+ ##
413
+ # Used for wrapping and indenting text
414
+ #
415
+ def format_text(text, wrap, indent=0)
416
+ result = []
417
+ pattern = Regexp.new("^(.{0,#{wrap}})[ \n]")
418
+ work = text.dup
419
+ while work.length > wrap
420
+ if work =~ pattern
421
+ result << $1
422
+ work.slice!(0, $&.length)
423
+ else
424
+ result << work.slice!(0, wrap)
425
+ end
426
+ end
427
+ result << work if work.length.nonzero?
428
+ result.join("\n").gsub(/^/, " " * indent)
429
+ end
430
+ end
431
+
432
+ ####################################################################
433
+ class ListCommand < QueryCommand
434
+ include CommandAids
435
+
436
+ def initialize
437
+ super(
438
+ 'list',
439
+ 'Display all gems whose name starts with STRING'
440
+ )
441
+ remove_option('--name-matches')
442
+ end
443
+
444
+ def defaults_str
445
+ "--local --no-details"
446
+ end
447
+
448
+ def usage
449
+ "#{program_name} [STRING]"
450
+ end
451
+
452
+ def arguments
453
+ "STRING start of gem name to look for"
454
+ end
455
+
456
+ def execute
457
+ string = get_one_optional_argument || ''
458
+ options[:name] = /^#{string}/i
459
+ super
460
+ end
461
+ end
462
+
463
+ ####################################################################
464
+ class SearchCommand < QueryCommand
465
+ include CommandAids
466
+
467
+ def initialize
468
+ super(
469
+ 'search',
470
+ 'Display all gems whose name contains STRING'
471
+ )
472
+ remove_option('--name-matches')
473
+ end
474
+
475
+ def defaults_str
476
+ "--local --no-details"
477
+ end
478
+
479
+ def usage
480
+ "#{program_name} [STRING]"
481
+ end
482
+
483
+ def arguments
484
+ "STRING fragment of gem name to look for"
485
+ end
486
+
487
+ def execute
488
+ string = get_one_optional_argument
489
+ options[:name] = /#{string}/i
490
+ super
491
+ end
492
+ end
493
+
494
+ ####################################################################
495
+ class UpdateCommand < Command
496
+ include InstallUpdateOptions
497
+
498
+ def initialize
499
+ super(
500
+ 'update',
501
+ 'Upgrade all currently installed gems in the local repository',
502
+ {
503
+ :generate_rdoc => true,
504
+ :force => false,
505
+ :test => false,
506
+ :install_dir => Gem.dir
507
+ })
508
+ add_install_update_options
509
+ end
510
+
511
+ def defaults_str
512
+ "--rdoc --no-force --no-test\n" +
513
+ "--install-dir #{Gem.dir}"
514
+ end
515
+
516
+ def execute
517
+ say "Upgrading installed gems..."
518
+ hig = highest_installed_gems = {}
519
+ Gem::SourceIndex.from_installed_gems.each do |name, spec|
520
+ if hig[spec.name].nil? or hig[spec.name].version < spec.version
521
+ hig[spec.name] = spec
522
+ end
523
+ end
524
+ remote_gemspecs = Gem::RemoteInstaller.new(options[:http_proxy]).search(//)
525
+ # For some reason, this is an array of arrays. The actual list of specifications is
526
+ # the first and only element. If there were more remote sources, perhaps there would be
527
+ # more.
528
+ remote_gemspecs = remote_gemspecs.flatten
529
+ gems_to_update = []
530
+ highest_installed_gems.each do |l_name, l_spec|
531
+ hrg = highest_remote_gem =
532
+ remote_gemspecs.select { |spec| spec.name == l_name }.
533
+ sort_by { |spec| spec.version }.
534
+ last
535
+ if hrg and l_spec.version < hrg.version
536
+ gems_to_update << l_name
537
+ end
538
+ end
539
+ options[:domain] = :remote # install from remote source
540
+ install_command = command_manager['install']
541
+ gems_to_update.uniq.sort.each do |name|
542
+ say "Attempting remote upgrade of #{name}"
543
+ options[:args] = [name]
544
+ install_command.merge_options(options)
545
+ install_command.execute
546
+ end
547
+ say "All gems up to date"
548
+ end
549
+
550
+ def command_manager
551
+ Gem::CommandManager.instance
552
+ end
553
+ end
554
+
555
+ ####################################################################
556
+ class RDocCommand < Command
557
+ include VersionOption
558
+ include CommandAids
559
+
560
+ def initialize
561
+ super('rdoc', 'Generates RDoc for pre-installed gems', {:version=>"> 0.0.0"})
562
+ add_option('--all', 'Generate RDoc documentation for all installed gems') do |value, options|
563
+ options[:all] = value
564
+ end
565
+ add_version_option('rdoc')
566
+ end
567
+
568
+ def defaults_str
569
+ "--version '> 0.0.0'"
570
+ end
571
+
572
+ def usage
573
+ "#{program_name} [args]"
574
+ end
575
+
576
+ def arguments
577
+ "GEMNAME The gem to generate RDoc for (unless --all)"
578
+ end
579
+
580
+ def execute
581
+ if options[:all]
582
+ Gem::SourceIndex.from_installed_gems.each do |name, spec|
583
+ say "Doing gem #{spec.name}"
584
+ Gem::DocManager.new(spec).generate_rdoc
585
+ end
586
+ else
587
+ gem_name = get_one_gem_name
588
+ specs = Gem::SourceIndex.from_installed_gems.search(gem_name, options[:version])
589
+ if specs.empty?
590
+ #version = options[:version] || "> 0.0.0"
591
+ fail "Failed to find gem #{gem_name} to generate RDoc for #{options[:version]}"
592
+ end
593
+ specs.each do |spec|
594
+ Gem::DocManager.new(spec).generate_rdoc
595
+ end
596
+ end
597
+ true
598
+ end
599
+ end
600
+
601
+ ####################################################################
602
+ class EnvironmentCommand < Command
603
+ include CommandAids
604
+
605
+ def initialize
606
+ super('environment', 'Display RubyGems environmental information')
607
+ end
608
+
609
+ def usage
610
+ "#{program_name} [args]"
611
+ end
612
+
613
+ def arguments
614
+ args = <<-EOF
615
+ packageversion display the package version
616
+ gemdir display the path where gems are installed
617
+ gempath display path used to search for gems
618
+ version display the gem format version
619
+ remotesources display the remote gem servers
620
+ <omitted> display everything
621
+ EOF
622
+ return args.gsub(/^\s+/, '')
623
+ end
624
+
625
+ def execute
626
+ out = ''
627
+ arg = options[:args][0]
628
+ if begins?("packageversion", arg)
629
+ out = Gem::RubyGemsPackageVersion.to_s
630
+ elsif begins?("version", arg)
631
+ out = Gem::RubyGemsVersion.to_s
632
+ elsif begins?("gemdir", arg)
633
+ out = Gem.dir
634
+ elsif begins?("gempath", arg)
635
+ Gem.path.collect { |p| out << "#{p}\n" }
636
+ elsif begins?("remotesources", arg)
637
+ Gem::RemoteInstaller.new.sources.collect do |s|
638
+ out << "#{s}\n"
639
+ end
640
+ elsif arg
641
+ fail Gem::CommandLineError, "Unknown enviroment option [#{arg}]"
642
+ else
643
+ out = "Rubygems Environment:\n"
644
+ out << " - VERSION: #{Gem::RubyGemsVersion} (#{Gem::RubyGemsPackageVersion})\n"
645
+ out << " - INSTALLATION DIRECTORY: #{Gem.dir}\n"
646
+ out << " - GEM PATH:\n"
647
+ Gem.path.collect { |p| out << " - #{p}\n" }
648
+ out << " - REMOTE SOURCES:\n"
649
+ Gem::RemoteInstaller.new.sources.collect do |s|
650
+ out << " - #{s}\n"
651
+ end
652
+ end
653
+ say out
654
+ true
655
+ end
656
+ end
657
+
658
+ ####################################################################
659
+ class SpecificationCommand < Command
660
+ include VersionOption
661
+ include LocalRemoteOptions
662
+ include CommandAids
663
+
664
+ def initialize
665
+ super('specification', 'Display gem specification (in yaml)', {:domain=>:local, :version=>"> 0.0.0"})
666
+ add_version_option('examine')
667
+ add_local_remote_options
668
+ add_option('--all', 'Output specifications for all versions of the gem') do
669
+ options[:all] = true
670
+ end
671
+ end
672
+
673
+ def defaults_str
674
+ "--local --version '(latest)'"
675
+ end
676
+
677
+ def usage
678
+ "#{program_name} GEMFILE"
679
+ end
680
+
681
+ def arguments
682
+ "GEMFILE Name of a .gem file to examine"
683
+ end
684
+
685
+ def execute
686
+ if local?
687
+ gem = get_one_gem_name
688
+ gem_specs = Gem::SourceIndex.from_installed_gems.search(gem, options[:version])
689
+ unless gem_specs.empty?
690
+ require 'yaml'
691
+ output = lambda { |spec| say spec.to_yaml; say "\n" }
692
+ if options[:all]
693
+ gem_specs.each(&output)
694
+ else
695
+ spec = gem_specs.sort_by { |spec| spec.version }.last
696
+ output[spec]
697
+ end
698
+ else
699
+ alert_error "Unknown gem #{gem}"
700
+ end
701
+ end
702
+
703
+ if remote?
704
+ say "(Remote 'info' operation is not yet implemented.)"
705
+ # NOTE: when we do implement remote info, make sure we don't duplicate huge swabs of
706
+ # local data. If it's the same, just say it's the same.
707
+ end
708
+ end
709
+ end
710
+
711
+ ####################################################################
712
+ class UnpackCommand < Command
713
+ include VersionOption
714
+ include CommandAids
715
+
716
+ def initialize
717
+ super(
718
+ 'unpack',
719
+ 'Unpack an installed gem to the current directory',
720
+ { :version => '> 0' }
721
+ )
722
+ add_version_option('unpack')
723
+ end
724
+
725
+ def defaults_str
726
+ "--version '> 0'"
727
+ end
728
+
729
+ def usage
730
+ "#{program_name} GEMNAME"
731
+ end
732
+
733
+ def arguments
734
+ "GEMNAME Name of the gem to unpack"
735
+ end
736
+
737
+ # TODO: allow, e.g., 'gem unpack rake-0.3.1'. Find a general solution for this, so that it
738
+ # works for uninstall as well. (And check other commands at the same time.)
739
+ def execute
740
+ gemname = get_one_gem_name
741
+ path = get_path(gemname, options[:version])
742
+ if path
743
+ require 'fileutils'
744
+ target_dir = File.basename(path).sub(/\.gem$/, '')
745
+ FileUtils.mkdir_p target_dir
746
+ Installer.new(path).unpack(target_dir)
747
+ say "Unpacked gem: '#{target_dir}'"
748
+ else
749
+ alert_error "Gem '#{gemname}' not installed."
750
+ end
751
+ end
752
+
753
+ # Return the full path to the cached gem file matching the given name and version
754
+ # requirement. Returns 'nil' if no match. Example:
755
+ #
756
+ # get_path('rake', '> 0.4') # -> '/usr/lib/ruby/gems/1.8/cache/rake-0.4.2.gem'
757
+ # get_path('rake', '< 0.1') # -> nil
758
+ # get_path('rak') # -> nil (exact name required)
759
+ #
760
+ # XXX: This should be refactored so that it's a general service. I don't think any of our
761
+ # existing classes are the right place though. Just maybe 'Cache'?
762
+ #
763
+ # XXX: It just uses Gem.dir for now. What's an easy way to get the list of source directories?
764
+ #
765
+ def get_path(gemname, version_req)
766
+ specs = SourceIndex.from_installed_gems.search(gemname, version_req)
767
+ selected = specs.sort_by { |s| s.full_name }.last
768
+ return nil if selected.nil?
769
+ # We expect to find (basename).gem in the 'cache' directory. Furthermore, the name match
770
+ # must be exact.
771
+ if gemname == selected.name
772
+ filename = selected.full_name + '.gem'
773
+ return File.join(Gem.dir, 'cache', filename)
774
+ else
775
+ return nil
776
+ end
777
+ end
778
+ end
779
+
780
+ ####################################################################
781
+ class HelpCommand < Command
782
+ include CommandAids
783
+
784
+ def initialize
785
+ super('help', "Provide help on the 'gem' command")
786
+ end
787
+
788
+ def usage
789
+ "#{program_name} ARGUMENT"
790
+ end
791
+
792
+ def arguments
793
+ args = <<-EOF
794
+ commands List all 'gem' commands
795
+ examples Show examples of 'gem' usage
796
+ <command> Show specific help for <command>
797
+ EOF
798
+ return args.gsub(/^\s+/, '')
799
+ end
800
+
801
+ def execute
802
+ arg = options[:args][0]
803
+ if begins?("commands", arg)
804
+ require 'stringio'
805
+ out = StringIO.new
806
+ out.puts "\nGEM commands are:\n\n"
807
+ desc_indent = command_manager.command_names.collect {|n| n.size}.max + 4
808
+ format = " %-#{desc_indent}s %s\n"
809
+ command_manager.command_names.each do |cmd_name|
810
+ out.printf format, "#{cmd_name}", command_manager[cmd_name].summary
811
+ end
812
+ out.puts "\nFor help on a particular command, use 'gem help COMMAND'."
813
+ out.puts "\nCommands may be abbreviated, so long as they are unambiguous."
814
+ out.puts "e.g. 'gem i rake' is short for 'gem install rake'."
815
+ say out.string
816
+ elsif begins?("options", arg)
817
+ say Gem::HELP
818
+ elsif begins?("examples", arg)
819
+ say Gem::EXAMPLES
820
+ elsif options[:help]
821
+ command = command_manager[options[:help]]
822
+ if command
823
+ # help with provided command
824
+ command.invoke("--help")
825
+ else
826
+ alert_error "Unknown command #{options[:help]}. Try 'gem help commands'"
827
+ end
828
+ elsif arg
829
+ possibilities = command_manager.find_command_possibilities(arg.downcase)
830
+ if possibilities.size == 1
831
+ command = command_manager[possibilities.first]
832
+ command.invoke("--help")
833
+ elsif possibilities.size > 1
834
+ alert_warning "Ambiguous command #{arg} (#{possibilities.join(', ')})"
835
+ else
836
+ alert_warning "Unknown command #{arg}. Try gem help commands"
837
+ end
838
+ else
839
+ say Gem::HELP
840
+ end
841
+ end
842
+
843
+ def command_manager
844
+ Gem::CommandManager.instance
845
+ end
846
+ end
847
+
848
+ end # module
849
+
850
+ ## Documentation Constants
851
+
852
+ module Gem
853
+
854
+ HELP = %{
855
+ RubyGems is a sophisticated package manager for Ruby. This is a
856
+ basic help message containing pointers to more information.
857
+
858
+ Usage:
859
+ gem -h/--help
860
+ gem -v/--version
861
+ gem command [arguments...] [options...]
862
+
863
+ Examples:
864
+ gem install rake
865
+ gem list --local
866
+ gem build package.gemspec
867
+ gem help install
868
+
869
+ Further help:
870
+ gem help commands list all 'gem' commands
871
+ gem help examples show some examples of usage
872
+ gem help <COMMAND> show help on COMMAND
873
+ (e.g. 'gem help install')
874
+ Further information:
875
+ http://rubygems.rubyforge.org
876
+ }.gsub(/^ /, "")
877
+
878
+ EXAMPLES = %{
879
+ Some examples of 'gem' usage.
880
+
881
+ * Install 'rake', either from local directory or remote server:
882
+
883
+ gem install rake
884
+
885
+ * Install 'rake', only from remote server:
886
+
887
+ gem install rake --remote
888
+
889
+ * Install 'rake' from remote server, and run unit tests,
890
+ and generate RDocs:
891
+
892
+ gem install --remote rake --test --rdoc
893
+
894
+ * Install 'rake', but only version 0.3.1, even if dependencies
895
+ are not met, and into a specific directory:
896
+
897
+ gem install rake --version 0.3.1 --force --install-dir $HOME/.gems
898
+
899
+ * List local gems whose name begins with 'D':
900
+
901
+ gem list D
902
+
903
+ * List local and remote gems whose name contains 'log':
904
+
905
+ gem search log --both
906
+
907
+ * List only remote gems whose name contains 'log':
908
+
909
+ gem search log --remote
910
+
911
+ * Uninstall 'rake':
912
+
913
+ gem uninstall rake
914
+
915
+ * Create a gem:
916
+
917
+ See http://rubygems.rubyforge.org/wiki/wiki.pl?CreateAGemInTenMinutes
918
+
919
+ * See information about RubyGems:
920
+
921
+ gem environment
922
+
923
+ }.gsub(/^ /, "")
924
+
925
+ end