# 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 xml.dom.minidom
import urllib.parse

import gitc_utils
from git_config import GitConfig, IsId
from git_refs import R_HEADS, HEAD
from git_superproject import Superproject
import platform_utils
from project import (Annotation, RemoteSpec, Project, RepoProject,
                     ManifestProject)
from error import (ManifestParseError, ManifestInvalidPathError,
                   ManifestInvalidRevisionError)
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('manifest: invalid %s="%s" integer' %
                             (attr, value))


class _Default(object):
  """Project defaults within the manifest."""

  revisionExpr = None
  destBranchExpr = None
  upstreamExpr = None
  remote = None
  sync_j = 1
  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(object):
  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 ''
    url = self.fetchUrl.rstrip('/')
    manifestUrl = self.manifestUrl.rstrip('/')
    # urljoin will gets confused over quite a few things.  The ones we care
    # about here are:
    # * no scheme in the base url, like <hostname:port>
    # We handle no scheme by replacing it with an obscure protocol, gopher
    # and then replacing it with the original when we are done.

    if manifestUrl.find(':') != manifestUrl.find('/') - 1:
      url = urllib.parse.urljoin('gopher://' + manifestUrl, url)
      url = re.sub(r'^gopher://', '', url)
    else:
      url = urllib.parse.urljoin(manifestUrl, url)
    return 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)
    rc = self.repo_client = RepoClient(
        parent.repodir, linkFile, parent_groups=','.join(groups) or '',
        submanifest_path=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(mp.remote.name).url
    manifestName = self.manifestName or 'default.xml'
    revision = self.revision or self.name
    path = self.path or revision.split('/')[-1]
    groups = self.groups or []
    default_groups = self.default_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(object):
  """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 outertree.
      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.join(os.path.dirname(self.repodir), 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 outer_client and self.isGitcClient:
      raise ManifestParseError('Multi-manifest is incompatible with `gitc-init`')

    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):
    """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 > 1:
      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

      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 l in p.linkfiles:
        le = doc.createElement('linkfile')
        le.setAttribute('src', l.src)
        le.setAttribute('dest', l.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 = set(subp.name for subp in p.subprojects)
        output_projects(p, e, list(sorted(subprojects)))

    projects = set(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 = dict((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('Unhandled element "%s"' % (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"""
    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."""
    self._Load()
    outer = self._outer_client
    yield outer
    for tree in outer.all_children:
      yield tree

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

  @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 `paths`."""
    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.

    Return:
      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):
    self._Load()
    return self._remotes

  @property
  def default(self):
    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 PartialCloneExclude(self):
    exclude = self.manifest.manifestProject.partial_clone_exclude or ''
    return set(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:{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}:{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 submanifest  manifests
      # as well.  We need to do this after self._loaded is set to avoid looping.
      for name in self._submanifests:
        tree = self._submanifests[name]
        spec = 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):
    """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.

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

    if not root or not root.childNodes:
      raise ManifestParseError("no root node in %s" % (path,))

    for manifest in root.childNodes:
      if manifest.nodeName == 'manifest':
        break
    else:
      raise ManifestParseError("no <manifest> in %s" % (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(
                '<include> invalid "name": %s: %s' % (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))
        # 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(
              "failed parsing included manifest %s: %s" % (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)
        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
    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)

        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:
            p.SetRevision(revision)

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

          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 = self._reqatt(node, 'name')

        if name in self._projects:
          for p in self._projects[name]:
            del self._paths[p.relpath]
          del self._projects[name]

          # If the manifest removes the hooks project, treat it as if it deleted
          # the repo-hooks element too.
          if repo_hooks_project == name:
            repo_hooks_project = None
        elif not XmlBool(node, 'optional', False):
          raise ManifestParseError('remove-project element specifies non-existent '
                                   'project: %s' % name)

    # 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(m.remote.name).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', 1)
    if 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(
              '<submanifest> invalid "name": %s: %s' % (name, msg))
    else:
      msg = self._CheckLocalPath(path)
      if msg:
        raise ManifestInvalidPathError(
            '<submanifest> invalid "path": %s: %s' % (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(
          '<project> invalid "name": %s: %s' % (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("no remote for project %s within %s" %
                               (name, 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(
            '<project> invalid "path": %s: %s' % (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.
    """
    # 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 = bool(self._outer_client._submanifests)
    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.
    """
    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 = {
        u'\u200C',  # ZERO WIDTH NON-JOINER
        u'\u200D',  # ZERO WIDTH JOINER
        u'\u200E',  # LEFT-TO-RIGHT MARK
        u'\u200F',  # RIGHT-TO-LEFT MARK
        u'\u202A',  # LEFT-TO-RIGHT EMBEDDING
        u'\u202B',  # RIGHT-TO-LEFT EMBEDDING
        u'\u202C',  # POP DIRECTIONAL FORMATTING
        u'\u202D',  # LEFT-TO-RIGHT OVERRIDE
        u'\u202E',  # RIGHT-TO-LEFT OVERRIDE
        u'\u206A',  # INHIBIT SYMMETRIC SWAPPING
        u'\u206B',  # ACTIVATE SYMMETRIC SWAPPING
        u'\u206C',  # INHIBIT ARABIC FORM SHAPING
        u'\u206D',  # ACTIVATE ARABIC FORM SHAPING
        u'\u206E',  # NATIONAL DIGIT SHAPES
        u'\u206F',  # NOMINAL DIGIT SHAPES
        u'\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 'bad component: %s' % (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(
          '<%s> invalid "dest": %s: %s' % (element, 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(
          '<%s> invalid "src": %s: %s' % (element, 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("remote %s not defined in %s" %
                               (name, 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 = sorted(toProjects.keys())

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

    for proj in fromKeys:
      if proj not in toKeys:
        diff['removed'].append(fromProjects[proj])
      else:
        fromProj = fromProjects[proj]
        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)

    for proj in toKeys:
      diff['added'].append(toProjects[proj])

    return diff


class GitcManifest(XmlManifest):
  """Parser for GitC (git-in-the-cloud) manifests."""

  def _ParseProject(self, node, parent=None):
    """Override _ParseProject and add support for GITC specific attributes."""
    return super()._ParseProject(
        node, parent=parent, old_revision=node.getAttribute('old-revision'))

  def _output_manifest_project_extras(self, p, e):
    """Output GITC Specific Project attributes"""
    if p.old_revision:
      e.setAttribute('old-revision', str(p.old_revision))


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

  def __init__(self, repodir, manifest_file=None, submanifest_path='', **kwargs):
    self.isGitcClient = False
    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


class GitcClient(RepoClient, GitcManifest):
  """Manages a GitC client checkout."""

  def __init__(self, repodir, gitc_client_name):
    """Initialize the GitcManifest object."""
    self.gitc_client_name = gitc_client_name
    self.gitc_client_dir = os.path.join(gitc_utils.get_gitc_manifest_dir(),
                                        gitc_client_name)

    super().__init__(repodir, os.path.join(self.gitc_client_dir, '.manifest'))
    self.isGitcClient = True
