# 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 errno
import filecmp
import glob
import os
import platform
import random
import re
import shutil
import stat
import subprocess
import sys
import tarfile
import tempfile
import time
from typing import List, NamedTuple
import urllib.parse

from color import Coloring
from error import DownloadError
from error import GitError
from error import ManifestInvalidPathError
from error import ManifestInvalidRevisionError
from error import ManifestParseError
from error import NoManifestException
from error import RepoError
from error import UploadError
import fetch
from git_command import git_require
from git_command import GitCommand
from git_config import GetSchemeFromUrl
from git_config import GetUrlCookieFile
from git_config import GitConfig
from git_config import IsId
from git_refs import GitRefs
from git_refs import HEAD
from git_refs import R_HEADS
from git_refs import R_M
from git_refs import R_PUB
from git_refs import R_TAGS
from git_refs import R_WORKTREE_M
import git_superproject
from git_trace2_event_log import EventLog
import platform_utils
import progress
from repo_logging import RepoLogger
from repo_trace import Trace


logger = RepoLogger(__file__)


class SyncNetworkHalfResult(NamedTuple):
    """Sync_NetworkHalf return value."""

    # Did we query the remote? False when optimized_fetch is True and we have
    # the commit already present.
    remote_fetched: bool
    # Error from SyncNetworkHalf
    error: Exception = None

    @property
    def success(self) -> bool:
        return not self.error


class SyncNetworkHalfError(RepoError):
    """Failure trying to sync."""


class DeleteWorktreeError(RepoError):
    """Failure to delete worktree."""

    def __init__(
        self, *args, aggregate_errors: List[Exception] = None, **kwargs
    ) -> None:
        super().__init__(*args, **kwargs)
        self.aggregate_errors = aggregate_errors or []


class DeleteDirtyWorktreeError(DeleteWorktreeError):
    """Failure to delete worktree due to uncommitted changes."""


# Maximum sleep time allowed during retries.
MAXIMUM_RETRY_SLEEP_SEC = 3600.0
# +-10% random jitter is added to each Fetches retry sleep duration.
RETRY_JITTER_PERCENT = 0.1

# Whether to use alternates.  Switching back and forth is *NOT* supported.
# TODO(vapier): Remove knob once behavior is verified.
_ALTERNATES = os.environ.get("REPO_USE_ALTERNATES") == "1"


def _lwrite(path, content):
    lock = "%s.lock" % path

    # Maintain Unix line endings on all OS's to match git behavior.
    with open(lock, "w", newline="\n") as fd:
        fd.write(content)

    try:
        platform_utils.rename(lock, path)
    except OSError:
        platform_utils.remove(lock)
        raise


def not_rev(r):
    return "^" + r


def sq(r):
    return "'" + r.replace("'", "'''") + "'"


_project_hook_list = None


def _ProjectHooks():
    """List the hooks present in the 'hooks' directory.

    These hooks are project hooks and are copied to the '.git/hooks' directory
    of all subprojects.

    This function caches the list of hooks (based on the contents of the
    'repo/hooks' directory) on the first call.

    Returns:
        A list of absolute paths to all of the files in the hooks directory.
    """
    global _project_hook_list
    if _project_hook_list is None:
        d = platform_utils.realpath(os.path.abspath(os.path.dirname(__file__)))
        d = os.path.join(d, "hooks")
        _project_hook_list = [
            os.path.join(d, x) for x in platform_utils.listdir(d)
        ]
    return _project_hook_list


class DownloadedChange(object):
    _commit_cache = None

    def __init__(self, project, base, change_id, ps_id, commit):
        self.project = project
        self.base = base
        self.change_id = change_id
        self.ps_id = ps_id
        self.commit = commit

    @property
    def commits(self):
        if self._commit_cache is None:
            self._commit_cache = self.project.bare_git.rev_list(
                "--abbrev=8",
                "--abbrev-commit",
                "--pretty=oneline",
                "--reverse",
                "--date-order",
                not_rev(self.base),
                self.commit,
                "--",
            )
        return self._commit_cache


class ReviewableBranch(object):
    _commit_cache = None
    _base_exists = None

    def __init__(self, project, branch, base):
        self.project = project
        self.branch = branch
        self.base = base

    @property
    def name(self):
        return self.branch.name

    @property
    def commits(self):
        if self._commit_cache is None:
            args = (
                "--abbrev=8",
                "--abbrev-commit",
                "--pretty=oneline",
                "--reverse",
                "--date-order",
                not_rev(self.base),
                R_HEADS + self.name,
                "--",
            )
            try:
                self._commit_cache = self.project.bare_git.rev_list(
                    *args, log_as_error=self.base_exists
                )
            except GitError:
                # We weren't able to probe the commits for this branch.  Was it
                # tracking a branch that no longer exists?  If so, return no
                # commits.  Otherwise, rethrow the error as we don't know what's
                # going on.
                if self.base_exists:
                    raise

                self._commit_cache = []

        return self._commit_cache

    @property
    def unabbrev_commits(self):
        r = dict()
        for commit in self.project.bare_git.rev_list(
            not_rev(self.base), R_HEADS + self.name, "--"
        ):
            r[commit[0:8]] = commit
        return r

    @property
    def date(self):
        return self.project.bare_git.log(
            "--pretty=format:%cd", "-n", "1", R_HEADS + self.name, "--"
        )

    @property
    def base_exists(self):
        """Whether the branch we're tracking exists.

        Normally it should, but sometimes branches we track can get deleted.
        """
        if self._base_exists is None:
            try:
                self.project.bare_git.rev_parse("--verify", not_rev(self.base))
                # If we're still here, the base branch exists.
                self._base_exists = True
            except GitError:
                # If we failed to verify, the base branch doesn't exist.
                self._base_exists = False

        return self._base_exists

    def UploadForReview(
        self,
        people,
        dryrun=False,
        auto_topic=False,
        hashtags=(),
        labels=(),
        private=False,
        notify=None,
        wip=False,
        ready=False,
        dest_branch=None,
        validate_certs=True,
        push_options=None,
    ):
        self.project.UploadForReview(
            branch=self.name,
            people=people,
            dryrun=dryrun,
            auto_topic=auto_topic,
            hashtags=hashtags,
            labels=labels,
            private=private,
            notify=notify,
            wip=wip,
            ready=ready,
            dest_branch=dest_branch,
            validate_certs=validate_certs,
            push_options=push_options,
        )

    def GetPublishedRefs(self):
        refs = {}
        output = self.project.bare_git.ls_remote(
            self.branch.remote.SshReviewUrl(self.project.UserEmail),
            "refs/changes/*",
        )
        for line in output.split("\n"):
            try:
                (sha, ref) = line.split()
                refs[sha] = ref
            except ValueError:
                pass

        return refs


class StatusColoring(Coloring):
    def __init__(self, config):
        super().__init__(config, "status")
        self.project = self.printer("header", attr="bold")
        self.branch = self.printer("header", attr="bold")
        self.nobranch = self.printer("nobranch", fg="red")
        self.important = self.printer("important", fg="red")

        self.added = self.printer("added", fg="green")
        self.changed = self.printer("changed", fg="red")
        self.untracked = self.printer("untracked", fg="red")


class DiffColoring(Coloring):
    def __init__(self, config):
        super().__init__(config, "diff")
        self.project = self.printer("header", attr="bold")
        self.fail = self.printer("fail", fg="red")


class Annotation(object):
    def __init__(self, name, value, keep):
        self.name = name
        self.value = value
        self.keep = keep

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

    def __lt__(self, other):
        # This exists just so that lists of Annotation objects can be sorted,
        # for use in comparisons.
        if not isinstance(other, Annotation):
            raise ValueError("comparison is not between two Annotation objects")
        if self.name == other.name:
            if self.value == other.value:
                return self.keep < other.keep
            return self.value < other.value
        return self.name < other.name


def _SafeExpandPath(base, subpath, skipfinal=False):
    """Make sure |subpath| is completely safe under |base|.

    We make sure no intermediate symlinks are traversed, and that the final path
    is not a special file (e.g. not a socket or fifo).

    NB: We rely on a number of paths already being filtered out while parsing
    the manifest.  See the validation logic in manifest_xml.py for more details.
    """
    # 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))
    components = resep.split(subpath)
    if skipfinal:
        # Whether the caller handles the final component itself.
        finalpart = components.pop()

    path = base
    for part in components:
        if part in {".", ".."}:
            raise ManifestInvalidPathError(
                '%s: "%s" not allowed in paths' % (subpath, part)
            )

        path = os.path.join(path, part)
        if platform_utils.islink(path):
            raise ManifestInvalidPathError(
                "%s: traversing symlinks not allow" % (path,)
            )

        if os.path.exists(path):
            if not os.path.isfile(path) and not platform_utils.isdir(path):
                raise ManifestInvalidPathError(
                    "%s: only regular files & directories allowed" % (path,)
                )

    if skipfinal:
        path = os.path.join(path, finalpart)

    return path


class _CopyFile(object):
    """Container for <copyfile> manifest element."""

    def __init__(self, git_worktree, src, topdir, dest):
        """Register a <copyfile> request.

        Args:
            git_worktree: Absolute path to the git project checkout.
            src: Relative path under |git_worktree| of file to read.
            topdir: Absolute path to the top of the repo client checkout.
            dest: Relative path under |topdir| of file to write.
        """
        self.git_worktree = git_worktree
        self.topdir = topdir
        self.src = src
        self.dest = dest

    def _Copy(self):
        src = _SafeExpandPath(self.git_worktree, self.src)
        dest = _SafeExpandPath(self.topdir, self.dest)

        if platform_utils.isdir(src):
            raise ManifestInvalidPathError(
                "%s: copying from directory not supported" % (self.src,)
            )
        if platform_utils.isdir(dest):
            raise ManifestInvalidPathError(
                "%s: copying to directory not allowed" % (self.dest,)
            )

        # Copy file if it does not exist or is out of date.
        if not os.path.exists(dest) or not filecmp.cmp(src, dest):
            try:
                # Remove existing file first, since it might be read-only.
                if os.path.exists(dest):
                    platform_utils.remove(dest)
                else:
                    dest_dir = os.path.dirname(dest)
                    if not platform_utils.isdir(dest_dir):
                        os.makedirs(dest_dir)
                shutil.copy(src, dest)
                # Make the file read-only.
                mode = os.stat(dest)[stat.ST_MODE]
                mode = mode & ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH)
                os.chmod(dest, mode)
            except IOError:
                logger.error("error: Cannot copy file %s to %s", src, dest)


class _LinkFile(object):
    """Container for <linkfile> manifest element."""

    def __init__(self, git_worktree, src, topdir, dest):
        """Register a <linkfile> request.

        Args:
            git_worktree: Absolute path to the git project checkout.
            src: Target of symlink relative to path under |git_worktree|.
            topdir: Absolute path to the top of the repo client checkout.
            dest: Relative path under |topdir| of symlink to create.
        """
        self.git_worktree = git_worktree
        self.topdir = topdir
        self.src = src
        self.dest = dest

    def __linkIt(self, relSrc, absDest):
        # Link file if it does not exist or is out of date.
        if not platform_utils.islink(absDest) or (
            platform_utils.readlink(absDest) != relSrc
        ):
            try:
                # Remove existing file first, since it might be read-only.
                if os.path.lexists(absDest):
                    platform_utils.remove(absDest)
                else:
                    dest_dir = os.path.dirname(absDest)
                    if not platform_utils.isdir(dest_dir):
                        os.makedirs(dest_dir)
                platform_utils.symlink(relSrc, absDest)
            except IOError:
                logger.error(
                    "error: Cannot link file %s to %s", relSrc, absDest
                )

    def _Link(self):
        """Link the self.src & self.dest paths.

        Handles wild cards on the src linking all of the files in the source in
        to the destination directory.
        """
        # Some people use src="." to create stable links to projects.  Let's
        # allow that but reject all other uses of "." to keep things simple.
        if self.src == ".":
            src = self.git_worktree
        else:
            src = _SafeExpandPath(self.git_worktree, self.src)

        if not glob.has_magic(src):
            # Entity does not contain a wild card so just a simple one to one
            # link operation.
            dest = _SafeExpandPath(self.topdir, self.dest, skipfinal=True)
            # dest & src are absolute paths at this point.  Make sure the target
            # of the symlink is relative in the context of the repo client
            # checkout.
            relpath = os.path.relpath(src, os.path.dirname(dest))
            self.__linkIt(relpath, dest)
        else:
            dest = _SafeExpandPath(self.topdir, self.dest)
            # Entity contains a wild card.
            if os.path.exists(dest) and not platform_utils.isdir(dest):
                logger.error(
                    "Link error: src with wildcard, %s must be a directory",
                    dest,
                )
            else:
                for absSrcFile in glob.glob(src):
                    # Create a releative path from source dir to destination
                    # dir.
                    absSrcDir = os.path.dirname(absSrcFile)
                    relSrcDir = os.path.relpath(absSrcDir, dest)

                    # Get the source file name.
                    srcFile = os.path.basename(absSrcFile)

                    # Now form the final full paths to srcFile. They will be
                    # absolute for the desintaiton and relative for the source.
                    absDest = os.path.join(dest, srcFile)
                    relSrc = os.path.join(relSrcDir, srcFile)
                    self.__linkIt(relSrc, absDest)


class RemoteSpec(object):
    def __init__(
        self,
        name,
        url=None,
        pushUrl=None,
        review=None,
        revision=None,
        orig_name=None,
        fetchUrl=None,
    ):
        self.name = name
        self.url = url
        self.pushUrl = pushUrl
        self.review = review
        self.revision = revision
        self.orig_name = orig_name
        self.fetchUrl = fetchUrl


