blob: a5e059318bf1706bec08f9465c54c2695faf97f3 [file] [log] [blame]
Chris Sosa90c78502012-10-05 17:07:42 -07001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
David Pursellffb90042015-03-23 09:21:41 -07005"""This implements the entry point for CLI toolsets `cros` and `brillo`.
Don Garrett25f309a2014-03-19 14:02:12 -07006
David Pursellffb90042015-03-23 09:21:41 -07007This script is invoked by chromite/bin/{cros,brillo}, which sets up the
8proper execution environment and calls this module's main() function.
Don Garrett25f309a2014-03-19 14:02:12 -07009
10In turn, this script looks for a subcommand based on how it was invoked. For
David Pursellffb90042015-03-23 09:21:41 -070011example, `cros lint` will use the cli/cros/cros_lint.py subcommand.
Don Garrett25f309a2014-03-19 14:02:12 -070012
David Pursellffb90042015-03-23 09:21:41 -070013See cli/ for actual command implementations.
Don Garrett25f309a2014-03-19 14:02:12 -070014"""
15
Mike Frysinger383367e2014-09-16 15:06:17 -040016from __future__ import print_function
17
Ryan Cui47f80e42013-04-01 19:01:54 -070018import sys
19
David Pursellf1c27c12015-03-18 09:51:38 -070020from chromite.cli import command
Chris Sosab445f792012-10-11 15:26:39 -070021from chromite.lib import commandline
Ralph Nathan91874ca2015-03-19 13:29:41 -070022from chromite.lib import cros_logging as logging
Ryan Cui47f80e42013-04-01 19:01:54 -070023from chromite.lib import stats
Chris Sosa90c78502012-10-05 17:07:42 -070024
25
Brian Harring984988f2012-10-10 22:53:30 -070026def GetOptions(my_commands):
David Pursellffb90042015-03-23 09:21:41 -070027 """Returns the argparse to use for commandline parsing."""
Ralph Nathan1fc77f22015-04-21 15:05:48 -070028 if command.GetToolset() == 'brillo':
29 parser = commandline.ArgumentParser(caching=True,
30 default_log_level='notice')
Ralph Nathan74e864d2015-05-11 12:13:53 -070031 # For brillo commands, we want to store the logs to a file for error
32 # handling at logging level notice.
33 command.SetupFileLogger()
Ralph Nathan1fc77f22015-04-21 15:05:48 -070034 else:
35 parser = commandline.ArgumentParser(caching=True)
David Pursellf1c27c12015-03-18 09:51:38 -070036 if not command:
Chris Sosa90c78502012-10-05 17:07:42 -070037 return parser
38
David Pursellffb90042015-03-23 09:21:41 -070039 subparsers = parser.add_subparsers(title='Subcommands')
Mike Frysingerd6e2df02014-11-26 02:55:04 -050040 for cmd_name, class_def in sorted(my_commands.iteritems(),
41 key=lambda x: x[0]):
David James57d82a22012-12-04 11:24:58 -080042 epilog = getattr(class_def, 'EPILOG', None)
43 sub_parser = subparsers.add_parser(
Ryan Cui8b864512013-01-29 15:40:24 -080044 cmd_name, description=class_def.__doc__, epilog=epilog,
Ryo Hashimoto8bc997b2014-01-22 18:46:17 +090045 caching=class_def.use_caching_options,
David James57d82a22012-12-04 11:24:58 -080046 formatter_class=commandline.argparse.RawDescriptionHelpFormatter)
Chris Sosa90c78502012-10-05 17:07:42 -070047 class_def.AddParser(sub_parser)
48
49 return parser
50
51
Ryan Cui47f80e42013-04-01 19:01:54 -070052def _RunSubCommand(subcommand):
53 """Helper function for testing purposes."""
Ryan Cuide21f482013-08-06 11:50:59 -070054 return subcommand.Run()
Ryan Cui47f80e42013-04-01 19:01:54 -070055
56
Mike Frysinger9ad5fab2013-05-30 13:37:26 -040057def main(argv):
David Purselldfbfbc82015-03-05 10:59:16 -080058 try:
David Pursellf1c27c12015-03-18 09:51:38 -070059 parser = GetOptions(command.ListCommands())
David Purselldfbfbc82015-03-05 10:59:16 -080060 # Cros currently does nothing without a subcmd. Print help if no args are
61 # specified.
62 if not argv:
63 parser.print_help()
64 return 1
65
66 namespace = parser.parse_args(argv)
David Pursellffb90042015-03-23 09:21:41 -070067 subcommand = namespace.command_class(namespace)
David Purselldfbfbc82015-03-05 10:59:16 -080068 with stats.UploadContext() as queue:
69 if subcommand.upload_stats:
David Pursellffb90042015-03-23 09:21:41 -070070 cmd_base = subcommand.options.command_class.command_name
David Purselldfbfbc82015-03-05 10:59:16 -080071 cmd_stats = stats.Stats.SafeInit(cmd_line=sys.argv, cmd_base=cmd_base)
72 if cmd_stats:
73 queue.put([cmd_stats, stats.StatsUploader.URL,
74 subcommand.upload_stats_timeout])
75 # TODO: to make command completion faster, send an interrupt signal to the
76 # stats uploader task after the subcommand completes.
77 code = _RunSubCommand(subcommand)
78 if code is not None:
79 return code
80
81 return 0
82 except KeyboardInterrupt:
83 logging.debug('Aborted due to keyboard interrupt.')
Chris Sosa90c78502012-10-05 17:07:42 -070084 return 1