# 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)
    # 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>
    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") 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])
