# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import collections
import itertools
import os
import platform
import re
import sys
import urllib.parse
import xml.dom.minidom

from error import ManifestInvalidPathError
from error import ManifestInvalidRevisionError
from error import ManifestParseError
from git_config import GitConfig
from git_refs import HEAD
from git_refs import R_HEADS
from git_superproject import Superproject
import platform_utils
from project import Annotation
from project import ManifestProject
from project import Project
from project import RemoteSpec
from project import RepoProject
from wrapper import Wrapper


MANIFEST_FILE_NAME = "manifest.xml"
LOCAL_MANIFEST_NAME = "local_manifest.xml"
LOCAL_MANIFESTS_DIR_NAME = "local_manifests"
SUBMANIFEST_DIR = "submanifests"
# Limit submanifests to an arbitrary depth for loop detection.
MAX_SUBMANIFEST_DEPTH = 8
# Add all projects from sub manifest into a group.
SUBMANIFEST_GROUP_PREFIX = "submanifest:"

# Add all projects from local manifest into a group.
LOCAL_MANIFEST_GROUP_PREFIX = "local:"

# ContactInfo has the self-registered bug url, supplied by the manifest authors.
ContactInfo = collections.namedtuple("ContactInfo", "bugurl")

# urljoin gets confused if the scheme is not known.
urllib.parse.uses_relative.extend(
    ["ssh", "git", "persistent-https", "sso", "rpc"]
)
urllib.parse.uses_netloc.extend(
    ["ssh", "git", "persistent-https", "sso", "rpc"]
)


def XmlBool(node, attr, default=None):
    """Determine boolean value of |node|'s |attr|.

    Invalid values will issue a non-fatal warning.

    Args:
        node: XML node whose attributes we access.
        attr: The attribute to access.
        default: If the attribute is not set (value is empty), then use this.

    Returns:
        True if the attribute is a valid string representing true.
        False if the attribute is a valid string representing false.
        |default| otherwise.
    """
    value = node.getAttribute(attr)
    s = value.lower()
    if s == "":
        return default
    elif s in {"yes", "true", "1"}:
        return True
    elif s in {"no", "false", "0"}:
        return False
    else:
        print(
            'warning: manifest: %s="%s": ignoring invalid XML boolean'
            % (attr, value),
            file=sys.stderr,
        )
        return default


def XmlInt(node, attr, default=None):
    """Determine integer value of |node|'s |attr|.

    Args:
        node: XML node whose attributes we access.
        attr: The attribute to access.
        default: If the attribute is not set (value is empty), then use this.

    Returns:
        The number if the attribute is a valid number.

    Raises:
        ManifestParseError: The number is invalid.
    """
    value = node.getAttribute(attr)
    if not value:
        return default

    try:
        return int(value)
    except ValueError:
        raise ManifestParseError(f'manifest: invalid {attr}="{value}" integer')


def normalize_url(url: str) -> str:
    """Mutate input 'url' into normalized form:

    * remove trailing slashes
    * convert SCP-like syntax to SSH URL

    Args:
        url: URL to modify

    Returns:
        The normalized URL.
    """

    url = url.rstrip("/")
    parsed_url = urllib.parse.urlparse(url)

    # This matches patterns like "git@github.com:foo".
    scp_like_url_re = r"^[^/:]+@[^/:]+:[^/]+"

    # If our URL is missing a schema and matches git's
    # SCP-like syntax we should convert it to a proper
    # SSH URL instead to make urljoin() happier.
    #
    # See: https://git-scm.com/docs/git-clone#URLS
    if not parsed_url.scheme and re.match(scp_like_url_re, url):
        return "ssh://" + url.replace(":", "/", 1)

    return url


class _Default:
    """Project defaults within the manifest."""

    revisionExpr = None
    destBranchExpr = None
    upstreamExpr = None
    remote = None
    sync_j = None
    sync_c = False
    sync_s = False
    sync_tags = True

    def __eq__(self, other):
        if not isinstance(other, _Default):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other):
        if not isinstance(other, _Default):
            return True
        return self.__dict__ != other.__dict__


class _XmlRemote:
    def __init__(
        self,
        name,
        alias=None,
        fetch=None,
        pushUrl=None,
        manifestUrl=None,
        review=None,
        revision=None,
    ):
        self.name = name
        self.fetchUrl = fetch
        self.pushUrl = pushUrl
        self.manifestUrl = manifestUrl
        self.remoteAlias = alias
        self.reviewUrl = review
        self.revision = revision
        self.resolvedFetchUrl = self._resolveFetchUrl()
        self.annotations = []

    def __eq__(self, other):
        if not isinstance(other, _XmlRemote):
            return False
        return (
            sorted(self.annotations) == sorted(other.annotations)
            and self.name == other.name
            and self.fetchUrl == other.fetchUrl
            and self.pushUrl == other.pushUrl
            and self.remoteAlias == other.remoteAlias
            and self.reviewUrl == other.reviewUrl
            and self.revision == other.revision
        )

    def __ne__(self, other):
        return not self.__eq__(other)

    def _resolveFetchUrl(self):
        if self.fetchUrl is None:
            return ""

        fetch_url = normalize_url(self.fetchUrl)
        manifest_url = normalize_url(self.manifestUrl)

        # urljoin doesn't like URLs with no scheme in the base URL
        # such as file paths.  We handle this by prefixing it with
        # an obscure protocol, gopher, and replacing it with the
        # original after urljoin
        if manifest_url.find(":") != manifest_url.find("/") - 1:
            fetch_url = urllib.parse.urljoin(
                "gopher://" + manifest_url, fetch_url
            )
            fetch_url = re.sub(r"^gopher://", "", fetch_url)
        else:
            fetch_url = urllib.parse.urljoin(manifest_url, fetch_url)
        return fetch_url

    def ToRemoteSpec(self, projectName):
        fetchUrl = self.resolvedFetchUrl.rstrip("/")
        url = fetchUrl + "/" + projectName
        remoteName = self.name
        if self.remoteAlias:
            remoteName = self.remoteAlias
        return RemoteSpec(
            remoteName,
            url=url,
            pushUrl=self.pushUrl,
            review=self.reviewUrl,
            orig_name=self.name,
            fetchUrl=self.fetchUrl,
        )

    def AddAnnotation(self, name, value, keep):
        self.annotations.append(Annotation(name, value, keep))


class _XmlSubmanifest:
    """Manage the <submanifest> element specified in the manifest.

    Attributes:
      name: a string, the name for this submanifest.
      remote: a string, the remote.name for this submanifest.
      project: a string, the name of the manifest project.
      revision: a string, the commitish.
      manifestName: a string, the submanifest file name.
      groups: a list of strings, the groups to add to all projects in the
          submanifest.
      default_groups: a list of strings, the default groups to sync.
      path: a string, the relative path for the submanifest checkout.
      parent: an XmlManifest, the parent manifest.
      annotations: (derived) a list of annotations.
      present: (derived) a boolean, whether the sub manifest file is present.
    """

    def __init__(
        self,
        name,
        remote=None,
        project=None,
        revision=None,
        manifestName=None,
        groups=None,
        default_groups=None,
        path=None,
        parent=None,
    ):
        self.name = name
        self.remote = remote
        self.project = project
        self.revision = revision
        self.manifestName = manifestName
        self.groups = groups
        self.default_groups = default_groups
        self.path = path
        self.parent = parent
        self.annotations = []
        outer_client = parent._outer_client or parent
        if self.remote and not self.project:
            raise ManifestParseError(
                f"Submanifest {name}: must specify project when remote is "
                "given."
            )
        # Construct the absolute path to the manifest file using the parent's
        # method, so that we can correctly create our repo_client.
        manifestFile = parent.SubmanifestInfoDir(
            os.path.join(parent.path_prefix, self.relpath),
            os.path.join("manifests", manifestName or "default.xml"),
        )
        linkFile = parent.SubmanifestInfoDir(
            os.path.join(parent.path_prefix, self.relpath), MANIFEST_FILE_NAME
        )
        self.repo_client = RepoClient(
            parent.repodir,
            linkFile,
            parent_groups=",".join(groups) or "",
            submanifest_path=os.path.join(parent.path_prefix, self.relpath),
            outer_client=outer_client,
            default_groups=default_groups,
        )

        self.present = os.path.exists(manifestFile)

    def __eq__(self, other):
        if not isinstance(other, _XmlSubmanifest):
            return False
        return (
            self.name == other.name
            and self.remote == other.remote
            and self.project == other.project
            and self.revision == other.revision
            and self.manifestName == other.manifestName
            and self.groups == other.groups
            and self.default_groups == other.default_groups
            and self.path == other.path
            and sorted(self.annotations) == sorted(other.annotations)
        )

    def __ne__(self, other):
        return not self.__eq__(other)

    def ToSubmanifestSpec(self):
        """Return a SubmanifestSpec object, populating attributes"""
        mp = self.parent.manifestProject
        remote = self.parent.remotes[
            self.remote or self.parent.default.remote.name
        ]
        # If a project was given, generate the url from the remote and project.
        # If not, use this manifestProject's url.
        if self.project:
            manifestUrl = remote.ToRemoteSpec(self.project).url
        else:
            manifestUrl = mp.GetRemote().url
        manifestName = self.manifestName or "default.xml"
        revision = self.revision or self.name
        path = self.path or revision.split("/")[-1]
        groups = self.groups or []

        return SubmanifestSpec(
            self.name, manifestUrl, manifestName, revision, path, groups
        )

    @property
    def relpath(self):
        """The path of this submanifest relative to the parent manifest."""
        revision = self.revision or self.name
        return self.path or revision.split("/")[-1]

    def GetGroupsStr(self):
        """Returns the `groups` given for this submanifest."""
        if self.groups:
            return ",".join(self.groups)
        return ""

    def GetDefaultGroupsStr(self):
        """Returns the `default-groups` given for this submanifest."""
        return ",".join(self.default_groups or [])

    def AddAnnotation(self, name, value, keep):
        """Add annotations to the submanifest."""
        self.annotations.append(Annotation(name, value, keep))