class Project(object):
    # These objects can be shared between several working trees.
    @property
    def shareable_dirs(self):
        """Return the shareable directories"""
        if self.UseAlternates:
            return ["hooks", "rr-cache"]
        else:
            return ["hooks", "objects", "rr-cache"]

    def __init__(
        self,
        manifest,
        name,
        remote,
        gitdir,
        objdir,
        worktree,
        relpath,
        revisionExpr,
        revisionId,
        rebase=True,
        groups=None,
        sync_c=False,
        sync_s=False,
        sync_tags=True,
        clone_depth=None,
        upstream=None,
        parent=None,
        use_git_worktrees=False,
        is_derived=False,
        dest_branch=None,
        optimized_fetch=False,
        retry_fetches=0,
        old_revision=None,
    ):
        """Init a Project object.

        Args:
            manifest: The XmlManifest object.
            name: The `name` attribute of manifest.xml's project element.
            remote: RemoteSpec object specifying its remote's properties.
            gitdir: Absolute path of git directory.
            objdir: Absolute path of directory to store git objects.
            worktree: Absolute path of git working tree.
            relpath: Relative path of git working tree to repo's top directory.
            revisionExpr: The `revision` attribute of manifest.xml's project
                element.
            revisionId: git commit id for checking out.
            rebase: The `rebase` attribute of manifest.xml's project element.
            groups: The `groups` attribute of manifest.xml's project element.
            sync_c: The `sync-c` attribute of manifest.xml's project element.
            sync_s: The `sync-s` attribute of manifest.xml's project element.
            sync_tags: The `sync-tags` attribute of manifest.xml's project
                element.
            upstream: The `upstream` attribute of manifest.xml's project
                element.
            parent: The parent Project object.
            use_git_worktrees: Whether to use `git worktree` for this project.
            is_derived: False if the project was explicitly defined in the
                manifest; True if the project is a discovered submodule.
            dest_branch: The branch to which to push changes for review by
                default.
            optimized_fetch: If True, when a project is set to a sha1 revision,
                only fetch from the remote if the sha1 is not present locally.
            retry_fetches: Retry remote fetches n times upon receiving transient
                error with exponential backoff and jitter.
            old_revision: saved git commit id for open GITC projects.
        """
        self.client = self.manifest = manifest
        self.name = name
        self.remote = remote
        self.UpdatePaths(relpath, worktree, gitdir, objdir)
        self.SetRevision(revisionExpr, revisionId=revisionId)

        self.rebase = rebase
        self.groups = groups
        self.sync_c = sync_c
        self.sync_s = sync_s
        self.sync_tags = sync_tags
        self.clone_depth = clone_depth
        self.upstream = upstream
        self.parent = parent
        # NB: Do not use this setting in __init__ to change behavior so that the
        # manifest.git checkout can inspect & change it after instantiating.
        # See the XmlManifest init code for more info.
        self.use_git_worktrees = use_git_worktrees
        self.is_derived = is_derived
        self.optimized_fetch = optimized_fetch
        self.retry_fetches = max(0, retry_fetches)
        self.subprojects = []

        self.snapshots = {}
        self.copyfiles = []
        self.linkfiles = []
        self.annotations = []
        self.dest_branch = dest_branch
        self.old_revision = old_revision

        # This will be filled in if a project is later identified to be the
        # project containing repo hooks.
        self.enabled_repo_hooks = []

    def RelPath(self, local=True):
        """Return the path for the project relative to a manifest.

        Args:
            local: a boolean, if True, the path is relative to the local
                (sub)manifest.  If false, the path is relative to the outermost
                manifest.
        """
        if local:
            return self.relpath
        return os.path.join(self.manifest.path_prefix, self.relpath)

    def SetRevision(self, revisionExpr, revisionId=None):
        """Set revisionId based on revision expression and id"""
        self.revisionExpr = revisionExpr
        if revisionId is None and revisionExpr and IsId(revisionExpr):
            self.revisionId = self.revisionExpr
        else:
            self.revisionId = revisionId

    def UpdatePaths(self, relpath, worktree, gitdir, objdir):
        """Update paths used by this project"""
        self.gitdir = gitdir.replace("\\", "/")
        self.objdir = objdir.replace("\\", "/")
        if worktree:
            self.worktree = os.path.normpath(worktree).replace("\\", "/")
        else:
            self.worktree = None
        self.relpath = relpath

        self.config = GitConfig.ForRepository(
            gitdir=self.gitdir, defaults=self.manifest.globalConfig
        )

        if self.worktree:
            self.work_git = self._GitGetByExec(
                self, bare=False, gitdir=self.gitdir
            )
        else:
            self.work_git = None
        self.bare_git = self._GitGetByExec(self, bare=True, gitdir=self.gitdir)
        self.bare_ref = GitRefs(self.gitdir)
        self.bare_objdir = self._GitGetByExec(
            self, bare=True, gitdir=self.objdir
        )

    @property
    def UseAlternates(self):
        """Whether git alternates are in use.

        This will be removed once migration to alternates is complete.
        """
        return _ALTERNATES or self.manifest.is_multimanifest

    @property
    def Derived(self):
        return self.is_derived

    @property
    def Exists(self):
        return platform_utils.isdir(self.gitdir) and platform_utils.isdir(
            self.objdir
        )

    @property
    def CurrentBranch(self):
        """Obtain the name of the currently checked out branch.

        The branch name omits the 'refs/heads/' prefix.
        None is returned if the project is on a detached HEAD, or if the
        work_git is otheriwse inaccessible (e.g. an incomplete sync).
        """
        try:
            b = self.work_git.GetHead()
        except NoManifestException:
            # If the local checkout is in a bad state, don't barf.  Let the
            # callers process this like the head is unreadable.
            return None
        if b.startswith(R_HEADS):
            return b[len(R_HEADS) :]
        return None

    def IsRebaseInProgress(self):
        return (
            os.path.exists(self.work_git.GetDotgitPath("rebase-apply"))
            or os.path.exists(self.work_git.GetDotgitPath("rebase-merge"))
            or os.path.exists(os.path.join(self.worktree, ".dotest"))
        )

    def IsDirty(self, consider_untracked=True):
        """Is the working directory modified in some way?"""
        self.work_git.update_index(
            "-q", "--unmerged", "--ignore-missing", "--refresh"
        )
        if self.work_git.DiffZ("diff-index", "-M", "--cached", HEAD):
            return True
        if self.work_git.DiffZ("diff-files"):
            return True
        if consider_untracked and self.UntrackedFiles():
            return True
        return False

    _userident_name = None
    _userident_email = None

    @property
    def UserName(self):
        """Obtain the user's personal name."""
        if self._userident_name is None:
            self._LoadUserIdentity()
        return self._userident_name

    @property
    def UserEmail(self):
        """Obtain the user's email address.  This is very likely
        to be their Gerrit login.
        """
        if self._userident_email is None:
            self._LoadUserIdentity()
        return self._userident_email

    def _LoadUserIdentity(self):
        u = self.bare_git.var("GIT_COMMITTER_IDENT")
        m = re.compile("^(.*) <([^>]*)> ").match(u)
        if m:
            self._userident_name = m.group(1)
            self._userident_email = m.group(2)
        else:
            self._userident_name = ""
            self._userident_email = ""

    def GetRemote(self, name=None):
        """Get the configuration for a single remote.

        Defaults to the current project's remote.
        """
        if name is None:
            name = self.remote.name
        return self.config.GetRemote(name)

    def GetBranch(self, name):
        """Get the configuration for a single branch."""
        return self.config.GetBranch(name)

    def GetBranches(self):
        """Get all existing local branches."""
        current = self.CurrentBranch
        all_refs = self._allrefs
        heads = {}

        for name, ref_id in all_refs.items():
            if name.startswith(R_HEADS):
                name = name[len(R_HEADS) :]
                b = self.GetBranch(name)
                b.current = name == current
                b.published = None
                b.revision = ref_id
                heads[name] = b

        for name, ref_id in all_refs.items():
            if name.startswith(R_PUB):
                name = name[len(R_PUB) :]
                b = heads.get(name)
                if b:
                    b.published = ref_id

        return heads

    def MatchesGroups(self, manifest_groups):
        """Returns true if the manifest groups specified at init should cause
        this project to be synced.
        Prefixing a manifest group with "-" inverts the meaning of a group.
        All projects are implicitly labelled with "all".

        labels are resolved in order.  In the example case of
        project_groups: "all,group1,group2"
        manifest_groups: "-group1,group2"
        the project will be matched.

        The special manifest group "default" will match any project that
        does not have the special project group "notdefault"
        """
        default_groups = self.manifest.default_groups or ["default"]
        expanded_manifest_groups = manifest_groups or default_groups
        expanded_project_groups = ["all"] + (self.groups or [])
        if "notdefault" not in expanded_project_groups:
            expanded_project_groups += ["default"]

        matched = False
        for group in expanded_manifest_groups:
            if group.startswith("-") and group[1:] in expanded_project_groups:
                matched = False
            elif group in expanded_project_groups:
                matched = True

        return matched

    def UncommitedFiles(self, get_all=True):
        """Returns a list of strings, uncommitted files in the git tree.

        Args:
            get_all: a boolean, if True - get information about all different
                uncommitted files. If False - return as soon as any kind of
                uncommitted files is detected.
        """
        details = []
        self.work_git.update_index(
            "-q", "--unmerged", "--ignore-missing", "--refresh"
        )
        if self.IsRebaseInProgress():
            details.append("rebase in progress")
            if not get_all:
                return details

        changes = self.work_git.DiffZ("diff-index", "--cached", HEAD).keys()
        if changes:
            details.extend(changes)
            if not get_all:
                return details

        changes = self.work_git.DiffZ("diff-files").keys()
        if changes:
            details.extend(changes)
            if not get_all:
                return details

        changes = self.UntrackedFiles()
        if changes:
            details.extend(changes)

        return details

    def UntrackedFiles(self):
        """Returns a list of strings, untracked files in the git tree."""
        return self.work_git.LsOthers()

    def HasChanges(self):
        """Returns true if there are uncommitted changes."""
        return bool(self.UncommitedFiles(get_all=False))

    def PrintWorkTreeStatus(self, output_redir=None, quiet=False, local=False):
        """Prints the status of the repository to stdout.

        Args:
            output_redir: If specified, redirect the output to this object.
            quiet:  If True then only print the project name.  Do not print
                the modified files, branch name, etc.
            local: a boolean, if True, the path is relative to the local
                (sub)manifest.  If false, the path is relative to the outermost
                manifest.
        """
        if not platform_utils.isdir(self.worktree):
            if output_redir is None:
                output_redir = sys.stdout
            print(file=output_redir)
            print("project %s/" % self.RelPath(local), file=output_redir)
            print('  missing (run "repo sync")', file=output_redir)
            return

        self.work_git.update_index(
            "-q", "--unmerged", "--ignore-missing", "--refresh"
        )
        rb = self.IsRebaseInProgress()
        di = self.work_git.DiffZ("diff-index", "-M", "--cached", HEAD)
        df = self.work_git.DiffZ("diff-files")
        do = self.work_git.LsOthers()
        if not rb and not di and not df and not do and not self.CurrentBranch:
            return "CLEAN"

        out = StatusColoring(self.config)
        if output_redir is not None:
            out.redirect(output_redir)
        out.project("project %-40s", self.RelPath(local) + "/ ")

        if quiet:
            out.nl()
            return "DIRTY"

        branch = self.CurrentBranch
        if branch is None:
            out.nobranch("(*** NO BRANCH ***)")
        else:
            out.branch("branch %s", branch)
        out.nl()

        if rb:
            out.important("prior sync failed; rebase still in progress")
            out.nl()

        paths = list()
        paths.extend(di.keys())
        paths.extend(df.keys())
        paths.extend(do)

        for p in sorted(set(paths)):
            try:
                i = di[p]
            except KeyError:
                i = None

            try:
                f = df[p]
            except KeyError:
                f = None

            if i:
                i_status = i.status.upper()
            else:
                i_status = "-"

            if f:
                f_status = f.status.lower()
            else:
                f_status = "-"

            if i and i.src_path:
                line = " %s%s\t%s => %s (%s%%)" % (
                    i_status,
                    f_status,
                    i.src_path,
                    p,
                    i.level,
                )
            else:
                line = " %s%s\t%s" % (i_status, f_status, p)

            if i and not f:
                out.added("%s", line)
            elif (i and f) or (not i and f):
                out.changed("%s", line)
            elif not i and not f:
                out.untracked("%s", line)
            else:
                out.write("%s", line)
            out.nl()

        return "DIRTY"

    def PrintWorkTreeDiff(
        self, absolute_paths=False, output_redir=None, local=False
    ):
        """Prints the status of the repository to stdout."""
        out = DiffColoring(self.config)
        if output_redir:
            out.redirect(output_redir)
        cmd = ["diff"]
        if out.is_on:
            cmd.append("--color")
        cmd.append(HEAD)
        if absolute_paths:
            cmd.append("--src-prefix=a/%s/" % self.RelPath(local))
            cmd.append("--dst-prefix=b/%s/" % self.RelPath(local))
        cmd.append("--")
        try:
            p = GitCommand(self, cmd, capture_stdout=True, capture_stderr=True)
            p.Wait()
        except GitError as e:
            out.nl()
            out.project("project %s/" % self.RelPath(local))
            out.nl()
            out.fail("%s", str(e))
            out.nl()
            return False
        if p.stdout:
            out.nl()
            out.project("project %s/" % self.RelPath(local))
            out.nl()
            out.write("%s", p.stdout)
        return p.Wait() == 0

    def WasPublished(self, branch, all_refs=None):
        """Was the branch published (uploaded) for code review?
        If so, returns the SHA-1 hash of the last published
        state for the branch.
        """
        key = R_PUB + branch
        if all_refs is None:
            try:
                return self.bare_git.rev_parse(key)
            except GitError:
                return None
        else:
            try:
                return all_refs[key]
            except KeyError:
                return None

    def CleanPublishedCache(self, all_refs=None):
        """Prunes any stale published refs."""
        if all_refs is None:
            all_refs = self._allrefs
        heads = set()
        canrm = {}
        for name, ref_id in all_refs.items():
            if name.startswith(R_HEADS):
                heads.add(name)
            elif name.startswith(R_PUB):
                canrm[name] = ref_id

        for name, ref_id in canrm.items():
            n = name[len(R_PUB) :]
            if R_HEADS + n not in heads:
                self.bare_git.DeleteRef(name, ref_id)

    def GetUploadableBranches(self, selected_branch=None):
        """List any branches which can be uploaded for review."""
        heads = {}
        pubed = {}

        for name, ref_id in self._allrefs.items():
            if name.startswith(R_HEADS):
                heads[name[len(R_HEADS) :]] = ref_id
            elif name.startswith(R_PUB):
                pubed[name[len(R_PUB) :]] = ref_id

        ready = []
        for branch, ref_id in heads.items():
            if branch in pubed and pubed[branch] == ref_id:
                continue
            if selected_branch and branch != selected_branch:
                continue

            rb = self.GetUploadableBranch(branch)
            if rb:
                ready.append(rb)
        return ready

    def GetUploadableBranch(self, branch_name):
        """Get a single uploadable branch, or None."""
        branch = self.GetBranch(branch_name)
        base = branch.LocalMerge
        if branch.LocalMerge:
            rb = ReviewableBranch(self, branch, base)
            if rb.commits:
                return rb
        return None

    def UploadForReview(
        self,
        branch=None,
        people=([], []),
        dryrun=False,
        auto_topic=False,
        hashtags=(),
        labels=(),
        private=False,
        notify=None,
        wip=False,
        ready=False,
        dest_branch=None,
        validate_certs=True,
        push_options=None,
    ):
        """Uploads the named branch for code review."""
        if branch is None:
            branch = self.CurrentBranch
        if branch is None:
            raise GitError("not currently on a branch", project=self.name)

        branch = self.GetBranch(branch)
        if not branch.LocalMerge:
            raise GitError(
                "branch %s does not track a remote" % branch.name,
                project=self.name,
            )
        if not branch.remote.review:
            raise GitError(
                "remote %s has no review url" % branch.remote.name,
                project=self.name,
            )

        # Basic validity check on label syntax.
        for label in labels:
            if not re.match(r"^.+[+-][0-9]+$", label):
                raise UploadError(
                    f'invalid label syntax "{label}": labels use forms like '
                    "CodeReview+1 or Verified-1",
                    project=self.name,
                )

        if dest_branch is None:
            dest_branch = self.dest_branch
        if dest_branch is None:
            dest_branch = branch.merge
        if not dest_branch.startswith(R_HEADS):
            dest_branch = R_HEADS + dest_branch

        if not branch.remote.projectname:
            branch.remote.projectname = self.name
            branch.remote.Save()

        url = branch.remote.ReviewUrl(self.UserEmail, validate_certs)
        if url is None:
            raise UploadError("review not configured", project=self.name)
        cmd = ["push"]
        if dryrun:
            cmd.append("-n")

        if url.startswith("ssh://"):
            cmd.append("--receive-pack=gerrit receive-pack")

        # This stops git from pushing all reachable annotated tags when
        # push.followTags is configured. Gerrit does not accept any tags
        # pushed to a CL.
        if git_require((1, 8, 3)):
            cmd.append("--no-follow-tags")

        for push_option in push_options or []:
            cmd.append("-o")
            cmd.append(push_option)

        cmd.append(url)

        if dest_branch.startswith(R_HEADS):
            dest_branch = dest_branch[len(R_HEADS) :]

        ref_spec = "%s:refs/for/%s" % (R_HEADS + branch.name, dest_branch)
        opts = []
        if auto_topic:
            opts += ["topic=" + branch.name]
        opts += ["t=%s" % p for p in hashtags]
        # NB: No need to encode labels as they've been validated above.
        opts += ["l=%s" % p for p in labels]

        opts += ["r=%s" % p for p in people[0]]
        opts += ["cc=%s" % p for p in people[1]]
        if notify:
            opts += ["notify=" + notify]
        if private:
            opts += ["private"]
        if wip:
            opts += ["wip"]
        if ready:
            opts += ["ready"]
        if opts:
            ref_spec = ref_spec + "%" + ",".join(opts)
        cmd.append(ref_spec)

        GitCommand(self, cmd, bare=True, verify_command=True).Wait()

        if not dryrun:
            msg = "posted to %s for %s" % (branch.remote.review, dest_branch)
            self.bare_git.UpdateRef(
                R_PUB + branch.name, R_HEADS + branch.name, message=msg
            )

    def _ExtractArchive(self, tarpath, path=None):
        """Extract the given tar on its current location

        Args:
            tarpath: The path to the actual tar file

        """
        try:
            with tarfile.open(tarpath, "r") as tar:
                tar.extractall(path=path)
                return True
        except (IOError, tarfile.TarError) as e:
            logger.error("error: Cannot extract archive %s: %s", tarpath, e)
        return False

    def Sync_NetworkHalf(
        self,
        quiet=False,
        verbose=False,
        output_redir=None,
        is_new=None,
        current_branch_only=None,
        force_sync=False,
        clone_bundle=True,
        tags=None,
        archive=False,
        optimized_fetch=False,
        retry_fetches=0,
        prune=False,
        submodules=False,
        ssh_proxy=None,
        clone_filter=None,
        partial_clone_exclude=set(),
        clone_filter_for_depth=None,
    ):
        """Perform only the network IO portion of the sync process.
        Local working directory/branch state is not affected.
        """
        if archive and not isinstance(self, MetaProject):
            if self.remote.url.startswith(("http://", "https://")):
                msg_template = (
                    "%s: Cannot fetch archives from http/https remotes."
                )
                msg_args = self.name
                msg = msg_template % msg_args
                logger.error(msg_template, msg_args)
                return SyncNetworkHalfResult(
                    False, SyncNetworkHalfError(msg, project=self.name)
                )

            name = self.relpath.replace("\\", "/")
            name = name.replace("/", "_")
            tarpath = "%s.tar" % name
            topdir = self.manifest.topdir

            try:
                self._FetchArchive(tarpath, cwd=topdir)
            except GitError as e:
                logger.error("error: %s", e)
                return SyncNetworkHalfResult(False, e)

            # From now on, we only need absolute tarpath.
            tarpath = os.path.join(topdir, tarpath)

            if not self._ExtractArchive(tarpath, path=topdir):
                return SyncNetworkHalfResult(
                    True,
                    SyncNetworkHalfError(
                        f"Unable to Extract Archive {tarpath}",
                        project=self.name,
                    ),
                )
            try:
                platform_utils.remove(tarpath)
            except OSError as e:
                logger.warn("warn: Cannot remove archive %s: %s", tarpath, e)
            self._CopyAndLinkFiles()
            return SyncNetworkHalfResult(True)

        # If the shared object dir already exists, don't try to rebootstrap with
        # a clone bundle download.  We should have the majority of objects
        # already.
        if clone_bundle and os.path.exists(self.objdir):
            clone_bundle = False

        if self.name in partial_clone_exclude:
            clone_bundle = True
            clone_filter = None

        if is_new is None:
            is_new = not self.Exists
        if is_new:
            self._InitGitDir(force_sync=force_sync, quiet=quiet)
        else:
            self._UpdateHooks(quiet=quiet)
        self._InitRemote()

        if self.UseAlternates:
            # If gitdir/objects is a symlink, migrate it from the old layout.
            gitdir_objects = os.path.join(self.gitdir, "objects")
            if platform_utils.islink(gitdir_objects):
                platform_utils.remove(gitdir_objects, missing_ok=True)
            gitdir_alt = os.path.join(self.gitdir, "objects/info/alternates")
            if not os.path.exists(gitdir_alt):
                os.makedirs(os.path.dirname(gitdir_alt), exist_ok=True)
                _lwrite(
                    gitdir_alt,
                    os.path.join(
                        os.path.relpath(self.objdir, gitdir_objects), "objects"
                    )
                    + "\n",
                )

        if is_new:
            alt = os.path.join(self.objdir, "objects/info/alternates")
            try:
                with open(alt) as fd:
                    # This works for both absolute and relative alternate
                    # directories.
                    alt_dir = os.path.join(
                        self.objdir, "objects", fd.readline().rstrip()
                    )
            except IOError:
                alt_dir = None
        else:
            alt_dir = None

        if (
            clone_bundle
            and alt_dir is None
            and self._ApplyCloneBundle(
                initial=is_new, quiet=quiet, verbose=verbose
            )
        ):
            is_new = False

        if current_branch_only is None:
            if self.sync_c:
                current_branch_only = True
            elif not self.manifest._loaded:
                # Manifest cannot check defaults until it syncs.
                current_branch_only = False
            elif self.manifest.default.sync_c:
                current_branch_only = True

        if tags is None:
            tags = self.sync_tags

        if self.clone_depth:
            depth = self.clone_depth
        else:
            depth = self.manifest.manifestProject.depth

        if depth and clone_filter_for_depth:
            depth = None
            clone_filter = clone_filter_for_depth

        # See if we can skip the network fetch entirely.
        remote_fetched = False
        if not (
            optimized_fetch
            and IsId(self.revisionExpr)
            and self._CheckForImmutableRevision()
        ):
            remote_fetched = True
            try:
                if not self._RemoteFetch(
                    initial=is_new,
                    quiet=quiet,
                    verbose=verbose,
                    output_redir=output_redir,
                    alt_dir=alt_dir,
                    current_branch_only=current_branch_only,
                    tags=tags,
                    prune=prune,
                    depth=depth,
                    submodules=submodules,
                    force_sync=force_sync,
                    ssh_proxy=ssh_proxy,
                    clone_filter=clone_filter,
                    retry_fetches=retry_fetches,
                ):
                    return SyncNetworkHalfResult(
                        remote_fetched,
                        SyncNetworkHalfError(
                            f"Unable to remote fetch project {self.name}",
                            project=self.name,
                        ),
                    )
            except RepoError as e:
                return SyncNetworkHalfResult(
                    remote_fetched,
                    e,
                )

        mp = self.manifest.manifestProject
        dissociate = mp.dissociate
        if dissociate:
            alternates_file = os.path.join(
                self.objdir, "objects/info/alternates"
            )
            if os.path.exists(alternates_file):
                cmd = ["repack", "-a", "-d"]
                p = GitCommand(
                    self,
                    cmd,
                    bare=True,
                    capture_stdout=bool(output_redir),
                    merge_output=bool(output_redir),
                )
                if p.stdout and output_redir:
                    output_redir.write(p.stdout)
                if p.Wait() != 0:
                    return SyncNetworkHalfResult(
                        remote_fetched,
                        GitError(
                            "Unable to repack alternates", project=self.name
                        ),
                    )
                platform_utils.remove(alternates_file)

        if self.worktree:
            self._InitMRef()
        else:
            self._InitMirrorHead()
            platform_utils.remove(
                os.path.join(self.gitdir, "FETCH_HEAD"), missing_ok=True
            )
        return SyncNetworkHalfResult(remote_fetched)

    def PostRepoUpgrade(self):
        self._InitHooks()

    def _CopyAndLinkFiles(self):
        if self.client.isGitcClient:
            return
        for copyfile in self.copyfiles:
            copyfile._Copy()
        for linkfile in self.linkfiles:
            linkfile._Link()

    def GetCommitRevisionId(self):
        """Get revisionId of a commit.

        Use this method instead of GetRevisionId to get the id of the commit
        rather than the id of the current git object (for example, a tag)

        """
        if self.revisionId:
            return self.revisionId
        if not self.revisionExpr.startswith(R_TAGS):
            return self.GetRevisionId(self._allrefs)

        try:
            return self.bare_git.rev_list(self.revisionExpr, "-1")[0]
        except GitError:
            raise ManifestInvalidRevisionError(
                "revision %s in %s not found" % (self.revisionExpr, self.name)
            )

    def GetRevisionId(self, all_refs=None):
        if self.revisionId:
            return self.revisionId

        rem = self.GetRemote()
        rev = rem.ToLocal(self.revisionExpr)

        if all_refs is not None and rev in all_refs:
            return all_refs[rev]

        try:
            return self.bare_git.rev_parse("--verify", "%s^0" % rev)
        except GitError:
            raise ManifestInvalidRevisionError(
                "revision %s in %s not found" % (self.revisionExpr, self.name)
            )

    def SetRevisionId(self, revisionId):
        if self.revisionExpr:
            self.upstream = self.revisionExpr

        self.revisionId = revisionId

    def Sync_LocalHalf(
        self, syncbuf, force_sync=False, submodules=False, errors=None
    ):
        """Perform only the local IO portion of the sync process.

        Network access is not required.
        """
        if errors is None:
            errors = []

        def fail(error: Exception):
            errors.append(error)
            syncbuf.fail(self, error)

        if not os.path.exists(self.gitdir):
            fail(
                LocalSyncFail(
                    "Cannot checkout %s due to missing network sync; Run "
                    "`repo sync -n %s` first." % (self.name, self.name),
                    project=self.name,
                )
            )
            return

        self._InitWorkTree(force_sync=force_sync, submodules=submodules)
        all_refs = self.bare_ref.all
        self.CleanPublishedCache(all_refs)
        revid = self.GetRevisionId(all_refs)

        # Special case the root of the repo client checkout.  Make sure it
        # doesn't contain files being checked out to dirs we don't allow.
        if self.relpath == ".":
            PROTECTED_PATHS = {".repo"}
            paths = set(
                self.work_git.ls_tree("-z", "--name-only", "--", revid).split(
                    "\0"
                )
            )
            bad_paths = paths & PROTECTED_PATHS
            if bad_paths:
                fail(
                    LocalSyncFail(
                        "Refusing to checkout project that writes to protected "
                        "paths: %s" % (", ".join(bad_paths),),
                        project=self.name,
                    )
                )
                return

        def _doff():
            self._FastForward(revid)
            self._CopyAndLinkFiles()

        def _dosubmodules():
            self._SyncSubmodules(quiet=True)

        head = self.work_git.GetHead()
        if head.startswith(R_HEADS):
            branch = head[len(R_HEADS) :]
            try:
                head = all_refs[head]
            except KeyError:
                head = None
        else:
            branch = None

        if branch is None or syncbuf.detach_head:
            # Currently on a detached HEAD.  The user is assumed to
            # not have any local modifications worth worrying about.
            if self.IsRebaseInProgress():
                fail(_PriorSyncFailedError(project=self.name))
                return

            if head == revid:
                # No changes; don't do anything further.
                # Except if the head needs to be detached.
                if not syncbuf.detach_head:
                    # The copy/linkfile config may have changed.
                    self._CopyAndLinkFiles()
                    return
            else:
                lost = self._revlist(not_rev(revid), HEAD)
                if lost:
                    syncbuf.info(self, "discarding %d commits", len(lost))

            try:
                self._Checkout(revid, quiet=True)
                if submodules:
                    self._SyncSubmodules(quiet=True)
            except GitError as e:
                fail(e)
                return
            self._CopyAndLinkFiles()
            return

        if head == revid:
            # No changes; don't do anything further.
            #
            # The copy/linkfile config may have changed.
            self._CopyAndLinkFiles()
            return

        branch = self.GetBranch(branch)

        if not branch.LocalMerge:
            # The current branch has no tracking configuration.
            # Jump off it to a detached HEAD.
            syncbuf.info(
                self, "leaving %s; does not track upstream", branch.name
            )
            try:
                self._Checkout(revid, quiet=True)
                if submodules:
                    self._SyncSubmodules(quiet=True)
            except GitError as e:
                fail(e)
                return
            self._CopyAndLinkFiles()
            return

        upstream_gain = self._revlist(not_rev(HEAD), revid)

        # See if we can perform a fast forward merge.  This can happen if our
        # branch isn't in the exact same state as we last published.
        try:
            self.work_git.merge_base(
                "--is-ancestor", HEAD, revid, log_as_error=False
            )
            # Skip the published logic.
            pub = False
        except GitError:
            pub = self.WasPublished(branch.name, all_refs)

        if pub:
            not_merged = self._revlist(not_rev(revid), pub)
            if not_merged:
                if upstream_gain:
                    # The user has published this branch and some of those
                    # commits are not yet merged upstream.  We do not want
                    # to rewrite the published commits so we punt.
                    fail(
                        LocalSyncFail(
                            "branch %s is published (but not merged) and is "
                            "now %d commits behind"
                            % (branch.name, len(upstream_gain)),
                            project=self.name,
                        )
                    )
                return
            elif pub == head:
                # All published commits are merged, and thus we are a
                # strict subset.  We can fast-forward safely.
                syncbuf.later1(self, _doff)
                if submodules:
                    syncbuf.later1(self, _dosubmodules)
                return

        # Examine the local commits not in the remote.  Find the
        # last one attributed to this user, if any.
        local_changes = self._revlist(not_rev(revid), HEAD, format="%H %ce")
        last_mine = None
        cnt_mine = 0
        for commit in local_changes:
            commit_id, committer_email = commit.split(" ", 1)
            if committer_email == self.UserEmail:
                last_mine = commit_id
                cnt_mine += 1

        if not upstream_gain and cnt_mine == len(local_changes):
            # The copy/linkfile config may have changed.
            self._CopyAndLinkFiles()
            return

        if self.IsDirty(consider_untracked=False):
            fail(_DirtyError(project=self.name))
            return

        # If the upstream switched on us, warn the user.
        if branch.merge != self.revisionExpr:
            if branch.merge and self.revisionExpr:
                syncbuf.info(
                    self,
                    "manifest switched %s...%s",
                    branch.merge,
                    self.revisionExpr,
                )
            elif branch.merge:
                syncbuf.info(self, "manifest no longer tracks %s", branch.merge)

        if cnt_mine < len(local_changes):
            # Upstream rebased. Not everything in HEAD was created by this user.
            syncbuf.info(
                self,
                "discarding %d commits removed from upstream",
                len(local_changes) - cnt_mine,
            )

        branch.remote = self.GetRemote()
        if not IsId(self.revisionExpr):
            # In case of manifest sync the revisionExpr might be a SHA1.
            branch.merge = self.revisionExpr
            if not branch.merge.startswith("refs/"):
                branch.merge = R_HEADS + branch.merge
        branch.Save()

        if cnt_mine > 0 and self.rebase:

            def _docopyandlink():
                self._CopyAndLinkFiles()

            def _dorebase():
                self._Rebase(upstream="%s^1" % last_mine, onto=revid)

            syncbuf.later2(self, _dorebase)
            if submodules:
                syncbuf.later2(self, _dosubmodules)
            syncbuf.later2(self, _docopyandlink)
        elif local_changes:
            try:
                self._ResetHard(revid)
                if submodules:
                    self._SyncSubmodules(quiet=True)
                self._CopyAndLinkFiles()
            except GitError as e:
                fail(e)
                return
        else:
            syncbuf.later1(self, _doff)
            if submodules:
                syncbuf.later1(self, _dosubmodules)

    def AddCopyFile(self, src, dest, topdir):
        """Mark |src| for copying to |dest| (relative to |topdir|).

        No filesystem changes occur here.  Actual copying happens later on.

        Paths should have basic validation run on them before being queued.
        Further checking will be handled when the actual copy happens.
        """
        self.copyfiles.append(_CopyFile(self.worktree, src, topdir, dest))

    def AddLinkFile(self, src, dest, topdir):
        """Mark |dest| to create a symlink (relative to |topdir|) pointing to
        |src|.

        No filesystem changes occur here.  Actual linking happens later on.

        Paths should have basic validation run on them before being queued.
        Further checking will be handled when the actual link happens.
        """
        self.linkfiles.append(_LinkFile(self.worktree, src, topdir, dest))

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

    def DownloadPatchSet(self, change_id, patch_id):
        """Download a single patch set of a single change to FETCH_HEAD."""
        remote = self.GetRemote()

        cmd = ["fetch", remote.name]
        cmd.append(
            "refs/changes/%2.2d/%d/%d" % (change_id % 100, change_id, patch_id)
        )
        GitCommand(self, cmd, bare=True, verify_command=True).Wait()
        return DownloadedChange(
            self,
            self.GetRevisionId(),
            change_id,
            patch_id,
            self.bare_git.rev_parse("FETCH_HEAD"),
        )

    def DeleteWorktree(self, quiet=False, force=False):
        """Delete the source checkout and any other housekeeping tasks.

        This currently leaves behind the internal .repo/ cache state.  This
        helps when switching branches or manifest changes get reverted as we
        don't have to redownload all the git objects.  But we should do some GC
        at some point.

        Args:
            quiet: Whether to hide normal messages.
            force: Always delete tree even if dirty.

        Returns:
            True if the worktree was completely cleaned out.
        """
        if self.IsDirty():
            if force:
                logger.warn(
                    "warning: %s: Removing dirty project: uncommitted changes "
                    "lost.",
                    self.RelPath(local=False),
                )
            else:
                msg = (
                    "error: %s: Cannot remove project: uncommitted"
                    "changes are present.\n" % self.RelPath(local=False)
                )
                logger.error(msg)
                raise DeleteDirtyWorktreeError(msg, project=self)

        if not quiet:
            print(
                "%s: Deleting obsolete checkout." % (self.RelPath(local=False),)
            )

        # Unlock and delink from the main worktree.  We don't use git's worktree
        # remove because it will recursively delete projects -- we handle that
        # ourselves below.  https://crbug.com/git/48
        if self.use_git_worktrees:
            needle = platform_utils.realpath(self.gitdir)
            # Find the git worktree commondir under .repo/worktrees/.
            output = self.bare_git.worktree("list", "--porcelain").splitlines()[
                0
            ]
            assert output.startswith("worktree "), output
            commondir = output[9:]
            # Walk each of the git worktrees to see where they point.
            configs = os.path.join(commondir, "worktrees")
            for name in os.listdir(configs):
                gitdir = os.path.join(configs, name, "gitdir")
                with open(gitdir) as fp:
                    relpath = fp.read().strip()
                # Resolve the checkout path and see if it matches this project.
                fullpath = platform_utils.realpath(
                    os.path.join(configs, name, relpath)
                )
                if fullpath == needle:
                    platform_utils.rmtree(os.path.join(configs, name))

        # Delete the .git directory first, so we're less likely to have a
        # partially working git repository around. There shouldn't be any git
        # projects here, so rmtree works.

        # Try to remove plain files first in case of git worktrees.  If this
        # fails for any reason, we'll fall back to rmtree, and that'll display
        # errors if it can't remove things either.
        try:
            platform_utils.remove(self.gitdir)
        except OSError:
            pass
        try:
            platform_utils.rmtree(self.gitdir)
        except OSError as e:
            if e.errno != errno.ENOENT:
                logger.error("error: %s: %s", self.gitdir, e)
                logger.error(
                    "error: %s: Failed to delete obsolete checkout; remove "
                    "manually, then run `repo sync -l`.",
                    self.RelPath(local=False),
                )
                raise DeleteWorktreeError(aggregate_errors=[e])

        # Delete everything under the worktree, except for directories that
        # contain another git project.
        dirs_to_remove = []
        failed = False
        errors = []
        for root, dirs, files in platform_utils.walk(self.worktree):
            for f in files:
                path = os.path.join(root, f)
                try:
                    platform_utils.remove(path)
                except OSError as e:
                    if e.errno != errno.ENOENT:
                        logger.error("error: %s: Failed to remove: %s", path, e)
                        failed = True
                        errors.append(e)
            dirs[:] = [
                d
                for d in dirs
                if not os.path.lexists(os.path.join(root, d, ".git"))
            ]
            dirs_to_remove += [
                os.path.join(root, d)
                for d in dirs
                if os.path.join(root, d) not in dirs_to_remove
            ]
        for d in reversed(dirs_to_remove):
            if platform_utils.islink(d):
                try:
                    platform_utils.remove(d)
                except OSError as e:
                    if e.errno != errno.ENOENT:
                        logger.error("error: %s: Failed to remove: %s", d, e)
                        failed = True
                        errors.append(e)
            elif not platform_utils.listdir(d):
                try:
                    platform_utils.rmdir(d)
                except OSError as e:
                    if e.errno != errno.ENOENT:
                        logger.error("error: %s: Failed to remove: %s", d, e)
                        failed = True
                        errors.append(e)
        if failed:
            logger.error(
                "error: %s: Failed to delete obsolete checkout.",
                self.RelPath(local=False),
            )
            logger.error(
                "       Remove manually, then run `repo sync -l`.",
            )
            raise DeleteWorktreeError(aggregate_errors=errors)

        # Try deleting parent dirs if they are empty.
        path = self.worktree
        while path != self.manifest.topdir:
            try:
                platform_utils.rmdir(path)
            except OSError as e:
                if e.errno != errno.ENOENT:
                    break
            path = os.path.dirname(path)

        return True

    def StartBranch(self, name, branch_merge="", revision=None):
        """Create a new branch off the manifest's revision."""
        if not branch_merge:
            branch_merge = self.revisionExpr
        head = self.work_git.GetHead()
        if head == (R_HEADS + name):
            return True

        all_refs = self.bare_ref.all
        if R_HEADS + name in all_refs:
            GitCommand(
                self, ["checkout", "-q", name, "--"], verify_command=True
            ).Wait()
            return True

        branch = self.GetBranch(name)
        branch.remote = self.GetRemote()
        branch.merge = branch_merge
        if not branch.merge.startswith("refs/") and not IsId(branch_merge):
            branch.merge = R_HEADS + branch_merge

        if revision is None:
            revid = self.GetRevisionId(all_refs)
        else:
            revid = self.work_git.rev_parse(revision)

        if head.startswith(R_HEADS):
            try:
                head = all_refs[head]
            except KeyError:
                head = None
        if revid and head and revid == head:
            ref = R_HEADS + name
            self.work_git.update_ref(ref, revid)
            self.work_git.symbolic_ref(HEAD, ref)
            branch.Save()
            return True

        GitCommand(
            self,
            ["checkout", "-q", "-b", branch.name, revid],
            verify_command=True,
        ).Wait()
        branch.Save()
        return True

    def CheckoutBranch(self, name):
        """Checkout a local topic branch.

        Args:
            name: The name of the branch to checkout.

        Returns:
            True if the checkout succeeded; False if the
            branch doesn't exist.
        """
        rev = R_HEADS + name
        head = self.work_git.GetHead()
        if head == rev:
            # Already on the branch.
            return True

        all_refs = self.bare_ref.all
        try:
            revid = all_refs[rev]
        except KeyError:
            # Branch does not exist in this project.
            return False

        if head.startswith(R_HEADS):
            try:
                head = all_refs[head]
            except KeyError:
                head = None

        if head == revid:
            # Same revision; just update HEAD to point to the new
            # target branch, but otherwise take no other action.
            _lwrite(
                self.work_git.GetDotgitPath(subpath=HEAD),
                "ref: %s%s\n" % (R_HEADS, name),
            )
            return True

        GitCommand(
            self,
            ["checkout", name, "--"],
            capture_stdout=True,
            capture_stderr=True,
            verify_command=True,
        ).Wait()
        return True

    def AbandonBranch(self, name):
        """Destroy a local topic branch.

        Args:
            name: The name of the branch to abandon.

        Returns:
            True if the abandon succeeded; Raises GitCommandError if it didn't;
            None if the branch didn't exist.
        """
        rev = R_HEADS + name
        all_refs = self.bare_ref.all
        if rev not in all_refs:
            # Doesn't exist
            return None

        head = self.work_git.GetHead()
        if head == rev:
            # We can't destroy the branch while we are sitting
            # on it.  Switch to a detached HEAD.
            head = all_refs[head]

            revid = self.GetRevisionId(all_refs)
            if head == revid:
                _lwrite(
                    self.work_git.GetDotgitPath(subpath=HEAD), "%s\n" % revid
                )
            else:
                self._Checkout(revid, quiet=True)
        GitCommand(
            self,
            ["branch", "-D", name],
            capture_stdout=True,
            capture_stderr=True,
            verify_command=True,
        ).Wait()
        return True

    def PruneHeads(self):
        """Prune any topic branches already merged into upstream."""
        cb = self.CurrentBranch
        kill = []
        left = self._allrefs
        for name in left.keys():
            if name.startswith(R_HEADS):
                name = name[len(R_HEADS) :]
                if cb is None or name != cb:
                    kill.append(name)

        # Minor optimization: If there's nothing to prune, then don't try to
        # read any project state.
        if not kill and not cb:
            return []

        rev = self.GetRevisionId(left)
        if (
            cb is not None
            and not self._revlist(HEAD + "..." + rev)
            and not self.IsDirty(consider_untracked=False)
        ):
            self.work_git.DetachHead(HEAD)
            kill.append(cb)

        if kill:
            old = self.bare_git.GetHead()

            try:
                self.bare_git.DetachHead(rev)

                b = ["branch", "-d"]
                b.extend(kill)
                b = GitCommand(
                    self, b, bare=True, capture_stdout=True, capture_stderr=True
                )
                b.Wait()
            finally:
                if IsId(old):
                    self.bare_git.DetachHead(old)
                else:
                    self.bare_git.SetHead(old)
                left = self._allrefs

            for branch in kill:
                if (R_HEADS + branch) not in left:
                    self.CleanPublishedCache()
                    break

        if cb and cb not in kill:
            kill.append(cb)
        kill.sort()

        kept = []
        for branch in kill:
            if R_HEADS + branch in left:
                branch = self.GetBranch(branch)
                base = branch.LocalMerge
                if not base:
                    base = rev
                kept.append(ReviewableBranch(self, branch, base))
        return kept

    def GetRegisteredSubprojects(self):
        result = []

        def rec(subprojects):
            if not subprojects:
                return
            result.extend(subprojects)
            for p in subprojects:
                rec(p.subprojects)

        rec(self.subprojects)
        return result

    def _GetSubmodules(self):
        # Unfortunately we cannot call `git submodule status --recursive` here
        # because the working tree might not exist yet, and it cannot be used
        # without a working tree in its current implementation.

        def get_submodules(gitdir, rev):
            # Parse .gitmodules for submodule sub_paths and sub_urls.
            sub_paths, sub_urls = parse_gitmodules(gitdir, rev)
            if not sub_paths:
                return []
            # Run `git ls-tree` to read SHAs of submodule object, which happen
            # to be revision of submodule repository.
            sub_revs = git_ls_tree(gitdir, rev, sub_paths)
            submodules = []
            for sub_path, sub_url in zip(sub_paths, sub_urls):
                try:
                    sub_rev = sub_revs[sub_path]
                except KeyError:
                    # Ignore non-exist submodules.
                    continue
                submodules.append((sub_rev, sub_path, sub_url))
            return submodules

        re_path = re.compile(r"^submodule\.(.+)\.path=(.*)$")
        re_url = re.compile(r"^submodule\.(.+)\.url=(.*)$")

        def parse_gitmodules(gitdir, rev):
            cmd = ["cat-file", "blob", "%s:.gitmodules" % rev]
            try:
                p = GitCommand(
                    None,
                    cmd,
                    capture_stdout=True,
                    capture_stderr=True,
                    bare=True,
                    gitdir=gitdir,
                )
            except GitError:
                return [], []
            if p.Wait() != 0:
                return [], []

            gitmodules_lines = []
            fd, temp_gitmodules_path = tempfile.mkstemp()
            try:
                os.write(fd, p.stdout.encode("utf-8"))
                os.close(fd)
                cmd = ["config", "--file", temp_gitmodules_path, "--list"]
                p = GitCommand(
                    None,
                    cmd,
                    capture_stdout=True,
                    capture_stderr=True,
                    bare=True,
                    gitdir=gitdir,
                )
                if p.Wait() != 0:
                    return [], []
                gitmodules_lines = p.stdout.split("\n")
            except GitError:
                return [], []
            finally:
                platform_utils.remove(temp_gitmodules_path)

            names = set()
            paths = {}
            urls = {}
            for line in gitmodules_lines:
                if not line:
                    continue
                m = re_path.match(line)
                if m:
                    names.add(m.group(1))
                    paths[m.group(1)] = m.group(2)
                    continue
                m = re_url.match(line)
                if m:
                    names.add(m.group(1))
                    urls[m.group(1)] = m.group(2)
                    continue
            names = sorted(names)
            return (
                [paths.get(name, "") for name in names],
                [urls.get(name, "") for name in names],
            )

        def git_ls_tree(gitdir, rev, paths):
            cmd = ["ls-tree", rev, "--"]
            cmd.extend(paths)
            try:
                p = GitCommand(
                    None,
                    cmd,
                    capture_stdout=True,
                    capture_stderr=True,
                    bare=True,
                    gitdir=gitdir,
                )
            except GitError:
                return []
            if p.Wait() != 0:
                return []
            objects = {}
            for line in p.stdout.split("\n"):
                if not line.strip():
                    continue
                object_rev, object_path = line.split()[2:4]
                objects[object_path] = object_rev
            return objects

        try:
            rev = self.GetRevisionId()
        except GitError:
            return []
        return get_submodules(self.gitdir, rev)

    def GetDerivedSubprojects(self):
        result = []
        if not self.Exists:
            # If git repo does not exist yet, querying its submodules will
            # mess up its states; so return here.
            return result
        for rev, path, url in self._GetSubmodules():
            name = self.manifest.GetSubprojectName(self, path)
            (
                relpath,
                worktree,
                gitdir,
                objdir,
            ) = self.manifest.GetSubprojectPaths(self, name, path)
            project = self.manifest.paths.get(relpath)
            if project:
                result.extend(project.GetDerivedSubprojects())
                continue

            if url.startswith(".."):
                url = urllib.parse.urljoin("%s/" % self.remote.url, url)
            remote = RemoteSpec(
                self.remote.name,
                url=url,
                pushUrl=self.remote.pushUrl,
                review=self.remote.review,
                revision=self.remote.revision,
            )
            subproject = Project(
                manifest=self.manifest,
                name=name,
                remote=remote,
                gitdir=gitdir,
                objdir=objdir,
                worktree=worktree,
                relpath=relpath,
                revisionExpr=rev,
                revisionId=rev,
                rebase=self.rebase,
                groups=self.groups,
                sync_c=self.sync_c,
                sync_s=self.sync_s,
                sync_tags=self.sync_tags,
                parent=self,
                is_derived=True,
            )
            result.append(subproject)
            result.extend(subproject.GetDerivedSubprojects())
        return result

    def EnableRepositoryExtension(self, key, value="true", version=1):
        """Enable git repository extension |key| with |value|.

        Args:
            key: The extension to enabled.  Omit the "extensions." prefix.
            value: The value to use for the extension.
            version: The minimum git repository version needed.
        """
        # Make sure the git repo version is new enough already.
        found_version = self.config.GetInt("core.repositoryFormatVersion")
        if found_version is None:
            found_version = 0
        if found_version < version:
            self.config.SetString("core.repositoryFormatVersion", str(version))

        # Enable the extension!
        self.config.SetString("extensions.%s" % (key,), value)

    def ResolveRemoteHead(self, name=None):
        """Find out what the default branch (HEAD) points to.

        Normally this points to refs/heads/master, but projects are moving to
        main. Support whatever the server uses rather than hardcoding "master"
        ourselves.
        """
        if name is None:
            name = self.remote.name

        # The output will look like (NB: tabs are separators):
        # ref: refs/heads/master	HEAD
        # 5f6803b100bb3cd0f534e96e88c91373e8ed1c44	HEAD
        output = self.bare_git.ls_remote(
            "-q", "--symref", "--exit-code", name, "HEAD"
        )

        for line in output.splitlines():
            lhs, rhs = line.split("\t", 1)
            if rhs == "HEAD" and lhs.startswith("ref:"):
                return lhs[4:].strip()

        return None

    def _CheckForImmutableRevision(self):
        try:
            # if revision (sha or tag) is not present then following function
            # throws an error.
            self.bare_git.rev_list(
                "-1",
                "--missing=allow-any",
                "%s^0" % self.revisionExpr,
                "--",
                log_as_error=False,
            )
            if self.upstream:
                rev = self.GetRemote().ToLocal(self.upstream)
                self.bare_git.rev_list(
                    "-1",
                    "--missing=allow-any",
                    "%s^0" % rev,
                    "--",
                    log_as_error=False,
                )
                self.bare_git.merge_base(
                    "--is-ancestor",
                    self.revisionExpr,
                    rev,
                    log_as_error=False,
                )
            return True
        except GitError:
            # There is no such persistent revision. We have to fetch it.
            return False

    def _FetchArchive(self, tarpath, cwd=None):
        cmd = ["archive", "-v", "-o", tarpath]
        cmd.append("--remote=%s" % self.remote.url)
        cmd.append("--prefix=%s/" % self.RelPath(local=False))
        cmd.append(self.revisionExpr)

        command = GitCommand(
            self,
            cmd,
            cwd=cwd,
            capture_stdout=True,
            capture_stderr=True,
            verify_command=True,
        )
        command.Wait()

    def _RemoteFetch(
        self,
        name=None,
        current_branch_only=False,
        initial=False,
        quiet=False,
        verbose=False,
        output_redir=None,
        alt_dir=None,
        tags=True,
        prune=False,
        depth=None,
        submodules=False,
        ssh_proxy=None,
        force_sync=False,
        clone_filter=None,
        retry_fetches=2,
        retry_sleep_initial_sec=4.0,
        retry_exp_factor=2.0,
    ) -> bool:
        tag_name = None
        # The depth should not be used when fetching to a mirror because
        # it will result in a shallow repository that cannot be cloned or
        # fetched from.
        # The repo project should also never be synced with partial depth.
        if self.manifest.IsMirror or self.relpath == ".repo/repo":
            depth = None

        if depth:
            current_branch_only = True

        is_sha1 = bool(IsId(self.revisionExpr))

        if current_branch_only:
            if self.revisionExpr.startswith(R_TAGS):
                # This is a tag and its commit id should never change.
                tag_name = self.revisionExpr[len(R_TAGS) :]
            elif self.upstream and self.upstream.startswith(R_TAGS):
                # This is a tag and its commit id should never change.
                tag_name = self.upstream[len(R_TAGS) :]

            if is_sha1 or tag_name is not None:
                if self._CheckForImmutableRevision():
                    if verbose:
                        print(
                            "Skipped fetching project %s (already have "
                            "persistent ref)" % self.name
                        )
                    return True
            if is_sha1 and not depth:
                # When syncing a specific commit and --depth is not set:
                # * if upstream is explicitly specified and is not a sha1, fetch
                #   only upstream as users expect only upstream to be fetch.
                #   Note: The commit might not be in upstream in which case the
                #   sync will fail.
                # * otherwise, fetch all branches to make sure we end up with
                #   the specific commit.
                if self.upstream:
                    current_branch_only = not IsId(self.upstream)
                else:
                    current_branch_only = False

        if not name:
            name = self.remote.name

        remote = self.GetRemote(name)
        if not remote.PreConnectFetch(ssh_proxy):
            ssh_proxy = None

        if initial:
            if alt_dir and "objects" == os.path.basename(alt_dir):
                ref_dir = os.path.dirname(alt_dir)
                packed_refs = os.path.join(self.gitdir, "packed-refs")

                all_refs = self.bare_ref.all
                ids = set(all_refs.values())
                tmp = set()

                for r, ref_id in GitRefs(ref_dir).all.items():
                    if r not in all_refs:
                        if r.startswith(R_TAGS) or remote.WritesTo(r):
                            all_refs[r] = ref_id
                            ids.add(ref_id)
                            continue

                    if ref_id in ids:
                        continue

                    r = "refs/_alt/%s" % ref_id
                    all_refs[r] = ref_id
                    ids.add(ref_id)
                    tmp.add(r)

                tmp_packed_lines = []
                old_packed_lines = []

                for r in sorted(all_refs):
                    line = "%s %s\n" % (all_refs[r], r)
                    tmp_packed_lines.append(line)
                    if r not in tmp:
                        old_packed_lines.append(line)

                tmp_packed = "".join(tmp_packed_lines)
                old_packed = "".join(old_packed_lines)
                _lwrite(packed_refs, tmp_packed)
            else:
                alt_dir = None

        cmd = ["fetch"]

        if clone_filter:
            git_require((2, 19, 0), fail=True, msg="partial clones")
            cmd.append("--filter=%s" % clone_filter)
            self.EnableRepositoryExtension("partialclone", self.remote.name)

        if depth:
            cmd.append("--depth=%s" % depth)
        else:
            # If this repo has shallow objects, then we don't know which refs
            # have shallow objects or not. Tell git to unshallow all fetched
            # refs.  Don't do this with projects that don't have shallow
            # objects, since it is less efficient.
            if os.path.exists(os.path.join(self.gitdir, "shallow")):
                cmd.append("--depth=2147483647")

        if not verbose:
            cmd.append("--quiet")
        if not quiet and sys.stdout.isatty():
            cmd.append("--progress")
        if not self.worktree:
            cmd.append("--update-head-ok")
        cmd.append(name)

        if force_sync:
            cmd.append("--force")

        if prune:
            cmd.append("--prune")

        # Always pass something for --recurse-submodules, git with GIT_DIR
        # behaves incorrectly when not given `--recurse-submodules=no`.
        # (b/218891912)
        cmd.append(
            f'--recurse-submodules={"on-demand" if submodules else "no"}'
        )

        spec = []
        if not current_branch_only:
            # Fetch whole repo.
            spec.append(
                str(("+refs/heads/*:") + remote.ToLocal("refs/heads/*"))
            )
        elif tag_name is not None:
            spec.append("tag")
            spec.append(tag_name)

        if self.manifest.IsMirror and not current_branch_only:
            branch = None
        else:
            branch = self.revisionExpr
        if (
            not self.manifest.IsMirror
            and is_sha1
            and depth
            and git_require((1, 8, 3))
        ):
            # Shallow checkout of a specific commit, fetch from that commit and
            # not the heads only as the commit might be deeper in the history.
            spec.append(branch)
            if self.upstream:
                spec.append(self.upstream)
        else:
            if is_sha1:
                branch = self.upstream
            if branch is not None and branch.strip():
                if not branch.startswith("refs/"):
                    branch = R_HEADS + branch
                spec.append(str(("+%s:" % branch) + remote.ToLocal(branch)))

        # If mirroring repo and we cannot deduce the tag or branch to fetch,
        # fetch whole repo.
        if self.manifest.IsMirror and not spec:
            spec.append(
                str(("+refs/heads/*:") + remote.ToLocal("refs/heads/*"))
            )

        # If using depth then we should not get all the tags since they may
        # be outside of the depth.
        if not tags or depth:
            cmd.append("--no-tags")
        else:
            cmd.append("--tags")
            spec.append(str(("+refs/tags/*:") + remote.ToLocal("refs/tags/*")))

        cmd.extend(spec)

        # At least one retry minimum due to git remote prune.
        retry_fetches = max(retry_fetches, 2)
        retry_cur_sleep = retry_sleep_initial_sec
        ok = prune_tried = False
        for try_n in range(retry_fetches):
            verify_command = try_n == retry_fetches - 1
            gitcmd = GitCommand(
                self,
                cmd,
                bare=True,
                objdir=os.path.join(self.objdir, "objects"),
                ssh_proxy=ssh_proxy,
                merge_output=True,
                capture_stdout=quiet or bool(output_redir),
                verify_command=verify_command,
            )
            if gitcmd.stdout and not quiet and output_redir:
                output_redir.write(gitcmd.stdout)
            ret = gitcmd.Wait()
            if ret == 0:
                ok = True
                break

            # Retry later due to HTTP 429 Too Many Requests.
            elif (
                gitcmd.stdout
                and "error:" in gitcmd.stdout
                and "HTTP 429" in gitcmd.stdout
            ):
                # Fallthru to sleep+retry logic at the bottom.
                pass

            # Try to prune remote branches once in case there are conflicts.
            # For example, if the remote had refs/heads/upstream, but deleted
            # that and now has refs/heads/upstream/foo.
            elif (
                gitcmd.stdout
                and "error:" in gitcmd.stdout
                and "git remote prune" in gitcmd.stdout
                and not prune_tried
            ):
                prune_tried = True
                prunecmd = GitCommand(
                    self,
                    ["remote", "prune", name],
                    bare=True,
                    ssh_proxy=ssh_proxy,
                )
                ret = prunecmd.Wait()
                if ret:
                    break
                print(
                    "retrying fetch after pruning remote branches",
                    file=output_redir,
                )
                # Continue right away so we don't sleep as we shouldn't need to.
                continue
            elif current_branch_only and is_sha1 and ret == 128:
                # Exit code 128 means "couldn't find the ref you asked for"; if
                # we're in sha1 mode, we just tried sync'ing from the upstream
                # field; it doesn't exist, thus abort the optimization attempt
                # and do a full sync.
                break
            elif ret < 0:
                # Git died with a signal, exit immediately.
                break

            # Figure out how long to sleep before the next attempt, if there is
            # one.
            if not verbose and gitcmd.stdout:
                print(
                    "\n%s:\n%s" % (self.name, gitcmd.stdout),
                    end="",
                    file=output_redir,
                )
            if try_n < retry_fetches - 1:
                print(
                    "%s: sleeping %s seconds before retrying"
                    % (self.name, retry_cur_sleep),
                    file=output_redir,
                )
                time.sleep(retry_cur_sleep)
                retry_cur_sleep = min(
                    retry_exp_factor * retry_cur_sleep, MAXIMUM_RETRY_SLEEP_SEC
                )
                retry_cur_sleep *= 1 - random.uniform(
                    -RETRY_JITTER_PERCENT, RETRY_JITTER_PERCENT
                )

        if initial:
            if alt_dir:
                if old_packed != "":
                    _lwrite(packed_refs, old_packed)
                else:
                    platform_utils.remove(packed_refs)
            self.bare_git.pack_refs("--all", "--prune")

        if is_sha1 and current_branch_only:
            # We just synced the upstream given branch; verify we
            # got what we wanted, else trigger a second run of all
            # refs.
            if not self._CheckForImmutableRevision():
                # Sync the current branch only with depth set to None.
                # We always pass depth=None down to avoid infinite recursion.
                return self._RemoteFetch(
                    name=name,
                    quiet=quiet,
                    verbose=verbose,
                    output_redir=output_redir,
                    current_branch_only=current_branch_only and depth,
                    initial=False,
                    alt_dir=alt_dir,
                    tags=tags,
                    depth=None,
                    ssh_proxy=ssh_proxy,
                    clone_filter=clone_filter,
                )

        return ok

    def _ApplyCloneBundle(self, initial=False, quiet=False, verbose=False):
        if initial and (
            self.manifest.manifestProject.depth or self.clone_depth
        ):
            return False

        remote = self.GetRemote()
        bundle_url = remote.url + "/clone.bundle"
        bundle_url = GitConfig.ForUser().UrlInsteadOf(bundle_url)
        if GetSchemeFromUrl(bundle_url) not in (
            "http",
            "https",
            "persistent-http",
            "persistent-https",
        ):
            return False

        bundle_dst = os.path.join(self.gitdir, "clone.bundle")
        bundle_tmp = os.path.join(self.gitdir, "clone.bundle.tmp")

        exist_dst = os.path.exists(bundle_dst)
        exist_tmp = os.path.exists(bundle_tmp)

        if not initial and not exist_dst and not exist_tmp:
            return False

        if not exist_dst:
            exist_dst = self._FetchBundle(
                bundle_url, bundle_tmp, bundle_dst, quiet, verbose
            )
        if not exist_dst:
            return False

        cmd = ["fetch"]
        if not verbose:
            cmd.append("--quiet")
        if not quiet and sys.stdout.isatty():
            cmd.append("--progress")
        if not self.worktree:
            cmd.append("--update-head-ok")
        cmd.append(bundle_dst)
        for f in remote.fetch:
            cmd.append(str(f))
        cmd.append("+refs/tags/*:refs/tags/*")

        ok = (
            GitCommand(
                self,
                cmd,
                bare=True,
                objdir=os.path.join(self.objdir, "objects"),
            ).Wait()
            == 0
        )
        platform_utils.remove(bundle_dst, missing_ok=True)
        platform_utils.remove(bundle_tmp, missing_ok=True)
        return ok

    def _FetchBundle(self, srcUrl, tmpPath, dstPath, quiet, verbose):
        platform_utils.remove(dstPath, missing_ok=True)

        cmd = ["curl", "--fail", "--output", tmpPath, "--netrc", "--location"]
        if quiet:
            cmd += ["--silent", "--show-error"]
        if os.path.exists(tmpPath):
            size = os.stat(tmpPath).st_size
            if size >= 1024:
                cmd += ["--continue-at", "%d" % (size,)]
            else:
                platform_utils.remove(tmpPath)
        with GetUrlCookieFile(srcUrl, quiet) as (cookiefile, proxy):
            if cookiefile:
                cmd += ["--cookie", cookiefile]
            if proxy:
                cmd += ["--proxy", proxy]
            elif "http_proxy" in os.environ and "darwin" == sys.platform:
                cmd += ["--proxy", os.environ["http_proxy"]]
            if srcUrl.startswith("persistent-https"):
                srcUrl = "http" + srcUrl[len("persistent-https") :]
            elif srcUrl.startswith("persistent-http"):
                srcUrl = "http" + srcUrl[len("persistent-http") :]
            cmd += [srcUrl]

            proc = None
            with Trace("Fetching bundle: %s", " ".join(cmd)):
                if verbose:
                    print("%s: Downloading bundle: %s" % (self.name, srcUrl))
                stdout = None if verbose else subprocess.PIPE
                stderr = None if verbose else subprocess.STDOUT
                try:
                    proc = subprocess.Popen(cmd, stdout=stdout, stderr=stderr)
                except OSError:
                    return False

            (output, _) = proc.communicate()
            curlret = proc.returncode

            if curlret == 22:
                # From curl man page:
                # 22: HTTP page not retrieved. The requested url was not found
                # or returned another error with the HTTP error code being 400
                # or above. This return code only appears if -f, --fail is used.
                if verbose:
                    print(
                        "%s: Unable to retrieve clone.bundle; ignoring."
                        % self.name
                    )
                    if output:
                        print("Curl output:\n%s" % output)
                return False
            elif curlret and not verbose and output:
                logger.error("%s", output)

        if os.path.exists(tmpPath):
            if curlret == 0 and self._IsValidBundle(tmpPath, quiet):
                platform_utils.rename(tmpPath, dstPath)
                return True
            else:
                platform_utils.remove(tmpPath)
                return False
        else:
            return False

    def _IsValidBundle(self, path, quiet):
        try:
            with open(path, "rb") as f:
                if f.read(16) == b"# v2 git bundle\n":
                    return True
                else:
                    if not quiet:
                        logger.error("Invalid clone.bundle file; ignoring.")
                    return False
        except OSError:
            return False

    def _Checkout(self, rev, quiet=False):
        cmd = ["checkout"]
        if quiet:
            cmd.append("-q")
        cmd.append(rev)
        cmd.append("--")
        if GitCommand(self, cmd).Wait() != 0:
            if self._allrefs:
                raise GitError(
                    "%s checkout %s " % (self.name, rev), project=self.name
                )

    def _CherryPick(self, rev, ffonly=False, record_origin=False):
        cmd = ["cherry-pick"]
        if ffonly:
            cmd.append("--ff")
        if record_origin:
            cmd.append("-x")
        cmd.append(rev)
        cmd.append("--")
        if GitCommand(self, cmd).Wait() != 0:
            if self._allrefs:
                raise GitError(
                    "%s cherry-pick %s " % (self.name, rev), project=self.name
                )

    def _LsRemote(self, refs):
        cmd = ["ls-remote", self.remote.name, refs]
        p = GitCommand(self, cmd, capture_stdout=True)
        if p.Wait() == 0:
            return p.stdout
        return None

    def _Revert(self, rev):
        cmd = ["revert"]
        cmd.append("--no-edit")
        cmd.append(rev)
        cmd.append("--")
        if GitCommand(self, cmd).Wait() != 0:
            if self._allrefs:
                raise GitError(
                    "%s revert %s " % (self.name, rev), project=self.name
                )

    def _ResetHard(self, rev, quiet=True):
        cmd = ["reset", "--hard"]
        if quiet:
            cmd.append("-q")
        cmd.append(rev)
        if GitCommand(self, cmd).Wait() != 0:
            raise GitError(
                "%s reset --hard %s " % (self.name, rev), project=self.name
            )

    def _SyncSubmodules(self, quiet=True):
        cmd = ["submodule", "update", "--init", "--recursive"]
        if quiet:
            cmd.append("-q")
        if GitCommand(self, cmd).Wait() != 0:
            raise GitError(
                "%s submodule update --init --recursive " % self.name,
                project=self.name,
            )

    def _Rebase(self, upstream, onto=None):
        cmd = ["rebase"]
        if onto is not None:
            cmd.extend(["--onto", onto])
        cmd.append(upstream)
        if GitCommand(self, cmd).Wait() != 0:
            raise GitError(
                "%s rebase %s " % (self.name, upstream), project=self.name
            )

    def _FastForward(self, head, ffonly=False):
        cmd = ["merge", "--no-stat", head]
        if ffonly:
            cmd.append("--ff-only")
        if GitCommand(self, cmd).Wait() != 0:
            raise GitError(
                "%s merge %s " % (self.name, head), project=self.name
            )

    def _InitGitDir(self, mirror_git=None, force_sync=False, quiet=False):
        init_git_dir = not os.path.exists(self.gitdir)
        init_obj_dir = not os.path.exists(self.objdir)
        try:
            # Initialize the bare repository, which contains all of the objects.
            if init_obj_dir:
                os.makedirs(self.objdir)
                self.bare_objdir.init()

                self._UpdateHooks(quiet=quiet)

                if self.use_git_worktrees:
                    # Enable per-worktree config file support if possible.  This
                    # is more a nice-to-have feature for users rather than a
                    # hard requirement.
                    if git_require((2, 20, 0)):
                        self.EnableRepositoryExtension("worktreeConfig")

            # If we have a separate directory to hold refs, initialize it as
            # well.
            if self.objdir != self.gitdir:
                if init_git_dir:
                    os.makedirs(self.gitdir)

                if init_obj_dir or init_git_dir:
                    self._ReferenceGitDir(
                        self.objdir, self.gitdir, copy_all=True
                    )
                try:
                    self._CheckDirReference(self.objdir, self.gitdir)
                except GitError as e:
                    if force_sync:
                        logger.error(
                            "Retrying clone after deleting %s", self.gitdir
                        )
                        try:
                            platform_utils.rmtree(
                                platform_utils.realpath(self.gitdir)
                            )
                            if self.worktree and os.path.exists(
                                platform_utils.realpath(self.worktree)
                            ):
                                platform_utils.rmtree(
                                    platform_utils.realpath(self.worktree)
                                )
                            return self._InitGitDir(
                                mirror_git=mirror_git,
                                force_sync=False,
                                quiet=quiet,
                            )
                        except Exception:
                            raise e
                    raise e

            if init_git_dir:
                mp = self.manifest.manifestProject
                ref_dir = mp.reference or ""

                def _expanded_ref_dirs():
                    """Iterate through possible git reference dir paths."""
                    name = self.name + ".git"
                    yield mirror_git or os.path.join(ref_dir, name)
                    for prefix in "", self.remote.name:
                        yield os.path.join(
                            ref_dir, ".repo", "project-objects", prefix, name
                        )
                        yield os.path.join(
                            ref_dir, ".repo", "worktrees", prefix, name
                        )

                if ref_dir or mirror_git:
                    found_ref_dir = None
                    for path in _expanded_ref_dirs():
                        if os.path.exists(path):
                            found_ref_dir = path
                            break
                    ref_dir = found_ref_dir

                    if ref_dir:
                        if not os.path.isabs(ref_dir):
                            # The alternate directory is relative to the object
                            # database.
                            ref_dir = os.path.relpath(
                                ref_dir, os.path.join(self.objdir, "objects")
                            )
                        _lwrite(
                            os.path.join(
                                self.objdir, "objects/info/alternates"
                            ),
                            os.path.join(ref_dir, "objects") + "\n",
                        )

                m = self.manifest.manifestProject.config
                for key in ["user.name", "user.email"]:
                    if m.Has(key, include_defaults=False):
                        self.config.SetString(key, m.GetString(key))
                if not self.manifest.EnableGitLfs:
                    self.config.SetString(
                        "filter.lfs.smudge", "git-lfs smudge --skip -- %f"
                    )
                    self.config.SetString(
                        "filter.lfs.process", "git-lfs filter-process --skip"
                    )
                self.config.SetBoolean(
                    "core.bare", True if self.manifest.IsMirror else None
                )
        except Exception:
            if init_obj_dir and os.path.exists(self.objdir):
                platform_utils.rmtree(self.objdir)
            if init_git_dir and os.path.exists(self.gitdir):
                platform_utils.rmtree(self.gitdir)
            raise

    def _UpdateHooks(self, quiet=False):
        if os.path.exists(self.objdir):
            self._InitHooks(quiet=quiet)

    def _InitHooks(self, quiet=False):
        hooks = platform_utils.realpath(os.path.join(self.objdir, "hooks"))
        if not os.path.exists(hooks):
            os.makedirs(hooks)

        # Delete sample hooks.  They're noise.
        for hook in glob.glob(os.path.join(hooks, "*.sample")):
            try:
                platform_utils.remove(hook, missing_ok=True)
            except PermissionError:
                pass

        for stock_hook in _ProjectHooks():
            name = os.path.basename(stock_hook)

            if (
                name in ("commit-msg",)
                and not self.remote.review
                and self is not self.manifest.manifestProject
            ):
                # Don't install a Gerrit Code Review hook if this
                # project does not appear to use it for reviews.
                #
                # Since the manifest project is one of those, but also
                # managed through gerrit, it's excluded.
                continue

            dst = os.path.join(hooks, name)
            if platform_utils.islink(dst):
                continue
            if os.path.exists(dst):
                # If the files are the same, we'll leave it alone.  We create
                # symlinks below by default but fallback to hardlinks if the OS
                # blocks them. So if we're here, it's probably because we made a
                # hardlink below.
                if not filecmp.cmp(stock_hook, dst, shallow=False):
                    if not quiet:
                        logger.warn(
                            "warn: %s: Not replacing locally modified %s hook",
                            self.RelPath(local=False),
                            name,
                        )
                continue
            try:
                platform_utils.symlink(
                    os.path.relpath(stock_hook, os.path.dirname(dst)), dst
                )
            except OSError as e:
                if e.errno == errno.EPERM:
                    try:
                        os.link(stock_hook, dst)
                    except OSError:
                        raise GitError(
                            self._get_symlink_error_message(), project=self.name
                        )
                else:
                    raise

    def _InitRemote(self):
        if self.remote.url:
            remote = self.GetRemote()
            remote.url = self.remote.url
            remote.pushUrl = self.remote.pushUrl
            remote.review = self.remote.review
            remote.projectname = self.name

            if self.worktree:
                remote.ResetFetch(mirror=False)
            else:
                remote.ResetFetch(mirror=True)
            remote.Save()

    def _InitMRef(self):
        """Initialize the pseudo m/<manifest branch> ref."""
        if self.manifest.branch:
            if self.use_git_worktrees:
                # Set up the m/ space to point to the worktree-specific ref
                # space. We'll update the worktree-specific ref space on each
                # checkout.
                ref = R_M + self.manifest.branch
                if not self.bare_ref.symref(ref):
                    self.bare_git.symbolic_ref(
                        "-m",
                        "redirecting to worktree scope",
                        ref,
                        R_WORKTREE_M + self.manifest.branch,
                    )

                # We can't update this ref with git worktrees until it exists.
                # We'll wait until the initial checkout to set it.
                if not os.path.exists(self.worktree):
                    return

                base = R_WORKTREE_M
                active_git = self.work_git

                self._InitAnyMRef(HEAD, self.bare_git, detach=True)
            else:
                base = R_M
                active_git = self.bare_git

            self._InitAnyMRef(base + self.manifest.branch, active_git)

    def _InitMirrorHead(self):
        self._InitAnyMRef(HEAD, self.bare_git)

    def _InitAnyMRef(self, ref, active_git, detach=False):
        """Initialize |ref| in |active_git| to the value in the manifest.

        This points |ref| to the <project> setting in the manifest.

        Args:
            ref: The branch to update.
            active_git: The git repository to make updates in.
            detach: Whether to update target of symbolic refs, or overwrite the
                ref directly (and thus make it non-symbolic).
        """
        cur = self.bare_ref.symref(ref)

        if self.revisionId:
            if cur != "" or self.bare_ref.get(ref) != self.revisionId:
                msg = "manifest set to %s" % self.revisionId
                dst = self.revisionId + "^0"
                active_git.UpdateRef(ref, dst, message=msg, detach=True)
        else:
            remote = self.GetRemote()
            dst = remote.ToLocal(self.revisionExpr)
            if cur != dst:
                msg = "manifest set to %s" % self.revisionExpr
                if detach:
                    active_git.UpdateRef(ref, dst, message=msg, detach=True)
                else:
                    active_git.symbolic_ref("-m", msg, ref, dst)

    def _CheckDirReference(self, srcdir, destdir):
        # Git worktrees don't use symlinks to share at all.
        if self.use_git_worktrees:
            return

        for name in self.shareable_dirs:
            # Try to self-heal a bit in simple cases.
            dst_path = os.path.join(destdir, name)
            src_path = os.path.join(srcdir, name)

            dst = platform_utils.realpath(dst_path)
            if os.path.lexists(dst):
                src = platform_utils.realpath(src_path)
                # Fail if the links are pointing to the wrong place.
                if src != dst:
                    logger.error(
                        "error: %s is different in %s vs %s",
                        name,
                        destdir,
                        srcdir,
                    )
                    raise GitError(
                        "--force-sync not enabled; cannot overwrite a local "
                        "work tree. If you're comfortable with the "
                        "possibility of losing the work tree's git metadata,"
                        " use `repo sync --force-sync {0}` to "
                        "proceed.".format(self.RelPath(local=False)),
                        project=self.name,
                    )

    def _ReferenceGitDir(self, gitdir, dotgit, copy_all):
        """Update |dotgit| to reference |gitdir|, using symlinks where possible.

        Args:
            gitdir: The bare git repository. Must already be initialized.
            dotgit: The repository you would like to initialize.
            copy_all: If true, copy all remaining files from |gitdir| ->
                |dotgit|. This saves you the effort of initializing |dotgit|
                yourself.
        """
        symlink_dirs = self.shareable_dirs[:]
        to_symlink = symlink_dirs

        to_copy = []
        if copy_all:
            to_copy = platform_utils.listdir(gitdir)

        dotgit = platform_utils.realpath(dotgit)
        for name in set(to_copy).union(to_symlink):
            try:
                src = platform_utils.realpath(os.path.join(gitdir, name))
                dst = os.path.join(dotgit, name)

                if os.path.lexists(dst):
                    continue

                # If the source dir doesn't exist, create an empty dir.
                if name in symlink_dirs and not os.path.lexists(src):
                    os.makedirs(src)

                if name in to_symlink:
                    platform_utils.symlink(
                        os.path.relpath(src, os.path.dirname(dst)), dst
                    )
                elif copy_all and not platform_utils.islink(dst):
                    if platform_utils.isdir(src):
                        shutil.copytree(src, dst)
                    elif os.path.isfile(src):
                        shutil.copy(src, dst)

            except OSError as e:
                if e.errno == errno.EPERM:
                    raise DownloadError(self._get_symlink_error_message())
                else:
                    raise

    def _InitGitWorktree(self):
        """Init the project using git worktrees."""
        self.bare_git.worktree("prune")
        self.bare_git.worktree(
            "add",
            "-ff",
            "--checkout",
            "--detach",
            "--lock",
            self.worktree,
            self.GetRevisionId(),
        )

        # Rewrite the internal state files to use relative paths between the
        # checkouts & worktrees.
        dotgit = os.path.join(self.worktree, ".git")
        with open(dotgit, "r") as fp:
            # Figure out the checkout->worktree path.
            setting = fp.read()
            assert setting.startswith("gitdir:")
            git_worktree_path = setting.split(":", 1)[1].strip()
        # Some platforms (e.g. Windows) won't let us update dotgit in situ
        # because of file permissions.  Delete it and recreate it from scratch
        # to avoid.
        platform_utils.remove(dotgit)
        # Use relative path from checkout->worktree & maintain Unix line endings
        # on all OS's to match git behavior.
        with open(dotgit, "w", newline="\n") as fp:
            print(
                "gitdir:",
                os.path.relpath(git_worktree_path, self.worktree),
                file=fp,
            )
        # Use relative path from worktree->checkout & maintain Unix line endings
        # on all OS's to match git behavior.
        with open(
            os.path.join(git_worktree_path, "gitdir"), "w", newline="\n"
        ) as fp:
            print(os.path.relpath(dotgit, git_worktree_path), file=fp)

        self._InitMRef()

    def _InitWorkTree(self, force_sync=False, submodules=False):
        """Setup the worktree .git path.

        This is the user-visible path like src/foo/.git/.

        With non-git-worktrees, this will be a symlink to the .repo/projects/
        path. With git-worktrees, this will be a .git file using "gitdir: ..."
        syntax.

        Older checkouts had .git/ directories.  If we see that, migrate it.

        This also handles changes in the manifest.  Maybe this project was
        backed by "foo/bar" on the server, but now it's "new/foo/bar".  We have
        to update the path we point to under .repo/projects/ to match.
        """
        dotgit = os.path.join(self.worktree, ".git")

        # If using an old layout style (a directory), migrate it.
        if not platform_utils.islink(dotgit) and platform_utils.isdir(dotgit):
            self._MigrateOldWorkTreeGitDir(dotgit, project=self.name)

        init_dotgit = not os.path.exists(dotgit)
        if self.use_git_worktrees:
            if init_dotgit:
                self._InitGitWorktree()
                self._CopyAndLinkFiles()
        else:
            if not init_dotgit:
                # See if the project has changed.
                if platform_utils.realpath(
                    self.gitdir
                ) != platform_utils.realpath(dotgit):
                    platform_utils.remove(dotgit)

            if init_dotgit or not os.path.exists(dotgit):
                os.makedirs(self.worktree, exist_ok=True)
                platform_utils.symlink(
                    os.path.relpath(self.gitdir, self.worktree), dotgit
                )

            if init_dotgit:
                _lwrite(
                    os.path.join(dotgit, HEAD), "%s\n" % self.GetRevisionId()
                )

                # Finish checking out the worktree.
                cmd = ["read-tree", "--reset", "-u", "-v", HEAD]
                if GitCommand(self, cmd).Wait() != 0:
                    raise GitError(
                        "Cannot initialize work tree for " + self.name,
                        project=self.name,
                    )

                if submodules:
                    self._SyncSubmodules(quiet=True)
                self._CopyAndLinkFiles()

    @classmethod
    def _MigrateOldWorkTreeGitDir(cls, dotgit, project=None):
        """Migrate the old worktree .git/ dir style to a symlink.

        This logic specifically only uses state from |dotgit| to figure out
        where to move content and not |self|.  This way if the backing project
        also changed places, we only do the .git/ dir to .git symlink migration
        here.  The path updates will happen independently.
        """
        # Figure out where in .repo/projects/ it's pointing to.
        if not os.path.islink(os.path.join(dotgit, "refs")):
            raise GitError(
                f"{dotgit}: unsupported checkout state", project=project
            )
        gitdir = os.path.dirname(os.path.realpath(os.path.join(dotgit, "refs")))

        # Remove known symlink paths that exist in .repo/projects/.
        KNOWN_LINKS = {
            "config",
            "description",
            "hooks",
            "info",
            "logs",
            "objects",
            "packed-refs",
            "refs",
            "rr-cache",
            "shallow",
            "svn",
        }
        # Paths that we know will be in both, but are safe to clobber in
        # .repo/projects/.
        SAFE_TO_CLOBBER = {
            "COMMIT_EDITMSG",
            "FETCH_HEAD",
            "HEAD",
            "gc.log",
            "gitk.cache",
            "index",
            "ORIG_HEAD",
        }

        # First see if we'd succeed before starting the migration.
        unknown_paths = []
        for name in platform_utils.listdir(dotgit):
            # Ignore all temporary/backup names.  These are common with vim &
            # emacs.
            if name.endswith("~") or (name[0] == "#" and name[-1] == "#"):
                continue

            dotgit_path = os.path.join(dotgit, name)
            if name in KNOWN_LINKS:
                if not platform_utils.islink(dotgit_path):
                    unknown_paths.append(f"{dotgit_path}: should be a symlink")
            else:
                gitdir_path = os.path.join(gitdir, name)
                if name not in SAFE_TO_CLOBBER and os.path.exists(gitdir_path):
                    unknown_paths.append(
                        f"{dotgit_path}: unknown file; please file a bug"
                    )
        if unknown_paths:
            raise GitError(
                "Aborting migration: " + "\n".join(unknown_paths),
                project=project,
            )

        # Now walk the paths and sync the .git/ to .repo/projects/.
        for name in platform_utils.listdir(dotgit):
            dotgit_path = os.path.join(dotgit, name)

            # Ignore all temporary/backup names.  These are common with vim &
            # emacs.
            if name.endswith("~") or (name[0] == "#" and name[-1] == "#"):
                platform_utils.remove(dotgit_path)
            elif name in KNOWN_LINKS:
                platform_utils.remove(dotgit_path)
            else:
                gitdir_path = os.path.join(gitdir, name)
                platform_utils.remove(gitdir_path, missing_ok=True)
                platform_utils.rename(dotgit_path, gitdir_path)

        # Now that the dir should be empty, clear it out, and symlink it over.
        platform_utils.rmdir(dotgit)
        platform_utils.symlink(
            os.path.relpath(gitdir, os.path.dirname(dotgit)), dotgit
        )

    def _get_symlink_error_message(self):
        if platform_utils.isWindows():
            return (
                "Unable to create symbolic link. Please re-run the command as "
                "Administrator, or see "
                "https://github.com/git-for-windows/git/wiki/Symbolic-Links "
                "for other options."
            )
        return "filesystem must support symlinks"

    def _revlist(self, *args, **kw):
        a = []
        a.extend(args)
        a.append("--")
        return self.work_git.rev_list(*a, **kw)

    @property
    def _allrefs(self):
        return self.bare_ref.all

    def _getLogs(
        self, rev1, rev2, oneline=False, color=True, pretty_format=None
    ):
        """Get logs between two revisions of this project."""
        comp = ".."
        if rev1:
            revs = [rev1]
            if rev2:
                revs.extend([comp, rev2])
            cmd = ["log", "".join(revs)]
            out = DiffColoring(self.config)
            if out.is_on and color:
                cmd.append("--color")
            if pretty_format is not None:
                cmd.append("--pretty=format:%s" % pretty_format)
            if oneline:
                cmd.append("--oneline")

            try:
                log = GitCommand(
                    self, cmd, capture_stdout=True, capture_stderr=True
                )
                if log.Wait() == 0:
                    return log.stdout
            except GitError:
                # worktree may not exist if groups changed for example. In that
                # case, try in gitdir instead.
                if not os.path.exists(self.worktree):
                    return self.bare_git.log(*cmd[1:])
                else:
                    raise
        return None

    def getAddedAndRemovedLogs(
        self, toProject, oneline=False, color=True, pretty_format=None
    ):
        """Get the list of logs from this revision to given revisionId"""
        logs = {}
        selfId = self.GetRevisionId(self._allrefs)
        toId = toProject.GetRevisionId(toProject._allrefs)

        logs["added"] = self._getLogs(
            selfId,
            toId,
            oneline=oneline,
            color=color,
            pretty_format=pretty_format,
        )
        logs["removed"] = self._getLogs(
            toId,
            selfId,
            oneline=oneline,
            color=color,
            pretty_format=pretty_format,
        )
        return logs

    class _GitGetByExec(object):
        def __init__(self, project, bare, gitdir):
            self._project = project
            self._bare = bare
            self._gitdir = gitdir

        # __getstate__ and __setstate__ are required for pickling because
        # __getattr__ exists.
        def __getstate__(self):
            return (self._project, self._bare, self._gitdir)

        def __setstate__(self, state):
            self._project, self._bare, self._gitdir = state

        def LsOthers(self):
            p = GitCommand(
                self._project,
                ["ls-files", "-z", "--others", "--exclude-standard"],
                bare=False,
                gitdir=self._gitdir,
                capture_stdout=True,
                capture_stderr=True,
            )
            if p.Wait() == 0:
                out = p.stdout
                if out:
                    # Backslash is not anomalous.
                    return out[:-1].split("\0")
            return []

        def DiffZ(self, name, *args):
            cmd = [name]
            cmd.append("-z")
            cmd.append("--ignore-submodules")
            cmd.extend(args)
            p = GitCommand(
                self._project,
                cmd,
                gitdir=self._gitdir,
                bare=False,
                capture_stdout=True,
                capture_stderr=True,
            )
            p.Wait()
            r = {}
            out = p.stdout
            if out:
                out = iter(out[:-1].split("\0"))
                while out:
                    try:
                        info = next(out)
                        path = next(out)
                    except StopIteration:
                        break

                    class _Info(object):
                        def __init__(self, path, omode, nmode, oid, nid, state):
                            self.path = path
                            self.src_path = None
                            self.old_mode = omode
                            self.new_mode = nmode
                            self.old_id = oid
                            self.new_id = nid

                            if len(state) == 1:
                                self.status = state
                                self.level = None
                            else:
                                self.status = state[:1]
                                self.level = state[1:]
                                while self.level.startswith("0"):
                                    self.level = self.level[1:]

                    info = info[1:].split(" ")
                    info = _Info(path, *info)
                    if info.status in ("R", "C"):
                        info.src_path = info.path
                        info.path = next(out)
                    r[info.path] = info
            return r

        def GetDotgitPath(self, subpath=None):
            """Return the full path to the .git dir.

            As a convenience, append |subpath| if provided.
            """
            if self._bare:
                dotgit = self._gitdir
            else:
                dotgit = os.path.join(self._project.worktree, ".git")
                if os.path.isfile(dotgit):
                    # Git worktrees use a "gitdir:" syntax to point to the
                    # scratch space.
                    with open(dotgit) as fp:
                        setting = fp.read()
                    assert setting.startswith("gitdir:")
                    gitdir = setting.split(":", 1)[1].strip()
                    dotgit = os.path.normpath(
                        os.path.join(self._project.worktree, gitdir)
                    )

            return dotgit if subpath is None else os.path.join(dotgit, subpath)

        def GetHead(self):
            """Return the ref that HEAD points to."""
            path = self.GetDotgitPath(subpath=HEAD)
            try:
                with open(path) as fd:
                    line = fd.readline()
            except IOError as e:
                raise NoManifestException(path, str(e))
            try:
                line = line.decode()
            except AttributeError:
                pass
            if line.startswith("ref: "):
                return line[5:-1]
            return line[:-1]

        def SetHead(self, ref, message=None):
            cmdv = []
            if message is not None:
                cmdv.extend(["-m", message])
            cmdv.append(HEAD)
            cmdv.append(ref)
            self.symbolic_ref(*cmdv)

        def DetachHead(self, new, message=None):
            cmdv = ["--no-deref"]
            if message is not None:
                cmdv.extend(["-m", message])
            cmdv.append(HEAD)
            cmdv.append(new)
            self.update_ref(*cmdv)

        def UpdateRef(self, name, new, old=None, message=None, detach=False):
            cmdv = []
            if message is not None:
                cmdv.extend(["-m", message])
            if detach:
                cmdv.append("--no-deref")
            cmdv.append(name)
            cmdv.append(new)
            if old is not None:
                cmdv.append(old)
            self.update_ref(*cmdv)

        def DeleteRef(self, name, old=None):
            if not old:
                old = self.rev_parse(name)
            self.update_ref("-d", name, old)
            self._project.bare_ref.deleted(name)

        def rev_list(self, *args, log_as_error=True, **kw):
            if "format" in kw:
                cmdv = ["log", "--pretty=format:%s" % kw["format"]]
            else:
                cmdv = ["rev-list"]
            cmdv.extend(args)
            p = GitCommand(
                self._project,
                cmdv,
                bare=self._bare,
                gitdir=self._gitdir,
                capture_stdout=True,
                capture_stderr=True,
                verify_command=True,
                log_as_error=log_as_error,
            )
            p.Wait()
            return p.stdout.splitlines()

        def __getattr__(self, name):
            """Allow arbitrary git commands using pythonic syntax.

            This allows you to do things like:
                git_obj.rev_parse('HEAD')

            Since we don't have a 'rev_parse' method defined, the __getattr__
            will run.  We'll replace the '_' with a '-' and try to run a git
            command. Any other positional arguments will be passed to the git
            command, and the following keyword arguments are supported:
                config: An optional dict of git config options to be passed with
                    '-c'.

            Args:
                name: The name of the git command to call.  Any '_' characters
                    will be replaced with '-'.

            Returns:
                A callable object that will try to call git with the named
                command.
            """
            name = name.replace("_", "-")

            def runner(*args, log_as_error=True, **kwargs):
                cmdv = []
                config = kwargs.pop("config", None)
                for k in kwargs:
                    raise TypeError(
                        "%s() got an unexpected keyword argument %r" % (name, k)
                    )
                if config is not None:
                    for k, v in config.items():
                        cmdv.append("-c")
                        cmdv.append("%s=%s" % (k, v))
                cmdv.append(name)
                cmdv.extend(args)
                p = GitCommand(
                    self._project,
                    cmdv,
                    bare=self._bare,
                    gitdir=self._gitdir,
                    capture_stdout=True,
                    capture_stderr=True,
                    verify_command=True,
                    log_as_error=log_as_error,
                )
                p.Wait()
                r = p.stdout
                if r.endswith("\n") and r.index("\n") == len(r) - 1:
                    return r[:-1]
                return r

            return runner


