Imported File#ftype spec from rubyspecs.
[rbx.git] / lib / rubygems / command_manager.rb
blobdd9a1aee15bf039092a875f5835518a962ccec83
1 #--
2 # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
3 # All rights reserved.
4 # See LICENSE.txt for permissions.
5 #++
7 require 'timeout'
8 require 'rubygems/command'
9 require 'rubygems/user_interaction'
11 module Gem
13   ####################################################################
14   # The command manager registers and installs all the individual
15   # sub-commands supported by the gem command.
16   class CommandManager
17     include UserInteraction
18     
19     # Return the authoritative instance of the command manager.
20     def self.instance
21       @command_manager ||= CommandManager.new
22     end
23     
24     # Register all the subcommands supported by the gem command.
25     def initialize
26       @commands = {}
27       register_command :build
28       register_command :cert
29       register_command :check
30       register_command :cleanup
31       register_command :contents
32       register_command :dependency
33       register_command :environment
34       register_command :fetch
35       register_command :generate_index
36       register_command :help
37       register_command :install
38       register_command :list
39       register_command :lock
40       register_command :mirror
41       register_command :outdated
42       register_command :pristine
43       register_command :query
44       register_command :rdoc
45       register_command :search
46       register_command :server
47       register_command :sources
48       register_command :specification
49       register_command :stale
50       register_command :uninstall
51       register_command :unpack
52       register_command :update
53       register_command :which
54     end
55     
56     # Register the command object.
57     def register_command(command_obj)
58       @commands[command_obj] = false
59     end
60     
61     # Return the registered command from the command name.
62     def [](command_name)
63       command_name = command_name.intern
64       return nil if @commands[command_name].nil?
65       @commands[command_name] ||= load_and_instantiate(command_name)
66     end
67     
68     # Return a list of all command names (as strings).
69     def command_names
70       @commands.keys.collect {|key| key.to_s}.sort
71     end
72     
73     # Run the config specified by +args+.
74     def run(args)
75       process_args(args)
76     rescue StandardError, Timeout::Error => ex
77       alert_error "While executing gem ... (#{ex.class})\n    #{ex.to_s}"
78       ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
79         Gem.configuration.backtrace
80       terminate_interaction(1)
81     rescue Interrupt
82       alert_error "Interrupted"
83       terminate_interaction(1)
84     end
86     def process_args(args)
87       args = args.to_str.split(/\s+/) if args.respond_to?(:to_str)
88       if args.size == 0
89         say Gem::Command::HELP
90         terminate_interaction(1)
91       end 
92       case args[0]
93       when '-h', '--help'
94         say Gem::Command::HELP
95         terminate_interaction(0)
96       when '-v', '--version'
97         say Gem::RubyGemsVersion
98         terminate_interaction(0)
99       when /^-/
100         alert_error "Invalid option: #{args[0]}.  See 'gem --help'."
101         terminate_interaction(1)
102       else
103         cmd_name = args.shift.downcase
104         cmd = find_command(cmd_name)
105         cmd.invoke(*args)
106       end
107     end
109     def find_command(cmd_name)
110       possibilities = find_command_possibilities(cmd_name)
111       if possibilities.size > 1
112         raise "Ambiguous command #{cmd_name} matches [#{possibilities.join(', ')}]"
113       end
114       if possibilities.size < 1
115         raise "Unknown command #{cmd_name}"
116       end
118       self[possibilities.first]
119     end
121     def find_command_possibilities(cmd_name)
122       len = cmd_name.length
123       self.command_names.select { |n| cmd_name == n[0,len] }
124     end
125     
126     private
128     def load_and_instantiate(command_name)
129       command_name = command_name.to_s
130       retried = false
132       begin
133         const_name = command_name.capitalize.gsub(/_(.)/) { $1.upcase }
134         Gem::Commands.const_get("#{const_name}Command").new
135       rescue NameError
136         if retried then
137           raise
138         else
139           retried = true
140           require "rubygems/commands/#{command_name}_command"
141           retry
142         end
143       end
144     end
145   end
146 end