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

import collections
import contextlib
import functools
import http.cookiejar as cookielib
import io
import json
import multiprocessing
import netrc
import optparse
import os
from pathlib import Path
import shutil
import subprocess
import sys
import tempfile
import time
from typing import Dict, List, NamedTuple, Optional, Set, Tuple, Union
import urllib.error
import urllib.parse
import urllib.request
import xml.parsers.expat
import xmlrpc.client


try:
    import threading as _threading
except ImportError:
    import dummy_threading as _threading

try:
    import resource

    def _rlimit_nofile():
        return resource.getrlimit(resource.RLIMIT_NOFILE)

except ImportError:

    def _rlimit_nofile():
        return (256, 256)


from command import Command
from command import DEFAULT_LOCAL_JOBS
from command import MirrorSafeCommand
from command import WORKER_BATCH_SIZE
from error import GitError
from error import RepoChangedException
from error import RepoError
from error import RepoExitError
from error import RepoUnhandledExceptionError
from error import SyncError
from error import UpdateManifestError
import event_log
from git_command import git_require
from git_command import GitCommand
from git_config import GetUrlCookieFile
from git_refs import HEAD
from git_refs import R_HEADS
import git_superproject
from hooks import RepoHook
from manifest_xml import XmlManifest
import platform_utils
from progress import elapsed_str
from progress import jobs_str
from progress import Progress
from project import DeleteWorktreeError
from project import Project
from project import RemoteSpec
from project import SyncBuffer
from repo_logging import RepoLogger
from repo_trace import Trace
import ssh
from wrapper import Wrapper


_ONE_DAY_S = 24 * 60 * 60

_REPO_ALLOW_SHALLOW = os.environ.get("REPO_ALLOW_SHALLOW")

_BLOAT_PACK_COUNT_THRESHOLD = 10
_BLOAT_SIZE_PACK_THRESHOLD_KB = 10 * 1024 * 1024  # 10 GiB in KiB
_BLOAT_SIZE_GARBAGE_THRESHOLD_KB = 1 * 1024 * 1024  # 1 GiB in KiB

logger = RepoLogger(__file__)


def _SafeCheckoutOrder(checkouts: List[Project]) -> List[List[Project]]:
    """Generate a sequence of checkouts that is safe to perform.

    The client should checkout everything from n-th index before moving to
    n+1.

    This is only useful if manifest contains nested projects.

    E.g. if foo, foo/bar and foo/bar/baz are project paths, then foo needs to
    finish before foo/bar can proceed, and foo/bar needs to finish before
    foo/bar/baz.

    Discovered submodules have an additional constraint: sibling submodules in
    the same parent repository must not be checked out in parallel because they
    all run `git submodule init` against the same parent .git/config.
    """
    res = [[]]

    # depth_stack contains the current stack of parent paths together with the
    # effective checkout level assigned to each path.
    depth_stack = []
    submodule_parent_level = {}
    # Checkouts are iterated in the hierarchical order. That way, it can easily
    # be determined if the previous checkout is parent of the current checkout.
    # We are splitting by the path separator so the final result is
    # hierarchical, and not just lexicographical. For example, if the projects
    # are: foo, foo/bar, foo-bar, lexicographical order produces foo, foo-bar
    # and foo/bar, which doesn't work.
    for checkout in sorted(checkouts, key=lambda x: x.relpath.split("/")):
        checkout_path = Path(checkout.relpath)
        while depth_stack:
            try:
                checkout_path.relative_to(depth_stack[-1][0])
            except ValueError:
                # Path.relative_to returns ValueError if paths are not relative.
                # TODO(sokcevic): Switch to is_relative_to once min supported
                # version is py3.9.
                depth_stack.pop()
            else:
                break

        level = depth_stack[-1][1] + 1 if depth_stack else 0
        parent = checkout.parent
        if parent is not None:
            level = max(
                level,
                submodule_parent_level.get(parent.worktree, level - 1) + 1,
            )
            submodule_parent_level[parent.worktree] = level
        if level >= len(res):
            res.extend([] for _ in range(level + 1 - len(res)))

        current = res[level]
        current.append(checkout)
        depth_stack.append((checkout_path, level))

    return res


def _NestedProjects(projects: List[Project]) -> List[Project]:
    """Return the projects in |projects| living inside another one's path."""
    return [p for level in _SafeCheckoutOrder(projects)[1:] for p in level]


def _ParentFirstBatches(projects: List[Project]) -> List[List[Project]]:
    """Group |projects| so that a parent is fetched before its submodules.

    A discovered submodule can only be fetched at the right revision once the
    project holding its gitlink has been fetched, so it is held back to a later
    batch than its parent. Projects that are not discovered submodules all end
    up in the first batch, which keeps manifests without submodules on a single
    batch.
    """
    batches = collections.defaultdict(list)
    for project in projects:
        depth = 0
        ancestor = project
        while ancestor.Derived and ancestor.parent:
            depth += 1
            ancestor = ancestor.parent
        batches[depth].append(project)
    return [batches[depth] for depth in sorted(batches)]


def _RefreshDerivedRevisions(
    projects: List[Project],
    submodule_revisions: Optional[Dict[Project, Dict[str, str]]] = None,
) -> List[Project]:
    """Re-resolve the gitlinks of the discovered submodules in |projects|.

    The revision of a discovered submodule is read from its parent when the
    manifest is loaded, so it is stale as soon as the parent gets fetched. It
    has to be resolved again once the parent is up-to-date, and before the
    submodule itself is fetched and checked out.

    Args:
        projects: The projects whose discovered submodules to resolve.
        submodule_revisions: Gitlinks already read, keyed by the project
            holding them. Passing the same dict for project sets that follow
            the same fetches, e.g. the levels of one checkout order, keeps a
            project from being read more than once.

    Returns:
        The submodules that their parent no longer holds a gitlink for.
    """
    if submodule_revisions is None:
        submodule_revisions = {}

    subprojects_by_parent = collections.defaultdict(list)
    for project in projects:
        if project.Derived and project.parent:
            subprojects_by_parent[project.parent].append(project)

    removed = []
    for parent, subprojects in subprojects_by_parent.items():
        revisions = submodule_revisions.get(parent)
        if revisions is None:
            revisions = parent.GetSubmoduleRevisions()
            if revisions is None:
                # Leave the submodules of a parent we cannot read alone.
                continue
            submodule_revisions[parent] = revisions
        for subproject in subprojects:
            rev = revisions.get(subproject.gitlink_path)
            if rev:
                subproject.SetRevision(rev, revisionId=rev)
            else:
                removed.append(subproject)
    return removed


def _WithoutProjects(
    projects: List[Project], unwanted: List[Project]
) -> List[Project]:
    """Return |projects| without the projects in |unwanted|."""
    if not unwanted:
        return projects
    dropped = set(unwanted)
    return [p for p in projects if p not in dropped]


