# 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.

"""Generate an HTML file containing license info for all installed packages.

Documentation on this script is also available here:
https://dev.chromium.org/chromium-os/licensing/licensing-for-chromiumos-developers

End user (i.e. package owners) documentation is here:
https://dev.chromium.org/chromium-os/licensing/licensing-for-chromiumos-package-owners

The license bits for each package are automatically generated by
src/scripts/hooks/install/gen-package-licenses.sh which gets run
by emerge as part of a package build (by running this script with
--hook /path/to/tmp/portage/build/tree/for/that/package).
These license bits are stored in `$SYSROOT/var/db/pkg/$CATEGORY/$PACKAGE` as
the build continues.
license.py script will subsequently gather the license bits from there to
compose the final license file, unless this script is run with
`--generate-licenses`, in which case the script will regenerate the license
bits.

If license bits are missing, they are generated on the fly if you were running
with sudo. If you didn't use sudo, this on the fly late generation will fail
and act as a warning that your prebuilts were missing package build time
licenses.

You can check the licenses and/or generate a HTML file for a list of
packages using --package or -p:
  (cr) licenses --package "dev-libs/libatomic_ops-7.2d" --package \
       "net-misc/wget-1.14" --board $BOARD -o out.html

Note that you'll want to use --generate-licenses to force regeneration of the
licensing bits from a package source you may have just modified but not rebuilt.

If you want to check licensing against all ChromeOS packages, you should
run `cros build-packages --board=$BOARD` to build everything and then run this
script with --all-packages.

By default, when no package is specified, this script processes all
packages for $BOARD.
"""

import logging
import os

from chromite.lib import build_target_lib
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.licensing import licenses_lib


def LoadPackageInfo(
    sysroot, all_packages, generateMissing, packages, placeholder
):
    """Do the work when we're not called as a hook."""
    logging.info("Processing sysroot %s", sysroot)

    detect_packages = not packages
    if detect_packages:
        # If no packages were specified, we look up the full list.
        if placeholder:
            # A random set of names to generate the placeholder file.
            packages = [
                "sys-libs/placeholder-1-r3",
                "chromeos-base/placeheld-1.0",
            ]
        else:
            packages = licenses_lib.ListInstalledPackages(sysroot, all_packages)

    assert packages, f"{sysroot}: could not find any packages"

    logging.debug(
        "Initial Package list to work through:\n%s", "\n".join(sorted(packages))
    )
    licensing = licenses_lib.Licensing(
        sysroot, packages, generateMissing, placeholder=placeholder
    )

    licensing.LoadPackageInfo()
    logging.debug(
        "Package list to skip:\n%s",
        "\n".join([p for p in sorted(packages) if licensing.packages[p].skip]),
    )
    logging.debug(
        "Package list left to work through:\n%s",
        "\n".join(
            [p for p in sorted(packages) if not licensing.packages[p].skip]
        ),
    )
    licensing.ProcessPackageLicenses()

    return licensing


def get_parser() -> commandline.ArgumentParser:
    """Return a command line parser."""
    parser = commandline.ArgumentParser(usage=__doc__)

    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument(
        "-b", "--board", help="which board to run for, like x86-alex"
    )
    group.add_argument(
        "--sysroot",
        type="str_path",
        help="which sysroot to run on (e.g. /build/eve)",
    )
    group.add_argument(
        "--placeholder",
        action="store_true",
        help="Generate a placeholder file (for testing).",
    )

    parser.add_argument(
        "--os-version",
        help="Overall OS version when building CrOS images.",
    )
    parser.add_argument(
        "--milestone-version",
        help="Overall OS milestone when building CrOS images.",
    )
    parser.add_argument(
        "-p",
        "--package",
        action="append",
        default=[],
        dest="packages",
        help="check the license of the package, e.g.,"
        "dev-libs/libatomic_ops-7.2d",
    )
    parser.add_argument(
        "-a",
        "--all-packages",
        action="store_true",
        help="Run licensing against all packages in the "
        "build tree, instead of just virtual/target-os "
        "dependencies.",
    )
    parser.add_argument(
        "-g",
        "--generate-licenses",
        action="store_true",
        dest="gen_licenses",
        help="Generate license information, if missing.",
    )
    parser.add_argument(
        "-o",
        "--output",
        type="str_path",
        help="which html file to create with output",
    )
    parser.add_argument(
        "-c",
        "--compress-output",
        action="store_true",
        help="whether to compress the html output. If true, output must end in "
        "an appropriate extension.",
    )
    return parser


def main(args) -> None:
    parser = get_parser()
    opts = parser.parse_args(args)

    if not opts.output and not opts.gen_licenses:
        parser.error("You must specify --output and/or --generate-licenses")

    sysroot = opts.sysroot or build_target_lib.get_default_sysroot_path(
        opts.board
    )

    if (
        opts.output
        and os.path.exists(opts.output)
        and not os.path.isfile(opts.output)
    ):
        parser.error(f"--output must point to a file: {opts.output}")

    if opts.compress_output:
        if not opts.output:
            parser.error("--compress-output requires --output")
        if (
            cros_build_lib.CompressionExtToType(opts.output)
            == cros_build_lib.CompressionType.NONE
        ):
            parser.error(
                "if --compress-output is specified, --output must end in "
                f"appropriate compression format but is: {opts.output}"
            )

    licensing = LoadPackageInfo(
        sysroot,
        opts.all_packages,
        opts.gen_licenses,
        opts.packages,
        placeholder=opts.placeholder,
    )

    if opts.output:
        licensing.GenerateHTMLLicenseOutput(
            opts.output,
            os_version=opts.os_version,
            milestone_version=opts.milestone_version,
            compress_output=opts.compress_output,
        )
