# 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 ManifestParseError
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",
                default=None,
                help="smart sync using manifest from the latest known good "
                "build",
            )
            p.add_option(
                "--no-smart-sync",
                dest="smart_sync",
                action="store_false",
                help="disable smart sync and sync to ToT instead",
            )
            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:
            superproject_logging_data.update(
                superproject=False,
                haslocalmanifests=bool(manifest.HasLocalManifests),
                hassuperprojecttag=False,
            )
            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)

        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(
                        "error: Update of revsionId from superproject "
                        "has failed"
                    )
                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]

        # Only check dirty or locally modified projects. These can't be
        # freshly cloned and will accumulate garbage.
        try:
            is_dirty, head_rev = project.GetDirtyAndHead()
            if head_rev is None:
                # An unborn branch has no HEAD to compare, so skip it.
                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.
        """
        # --network-only promises not to touch worktrees, but git status and
        # update-index --refresh can both rewrite the index.
        if opt.network_only:
            return

        # 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

        # Skip projects with no worktree on disk, e.g. ones only ever synced
        # with --network-only.
        projects = [
            p
            for p in projects
            if p.clone_depth
            and not p.stateless_prune_needed
            and p.worktree
            and p.Exists
            and platform_utils.isdir(p.worktree)
        ]
        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 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 _ResolveSmartSyncOption(
        self, opt: optparse.Values, manifest: XmlManifest
    ) -> bool:
        """Resolve opt.smart_sync from the CLI flags and manifest default.

        Returns:
            True if smart_sync was enabled implicitly by the manifest default,
            False otherwise.
        """
        implicit = (
            opt.smart_sync is None
            and not opt.smart_tag
            and not opt.manifest_name
            and not opt.superproject_revision
            and not opt.local_only
            and opt.mp_update
            and getattr(manifest.default, "sync_smartsync", False) is True
        )
        if opt.smart_sync is None:
            opt.smart_sync = implicit

        if (
            opt.manifest_server_username or opt.manifest_server_password
        ) and not (opt.smart_sync or opt.smart_tag):
            raise SmartSyncError("-u and -p may only be combined with -s or -t")

        return implicit

    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

        # An onboarded client run with -l or --no-manifest-update keeps the
        # smart sync manifest it last synced to instead of contacting the
        # manifest server. Computed before _ResolveSmartSyncOption, which
        # makes an unset opt.smart_sync indistinguishable from --no-smart-sync.
        reuse_smart_sync_override = (
            (opt.local_only or not opt.mp_update)
            and opt.smart_sync is None
            and not opt.smart_tag
            and not opt.manifest_name
            and not opt.superproject_revision
            and getattr(manifest.default, "sync_smartsync", False) is True
            and os.path.isfile(smart_sync_manifest_path)
        )

        implicit_smart_sync = self._ResolveSmartSyncOption(opt, manifest)

        if opt.smart_sync or opt.smart_tag:
            try:
                manifest_name = self._SmartSyncSetup(
                    opt, smart_sync_manifest_path, manifest
                )
            except (SmartSyncError, ManifestParseError) as e:
                if not implicit_smart_sync:
                    raise
                # The user did not ask for a smart sync, so failing to get a
                # usable manifest from the server should not fail the sync.
                # Fall back to a regular ToT sync instead.
                opt.smart_sync = False
                # Override() records the override before parsing it, so an
                # unparsable manifest would otherwise leave the client pinned
                # to a file it cannot load.
                manifest.ClearOverride()
                if opt.verbose:
                    logger.warning(
                        "warning: smart sync failed; falling back to ToT: %s", e
                    )
        elif reuse_smart_sync_override:
            manifest_name = os.path.basename(smart_sync_manifest_path)
            try:
                self._ReloadManifest(manifest_name, manifest)
            except ManifestParseError as e:
                reuse_smart_sync_override = False
                manifest_name = None
                manifest.ClearOverride()
                if opt.verbose:
                    logger.warning(
                        "warning: failed to load existing smart sync manifest; "
                        "falling back to ToT: %s",
                        e,
                    )

        if not (opt.smart_sync or opt.smart_tag or reuse_smart_sync_override):
            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(local=False)
        if p not in self._state:
            return
        return self._state[p].get(key)

    def _Set(self, project, key):
        p = project.RelPath(local=False)
        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()
        outer_topdir = self._manifest.outer_client.topdir
        for path in self._state:
            gitdir = os.path.join(outer_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