class LocalSyncFail(RepoError):
    """Default error when there is an Sync_LocalHalf error."""


class _PriorSyncFailedError(LocalSyncFail):
    def __str__(self):
        return "prior sync failed; rebase still in progress"


class _DirtyError(LocalSyncFail):
    def __str__(self):
        return "contains uncommitted changes"


class _InfoMessage(object):
    def __init__(self, project, text):
        self.project = project
        self.text = text

    def Print(self, syncbuf):
        syncbuf.out.info(
            "%s/: %s", self.project.RelPath(local=False), self.text
        )
        syncbuf.out.nl()


class _Failure(object):
    def __init__(self, project, why):
        self.project = project
        self.why = why

    def Print(self, syncbuf):
        syncbuf.out.fail(
            "error: %s/: %s", self.project.RelPath(local=False), str(self.why)
        )
        syncbuf.out.nl()


class _Later(object):
    def __init__(self, project, action):
        self.project = project
        self.action = action

    def Run(self, syncbuf):
        out = syncbuf.out
        out.project("project %s/", self.project.RelPath(local=False))
        out.nl()
        try:
            self.action()
            out.nl()
            return True
        except GitError:
            out.nl()
            return False


class _SyncColoring(Coloring):
    def __init__(self, config):
        super().__init__(config, "reposync")
        self.project = self.printer("header", attr="bold")
        self.info = self.printer("info")
        self.fail = self.printer("fail", fg="red")