class SubmanifestSpec:
    """The submanifest element, with all fields expanded."""

    def __init__(self, name, manifestUrl, manifestName, revision, path, groups):
        self.name = name
        self.manifestUrl = manifestUrl
        self.manifestName = manifestName
        self.revision = revision
        self.path = path
        self.groups = groups or []


class XmlManifest:
    """manages the repo configuration file"""

    def __init__(
        self,
        repodir,
        manifest_file,
        local_manifests=None,
        outer_client=None,
        parent_groups="",
        submanifest_path="",
        default_groups=None,
    ):
        """Initialize.

        Args:
            repodir: Path to the .repo/ dir for holding all internal checkout
                state. It must be in the top directory of the repo client
                checkout.
            manifest_file: Full path to the manifest file to parse.  This will
                usually be |repodir|/|MANIFEST_FILE_NAME|.
            local_manifests: Full path to the directory of local override
                manifests. This will usually be
                |repodir|/|LOCAL_MANIFESTS_DIR_NAME|.
            outer_client: RepoClient of the outer manifest.
            parent_groups: a string, the groups to apply to this projects.
            submanifest_path: The submanifest root relative to the repo root.
            default_groups: a string, the default manifest groups to use.
        """
        # TODO(vapier): Move this out of this class.
        self.globalConfig = GitConfig.ForUser()

        self.repodir = os.path.abspath(repodir)
        self._CheckLocalPath(submanifest_path)
        self.topdir = os.path.dirname(self.repodir)
        if submanifest_path:
            # This avoids a trailing os.path.sep when submanifest_path is empty.
            self.topdir = os.path.join(self.topdir, submanifest_path)
        if manifest_file != os.path.abspath(manifest_file):
            raise ManifestParseError("manifest_file must be abspath")
        self.manifestFile = manifest_file
        if not outer_client or outer_client == self:
            # manifestFileOverrides only exists in the outer_client's manifest,
            # since that is the only instance left when Unload() is called on
            # the outer manifest.
            self.manifestFileOverrides = {}
        self.local_manifests = local_manifests
        self._load_local_manifests = True
        self.parent_groups = parent_groups
        self.default_groups = default_groups

        if submanifest_path and not outer_client:
            # If passing a submanifest_path, there must be an outer_client.
            raise ManifestParseError(f"Bad call to {self.__class__.__name__}")

        # If self._outer_client is None, this is not a checkout that supports
        # multi-tree.
        self._outer_client = outer_client or self

        self.repoProject = RepoProject(
            self,
            "repo",
            gitdir=os.path.join(repodir, "repo/.git"),
            worktree=os.path.join(repodir, "repo"),
        )

        mp = self.SubmanifestProject(self.path_prefix)
        self.manifestProject = mp

        # This is a bit hacky, but we're in a chicken & egg situation: all the
        # normal repo settings live in the manifestProject which we just setup
        # above, so we couldn't easily query before that.  We assume Project()
        # init doesn't care if this changes afterwards.
        if os.path.exists(mp.gitdir) and mp.use_worktree:
            mp.use_git_worktrees = True

        self.Unload()

    def Override(self, name, load_local_manifests=True):
        """Use a different manifest, just for the current instantiation."""
        path = None

        # Look for a manifest by path in the filesystem (including the cwd).
        if not load_local_manifests:
            local_path = os.path.abspath(name)
            if os.path.isfile(local_path):
                path = local_path

        # Look for manifests by name from the manifests repo.
        if path is None:
            path = os.path.join(self.manifestProject.worktree, name)
            if not os.path.isfile(path):
                raise ManifestParseError("manifest %s not found" % name)

        self._load_local_manifests = load_local_manifests
        self._outer_client.manifestFileOverrides[self.path_prefix] = path
        self.Unload()
        self._Load()

    def Link(self, name):
        """Update the repo metadata to use a different manifest."""
        self.Override(name)

        # Old versions of repo would generate symlinks we need to clean up.
        platform_utils.remove(self.manifestFile, missing_ok=True)
        # This file is interpreted as if it existed inside the manifest repo.
        # That allows us to use <include> with the relative file name.
        with open(self.manifestFile, "w") as fp:
            fp.write(
                """<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT THIS FILE!  It is generated by repo and changes will be discarded.
If you want to use a different manifest, use `repo init -m <file>` instead.

If you want to customize your checkout by overriding manifest settings, use
the local_manifests/ directory instead.

For more information on repo manifests, check out:
https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
-->
<manifest>
  <include name="%s" />
</manifest>
"""
                % (name,)
            )

    def _RemoteToXml(self, r, doc, root):
        e = doc.createElement("remote")
        root.appendChild(e)
        e.setAttribute("name", r.name)
        e.setAttribute("fetch", r.fetchUrl)
        if r.pushUrl is not None:
            e.setAttribute("pushurl", r.pushUrl)
        if r.remoteAlias is not None:
            e.setAttribute("alias", r.remoteAlias)
        if r.reviewUrl is not None:
            e.setAttribute("review", r.reviewUrl)
        if r.revision is not None:
            e.setAttribute("revision", r.revision)

        for a in r.annotations:
            if a.keep == "true":
                ae = doc.createElement("annotation")
                ae.setAttribute("name", a.name)
                ae.setAttribute("value", a.value)
                e.appendChild(ae)

    def _SubmanifestToXml(self, r, doc, root):
        """Generate XML <submanifest/> node."""
        e = doc.createElement("submanifest")
        root.appendChild(e)
        e.setAttribute("name", r.name)
        if r.remote is not None:
            e.setAttribute("remote", r.remote)
        if r.project is not None:
            e.setAttribute("project", r.project)
        if r.manifestName is not None:
            e.setAttribute("manifest-name", r.manifestName)
        if r.revision is not None:
            e.setAttribute("revision", r.revision)
        if r.path is not None:
            e.setAttribute("path", r.path)
        if r.groups:
            e.setAttribute("groups", r.GetGroupsStr())
        if r.default_groups:
            e.setAttribute("default-groups", r.GetDefaultGroupsStr())

        for a in r.annotations:
            if a.keep == "true":
                ae = doc.createElement("annotation")
                ae.setAttribute("name", a.name)
                ae.setAttribute("value", a.value)
                e.appendChild(ae)

    def _ParseList(self, field):
        """Parse fields that contain flattened lists.

        These are whitespace & comma separated.  Empty elements will be
        discarded.
        """
        return [x for x in re.split(r"[,\s]+", field) if x]

    def ToXml(
        self,
        peg_rev=False,
        peg_rev_upstream=True,
        peg_rev_dest_branch=True,
        groups=None,
        omit_local=False,
    ):
        """Return the current manifest XML."""
        mp = self.manifestProject

        if groups is None:
            groups = mp.manifest_groups
        if groups:
            groups = self._ParseList(groups)

        doc = xml.dom.minidom.Document()
        root = doc.createElement("manifest")
        if self.is_submanifest:
            root.setAttribute("path", self.path_prefix)
        doc.appendChild(root)

        # Save out the notice.  There's a little bit of work here to give it the
        # right whitespace, which assumes that the notice is automatically
        # indented by 4 by minidom.
        if self.notice:
            notice_element = root.appendChild(doc.createElement("notice"))
            notice_lines = self.notice.splitlines()
            indented_notice = (
                "\n".join(" " * 4 + line for line in notice_lines)
            )[4:]
            notice_element.appendChild(doc.createTextNode(indented_notice))

        d = self.default

        for r in sorted(self.remotes):
            self._RemoteToXml(self.remotes[r], doc, root)
        if self.remotes:
            root.appendChild(doc.createTextNode(""))

        have_default = False
        e = doc.createElement("default")
        if d.remote:
            have_default = True
            e.setAttribute("remote", d.remote.name)
        if d.revisionExpr:
            have_default = True
            e.setAttribute("revision", d.revisionExpr)
        if d.destBranchExpr:
            have_default = True
            e.setAttribute("dest-branch", d.destBranchExpr)
        if d.upstreamExpr:
            have_default = True
            e.setAttribute("upstream", d.upstreamExpr)
        if d.sync_j is not None:
            have_default = True
            e.setAttribute("sync-j", "%d" % d.sync_j)
        if d.sync_c:
            have_default = True
            e.setAttribute("sync-c", "true")
        if d.sync_s:
            have_default = True
            e.setAttribute("sync-s", "true")
        if not d.sync_tags:
            have_default = True
            e.setAttribute("sync-tags", "false")
        if have_default:
            root.appendChild(e)
            root.appendChild(doc.createTextNode(""))

        if self._manifest_server:
            e = doc.createElement("manifest-server")
            e.setAttribute("url", self._manifest_server)
            root.appendChild(e)
            root.appendChild(doc.createTextNode(""))

        for r in sorted(self.submanifests):
            self._SubmanifestToXml(self.submanifests[r], doc, root)
        if self.submanifests:
            root.appendChild(doc.createTextNode(""))

        def output_projects(parent, parent_node, projects):
            for project_name in projects:
                for project in self._projects[project_name]:
                    output_project(parent, parent_node, project)

        def output_project(parent, parent_node, p):
            if not p.MatchesGroups(groups):
                return

            if omit_local and self.IsFromLocalManifest(p):
                return

            name = p.name
            relpath = p.relpath
            if parent:
                name = self._UnjoinName(parent.name, name)
                relpath = self._UnjoinRelpath(parent.relpath, relpath)

            e = doc.createElement("project")
            parent_node.appendChild(e)
            e.setAttribute("name", name)
            if relpath != name:
                e.setAttribute("path", relpath)
            remoteName = None
            if d.remote:
                remoteName = d.remote.name
            if not d.remote or p.remote.orig_name != remoteName:
                remoteName = p.remote.orig_name
                e.setAttribute("remote", remoteName)
            if peg_rev:
                if self.IsMirror:
                    value = p.bare_git.rev_parse(p.revisionExpr + "^0")
                else:
                    value = p.work_git.rev_parse(HEAD + "^0")
                e.setAttribute("revision", value)
                if peg_rev_upstream:
                    if p.upstream:
                        e.setAttribute("upstream", p.upstream)
                    elif value != p.revisionExpr:
                        # Only save the origin if the origin is not a sha1, and
                        # the default isn't our value
                        e.setAttribute("upstream", p.revisionExpr)

                if peg_rev_dest_branch:
                    if p.dest_branch:
                        e.setAttribute("dest-branch", p.dest_branch)
                    elif value != p.revisionExpr:
                        e.setAttribute("dest-branch", p.revisionExpr)

            else:
                revision = (
                    self.remotes[p.remote.orig_name].revision or d.revisionExpr
                )
                if not revision or revision != p.revisionExpr:
                    e.setAttribute("revision", p.revisionExpr)
                elif p.revisionId:
                    e.setAttribute("revision", p.revisionId)
                if p.upstream and (
                    p.upstream != p.revisionExpr or p.upstream != d.upstreamExpr
                ):
                    e.setAttribute("upstream", p.upstream)

            if p.dest_branch and p.dest_branch != d.destBranchExpr:
                e.setAttribute("dest-branch", p.dest_branch)

            for c in p.copyfiles:
                ce = doc.createElement("copyfile")
                ce.setAttribute("src", c.src)
                ce.setAttribute("dest", c.dest)
                e.appendChild(ce)

            for lf in p.linkfiles:
                le = doc.createElement("linkfile")
                le.setAttribute("src", lf.src)
                le.setAttribute("dest", lf.dest)
                e.appendChild(le)

            default_groups = ["all", "name:%s" % p.name, "path:%s" % p.relpath]
            egroups = [g for g in p.groups if g not in default_groups]
            if egroups:
                e.setAttribute("groups", ",".join(egroups))

            for a in p.annotations:
                if a.keep == "true":
                    ae = doc.createElement("annotation")
                    ae.setAttribute("name", a.name)
                    ae.setAttribute("value", a.value)
                    e.appendChild(ae)

            if p.sync_c:
                e.setAttribute("sync-c", "true")

            if p.sync_s:
                e.setAttribute("sync-s", "true")

            if not p.sync_tags:
                e.setAttribute("sync-tags", "false")

            if p.clone_depth:
                e.setAttribute("clone-depth", str(p.clone_depth))

            self._output_manifest_project_extras(p, e)

            if p.subprojects:
                subprojects = {subp.name for subp in p.subprojects}
                output_projects(p, e, list(sorted(subprojects)))

        projects = {p.name for p in self._paths.values() if not p.parent}
        output_projects(None, root, list(sorted(projects)))

        if self._repo_hooks_project:
            root.appendChild(doc.createTextNode(""))
            e = doc.createElement("repo-hooks")
            e.setAttribute("in-project", self._repo_hooks_project.name)
            e.setAttribute(
                "enabled-list",
                " ".join(self._repo_hooks_project.enabled_repo_hooks),
            )
            root.appendChild(e)

        if self._superproject:
            root.appendChild(doc.createTextNode(""))
            e = doc.createElement("superproject")
            e.setAttribute("name", self._superproject.name)
            remoteName = None
            if d.remote:
                remoteName = d.remote.name
            remote = self._superproject.remote
            if not d.remote or remote.orig_name != remoteName:
                remoteName = remote.orig_name
                e.setAttribute("remote", remoteName)
            revision = remote.revision or d.revisionExpr
            if not revision or revision != self._superproject.revision:
                e.setAttribute("revision", self._superproject.revision)
            root.appendChild(e)

        if self._contactinfo.bugurl != Wrapper().BUG_URL:
            root.appendChild(doc.createTextNode(""))
            e = doc.createElement("contactinfo")
            e.setAttribute("bugurl", self._contactinfo.bugurl)
            root.appendChild(e)

        return doc

    def ToDict(self, **kwargs):
        """Return the current manifest as a dictionary."""
        # Elements that may only appear once.
        SINGLE_ELEMENTS = {
            "notice",
            "default",
            "manifest-server",
            "repo-hooks",
            "superproject",
            "contactinfo",
        }
        # Elements that may be repeated.
        MULTI_ELEMENTS = {
            "remote",
            "remove-project",
            "project",
            "extend-project",
            "include",
            "submanifest",
            # These are children of 'project' nodes.
            "annotation",
            "project",
            "copyfile",
            "linkfile",
        }

        doc = self.ToXml(**kwargs)
        ret = {}

        def append_children(ret, node):
            for child in node.childNodes:
                if child.nodeType == xml.dom.Node.ELEMENT_NODE:
                    attrs = child.attributes
                    element = {
                        attrs.item(i).localName: attrs.item(i).value
                        for i in range(attrs.length)
                    }
                    if child.nodeName in SINGLE_ELEMENTS:
                        ret[child.nodeName] = element
                    elif child.nodeName in MULTI_ELEMENTS:
                        ret.setdefault(child.nodeName, []).append(element)
                    else:
                        raise ManifestParseError(
                            f'Unhandled element "{child.nodeName}"'
                        )

                    append_children(element, child)

        append_children(ret, doc.firstChild)

        return ret

    def Save(self, fd, **kwargs):
        """Write the current manifest out to the given file descriptor."""
        doc = self.ToXml(**kwargs)
        doc.writexml(fd, "", "  ", "\n", "UTF-8")

    def _output_manifest_project_extras(self, p, e):
        """Manifests can modify e if they support extra project attributes."""

    @property
    def is_multimanifest(self):
        """Whether this is a multimanifest checkout.

        This is safe to use as long as the outermost manifest XML has been
        parsed.
        """
        return bool(self._outer_client._submanifests)

    @property
    def is_submanifest(self):
        """Whether this manifest is a submanifest.

        This is safe to use as long as the outermost manifest XML has been
        parsed.
        """
        return self._outer_client and self._outer_client != self

    @property
    def outer_client(self):
        """The instance of the outermost manifest client."""
        self._Load()
        return self._outer_client

    @property
    def all_manifests(self):
        """Generator yielding all (sub)manifests, in depth-first order."""
        self._Load()
        outer = self._outer_client
        yield outer
        yield from outer.all_children

    @property
    def all_children(self):
        """Generator yielding all (present) child submanifests."""
        self._Load()
        for child in self._submanifests.values():
            if child.repo_client:
                yield child.repo_client
                yield from child.repo_client.all_children

    @property
    def path_prefix(self):
        """The path of this submanifest, relative to the outermost manifest."""
        if not self._outer_client or self == self._outer_client:
            return ""
        return os.path.relpath(self.topdir, self._outer_client.topdir)

    @property
    def all_paths(self):
        """All project paths for all (sub)manifests.

        See also `paths`.

        Returns:
            A dictionary of {path: Project()}.  `path` is relative to the outer
            manifest.
        """
        ret = {}
        for tree in self.all_manifests:
            prefix = tree.path_prefix
            ret.update(
                {os.path.join(prefix, k): v for k, v in tree.paths.items()}
            )
        return ret

    @property
    def all_projects(self):
        """All projects for all (sub)manifests.  See `projects`."""
        return list(
            itertools.chain.from_iterable(
                x._paths.values() for x in self.all_manifests
            )
        )

    @property
    def paths(self):
        """Return all paths for this manifest.

        Returns:
            A dictionary of {path: Project()}.  `path` is relative to this
            manifest.
        """
        self._Load()
        return self._paths

    @property
    def projects(self):
        """Return a list of all Projects in this manifest."""
        self._Load()
        return list(self._paths.values())

    @property
    def remotes(self):
        """Return a list of remotes for this manifest."""
        self._Load()
        return self._remotes

    @property
    def default(self):
        """Return default values for this manifest."""
        self._Load()
        return self._default

    @property
    def submanifests(self):
        """All submanifests in this manifest."""
        self._Load()
        return self._submanifests

    @property
    def repo_hooks_project(self):
        self._Load()
        return self._repo_hooks_project

    @property
    def superproject(self):
        self._Load()
        return self._superproject

    @property
    def contactinfo(self):
        self._Load()
        return self._contactinfo

    @property
    def notice(self):
        self._Load()
        return self._notice

    @property
    def manifest_server(self):
        self._Load()
        return self._manifest_server

    @property
    def CloneBundle(self):
        clone_bundle = self.manifestProject.clone_bundle
        if clone_bundle is None:
            return False if self.manifestProject.partial_clone else True
        else:
            return clone_bundle

    @property
    def CloneFilter(self):
        if self.manifestProject.partial_clone:
            return self.manifestProject.clone_filter
        return None

    @property
    def CloneFilterForDepth(self):
        if self.manifestProject.clone_filter_for_depth:
            return self.manifestProject.clone_filter_for_depth
        return None

    @property
    def PartialCloneExclude(self):
        exclude = self.manifest.manifestProject.partial_clone_exclude or ""
        return {x.strip() for x in exclude.split(",")}

    def SetManifestOverride(self, path):
        """Override manifestFile.  The caller must call Unload()"""
        self._outer_client.manifest.manifestFileOverrides[
            self.path_prefix
        ] = path

    @property
    def UseLocalManifests(self):
        return self._load_local_manifests

    def SetUseLocalManifests(self, value):
        self._load_local_manifests = value

    @property
    def HasLocalManifests(self):
        return self._load_local_manifests and self.local_manifests

    def IsFromLocalManifest(self, project):
        """Is the project from a local manifest?"""
        return any(
            x.startswith(LOCAL_MANIFEST_GROUP_PREFIX) for x in project.groups
        )

    @property
    def IsMirror(self):
        return self.manifestProject.mirror

    @property
    def UseGitWorktrees(self):
        return self.manifestProject.use_worktree

    @property
    def IsArchive(self):
        return self.manifestProject.archive

    @property
    def HasSubmodules(self):
        return self.manifestProject.submodules

    @property
    def EnableGitLfs(self):
        return self.manifestProject.git_lfs

    def FindManifestByPath(self, path):
        """Returns the manifest containing path."""
        path = os.path.abspath(path)
        manifest = self._outer_client or self
        old = None
        while manifest._submanifests and manifest != old:
            old = manifest
            for name in manifest._submanifests:
                tree = manifest._submanifests[name]
                if path.startswith(tree.repo_client.manifest.topdir):
                    manifest = tree.repo_client
                    break
        return manifest

    @property
    def subdir(self):
        """Returns the path for per-submanifest objects for this manifest."""
        return self.SubmanifestInfoDir(self.path_prefix)

    def SubmanifestInfoDir(self, submanifest_path, object_path=""):
        """Return the path to submanifest-specific info for a submanifest.

        Return the full path of the directory in which to put per-manifest
        objects.

        Args:
            submanifest_path: a string, the path of the submanifest, relative to
                the outermost topdir.  If empty, then repodir is returned.
            object_path: a string, relative path to append to the submanifest
                info directory path.
        """
        if submanifest_path:
            return os.path.join(
                self.repodir, SUBMANIFEST_DIR, submanifest_path, object_path
            )
        else:
            return os.path.join(self.repodir, object_path)

    def SubmanifestProject(self, submanifest_path):
        """Return a manifestProject for a submanifest."""
        subdir = self.SubmanifestInfoDir(submanifest_path)
        mp = ManifestProject(
            self,
            "manifests",
            gitdir=os.path.join(subdir, "manifests.git"),
            worktree=os.path.join(subdir, "manifests"),
        )
        return mp

    def GetDefaultGroupsStr(self, with_platform=True):
        """Returns the default group string to use.

        Args:
            with_platform: a boolean, whether to include the group for the
                          underlying platform.
        """
        groups = ",".join(self.default_groups or ["default"])
        if with_platform:
            groups += f",platform-{platform.system().lower()}"
        return groups

    def GetGroupsStr(self):
        """Returns the manifest group string that should be synced."""
        return (
            self.manifestProject.manifest_groups or self.GetDefaultGroupsStr()
        )

    def Unload(self):
        """Unload the manifest.

        If the manifest files have been changed since Load() was called, this
        will cause the new/updated manifest to be used.

        """
        self._loaded = False
        self._projects = {}
        self._paths = {}
        self._remotes = {}
        self._default = None
        self._submanifests = {}
        self._repo_hooks_project = None
        self._superproject = None
        self._contactinfo = ContactInfo(Wrapper().BUG_URL)
        self._notice = None
        self.branch = None
        self._manifest_server = None

    def Load(self):
        """Read the manifest into memory."""
        # Do not expose internal arguments.
        self._Load()

    def _Load(self, initial_client=None, submanifest_depth=0):
        if submanifest_depth > MAX_SUBMANIFEST_DEPTH:
            raise ManifestParseError(
                "maximum submanifest depth %d exceeded." % MAX_SUBMANIFEST_DEPTH
            )
        if not self._loaded:
            if self._outer_client and self._outer_client != self:
                # This will load all clients.
                self._outer_client._Load(initial_client=self)

            savedManifestFile = self.manifestFile
            override = self._outer_client.manifestFileOverrides.get(
                self.path_prefix
            )
            if override:
                self.manifestFile = override

            try:
                m = self.manifestProject
                b = m.GetBranch(m.CurrentBranch).merge
                if b is not None and b.startswith(R_HEADS):
                    b = b[len(R_HEADS) :]
                self.branch = b

                parent_groups = self.parent_groups
                if self.path_prefix:
                    parent_groups = (
                        f"{SUBMANIFEST_GROUP_PREFIX}:path:"
                        f"{self.path_prefix},{parent_groups}"
                    )

                # The manifestFile was specified by the user which is why we
                # allow include paths to point anywhere.
                nodes = []
                nodes.append(
                    self._ParseManifestXml(
                        self.manifestFile,
                        self.manifestProject.worktree,
                        parent_groups=parent_groups,
                        restrict_includes=False,
                    )
                )

                if self._load_local_manifests and self.local_manifests:
                    try:
                        for local_file in sorted(
                            platform_utils.listdir(self.local_manifests)
                        ):
                            if local_file.endswith(".xml"):
                                local = os.path.join(
                                    self.local_manifests, local_file
                                )
                                # Since local manifests are entirely managed by
                                # the user, allow them to point anywhere the
                                # user wants.
                                local_group = (
                                    f"{LOCAL_MANIFEST_GROUP_PREFIX}:"
                                    f"{local_file[:-4]}"
                                )
                                nodes.append(
                                    self._ParseManifestXml(
                                        local,
                                        self.subdir,
                                        parent_groups=(
                                            f"{local_group},{parent_groups}"
                                        ),
                                        restrict_includes=False,
                                    )
                                )
                    except OSError:
                        pass

                try:
                    self._ParseManifest(nodes)
                except ManifestParseError as e:
                    # There was a problem parsing, unload ourselves in case they
                    # catch this error and try again later, we will show the
                    # correct error
                    self.Unload()
                    raise e

                if self.IsMirror:
                    self._AddMetaProjectMirror(self.repoProject)
                    self._AddMetaProjectMirror(self.manifestProject)

                self._loaded = True
            finally:
                if override:
                    self.manifestFile = savedManifestFile

            # Now that we have loaded this manifest, load any submanifests as
            # well. We need to do this after self._loaded is set to avoid
            # looping.
            for name in self._submanifests:
                tree = self._submanifests[name]
                tree.ToSubmanifestSpec()
                present = os.path.exists(
                    os.path.join(self.subdir, MANIFEST_FILE_NAME)
                )
                if present and tree.present and not tree.repo_client:
                    if initial_client and initial_client.topdir == self.topdir:
                        tree.repo_client = self
                        tree.present = present
                    elif not os.path.exists(self.subdir):
                        tree.present = False
                if present and tree.present:
                    tree.repo_client._Load(
                        initial_client=initial_client,
                        submanifest_depth=submanifest_depth + 1,
                    )

    def _ParseManifestXml(
        self,
        path,
        include_root,
        parent_groups="",
        restrict_includes=True,
        parent_node=None,
    ):
        """Parse a manifest XML and return the computed nodes.

        Args:
            path: The XML file to read & parse.
            include_root: The path to interpret include "name"s relative to.
            parent_groups: The groups to apply to this projects.
            restrict_includes: Whether to constrain the "name" attribute of
                includes.
            parent_node: The parent include node, to apply attribute to this
                projects.

        Returns:
            List of XML nodes.
        """
        try:
            root = xml.dom.minidom.parse(path)
        except (OSError, xml.parsers.expat.ExpatError) as e:
            raise ManifestParseError(f"error parsing manifest {path}: {e}")

        if not root or not root.childNodes:
            raise ManifestParseError(f"no root node in {path}")

        for manifest in root.childNodes:
            if (
                manifest.nodeType == manifest.ELEMENT_NODE
                and manifest.nodeName == "manifest"
            ):
                break
        else:
            raise ManifestParseError(f"no <manifest> in {path}")

        nodes = []
        for node in manifest.childNodes:
            if node.nodeName == "include":
                name = self._reqatt(node, "name")
                if restrict_includes:
                    msg = self._CheckLocalPath(name)
                    if msg:
                        raise ManifestInvalidPathError(
                            f'<include> invalid "name": {name}: {msg}'
                        )
                include_groups = ""
                if parent_groups:
                    include_groups = parent_groups
                if node.hasAttribute("groups"):
                    include_groups = (
                        node.getAttribute("groups") + "," + include_groups
                    )
                fp = os.path.join(include_root, name)
                if not os.path.isfile(fp):
                    raise ManifestParseError(
                        "include [%s/]%s doesn't exist or isn't a file"
                        % (include_root, name)
                    )
                try:
                    nodes.extend(
                        self._ParseManifestXml(
                            fp, include_root, include_groups, parent_node=node
                        )
                    )
                # should isolate this to the exact exception, but that's
                # tricky.  actual parsing implementation may vary.
                except (
                    KeyboardInterrupt,
                    RuntimeError,
                    SystemExit,
                    ManifestParseError,
                ):
                    raise
                except Exception as e:
                    raise ManifestParseError(
                        f"failed parsing included manifest {name}: {e}"
                    )
            else:
                if parent_groups and node.nodeName == "project":
                    nodeGroups = parent_groups
                    if node.hasAttribute("groups"):
                        nodeGroups = (
                            node.getAttribute("groups") + "," + nodeGroups
                        )
                    node.setAttribute("groups", nodeGroups)
                if (
                    parent_node
                    and node.nodeName == "project"
                    and not node.hasAttribute("revision")
                ):
                    node.setAttribute(
                        "revision", parent_node.getAttribute("revision")
                    )
                nodes.append(node)
        return nodes

    def _ParseManifest(self, node_list):
        for node in itertools.chain(*node_list):
            if node.nodeName == "remote":
                remote = self._ParseRemote(node)
                if remote:
                    if remote.name in self._remotes:
                        if remote != self._remotes[remote.name]:
                            raise ManifestParseError(
                                "remote %s already exists with different "
                                "attributes" % (remote.name)
                            )
                    else:
                        self._remotes[remote.name] = remote

        for node in itertools.chain(*node_list):
            if node.nodeName == "default":
                new_default = self._ParseDefault(node)
                emptyDefault = (
                    not node.hasAttributes() and not node.hasChildNodes()
                )
                if self._default is None:
                    self._default = new_default
                elif not emptyDefault and new_default != self._default:
                    raise ManifestParseError(
                        "duplicate default in %s" % (self.manifestFile)
                    )

        if self._default is None:
            self._default = _Default()

        submanifest_paths = set()
        for node in itertools.chain(*node_list):
            if node.nodeName == "submanifest":
                submanifest = self._ParseSubmanifest(node)
                if submanifest:
                    if submanifest.name in self._submanifests:
                        if submanifest != self._submanifests[submanifest.name]:
                            raise ManifestParseError(
                                "submanifest %s already exists with different "
                                "attributes" % (submanifest.name)
                            )
                    else:
                        self._submanifests[submanifest.name] = submanifest
                        submanifest_paths.add(submanifest.relpath)

        for node in itertools.chain(*node_list):
            if node.nodeName == "notice":
                if self._notice is not None:
                    raise ManifestParseError(
                        "duplicate notice in %s" % (self.manifestFile)
                    )
                self._notice = self._ParseNotice(node)

        for node in itertools.chain(*node_list):
            if node.nodeName == "manifest-server":
                url = self._reqatt(node, "url")
                if self._manifest_server is not None:
                    raise ManifestParseError(
                        "duplicate manifest-server in %s" % (self.manifestFile)
                    )
                self._manifest_server = url

        def recursively_add_projects(project):
            projects = self._projects.setdefault(project.name, [])
            if project.relpath is None:
                raise ManifestParseError(
                    "missing path for %s in %s"
                    % (project.name, self.manifestFile)
                )
            if project.relpath in self._paths:
                raise ManifestParseError(
                    "duplicate path %s in %s"
                    % (project.relpath, self.manifestFile)
                )
            for tree in submanifest_paths:
                if project.relpath.startswith(tree):
                    raise ManifestParseError(
                        "project %s conflicts with submanifest path %s"
                        % (project.relpath, tree)
                    )
            self._paths[project.relpath] = project
            projects.append(project)
            for subproject in project.subprojects:
                recursively_add_projects(subproject)

        repo_hooks_project = None
        enabled_repo_hooks = None
        failed_revision_changes = []
        for node in itertools.chain(*node_list):
            if node.nodeName == "project":
                project = self._ParseProject(node)
                recursively_add_projects(project)
            if node.nodeName == "extend-project":
                name = self._reqatt(node, "name")

                if name not in self._projects:
                    raise ManifestParseError(
                        "extend-project element specifies non-existent "
                        "project: %s" % name
                    )

                path = node.getAttribute("path")
                dest_path = node.getAttribute("dest-path")
                groups = node.getAttribute("groups")
                if groups:
                    groups = self._ParseList(groups)
                revision = node.getAttribute("revision")
                remote_name = node.getAttribute("remote")
                if not remote_name:
                    remote = self._default.remote
                else:
                    remote = self._get_remote(node)
                dest_branch = node.getAttribute("dest-branch")
                upstream = node.getAttribute("upstream")
                base_revision = node.getAttribute("base-rev")

                named_projects = self._projects[name]
                if dest_path and not path and len(named_projects) > 1:
                    raise ManifestParseError(
                        "extend-project cannot use dest-path when "
                        "matching multiple projects: %s" % name
                    )
                for p in self._projects[name]:
                    if path and p.relpath != path:
                        continue
                    if groups:
                        p.groups.extend(groups)
                    if revision:
                        if base_revision:
                            if p.revisionExpr != base_revision:
                                failed_revision_changes.append(
                                    "extend-project name %s mismatch base "
                                    "%s vs revision %s"
                                    % (name, base_revision, p.revisionExpr)
                                )
                        p.SetRevision(revision)

                    if remote_name:
                        p.remote = remote.ToRemoteSpec(name)
                    if dest_branch:
                        p.dest_branch = dest_branch
                    if upstream:
                        p.upstream = upstream

                    if dest_path:
                        del self._paths[p.relpath]
                        (
                            relpath,
                            worktree,
                            gitdir,
                            objdir,
                            _,
                        ) = self.GetProjectPaths(name, dest_path, remote.name)
                        p.UpdatePaths(relpath, worktree, gitdir, objdir)
                        self._paths[p.relpath] = p

            if node.nodeName == "repo-hooks":
                # Only one project can be the hooks project
                if repo_hooks_project is not None:
                    raise ManifestParseError(
                        "duplicate repo-hooks in %s" % (self.manifestFile)
                    )

                # Get the name of the project and the (space-separated) list of
                # enabled.
                repo_hooks_project = self._reqatt(node, "in-project")
                enabled_repo_hooks = self._ParseList(
                    self._reqatt(node, "enabled-list")
                )
            if node.nodeName == "superproject":
                name = self._reqatt(node, "name")
                # There can only be one superproject.
                if self._superproject:
                    raise ManifestParseError(
                        "duplicate superproject in %s" % (self.manifestFile)
                    )
                remote_name = node.getAttribute("remote")
                if not remote_name:
                    remote = self._default.remote
                else:
                    remote = self._get_remote(node)
                if remote is None:
                    raise ManifestParseError(
                        "no remote for superproject %s within %s"
                        % (name, self.manifestFile)
                    )
                revision = node.getAttribute("revision") or remote.revision
                if not revision:
                    revision = self._default.revisionExpr
                if not revision:
                    raise ManifestParseError(
                        "no revision for superproject %s within %s"
                        % (name, self.manifestFile)
                    )
                self._superproject = Superproject(
                    self,
                    name=name,
                    remote=remote.ToRemoteSpec(name),
                    revision=revision,
                )
            if node.nodeName == "contactinfo":
                bugurl = self._reqatt(node, "bugurl")
                # This element can be repeated, later entries will clobber
                # earlier ones.
                self._contactinfo = ContactInfo(bugurl)

            if node.nodeName == "remove-project":
                name = node.getAttribute("name")
                path = node.getAttribute("path")
                base_revision = node.getAttribute("base-rev")

                # Name or path needed.
                if not name and not path:
                    raise ManifestParseError(
                        "remove-project must have name and/or path"
                    )

                removed_project = ""

                # Find and remove projects based on name and/or path.
                for projname, projects in list(self._projects.items()):
                    for p in projects:
                        if name == projname and not path:
                            if base_revision:
                                if p.revisionExpr != base_revision:
                                    failed_revision_changes.append(
                                        "remove-project name %s mismatch base "
                                        "%s vs revision %s"
                                        % (name, base_revision, p.revisionExpr)
                                    )
                            del self._paths[p.relpath]
                            if not removed_project:
                                del self._projects[name]
                                removed_project = name
                        elif path == p.relpath and (
                            name == projname or not name
                        ):
                            if base_revision:
                                if p.revisionExpr != base_revision:
                                    failed_revision_changes.append(
                                        "remove-project path %s mismatch base "
                                        "%s vs revision %s"
                                        % (
                                            p.relpath,
                                            base_revision,
                                            p.revisionExpr,
                                        )
                                    )
                            self._projects[projname].remove(p)
                            del self._paths[p.relpath]
                            removed_project = p.name

                # If the manifest removes the hooks project, treat it as if
                # it deleted the repo-hooks element too.
                if (
                    removed_project
                    and removed_project not in self._projects
                    and repo_hooks_project == removed_project
                ):
                    repo_hooks_project = None

                if not removed_project and not XmlBool(node, "optional", False):
                    raise ManifestParseError(
                        "remove-project element specifies non-existent "
                        "project: %s" % node.toxml()
                    )

        if failed_revision_changes:
            raise ManifestParseError(
                "revision base check failed, rebase patches and update "
                "base revs for: ",
                failed_revision_changes,
            )

        # Store repo hooks project information.
        if repo_hooks_project:
            # Store a reference to the Project.
            try:
                repo_hooks_projects = self._projects[repo_hooks_project]
            except KeyError:
                raise ManifestParseError(
                    "project %s not found for repo-hooks" % (repo_hooks_project)
                )

            if len(repo_hooks_projects) != 1:
                raise ManifestParseError(
                    "internal error parsing repo-hooks in %s"
                    % (self.manifestFile)
                )
            self._repo_hooks_project = repo_hooks_projects[0]
            # Store the enabled hooks in the Project object.
            self._repo_hooks_project.enabled_repo_hooks = enabled_repo_hooks

    def _AddMetaProjectMirror(self, m):
        name = None
        m_url = m.GetRemote().url
        if m_url.endswith("/.git"):
            raise ManifestParseError("refusing to mirror %s" % m_url)

        if self._default and self._default.remote:
            url = self._default.remote.resolvedFetchUrl
            if not url.endswith("/"):
                url += "/"
            if m_url.startswith(url):
                remote = self._default.remote
                name = m_url[len(url) :]

        if name is None:
            s = m_url.rindex("/") + 1
            manifestUrl = self.manifestProject.config.GetString(
                "remote.origin.url"
            )
            remote = _XmlRemote(
                "origin", fetch=m_url[:s], manifestUrl=manifestUrl
            )
            name = m_url[s:]

        if name.endswith(".git"):
            name = name[:-4]

        if name not in self._projects:
            m.PreSync()
            gitdir = os.path.join(self.topdir, "%s.git" % name)
            project = Project(
                manifest=self,
                name=name,
                remote=remote.ToRemoteSpec(name),
                gitdir=gitdir,
                objdir=gitdir,
                worktree=None,
                relpath=name or None,
                revisionExpr=m.revisionExpr,
                revisionId=None,
            )
            self._projects[project.name] = [project]
            self._paths[project.relpath] = project

    def _ParseRemote(self, node):
        """
        reads a <remote> element from the manifest file
        """
        name = self._reqatt(node, "name")
        alias = node.getAttribute("alias")
        if alias == "":
            alias = None
        fetch = self._reqatt(node, "fetch")
        pushUrl = node.getAttribute("pushurl")
        if pushUrl == "":
            pushUrl = None
        review = node.getAttribute("review")
        if review == "":
            review = None
        revision = node.getAttribute("revision")
        if revision == "":
            revision = None
        manifestUrl = self.manifestProject.config.GetString("remote.origin.url")

        remote = _XmlRemote(
            name, alias, fetch, pushUrl, manifestUrl, review, revision
        )

        for n in node.childNodes:
            if n.nodeName == "annotation":
                self._ParseAnnotation(remote, n)

        return remote

    def _ParseDefault(self, node):
        """
        reads a <default> element from the manifest file
        """
        d = _Default()
        d.remote = self._get_remote(node)
        d.revisionExpr = node.getAttribute("revision")
        if d.revisionExpr == "":
            d.revisionExpr = None

        d.destBranchExpr = node.getAttribute("dest-branch") or None
        d.upstreamExpr = node.getAttribute("upstream") or None

        d.sync_j = XmlInt(node, "sync-j", None)
        if d.sync_j is not None and d.sync_j <= 0:
            raise ManifestParseError(
                '%s: sync-j must be greater than 0, not "%s"'
                % (self.manifestFile, d.sync_j)
            )

        d.sync_c = XmlBool(node, "sync-c", False)
        d.sync_s = XmlBool(node, "sync-s", False)
        d.sync_tags = XmlBool(node, "sync-tags", True)
        return d

    def _ParseNotice(self, node):
        """
        reads a <notice> element from the manifest file

        The <notice> element is distinct from other tags in the XML in that the
        data is conveyed between the start and end tag (it's not an
        empty-element tag).

        The white space (carriage returns, indentation) for the notice element
        is relevant and is parsed in a way that is based on how python
        docstrings work. In fact, the code is remarkably similar to here:
          http://www.python.org/dev/peps/pep-0257/
        """
        # Get the data out of the node...
        notice = node.childNodes[0].data

        # Figure out minimum indentation, skipping the first line (the same line
        # as the <notice> tag)...
        minIndent = sys.maxsize
        lines = notice.splitlines()
        for line in lines[1:]:
            lstrippedLine = line.lstrip()
            if lstrippedLine:
                indent = len(line) - len(lstrippedLine)
                minIndent = min(indent, minIndent)

        # Strip leading / trailing blank lines and also indentation.
        cleanLines = [lines[0].strip()]
        for line in lines[1:]:
            cleanLines.append(line[minIndent:].rstrip())

        # Clear completely blank lines from front and back...
        while cleanLines and not cleanLines[0]:
            del cleanLines[0]
        while cleanLines and not cleanLines[-1]:
            del cleanLines[-1]

        return "\n".join(cleanLines)

    def _ParseSubmanifest(self, node):
        """Reads a <submanifest> element from the manifest file."""
        name = self._reqatt(node, "name")
        remote = node.getAttribute("remote")
        if remote == "":
            remote = None
        project = node.getAttribute("project")
        if project == "":
            project = None
        revision = node.getAttribute("revision")
        if revision == "":
            revision = None
        manifestName = node.getAttribute("manifest-name")
        if manifestName == "":
            manifestName = None
        groups = ""
        if node.hasAttribute("groups"):
            groups = node.getAttribute("groups")
        groups = self._ParseList(groups)
        default_groups = self._ParseList(node.getAttribute("default-groups"))
        path = node.getAttribute("path")
        if path == "":
            path = None
            if revision:
                msg = self._CheckLocalPath(revision.split("/")[-1])
                if msg:
                    raise ManifestInvalidPathError(
                        '<submanifest> invalid "revision": %s: %s'
                        % (revision, msg)
                    )
            else:
                msg = self._CheckLocalPath(name)
                if msg:
                    raise ManifestInvalidPathError(
                        f'<submanifest> invalid "name": {name}: {msg}'
                    )
        else:
            msg = self._CheckLocalPath(path)
            if msg:
                raise ManifestInvalidPathError(
                    f'<submanifest> invalid "path": {path}: {msg}'
                )

        submanifest = _XmlSubmanifest(
            name,
            remote,
            project,
            revision,
            manifestName,
            groups,
            default_groups,
            path,
            self,
        )

        for n in node.childNodes:
            if n.nodeName == "annotation":
                self._ParseAnnotation(submanifest, n)

        return submanifest

    def _JoinName(self, parent_name, name):
        return os.path.join(parent_name, name)

    def _UnjoinName(self, parent_name, name):
        return os.path.relpath(name, parent_name)

    def _ParseProject(self, node, parent=None, **extra_proj_attrs):
        """
        reads a <project> element from the manifest file
        """
        name = self._reqatt(node, "name")
        msg = self._CheckLocalPath(name, dir_ok=True)
        if msg:
            raise ManifestInvalidPathError(
                f'<project> invalid "name": {name}: {msg}'
            )
        if parent:
            name = self._JoinName(parent.name, name)

        remote = self._get_remote(node)
        if remote is None:
            remote = self._default.remote
        if remote is None:
            raise ManifestParseError(
                f"no remote for project {name} within {self.manifestFile}"
            )

        revisionExpr = node.getAttribute("revision") or remote.revision
        if not revisionExpr:
            revisionExpr = self._default.revisionExpr
        if not revisionExpr:
            raise ManifestParseError(
                "no revision for project %s within %s"
                % (name, self.manifestFile)
            )

        path = node.getAttribute("path")
        if not path:
            path = name
        else:
            # NB: The "." project is handled specially in
            # Project.Sync_LocalHalf.
            msg = self._CheckLocalPath(path, dir_ok=True, cwd_dot_ok=True)
            if msg:
                raise ManifestInvalidPathError(
                    f'<project> invalid "path": {path}: {msg}'
                )

        rebase = XmlBool(node, "rebase", True)
        sync_c = XmlBool(node, "sync-c", False)
        sync_s = XmlBool(node, "sync-s", self._default.sync_s)
        sync_tags = XmlBool(node, "sync-tags", self._default.sync_tags)

        clone_depth = XmlInt(node, "clone-depth")
        if clone_depth is not None and clone_depth <= 0:
            raise ManifestParseError(
                '%s: clone-depth must be greater than 0, not "%s"'
                % (self.manifestFile, clone_depth)
            )

        dest_branch = (
            node.getAttribute("dest-branch") or self._default.destBranchExpr
        )

        upstream = node.getAttribute("upstream") or self._default.upstreamExpr

        groups = ""
        if node.hasAttribute("groups"):
            groups = node.getAttribute("groups")
        groups = self._ParseList(groups)

        if parent is None:
            (
                relpath,
                worktree,
                gitdir,
                objdir,
                use_git_worktrees,
            ) = self.GetProjectPaths(name, path, remote.name)
        else:
            use_git_worktrees = False
            relpath, worktree, gitdir, objdir = self.GetSubprojectPaths(
                parent, name, path
            )

        default_groups = ["all", "name:%s" % name, "path:%s" % relpath]
        groups.extend(set(default_groups).difference(groups))

        if self.IsMirror and node.hasAttribute("force-path"):
            if XmlBool(node, "force-path", False):
                gitdir = os.path.join(self.topdir, "%s.git" % path)

        project = Project(
            manifest=self,
            name=name,
            remote=remote.ToRemoteSpec(name),
            gitdir=gitdir,
            objdir=objdir,
            worktree=worktree,
            relpath=relpath,
            revisionExpr=revisionExpr,
            revisionId=None,
            rebase=rebase,
            groups=groups,
            sync_c=sync_c,
            sync_s=sync_s,
            sync_tags=sync_tags,
            clone_depth=clone_depth,
            upstream=upstream,
            parent=parent,
            dest_branch=dest_branch,
            use_git_worktrees=use_git_worktrees,
            **extra_proj_attrs,
        )

        for n in node.childNodes:
            if n.nodeName == "copyfile":
                self._ParseCopyFile(project, n)
            if n.nodeName == "linkfile":
                self._ParseLinkFile(project, n)
            if n.nodeName == "annotation":
                self._ParseAnnotation(project, n)
            if n.nodeName == "project":
                project.subprojects.append(
                    self._ParseProject(n, parent=project)
                )

        return project

    def GetProjectPaths(self, name, path, remote):
        """Return the paths for a project.

        Args:
            name: a string, the name of the project.
            path: a string, the path of the project.
            remote: a string, the remote.name of the project.

        Returns:
            A tuple of (relpath, worktree, gitdir, objdir, use_git_worktrees)
            for the project with |name| and |path|.
        """
        # The manifest entries might have trailing slashes.  Normalize them to
        # avoid unexpected filesystem behavior since we do string concatenation
        # below.
        path = path.rstrip("/")
        name = name.rstrip("/")
        remote = remote.rstrip("/")
        use_git_worktrees = False
        use_remote_name = self.is_multimanifest
        relpath = path
        if self.IsMirror:
            worktree = None
            gitdir = os.path.join(self.topdir, "%s.git" % name)
            objdir = gitdir
        else:
            if use_remote_name:
                namepath = os.path.join(remote, f"{name}.git")
            else:
                namepath = f"{name}.git"
            worktree = os.path.join(self.topdir, path).replace("\\", "/")
            gitdir = os.path.join(self.subdir, "projects", "%s.git" % path)
            # We allow people to mix git worktrees & non-git worktrees for now.
            # This allows for in situ migration of repo clients.
            if os.path.exists(gitdir) or not self.UseGitWorktrees:
                objdir = os.path.join(self.repodir, "project-objects", namepath)
            else:
                use_git_worktrees = True
                gitdir = os.path.join(self.repodir, "worktrees", namepath)
                objdir = gitdir
        return relpath, worktree, gitdir, objdir, use_git_worktrees

    def GetProjectsWithName(self, name, all_manifests=False):
        """All projects with |name|.

        Args:
            name: a string, the name of the project.
            all_manifests: a boolean, if True, then all manifests are searched.
                If False, then only this manifest is searched.

        Returns:
            A list of Project instances with name |name|.
        """
        if all_manifests:
            return list(
                itertools.chain.from_iterable(
                    x._projects.get(name, []) for x in self.all_manifests
                )
            )
        return self._projects.get(name, [])

    def GetSubprojectName(self, parent, submodule_path):
        return os.path.join(parent.name, submodule_path)

    def _JoinRelpath(self, parent_relpath, relpath):
        return os.path.join(parent_relpath, relpath)

    def _UnjoinRelpath(self, parent_relpath, relpath):
        return os.path.relpath(relpath, parent_relpath)

    def GetSubprojectPaths(self, parent, name, path):
        # The manifest entries might have trailing slashes.  Normalize them to
        # avoid unexpected filesystem behavior since we do string concatenation
        # below.
        path = path.rstrip("/")
        name = name.rstrip("/")
        relpath = self._JoinRelpath(parent.relpath, path)
        gitdir = os.path.join(parent.gitdir, "subprojects", "%s.git" % path)
        objdir = os.path.join(
            parent.gitdir, "subproject-objects", "%s.git" % name
        )
        if self.IsMirror:
            worktree = None
        else:
            worktree = os.path.join(parent.worktree, path).replace("\\", "/")
        return relpath, worktree, gitdir, objdir

    @staticmethod
    def _CheckLocalPath(path, dir_ok=False, cwd_dot_ok=False):
        """Verify |path| is reasonable for use in filesystem paths.

        Used with <copyfile> & <linkfile> & <project> elements.

        This only validates the |path| in isolation: it does not check against
        the current filesystem state.  Thus it is suitable as a first-past in a
        parser.

        It enforces a number of constraints:
        * No empty paths.
        * No "~" in paths.
        * No Unicode codepoints that filesystems might elide when normalizing.
        * No relative path components like "." or "..".
        * No absolute paths.
        * No ".git" or ".repo*" path components.

        Args:
            path: The path name to validate.
            dir_ok: Whether |path| may force a directory (e.g. end in a /).
            cwd_dot_ok: Whether |path| may be just ".".

        Returns:
            None if |path| is OK, a failure message otherwise.
        """
        if not path:
            return "empty paths not allowed"

        if "~" in path:
            return "~ not allowed (due to 8.3 filenames on Windows filesystems)"

        path_codepoints = set(path)

        # Some filesystems (like Apple's HFS+) try to normalize Unicode
        # codepoints which means there are alternative names for ".git".  Reject
        # paths with these in it as there shouldn't be any reasonable need for
        # them here. The set of codepoints here was cribbed from jgit's
        # implementation:
        # https://eclipse.googlesource.com/jgit/jgit/+/9110037e3e9461ff4dac22fee84ef3694ed57648/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java#884
        BAD_CODEPOINTS = {
            "\u200C",  # ZERO WIDTH NON-JOINER
            "\u200D",  # ZERO WIDTH JOINER
            "\u200E",  # LEFT-TO-RIGHT MARK
            "\u200F",  # RIGHT-TO-LEFT MARK
            "\u202A",  # LEFT-TO-RIGHT EMBEDDING
            "\u202B",  # RIGHT-TO-LEFT EMBEDDING
            "\u202C",  # POP DIRECTIONAL FORMATTING
            "\u202D",  # LEFT-TO-RIGHT OVERRIDE
            "\u202E",  # RIGHT-TO-LEFT OVERRIDE
            "\u206A",  # INHIBIT SYMMETRIC SWAPPING
            "\u206B",  # ACTIVATE SYMMETRIC SWAPPING
            "\u206C",  # INHIBIT ARABIC FORM SHAPING
            "\u206D",  # ACTIVATE ARABIC FORM SHAPING
            "\u206E",  # NATIONAL DIGIT SHAPES
            "\u206F",  # NOMINAL DIGIT SHAPES
            "\uFEFF",  # ZERO WIDTH NO-BREAK SPACE
        }
        if BAD_CODEPOINTS & path_codepoints:
            # This message is more expansive than reality, but should be fine.
            return "Unicode combining characters not allowed"

        # Reject newlines as there shouldn't be any legitmate use for them,
        # they'll be confusing to users, and they can easily break tools that
        # expect to be able to iterate over newline delimited lists.  This even
        # applies to our own code like .repo/project.list.
        if {"\r", "\n"} & path_codepoints:
            return "Newlines not allowed"

        # Assume paths might be used on case-insensitive filesystems.
        path = path.lower()

        # Split up the path by its components.  We can't use os.path.sep
        # exclusively as some platforms (like Windows) will convert / to \ and
        # that bypasses all our constructed logic here.  Especially since
        # manifest authors only use / in their paths.
        resep = re.compile(r"[/%s]" % re.escape(os.path.sep))
        # Strip off trailing slashes as those only produce '' elements, and we
        # use parts to look for individual bad components.
        parts = resep.split(path.rstrip("/"))

        # Some people use src="." to create stable links to projects.  Lets
        # allow that but reject all other uses of "." to keep things simple.
        if not cwd_dot_ok or parts != ["."]:
            for part in set(parts):
                if part in {".", "..", ".git"} or part.startswith(".repo"):
                    return f"bad component: {part}"

        if not dir_ok and resep.match(path[-1]):
            return "dirs not allowed"

        # NB: The two abspath checks here are to handle platforms with multiple
        # filesystem path styles (e.g. Windows).
        norm = os.path.normpath(path)
        if (
            norm == ".."
            or (
                len(norm) >= 3
                and norm.startswith("..")
                and resep.match(norm[0])
            )
            or os.path.isabs(norm)
            or norm.startswith("/")
        ):
            return "path cannot be outside"

    @classmethod
    def _ValidateFilePaths(cls, element, src, dest):
        """Verify |src| & |dest| are reasonable for <copyfile> & <linkfile>.

        We verify the path independent of any filesystem state as we won't have
        a checkout available to compare to.  i.e. This is for parsing validation
        purposes only.

        We'll do full/live sanity checking before we do the actual filesystem
        modifications in _CopyFile/_LinkFile/etc...
        """
        # |dest| is the file we write to or symlink we create.
        # It is relative to the top of the repo client checkout.
        msg = cls._CheckLocalPath(dest)
        if msg:
            raise ManifestInvalidPathError(
                f'<{element}> invalid "dest": {dest}: {msg}'
            )

        # |src| is the file we read from or path we point to for symlinks.
        # It is relative to the top of the git project checkout.
        is_linkfile = element == "linkfile"
        msg = cls._CheckLocalPath(
            src, dir_ok=is_linkfile, cwd_dot_ok=is_linkfile
        )
        if msg:
            raise ManifestInvalidPathError(
                f'<{element}> invalid "src": {src}: {msg}'
            )

    def _ParseCopyFile(self, project, node):
        src = self._reqatt(node, "src")
        dest = self._reqatt(node, "dest")
        if not self.IsMirror:
            # src is project relative;
            # dest is relative to the top of the tree.
            # We only validate paths if we actually plan to process them.
            self._ValidateFilePaths("copyfile", src, dest)
            project.AddCopyFile(src, dest, self.topdir)

    def _ParseLinkFile(self, project, node):
        src = self._reqatt(node, "src")
        dest = self._reqatt(node, "dest")
        if not self.IsMirror:
            # src is project relative;
            # dest is relative to the top of the tree.
            # We only validate paths if we actually plan to process them.
            self._ValidateFilePaths("linkfile", src, dest)
            project.AddLinkFile(src, dest, self.topdir)

    def _ParseAnnotation(self, element, node):
        name = self._reqatt(node, "name")
        value = self._reqatt(node, "value")
        try:
            keep = self._reqatt(node, "keep").lower()
        except ManifestParseError:
            keep = "true"
        if keep != "true" and keep != "false":
            raise ManifestParseError(
                'optional "keep" attribute must be ' '"true" or "false"'
            )
        element.AddAnnotation(name, value, keep)

    def _get_remote(self, node):
        name = node.getAttribute("remote")
        if not name:
            return None

        v = self._remotes.get(name)
        if not v:
            raise ManifestParseError(
                f"remote {name} not defined in {self.manifestFile}"
            )
        return v

    def _reqatt(self, node, attname):
        """
        reads a required attribute from the node.
        """
        v = node.getAttribute(attname)
        if not v:
            raise ManifestParseError(
                "no %s in <%s> within %s"
                % (attname, node.nodeName, self.manifestFile)
            )
        return v

    def projectsDiff(self, manifest):
        """return the projects differences between two manifests.

        The diff will be from self to given manifest.

        """
        fromProjects = self.paths
        toProjects = manifest.paths

        fromKeys = sorted(fromProjects.keys())
        toKeys = set(toProjects.keys())

        diff = {
            "added": [],
            "removed": [],
            "missing": [],
            "changed": [],
            "unreachable": [],
        }

        for proj in fromKeys:
            fromProj = fromProjects[proj]
            if proj not in toKeys:
                diff["removed"].append(fromProj)
            elif not fromProj.Exists:
                diff["missing"].append(toProjects[proj])
                toKeys.remove(proj)
            else:
                toProj = toProjects[proj]
                try:
                    fromRevId = fromProj.GetCommitRevisionId()
                    toRevId = toProj.GetCommitRevisionId()
                except ManifestInvalidRevisionError:
                    diff["unreachable"].append((fromProj, toProj))
                else:
                    if fromRevId != toRevId:
                        diff["changed"].append((fromProj, toProj))
                toKeys.remove(proj)

        diff["added"].extend(toProjects[proj] for proj in sorted(toKeys))

        return diff


