1#!/usr/bin/env python3
2
3# This script has subcommands which operate against your bitbake layers, either
4# displaying useful information, or acting against them.
5# See the help output for details on available commands.
6
7# Copyright (C) 2011 Mentor Graphics Corporation
8# Copyright (C) 2011-2015 Intel Corporation
9#
10# SPDX-License-Identifier: GPL-2.0-only
11#
12
13import logging
14import os
15import sys
16import argparse
17import warnings
18warnings.simplefilter("default")
19
20bindir = os.path.dirname(__file__)
21topdir = os.path.dirname(bindir)
22sys.path[0:0] = [os.path.join(topdir, 'lib')]
23
24import bb.tinfoil
25import bb.msg
26
27logger = bb.msg.logger_create('bitbake-layers', sys.stdout)
28
29def main():
30    parser = argparse.ArgumentParser(
31        description="BitBake layers utility",
32        epilog="Use %(prog)s <subcommand> --help to get help on a specific command",
33        add_help=False)
34    parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
35    parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
36    parser.add_argument('-F', '--force', help='Force add without recipe parse verification', action='store_true')
37    parser.add_argument('--color', choices=['auto', 'always', 'never'], default='auto', help='Colorize output (where %(metavar)s is %(choices)s)', metavar='COLOR')
38
39    global_args, unparsed_args = parser.parse_known_args()
40
41    # Help is added here rather than via add_help=True, as we don't want it to
42    # be handled by parse_known_args()
43    parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS,
44                        help='show this help message and exit')
45    subparsers = parser.add_subparsers(title='subcommands', metavar='<subcommand>')
46    subparsers.required = True
47
48    if global_args.debug:
49        logger.setLevel(logging.DEBUG)
50    elif global_args.quiet:
51        logger.setLevel(logging.ERROR)
52
53    # Need to re-run logger_create with color argument
54    # (will be the same logger since it has the same name)
55    bb.msg.logger_create('bitbake-layers', output=sys.stdout,
56                         color=global_args.color,
57                         level=logger.getEffectiveLevel())
58
59    plugins = []
60    tinfoil = bb.tinfoil.Tinfoil(tracking=True)
61    tinfoil.logger.setLevel(logger.getEffectiveLevel())
62    try:
63        tinfoil.prepare(True)
64        for path in ([topdir] +
65                    tinfoil.config_data.getVar('BBPATH').split(':')):
66            pluginpath = os.path.join(path, 'lib', 'bblayers')
67            bb.utils.load_plugins(logger, plugins, pluginpath)
68
69        registered = False
70        for plugin in plugins:
71            if hasattr(plugin, 'tinfoil_init'):
72                plugin.tinfoil_init(tinfoil)
73            if hasattr(plugin, 'register_commands'):
74                registered = True
75                plugin.register_commands(subparsers)
76
77        if not registered:
78            logger.error("No commands registered - missing plugins?")
79            sys.exit(1)
80
81        args = parser.parse_args(unparsed_args, namespace=global_args)
82
83        if getattr(args, 'parserecipes', False):
84            tinfoil.config_data.disableTracking()
85            tinfoil.parse_recipes()
86            tinfoil.config_data.enableTracking()
87
88        return args.func(args)
89    finally:
90        tinfoil.shutdown()
91
92
93if __name__ == "__main__":
94    try:
95        ret = main()
96    except bb.BBHandledException:
97        ret = 1
98    except Exception:
99        ret = 1
100        import traceback
101        traceback.print_exc()
102    sys.exit(ret)
103