class SyncBuffer(object):
    def __init__(self, config, detach_head=False):
        self._messages = []
        self._failures = []
        self._later_queue1 = []
        self._later_queue2 = []

        self.out = _SyncColoring(config)
        self.out.redirect(sys.stderr)

        self.detach_head = detach_head
        self.clean = True
        self.recent_clean = True

    def info(self, project, fmt, *args):
        self._messages.append(_InfoMessage(project, fmt % args))

    def fail(self, project, err=None):
        self._failures.append(_Failure(project, err))
        self._MarkUnclean()

    def later1(self, project, what):
        self._later_queue1.append(_Later(project, what))

    def later2(self, project, what):
        self._later_queue2.append(_Later(project, what))

    def Finish(self):
        self._PrintMessages()
        self._RunLater()
        self._PrintMessages()
        return self.clean

    def Recently(self):
        recent_clean = self.recent_clean
        self.recent_clean = True
        return recent_clean

    def _MarkUnclean(self):
        self.clean = False
        self.recent_clean = False

    def _RunLater(self):
        for q in ["_later_queue1", "_later_queue2"]:
            if not self._RunQueue(q):
                return

    def _RunQueue(self, queue):
        for m in getattr(self, queue):
            if not m.Run(self):
                self._MarkUnclean()
                return False
        setattr(self, queue, [])
        return True

    def _PrintMessages(self):
        if self._messages or self._failures:
            if os.isatty(2):
                self.out.write(progress.CSI_ERASE_LINE)
            self.out.write("\r")

        for m in self._messages:
            m.Print(self)
        for m in self._failures:
            m.Print(self)

        self._messages = []
        self._failures = []