def _chunksize(projects: int, jobs: int) -> int:
    """Calculate chunk size for the given number of projects and jobs."""
    return min(max(1, projects // jobs), WORKER_BATCH_SIZE)


class _FetchOneResult(NamedTuple):
    """_FetchOne return value.

    Attributes:
      success (bool): True if successful.
      project_idx (int): The fetched project index.
      start (float): The starting time.time().
      finish (float): The ending time.time().
      remote_fetched (bool): True if the remote was actually queried.
    """

    success: bool
    errors: List[Exception]
    project_idx: int
    start: float
    finish: float
    remote_fetched: bool


class _FetchResult(NamedTuple):
    """_Fetch return value.

    Attributes:
      success (bool): True if successful.
      projects (Set[str]): The names of the git directories of fetched projects.
    """

    success: bool
    projects: Set[str]


class _FetchMainResult(NamedTuple):
    """_FetchMain return value.

    Attributes:
      all_projects (List[Project]): The fetched projects.
    """

    all_projects: List[Project]


class _CheckoutOneResult(NamedTuple):
    """_CheckoutOne return value.

    Attributes:
      success (bool): True if successful.
      project_idx (int): The project index.
      start (float): The starting time.time().
      finish (float): The ending time.time().
    """

    success: bool
    errors: List[Exception]
    project_idx: int
    start: float
    finish: float


class _SyncResult(NamedTuple):
    """Individual project sync result for interleaved mode.

    Attributes:
      project_index (int): The index of the project in the shared list.
      relpath (str): The project's path relative to the tree being synced.
          Unlike Project.relpath, it is unique across submanifests.
      remote_fetched (bool): True if the remote was actually queried.
      fetch_success (bool): True if the fetch operation was successful.
      fetch_errors (List[Exception]): The Exceptions from a failed fetch.
      fetch_start (Optional[float]): The time.time() when fetch started.
      fetch_finish (Optional[float]): The time.time() when fetch finished.
      checkout_success (bool): True if the checkout operation was
          successful.
      checkout_errors (List[Exception]): The Exceptions from a failed
          checkout.
      checkout_start (Optional[float]): The time.time() when checkout
          started.
      checkout_finish (Optional[float]): The time.time() when checkout
          finished.
      stderr_text (str): The combined output from both fetch and checkout.
    """

    project_index: int
    relpath: str

    remote_fetched: bool
    fetch_success: bool
    fetch_errors: List[Exception]
    fetch_start: Optional[float]
    fetch_finish: Optional[float]

    checkout_success: bool
    checkout_errors: List[Exception]
    checkout_start: Optional[float]
    checkout_finish: Optional[float]

    stderr_text: str


class _InterleavedSyncResult(NamedTuple):
    """Result of an interleaved sync.

    Attributes:
      results (List[_SyncResult]): A list of results, one for each project
          processed. Empty if the worker failed before creating results.
    """

    results: List[_SyncResult]


class SuperprojectError(SyncError):
    """Superproject sync repo."""


class SyncFailFastError(SyncError):
    """Sync exit error when --fail-fast set."""


class SmartSyncError(SyncError):
    """Smart sync exit error."""


class ManifestInterruptError(RepoError):
    """Aggregate Error to be logged when a user interrupts a manifest update."""

    def __init__(self, output, **kwargs):
        super().__init__(output, **kwargs)
        self.output = output

    def __str__(self):
        error_type = type(self).__name__
        return f"{error_type}:{self.output}"


class TeeStringIO(io.StringIO):
    """StringIO class that can write to an additional destination."""

    def __init__(
        self, io: Union[io.TextIOWrapper, None], *args, **kwargs
    ) -> None:
        super().__init__(*args, **kwargs)
        self.io = io

    def write(self, s: str) -> int:
        """Write to additional destination."""
        ret = super().write(s)
        if self.io is not None:
            self.io.write(s)
        return ret


class Sync(Command, MirrorSafeCommand):
    COMMON = True
    RESPECT_SMART_SYNC_OVERRIDE = False
    MULTI_MANIFEST_SUPPORT = True
    helpSummary = "Update working tree to the latest revision"
    helpUsage = """
%prog [<project>...]
"""
    helpDescription = """
The '%prog' command synchronizes local project directories
with the remote repositories specified in the manifest.  If a local
project does not yet exist, it will clone a new local directory from
the remote repository and set up tracking branches as specified in
the manifest.  If the local project already exists, '%prog'
will update the remote branches and rebase any new local changes
on top of the new remote changes.

'%prog' will synchronize all projects listed at the command
line.  Projects can be specified either by name, or by a relative
or absolute path to the project's local directory. If no projects
are specified, '%prog' will synchronize all projects listed in
the manifest.

The -d/--detach option can be used to switch specified projects
back to the manifest revision.  This option is especially helpful
if the project is currently on a topic branch, but the manifest
revision is temporarily needed.

The -s/--smart-sync option can be used to sync to a known good
build as specified by the manifest-server element in the current
manifest. The -t/--smart-tag option is similar and allows you to
specify a custom tag/label.

The -u/--manifest-server-username and -p/--manifest-server-password
options can be used to specify a username and password to authenticate
with the manifest server when using the -s or -t option.

If -u and -p are not specified when using the -s or -t option, '%prog'
will attempt to read authentication credentials for the manifest server
from the user's .netrc file.

'%prog' will not use authentication credentials from -u/-p or .netrc
if the manifest server specified in the manifest file already includes
credentials.

By default, all projects will be synced. The --fail-fast option can be used
to halt syncing as soon as possible when the first project fails to sync.

The --force-sync option can be used to overwrite existing git
directories if they have previously been linked to a different
object directory. WARNING: This may cause data to be lost since
refs may be removed when overwriting.

The --force-checkout option can be used to force git to switch revs even if the
index or the working tree differs from HEAD, and if there are untracked files.
WARNING: This may cause data to be lost since uncommitted changes may be
removed.

The --force-remove-dirty option can be used to remove previously used
projects with uncommitted changes. WARNING: This may cause data to be
lost since uncommitted changes may be removed with projects that no longer
exist in the manifest.

The --no-clone-bundle option disables any attempt to use
$URL/clone.bundle to bootstrap a new Git repository from a
resumeable bundle file on a content delivery network. This
may be necessary if there are problems with the local Python
HTTP client or proxy configuration, but the Git binary works.

The --recurse-submodules option enables syncing Git submodules of all projects
from the server. The --no-recurse-submodules option disables syncing Git
submodules, even when a project has sync-s="true" in the manifest.

The --fetch-submodules and --no-fetch-submodules options are deprecated aliases
for --recurse-submodules and --no-recurse-submodules, respectively.

The -c/--current-branch option can be used to only fetch objects that
are on the branch specified by a project's revision.

The --optimized-fetch option can be used to only fetch projects that
are fixed to a sha1 revision if the sha1 revision does not already
exist locally.

The --prune option can be used to remove any refs that no longer
exist on the remote.

The --auto-gc option can be used to trigger garbage collection on all
projects. By default, repo does not run garbage collection.

# SSH Connections

If at least one project remote URL uses an SSH connection (ssh://,
git+ssh://, or user@host:path syntax) repo will automatically
enable the SSH ControlMaster option when connecting to that host.
This feature permits other projects in the same '%prog' session to
reuse the same SSH tunnel, saving connection setup overheads.

To disable this behavior on UNIX platforms, set the GIT_SSH
environment variable to 'ssh'.  For example:

  export GIT_SSH=ssh
  %prog

# Compatibility

This feature is automatically disabled on Windows, due to the lack
of UNIX domain socket support.

This feature is not compatible with url.insteadof rewrites in the
user's ~/.gitconfig.  '%prog' is currently not able to perform the
rewrite early enough to establish the ControlMaster tunnel.

If the remote SSH daemon is Gerrit Code Review, version 2.0.10 or
later is required to fix a server side protocol bug.

"""
    # A value of 0 means we want parallel jobs, but we'll determine the default
    # value later on.
    PARALLEL_JOBS = 0

    _JOBS_WARN_THRESHOLD = 100

    @staticmethod
    def _deprecated_submodules_option(option, opt_str, _value, parser):
        enabled = opt_str == "--fetch-submodules"
        replacement = (
            "--recurse-submodules" if enabled else "--no-recurse-submodules"
        )
        logger.warning("%s is deprecated; use %s instead", opt_str, replacement)
        setattr(parser.values, option.dest, enabled)

    def _Options(self, p, show_smart=True):
        p.add_option(
            "--jobs-network",
            default=None,
            type=int,
            metavar="JOBS",
            help="number of network jobs to run in parallel (defaults to "
            "--jobs or 1). Ignored unless --no-interleaved is set",
        )

        jobs_checkout_default = self._GetHelpForCpuJobCount(DEFAULT_LOCAL_JOBS)
        p.add_option(
            "--jobs-checkout",
            default=None,
            type=int,
            metavar="JOBS",
            help=(
                "number of local checkout jobs to run in parallel (defaults "
                f"to --jobs or {jobs_checkout_default}). Ignored unless "
                "--no-interleaved is set"
            ),
        )

        p.add_option(
            "-f",
            "--force-broken",
            action="store_true",
            help="obsolete option (to be deleted in the future)",
        )
        p.add_option(
            "--fail-fast",
            action="store_true",
            help="stop syncing after first error is hit",
        )
        p.add_option(
            "--force-sync",
            action="store_true",
            help="overwrite an existing git directory if it needs to "
            "point to a different object directory. WARNING: this "
            "may cause loss of data",
        )
        p.add_option(
            "--force-checkout",
            action="store_true",
            help="force checkout even if it results in throwing away "
            "uncommitted modifications. "
            "WARNING: this may cause loss of data",
        )
        p.add_option(
            "--force-remove-dirty",
            action="store_true",
            help="force remove projects with uncommitted modifications if "
            "projects no longer exist in the manifest. "
            "WARNING: this may cause loss of data",
        )
        p.add_option(
            "--rebase",
            action="store_true",
            help="rebase local commits regardless of whether they are "
            "published",
        )
        p.add_option(
            "-l",
            "--local-only",
            action="store_true",
            help="only update working tree, don't fetch",
        )
        p.add_option(
            "--no-manifest-update",
            "--nmu",
            dest="mp_update",
            action="store_false",
            default="true",
            help="use the existing manifest checkout as-is. "
            "(do not update to the latest revision)",
        )
        p.add_option(
            "--interleaved",
            action="store_true",
            default=True,
            help="fetch and checkout projects in parallel (default)",
        )
        p.add_option(
            "--no-interleaved",
            dest="interleaved",
            action="store_false",
            help="fetch and checkout projects in phases",
        )
        p.add_option(
            "-n",
            "--network-only",
            action="store_true",
            help="fetch only, don't update working tree",
        )
        p.add_option(
            "-d",
            "--detach",
            dest="detach_head",
            action="store_true",
            help="detach projects back to manifest revision",
        )
        p.add_option(
            "-c",
            "--current-branch",
            dest="current_branch_only",
            action="store_true",
            help="fetch only current branch from server",
        )
        p.add_option(
            "--no-current-branch",
            dest="current_branch_only",
            action="store_false",
            help="fetch all branches from server",
        )
        p.add_option(
            "-m",
            "--manifest-name",
            help="temporary manifest to use for this sync",
            metavar="NAME.xml",
        )
        p.add_option(
            "-g",
            "--groups",
            help="sync projects matching the specific groups.  Not persistent "
            "unlike when used on init",
            metavar="GROUP",
        )
        p.add_option(
            "--clone-bundle",
            action="store_true",
            help="enable use of /clone.bundle on HTTP/HTTPS",
        )
        p.add_option(
            "--no-clone-bundle",
            dest="clone_bundle",
            action="store_false",
            help="disable use of /clone.bundle on HTTP/HTTPS",
        )
        p.add_option(
            "-u",
            "--manifest-server-username",
            action="store",
            help="username to authenticate with the manifest server",
        )
        p.add_option(
            "-p",
            "--manifest-server-password",
            action="store",
            help="password to authenticate with the manifest server",
        )
        p.add_option(
            "--recurse-submodules",
            action="store_true",
            help="sync submodules from server",
        )
        p.add_option(
            "--no-recurse-submodules",
            dest="recurse_submodules",
            action="store_false",
            help="don't sync submodules from server",
        )
        p.add_option(
            "--fetch-submodules",
            dest="recurse_submodules",
            action="callback",
            callback=self._deprecated_submodules_option,
            help=optparse.SUPPRESS_HELP,
        )
        p.add_option(
            "--no-fetch-submodules",
            dest="recurse_submodules",
            action="callback",
            callback=self._deprecated_submodules_option,
            help=optparse.SUPPRESS_HELP,
        )
        p.add_option(
            "--use-superproject",
            action="store_true",
            help="use the manifest superproject to sync projects; implies -c",
        )
        p.add_option(
            "--no-use-superproject",
            action="store_false",
            dest="use_superproject",
            help="disable use of manifest superprojects",
        )
        p.add_option(
            "--superproject-revision",
            action="store",
            help="sync to superproject revision (applies to outer manifest)",
        )
        p.add_option("--tags", action="store_true", help="fetch tags")
        p.add_option(
            "--no-tags",
            dest="tags",
            action="store_false",
            help="don't fetch tags (default)",
        )
        p.add_option(
            "--optimized-fetch",
            action="store_true",
            help="only fetch projects fixed to sha1 if revision does not exist "
            "locally",
        )
        p.add_option(
            "--retry-fetches",
            default=0,
            action="store",
            type="int",
            help="number of times to retry fetches on transient errors",
        )
        p.add_option(
            "--prune",
            action="store_true",
            help="delete refs that no longer exist on the remote (default)",
        )
        p.add_option(
            "--no-prune",
            dest="prune",
            action="store_false",
            help="do not delete refs that no longer exist on the remote",
        )
        p.add_option(
            "--auto-gc",
            action="store_true",
            default=None,
            help="run garbage collection on all synced projects",
        )
        p.add_option(
            "--no-auto-gc",
            dest="auto_gc",
            action="store_false",
            help="do not run garbage collection on any projects (default)",
        )
        if show_smart:
            p.add_option(
                "-s",
                "--smart-sync",
                action="store_true",
                help="smart sync using manifest from the latest known good "
                "build",
            )
            p.add_option(
                "-t",
                "--smart-tag",
                action="store",
                help="smart sync using manifest from a known tag",
            )

        g = p.add_option_group("repo Version options")
        g.add_option(
            "--no-repo-verify",
            dest="repo_verify",
            default=True,
            action="store_false",
            help="do not verify repo source code",
        )
        g.add_option(
            "--repo-upgraded",
            action="store_true",
            help=optparse.SUPPRESS_HELP,
        )
        RepoHook.AddOptionGroup(p, "post-sync")

    def _GetBranch(self, manifest_project):
        """Returns the branch name for getting the approved smartsync manifest.

        Args:
            manifest_project: The manifestProject to query.
        """
        b = manifest_project.GetBranch(manifest_project.CurrentBranch)
        branch = b.merge
        if branch.startswith(R_HEADS):
            branch = branch[len(R_HEADS) :]
        return branch

    @classmethod
    def _GetCurrentBranchOnly(cls, opt, manifest):
        """Returns whether current-branch or use-superproject options are
        enabled.

        Args:
            opt: Program options returned from optparse.  See _Options().
            manifest: The manifest to use.

        Returns:
            True if a superproject is requested, otherwise the value of the
            current_branch option (True, False or None).
        """
        return (
            git_superproject.UseSuperproject(opt.use_superproject, manifest)
            or opt.current_branch_only
        )

    def _ConfigureSuperproject(
        self,
        opt: optparse.Values,
        manifest,
        revision: Optional[str] = None,
    ) -> bool:
        """Configure superproject with options."""
        if not manifest.superproject:
            return False
        manifest.superproject.SetQuiet(not opt.verbose)
        print_messages = git_superproject.PrintMessages(
            opt.use_superproject, manifest
        )
        manifest.superproject.SetPrintMessages(print_messages)
        if revision:
            manifest.superproject.SetRevisionId(revision)
        return print_messages

    def _UpdateProjectsRevisionId(
        self, opt, args, superproject_logging_data, manifest
    ):
        """Update revisionId of projects with the commit from the superproject.

        This function updates each project's revisionId with the commit hash
        from the superproject.  It writes the updated manifest into a file and
        reloads the manifest from it.  When appropriate, sub manifests are also
        processed.

        Args:
            opt: Program options returned from optparse.  See _Options().
            args: Arguments to pass to GetProjects. See the GetProjects
                docstring for details.
            superproject_logging_data: A dictionary of superproject data to log.
            manifest: The manifest to use.
        """
        have_superproject = manifest.superproject or any(
            m.superproject for m in manifest.all_children
        )
        if not have_superproject:
            return

        if opt.local_only and manifest.superproject:
            manifest_path = manifest.superproject.manifest_path
            if manifest_path:
                self._ReloadManifest(manifest_path, manifest)
            return

        all_projects = self.GetProjects(
            args,
            groups=opt.groups,
            missing_ok=True,
            submodules_ok=opt.recurse_submodules,
            manifest=manifest,
            all_manifests=not opt.this_manifest_only,
        )

        per_manifest = collections.defaultdict(list)
        if opt.this_manifest_only:
            per_manifest[manifest.path_prefix] = all_projects
        else:
            for p in all_projects:
                per_manifest[p.manifest.path_prefix].append(p)

        superproject_logging_data = {}
        need_unload = False
        for m in self.ManifestList(opt):
            if m.path_prefix not in per_manifest:
                continue
            use_super = git_superproject.UseSuperproject(
                opt.use_superproject, m
            )
            if superproject_logging_data:
                superproject_logging_data["multimanifest"] = True
            superproject_logging_data.update(
                superproject=use_super,
                haslocalmanifests=bool(m.HasLocalManifests),
                hassuperprojecttag=bool(m.superproject),
            )
            if use_super and (m.IsMirror or m.IsArchive):
                # Don't use superproject, because we have no working tree.
                use_super = False
                superproject_logging_data["superproject"] = False
                superproject_logging_data["noworktree"] = True
                if opt.use_superproject is not False:
                    logger.warning(
                        "%s: not using superproject because there is no "
                        "working tree.",
                        m.path_prefix,
                    )

            if not use_super:
                continue
            print_messages = self._ConfigureSuperproject(opt, m)
            update_result = m.superproject.UpdateProjectsRevisionId(
                per_manifest[m.path_prefix], git_event_log=self.git_event_log
            )
            manifest_path = update_result.manifest_path
            superproject_logging_data["updatedrevisionid"] = bool(manifest_path)
            if manifest_path:
                m.SetManifestOverride(manifest_path)
                need_unload = True
            else:
                if print_messages:
                    logger.warning(
                        "%s: warning: Update of revisionId from superproject "
                        "has failed, repo sync will not use superproject to "
                        "fetch the source. Please resync with the "
                        "--no-use-superproject option to avoid this repo "
                        "warning.",
                        m.path_prefix,
                    )
                if update_result.fatal and opt.use_superproject is not None:
                    raise SuperprojectError()
        if need_unload:
            m.outer_client.manifest.Unload()

    @classmethod
    def _FetchProjectList(cls, opt, projects):
        """Main function of the fetch worker.

        The projects we're given share the same underlying git object store, so
        we have to fetch them in serial.

        Delegates most of the work to _FetchOne.

        Args:
            opt: Program options returned from optparse.  See _Options().
            projects: Projects to fetch.
        """
        return [cls._FetchOne(opt, x) for x in projects]

    @classmethod
    def _FetchOne(cls, opt, project_idx):
        """Fetch git objects for a single project.

        Args:
            opt: Program options returned from optparse.  See _Options().
            project_idx: Project index for the project to fetch.

        Returns:
            Whether the fetch was successful.
        """
        project = cls.get_parallel_context()["projects"][project_idx]
        start = time.time()
        k = f"{project.name} @ {project.relpath}"
        cls.get_parallel_context()["sync_dict"][k] = start
        success = False
        remote_fetched = False
        errors = []
        buf = TeeStringIO(sys.stdout if opt.verbose else None)
        try:
            sync_result = project.Sync_NetworkHalf(
                quiet=opt.quiet,
                verbose=opt.verbose,
                output_redir=buf,
                use_superproject=opt.use_superproject,
                current_branch_only=cls._GetCurrentBranchOnly(
                    opt, project.manifest
                ),
                force_sync=opt.force_sync,
                clone_bundle=opt.clone_bundle,
                tags=opt.tags,
                archive=project.manifest.IsArchive,
                optimized_fetch=opt.optimized_fetch,
                retry_fetches=opt.retry_fetches,
                prune=opt.prune,
                ssh_proxy=cls.get_parallel_context()["ssh_proxy"],
                clone_filter=project.manifest.CloneFilter,
                partial_clone_exclude=project.manifest.PartialCloneExclude,
                clone_filter_for_depth=project.manifest.CloneFilterForDepth,
            )
            success = sync_result.success
            remote_fetched = sync_result.remote_fetched
            if sync_result.error:
                errors.append(sync_result.error)

            output = buf.getvalue()
            if output and buf.io is None and not success:
                print("\n" + output.rstrip())

            if not success:
                logger.error(
                    "error: Cannot fetch %s from %s",
                    project.name,
                    project.remote.url,
                )
        except KeyboardInterrupt:
            logger.error("Keyboard interrupt while processing %s", project.name)
            if not cls.is_multiprocessing_active():
                raise
        except GitError as e:
            logger.error("error.GitError: Cannot fetch %s", e)
            errors.append(e)
        except Exception as e:
            logger.error(
                "error: Cannot fetch %s (%s: %s)",
                project.name,
                type(e).__name__,
                e,
            )
            errors.append(e)
            raise
        finally:
            del cls.get_parallel_context()["sync_dict"][k]

        finish = time.time()
        return _FetchOneResult(
            success, errors, project_idx, start, finish, remote_fetched
        )

    def _GetSyncProgressMessage(self):
        earliest_time = float("inf")
        earliest_proj = None
        items = self.get_parallel_context()["sync_dict"].items()
        for project, t in items:
            if t < earliest_time:
                earliest_time = t
                earliest_proj = project

        if not earliest_proj:
            # This function is called when sync is still running but in some
            # cases (by chance), sync_dict can contain no entries. Return some
            # text to indicate that sync is still working.
            return "..working.."

        elapsed = time.time() - earliest_time
        jobs = jobs_str(len(items))
        return f"{jobs} | {elapsed_str(elapsed)} {earliest_proj}"

    @classmethod
    def InitWorker(cls):
        # Force connect to the manager server now.
        # This is good because workers are initialized one by one. Without this,
        # multiple workers may connect to the manager when handling the first
        # job at the same time. Then the connection may fail if too many
        # connections are pending and execeeded the socket listening backlog,
        # especially on MacOS.
        len(cls.get_parallel_context()["sync_dict"])

    def _Fetch(self, projects, opt, err_event, ssh_proxy, errors):
        ret = True

        fetched = set()
        remote_fetched = set()
        pm = Progress(
            "Fetching",
            len(projects),
            delay=False,
            quiet=opt.quiet,
            show_elapsed=True,
            elide=True,
        )

        sync_event = _threading.Event()
        sync_progress_thread = self._CreateSyncProgressThread(pm, sync_event)

        def _ProcessResults(pool, pm, results_sets):
            ret = True
            for results in results_sets:
                for result in results:
                    success = result.success
                    project = projects[result.project_idx]
                    start = result.start
                    finish = result.finish
                    self._fetch_times.Set(project, finish - start)
                    self._local_sync_state.SetFetchTime(project)
                    self.event_log.AddSync(
                        project,
                        event_log.TASK_SYNC_NETWORK,
                        start,
                        finish,
                        success,
                    )
                    if result.errors:
                        errors.extend(result.errors)
                    if result.remote_fetched:
                        remote_fetched.add(project)
                    # Check for any errors before running any more tasks.
                    # ...we'll let existing jobs finish, though.
                    if not success:
                        ret = False
                    else:
                        fetched.add(project.gitdir)
                    pm.update()
                if not ret and opt.fail_fast:
                    if pool:
                        pool.close()
                    break
            return ret

        with self.ParallelContext():
            self.get_parallel_context()["projects"] = projects
            self.get_parallel_context()[
                "sync_dict"
            ] = multiprocessing.Manager().dict()

            objdir_project_map = {}
            for index, project in enumerate(projects):
                objdir_project_map.setdefault(project.objdir, []).append(index)
            projects_list = list(objdir_project_map.values())

            jobs = max(1, min(opt.jobs_network, len(projects_list)))

            # We pass the ssh proxy settings via the class.  This allows
            # multiprocessing to pickle it up when spawning children.  We can't
            # pass it as an argument to _FetchProjectList below as
            # multiprocessing is unable to pickle those.
            self.get_parallel_context()["ssh_proxy"] = ssh_proxy

            sync_progress_thread.start()
            if not opt.quiet:
                pm.update(inc=0, msg="warming up")
            try:
                ret = self.ExecuteInParallel(
                    jobs,
                    functools.partial(self._FetchProjectList, opt),
                    projects_list,
                    callback=_ProcessResults,
                    output=pm,
                    # Use chunksize=1 to avoid the chance that some workers are
                    # idle while other workers still have more than one job in
                    # their chunk queue.
                    chunksize=1,
                    initializer=self.InitWorker,
                )
            finally:
                sync_event.set()
                sync_progress_thread.join()

        if not self.outer_client.manifest.IsArchive:
            self._GCProjects(projects, opt, err_event)

        return _FetchResult(ret, fetched)

    def _FetchParentFirst(
        self,
        projects: List[Project],
        opt: optparse.Values,
        err_event: _threading.Event,
        ssh_proxy: ssh.ProxyManager,
        errors: List[Exception],
    ) -> _FetchResult:
        """Fetch |projects|, holding submodules back until their parent is done.

        Args:
            projects: Projects to fetch.
            opt: Program options returned from optparse. See _Options().
            err_event: Whether an error was hit while processing.
            ssh_proxy: SSH manager for clients & masters.
            errors: A list to accumulate errors.

        Returns:
            _FetchResult for all the batches combined.
        """
        success = True
        fetched = set()
        for batch in _ParentFirstBatches(projects):
            batch = _WithoutProjects(batch, _RefreshDerivedRevisions(batch))
            if not batch:
                continue
            batch.sort(key=self._fetch_times.Get, reverse=True)
            result = self._Fetch(batch, opt, err_event, ssh_proxy, errors)
            success = success and result.success
            fetched.update(result.projects)
            if not success and opt.fail_fast:
                break
        return _FetchResult(success, fetched)

    def _FetchMain(
        self, opt, args, all_projects, err_event, ssh_proxy, manifest, errors
    ):
        """The main network fetch loop.

        Args:
            opt: Program options returned from optparse.  See _Options().
            args: Command line args used to filter out projects.
            all_projects: List of all projects that should be fetched.
            err_event: Whether an error was hit while processing.
            ssh_proxy: SSH manager for clients & masters.
            manifest: The manifest to use.

        Returns:
            List of all projects that should be checked out.
        """
        try:
            result = self._FetchParentFirst(
                all_projects, opt, err_event, ssh_proxy, errors
            )
            success = result.success
            fetched = result.projects
            if not success:
                err_event.set()

            if opt.network_only:
                # Bail out now; the rest touches the working tree.
                if err_event.is_set():
                    e = SyncError(
                        "error: Exited sync due to fetch errors.",
                        aggregate_errors=errors,
                    )

                    logger.error(e)
                    raise e
                return _FetchMainResult([])

            # Iteratively fetch missing and/or nested unregistered submodules.
            previously_missing_set = set()
            while True:
                self._ReloadManifest(None, manifest)
                all_projects = self.GetProjects(
                    args,
                    groups=opt.groups,
                    missing_ok=True,
                    submodules_ok=opt.recurse_submodules,
                    manifest=manifest,
                    all_manifests=not opt.this_manifest_only,
                )
                missing = []
                for project in all_projects:
                    if project.gitdir not in fetched:
                        missing.append(project)
                if not missing:
                    break
                # Stop us from non-stopped fetching actually-missing repos: If
                # set of missing repos has not been changed from last fetch, we
                # break.
                missing_set = {p.name for p in missing}
                if previously_missing_set == missing_set:
                    break
                previously_missing_set = missing_set
                result = self._FetchParentFirst(
                    missing, opt, err_event, ssh_proxy, errors
                )
                success = result.success
                new_fetched = result.projects
                if not success:
                    err_event.set()
                fetched.update(new_fetched)
        finally:
            self._fetch_times.Save()
            self._local_sync_state.Save()

        return _FetchMainResult(all_projects)

    @classmethod
    def _CheckoutOne(
        cls,
        detach_head,
        force_sync,
        force_checkout,
        force_rebase,
        verbose,
        project_idx,
    ):
        """Checkout work tree for one project

        Args:
            detach_head: Whether to leave a detached HEAD.
            force_sync: Force checking out of .git directory (e.g. overwrite
            existing git directory that was previously linked to a different
            object directory).
            force_checkout: Force checking out of the repo content.
            force_rebase: Force rebase.
            verbose: Whether to show verbose messages.
            project_idx: Project index for the project to checkout.

        Returns:
            Whether the fetch was successful.
        """
        project = cls.get_parallel_context()["projects"][project_idx]
        start = time.time()
        syncbuf = SyncBuffer(
            project.manifest.manifestProject.config, detach_head=detach_head
        )
        success = False
        errors = []
        try:
            project.Sync_LocalHalf(
                syncbuf,
                force_sync=force_sync,
                force_checkout=force_checkout,
                force_rebase=force_rebase,
                verbose=verbose,
            )
            success = syncbuf.Finish()
            errors.extend(syncbuf.errors)
        except KeyboardInterrupt:
            logger.error("Keyboard interrupt while processing %s", project.name)
            if not cls.is_multiprocessing_active():
                raise
        except GitError as e:
            logger.error(
                "error.GitError: Cannot checkout %s: %s", project.name, e
            )
            errors.append(e)
        except Exception as e:
            logger.error(
                "error: Cannot checkout %s: %s: %s",
                project.name,
                type(e).__name__,
                e,
            )
            raise

        if not success:
            logger.error("error: Cannot checkout %s", project.name)
        finish = time.time()
        return _CheckoutOneResult(success, errors, project_idx, start, finish)

    def _Checkout(self, all_projects, opt, err_results, checkout_errors):
        """Checkout projects listed in all_projects

        Args:
            all_projects: List of all projects that should be checked out.
            opt: Program options returned from optparse.  See _Options().
            err_results: A list of strings, paths to git repos where checkout
                failed.
        """
        # Only checkout projects with worktrees.
        all_projects = [x for x in all_projects if x.worktree]

        def _ProcessResults(pool, pm, results):
            ret = True
            for result in results:
                success = result.success
                project = self.get_parallel_context()["projects"][
                    result.project_idx
                ]
                start = result.start
                finish = result.finish
                self.event_log.AddSync(
                    project, event_log.TASK_SYNC_LOCAL, start, finish, success
                )

                if result.errors:
                    checkout_errors.extend(result.errors)

                # Check for any errors before running any more tasks.
                # ...we'll let existing jobs finish, though.
                if success:
                    self._local_sync_state.SetCheckoutTime(project)
                else:
                    ret = False
                    err_results.append(
                        project.RelPath(local=opt.this_manifest_only)
                    )
                    if opt.fail_fast:
                        if pool:
                            pool.close()
                        return ret
                pm.update(msg=project.name)
            return ret

        for projects in _SafeCheckoutOrder(all_projects):
            with self.ParallelContext():
                self.get_parallel_context()["projects"] = projects
                proc_res = self.ExecuteInParallel(
                    opt.jobs_checkout,
                    functools.partial(
                        self._CheckoutOne,
                        opt.detach_head,
                        opt.force_sync,
                        opt.force_checkout,
                        opt.rebase,
                        opt.verbose,
                    ),
                    range(len(projects)),
                    callback=_ProcessResults,
                    output=Progress(
                        "Checking out", len(all_projects), quiet=opt.quiet
                    ),
                    # Use chunksize=1 to avoid the chance that some workers are
                    # idle while other workers still have more than one job in
                    # their chunk queue.
                    chunksize=1,
                )

        self._local_sync_state.Save()
        return proc_res and not err_results

    def _PrintManifestNotices(self, opt):
        """Print all manifest notices, but only once."""
        printed_notices = set()
        # Print all manifest notices, but only once.
        # Sort by path_prefix to ensure consistent ordering.
        for m in sorted(self.ManifestList(opt), key=lambda x: x.path_prefix):
            if m.notice and m.notice not in printed_notices:
                print(m.notice)
                printed_notices.add(m.notice)

    @staticmethod
    def _GetPreciousObjectsState(project: Project, opt):
        """Get the preciousObjects state for the project.

        Args:
            project (Project): the project to examine, and possibly correct.
            opt (optparse.Values): options given to sync.

        Returns:
            Expected state of extensions.preciousObjects:
                False: Should be disabled. (not present)
                True: Should be enabled.
        """
        if project.use_git_worktrees:
            return False
        projects = project.manifest.GetProjectsWithName(
            project.name, all_manifests=True
        )
        if len(projects) == 1:
            return False
        if len(projects) > 1:
            # Objects are potentially shared with another project.
            # See the logic in Project.Sync_NetworkHalf regarding UseAlternates.
            # - When False, shared projects share (via symlink)
            #   .repo/project-objects/{PROJECT_NAME}.git as the one-and-only
            #   objects directory.  All objects are precious, since there is no
            #   project with a complete set of refs.
            # - When True, shared projects share (via info/alternates)
            #   .repo/project-objects/{PROJECT_NAME}.git as an alternate object
            #   store, which is written only on the first clone of the project,
            #   and is not written subsequently. (When Sync_NetworkHalf sees
            #   that it exists, it makes sure that the alternates file points
            #   there, and uses a project-local .git/objects directory for all
            #   syncs going forward.
            # We do not support switching between the options.  The environment
            # variable is present for testing and migration only.
            return not project.UseAlternates

        return False

    @classmethod
    def _SetPreciousObjectsState(cls, project: Project, opt):
        """Correct the preciousObjects state for the project.

        Args:
            project: the project to examine, and possibly correct.
            opt: options given to sync.
        """
        expected = cls._GetPreciousObjectsState(project, opt)
        actual = (
            project.config.GetBoolean("extensions.preciousObjects") or False
        )
        relpath = project.RelPath(local=opt.this_manifest_only)

        if expected != actual:
            # If this is unexpected, log it and repair.
            Trace(
                f"{relpath} expected preciousObjects={expected}, got {actual}"
            )
            if expected:
                if not opt.quiet:
                    print(
                        "\r%s: Shared project %s found, disabling pruning."
                        % (relpath, project.name)
                    )

                if git_require((2, 7, 0)):
                    project.EnableRepositoryExtension("preciousObjects")
                else:
                    # This isn't perfect, but it's the best we can do with old
                    # git.
                    logger.warning(
                        "%s: WARNING: shared projects are unreliable when "
                        "using old versions of git; please upgrade to "
                        "git-2.7.0+.",
                        relpath,
                    )
                    project.config.SetString("gc.pruneExpire", "never")
            else:
                project.config.SetString("extensions.preciousObjects", None)
                project.config.SetString("gc.pruneExpire", None)

    @staticmethod
    def _RunOneGC(project: Project, config: Optional[dict] = None) -> None:
        """Run auto GC on a single project."""
        local_config = {}
        if config:
            local_config.update(config)
        local_config["gc.autoDetach"] = "false"
        project.bare_git.gc("--auto", config=local_config)

    @classmethod
    def _GCProjects(
        cls,
        projects: List[Project],
        opt: optparse.Values,
        err_event: _threading.Event,
    ) -> None:
        """Perform garbage collection.

        If We are skipping garbage collection (opt.auto_gc not set), we still
        want to potentially mark objects precious, so that `git gc` does not
        discard shared objects.
        """
        if not opt.auto_gc:
            # Just repair preciousObjects state, and return.
            for project in projects:
                cls._SetPreciousObjectsState(project, opt)
            return

        pm = Progress(
            "Garbage collecting", len(projects), delay=False, quiet=opt.quiet
        )
        pm.update(inc=0, msg="prescan")

        tidy_dirs = {}
        for project in projects:
            cls._SetPreciousObjectsState(project, opt)

            # Only call git gc once per objdir, but call pack-refs for the
            # remainder.
            if project.objdir not in tidy_dirs:
                tidy_dirs[project.objdir] = (
                    True,  # Run a full gc.
                    project.bare_git,
                )
            elif project.gitdir not in tidy_dirs:
                tidy_dirs[project.gitdir] = (
                    False,  # Do not run a full gc; just run pack-refs.
                    project.bare_git,
                )

        jobs = opt.jobs

        if jobs < 2:
            for run_gc, bare_git in tidy_dirs.values():
                pm.update(msg=bare_git._project.name)

                if run_gc:
                    cls._RunOneGC(bare_git._project)
                else:
                    bare_git.pack_refs()
            pm.end()
            return

        cpu_count = os.cpu_count()
        config = {"pack.threads": cpu_count // jobs if cpu_count > jobs else 1}

        threads = set()
        sem = _threading.Semaphore(jobs)

        def tidy_up(run_gc, bare_git):
            pm.start(bare_git._project.name)
            try:
                try:
                    if run_gc:
                        cls._RunOneGC(bare_git._project, config=config)
                    else:
                        bare_git.pack_refs(config=config)
                except GitError:
                    err_event.set()
                except Exception:
                    err_event.set()
                    raise
            finally:
                pm.finish(bare_git._project.name)
                sem.release()

        for run_gc, bare_git in tidy_dirs.values():
            if err_event.is_set() and opt.fail_fast:
                break
            sem.acquire()
            t = _threading.Thread(
                target=tidy_up,
                args=(
                    run_gc,
                    bare_git,
                ),
            )
            t.daemon = True
            threads.add(t)
            t.start()

        for t in threads:
            t.join()
        pm.end()

    @classmethod
    def _CheckOneBloatedProject(cls, project_index: int) -> Optional[str]:
        """Checks if a single project is bloated.

        Args:
            project_index: The index of the project in the parallel context.

        Returns:
            The name of the project if it is bloated, else None.
        """
        project = cls.get_parallel_context()["projects"][project_index]

        if not project.Exists or not project.worktree:
            return None

        # Only check dirty or locally modified projects. These can't be
        # freshly cloned and will accumulate garbage.
        try:
            status = project._GetStatusSnapshot(
                untracked_files="normal", branch=True
            )
            if status is not None:
                is_dirty = status.is_dirty(consider_untracked=True)
                head_rev = status.branch_oid
            else:
                is_dirty = project.IsDirty(consider_untracked=True)
                head_rev = project.work_git.rev_parse(HEAD)

            if head_rev is None:
                # Porcelain v2 reports an unborn branch as "(initial)".  The
                # legacy rev-parse path failed here and skipped the bloat
                # calculation, so preserve that behavior.
                return None

            manifest_rev = project.GetRevisionId(project.bare_ref.all)
            has_local_commits = manifest_rev != head_rev

            if not (is_dirty or has_local_commits):
                return None

            output = project.bare_git.count_objects("-v")
        except Exception:
            return None

        stats = {}
        for line in output.splitlines():
            try:
                key, value = line.split(": ", 1)
                stats[key.strip()] = int(value.strip())
            except ValueError:
                pass

        pack_count = stats.get("packs", 0)
        size_pack_kb = stats.get("size-pack", 0)
        size_garbage_kb = stats.get("size-garbage", 0)

        is_fragmented = (
            pack_count > _BLOAT_PACK_COUNT_THRESHOLD
            and size_pack_kb > _BLOAT_SIZE_PACK_THRESHOLD_KB
        )
        has_excessive_garbage = (
            size_garbage_kb > _BLOAT_SIZE_GARBAGE_THRESHOLD_KB
        )

        if is_fragmented or has_excessive_garbage:
            return project.name
        return None

    def _CheckForBloatedProjects(self, projects, opt):
        """Check for shallow projects that are accumulating unoptimized data.

        For projects with clone-depth="1" that are dirty (have local changes),
        run 'git count-objects -v' and warn if the repository is accumulating
        excessive pack files or garbage.
        """
        # We only care about bloated projects if we have a git version that
        # supports --no-auto-gc (2.23.0+) since what we use to disable auto-gc
        # in Project._RemoteFetch.
        if not git_require((2, 23, 0)):
            return

        projects = [
            p
            for p in projects
            if p.clone_depth and not p.stateless_prune_needed
        ]
        if not projects:
            return

        pm = Progress(
            "Checking for bloat", len(projects), delay=False, quiet=opt.quiet
        )

        def _ProcessResults(pool, pm, results):
            for result in results:
                if result:
                    self._bloated_projects.append(result)
                pm.update(msg="")

        with self.ParallelContext():
            self.get_parallel_context()["projects"] = projects
            self.ExecuteInParallel(
                opt.jobs,
                self._CheckOneBloatedProject,
                range(len(projects)),
                callback=_ProcessResults,
                output=pm,
                chunksize=1,
            )
        pm.end()

    def _UpdateRepoProject(self, opt, manifest, errors):
        """Fetch the repo project and check for updates."""
        if opt.local_only:
            return

        rp = manifest.repoProject
        now = time.time()
        # If we've fetched in the last day, don't bother fetching again.
        if (now - rp.LastFetch) < _ONE_DAY_S:
            return

        with multiprocessing.Manager() as manager:
            with ssh.ProxyManager(manager) as ssh_proxy:
                ssh_proxy.sock()
                start = time.time()
                buf = TeeStringIO(sys.stdout if opt.verbose else None)
                sync_result = rp.Sync_NetworkHalf(
                    quiet=opt.quiet,
                    verbose=opt.verbose,
                    output_redir=buf,
                    use_superproject=opt.use_superproject,
                    current_branch_only=self._GetCurrentBranchOnly(
                        opt, manifest
                    ),
                    force_sync=opt.force_sync,
                    clone_bundle=opt.clone_bundle,
                    tags=opt.tags,
                    archive=manifest.IsArchive,
                    optimized_fetch=opt.optimized_fetch,
                    retry_fetches=opt.retry_fetches,
                    prune=opt.prune,
                    ssh_proxy=ssh_proxy,
                    clone_filter=manifest.CloneFilter,
                    partial_clone_exclude=manifest.PartialCloneExclude,
                    clone_filter_for_depth=manifest.CloneFilterForDepth,
                )
                if sync_result.error:
                    errors.append(sync_result.error)

                finish = time.time()
                self.event_log.AddSync(
                    rp,
                    event_log.TASK_SYNC_NETWORK,
                    start,
                    finish,
                    sync_result.success,
                )
                if not sync_result.success:
                    logger.error("error: Cannot fetch repo tool %s", rp.name)
                    return

        # After fetching, check if a new version of repo is available and
        # restart. This is only done if the user hasn't explicitly disabled it.
        if os.environ.get("REPO_SKIP_SELF_UPDATE", "0") == "0":
            _PostRepoFetch(rp, opt.repo_verify)

    def _ReloadManifest(self, manifest_name, manifest):
        """Reload the manfiest from the file specified by the |manifest_name|.

        It unloads the manifest if |manifest_name| is None.

        Args:
            manifest_name: Manifest file to be reloaded.
            manifest: The manifest to use.
        """
        if manifest_name:
            # Override calls Unload already.
            manifest.Override(manifest_name)
        else:
            manifest.Unload()

    def UpdateProjectList(self, opt, manifest):
        """Update the cached projects list for |manifest|

        In a multi-manifest checkout, each manifest has its own project.list.

        Args:
            opt: Program options returned from optparse.  See _Options().
            manifest: The manifest to use.

        Returns:
            0: success
            1: failure
        """
        new_project_paths = []
        for project in self.GetProjects(
            None, missing_ok=True, manifest=manifest, all_manifests=False
        ):
            if project.relpath:
                new_project_paths.append(project.relpath)
        file_name = "project.list"
        file_path = os.path.join(manifest.subdir, file_name)
        old_project_paths = []

        if os.path.exists(file_path):
            with open(file_path) as fd:
                old_project_paths = fd.read().split("\n")
            # In reversed order, so subfolders are deleted before parent folder.
            for path in sorted(old_project_paths, reverse=True):
                if not path:
                    continue
                if path not in new_project_paths:
                    # If the path has already been deleted, we don't need to do
                    # it.
                    gitdir = os.path.join(manifest.topdir, path, ".git")
                    if os.path.exists(gitdir):
                        project = Project(
                            manifest=manifest,
                            name=path,
                            remote=RemoteSpec("origin"),
                            gitdir=gitdir,
                            objdir=gitdir,
                            use_git_worktrees=os.path.isfile(gitdir),
                            worktree=os.path.join(manifest.topdir, path),
                            relpath=path,
                            revisionExpr="HEAD",
                            revisionId=None,
                            groups=None,
                        )
                        project.DeleteWorktree(
                            verbose=opt.verbose, force=opt.force_remove_dirty
                        )

        new_project_paths.sort()
        with open(file_path, "w") as fd:
            fd.write("\n".join(new_project_paths))
            fd.write("\n")
        return 0

    def UpdateCopyLinkfileList(self, manifest):
        """Save all dests of copyfile and linkfile, and update them if needed.

        Returns:
            Whether update was successful.
        """
        new_paths = {}
        new_linkfile_paths = []
        new_copyfile_paths = []
        projects = self.GetProjects(
            None, missing_ok=True, manifest=manifest, all_manifests=False
        )
        for project in projects:
            new_linkfile_paths.extend(x.dest for x in project.linkfiles)
            new_copyfile_paths.extend(x.dest for x in project.copyfiles)

        new_paths = {
            "linkfile": new_linkfile_paths,
            "copyfile": new_copyfile_paths,
        }

        copylinkfile_name = "copy-link-files.json"
        copylinkfile_path = os.path.join(manifest.subdir, copylinkfile_name)
        old_copylinkfile_paths = {}

        if os.path.exists(copylinkfile_path):
            with open(copylinkfile_path, "rb") as fp:
                try:
                    old_copylinkfile_paths = json.load(fp)
                except Exception:
                    logger.error(
                        "error: %s is not a json formatted file.",
                        copylinkfile_path,
                    )
                    platform_utils.remove(copylinkfile_path)
                    raise

            need_remove_files = []
            need_remove_files.extend(
                set(old_copylinkfile_paths.get("linkfile", []))
                - set(new_linkfile_paths)
            )
            need_remove_files.extend(
                set(old_copylinkfile_paths.get("copyfile", []))
                - set(new_copyfile_paths)
            )

            for need_remove_file in need_remove_files:
                need_remove_path = os.path.join(
                    self.client.topdir, need_remove_file
                )
                if os.path.isfile(need_remove_path):
                    platform_utils.remove(need_remove_path)
                else:
                    platform_utils.removedirs(need_remove_path)

                # Also try to remove empty parent directories.
                parent = os.path.dirname(need_remove_path)
                while parent != self.client.topdir:
                    try:
                        os.rmdir(parent)
                    except OSError:
                        break
                    parent = os.path.dirname(parent)

        # Create copy-link-files.json, save dest path of "copyfile" and
        # "linkfile".
        with open(copylinkfile_path, "w", encoding="utf-8") as fp:
            json.dump(new_paths, fp)

        # Retry linkfile/copyfile creation for all projects.  In
        # interleaved sync mode, _CopyAndLinkFiles runs before this
        # cleanup, so linkfiles whose dest was blocked by an old
        # directory may have failed.  _CopyAndLinkFiles is idempotent
        # and skips dests that are already correct.
        for project in projects:
            project._CopyAndLinkFiles()

        return True

    def _ResolveManifestServerTransport(self, opt, manifest):
        """Resolves the manifest server URL and transport.

        Returns:
            Tuple[str, xmlrpc.client.Transport]: The resolved server URL and
                transport.

        Raises:
            SmartSyncError: If resolution fails (e.g. helper missing, helper
                error, unsupported scheme).
        """
        manifest_server = manifest.manifest_server
        helper_binary = manifest.manifest_server_helper

        if helper_binary:
            if not shutil.which(helper_binary):
                raise SmartSyncError(
                    f"error: helper binary '{helper_binary}' declared in "
                    "manifest was not found in your PATH."
                )

            if not opt.quiet:
                print(f"Using remote helper {helper_binary}")

            p = None
            try:
                p = subprocess.Popen(
                    [helper_binary, manifest_server],
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    text=True,
                )
                stdout, stderr = p.communicate(timeout=10)
                output = stdout.strip()
                stderr_content = stderr.strip() if stderr else ""
            except subprocess.TimeoutExpired as e:
                err_msg = f"helper {helper_binary} timed out after 10 seconds"
                timeout_stderr = e.stderr.strip() if e.stderr else ""
                if timeout_stderr:
                    err_msg += f". Stderr: {timeout_stderr}"
                raise SmartSyncError(err_msg)
            except OSError as e:
                raise SmartSyncError(
                    "failed to start or communicate with helper "
                    f"{helper_binary}: {e}"
                )
            finally:
                if p and p.poll() is None:
                    p.kill()
                    p.wait()

            if p.returncode != 0:
                err_msg = (
                    f"helper {helper_binary} exited with exit code "
                    f"{p.returncode}."
                )
                if stderr_content:
                    err_msg += f" Stderr: {stderr_content}"
                raise SmartSyncError(err_msg)

            try:
                res = json.loads(output)
                status = res.get("status")
                msg = res.get("message")
            except json.JSONDecodeError as e:
                err_msg = (
                    f"failed to parse JSON from helper {helper_binary}: {e}. "
                    f"Output was: {output}"
                )
                if stderr_content:
                    err_msg += f"\nStderr was: {stderr_content}"
                raise SmartSyncError(err_msg)

            if status != "ok":
                err_msg = f"helper {helper_binary} returned error: {msg}"
                if stderr_content:
                    err_msg += f"\nStderr was: {stderr_content}"
                raise SmartSyncError(err_msg)

            proxy_url = msg
            transport = PersistentTransport(manifest_server, proxy=proxy_url)
            server_url = manifest_server
            if server_url.startswith("persistent-"):
                server_url = server_url[len("persistent-") :]
            return server_url, transport

        # Fallback path if helper isn't specified
        scheme = urllib.parse.urlparse(manifest_server).scheme
        if scheme not in (
            "http",
            "https",
            "persistent-http",
            "persistent-https",
        ):
            raise SmartSyncError(
                f"error: unsupported manifest server scheme '{scheme}'."
            )

        if "@" not in manifest_server:
            username = None
            password = None
            if opt.manifest_server_username and opt.manifest_server_password:
                username = opt.manifest_server_username
                password = opt.manifest_server_password
            else:
                try:
                    info = netrc.netrc()
                except OSError:
                    # .netrc file does not exist or could not be opened.
                    pass
                else:
                    try:
                        parse_result = urllib.parse.urlparse(manifest_server)
                        if parse_result.hostname:
                            auth = info.authenticators(parse_result.hostname)
                            if auth:
                                username, _account, password = auth
                            else:
                                logger.error(
                                    "No credentials found for %s in .netrc",
                                    parse_result.hostname,
                                )
                    except netrc.NetrcParseError as e:
                        logger.error("Error parsing .netrc file: %s", e)

            if username and password:
                manifest_server = manifest_server.replace(
                    "://", f"://{username}:{password}@", 1
                )

        transport = PersistentTransport(manifest_server)
        server_url = manifest_server
        if server_url.startswith("persistent-"):
            server_url = server_url[len("persistent-") :]

        return server_url, transport

    def _SmartSyncSetup(self, opt, smart_sync_manifest_path, manifest):
        if not manifest.manifest_server:
            raise SmartSyncError(
                "error: cannot smart sync: no manifest server defined in "
                "manifest"
            )

        if not opt.quiet:
            print("Using manifest server %s" % manifest.manifest_server)

        server_url, transport = self._ResolveManifestServerTransport(
            opt, manifest
        )

        # Changes in behavior should update docs/smart-sync.md accordingly.
        try:
            server = xmlrpc.client.Server(server_url, transport=transport)
            if opt.smart_sync:
                branch = self._GetBranch(manifest.manifestProject)
                target = None
                if "SYNC_TARGET" in os.environ:
                    target = os.environ["SYNC_TARGET"]
                elif (
                    "TARGET_PRODUCT" in os.environ
                    and "TARGET_BUILD_VARIANT" in os.environ
                    and "TARGET_RELEASE" in os.environ
                ):
                    target = "%s-%s-%s" % (
                        os.environ["TARGET_PRODUCT"],
                        os.environ["TARGET_RELEASE"],
                        os.environ["TARGET_BUILD_VARIANT"],
                    )
                elif (
                    "TARGET_PRODUCT" in os.environ
                    and "TARGET_BUILD_VARIANT" in os.environ
                ):
                    target = "%s-%s" % (
                        os.environ["TARGET_PRODUCT"],
                        os.environ["TARGET_BUILD_VARIANT"],
                    )

                if target:
                    [success, manifest_str] = server.GetApprovedManifest(
                        branch, target
                    )
                else:
                    [success, manifest_str] = server.GetApprovedManifest(branch)
            else:
                assert opt.smart_tag
                [success, manifest_str] = server.GetManifest(opt.smart_tag)

            if success:
                manifest_name = os.path.basename(smart_sync_manifest_path)
                try:
                    with open(smart_sync_manifest_path, "w") as f:
                        f.write(manifest_str)
                except OSError as e:
                    raise SmartSyncError(
                        "error: cannot write manifest to %s:\n%s"
                        % (smart_sync_manifest_path, e),
                        aggregate_errors=[e],
                    )
                self._ReloadManifest(manifest_name, manifest)
                return manifest_name

            raise SmartSyncError(
                "error: manifest server RPC call failed: %s" % manifest_str
            )
        except (OSError, xmlrpc.client.Fault) as e:
            if manifest.manifest_server_helper:
                raise SmartSyncError(
                    "error: failed to communicate with manifest server via "
                    f"helper: {e}"
                )
            raise SmartSyncError(
                "error: cannot connect to manifest server %s:\n%s"
                % (manifest.manifest_server, e),
                aggregate_errors=[e],
            )
        except xmlrpc.client.ProtocolError as e:
            if manifest.manifest_server_helper:
                raise SmartSyncError(
                    "error: failed to communicate with manifest server via "
                    f"helper: {e}"
                )
            raise SmartSyncError(
                "error: cannot connect to manifest server %s:\n%d %s"
                % (manifest.manifest_server, e.errcode, e.errmsg),
                aggregate_errors=[e],
            )

    def _UpdateAllManifestProjects(self, opt, mp, manifest_name, errors):
        """Fetch & update the local manifest project.

        After syncing the manifest project, if the manifest has any sub
        manifests, those are recursively processed.

        Args:
            opt: Program options returned from optparse.  See _Options().
            mp: the manifestProject to query.
            manifest_name: Manifest file to be reloaded.
        """
        if opt.superproject_revision and mp.manifest == self.outer_manifest:
            self._SyncToSuperprojectRev(
                opt, mp.manifest, mp, manifest_name, errors
            )
        elif not mp.standalone_manifest_url:
            self._UpdateManifestProject(opt, mp, manifest_name, errors)

        if mp.manifest.submanifests:
            for submanifest in mp.manifest.submanifests.values():
                child = submanifest.repo_client.manifest
                child.manifestProject.SyncWithPossibleInit(
                    submanifest,
                    current_branch_only=self._GetCurrentBranchOnly(opt, child),
                    verbose=opt.verbose,
                    tags=opt.tags,
                    git_event_log=self.git_event_log,
                )
                self._UpdateAllManifestProjects(
                    opt, child.manifestProject, None, errors
                )

    def _UpdateManifestProject(self, opt, mp, manifest_name, errors):
        """Fetch & update the local manifest project.

        Args:
            opt: Program options returned from optparse.  See _Options().
            mp: the manifestProject to query.
            manifest_name: Manifest file to be reloaded.
        """
        if not opt.local_only:
            start = time.time()
            buf = TeeStringIO(sys.stdout)
            try:
                result = mp.Sync_NetworkHalf(
                    quiet=not opt.verbose,
                    output_redir=buf,
                    verbose=opt.verbose,
                    use_superproject=opt.use_superproject,
                    current_branch_only=self._GetCurrentBranchOnly(
                        opt, mp.manifest
                    ),
                    force_sync=opt.force_sync,
                    tags=opt.tags,
                    optimized_fetch=opt.optimized_fetch,
                    retry_fetches=opt.retry_fetches,
                    submodules=mp.manifest.HasSubmodules,
                    clone_filter=mp.manifest.CloneFilter,
                    partial_clone_exclude=mp.manifest.PartialCloneExclude,
                    clone_filter_for_depth=mp.manifest.CloneFilterForDepth,
                )
                if result.error:
                    errors.append(result.error)
            except KeyboardInterrupt:
                errors.append(
                    ManifestInterruptError(buf.getvalue(), project=mp.name)
                )
                raise

            finish = time.time()
            self.event_log.AddSync(
                mp, event_log.TASK_SYNC_NETWORK, start, finish, result.success
            )

        if mp.HasChanges:
            errors = []
            syncbuf = SyncBuffer(mp.config)
            start = time.time()
            mp.Sync_LocalHalf(
                syncbuf,
                submodules=mp.manifest.HasSubmodules,
                verbose=opt.verbose,
            )
            clean = syncbuf.Finish()
            errors.extend(syncbuf.errors)
            self.event_log.AddSync(
                mp, event_log.TASK_SYNC_LOCAL, start, time.time(), clean
            )
            if not clean:
                raise UpdateManifestError(aggregate_errors=errors)
            self._ReloadManifest(manifest_name, mp.manifest)

    def ValidateOptions(self, opt, args):
        if opt.force_broken:
            logger.warning(
                "warning: -f/--force-broken is now the default behavior, and "
                "the options are deprecated"
            )
        if opt.network_only and opt.detach_head:
            self.OptionParser.error("cannot combine -n and -d")
        if opt.network_only and opt.local_only:
            self.OptionParser.error("cannot combine -n and -l")
        if opt.manifest_name and opt.smart_sync:
            self.OptionParser.error("cannot combine -m and -s")
        if opt.manifest_name and opt.smart_tag:
            self.OptionParser.error("cannot combine -m and -t")
        if opt.manifest_server_username or opt.manifest_server_password:
            if not (opt.smart_sync or opt.smart_tag):
                self.OptionParser.error(
                    "-u and -p may only be combined with -s or -t"
                )
            if None in [
                opt.manifest_server_username,
                opt.manifest_server_password,
            ]:
                self.OptionParser.error("both -u and -p must be given")

        if opt.prune is None:
            opt.prune = True

    def _ValidateOptionsWithManifest(self, opt, mp):
        """Like ValidateOptions, but after we've updated the manifest.

        Needed to handle sync-xxx option defaults in the manifest.

        Args:
            opt: The options to process.
            mp: The manifest project to pull defaults from.
        """
        if not opt.jobs:
            # If the user hasn't made a choice, use the manifest value.
            opt.jobs = mp.manifest.default.sync_j
        if opt.jobs:
            # If --jobs has a non-default value, propagate it as the default for
            # --jobs-xxx flags too.
            if not opt.jobs_network:
                opt.jobs_network = opt.jobs
            if not opt.jobs_checkout:
                opt.jobs_checkout = opt.jobs
        else:
            # Neither user nor manifest have made a choice, so setup defaults.
            if not opt.jobs_network:
                opt.jobs_network = 1
            if not opt.jobs_checkout:
                opt.jobs_checkout = DEFAULT_LOCAL_JOBS
            opt.jobs = os.cpu_count()

        # Try to stay under user rlimit settings.
        #
        # Since each worker requires at 3 file descriptors to run `git fetch`,
        # use that to scale down the number of jobs.  Unfortunately there isn't
        # an easy way to determine this reliably as systems change, but it was
        # last measured by hand in 2011.
        soft_limit, _ = _rlimit_nofile()
        jobs_soft_limit = max(1, (soft_limit - 5) // 3)
        opt.jobs = min(opt.jobs, jobs_soft_limit)
        opt.jobs_network = min(opt.jobs_network, jobs_soft_limit)
        opt.jobs_checkout = min(opt.jobs_checkout, jobs_soft_limit)

        sync_j_max = mp.manifest.default.sync_j_max or None

        # Check for shared options.
        # Prioritize --jobs, then --jobs-network, then --jobs-checkout.
        job_attributes = (
            ("--jobs", "jobs"),
            ("--jobs-network", "jobs_network"),
            ("--jobs-checkout", "jobs_checkout"),
        )

        warned = False
        limit_warned = False
        for name, attr in job_attributes:
            value = getattr(opt, attr)

            if sync_j_max and value > sync_j_max:
                if not limit_warned:
                    logger.warning(
                        "warning: manifest limits %s to %d",
                        name,
                        sync_j_max,
                    )
                    limit_warned = True
                setattr(opt, attr, sync_j_max)
                value = sync_j_max

            if not warned and value > self._JOBS_WARN_THRESHOLD:
                logger.warning(
                    "High job count (%d > %d) specified for %s; this may "
                    "lead to excessive resource usage or diminishing returns.",
                    value,
                    self._JOBS_WARN_THRESHOLD,
                    name,
                )
                warned = True

    def Execute(self, opt, args):
        errors = []
        start_time = time.time()
        try:
            self._ExecuteHelper(opt, args, errors)
            sync_duration_seconds = time.time() - start_time
        except (RepoExitError, RepoChangedException):
            raise
        except (KeyboardInterrupt, Exception) as e:
            raise RepoUnhandledExceptionError(e, aggregate_errors=errors)

        # Run post-sync hook only after successful sync
        self._RunPostSyncHook(opt, sync_duration_seconds=sync_duration_seconds)

    def _RunPostSyncHook(self, opt, sync_duration_seconds=None):
        """Run post-sync hook if configured in manifest <repo-hooks>."""
        hook = RepoHook.FromSubcmd(
            hook_type="post-sync",
            manifest=self.manifest,
            opt=opt,
            abort_if_user_denies=False,
        )
        success = hook.Run(
            repo_topdir=self.client.topdir,
            sync_duration_seconds=sync_duration_seconds,
        )
        if not success:
            print("Warning: post-sync hook reported failure.")

    def _SyncToSuperprojectRev(
        self,
        opt: optparse.Values,
        manifest,
        mp: Project,
        manifest_name: Optional[str],
        errors: List[Exception],
    ) -> None:
        """Sync to a specific superproject commit."""
        if not manifest.superproject:
            raise SyncError("superproject not defined in manifest")

        self._ConfigureSuperproject(
            opt, manifest, revision=opt.superproject_revision
        )

        sync_result = manifest.superproject.Sync(self.git_event_log)
        if not sync_result.success:
            raise SyncError("failed to sync superproject")

        cmd = ["show", f"{opt.superproject_revision}:.supermanifest"]
        p = GitCommand(
            None,
            cmd,
            gitdir=manifest.superproject._work_git,
            bare=True,
            capture_stdout=True,
            capture_stderr=True,
        )
        if p.Wait() != 0:
            raise SyncError(
                f"failed to read .supermanifest from superproject: {p.stderr}"
            )

        try:
            _, _, manifest_commit = p.stdout.strip().split()
        except ValueError:
            raise SyncError("could not parse .supermanifest")

        mp.SetRevision(manifest_commit)
        try:
            self._UpdateManifestProject(opt, mp, manifest_name, errors)
        except UpdateManifestError as e:
            raise SyncError(
                "failed to sync manifest project", aggregate_errors=[e]
            )

    def _ExecuteHelper(self, opt, args, errors):
        manifest = self.outer_manifest
        if not opt.outer_manifest:
            manifest = self.manifest

        if opt.manifest_name:
            manifest.Override(opt.manifest_name)

        manifest_name = opt.manifest_name
        smart_sync_manifest_path = self.GetSmartSyncOverridePath(manifest)

        if opt.clone_bundle is None:
            opt.clone_bundle = manifest.CloneBundle

        if opt.smart_sync or opt.smart_tag:
            manifest_name = self._SmartSyncSetup(
                opt, smart_sync_manifest_path, manifest
            )
        else:
            if os.path.isfile(smart_sync_manifest_path):
                try:
                    platform_utils.remove(smart_sync_manifest_path)
                except OSError as e:
                    logger.error(
                        "error: failed to remove existing smart sync override "
                        "manifest: %s",
                        e,
                    )

        rp = manifest.repoProject
        rp.PreSync()
        cb = rp.CurrentBranch
        if cb:
            base = rp.GetBranch(cb).merge
            if not base or not base.startswith("refs/heads/"):
                logger.warning(
                    "warning: repo is not tracking a remote branch, so it will "
                    "not receive updates; run `repo init --repo-rev=stable` to "
                    "fix."
                )

        for m in self.ManifestList(opt):
            if not m.manifestProject.standalone_manifest_url:
                m.manifestProject.PreSync()

        if opt.repo_upgraded:
            _PostRepoUpgrade(manifest, quiet=opt.quiet)

        mp = manifest.manifestProject

        if _REPO_ALLOW_SHALLOW is not None:
            if _REPO_ALLOW_SHALLOW == "1":
                mp.ConfigureCloneFilterForDepth(None)
            elif (
                _REPO_ALLOW_SHALLOW == "0" and mp.clone_filter_for_depth is None
            ):
                mp.ConfigureCloneFilterForDepth("blob:none")

        if opt.mp_update or opt.superproject_revision:
            self._UpdateAllManifestProjects(opt, mp, manifest_name, errors)
        else:
            print("Skipping update of local manifest project.")

        # Now that the manifests are up-to-date, setup options whose defaults
        # might be in the manifest.
        self._ValidateOptionsWithManifest(opt, mp)

        # Update the repo project and check for new versions of repo.
        self._UpdateRepoProject(opt, manifest, errors)

        superproject_logging_data = {}
        self._UpdateProjectsRevisionId(
            opt, args, superproject_logging_data, manifest
        )

        all_projects = self.GetProjects(
            args,
            groups=opt.groups,
            missing_ok=True,
            submodules_ok=opt.recurse_submodules,
            manifest=manifest,
            all_manifests=not opt.this_manifest_only,
        )
        self._CheckReprojectCmdNesting(opt, args, manifest, all_projects)

        # Log the repo projects by existing and new.
        existing = [x for x in all_projects if x.Exists]
        mp.config.SetString("repo.existingprojectcount", str(len(existing)))
        mp.config.SetString(
            "repo.newprojectcount", str(len(all_projects) - len(existing))
        )

        self._fetch_times = _FetchTimes(manifest)
        self._local_sync_state = LocalSyncState(manifest)
        self._bloated_projects = []

        if opt.interleaved:
            sync_method = self._SyncInterleaved
        else:
            sync_method = self._SyncPhased

        sync_method(
            opt,
            args,
            errors,
            manifest,
            mp,
            all_projects,
            superproject_logging_data,
        )

        if not opt.quiet:
            print("Finalizing sync state...")

        # Log the previous sync analysis state from the config.
        self.git_event_log.LogDataConfigEvents(
            mp.config.GetSyncAnalysisStateData(), "previous_sync_state"
        )

        # Update and log with the new sync analysis state.
        mp.config.UpdateSyncAnalysisState(opt, superproject_logging_data)
        self.git_event_log.LogDataConfigEvents(
            mp.config.GetSyncAnalysisStateData(), "current_sync_state"
        )

        self._local_sync_state.PruneRemovedProjects()
        if self._local_sync_state.IsPartiallySynced():
            logger.warning(
                "warning: Partial syncs are not supported. For the best "
                "experience, sync the entire tree."
            )

        if existing:
            self._CheckForBloatedProjects(all_projects, opt)

        for project_name in sorted(self._bloated_projects):
            warn_msg = (
                f'warning: Project "{project_name}" is accumulating '
                'unoptimized data. Please run "git repack -a -d" in the '
                'project directory or "repo gc --repack" to clean up.'
            )
            self.git_event_log.ErrorEvent(warn_msg)
            logger.warning(warn_msg)

        if not opt.quiet:
            print("repo sync has finished successfully.")

    def _CheckReprojectCmdNesting(
        self,
        opt: optparse.Values,
        args: List[str],
        manifest: XmlManifest,
        all_projects: List[Project],
    ) -> None:
        """Fail when repo.reprojectcmd is used on a manifest nesting projects.

        The command materializes a project's tree without Git, so nothing
        keeps it from clobbering a project or submodule checked out inside
        that tree. See docs/reproject-cmd.md.
        """
        if not any(p.UseReprojectCmd for p in all_projects):
            return
        projects = all_projects
        if args:
            # Nesting is a property of the manifest, not of the projects
            # picked on the command line.
            projects = self.GetProjects(
                [],
                groups=opt.groups,
                missing_ok=True,
                submodules_ok=opt.recurse_submodules,
                manifest=manifest,
                all_manifests=not opt.this_manifest_only,
            )
        nested = _NestedProjects(projects)
        if not nested:
            return
        e = SyncError(
            "error: repo.reprojectcmd does not support nested projects or "
            "submodules; found:\n"
            + "\n".join(
                f" - {p.RelPath(local=opt.this_manifest_only)}" for p in nested
            )
        )
        logger.error(e)
        raise e

    def _CreateSyncProgressThread(
        self, pm: Progress, stop_event: _threading.Event
    ) -> _threading.Thread:
        """Creates and returns a daemon thread to update a Progress object.

        The returned thread is not yet started. The thread will periodically
        update the progress bar with information from _GetSyncProgressMessage
        until the stop_event is set.

        Args:
            pm: The Progress object to update.
            stop_event: The threading.Event to signal the monitor to stop.

        Returns:
            The configured _threading.Thread object.
        """

        def _monitor_loop():
            """The target function for the monitor thread."""
            while True:
                # Update the progress bar with the current status message.
                pm.update(inc=0, msg=self._GetSyncProgressMessage())
                # Wait for 1 second or until the stop_event is set.
                if stop_event.wait(timeout=1):
                    return

        return _threading.Thread(target=_monitor_loop, daemon=True)

    def _UpdateManifestLists(
        self,
        opt: optparse.Values,
        err_event: multiprocessing.Event,
        errors: List[Exception],
    ) -> Tuple[bool, bool]:
        """Updates project lists and copy/link files for all manifests.

        Args:
            opt: Program options from optparse.
            err_event: An event to set if any error occurs.
            errors: A list to append any encountered exceptions to.

        Returns:
            A tuple (err_update_projects, err_update_linkfiles) indicating
                an error for each task.
        """
        err_update_projects = False
        err_update_linkfiles = False
        for m in self.ManifestList(opt):
            if m.IsMirror or m.IsArchive:
                continue

            try:
                self.UpdateProjectList(opt, m)
            except Exception as e:
                err_event.set()
                err_update_projects = True
                errors.append(e)
                if isinstance(e, DeleteWorktreeError):
                    errors.extend(e.aggregate_errors)
                if opt.fail_fast:
                    logger.error("error: Local checkouts *not* updated.")
                    raise SyncFailFastError(aggregate_errors=errors)

            try:
                self.UpdateCopyLinkfileList(m)
            except Exception as e:
                err_event.set()
                err_update_linkfiles = True
                errors.append(e)
                if opt.fail_fast:
                    logger.error(
                        "error: Local update copyfile or linkfile failed."
                    )
                    raise SyncFailFastError(aggregate_errors=errors)
        return err_update_projects, err_update_linkfiles

    def _ReportErrors(
        self,
        errors,
        err_network_sync=False,
        failing_network_repos=None,
        err_checkout=False,
        failing_checkout_repos=None,
        err_update_projects=False,
        err_update_linkfiles=False,
    ):
        """Logs detailed error messages and raises a SyncError."""

        def print_and_log(err_msg):
            self.git_event_log.ErrorEvent(err_msg)
            logger.error("%s", err_msg)

        print_and_log("error: Unable to fully sync the tree")
        if err_network_sync:
            print_and_log("error: Downloading network changes failed.")
            if failing_network_repos:
                logger.error(
                    "Failing repos (network):\n%s",
                    "\n".join(sorted(failing_network_repos)),
                )
        if err_update_projects:
            print_and_log("error: Updating local project lists failed.")
        if err_update_linkfiles:
            print_and_log("error: Updating copyfiles or linkfiles failed.")
        if err_checkout:
            print_and_log("error: Checking out local projects failed.")
            if failing_checkout_repos:
                logger.error(
                    "Failing repos (checkout):\n%s",
                    "\n".join(sorted(failing_checkout_repos)),
                )
        logger.error(
            'Try re-running with "-j1 --fail-fast" to exit at the first error.'
        )
        raise SyncError(aggregate_errors=errors)

    def _SyncPhased(
        self,
        opt,
        args,
        errors,
        manifest,
        mp,
        all_projects,
        superproject_logging_data,
    ):
        """Sync projects by separating network and local operations.

        This method performs sync in two distinct, sequential phases:
        1.  Network Phase: Fetches updates for all projects from their remotes.
        2.  Local Phase: Checks out the updated revisions into the local
            worktrees for all projects.

        This approach ensures that the local work-tree is not modified until
        all network operations are complete, providing a transactional-like
        safety net for the checkout state.
        """
        err_event = multiprocessing.Event()
        err_network_sync = False
        err_update_projects = False
        err_update_linkfiles = False

        if not opt.local_only:
            with multiprocessing.Manager() as manager:
                with ssh.ProxyManager(manager) as ssh_proxy:
                    # Initialize the socket dir once in the parent.
                    ssh_proxy.sock()
                    result = self._FetchMain(
                        opt,
                        args,
                        all_projects,
                        err_event,
                        ssh_proxy,
                        manifest,
                        errors,
                    )
                    all_projects = result.all_projects

            if opt.network_only:
                return

            # If we saw an error, exit with code 1 so that other scripts can
            # check.
            if err_event.is_set():
                err_network_sync = True
                if opt.fail_fast:
                    logger.error(
                        "error: Exited sync due to fetch errors.\n"
                        "Local checkouts *not* updated. Resolve network issues "
                        "& retry.\n"
                        "`repo sync -l` will update some local checkouts."
                    )
                    raise SyncFailFastError(aggregate_errors=errors)

        err_update_projects, err_update_linkfiles = self._UpdateManifestLists(
            opt,
            err_event,
            errors,
        )

        err_results = []
        # NB: We don't exit here because this is the last step.
        err_checkout = not self._Checkout(
            all_projects, opt, err_results, errors
        )
        if err_checkout:
            err_event.set()

        self._PrintManifestNotices(opt)

        # If we saw an error, exit with code 1 so that other scripts can check.
        if err_event.is_set():
            self._ReportErrors(
                errors,
                err_network_sync=err_network_sync,
                err_checkout=err_checkout,
                failing_checkout_repos=err_results,
                err_update_projects=err_update_projects,
                err_update_linkfiles=err_update_linkfiles,
            )

    @classmethod
    def _SyncOneProject(cls, opt, project_index, project) -> _SyncResult:
        """Syncs a single project for interleaved sync."""
        fetch_success = False
        remote_fetched = False
        fetch_errors = []
        fetch_start = None
        fetch_finish = None
        network_output = ""

        if opt.local_only:
            fetch_success = True
        else:
            fetch_start = time.time()
            network_output_capture = io.StringIO()
            try:
                ssh_proxy = cls.get_parallel_context().get("ssh_proxy")
                sync_result = project.Sync_NetworkHalf(
                    quiet=opt.quiet,
                    verbose=opt.verbose,
                    output_redir=network_output_capture,
                    use_superproject=opt.use_superproject,
                    current_branch_only=cls._GetCurrentBranchOnly(
                        opt, project.manifest
                    ),
                    force_sync=opt.force_sync,
                    clone_bundle=opt.clone_bundle,
                    tags=opt.tags,
                    archive=project.manifest.IsArchive,
                    optimized_fetch=opt.optimized_fetch,
                    retry_fetches=opt.retry_fetches,
                    prune=opt.prune,
                    ssh_proxy=ssh_proxy,
                    clone_filter=project.manifest.CloneFilter,
                    partial_clone_exclude=project.manifest.PartialCloneExclude,
                    clone_filter_for_depth=project.manifest.CloneFilterForDepth,
                )
                fetch_success = sync_result.success
                remote_fetched = sync_result.remote_fetched
                if sync_result.error:
                    fetch_errors.append(sync_result.error)
            except KeyboardInterrupt:
                logger.error(
                    "Keyboard interrupt while processing %s", project.name
                )
                if not cls.is_multiprocessing_active():
                    raise
            except GitError as e:
                fetch_errors.append(e)
                logger.error("error.GitError: Cannot fetch %s", e)
            except Exception as e:
                fetch_errors.append(e)
                logger.error(
                    "error: Cannot fetch %s (%s: %s)",
                    project.name,
                    type(e).__name__,
                    e,
                )
            finally:
                fetch_finish = time.time()
                network_output = network_output_capture.getvalue()

        checkout_success = False
        checkout_errors = []
        checkout_start = None
        checkout_finish = None
        checkout_stderr = ""

        if fetch_success:
            # We skip checkout if it's network-only or if the project has no
            # working tree (e.g., a mirror).
            if opt.network_only or not project.worktree:
                checkout_success = True
            else:
                # This is a normal project that needs a checkout.
                checkout_start = time.time()
                stderr_capture = io.StringIO()
                try:
                    with contextlib.redirect_stderr(stderr_capture):
                        syncbuf = SyncBuffer(
                            project.manifest.manifestProject.config,
                            detach_head=opt.detach_head,
                        )
                        project.Sync_LocalHalf(
                            syncbuf,
                            force_sync=opt.force_sync,
                            force_checkout=opt.force_checkout,
                            force_rebase=opt.rebase,
                            verbose=opt.verbose,
                        )
                        checkout_success = syncbuf.Finish()
                        if syncbuf.errors:
                            checkout_errors.extend(syncbuf.errors)
                except KeyboardInterrupt:
                    logger.error(
                        "Keyboard interrupt while processing %s", project.name
                    )
                    if not cls.is_multiprocessing_active():
                        raise
                except GitError as e:
                    checkout_errors.append(e)
                    logger.error(
                        "error.GitError: Cannot checkout %s: %s",
                        project.name,
                        e,
                    )
                except Exception as e:
                    checkout_errors.append(e)
                    logger.error(
                        "error: Cannot checkout %s: %s: %s",
                        project.name,
                        type(e).__name__,
                        e,
                    )
                finally:
                    checkout_finish = time.time()
                    checkout_stderr = stderr_capture.getvalue()

        # Consolidate all captured output.
        captured_parts = []
        if network_output:
            captured_parts.append(network_output)
        if checkout_stderr:
            captured_parts.append(checkout_stderr)
        stderr_text = "\n".join(captured_parts)

        return _SyncResult(
            project_index=project_index,
            relpath=project.RelPath(local=opt.this_manifest_only),
            fetch_success=fetch_success,
            remote_fetched=remote_fetched,
            checkout_success=checkout_success,
            fetch_errors=fetch_errors,
            checkout_errors=checkout_errors,
            stderr_text=stderr_text.strip(),
            fetch_start=fetch_start,
            fetch_finish=fetch_finish,
            checkout_start=checkout_start,
            checkout_finish=checkout_finish,
        )

    @classmethod
    def _SyncProjectList(cls, opt, project_indices) -> _InterleavedSyncResult:
        """Worker for interleaved sync.

        This function is responsible for syncing a group of projects that share
        a git object directory.

        Args:
            opt: Program options returned from optparse.  See _Options().
            project_indices: A list of indices into the projects list stored in
                the parallel context.

        Returns:
            An `_InterleavedSyncResult` containing the results for each project.
        """
        results = []
        context = cls.get_parallel_context()
        projects = context["projects"]
        sync_dict = context["sync_dict"]

        assert project_indices, "_SyncProjectList called with no indices."

        # Use the first project as the representative for the progress bar.
        first_project = projects[project_indices[0]]
        key = f"{first_project.name} @ {first_project.relpath}"
        sync_dict[key] = time.time()

        try:
            for idx in project_indices:
                project = projects[idx]
                results.append(cls._SyncOneProject(opt, idx, project))
        finally:
            del sync_dict[key]

        return _InterleavedSyncResult(results=results)

    def _ProcessSyncInterleavedResults(
        self,
        finished_relpaths: Set[str],
        err_event: _threading.Event,
        errors: List[Exception],
        opt: optparse.Values,
        pool: Optional[multiprocessing.Pool],
        pm: Progress,
        results_sets: List[_InterleavedSyncResult],
    ):
        """Callback to process results from interleaved sync workers."""
        ret = True
        projects = self.get_parallel_context()["projects"]
        for result_group in results_sets:
            for result in result_group.results:
                pm.update()
                project = projects[result.project_index]

                success = result.fetch_success and result.checkout_success
                if result.stderr_text and (opt.verbose or not success):
                    pm.display_message(result.stderr_text)

                if result.fetch_start:
                    self._fetch_times.Set(
                        project,
                        result.fetch_finish - result.fetch_start,
                    )
                    self._local_sync_state.SetFetchTime(project)
                    self.event_log.AddSync(
                        project,
                        event_log.TASK_SYNC_NETWORK,
                        result.fetch_start,
                        result.fetch_finish,
                        result.fetch_success,
                    )
                if result.checkout_start:
                    if result.checkout_success:
                        self._local_sync_state.SetCheckoutTime(project)
                    self.event_log.AddSync(
                        project,
                        event_log.TASK_SYNC_LOCAL,
                        result.checkout_start,
                        result.checkout_finish,
                        result.checkout_success,
                    )

                finished_relpaths.add(result.relpath)

                if not success:
                    ret = False
                    err_event.set()
                    if result.fetch_errors:
                        errors.extend(result.fetch_errors)
                        self._interleaved_err_network = True
                        self._interleaved_err_network_results.append(
                            result.relpath
                        )
                    if result.checkout_errors:
                        errors.extend(result.checkout_errors)
                        self._interleaved_err_checkout = True
                        self._interleaved_err_checkout_results.append(
                            result.relpath
                        )

            if not ret and opt.fail_fast:
                if pool:
                    pool.close()
                break
        return ret

    def _SyncInterleaved(
        self,
        opt,
        args,
        errors,
        manifest,
        mp,
        all_projects,
        superproject_logging_data,
    ):
        """Sync projects by performing network and local operations in parallel.

        This method processes each project (or groups of projects that share git
        objects) independently. For each project, it performs the fetch and
        checkout operations back-to-back. These independent tasks are run in
        parallel.

        It respects two constraints for correctness:
        1.  Projects in nested directories (e.g. 'foo' and 'foo/bar') are
            processed in hierarchical order.
        2.  Projects that share git objects are processed serially to prevent
            race conditions.
        """
        # Temporary state for tracking errors in interleaved mode.
        self._interleaved_err_network = False
        self._interleaved_err_network_results = []
        self._interleaved_err_checkout = False
        self._interleaved_err_checkout_results = []

        # Project.relpath is relative to its own (sub)manifest, so it does not
        # tell apart projects of different manifests being synced together.
        _RelPath = lambda p: p.RelPath(local=opt.this_manifest_only)

        err_event = multiprocessing.Event()
        finished_relpaths = set()
        project_list = list(all_projects)
        pm = Progress(
            "Syncing",
            len(project_list),
            delay=False,
            quiet=opt.quiet,
            show_elapsed=True,
            elide=True,
        )
        previously_pending_relpaths = set()

        sync_event = _threading.Event()
        sync_progress_thread = self._CreateSyncProgressThread(pm, sync_event)

        try:
            with multiprocessing.Manager() as manager, ssh.ProxyManager(
                manager
            ) as ssh_proxy:
                ssh_proxy.sock()
                with self.ParallelContext():
                    self.get_parallel_context()["ssh_proxy"] = ssh_proxy
                    # TODO(gavinmak): Use multprocessing.Queue instead of dict.
                    self.get_parallel_context()[
                        "sync_dict"
                    ] = multiprocessing.Manager().dict()
                    sync_progress_thread.start()

                    try:
                        # Outer loop for dynamic project discovery. This
                        # continues until no unsynced projects remain.
                        while True:
                            projects_to_sync = [
                                p
                                for p in project_list
                                if _RelPath(p) not in finished_relpaths
                            ]
                            if not projects_to_sync:
                                break

                            pending_relpaths = {
                                _RelPath(p) for p in projects_to_sync
                            }
                            if previously_pending_relpaths == pending_relpaths:
                                stalled_projects_str = "\n".join(
                                    f" - {path}"
                                    for path in sorted(pending_relpaths)
                                )
                                logger.error(
                                    "The following projects failed and could "
                                    "not be synced:\n%s",
                                    stalled_projects_str,
                                )
                                err_event.set()
                                break
                            previously_pending_relpaths = pending_relpaths

                            self.get_parallel_context()[
                                "projects"
                            ] = projects_to_sync
                            project_index_map = {
                                p: i for i, p in enumerate(projects_to_sync)
                            }

                            # Inner loop to process projects in a hierarchical
                            # order. This iterates through levels of project
                            # dependencies (e.g. 'foo' then 'foo/bar'). All
                            # projects in one level can be processed in
                            # parallel, but we must wait for a level to complete
                            # before starting the next.
                            submodule_revisions = {}
                            for level_projects in _SafeCheckoutOrder(
                                projects_to_sync
                            ):
                                if not level_projects:
                                    continue

                                level_projects = _WithoutProjects(
                                    level_projects,
                                    _RefreshDerivedRevisions(
                                        level_projects, submodule_revisions
                                    ),
                                )
                                if not level_projects:
                                    continue

                                objdir_project_map = collections.defaultdict(
                                    list
                                )
                                for p in level_projects:
                                    objdir_project_map[p.objdir].append(
                                        project_index_map[p]
                                    )

                                work_items = list(objdir_project_map.values())
                                if not work_items:
                                    continue

                                jobs = max(1, min(opt.jobs, len(work_items)))
                                callback = functools.partial(
                                    self._ProcessSyncInterleavedResults,
                                    finished_relpaths,
                                    err_event,
                                    errors,
                                    opt,
                                )
                                if not self.ExecuteInParallel(
                                    jobs,
                                    functools.partial(
                                        self._SyncProjectList, opt
                                    ),
                                    work_items,
                                    callback=callback,
                                    output=pm,
                                    chunksize=1,
                                    initializer=self.InitWorker,
                                ):
                                    err_event.set()

                                if err_event.is_set() and opt.fail_fast:
                                    raise SyncFailFastError(
                                        aggregate_errors=errors
                                    )

                            self._ReloadManifest(None, manifest)
                            project_list = self.GetProjects(
                                args,
                                groups=opt.groups,
                                missing_ok=True,
                                submodules_ok=opt.recurse_submodules,
                                manifest=manifest,
                                all_manifests=not opt.this_manifest_only,
                            )
                            pm.update_total(len(project_list))
                    finally:
                        sync_event.set()
                        sync_progress_thread.join()
        finally:
            self._fetch_times.Save()
            self._local_sync_state.Save()

        pm.end()

        err_update_projects, err_update_linkfiles = self._UpdateManifestLists(
            opt, err_event, errors
        )
        if not self.outer_client.manifest.IsArchive:
            self._GCProjects(project_list, opt, err_event)

        self._PrintManifestNotices(opt)
        if err_event.is_set():
            self._ReportErrors(
                errors,
                err_network_sync=self._interleaved_err_network,
                failing_network_repos=self._interleaved_err_network_results,
                err_checkout=self._interleaved_err_checkout,
                failing_checkout_repos=self._interleaved_err_checkout_results,
                err_update_projects=err_update_projects,
                err_update_linkfiles=err_update_linkfiles,
            )


def _PostRepoUpgrade(manifest, quiet=False):
    # Link the docs for the internal .repo/ layout for people.
    link = os.path.join(manifest.repodir, "internal-fs-layout.md")
    if not platform_utils.islink(link):
        target = os.path.join("repo", "docs", "internal-fs-layout.md")
        try:
            platform_utils.symlink(target, link)
        except Exception:
            pass

    wrapper = Wrapper()
    if wrapper.NeedSetupGnuPG():
        wrapper.SetupGnuPG(quiet)
    for project in manifest.projects:
        if project.Exists:
            project.PostRepoUpgrade()


def _PostRepoFetch(rp, repo_verify=True, verbose=False):
    if rp.HasChanges:
        logger.warning("info: A new version of repo is available")
        wrapper = Wrapper()
        try:
            rev = rp.bare_git.describe(rp.GetRevisionId())
        except GitError:
            rev = None
        _, new_rev = wrapper.check_repo_rev(
            rp.gitdir, rev, repo_verify=repo_verify
        )
        # See if we're held back due to missing signed tag.
        current_revid = rp.bare_git.rev_parse("HEAD")
        new_revid = rp.bare_git.rev_parse("--verify", new_rev)
        if current_revid != new_revid:
            # We want to switch to the new rev, but also not trash any
            # uncommitted changes.  This helps with local testing/hacking.
            # If a local change has been made, we will throw that away.
            # We also have to make sure this will switch to an older commit if
            # that's the latest tag in order to support release rollback.
            try:
                # Refresh index since reset --keep won't do it.
                rp.work_git.update_index("-q", "--refresh")
                rp.work_git.reset("--keep", new_rev)
            except GitError as e:
                raise RepoUnhandledExceptionError(e)
            print("info: Restarting repo with latest version")
            raise RepoChangedException(["--repo-upgraded"])
        else:
            logger.warning("warning: Skipped upgrade to unverified version")
    else:
        if verbose:
            print("repo version %s is current" % rp.work_git.describe(HEAD))


class _FetchTimes:
    _ALPHA = 0.5

    def __init__(self, manifest):
        self._path = os.path.join(manifest.repodir, ".repo_fetchtimes.json")
        self._saved = None
        self._seen = {}

    def Get(self, project):
        self._Load()
        return self._saved.get(project.name, _ONE_DAY_S)

    def Set(self, project, t):
        name = project.name

        # For shared projects, save the longest time.
        self._seen[name] = max(self._seen.get(name, 0), t)

    def _Load(self):
        if self._saved is None:
            try:
                with open(self._path) as f:
                    self._saved = json.load(f)
            except (OSError, ValueError):
                platform_utils.remove(self._path, missing_ok=True)
                self._saved = {}

    def Save(self):
        if not self._seen:
            return

        self._Load()

        for name, t in self._seen.items():
            # Keep a moving average across the previous/current sync runs.
            old = self._saved.get(name, t)
            self._saved[name] = (self._ALPHA * t) + ((1 - self._ALPHA) * old)

        try:
            with open(self._path, "w") as f:
                json.dump(self._saved, f, indent=2)
        except (OSError, TypeError):
            platform_utils.remove(self._path, missing_ok=True)


class LocalSyncState:
    _LAST_FETCH = "last_fetch"
    _LAST_CHECKOUT = "last_checkout"

    def __init__(self, manifest):
        self._manifest = manifest
        self._path = os.path.join(
            self._manifest.repodir, ".repo_localsyncstate.json"
        )
        self._time = time.time()
        self._state = None
        self._Load()

    def SetFetchTime(self, project):
        self._Set(project, self._LAST_FETCH)

    def SetCheckoutTime(self, project):
        self._Set(project, self._LAST_CHECKOUT)

    def GetFetchTime(self, project):
        return self._Get(project, self._LAST_FETCH)

    def GetCheckoutTime(self, project):
        return self._Get(project, self._LAST_CHECKOUT)

    def _Get(self, project, key):
        self._Load()
        p = project.relpath
        if p not in self._state:
            return
        return self._state[p].get(key)

    def _Set(self, project, key):
        p = project.relpath
        if p not in self._state:
            self._state[p] = {}
        self._state[p][key] = self._time

    def _Load(self):
        if self._state is None:
            try:
                with open(self._path) as f:
                    self._state = json.load(f)
            except (OSError, ValueError):
                platform_utils.remove(self._path, missing_ok=True)
                self._state = {}

    def Save(self):
        if not self._state:
            return
        try:
            with open(self._path, "w") as f:
                json.dump(self._state, f, indent=2)
        except (OSError, TypeError):
            platform_utils.remove(self._path, missing_ok=True)

    def PruneRemovedProjects(self):
        """Remove entries don't exist on disk and save."""
        if not self._state:
            return
        delete = set()
        for path in self._state:
            gitdir = os.path.join(self._manifest.topdir, path, ".git")
            if not os.path.exists(gitdir) or os.path.islink(gitdir):
                delete.add(path)
        if not delete:
            return
        for path in delete:
            del self._state[path]
        self.Save()

    def IsPartiallySynced(self):
        """Return whether a partial sync state is detected."""
        self._Load()
        prev_checkout_t = None
        for path, data in self._state.items():
            if path == self._manifest.repoProject.relpath:
                # The repo project isn't included in most syncs so we should
                # ignore it here.
                continue
            checkout_t = data.get(self._LAST_CHECKOUT)
            if not checkout_t:
                return True
            prev_checkout_t = prev_checkout_t or checkout_t
            if prev_checkout_t != checkout_t:
                return True
        return False


# This is a replacement for xmlrpc.client.Transport using urllib2
# and supporting persistent-http[s]. It cannot change hosts from
# request to request like the normal transport, the real url
# is passed during initialization.
class PersistentTransport(xmlrpc.client.Transport):
    def __init__(self, orig_host, proxy=None):
        super().__init__()
        self.orig_host = orig_host
        self.proxy = proxy

    def request(self, host, handler, request_body, verbose=False):
        with GetUrlCookieFile(self.orig_host, not verbose) as (
            cookiefile,
            cookie_proxy,
        ):
            # Python doesn't understand cookies with the #HttpOnly_ prefix
            # Since we're only using them for HTTP, copy the file temporarily,
            # stripping those prefixes away.
            if cookiefile:
                tmpcookiefile = tempfile.NamedTemporaryFile(mode="w")
                tmpcookiefile.write("# HTTP Cookie File")
                try:
                    with open(cookiefile) as f:
                        for line in f:
                            if line.startswith("#HttpOnly_"):
                                line = line[len("#HttpOnly_") :]
                            tmpcookiefile.write(line)
                    tmpcookiefile.flush()

                    cookiejar = cookielib.MozillaCookieJar(tmpcookiefile.name)
                    try:
                        cookiejar.load()
                    except cookielib.LoadError:
                        cookiejar = cookielib.CookieJar()
                finally:
                    tmpcookiefile.close()
            else:
                cookiejar = cookielib.CookieJar()

            active_proxy = self.proxy or cookie_proxy
            proxyhandler = urllib.request.ProxyHandler
            if active_proxy:
                proxyhandler = urllib.request.ProxyHandler(
                    {"http": active_proxy, "https": active_proxy}
                )

            opener = urllib.request.build_opener(
                urllib.request.HTTPCookieProcessor(cookiejar), proxyhandler
            )

            url = urllib.parse.urljoin(self.orig_host, handler)
            parse_results = urllib.parse.urlparse(url)

            scheme = parse_results.scheme
            if scheme == "persistent-http":
                scheme = "http"
            elif scheme == "persistent-https":
                # If we're proxying through persistent-https, use http. The
                # proxy itself will do the https.
                if active_proxy:
                    scheme = "http"
                else:
                    scheme = "https"
            elif scheme not in ("http", "https"):
                if active_proxy:
                    scheme = "http"

            # Parse out any authentication information using the base class.
            host, extra_headers, _ = self.get_host_info(parse_results.netloc)

            url = urllib.parse.urlunparse(
                (
                    scheme,
                    host,
                    parse_results.path,
                    parse_results.params,
                    parse_results.query,
                    parse_results.fragment,
                )
            )

            request = urllib.request.Request(url, request_body)
            if extra_headers is not None:
                for name, header in extra_headers:
                    request.add_header(name, header)
            request.add_header("Content-Type", "text/xml")
            try:
                response = opener.open(request)
            except urllib.error.HTTPError as e:
                if e.code == 501:
                    # We may have been redirected through a login process
                    # but our POST turned into a GET. Retry.
                    response = opener.open(request)
                else:
                    raise

            p, u = xmlrpc.client.getparser()
            # Response should be fairly small, so read it all at once.
            # This way we can show it to the user in case of error (e.g. HTML).
            data = response.read()
            try:
                p.feed(data)
            except xml.parsers.expat.ExpatError as e:
                raise OSError(
                    f"Parsing the manifest failed: {e}\n"
                    f"Please report this to your manifest server admin.\n"
                    f'Here is the full response:\n{data.decode("utf-8")}'
                )
            p.close()
            return u.close()

    def close(self):
        pass
