#
# Copyright (C) 2003, 2004  Chris Larson
# Copyright (C) 2003, 2004  Phil Blundell
# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
# Copyright (C) 2005        Holger Hans Peter Freyther
# Copyright (C) 2005        ROAD GmbH
# Copyright (C) 2006        Richard Purdie
#
# SPDX-License-Identifier: GPL-2.0-only
#

import os
import sys
import logging
import optparse
import warnings
import fcntl
import time
import traceback

import bb
from bb import event
import bb.msg
from bb import cooker
from bb import ui
from bb import server
from bb import cookerdata

import bb.server.process
import bb.server.xmlrpcclient

logger = logging.getLogger("BitBake")

class BBMainException(Exception):
    pass

class BBMainFatal(bb.BBHandledException):
    pass

def present_options(optionlist):
    if len(optionlist) > 1:
        return ' or '.join([', '.join(optionlist[:-1]), optionlist[-1]])
    else:
        return optionlist[0]

class BitbakeHelpFormatter(optparse.IndentedHelpFormatter):
    def format_option(self, option):
        # We need to do this here rather than in the text we supply to
        # add_option() because we don't want to call list_extension_modules()
        # on every execution (since it imports all of the modules)
        # Note also that we modify option.help rather than the returned text
        # - this is so that we don't have to re-format the text ourselves
        if option.dest == 'ui':
            valid_uis = list_extension_modules(bb.ui, 'main')
            option.help = option.help.replace('@CHOICES@', present_options(valid_uis))

        return optparse.IndentedHelpFormatter.format_option(self, option)

def list_extension_modules(pkg, checkattr):
    """
    Lists extension modules in a specific Python package
    (e.g. UIs, servers). NOTE: Calling this function will import all of the
    submodules of the specified module in order to check for the specified
    attribute; this can have unusual side-effects. As a result, this should
    only be called when displaying help text or error messages.
    Parameters:
        pkg: previously imported Python package to list
        checkattr: attribute to look for in module to determine if it's valid
            as the type of extension you are looking for
    """
    import pkgutil
    pkgdir = os.path.dirname(pkg.__file__)

    modules = []
    for _, modulename, _ in pkgutil.iter_modules([pkgdir]):
        if os.path.isdir(os.path.join(pkgdir, modulename)):
            # ignore directories
            continue
        try:
            module = __import__(pkg.__name__, fromlist=[modulename])
        except:
            # If we can't import it, it's not valid
            continue
        module_if = getattr(module, modulename)
        if getattr(module_if, 'hidden_extension', False):
            continue
        if not checkattr or hasattr(module_if, checkattr):
            modules.append(modulename)
    return modules

def import_extension_module(pkg, modulename, checkattr):
    try:
        # Dynamically load the UI based on the ui name. Although we
        # suggest a fixed set this allows you to have flexibility in which
        # ones are available.
        module = __import__(pkg.__name__, fromlist=[modulename])
        return getattr(module, modulename)
    except AttributeError:
        modules = present_options(list_extension_modules(pkg, checkattr))
        raise BBMainException('FATAL: Unable to import extension module "%s" from %s. '
                              'Valid extension modules: %s' % (modulename, pkg.__name__, modules))

# Display bitbake/OE warnings via the BitBake.Warnings logger, ignoring others"""
warnlog = logging.getLogger("BitBake.Warnings")
_warnings_showwarning = warnings.showwarning
def _showwarning(message, category, filename, lineno, file=None, line=None):
    if file is not None:
        if _warnings_showwarning is not None:
            _warnings_showwarning(message, category, filename, lineno, file, line)
    else:
        s = warnings.formatwarning(message, category, filename, lineno)
        warnlog.warning(s)

warnings.showwarning = _showwarning