class MetaProject(Project):
    """A special project housed under .repo."""

    def __init__(self, manifest, name, gitdir, worktree):
        Project.__init__(
            self,
            manifest=manifest,
            name=name,
            gitdir=gitdir,
            objdir=gitdir,
            worktree=worktree,
            remote=RemoteSpec("origin"),
            relpath=".repo/%s" % name,
            revisionExpr="refs/heads/master",
            revisionId=None,
            groups=None,
        )

    def PreSync(self):
        if self.Exists:
            cb = self.CurrentBranch
            if cb:
                base = self.GetBranch(cb).merge
                if base:
                    self.revisionExpr = base
                    self.revisionId = None

    @property
    def HasChanges(self):
        """Has the remote received new commits not yet checked out?"""
        if not self.remote or not self.revisionExpr:
            return False

        all_refs = self.bare_ref.all
        revid = self.GetRevisionId(all_refs)
        head = self.work_git.GetHead()
        if head.startswith(R_HEADS):
            try:
                head = all_refs[head]
            except KeyError:
                head = None

        if revid == head:
            return False
        elif self._revlist(not_rev(HEAD), revid):
            return True
        return False


class RepoProject(MetaProject):
    """The MetaProject for repo itself."""

    @property
    def LastFetch(self):
        try:
            fh = os.path.join(self.gitdir, "FETCH_HEAD")
            return os.path.getmtime(fh)
        except OSError:
            return 0


