# Copyright 2019 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Parser for Portage elog summary.log files

The summary.log file is created by Portage at ${PORT_LOGDIR}/elog/summary.log
and appended to by every run of `emerge`. Any package that emits information
via the `elog` system will have an entry in the summary log, even those with
fatal errors.

The `ebuild` command and invocations of `emerge` with --pretend will *NOT*
generate entries in the summary.log file.

Documentation for the Portage log system can be found at:
https://wiki.gentoo.org/wiki/Portage_log
"""

from __future__ import absolute_import

from collections import defaultdict
import re

from chromite.lib.parser import package_info


SECTION_HEADER = re.compile(
    r">>> Messages generated by process (?P<process>\d+) on (?P<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \w{3}) for package (?P<package>[^:]+):"  # pylint: disable=line-too-long
)

LOG_ENTRY = re.compile(
    r"(?P<level>INFO|WARN|LOG|ERROR|QA): (?P<phase>setup|unpack|prepare|configure|compile|test|install|preinst|postinst)"  # pylint: disable=line-too-long
)


class Error(Exception):
    """Base exception type for this parser"""


class MalformedLogError(Error):
    """Error indicating a parsed log has unexpected structure"""


class DuplicatePackageError(Error):
    """Error indicating that duplicate packages were found in a summary.log"""


class SummaryLog:
    """Parsed contents of a summary.log file"""

    def __init__(self, log_contents):
        self.package_logs = sorted(
            (PackageLog(cpv, logs) for cpv, logs in log_contents.items()),
            key=lambda x: x.cpv,
        )

    def has_failed_packages(self):
        return any(log.has_errors() for log in self.package_logs)

    def failed_packages(self):
        return sorted(log.cp for log in self.package_logs if log.has_errors())

    def has_warned_packages(self):
        return any(log.has_warnings() for log in self.package_logs)

    def warned_packages(self):
        return sorted(log.cp for log in self.package_logs if log.has_warnings())

    @staticmethod
    def parse_from_file(file_path):
        with open(file_path, encoding="utf-8") as logfile:
            return _parse_summary_log_from_lines_iterator(logfile)

    @staticmethod
    def parse_from_string(string):
        return _parse_summary_log_from_lines_iterator(string.splitlines(True))


class PackageLog:
    """Parsed contents of a single package's entry from a summary.log"""

    def __init__(self, cpv, log_mapping):
        self.cpv = cpv
        self.log_levels = dict((k, dict(v)) for k, v in log_mapping.items())

    @property
    def cp(self):
        return self.cpv.cp

    def has_errors(self):
        return "ERROR" in self.log_levels

    def has_warnings(self):
        return "WARN" in self.log_levels


def _parse_summary_log_from_lines_iterator(log_lines, no_duplicates=False):
    cpv = None
    level = None
    phase = None

    # A mapping of package cpv -> log level -> ebuild phase -> messages
    # Ex: contents["app-editor/vim"]["ERROR"]["compile"] -> "something happened"
    contents = defaultdict(lambda: defaultdict(lambda: defaultdict(str)))

    for line in log_lines:
        # Skip over blank lines
        if not line.strip():
            continue

        # Update the state once we're in a log section for a particular package
        # If we encounter the same package twice that means the log has entries
        # from a previous attempt.
        header_match = SECTION_HEADER.match(line.strip())
        if header_match:
            cpv = package_info.SplitCPV(header_match.group("package"))
            if cpv in contents and no_duplicates:
                raise DuplicatePackageError()
            continue

        # Match the ebuild phase and log entry. If we don't have a package set
        # yet, then the log we're reading is malformed.
        entry_match = LOG_ENTRY.match(line.strip())
        if entry_match:
            if not cpv:
                raise MalformedLogError()
            phase = entry_match.group("phase")
            level = entry_match.group("level")
            continue

        # All other lines are then the actual messages printed by ebuilds.
        # Append them to their respective categories. If anything is unset by
        # this point, the log is again malformed.
        if not all((cpv, phase, level)):
            raise MalformedLogError()
        contents[cpv][level][phase] += line

    return SummaryLog(contents)
