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

"""Manage projects in the local manifest."""

import os
import platform
from xml.etree import ElementTree

from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import git
from chromite.lib import osutils


class LocalManifest:
    """Abstraction for manipulating the local manifest."""

    @classmethod
    def FromPath(cls, path, empty_if_missing=False):
        if os.path.isfile(path):
            return cls(osutils.ReadFile(path))
        elif empty_if_missing:
            cros_build_lib.Die("Manifest file, %r, not found", path)
        return cls()

    def __init__(self, text=None):
        self._text = text or "<manifest>\n</manifest>"
        self.nodes = ElementTree.fromstring(self._text)

    def AddNonWorkonProject(self, name, path, remote=None, revision=None):
        """Add a new nonworkon project element to the manifest tree."""
        element = ElementTree.Element(
            "project", name=name, path=path, remote=remote
        )
        element.attrib["workon"] = "False"
        if revision is not None:
            element.attrib["revision"] = revision
        self.nodes.append(element)
        return element

    def GetProject(self, name, path=None):
        """Accessor method for getting a project node from the manifest tree.

        Returns:
            project element node from ElementTree, otherwise, None
        """
        if path is None:
            # Use a unique value that can't ever match.
            path = object()
        for project in self.nodes.findall("project"):
            if project.attrib["name"] == name or project.attrib["path"] == path:
                return project
        return None

    def ToString(self):
        # Reset the tail for each node, then just do a hacky replace.
        project = None
        for project in self.nodes.findall("project"):
            project.tail = "\n  "
        if project is not None:
            # Tweak the last project to not have the trailing space.
            project.tail = "\n"
        # Fix manifest tag text and tail.
        self.nodes.text = "\n  "
        self.nodes.tail = "\n"
        return ElementTree.tostring(self.nodes, encoding="unicode")

    def GetProjects(self):
        return list(self.nodes.findall("project"))


def _AddProjectsToManifestGroups(options, new_group):
    """Enable the given manifest groups for the configured repository."""

    groups_to_enable = ["name:%s" % x for x in new_group]

    git_config = options.git_config

    cmd = ["config", "-f", git_config, "--get", "manifest.groups"]
    enabled_groups = (
        git.RunGit(".", cmd, check=False).stdout.rstrip().split(",")
    )

    # Note that ordering actually matters, thus why the following code
    # is written this way.
    # Per repo behaviour, enforce an appropriate platform group if
    # we're converting from a default manifest group to a limited one.
    # Finally, note we reprocess the existing groups; this is to allow
    # us to clean up any user screwups, or our own screwups.
    requested_groups = (
        ["minilayout", "platform-%s" % (platform.system().lower(),)]
        + enabled_groups
        + list(groups_to_enable)
    )

    processed_groups = set()
    finalized_groups = []

    for group in requested_groups:
        if group not in processed_groups:
            finalized_groups.append(group)
            processed_groups.add(group)

    cmd = [
        "config",
        "-f",
        git_config,
        "manifest.groups",
        ",".join(finalized_groups),
    ]
    git.RunGit(".", cmd)


def _AssertNotMiniLayout():
    cros_build_lib.Die(
        "Your repository checkout is using the old minilayout.xml workflow; "
        "Autoupdate is no longer supported, reinstall your tree."
    )


def GetParser():
    """Return a command line parser."""
    parser = commandline.ArgumentParser(description=__doc__)

    # Subparsers are required by default under Python 2.  Python 3 changed to
    # not required, but didn't include a required option until 3.7.  Setting
    # the required member works in all versions (and setting dest name).
    subparsers = parser.add_subparsers(dest="command")
    subparsers.required = True

    subparser = subparsers.add_parser(
        "add", help="Add projects to the manifest."
    )
    subparser.add_argument(
        "-w",
        "--workon",
        action="store_true",
        default=False,
        help="Is this a workon package?",
    )
    subparser.add_argument(
        "-r", "--remote", help="Remote project name (for non-workon packages)."
    )
    subparser.add_argument(
        "--revision",
        help="Use to override the manifest defined default "
        "revision used for a given project.",
    )
    subparser.add_argument("project", help="Name of project in the manifest.")
    subparser.add_argument("path", nargs="?", help="Local path to the project.")

    return parser


def main(argv):
    parser = GetParser()
    options = parser.parse_args(argv)
    repo_dir = git.FindRepoDir(os.getcwd())
    if not repo_dir:
        parser.error(
            "This script must be invoked from within a repository " "checkout."
        )

    options.git_config = os.path.join(repo_dir, "manifests.git", "config")
    options.local_manifest_path = os.path.join(repo_dir, "local_manifest.xml")

    manifest_sym_path = os.path.join(repo_dir, "manifest.xml")
    if (
        os.path.basename(os.path.realpath(manifest_sym_path))
        == "minilayout.xml"
    ):
        _AssertNotMiniLayout()

    # For now, we only support the add command.
    assert options.command == "add"
    if options.workon:
        if options.path is not None:
            parser.error("Adding workon projects do not set project.")
    else:
        if options.remote is None:
            parser.error("Adding non-workon projects requires a remote.")
        if options.path is None:
            parser.error("Adding non-workon projects requires a path.")
    name = options.project
    path = options.path
    revision = options.revision
    if revision is not None:
        if not git.IsRefsTags(revision) and not git.IsSHA1(revision):
            revision = git.StripRefsHeads(revision, False)

    main_manifest = git.ManifestCheckout(os.getcwd())
    main_element = main_manifest.FindCheckouts(name)
    if path is not None:
        main_element_from_path = main_manifest.FindCheckoutFromPath(
            path, strict=False
        )
        if main_element_from_path is not None:
            main_element.append(main_element_from_path)

    local_manifest = LocalManifest.FromPath(options.local_manifest_path)

    if options.workon:
        if not main_element:
            parser.error("No project named %r in the default manifest." % name)
        _AddProjectsToManifestGroups(
            options, [checkout["name"] for checkout in main_element]
        )

    elif main_element:
        if options.remote is not None:
            # Likely this project wasn't meant to be remote, so workon main
            # element.
            print(
                "Project already exists in manifest. "
                "Using that as workon project."
            )
            _AddProjectsToManifestGroups(
                options, [checkout["name"] for checkout in main_element]
            )
        else:
            # Conflict will occur; complain.
            parser.error(
                "Requested project name=%r path=%r will conflict with "
                "your current manifest %s"
                % (name, path, main_manifest.manifest_path)
            )

    elif local_manifest.GetProject(name, path=path) is not None:
        parser.error(
            "Requested project name=%r path=%r conflicts with "
            "your local_manifest.xml" % (name, path)
        )

    else:
        element = local_manifest.AddNonWorkonProject(
            name=name, path=path, remote=options.remote, revision=revision
        )
        _AddProjectsToManifestGroups(options, [element.attrib["name"]])

        with open(options.local_manifest_path, "w", encoding="utf-8") as f:
            f.write(local_manifest.ToString())
    return 0
