# Copyright 2020 The Pigweed Authors
#
# 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
#
#     https://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.
"""Calls to checkout code.

Usage:
api.checkout(remote='https://pigweed.googlesource.com/pigweed/pigweed')
"""

import re
import xml.etree.ElementTree

import attr
from recipe_engine import config_types, recipe_api
from RECIPE_MODULES.fuchsia.utils import memoize
from six.moves import urllib

PIGWEED_REMOTE = 'https://pigweed.googlesource.com/pigweed/pigweed'


@attr.s
class _Manifest(object):
    remotes = attr.ib(default=attr.Factory(dict))
    projects = attr.ib(default=attr.Factory(list))

    def dict(self):
        return {
            'remotes': {k: v.dict() for k, v in self.remotes.items()},
            'projects': [x.dict() for x in self.projects],
        }


class _Url(object):
    def __init__(self, url, *args, **kwargs):
        super(_Url, self).__init__(*args, **kwargs)
        self.url = url
        self.https = None

    def dict(self):
        return self.__dict__.copy()


@attr.s
class _Remote(object):
    """Remote config from manifest."""

    name = attr.ib(type=str)
    fetch = attr.ib(type=_Url)
    review = attr.ib(type=str, default=None)
    revision = attr.ib(type=str, default=None)
    alias = attr.ib(type=str, default=None)

    def dict(self):
        res = self.__dict__.copy()
        res['fetch'] = res['fetch'].dict()
        return res


@attr.s
class _Project(object):
    """Key variables describing a repository/project."""

    name = attr.ib(type=str)
    path = attr.ib(type=str)
    remote = attr.ib(type=str)
    revision = attr.ib(type=str)
    upstream = attr.ib(type=str)
    url = attr.ib(type=str, default=None)

    def path_object(self, root):
        return root.join(self.path)

    def dict(self):
        return self.__dict__.copy()


def _str_or_none(x):
    if x is None:
        return x
    return str(x)


@attr.s
class _Change(object):
    """Data from buildbucket."""

    # TODO(pwbug/465) Remove converters after switch to Python 3.
    number = attr.ib(converter=int)
    bb_input = attr.ib(repr=False)
    remote = attr.ib(converter=_str_or_none)
    ref = attr.ib(converter=_str_or_none)
    rebase = attr.ib(type=bool)
    branch = attr.ib(converter=_str_or_none)
    gerrit_name = attr.ib(converter=_str_or_none)
    submitted = attr.ib(type=bool)
    applied = attr.ib(type=bool, default=False, repr=False)
    base = attr.ib(converter=_str_or_none, default=None)
    base_type = attr.ib(converter=_str_or_none, default=None)

    @property
    def gerrit_url(self):
        if not self.number:
            return self.gitiles_url
        return 'https://{}-review.googlesource.com/c/{}'.format(
            self.gerrit_name, self.number
        )

    @property
    def gitiles_url(self):
        return '{}/+/{}'.format(self.remote, self.ref)

    @property
    def name(self):
        return '{}:{}'.format(self.gerrit_name, self.number)


@attr.s
class _Submodule(object):
    """Submodule properties."""

    api = attr.ib(type=recipe_api.RecipeApi, repr=False)
    hash = attr.ib(type=str)
    relative_path = attr.ib(type=str)
    path = attr.ib(type=config_types.Path)
    describe = attr.ib(type=str)
    remote = attr.ib(type=str)


@attr.s
class _StatusOfChanges(object):
    """Changes that were applied or not applied."""

    applied = attr.ib()  # Tuple of _Change.
    not_applied = attr.ib()  # Tuple of _Change.