def create_bitbake_parser():
    parser = optparse.OptionParser(
        formatter=BitbakeHelpFormatter(),
        version="BitBake Build Tool Core version %s" % bb.__version__,
        usage="""%prog [options] [recipename/target recipe:do_task ...]

    Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
    It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
    will provide the layer, BBFILES and other configuration information.""")

    parser.add_option("-b", "--buildfile", action="store", dest="buildfile", default=None,
                      help="Execute tasks from a specific .bb recipe directly. WARNING: Does "
                           "not handle any dependencies from other recipes.")

    parser.add_option("-k", "--continue", action="store_false", dest="halt", default=True,
                      help="Continue as much as possible after an error. While the target that "
                           "failed and anything depending on it cannot be built, as much as "
                           "possible will be built before stopping.")

    parser.add_option("-f", "--force", action="store_true", dest="force", default=False,
                      help="Force the specified targets/task to run (invalidating any "
                           "existing stamp file).")

    parser.add_option("-c", "--cmd", action="store", dest="cmd",
                      help="Specify the task to execute. The exact options available "
                           "depend on the metadata. Some examples might be 'compile'"
                           " or 'populate_sysroot' or 'listtasks' may give a list of "
                           "the tasks available.")

    parser.add_option("-C", "--clear-stamp", action="store", dest="invalidate_stamp",
                      help="Invalidate the stamp for the specified task such as 'compile' "
                           "and then run the default task for the specified target(s).")

    parser.add_option("-r", "--read", action="append", dest="prefile", default=[],
                      help="Read the specified file before bitbake.conf.")

    parser.add_option("-R", "--postread", action="append", dest="postfile", default=[],
                      help="Read the specified file after bitbake.conf.")

    parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
                      help="Enable tracing of shell tasks (with 'set -x'). "
                           "Also print bb.note(...) messages to stdout (in "
                           "addition to writing them to ${T}/log.do_<task>).")

    parser.add_option("-D", "--debug", action="count", dest="debug", default=0,
                      help="Increase the debug level. You can specify this "
                           "more than once. -D sets the debug level to 1, "
                           "where only bb.debug(1, ...) messages are printed "
                           "to stdout; -DD sets the debug level to 2, where "
                           "both bb.debug(1, ...) and bb.debug(2, ...) "
                           "messages are printed; etc. Without -D, no debug "
                           "messages are printed. Note that -D only affects "
                           "output to stdout. All debug messages are written "
                           "to ${T}/log.do_taskname, regardless of the debug "
                           "level.")

    parser.add_option("-q", "--quiet", action="count", dest="quiet", default=0,
                      help="Output less log message data to the terminal. You can specify this more than once.")

    parser.add_option("-n", "--dry-run", action="store_true", dest="dry_run", default=False,
                      help="Don't execute, just go through the motions.")

    parser.add_option("-S", "--dump-signatures", action="append", dest="dump_signatures",
                      default=[], metavar="SIGNATURE_HANDLER",
                      help="Dump out the signature construction information, with no task "
                           "execution. The SIGNATURE_HANDLER parameter is passed to the "
                           "handler. Two common values are none and printdiff but the handler "
                           "may define more/less. none means only dump the signature, printdiff"
                           " means compare the dumped signature with the cached one.")

    parser.add_option("-p", "--parse-only", action="store_true",
                      dest="parse_only", default=False,
                      help="Quit after parsing the BB recipes.")

    parser.add_option("-s", "--show-versions", action="store_true",
                      dest="show_versions", default=False,
                      help="Show current and preferred versions of all recipes.")

    parser.add_option("-e", "--environment", action="store_true",
                      dest="show_environment", default=False,
                      help="Show the global or per-recipe environment complete with information"
                           " about where variables were set/changed.")

    parser.add_option("-g", "--graphviz", action="store_true", dest="dot_graph", default=False,
                      help="Save dependency tree information for the specified "
                           "targets in the dot syntax.")

    parser.add_option("-I", "--ignore-deps", action="append",
                      dest="extra_assume_provided", default=[],
                      help="Assume these dependencies don't exist and are already provided "
                           "(equivalent to ASSUME_PROVIDED). Useful to make dependency "
                           "graphs more appealing")

    parser.add_option("-l", "--log-domains", action="append", dest="debug_domains", default=[],
                      help="Show debug logging for the specified logging domains")

    parser.add_option("-P", "--profile", action="store_true", dest="profile", default=False,
                      help="Profile the command and save reports.")

    # @CHOICES@ is substituted out by BitbakeHelpFormatter above
    parser.add_option("-u", "--ui", action="store", dest="ui",
                      default=os.environ.get('BITBAKE_UI', 'knotty'),
                      help="The user interface to use (@CHOICES@ - default %default).")

    parser.add_option("", "--token", action="store", dest="xmlrpctoken",
                      default=os.environ.get("BBTOKEN"),
                      help="Specify the connection token to be used when connecting "
                           "to a remote server.")

    parser.add_option("", "--revisions-changed", action="store_true",
                      dest="revisions_changed", default=False,
                      help="Set the exit code depending on whether upstream floating "
                           "revisions have changed or not.")

    parser.add_option("", "--server-only", action="store_true",
                      dest="server_only", default=False,
                      help="Run bitbake without a UI, only starting a server "
                           "(cooker) process.")

    parser.add_option("-B", "--bind", action="store", dest="bind", default=False,
                      help="The name/address for the bitbake xmlrpc server to bind to.")

    parser.add_option("-T", "--idle-timeout", type=float, dest="server_timeout",
                      default=os.getenv("BB_SERVER_TIMEOUT"),
                      help="Set timeout to unload bitbake server due to inactivity, "
                           "set to -1 means no unload, "
                           "default: Environment variable BB_SERVER_TIMEOUT.")

    parser.add_option("", "--no-setscene", action="store_true",
                      dest="nosetscene", default=False,
                      help="Do not run any setscene tasks. sstate will be ignored and "
                           "everything needed, built.")

    parser.add_option("", "--skip-setscene", action="store_true",
                      dest="skipsetscene", default=False,
                      help="Skip setscene tasks if they would be executed. Tasks previously "
                           "restored from sstate will be kept, unlike --no-setscene")

    parser.add_option("", "--setscene-only", action="store_true",
                      dest="setsceneonly", default=False,
                      help="Only run setscene tasks, don't run any real tasks.")

    parser.add_option("", "--remote-server", action="store", dest="remote_server",
                      default=os.environ.get("BBSERVER"),
                      help="Connect to the specified server.")

    parser.add_option("-m", "--kill-server", action="store_true",
                      dest="kill_server", default=False,
                      help="Terminate any running bitbake server.")

    parser.add_option("", "--observe-only", action="store_true",
                      dest="observe_only", default=False,
                      help="Connect to a server as an observing-only client.")

    parser.add_option("", "--status-only", action="store_true",
                      dest="status_only", default=False,
                      help="Check the status of the remote bitbake server.")

    parser.add_option("-w", "--write-log", action="store", dest="writeeventlog",
                      default=os.environ.get("BBEVENTLOG"),
                      help="Writes the event log of the build to a bitbake event json file. "
                           "Use '' (empty string) to assign the name automatically.")

    parser.add_option("", "--runall", action="append", dest="runall",
                      help="Run the specified task for any recipe in the taskgraph of the specified target (even if it wouldn't otherwise have run).")

    parser.add_option("", "--runonly", action="append", dest="runonly",
                      help="Run only the specified task within the taskgraph of the specified targets (and any task dependencies those tasks may have).")
    return parser


