blob: 6bb7e4efe4291dcb3261166320b1bbcfe9267f5f [file] [log] [blame]
Mike Frysingere58c0e22017-10-04 15:43:30 -04001# -*- coding: utf-8 -*-
Chris Sosa90c78502012-10-05 17:07:42 -07002# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
David Purselle19f83b2015-07-01 12:57:07 -07006"""This implements the entry point for the `cros` CLI toolset.
Don Garrett25f309a2014-03-19 14:02:12 -07007
David Purselle19f83b2015-07-01 12:57:07 -07008This script is invoked by chromite/bin/cros, which sets up the
David Pursellffb90042015-03-23 09:21:41 -07009proper execution environment and calls this module's main() function.
Don Garrett25f309a2014-03-19 14:02:12 -070010
11In turn, this script looks for a subcommand based on how it was invoked. For
David Pursellffb90042015-03-23 09:21:41 -070012example, `cros lint` will use the cli/cros/cros_lint.py subcommand.
Don Garrett25f309a2014-03-19 14:02:12 -070013
David Pursellffb90042015-03-23 09:21:41 -070014See cli/ for actual command implementations.
Don Garrett25f309a2014-03-19 14:02:12 -070015"""
16
Mike Frysinger383367e2014-09-16 15:06:17 -040017from __future__ import print_function
18
David Pursellf1c27c12015-03-18 09:51:38 -070019from chromite.cli import command
Chris Sosab445f792012-10-11 15:26:39 -070020from chromite.lib import commandline
Ralph Nathan91874ca2015-03-19 13:29:41 -070021from chromite.lib import cros_logging as logging
Chris Sosa90c78502012-10-05 17:07:42 -070022
23
Brian Harring984988f2012-10-10 22:53:30 -070024def GetOptions(my_commands):
David Pursell643ed342015-07-07 09:24:32 -070025 """Returns the parser to use for commandline parsing.
Chris Sosa90c78502012-10-05 17:07:42 -070026
David Pursell643ed342015-07-07 09:24:32 -070027 Args:
28 my_commands: A dictionary mapping subcommand names to classes.
29
30 Returns:
31 A commandline.ArgumentParser object.
32 """
33 parser = commandline.ArgumentParser(caching=True, default_log_level='notice')
34
35 if my_commands:
36 subparsers = parser.add_subparsers(title='Subcommands')
37 for cmd_name in sorted(my_commands.iterkeys()):
38 class_def = my_commands[cmd_name]
39 epilog = getattr(class_def, 'EPILOG', None)
40 sub_parser = subparsers.add_parser(
41 cmd_name, description=class_def.__doc__, epilog=epilog,
42 caching=class_def.use_caching_options,
43 formatter_class=commandline.argparse.RawDescriptionHelpFormatter)
44 class_def.AddParser(sub_parser)
Chris Sosa90c78502012-10-05 17:07:42 -070045
46 return parser
47
48
Ryan Cui47f80e42013-04-01 19:01:54 -070049def _RunSubCommand(subcommand):
50 """Helper function for testing purposes."""
Ryan Cuide21f482013-08-06 11:50:59 -070051 return subcommand.Run()
Ryan Cui47f80e42013-04-01 19:01:54 -070052
53
Mike Frysinger9ad5fab2013-05-30 13:37:26 -040054def main(argv):
David Purselldfbfbc82015-03-05 10:59:16 -080055 try:
David Pursellf1c27c12015-03-18 09:51:38 -070056 parser = GetOptions(command.ListCommands())
David Purselldfbfbc82015-03-05 10:59:16 -080057 # Cros currently does nothing without a subcmd. Print help if no args are
58 # specified.
59 if not argv:
60 parser.print_help()
61 return 1
62
63 namespace = parser.parse_args(argv)
David Pursellffb90042015-03-23 09:21:41 -070064 subcommand = namespace.command_class(namespace)
Aviv Keshet01a82e92017-03-02 17:39:59 -080065 try:
66 code = _RunSubCommand(subcommand)
67 except (commandline.ChrootRequiredError, commandline.ExecRequiredError):
68 # The higher levels want these passed back, so oblige.
69 raise
70 except Exception as e:
71 code = 1
72 logging.error('cros %s failed before completing.',
73 subcommand.command_name)
74 if namespace.debug:
Mike Frysinger684d36e2015-06-03 05:03:34 -040075 raise
Aviv Keshet01a82e92017-03-02 17:39:59 -080076 else:
77 logging.error(e)
Mike Frysingera46f57d2018-07-19 12:18:22 -040078 logging.error('(Re-run with --debug for more details.)')
Mike Frysinger684d36e2015-06-03 05:03:34 -040079
Aviv Keshet01a82e92017-03-02 17:39:59 -080080 if code is not None:
81 return code
David Purselldfbfbc82015-03-05 10:59:16 -080082
83 return 0
84 except KeyboardInterrupt:
85 logging.debug('Aborted due to keyboard interrupt.')
Chris Sosa90c78502012-10-05 17:07:42 -070086 return 1