class CheckoutApi(recipe_api.RecipeApi):
    """Calls to checkout code."""

    def __init__(self, props, *args, **kwargs):
        super(CheckoutApi, self).__init__(*args, **kwargs)
        # TODO(pwbug/465) Remove str calls after switch to Python 3.
        self._remote = str(props.remote)
        self._branch = str(props.branch or 'main')
        self._use_repo = props.use_repo
        self._manifest_file = str(props.manifest_file or 'default.xml')
        self._root = None
        self._revision = None
        self._repo_top = None
        self._manifest = None
        self._triggering_repo = None
        self._changes = None
        self._manifest_snapshot = None
        self._submodule_snapshot = None
        self._repo_init_timeout_sec = props.repo_init_timeout_sec or 20
        self._repo_sync_timeout_sec = props.repo_sync_timeout_sec or 120
        self._number_of_attempts = props.number_of_attempts or 3
        self._submodule_data = {}
        self._equivalent_remotes = {}
        self._force_no_rebase = props.force_no_rebase
        self.props = props

    def initialize(self):
        for remotes in self.props.equivalent_remotes:
            new_remotes = [self.m.sso.sso_to_https(x) for x in remotes.remotes]
            for remote in new_remotes:
                assert remote not in self._equivalent_remotes
                self._equivalent_remotes[remote] = new_remotes

    def remotes_equivalent(self, remote1, remote2):
        # Sometimes remote1 or remote2 is None. In that case we shouldn't
        # convert sso to https.
        if remote1:
            remote1 = self.m.sso.sso_to_https(remote1)
        if remote2:
            remote2 = self.m.sso.sso_to_https(remote2)
        if remote1 == remote2:
            return True
        return remote1 in self._equivalent_remotes.get(remote2, ())

    def _read_manifest(self, manifest_remote, manifest_file):
        """Reads manifest file to get git repo locations."""

        with self.m.step.nest('read manifest') as read_step:
            manifest_text = self.m.file.read_text('read file', manifest_file)
            read_step.logs['raw'] = manifest_text

            xml_tree = xml.etree.ElementTree.fromstring(manifest_text)

            manifest = _Manifest()

            for remote in xml_tree.iter('remote'):
                remote = _Remote(**remote.attrib)
                if remote.fetch.startswith('..'):
                    rest = remote.fetch[2:]
                    parsed = urllib.parse.urlparse(manifest_remote)
                    remote.fetch = (
                        '{}://{}'.format(parsed.scheme, parsed.netloc,) + rest
                    )
                remote.fetch = _Url(remote.fetch)
                remote.fetch.https = self.m.sso.sso_to_https(remote.fetch.url)
                manifest.remotes[remote.name] = remote

            defaults = {}
            for default in xml_tree.iter('default'):
                defaults.update(default.attrib)

            for project in xml_tree.iter('project'):
                name = project.attrib['name']
                path = project.attrib.get('path', name)

                if 'remote' in project.attrib:
                    remote = project.attrib['remote']
                elif 'remote' in defaults:
                    remote = defaults['remote']
                else:  # pragma: no cover
                    assert False, 'remote not specified for {}'.format(name)

                assert (
                    remote in manifest.remotes
                ), 'Remote {} does not exist'.format(remote)

                if 'revision' in project.attrib:
                    revision = project.attrib['revision']
                elif manifest.remotes[remote].revision:
                    revision = manifest.remotes[remote].revision
                elif 'revision' in defaults:
                    revision = defaults['revision']
                else:  # pragma: no cover
                    assert False, 'revision not specified for {}'.format(name)

                if 'upstream' in project.attrib:
                    upstream = project.attrib['upstream']
                elif 'upstream' in defaults:  # pragma: no cover
                    # This is unlikely to be used and hard to test--it requires
                    # a completely separate manifest definition, otherwise the
                    # 'else' condition won't be covered. It's also simple.
                    upstream = defaults['upstream']
                else:
                    upstream = revision

                # urllib.urljoin does something different than what's desired
                # here.
                url = '/'.join(
                    (
                        manifest.remotes[remote].fetch.https.rstrip('/'),
                        name.lstrip('/'),
                    )
                )
                manifest.projects.append(
                    _Project(
                        name=name,
                        path=path,
                        remote=remote,
                        revision=revision,
                        upstream=upstream,
                        url=url,
                    )
                )

            self.m.file.write_json(
                'manifest json',
                self.m.path['start_dir'].join('manifest.json'),
                manifest.dict(),
            )

        return manifest

    def _process_gerrit_change(self, bb_input, change):
        """Process a LUCI GerritChange and return a _Change object."""

        assert change.host
        ref = 'refs/changes/{:02}/{}/{}'.format(
            change.change % 100, change.change, change.patchset,
        )
        host = change.host.replace(
            '-review.googlesource.com', '.googlesource.com'
        )
        remote = 'https://{}/{}'.format(host, change.project).strip('/')
        gerrit_name = host.split('.')[0]
        branch = self.m.gerrit.change_details(
            'details',
            change_id=str(change.change),
            host=change.host,
            max_attempts=5,
            timeout=30,
            test_data=self.m.json.test_api.output({'branch': 'main'}),
        ).json.output['branch']

        rebase = not self._force_no_rebase

        return _Change(
            number=change.change,
            bb_input=bb_input,
            remote=remote,
            ref=ref,
            rebase=rebase,
            branch=branch,
            gerrit_name=gerrit_name,
            submitted=False,
        )

    def _process_gerrit_changes(self, bb_input):
        seen = set()
        for i, change in enumerate(bb_input.gerrit_changes):
            with self.m.step.nest(str(i)):
                result = self._process_gerrit_change(bb_input, change)
                yield result
                seen.add(result.name)

        deps, unresolved = self.m.cq_deps.resolve(
            result.gerrit_name, result.number,
        )
        for dep in deps:
            # dep.name should only appear in seen if there are multiple
            # gerrit_changes from buildbucket and a later one depends on an
            # earlier one. If buildbucket has multiple gerrit_changes the
            # cq_deps module is not needed here, so this is just double-checking
            # something that shouldn't happen.
            if dep.name in seen:  # pragma: no cover
                continue
            seen.add(dep.name)
            yield self._process_gerrit_change(bb_input, dep)

        for cl in unresolved:
            yield _Change(
                number=cl.change,
                bb_input=None,
                remote=None,
                ref=None,
                rebase=None,
                branch=None,
                gerrit_name=cl.gerrit_name,
                submitted=False,
            )

    def _number_details(self, host, commit_hash, branch='main'):
        try:
            results = self.m.gerrit.change_query(
                'number',
                'commit:{}'.format(commit_hash),
                host=host,
                max_attempts=5,
                timeout=30,
                test_data=self.m.json.test_api.output(
                    [{'_number': '1234', 'branch': branch}]
                ),
            ).json.output
            # Skip this change if it didn't go through Gerrit.
            if results and len(results) == 1:
                return results[0]
        except self.m.step.StepFailure:  # pragma: no cover
            pass

        return None

    def _change_data(self, remote=None, branch=None):
        bb_input = self.m.buildbucket.build.input
        results = []

        with self.m.step.nest('change data'):
            if bb_input.gerrit_changes:
                with self.m.step.nest('process gerrit changes'):
                    results.extend(self._process_gerrit_changes(bb_input))

            elif bb_input.gitiles_commit.id:
                with self.m.step.nest('process gitiles commit'):
                    commit = bb_input.gitiles_commit
                    assert commit.host
                    if commit.project:
                        remote = 'https://{}/{}'.format(
                            commit.host, commit.project
                        )

                    host = commit.host.replace(
                        '.googlesource.com', '-review.googlesource.com'
                    )
                    gerrit_name = commit.host.split('.')[0]

                    result = self._number_details(host, commit.id)
                    if result:
                        results.append(
                            _Change(
                                number=result['_number'],
                                bb_input=bb_input,
                                remote=remote,
                                ref=commit.id,
                                rebase=False,
                                branch=result['branch'],
                                gerrit_name=gerrit_name,
                                submitted=True,
                            )
                        )

            else:
                # If not triggered by a gitiles_poller gitiles_commit may be
                # empty. In that case treat the most recent commit on the
                # remote as the triggering commit. This is a good assumption
                # except for Android Repo Tool projects, unless all projects
                # are pinned to commits instead of tracking branches. However,
                # even if this is wrong it's close enough to have utility.
                head = self.m.git.get_remote_branch_head(remote, branch)
                gerrit_name = urllib.parse.urlparse(remote).netloc.split('.')[0]
                host = '{}-review.googlesource.com'.format(gerrit_name)
                result = self._number_details(host, head)

                results.append(
                    _Change(
                        number=result['_number'] if result else 0,
                        bb_input=bb_input,
                        remote=remote,
                        ref=head,
                        rebase=False,
                        branch=result['branch'] if result else branch,
                        gerrit_name=gerrit_name,
                        submitted=True,
                    )
                )

            with self.m.step.nest('changes'):
                for result in results:
                    with self.m.step.nest(result.name) as change_data_pres:
                        change_data_pres.step_summary_text = repr(result)

            return tuple(results)

    def _parse_submodule_status(self, root, line):
        """Parse a `git submodule status` and get the remote URL."""
        match = re.search(
            r'^\+?(?P<hash>[0-9a-fA-F]{40})\s+'
            r'(?P<path>[^()]*)\s+'
            r'\((?P<describe>[^()]*)\)$',
            line.strip(),
        )
        if not match:
            raise self.m.step.InfraFailure(
                'unrecognized submodule status line "{}"'.format(line)
            )

        with self.m.step.nest(match.group('path')) as pres:
            pres.step_summary_text = 'hash={}\ndescribe={}'.format(
                match.group('hash'), match.group('describe')
            )
        path = root.join(match.group('path'))
        with self.m.context(cwd=path):
            remote = self.m.git(
                'git origin {}'.format(path),
                'config',
                '--get',
                'remote.origin.url',
                stdout=self.m.raw_io.output_text(),
            ).stdout.strip()
        remote_https = self.m.sso.sso_to_https(remote)
        if remote_https.endswith('.git'):
            remote_https = remote_https[0:-4]

        return _Submodule(
            api=self.m,
            hash=match.group('hash'),
            relative_path=match.group('path'),
            path=path,
            describe=match.group('describe'),
            remote=remote_https,
        )

    def _matching_branches(self, repo, branches, name='has branch', **kwargs):
        """Returns the subset of the given branches that exist on gitiles."""
        matches = set()
        with self.m.step.nest(name), self.m.context(infra_steps=True):
            for branch in branches:
                head = self.m.git.get_remote_branch_head(
                    repo,
                    branch,
                    step_name='git ls-remote {}'.format(branch),
                    step_test_data=lambda: self.m.raw_io.test_api.stream_output_text(
                        ''
                    ),
                    **kwargs
                )
                with self.m.step.nest('head') as pres:
                    pres.step_summary_text = repr(head)

                if head:
                    matches.add(branch)
        return sorted(matches)

    def _apply_change(self, change, cwd=None, extra_calls=None):
        """Applies the given change to the given directory.

        Args:
            change (_Change): Change to apply.
            cwd (Path): Working directory, defaults to current directory.
            extra_calls (callable): Additional steps to run within the nested
                'apply ...' step and, if specified, within directory cwd.
        """
        kwargs = {'cwd': cwd} if cwd else {}
        change.applied = True

        apply_step = 'apply {}'.format(change.name)
        with self.m.context(**kwargs), self.m.step.nest(apply_step) as pres:
            pres.links['gerrit'] = change.gerrit_url
            pres.links['gitiles'] = change.gitiles_url

            with self.m.context(infra_steps=True):
                # 'git fetch' fails if a submodule pin in the patch isn't
                # present in the remote (for example, if the pin is only
                # present in the uploader's workspace). Use
                # '--no-recurse-submodules' here so 'git fetch' doesn't fail
                # but instead 'git rebase' or 'git submodule update' fails
                # later (important because those are not infra steps). Also
                # don't use '--recurse-submodules' in 'git checkout' for
                # similar reasons.
                self.m.git.fetch(
                    change.remote,
                    change.ref,
                    recurse_submodules=False,
                    step_name='git fetch patch',
                )
                self.m.git(
                    'git checkout patch',
                    'checkout',
                    '--force',
                    '-b',
                    'working',
                    'FETCH_HEAD',
                )

            # These remain unused if change.submitted is False.
            remote = remote_branch = None

            if not change.submitted:
                with self.m.context(infra_steps=True):
                    # Change "https://foo.googlesource.com/bar"
                    #     to "https___foo_googlesource_com_bar".
                    remote = re.sub(r'[^\w]', '_', change.remote)
                    remote_branch = '/'.join((remote, change.branch))
                    self.m.git(
                        'git remote add',
                        'remote',
                        'add',
                        remote,
                        change.remote,
                    )

                    self.m.git('pre-rebase log', 'log', '--oneline', '-n', '10')
                    self.m.git.fetch(
                        remote,
                        change.branch,
                        prune=False,
                        step_name='git fetch branch',
                    )

                    self.m.git(
                        'git set upstream',
                        'branch',
                        '--set-upstream-to={}'.format(remote_branch),
                    )

            if change.submitted:
                change.base = self.m.git.rev_parse(
                    'HEAD',
                    step_test_data=lambda: self.m.raw_io.test_api.stream_output_text(
                        'HEAD_' * 8,
                    ),
                )
                change.base_type = 'submitted_commit_hash'

            elif change.rebase:
                self.m.git('git rebase', 'rebase', remote_branch)

                change.base = self.m.git.rev_parse(
                    remote_branch,
                    step_test_data=lambda: self.m.raw_io.test_api.stream_output_text(
                        'REMOTE_BRANCH_' * 3,
                    ),
                )
                change.base_type = 'remote_branch_tip'

            else:
                change.base = self.m.git(
                    'merge-base',
                    'merge-base',
                    'HEAD',
                    remote_branch,
                    stdout=self.m.raw_io.output_text(),
                    step_test_data=lambda: self.m.raw_io.test_api.stream_output_text(
                        'MERGEBASE_' * 4,
                    ),
                ).stdout
                change.base_type = 'merge-base'

            # In most cases this is redundant or unnecessary, but it shouldn't
            # cause problems. It's necessary when a superproject CL is updating
            # a submodule pin and we need to sync the submodule to the new
            # revision. Including "--init" in case this CL is adding a submodule
            # in which case it wouldn't otherwise be initialized.
            self.m.git(
                'git submodule update',
                'submodule',
                'update',
                '--init',
                '--recursive',
            )

            # TODO(pwbug/233) Make this function a context manager so callers
            # can do the following:
            # with self._apply_change(...):
            #   extra_calls()
            if extra_calls:
                extra_calls()

    def _check_unapplied_changes(self, changes):
        applied = []
        failed_to_apply = []
        if not changes:  # pragma: no cover
            return None

        def handle_unapplied_change(change):
            with self.m.step.nest(
                'failed to apply {}'.format(change.name)
            ) as pres:
                pres.status = 'WARNING'
                pres.links['gerrit'] = change.gerrit_url
                pres.links['gitiles'] = change.gitiles_url
            failed_to_apply.append(change)

        with self.m.context(infra_steps=True):
            if all(not x.applied for x in changes):
                with self.m.step.nest('no changes were applied') as pres:
                    pres.status = 'FAILURE'
                    for change in changes:
                        handle_unapplied_change(change)
                    pres.properties['changes'] = [x.name for x in changes]

                raise self.m.step.InfraFailure(
                    'could not find triggering changes in checkout'
                )

            elif any(not x.applied for x in changes):
                with self.m.step.nest('some changes were not applied') as pres:
                    pres.status = 'WARNING'
                    for change in changes:
                        if change.applied:
                            applied.append(change)
                        else:
                            handle_unapplied_change(change)

            else:
                applied.extend(changes)

        with self.m.step.nest('status') as pres:
            pres.step_summary_text = 'applied {}\nnot applied {}'.format(
                applied, failed_to_apply,
            )

        return _StatusOfChanges(
            applied=tuple(applied), not_applied=tuple(failed_to_apply),
        )

    @memoize
    def submodules(self, root=None, recursive=False):
        """Return data about all submodules of root."""

        if not root:
            root = self.root

        with self.m.context(cwd=root):
            args = ['git submodule status', 'submodule', 'status']
            if recursive:
                args.append('--recursive')
            kwargs = {
                'stdout': self.m.raw_io.output_text(),
                'step_test_data': lambda: self.m.raw_io.test_api.stream_output_text(
                    ''
                ),
            }
            submodule_status_lines = sorted(
                self.m.git(*args, **kwargs).stdout.splitlines()
            )

            submodules = []
            if submodule_status_lines:
                with self.m.step.nest('parse submodules'):
                    for line in submodule_status_lines:
                        submodules.append(
                            self._parse_submodule_status(root, line)
                        )

            return submodules

    def _git(self, remote, branch, use_trigger, root, changes):
        """Checkout code from git.

        Args:
            remote (str): URL of git repository.
            branch (str): Remote branch to retrieve.
            use_trigger (bool): Attempt to apply the triggering change to the
                checkout.
            root (Path): Path to checkout into.
            changes (sequence[_Change]): List of triggering changes.

        Returns:
            _StatusOfChanges with applied and not applied CLs.
        """

        with self.m.context(infra_steps=True):
            self.m.git.checkout(
                remote, path=root, ref=branch, recursive=True, submodules=True
            )

        with self.m.context(cwd=root):
            got_revision = None
            got_revision_type = 'no_trigger'

            submodules = []
            status_of_changes = None

            if use_trigger:
                got_revision = self.m.git.rev_parse(
                    'HEAD',
                    step_test_data=lambda: self.m.raw_io.test_api.stream_output_text(
                        'HEAD' * 10,
                    ),
                )

                # Check for CLs for the top-level repository.
                for change in changes:
                    if self.remotes_equivalent(remote, change.remote):
                        self._apply_change(change)
                        got_revision = change.base
                        got_revision_type = change.base_type

                submodules = self.submodules(root, recursive=True)

                # Check for CLs for submodules.
                for change in changes:
                    for submodule in submodules:
                        if self.remotes_equivalent(
                            submodule.remote, change.remote
                        ):
                            self._apply_change(change, cwd=submodule.path)

                status_of_changes = self._check_unapplied_changes(changes)

            # Run git log for both the top-level checkout and every submodule.
            with self.m.step.nest('git log'):
                self.m.git(str(root), 'log', '--oneline', '-n', '10')
                for submodule in sorted(submodules):
                    with self.m.context(cwd=submodule.path):
                        self.m.git(
                            str(submodule.path), 'log', '--oneline', '-n', '10',
                        )

            if got_revision:
                with self.m.step.nest('base') as pres:
                    pres.properties['got_revision'] = got_revision
                    # got_revision_type isn't needed by anything but helps
                    # explain why got_revision is the value it is.
                    pres.properties['got_revision_type'] = got_revision_type

            return status_of_changes

    def _repo(self, remote, branch, manifest_file, use_trigger, root, changes):
        """Checkout code from an Android Repo Tool manifest.

        Args:
            remote (str): URL of git repository.
            branch (str): Remote branch to retrieve.
            manifest_file (str): Name of manifest XML file.
            use_trigger (bool): Attempt to apply the triggering change to the
                checkout.
            root (Path): Path to checkout into.
            changes (sequence[_Change]): List of triggering changes.

        Returns:
            _StatusOfChanges with applied and not applied CLs.
        """

        # Git makes the top-level folder, Repo requires caller to make it.
        self.m.file.ensure_directory('mkdir checkout', root)

        if manifest_file is None:
            manifest_file = self._manifest_file

        status_of_changes = None

        with self.m.context(cwd=root):
            remote = remote.rstrip('/')

            # If the triggering change is on a branch name that is also present
            # in the manifest branch, use that manifest branch when checking
            # out the manifest.
            manifest_branch = branch
            branch_names = sorted(
                set(
                    x.branch
                    for x in changes
                    if x.branch not in ('master', 'main', None)
                )
            )

            if branch_names:
                with self.m.step.nest('branch names') as pres:
                    pres.step_summary_text = str(branch_names)
                if changes:
                    matching_branches = self._matching_branches(
                        remote, branch_names, name='manifest has branch'
                    )
                    if matching_branches:
                        if len(matching_branches) > 1:
                            with self.m.step.nest(
                                'too many matching branches ({})'.format(
                                    ', '.join(matching_branches)
                                )
                            ) as pres:
                                pres.step_summary_text = (
                                    "Can't figure out which manifest branch to "
                                    'use. Remove some "Requires:" lines to '
                                    'simplify the checkout.'
                                )
                                raise self.m.step.StepFailure(
                                    'too many matching branches'
                                )
                        else:
                            manifest_branch = matching_branches.pop()
                            self.m.step(
                                'changing manifest branch to {}'.format(
                                    manifest_branch
                                ),
                                None,
                            )

            with self.m.context(infra_steps=True):
                kwargs = {}
                if self._repo_init_timeout_sec:
                    kwargs['timeout'] = self._repo_init_timeout_sec
                    kwargs['attempts'] = self._number_of_attempts
                self.m.repo.init(
                    manifest_url=remote,
                    manifest_branch=manifest_branch,
                    manifest_name=self._manifest_file,
                    **kwargs
                )

            manifests_dir = root.join('.repo', 'manifests')
            # If the triggering CL is a manifest change, apply it before running
            # sync.
            if use_trigger:
                for change in changes:
                    if change.remote and self.remotes_equivalent(
                        remote, change.remote
                    ):

                        def update_upstream():
                            # Right now the upstream of 'working' is the local
                            # 'default' branch. 'repo sync' complains if the
                            # upstream isn't remote, so it's changed to the
                            # remote branch that's identical to 'default'.
                            self.m.git(
                                'git branch',
                                'branch',
                                '--set-upstream-to=origin/{}'.format(
                                    manifest_branch
                                ),
                            )

                        self._apply_change(
                            change,
                            cwd=manifests_dir,
                            extra_calls=update_upstream,
                        )

            self._manifest = self._read_manifest(
                remote, manifests_dir.join(manifest_file)
            )

            for _, remote_host in sorted(self._manifest.remotes.items()):
                if remote_host.fetch.url.startswith('sso://'):
                    self.m.sso.configure_insteadof(remote_host.fetch.url)

            with self.m.context(infra_steps=True):
                kwargs = {}
                if self._repo_sync_timeout_sec:
                    kwargs['timeout'] = self._repo_sync_timeout_sec
                    kwargs['attempts'] = self._number_of_attempts
                self.m.repo.sync(
                    force_sync=True, current_branch=True, jobs=2, **kwargs
                )
                self.m.repo.start('base')

            if use_trigger:
                for change in changes:
                    for entry in self._manifest.projects:
                        if self.remotes_equivalent(entry.url, change.remote):

                            def compare_branch_name():
                                with self.m.step.nest(
                                    'compare branch name'
                                ) as pres:
                                    pres.step_summary_text = (
                                        'CL branch: {}\nupstream branch: {}'
                                    ).format(change.branch, entry.upstream)

                            self._apply_change(
                                change,
                                cwd=entry.path_object(root),
                                extra_calls=compare_branch_name,
                            )

                status_of_changes = self._check_unapplied_changes(changes)

        # Some dependent projects have everything inside one top-level folder
        # in their repo workspace. For those projects pretend that top-level
        # folder is actually the checkout root. The repo_top member will always
        # point to the actual repo workspace root.
        with self.m.step.nest('root') as pres:
            pres.step_summary_text = 'root={}\nself._root={}\n'.format(
                root, self._root
            )
        if root == self._root:
            self._repo_top = self._root
            files = set(self.m.file.listdir('ls', root))
            dotrepo = self._root.join('.repo')
            if dotrepo in files:
                files.remove(dotrepo)
            if len(files) == 1:
                self._root = files.pop()

        return status_of_changes

    def __call__(
        self,
        remote=None,
        branch=None,
        name=None,
        use_trigger=True,
        root=None,
        use_repo=None,
        manifest_file=None,
    ):
        """Checkout code.

        Grabs data from buildbucket. If drawing a blank, uses remote. Returns
        path to checkout.

        Args:
            remote (str): URL of git repository.
            branch (str): Remote branch to retrieve.
            name (str|None): If not None, this is used in the nesting step that
                wraps all steps invoked by this method.
            use_trigger (bool): Attempt to apply the triggering change to the
                checkout.
            root (Path|None): If not None, checkout into this path and not
                self.root.
            use_repo (bool|None): If True, treat the remote/branch as an Android
                Repo Tool manifest. If False, treat as a regular Git repository.
                If None, use the property value instead.
            manifest_file (str|None): Path to manifest file, defaults to
                'default.xml'.
        """

        if use_repo is None:
            use_repo = self._use_repo

        # The caller supplying the branch and not the remote is a weird
        # situation that's probably an error. Only grab from properties if
        # caller supplied neither.
        if remote is None and branch is None:
            remote = self._remote
            branch = self._branch
        branch = branch or 'main'

        # Turn "https://foo/bar/baz.git" into "baz".
        checkout_name = 'checkout'
        if remote and name is None:
            name = remote.rstrip('/')
            if name.endswith('.git'):
                name = name[0:-4]
            parts = name.split('/')
            if use_repo and parts[-1] == 'manifest':
                parts.pop(-1)
            name = parts[-1]
            checkout_name = 'checkout {}'.format(name)

        if remote.endswith('.git'):
            remote = remote[0:-4]

        with self.m.step.nest(checkout_name) as pres:
            changes = []
            if use_trigger:
                changes = self._change_data(remote, branch)

            if not remote:
                assert len(changes) == 1
                remote = changes[0].remote

            if root is None:
                root = self._root = self.m.path['start_dir'].join('checkout')
                self._changes = changes

            if use_repo:
                status_of_changes = self._repo(
                    remote=remote,
                    branch=branch,
                    root=root,
                    use_trigger=use_trigger,
                    manifest_file=manifest_file,
                    changes=changes,
                )

            else:
                status_of_changes = self._git(
                    remote=remote,
                    branch=branch,
                    root=root,
                    use_trigger=use_trigger,
                    changes=changes,
                )

            if status_of_changes:
                for change in status_of_changes.applied:
                    pres.links[
                        'applied {}'.format(change.name)
                    ] = change.gerrit_url

                for change in status_of_changes.not_applied:
                    pres.links[
                        'failed to apply {}'.format(change.name)
                    ] = change.gerrit_url

            snapshot_dir = self.m.path['start_dir'].join('snapshot')
            self.snapshot_to_dir(snapshot_dir)

    @property
    def root(self):
        """Returns the logical top level directory of the checkout.

        Returns:
            For Git checkouts, returns the top-level directory. For Android Repo
            Tool checkouts, returns the top-level directory unless there is
            exactly one subdirectory of that top-level directory (except for
            .repo). In that case it returns that one subdirectory.
        """
        return self._root

    @property
    def repo_top(self):
        """Always returns the directory containing the .repo folder."""
        return self._repo_top

    @property
    def manifest(self):
        return self._manifest

    def snapshot_to_dir(self, directory):
        self.m.file.ensure_directory('mkdir', directory)
        if self.manifest_snapshot:
            self.m.file.write_text(
                'write manifest.xml',
                directory.join('manifest.xml'),
                self.manifest_snapshot,
            )

        if self.submodule_snapshot:
            self.m.file.write_text(
                'write submodule snapshot',
                directory.join('submodules.log'),
                self.submodule_snapshot,
            )

        with self.m.context(cwd=self.root):
            log = self.m.git(
                'log',
                'log',
                '--oneline',
                '-n',
                '10',
                stdout=self.m.raw_io.output_text(),
                ok_ret='any',
            ).stdout
        self.m.file.write_text(
            'write git log', directory.join('git.log'), log,
        )

    @property
    def manifest_snapshot(self):
        if not self.use_repo:
            return None
        if not self._manifest_snapshot:
            with self.m.context(cwd=self.root):
                self._manifest_snapshot = self.m.repo.manifest_snapshot()
        return self._manifest_snapshot

    @property
    def submodule_snapshot(self):
        if self._submodule_snapshot is None:
            with self.m.context(cwd=self.root):
                # To get step_test_data line to pass pylint.
                raw_io_stream_output = self.m.raw_io.test_api.stream_output_text

                self._submodule_snapshot = (
                    self.m.git(
                        'submodule-status',
                        'submodule',
                        'status',
                        '--recursive',
                        stdout=self.m.raw_io.output_text(),
                        step_test_data=lambda: raw_io_stream_output(
                            'submodule status filler text',
                        ),
                        ok_ret='any',
                    ).stdout.strip()
                    or ''
                )
        return self._submodule_snapshot

    @property
    def remote(self):
        return self._remote

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

    @property
    def manifest_file(self):
        return self._manifest_file

    @property
    def use_repo(self):
        return self._use_repo

    @property
    def revision(self):
        """Returns revision of the primary checkout directory."""
        assert self._root, 'checkout() not yet called'
        if self._revision:
            return self._revision

        self._revision = self.get_revision(self._root)
        return self._revision

    @property
    def changes(self):
        """Returns the changes that triggered the build.

        For CI builds this is a list with at most one item, the merged commit
        that triggered the build. For CQ builds this could contain multiple
        pending CLs.
        """
        assert self._root, 'checkout() not yet called'
        return self._changes

    def get_revision(self, root, name='git log', test_data='HASH'):
        """Like self.revision, but works for secondary checkouts."""
        with self.m.context(cwd=root):
            return self.m.git(
                name,
                'log',
                '--max-count=1',
                '--pretty=format:%H',
                stdout=self.m.raw_io.output_text(),
                step_test_data=lambda: self.test_api.m.raw_io.stream_output_text(
                    test_data,
                ),
            ).stdout.strip()

    # gerrit_host and gerrit_project aren't really properties of checkout, but
    # they make some sense here and don't make much sense anywhere else.
    _REMOTE_REGEX = re.compile(r'^https://(?P<host>[^/]+)/(?P<project>.+)$')

    def gerrit_host(self, remote=None):
        match = self._REMOTE_REGEX.match(remote or self.remote)
        if not match:
            return

        gerrit_review_host = '{}'.format(match.group('host'))
        if '-review' not in gerrit_review_host:
            gerrit_review_host = gerrit_review_host.replace('.', '-review.', 1)
        return gerrit_review_host

    def gerrit_project(self, remote=None):
        match = self._REMOTE_REGEX.match(remote or self.remote)
        if not match:
            return

        return match.group('project')
