OSDN Git Service

First version.
[osdn-codes/osdn-cli.git] / lib / osdn / cli / runner.rb
1 require 'getoptlong'
2 require 'logger'
3 require 'pp'
4
5 module OSDN
6   module CLI
7     class Runner
8       def initialize
9         @logger = Logger.new(STDERR)
10         @logger.level = Logger::WARN
11         @logger.formatter = proc { |severity, time, progname, msg|
12           "[%s] %s\n" % [severity, msg]
13         }
14       end
15       attr_reader :logger
16       
17       def parse_opt
18         opts = GetoptLong.new(
19           [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
20           [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
21           [ '--quiet', '-q', GetoptLong::NO_ARGUMENT ],
22         )
23         opts.ordering = GetoptLong::REQUIRE_ORDER
24         opts.each do |opt, arg|
25           case opt
26           when '--help'
27             help
28             exit 0
29           when '--verbose'
30             if logger.level == Logger::DEBUG
31               OSDNClient.configure do |config|
32                 config.debugging = true
33               end
34             end
35             logger.level > Logger::DEBUG and
36               logger.level -= 1
37           when '--quiet'
38             logger.level < Logger::UNKNOWN and
39               logger.level += 1
40           when '--help'
41             help
42             exit
43           end
44         end
45         logger.debug "Loglevel is #{logger.level}"
46       end
47
48       def get_command_class(command_name)
49         class_name = command_name.to_s.split('_').map(&:capitalize).join
50         begin
51           return self.class.const_get("OSDN::CLI::Command::#{class_name}")
52         rescue NameError => e
53           logger.fatal "Invalid command name '#{command_name}'. Use 'help' to list commands."
54           exit
55         end
56         false
57       end
58
59       def run
60         parse_opt
61
62         command_name = ARGV.shift
63         unless command_name
64           help
65           exit 1
66         end
67
68         OSDNClient.configure do |config|
69           # TODO: remove
70           config.verify_ssl = false
71           config.logger.level = logger.level
72         end
73
74         if command_name == 'help'
75           help
76           exit
77         end
78         
79         command = get_command_class(command_name).new(logger)
80         logger.debug "Run command #{command_name}"
81         begin
82           command.run
83         rescue OSDNClient::ApiError => e
84           begin
85             err = JSON.parse(e.response_body)
86             if err["message"]
87               logger.fatal "#{err["status"]}: #{err["message"]}"
88             elsif err["error_description"]
89               logger.fatal err["error_description"]
90             else
91               logger.fatal "Command failed: #{e.inspect}"
92             end
93           rescue
94             logger.fatal "Command failed: #{e.inspect}"
95           end
96         end
97       end
98
99       def help
100         command_name = ARGV.shift
101         if command_name
102           get_command_class(command_name).new(logger).help
103         else
104           puts "#{$0} [global-options] <command> [command-options] [args]"
105           puts "#{$0} help <command>"
106           puts "Global Options:"
107           puts "  -h --help      Show help message. use 'help <command>' for specific command. "
108           puts "  -v --verbose   Increase log level (multiple)"
109           puts "  -q --quiet     Decrease log level (multiple)"
110           puts "Avaiable Commands:"
111           puts "  help"
112           OSDN::CLI::Command.constants.each do |c|
113             c = c.to_s.split(/(?=[A-Z])/).join('_').downcase
114             c == 'base' and next
115             puts "  %-14s %s" % [c, get_command_class(c).description]
116           end
117         end
118       end
119     end
120   end
121 end