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.
- data/ChangeLog +60 -0
- data/lib/rubygems.rb +18 -15
- data/lib/rubygems/builder.rb +29 -23
- data/lib/rubygems/{cmd_manager.rb → command_manager.rb} +35 -24
- data/lib/rubygems/commands/build_command.rb +57 -0
- data/lib/rubygems/commands/cert_command.rb +83 -0
- data/lib/rubygems/commands/check_command.rb +74 -0
- data/lib/rubygems/commands/cleanup_command.rb +75 -0
- data/lib/rubygems/commands/contents_command.rb +66 -0
- data/lib/rubygems/commands/dependency_command.rb +105 -0
- data/lib/rubygems/commands/environment_command.rb +59 -0
- data/lib/rubygems/commands/help_command.rb +82 -0
- data/lib/rubygems/commands/install_command.rb +139 -0
- data/lib/rubygems/commands/list_command.rb +33 -0
- data/lib/rubygems/commands/outdated_command.rb +21 -0
- data/lib/rubygems/commands/pristine_command.rb +103 -0
- data/lib/rubygems/commands/query_command.rb +86 -0
- data/lib/rubygems/commands/rdoc_command.rb +75 -0
- data/lib/rubygems/commands/search_command.rb +35 -0
- data/lib/rubygems/commands/sources_command.rb +73 -0
- data/lib/rubygems/commands/specification_command.rb +58 -0
- data/lib/rubygems/commands/uninstall_command.rb +51 -0
- data/lib/rubygems/commands/unpack_command.rb +76 -0
- data/lib/rubygems/commands/update_command.rb +102 -0
- data/lib/rubygems/digest/digest_adapter.rb +40 -0
- data/lib/rubygems/digest/md5.rb +20 -0
- data/lib/rubygems/digest/sha1.rb +17 -0
- data/lib/rubygems/digest/sha2.rb +17 -0
- data/lib/rubygems/format.rb +1 -1
- data/lib/rubygems/gem_commands.rb +6 -1407
- data/lib/rubygems/gem_runner.rb +2 -2
- data/lib/rubygems/installer.rb +13 -5
- data/lib/rubygems/open-uri.rb +2 -2
- data/lib/rubygems/package.rb +13 -14
- data/lib/rubygems/rubygems_version.rb +1 -1
- data/lib/rubygems/source_index.rb +4 -4
- data/lib/rubygems/specification.rb +5 -0
- data/lib/rubygems/validator.rb +8 -8
- data/setup.rb +806 -588
- data/test/gemutilities.rb +2 -2
- data/test/test_builder.rb +15 -0
- data/test/test_check_command.rb +1 -1
- data/test/test_command.rb +1 -1
- data/test/test_gem_digest.rb +44 -0
- data/test/test_gem_outdated_command.rb +2 -1
- data/test/test_gem_sources_command.rb +11 -6
- data/test/test_installer.rb +1 -1
- data/test/test_open_uri.rb +14 -0
- data/test/test_parse_commands.rb +25 -25
- data/test/test_process_commands.rb +5 -5
- data/test/test_specific_extras.rb +1 -1
- data/test/test_validator.rb +3 -3
- 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
|
data/lib/rubygems/format.rb
CHANGED
@@ -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
|
-
|
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
|