class BitBakeConfigParameters(cookerdata.ConfigParameters):
    def parseCommandLine(self, argv=sys.argv):
        parser = create_bitbake_parser()
        options, targets = parser.parse_args(argv)

        if options.quiet and options.verbose:
            parser.error("options --quiet and --verbose are mutually exclusive")

        if options.quiet and options.debug:
            parser.error("options --quiet and --debug are mutually exclusive")

        # use configuration files from environment variables
        if "BBPRECONF" in os.environ:
            options.prefile.append(os.environ["BBPRECONF"])

        if "BBPOSTCONF" in os.environ:
            options.postfile.append(os.environ["BBPOSTCONF"])

        # fill in proper log name if not supplied
        if options.writeeventlog is not None and len(options.writeeventlog) == 0:
            from datetime import datetime
            eventlog = "bitbake_eventlog_%s.json" % datetime.now().strftime("%Y%m%d%H%M%S")
            options.writeeventlog = eventlog

        if options.bind:
            try:
                #Checking that the port is a number and is a ':' delimited value
                (host, port) = options.bind.split(':')
                port = int(port)
            except (ValueError,IndexError):
                raise BBMainException("FATAL: Malformed host:port bind parameter")
            options.xmlrpcinterface = (host, port)
        else:
            options.xmlrpcinterface = (None, 0)

        return options, targets[1:]


def bitbake_main(configParams, configuration):

    # Python multiprocessing requires /dev/shm on Linux
    if sys.platform.startswith('linux') and not os.access('/dev/shm', os.W_OK | os.X_OK):
        raise BBMainException("FATAL: /dev/shm does not exist or is not writable")

    # Unbuffer stdout to avoid log truncation in the event
    # of an unorderly exit as well as to provide timely
    # updates to log files for use with tail
    try:
        if sys.stdout.name == '<stdout>':
            # Reopen with O_SYNC (unbuffered)
            fl = fcntl.fcntl(sys.stdout.fileno(), fcntl.F_GETFL)
            fl |= os.O_SYNC
            fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, fl)
    except:
        pass

    if configParams.server_only and configParams.remote_server:
            raise BBMainException("FATAL: The '--server-only' option conflicts with %s.\n" %
                                  ("the BBSERVER environment variable" if "BBSERVER" in os.environ \
                                   else "the '--remote-server' option"))

    if configParams.observe_only and not (configParams.remote_server or configParams.bind):
        raise BBMainException("FATAL: '--observe-only' can only be used by UI clients "
                              "connecting to a server.\n")

    if "BBDEBUG" in os.environ:
        level = int(os.environ["BBDEBUG"])
        if level > configParams.debug:
            configParams.debug = level

    bb.msg.init_msgconfig(configParams.verbose, configParams.debug,
                          configParams.debug_domains)

    server_connection, ui_module = setup_bitbake(configParams)
    # No server connection
    if server_connection is None:
        if configParams.status_only:
            return 1
        if configParams.kill_server:
            return 0

    if not configParams.server_only:
        if configParams.status_only:
            server_connection.terminate()
            return 0

        try:
            for event in bb.event.ui_queue:
                server_connection.events.queue_event(event)
            bb.event.ui_queue = []

            return ui_module.main(server_connection.connection, server_connection.events,
                                  configParams)
        finally:
            server_connection.terminate()
    else:
        return 0

    return 1