class RepoClient(XmlManifest):
    """Manages a repo client checkout."""

    def __init__(
        self, repodir, manifest_file=None, submanifest_path="", **kwargs
    ):
        """Initialize.

        Args:
            repodir: Path to the .repo/ dir for holding all internal checkout
                state. It must be in the top directory of the repo client
                checkout.
            manifest_file: Full path to the manifest file to parse.  This will
                usually be |repodir|/|MANIFEST_FILE_NAME|.
            submanifest_path: The submanifest root relative to the repo root.
            **kwargs: Additional keyword arguments, passed to XmlManifest.
        """
        submanifest_path = submanifest_path or ""
        if submanifest_path:
            self._CheckLocalPath(submanifest_path)
            prefix = os.path.join(repodir, SUBMANIFEST_DIR, submanifest_path)
        else:
            prefix = repodir

        if os.path.exists(os.path.join(prefix, LOCAL_MANIFEST_NAME)):
            print(
                "error: %s is not supported; put local manifests in `%s` "
                "instead"
                % (
                    LOCAL_MANIFEST_NAME,
                    os.path.join(prefix, LOCAL_MANIFESTS_DIR_NAME),
                ),
                file=sys.stderr,
            )
            sys.exit(1)

        if manifest_file is None:
            manifest_file = os.path.join(prefix, MANIFEST_FILE_NAME)
        local_manifests = os.path.abspath(
            os.path.join(prefix, LOCAL_MANIFESTS_DIR_NAME)
        )
        super().__init__(
            repodir,
            manifest_file,
            local_manifests,
            submanifest_path=submanifest_path,
            **kwargs,
        )

        # TODO: Completely separate manifest logic out of the client.
        self.manifest = self