class ManifestProject(MetaProject):
    """The MetaProject for manifests."""

    def MetaBranchSwitch(self, submodules=False):
        """Prepare for manifest branch switch."""

        # detach and delete manifest branch, allowing a new
        # branch to take over
        syncbuf = SyncBuffer(self.config, detach_head=True)
        self.Sync_LocalHalf(syncbuf, submodules=submodules)
        syncbuf.Finish()

        return (
            GitCommand(
                self,
                ["update-ref", "-d", "refs/heads/default"],
                capture_stdout=True,
                capture_stderr=True,
            ).Wait()
            == 0
        )

    @property
    def standalone_manifest_url(self):
        """The URL of the standalone manifest, or None."""
        return self.config.GetString("manifest.standalone")

    @property
    def manifest_groups(self):
        """The manifest groups string."""
        return self.config.GetString("manifest.groups")

    @property
    def reference(self):
        """The --reference for this manifest."""
        return self.config.GetString("repo.reference")

    @property
    def dissociate(self):
        """Whether to dissociate."""
        return self.config.GetBoolean("repo.dissociate")

    @property
    def archive(self):
        """Whether we use archive."""
        return self.config.GetBoolean("repo.archive")

    @property
    def mirror(self):
        """Whether we use mirror."""
        return self.config.GetBoolean("repo.mirror")

    @property
    def use_worktree(self):
        """Whether we use worktree."""
        return self.config.GetBoolean("repo.worktree")

    @property
    def clone_bundle(self):
        """Whether we use clone_bundle."""
        return self.config.GetBoolean("repo.clonebundle")

    @property
    def submodules(self):
        """Whether we use submodules."""
        return self.config.GetBoolean("repo.submodules")

    @property
    def git_lfs(self):
        """Whether we use git_lfs."""
        return self.config.GetBoolean("repo.git-lfs")

    @property
    def use_superproject(self):
        """Whether we use superproject."""
        return self.config.GetBoolean("repo.superproject")

    @property
    def partial_clone(self):
        """Whether this is a partial clone."""
        return self.config.GetBoolean("repo.partialclone")

    @property
    def depth(self):
        """Partial clone depth."""
        return self.config.GetString("repo.depth")

    @property
    def clone_filter(self):
        """The clone filter."""
        return self.config.GetString("repo.clonefilter")

    @property
    def partial_clone_exclude(self):
        """Partial clone exclude string"""
        return self.config.GetString("repo.partialcloneexclude")

    @property
    def clone_filter_for_depth(self):
        """Replace shallow clone with partial clone."""
        return self.config.GetString("repo.clonefilterfordepth")

    @property
    def manifest_platform(self):
        """The --platform argument from `repo init`."""
        return self.config.GetString("manifest.platform")

    @property
    def _platform_name(self):
        """Return the name of the platform."""
        return platform.system().lower()

    def SyncWithPossibleInit(
        self,
        submanifest,
        verbose=False,
        current_branch_only=False,
        tags="",
        git_event_log=None,
    ):
        """Sync a manifestProject, possibly for the first time.

        Call Sync() with arguments from the most recent `repo init`.  If this is
        a new sub manifest, then inherit options from the parent's
        manifestProject.

        This is used by subcmds.Sync() to do an initial download of new sub
        manifests.

        Args:
            submanifest: an XmlSubmanifest, the submanifest to re-sync.
            verbose: a boolean, whether to show all output, rather than only
                errors.
            current_branch_only: a boolean, whether to only fetch the current
                manifest branch from the server.
            tags: a boolean, whether to fetch tags.
            git_event_log: an EventLog, for git tracing.
        """
        # TODO(lamontjones): when refactoring sync (and init?) consider how to
        # better get the init options that we should use for new submanifests
        # that are added when syncing an existing workspace.
        git_event_log = git_event_log or EventLog()
        spec = submanifest.ToSubmanifestSpec()
        # Use the init options from the existing manifestProject, or the parent
        # if it doesn't exist.
        #
        # Today, we only support changing manifest_groups on the sub-manifest,
        # with no supported-for-the-user way to change the other arguments from
        # those specified by the outermost manifest.
        #
        # TODO(lamontjones): determine which of these should come from the
        # outermost manifest and which should come from the parent manifest.
        mp = self if self.Exists else submanifest.parent.manifestProject
        return self.Sync(
            manifest_url=spec.manifestUrl,
            manifest_branch=spec.revision,
            standalone_manifest=mp.standalone_manifest_url,
            groups=mp.manifest_groups,
            platform=mp.manifest_platform,
            mirror=mp.mirror,
            dissociate=mp.dissociate,
            reference=mp.reference,
            worktree=mp.use_worktree,
            submodules=mp.submodules,
            archive=mp.archive,
            partial_clone=mp.partial_clone,
            clone_filter=mp.clone_filter,
            partial_clone_exclude=mp.partial_clone_exclude,
            clone_bundle=mp.clone_bundle,
            git_lfs=mp.git_lfs,
            use_superproject=mp.use_superproject,
            verbose=verbose,
            current_branch_only=current_branch_only,
            tags=tags,
            depth=mp.depth,
            git_event_log=git_event_log,
            manifest_name=spec.manifestName,
            this_manifest_only=True,
            outer_manifest=False,
            clone_filter_for_depth=mp.clone_filter_for_depth,
        )

    def Sync(
        self,
        _kwargs_only=(),
        manifest_url="",
        manifest_branch=None,
        standalone_manifest=False,
        groups="",
        mirror=False,
        reference="",
        dissociate=False,
        worktree=False,
        submodules=False,
        archive=False,
        partial_clone=None,
        depth=None,
        clone_filter="blob:none",
        partial_clone_exclude=None,
        clone_bundle=None,
        git_lfs=None,
        use_superproject=None,
        verbose=False,
        current_branch_only=False,
        git_event_log=None,
        platform="",
        manifest_name="default.xml",
        tags="",
        this_manifest_only=False,
        outer_manifest=True,
        clone_filter_for_depth=None,
    ):
        """Sync the manifest and all submanifests.

        Args:
            manifest_url: a string, the URL of the manifest project.
            manifest_branch: a string, the manifest branch to use.
            standalone_manifest: a boolean, whether to store the manifest as a
                static file.
            groups: a string, restricts the checkout to projects with the
                specified groups.
            mirror: a boolean, whether to create a mirror of the remote
                repository.
            reference: a string, location of a repo instance to use as a
                reference.
            dissociate: a boolean, whether to dissociate from reference mirrors
                after clone.
            worktree: a boolean, whether to use git-worktree to manage projects.
            submodules: a boolean, whether sync submodules associated with the
                manifest project.
            archive: a boolean, whether to checkout each project as an archive.
                See git-archive.
            partial_clone: a boolean, whether to perform a partial clone.
            depth: an int, how deep of a shallow clone to create.
            clone_filter: a string, filter to use with partial_clone.
            partial_clone_exclude : a string, comma-delimeted list of project
                names to exclude from partial clone.
            clone_bundle: a boolean, whether to enable /clone.bundle on
                HTTP/HTTPS.
            git_lfs: a boolean, whether to enable git LFS support.
            use_superproject: a boolean, whether to use the manifest
                superproject to sync projects.
            verbose: a boolean, whether to show all output, rather than only
                errors.
            current_branch_only: a boolean, whether to only fetch the current
                manifest branch from the server.
            platform: a string, restrict the checkout to projects with the
                specified platform group.
            git_event_log: an EventLog, for git tracing.
            tags: a boolean, whether to fetch tags.
            manifest_name: a string, the name of the manifest file to use.
            this_manifest_only: a boolean, whether to only operate on the
                current sub manifest.
            outer_manifest: a boolean, whether to start at the outermost
                manifest.
            clone_filter_for_depth: a string, when specified replaces shallow
                clones with partial.

        Returns:
            a boolean, whether the sync was successful.
        """
        assert _kwargs_only == (), "Sync only accepts keyword arguments."

        groups = groups or self.manifest.GetDefaultGroupsStr(
            with_platform=False
        )
        platform = platform or "auto"
        git_event_log = git_event_log or EventLog()
        if outer_manifest and self.manifest.is_submanifest:
            # In a multi-manifest checkout, use the outer manifest unless we are
            # told not to.
            return self.client.outer_manifest.manifestProject.Sync(
                manifest_url=manifest_url,
                manifest_branch=manifest_branch,
                standalone_manifest=standalone_manifest,
                groups=groups,
                platform=platform,
                mirror=mirror,
                dissociate=dissociate,
                reference=reference,
                worktree=worktree,
                submodules=submodules,
                archive=archive,
                partial_clone=partial_clone,
                clone_filter=clone_filter,
                partial_clone_exclude=partial_clone_exclude,
                clone_bundle=clone_bundle,
                git_lfs=git_lfs,
                use_superproject=use_superproject,
                verbose=verbose,
                current_branch_only=current_branch_only,
                tags=tags,
                depth=depth,
                git_event_log=git_event_log,
                manifest_name=manifest_name,
                this_manifest_only=this_manifest_only,
                outer_manifest=False,
            )

        # If repo has already been initialized, we take -u with the absence of
        # --standalone-manifest to mean "transition to a standard repo set up",
        # which necessitates starting fresh.
        # If --standalone-manifest is set, we always tear everything down and
        # start anew.
        if self.Exists:
            was_standalone_manifest = self.config.GetString(
                "manifest.standalone"
            )
            if was_standalone_manifest and not manifest_url:
                logger.error(
                    "fatal: repo was initialized with a standlone manifest, "
                    "cannot be re-initialized without --manifest-url/-u"
                )
                return False

            if standalone_manifest or (
                was_standalone_manifest and manifest_url
            ):
                self.config.ClearCache()
                if self.gitdir and os.path.exists(self.gitdir):
                    platform_utils.rmtree(self.gitdir)
                if self.worktree and os.path.exists(self.worktree):
                    platform_utils.rmtree(self.worktree)

        is_new = not self.Exists
        if is_new:
            if not manifest_url:
                logger.error("fatal: manifest url is required.")
                return False

            if verbose:
                print(
                    "Downloading manifest from %s"
                    % (GitConfig.ForUser().UrlInsteadOf(manifest_url),),
                    file=sys.stderr,
                )

            # The manifest project object doesn't keep track of the path on the
            # server where this git is located, so let's save that here.
            mirrored_manifest_git = None
            if reference:
                manifest_git_path = urllib.parse.urlparse(manifest_url).path[1:]
                mirrored_manifest_git = os.path.join(
                    reference, manifest_git_path
                )
                if not mirrored_manifest_git.endswith(".git"):
                    mirrored_manifest_git += ".git"
                if not os.path.exists(mirrored_manifest_git):
                    mirrored_manifest_git = os.path.join(
                        reference, ".repo/manifests.git"
                    )

            self._InitGitDir(mirror_git=mirrored_manifest_git)

        # If standalone_manifest is set, mark the project as "standalone" --
        # we'll still do much of the manifests.git set up, but will avoid actual
        # syncs to a remote.
        if standalone_manifest:
            self.config.SetString("manifest.standalone", manifest_url)
        elif not manifest_url and not manifest_branch:
            # If -u is set and --standalone-manifest is not, then we're not in
            # standalone mode. Otherwise, use config to infer what we were in
            # the last init.
            standalone_manifest = bool(
                self.config.GetString("manifest.standalone")
            )
        if not standalone_manifest:
            self.config.SetString("manifest.standalone", None)

        self._ConfigureDepth(depth)

        # Set the remote URL before the remote branch as we might need it below.
        if manifest_url:
            r = self.GetRemote()
            r.url = manifest_url
            r.ResetFetch()
            r.Save()

        if not standalone_manifest:
            if manifest_branch:
                if manifest_branch == "HEAD":
                    manifest_branch = self.ResolveRemoteHead()
                    if manifest_branch is None:
                        logger.error("fatal: unable to resolve HEAD")
                        return False
                self.revisionExpr = manifest_branch
            else:
                if is_new:
                    default_branch = self.ResolveRemoteHead()
                    if default_branch is None:
                        # If the remote doesn't have HEAD configured, default to
                        # master.
                        default_branch = "refs/heads/master"
                    self.revisionExpr = default_branch
                else:
                    self.PreSync()

        groups = re.split(r"[,\s]+", groups or "")
        all_platforms = ["linux", "darwin", "windows"]
        platformize = lambda x: "platform-" + x
        if platform == "auto":
            if not mirror and not self.mirror:
                groups.append(platformize(self._platform_name))
        elif platform == "all":
            groups.extend(map(platformize, all_platforms))
        elif platform in all_platforms:
            groups.append(platformize(platform))
        elif platform != "none":
            logger.error("fatal: invalid platform flag", file=sys.stderr)
            return False
        self.config.SetString("manifest.platform", platform)

        groups = [x for x in groups if x]
        groupstr = ",".join(groups)
        if (
            platform == "auto"
            and groupstr == self.manifest.GetDefaultGroupsStr()
        ):
            groupstr = None
        self.config.SetString("manifest.groups", groupstr)

        if reference:
            self.config.SetString("repo.reference", reference)

        if dissociate:
            self.config.SetBoolean("repo.dissociate", dissociate)

        if worktree:
            if mirror:
                logger.error("fatal: --mirror and --worktree are incompatible")
                return False
            if submodules:
                logger.error(
                    "fatal: --submodules and --worktree are incompatible"
                )
                return False
            self.config.SetBoolean("repo.worktree", worktree)
            if is_new:
                self.use_git_worktrees = True
            logger.warn("warning: --worktree is experimental!")

        if archive:
            if is_new:
                self.config.SetBoolean("repo.archive", archive)
            else:
                logger.error(
                    "fatal: --archive is only supported when initializing a "
                    "new workspace."
                )
                logger.error(
                    "Either delete the .repo folder in this workspace, or "
                    "initialize in another location."
                )
                return False

        if mirror:
            if is_new:
                self.config.SetBoolean("repo.mirror", mirror)
            else:
                logger.error(
                    "fatal: --mirror is only supported when initializing a new "
                    "workspace."
                )
                logger.error(
                    "Either delete the .repo folder in this workspace, or "
                    "initialize in another location."
                )
                return False

        if partial_clone is not None:
            if mirror:
                logger.error(
                    "fatal: --mirror and --partial-clone are mutually "
                    "exclusive"
                )
                return False
            self.config.SetBoolean("repo.partialclone", partial_clone)
            if clone_filter:
                self.config.SetString("repo.clonefilter", clone_filter)
        elif self.partial_clone:
            clone_filter = self.clone_filter
        else:
            clone_filter = None

        if partial_clone_exclude is not None:
            self.config.SetString(
                "repo.partialcloneexclude", partial_clone_exclude
            )

        if clone_bundle is None:
            clone_bundle = False if partial_clone else True
        else:
            self.config.SetBoolean("repo.clonebundle", clone_bundle)

        if submodules:
            self.config.SetBoolean("repo.submodules", submodules)

        if git_lfs is not None:
            if git_lfs:
                git_require((2, 17, 0), fail=True, msg="Git LFS support")

            self.config.SetBoolean("repo.git-lfs", git_lfs)
            if not is_new:
                logger.warn(
                    "warning: Changing --git-lfs settings will only affect new "
                    "project checkouts.\n"
                    "         Existing projects will require manual updates.\n"
                )

        if clone_filter_for_depth is not None:
            self.ConfigureCloneFilterForDepth(clone_filter_for_depth)

        if use_superproject is not None:
            self.config.SetBoolean("repo.superproject", use_superproject)

        if not standalone_manifest:
            success = self.Sync_NetworkHalf(
                is_new=is_new,
                quiet=not verbose,
                verbose=verbose,
                clone_bundle=clone_bundle,
                current_branch_only=current_branch_only,
                tags=tags,
                submodules=submodules,
                clone_filter=clone_filter,
                partial_clone_exclude=self.manifest.PartialCloneExclude,
                clone_filter_for_depth=self.manifest.CloneFilterForDepth,
            ).success
            if not success:
                r = self.GetRemote()
                logger.error("fatal: cannot obtain manifest %s", r.url)

                # Better delete the manifest git dir if we created it; otherwise
                # next time (when user fixes problems) we won't go through the
                # "is_new" logic.
                if is_new:
                    platform_utils.rmtree(self.gitdir)
                return False

            if manifest_branch:
                self.MetaBranchSwitch(submodules=submodules)

            syncbuf = SyncBuffer(self.config)
            self.Sync_LocalHalf(syncbuf, submodules=submodules)
            syncbuf.Finish()

            if is_new or self.CurrentBranch is None:
                try:
                    self.StartBranch("default")
                except GitError as e:
                    msg = str(e)
                    logger.error(
                        "fatal: cannot create default in manifest %s", msg
                    )
                    return False

            if not manifest_name:
                logger.error("fatal: manifest name (-m) is required.")
                return False

        elif is_new:
            # This is a new standalone manifest.
            manifest_name = "default.xml"
            manifest_data = fetch.fetch_file(manifest_url, verbose=verbose)
            dest = os.path.join(self.worktree, manifest_name)
            os.makedirs(os.path.dirname(dest), exist_ok=True)
            with open(dest, "wb") as f:
                f.write(manifest_data)

        try:
            self.manifest.Link(manifest_name)
        except ManifestParseError as e:
            logger.error("fatal: manifest '%s' not available", manifest_name)
            logger.error("fatal: %s", e)
            return False

        if not this_manifest_only:
            for submanifest in self.manifest.submanifests.values():
                spec = submanifest.ToSubmanifestSpec()
                submanifest.repo_client.manifestProject.Sync(
                    manifest_url=spec.manifestUrl,
                    manifest_branch=spec.revision,
                    standalone_manifest=standalone_manifest,
                    groups=self.manifest_groups,
                    platform=platform,
                    mirror=mirror,
                    dissociate=dissociate,
                    reference=reference,
                    worktree=worktree,
                    submodules=submodules,
                    archive=archive,
                    partial_clone=partial_clone,
                    clone_filter=clone_filter,
                    partial_clone_exclude=partial_clone_exclude,
                    clone_bundle=clone_bundle,
                    git_lfs=git_lfs,
                    use_superproject=use_superproject,
                    verbose=verbose,
                    current_branch_only=current_branch_only,
                    tags=tags,
                    depth=depth,
                    git_event_log=git_event_log,
                    manifest_name=spec.manifestName,
                    this_manifest_only=False,
                    outer_manifest=False,
                )

        # Lastly, if the manifest has a <superproject> then have the
        # superproject sync it (if it will be used).
        if git_superproject.UseSuperproject(use_superproject, self.manifest):
            sync_result = self.manifest.superproject.Sync(git_event_log)
            if not sync_result.success:
                submanifest = ""
                if self.manifest.path_prefix:
                    submanifest = f"for {self.manifest.path_prefix} "
                logger.warn(
                    "warning: git update of superproject %s failed, "
                    "repo sync will not use superproject to fetch source; "
                    "while this error is not fatal, and you can continue to "
                    "run repo sync, please run repo init with the "
                    "--no-use-superproject option to stop seeing this warning",
                    submanifest,
                )
                if sync_result.fatal and use_superproject is not None:
                    return False

        return True

    def ConfigureCloneFilterForDepth(self, clone_filter_for_depth):
        """Configure clone filter to replace shallow clones.

        Args:
            clone_filter_for_depth: a string or None, e.g. 'blob:none' will
            disable shallow clones and replace with partial clone. None will
            enable shallow clones.
        """
        self.config.SetString(
            "repo.clonefilterfordepth", clone_filter_for_depth
        )

    def _ConfigureDepth(self, depth):
        """Configure the depth we'll sync down.

        Args:
            depth: an int, how deep of a partial clone to create.
        """
        # Opt.depth will be non-None if user actually passed --depth to repo
        # init.
        if depth is not None:
            if depth > 0:
                # Positive values will set the depth.
                depth = str(depth)
            else:
                # Negative numbers will clear the depth; passing None to
                # SetString will do that.
                depth = None

            # We store the depth in the main manifest project.
            self.config.SetString("repo.depth", depth)
