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

"""Compares the packages between 2 images by parsing the license file output."""

import re

from chromite.lib import commandline


def GetPackagesLicensesFromHtml(html_file):
    """Get the list of packages and licenses in a ChromeOS license file.

    Args:
        html_file: which html license file to scan for packages.

    Returns:
        tuple of dictionary of packages and version numbers and set of licenses.

    Raises:
        AssertionError: if regex failed.
    """

    packages = {}
    licenses = set()

    pkg_rgx = re.compile(r'<span class="title">(.+)-(.+)</span>')
    # Do not add <pre> in the regex or it would only show the first entry on
    # a package that has multiple hits.
    license_rgx1 = re.compile(r"Scanned (Source License .+):", re.IGNORECASE)
    license_rgx2 = re.compile(r"(Custom License .+):", re.IGNORECASE)
    license_rgx3 = re.compile(r"(Copyright Attribution .+):", re.IGNORECASE)
    # pylint: disable=line-too-long
    # This regex isn't as tight because it has to match these:
    # Gentoo Package Stock License BZIP2:
    # <a ... class="title">Gentoo Package Provided Stock License public-domain</a>
    # <a ... class="title">Gentoo Package Stock License public-domain</a>
    # pylint: enable=line-too-long
    license_rgx4 = re.compile(r"(Stock License [^<:]+)", re.IGNORECASE)
    license_rgx5 = re.compile(
        r'class="title">(Custom License .+)</a>', re.IGNORECASE
    )
    with open(html_file, "r", encoding="utf-8") as f:
        for line in f:
            # Grep and turn
            # <span class="title">ath6k-34</span>
            # into
            # ath6k 34
            match = pkg_rgx.search(line)
            if match:
                packages[match.group(1)] = match.group(2)

            match = license_rgx1.search(line)
            if match:
                # Turn Source license simplejson-2.5.0/LICENSE.txt
                # into Source license simplejson/LICENSE.txt
                # (we don't want to create diffs based on version numbers)
                lic = re.sub(r"(.+)-([^/]+)/(.+)", r"\1/\3", match.group(1))
                # Old files had this lowercased.
                lic = re.sub(r"Source license", r"Source License", lic)
                licenses.add(lic)

            for rgx in (license_rgx2, license_rgx3, license_rgx4, license_rgx5):
                match = rgx.search(line)
                if match:
                    licenses.add(match.group(1))

    return (packages, licenses)


def ComparePkgLists(pkg_list1, pkg_list2):
    """Compare the package list in 2 dictionaries and output the differences.

    Args:
        pkg_list1: dict from GetPackagesLicensesFromHtml.
        pkg_list2: dict from GetPackagesLicensesFromHtml.

    Returns:
        N/A (outputs result on stdout).
    """

    for removed_package in sorted(set(pkg_list1) - set(pkg_list2)):
        print(
            "Package removed: %s-%s"
            % (removed_package, pkg_list1[removed_package])
        )

    print()
    for added_package in sorted(set(pkg_list2) - set(pkg_list1)):
        print(
            "Package added: %s-%s" % (added_package, pkg_list2[added_package])
        )

    print()
    for changed_package in sorted(set(pkg_list1) & set(pkg_list2)):
        ver1 = pkg_list1[changed_package]
        ver2 = pkg_list2[changed_package]
        if ver1 != ver2:
            print(
                "Package updated: %s from %s to %s"
                % (changed_package, ver1, ver2)
            )


def CompareLicenseSets(set1, set2):
    """Compare the license list in 2 sets and output the differences.

    Args:
        set1: set from GetPackagesLicensesFromHtml.
        set2: set from GetPackagesLicensesFromHtml.

    Returns:
        N/A (outputs result on stdout).
    """

    for removed_license in sorted(set1 - set2):
        print("License removed: %s" % (removed_license))

    print()
    for added_license in sorted(set2 - set1):
        print("License added: %s" % (added_license))


def main(args):
    parser = commandline.ArgumentParser(description=__doc__)
    parser.add_argument(
        "html1", metavar="license1.html", type="path", help="old html file"
    )
    parser.add_argument(
        "html2", metavar="license2.html", type="path", help="new html file"
    )
    opts = parser.parse_args(args)

    pkg_list1 = GetPackagesLicensesFromHtml(opts.html1)
    pkg_list2 = GetPackagesLicensesFromHtml(opts.html2)
    ComparePkgLists(pkg_list1[0], pkg_list2[0])
    print()
    CompareLicenseSets(pkg_list1[1], pkg_list2[1])