def setup_bitbake(configParams, extrafeatures=None):
    # Ensure logging messages get sent to the UI as events
    handler = bb.event.LogHandler()
    if not configParams.status_only:
        # In status only mode there are no logs and no UI
        logger.addHandler(handler)

    if configParams.server_only:
        featureset = []
        ui_module = None
    else:
        ui_module = import_extension_module(bb.ui, configParams.ui, 'main')
        # Collect the feature set for the UI
        featureset = getattr(ui_module, "featureSet", [])

    if extrafeatures:
        for feature in extrafeatures:
            if not feature in featureset:
                featureset.append(feature)

    server_connection = None

    # Clear away any spurious environment variables while we stoke up the cooker
    # (done after import_extension_module() above since for example import gi triggers env var usage)
    cleanedvars = bb.utils.clean_environment()

    if configParams.remote_server:
        # Connect to a remote XMLRPC server
        server_connection = bb.server.xmlrpcclient.connectXMLRPC(configParams.remote_server, featureset,
                                                                 configParams.observe_only, configParams.xmlrpctoken)
    else:
        retries = 8
        while retries:
            try:
                topdir, lock = lockBitbake()
                sockname = topdir + "/bitbake.sock"
                if lock:
                    if configParams.status_only or configParams.kill_server:
                        logger.info("bitbake server is not running.")
                        lock.close()
                        return None, None
                    # we start a server with a given featureset
                    logger.info("Starting bitbake server...")
                    # Clear the event queue since we already displayed messages
                    bb.event.ui_queue = []
                    server = bb.server.process.BitBakeServer(lock, sockname, featureset, configParams.server_timeout, configParams.xmlrpcinterface)

                else:
                    logger.info("Reconnecting to bitbake server...")
                    if not os.path.exists(sockname):
                        logger.info("Previous bitbake instance shutting down?, waiting to retry...")
                        i = 0
                        lock = None
                        # Wait for 5s or until we can get the lock
                        while not lock and i < 50:
                            time.sleep(0.1)
                            _, lock = lockBitbake()
                            i += 1
                        if lock:
                            bb.utils.unlockfile(lock)
                        raise bb.server.process.ProcessTimeout("Bitbake still shutting down as socket exists but no lock?")
                if not configParams.server_only:
                    server_connection = bb.server.process.connectProcessServer(sockname, featureset)

                if server_connection or configParams.server_only:
                    break
            except BBMainFatal:
                raise
            except (Exception, bb.server.process.ProcessTimeout, SystemExit) as e:
                # SystemExit does not inherit from the Exception class, needs to be included explicitly
                if not retries:
                    raise
                retries -= 1
                tryno = 8 - retries
                if isinstance(e, (bb.server.process.ProcessTimeout, BrokenPipeError, EOFError, SystemExit)):
                    logger.info("Retrying server connection (#%d)..." % tryno)
                else:
                    logger.info("Retrying server connection (#%d)... (%s)" % (tryno, traceback.format_exc()))

            if not retries:
                bb.fatal("Unable to connect to bitbake server, or start one (server startup failures would be in bitbake-cookerdaemon.log).")
            bb.event.print_ui_queue()
            if retries < 5:
                time.sleep(5)

    if configParams.kill_server:
        server_connection.connection.terminateServer()
        server_connection.terminate()
        bb.event.ui_queue = []
        logger.info("Terminated bitbake server.")
        return None, None

    # Restore the environment in case the UI needs it
    for k in cleanedvars:
        os.environ[k] = cleanedvars[k]

    logger.removeHandler(handler)

    return server_connection, ui_module

def lockBitbake():
    topdir = bb.cookerdata.findTopdir()
    if not topdir:
        bb.error("Unable to find conf/bblayers.conf or conf/bitbake.conf. BBPATH is unset and/or not in a build directory?")
        raise BBMainFatal
    lockfile = topdir + "/bitbake.lock"
    return topdir, bb.utils.lockfile(lockfile, False, False)

