# 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.
"""Roll a submodule of a git repository."""

import re

import attr
from PB.recipes.pigweed.submodule_roller import InputProperties
from recipe_engine import post_process
from six.moves import configparser
from six.moves import urllib
from six import StringIO

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/git',
    'fuchsia/status_check',
    'pigweed/checkout',
    'pigweed/cq_deps',
    'pigweed/roll_util',
    'recipe_engine/buildbucket',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = InputProperties

PYTHON_VERSION_COMPATIBILITY = "PY3"


@attr.s
class _RevisionChange(object):
    old = attr.ib(type=str)
    new = attr.ib(type=str)


def _update_submodule(api, path, new_revision):
    old_revision = api.checkout.get_revision(
        path, 'get old revision', test_data='1' * 40
    )

    with api.context(cwd=path):
        api.git('git fetch', 'fetch', 'origin', new_revision)
        api.git('git checkout', 'checkout', 'FETCH_HEAD')

    # In case new_revision is a branch name we need to retrieve the hash it
    # resolved to.
    if not re.search(r'^[0-9a-f]{40}$', new_revision):
        new_revision = api.checkout.get_revision(
            path, 'get new revision', test_data='2' * 40
        )

    return _RevisionChange(old=old_revision, new=str(new_revision))


def _process_deps(api, rolls, submodules, gerrit_name):
    """Process any dependencies and add them to rolls.

    Process any dependencies ("Requires:" lines) in the one initial entry in
    rolls and add them to rolls.

    Args:
        api: Recipe api object.
        rolls (dict[str,api.roll_util.Roll]): List of rolls, initially of
            length one but added to by this function.
        submodules (list[api.checkout.Submodule]): List of submodules in this
            checkout.
        gerrit_name (str): Name of initial gerrit server.

    Returns:
        Nothing.
    """

    deps = {}

    # Initially, there should only be one entry in rolls.
    assert len(rolls) == 1
    submodule_path = list(rolls)[0]
    submodule_dir = api.checkout.root.join(submodule_path)

    for commit in rolls[submodule_path].commits:
        dependencies, unresolved = api.cq_deps.resolve(
            gerrit_name, commit.hash, statuses=('MERGED',)
        )

        if unresolved:
            with api.step.nest('failed to resolve some dependencies') as pres:
                for dep in unresolved:
                    pres.links[dep.name] = dep.gerrit_url

        for dep in dependencies:
            deps[dep.name] = dep

    # Ok, this is complicated, so I'll go over what it's supposed to do
    # with an example. Suppose we're trying to roll commit 1 of submodule A.
    # That commit depends on commit 2 of submodule B and commit 3 of
    # submodule C. Commit 3 of submodule C depends on commit 4 of submodule
    # B. Submodule B is referenced twice, with commits 2 and 4. Commit 4 is
    # on top of commit 2, so we should roll B to commit 4 and skip the
    # intermediate step of commit 2.

    # Loop over all the dependencies and apply them all. If we see commit B4
    # first, we ignore commit B2 when we see it because it's a backwards
    # roll to go from B4 to B2. If we see commit B2 first, we roll to it
    # (B2~1..B2) and then we update the roll when we see B4 (to B2~1..B4).
    # The end result is that we are only rolling to B4 but the various
    # commits that roll brings includes B2.

    # The list of revisions between old_revision and new_revision isn't
    # processed until api.roll_util.message() is called in the
    # api.auto_roller.attempt_roll() call, so having an intermediate state
    # where we have a partial version of the final roll doesn't affect
    # anything.

    # Also handle various other cases like where the dependency is not in
    # the checkout or access to the dependency is forbidden. Does not yet
    # handle the case where an unrolled parent CL has unrolled dependencies.

    with api.step.nest('deps') as pres:
        pres.step_summary_text = repr(deps)

    for dep in deps.values():
        found_dep = False

        for sub in submodules:
            if not api.checkout.remotes_equivalent(dep.remote, sub.remote):
                continue
            found_dep = True

            with api.step.nest('applying {}'.format(dep.name)) as pres:
                old_revision = sub.hash
                if sub.relative_path in rolls:
                    old_revision = rolls[sub.relative_path].old_revision
                with api.context(cwd=submodule_dir):
                    api.git(
                        'fetch {}'.format(dep.commit),
                        'fetch',
                        dep.remote,
                        dep.commit,
                    )
                direction = api.roll_util.get_roll_direction(
                    submodule_dir, old_revision, dep.commit
                )

                if api.roll_util.can_roll(direction):
                    _update_submodule(api, sub.path, dep.commit)
                    rolls[sub.relative_path] = api.roll_util.Roll(
                        project_name=sub.relative_path,
                        old_revision=old_revision,
                        new_revision=dep.commit,
                        proj_dir=sub.path,
                        direction=direction,
                    )
                    pres.step_summary_text = 'applied'

                else:
                    api.roll_util.skip_roll_step(
                        dep.remote, old_revision, dep.commit,
                    )
                    pres.step_summary_text = 'already applied'

        if not found_dep:
            with api.step.nest('skipping required {}'.format(dep.name)) as pres:
                pres.step_summary_text = 'repository is not in checkout'


def RunSteps(api, props):  # pylint: disable=invalid-name
    submodule_path = props.submodule_path
    submodule_name = props.submodule_name or submodule_path
    new_revision = props.new_revision or None
    submodule_branch = props.submodule_branch or None
    dry_run = props.dry_run
    cc_authors_on_rolls = props.cc_authors_on_rolls
    cc_reviewers_on_rolls = props.cc_reviewers_on_rolls
    cc_domains = props.cc_domains
    always_cc = props.always_cc

    # The checkout module will try to use trigger data to pull in a specific
    # patch. Since the triggering commit is in a different repository that
    # needs to be disabled.
    api.checkout(use_trigger=False)

    if new_revision:
        new_revision = new_revision.lower()

    # If new_revision wasn't supplied in a property try to get it from the
    # trigger.
    bb_remote = None
    if new_revision is None:
        commit = api.buildbucket.build.input.gitiles_commit
        if commit and commit.project:
            new_revision = commit.id
            host = commit.host
            bb_remote = 'https://{}/{}'.format(host, commit.project)

    # Confirm the given path is actually a submodule.
    gitmodules = api.file.read_text(
        'read .gitmodules', api.checkout.root.join('.gitmodules')
    )
    # Example .gitmodules file:
    # [submodule "third_party/pigweed"]
    #   path = third_party/pigweed
    #   url = https://pigweed.googlesource.com/pigweed/pigweed

    # configparser doesn't like leading whitespace on lines, despite what its
    # documentation says.
    gitmodules = re.sub(r'\n\s+', '\n', gitmodules)
    parser = configparser.RawConfigParser()
    parser.readfp(StringIO(gitmodules))
    section = 'submodule "{}"'.format(submodule_name)
    if not parser.has_section(section):
        sections = parser.sections()
        submodules = sorted(re.sub(r'^.*"(.*)"$', r'\1', x) for x in sections)
        raise api.step.StepFailure(
            'no submodule "{}" (submodules: {})'.format(
                submodule_name, ', '.join('"{}"'.format(x) for x in submodules)
            )
        )

    if not submodule_branch:
        try:
            submodule_branch = parser.get(section, 'branch')
        except configparser.NoOptionError:
            submodule_branch = 'main'

    # If we still don't have a revision then it wasn't in the properties nor in
    # the trigger. (Perhaps this was manually triggered.) In this case we update
    # to the property-specified or inferred submodule branch HEAD.
    if new_revision is None:
        new_revision = submodule_branch

    # This isn't used until much later but needs to be invoked before any
    # submodules get updated.
    submodules = api.checkout.submodules(api.checkout.root)

    submodule_dir = api.checkout.root.join(submodule_path)

    remote = api.roll_util.normalize_remote(
        parser.get(section, 'url'), api.checkout.remote,
    )

    # If this was triggered by a gitiles poller, check that the triggering
    # repository matches submodule_path.

    if bb_remote:
        if not api.checkout.remotes_equivalent(remote, bb_remote):
            raise api.step.StepFailure(
                'triggering repository ({}) does not match submodule remote '
                '({})'.format(bb_remote, remote)
            )

    change = _update_submodule(api, submodule_dir, new_revision)

    direction = api.roll_util.get_roll_direction(
        submodule_dir, change.old, change.new
    )

    # If the primary roll is not necessary or is backwards we can exit
    # immediately and don't need to check deps.
    if not api.roll_util.can_roll(direction):
        api.roll_util.skip_roll_step(remote, change.old, change.new)
        return

    rolls = {
        submodule_path: api.roll_util.Roll(
            project_name=str(submodule_path),
            old_revision=change.old,
            new_revision=change.new,
            proj_dir=submodule_dir,
            direction=direction,
        ),
    }

    gerrit_name = urllib.parse.urlparse(remote).netloc.split('.')[0]

    if len(rolls[submodule_path].commits) >= 10:
        with api.step.nest('too many commits, not processing dependencies'):
            pass

    else:
        _process_deps(api, rolls, submodules, gerrit_name)

    cc = set()
    if cc_authors_on_rolls:
        cc.update(api.roll_util.authors(*rolls.values()))
    if cc_reviewers_on_rolls:
        cc.update(api.roll_util.reviewers(*rolls.values()))

    def include_cc(email):
        return api.roll_util.include_cc(
            email, cc_domains, api.checkout.gerrit_host()
        )

    # include_cc() writes steps, so we want things sorted before calling it.
    cc = sorted(set(cc))
    cc = [x for x in cc if include_cc(x)]

    roll_kwargs = {}
    if always_cc:
        roll_kwargs['cc'] = cc
    else:
        roll_kwargs['cc_on_failure'] = cc

    change = api.auto_roller.attempt_roll(
        gerrit_host=api.checkout.gerrit_host(),
        gerrit_project=api.checkout.gerrit_project(),
        upstream_ref=api.checkout.branch,
        repo_dir=api.checkout.root,
        commit_message=api.roll_util.message(*rolls.values()),
        dry_run=dry_run,
        labels_to_set=api.roll_util.labels_to_set,
        labels_to_wait_on=api.roll_util.labels_to_wait_on,
        bot_commit=props.bot_commit,
        **roll_kwargs
    )

    return api.auto_roller.raw_result(change)


def GenTests(api):  # pylint: disable=invalid-name
    """Create tests."""

    def _url(x):
        if x.startswith(('https://', 'sso://', '.')):
            return x
        return 'https://foo.googlesource.com/' + x

    def trigger(url, **kwargs):
        return api.checkout.ci_test_data(git_repo=_url(url), **kwargs)

    def gitmodules(**submodules):
        branches = {}
        for k, v in submodules.items():
            if k.endswith('_branch'):
                branches[k.replace('_branch', '')] = v

        for x in branches:
            del submodules['{}_branch'.format(x)]

        text = []
        for k, v in sorted(submodules.items()):
            text.append(
                '[submodule "{0}"]\n\tpath = {0}\n\turl = {1}\n'.format(
                    k, _url(v)
                )
            )
            if k in branches:
                text.append('\tbranch = {}\n'.format(branches[k]))

        return api.step_data(
            'read .gitmodules', api.file.read_text(''.join(text))
        )

    def properties(**kwargs):
        new_kwargs = api.checkout.git_properties()
        new_kwargs.update(kwargs)
        new_kwargs.setdefault('dry_run', True)
        return api.properties(**new_kwargs)

    def commit_data(name, **kwargs):
        return api.roll_util.commit_data(
            name,
            api.roll_util.commit('a' * 40, 'foo\nbar\n\nChange-Id: I1111'),
            **kwargs
        )

    yield (
        api.status_check.test('success-sso-cc-authors')
        + properties(submodule_path='a1', cc_authors_on_rolls=True)
        + trigger('a1')
        + commit_data('a1', prefix='')
        + gitmodules(a1='sso://foo/a1')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('failure-cc-authors', status='failure')
        + properties(submodule_path='a1', cc_authors_on_rolls=True)
        + trigger('a1')
        + commit_data('a1', prefix='')
        + gitmodules(a1='https://foo.googlesource.com/a1')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_failure()
    )

    yield (
        api.status_check.test('relative-dot', status='failure')
        + properties(submodule_path='a1', cc_authors_on_rolls=True)
        + trigger('https://pigweed.googlesource.com/pigweed/pigweed/a1')
        + commit_data('a1', prefix='')
        + gitmodules(a1='./a1')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_failure()
    )

    yield (
        api.status_check.test('relative-dotdot', status='failure')
        + properties(submodule_path='a1', cc_authors_on_rolls=True)
        + trigger('https://pigweed.googlesource.com/pigweed/a1')
        + commit_data('a1', prefix='')
        + gitmodules(a1='../a1')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_failure()
    )

    yield (
        api.status_check.test('relative-dotdot-dotdot', status='failure')
        + properties(submodule_path='a1', cc_authors_on_rolls=True)
        + trigger('https://pigweed.googlesource.com/a1')
        + commit_data('a1', prefix='')
        + gitmodules(a1='../../a1')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_failure()
    )

    yield (
        api.status_check.test('name-not-found', status='failure')
        + properties(submodule_path='a1')
        + trigger('a1')
        + gitmodules(b2='b2', c3='c3', d4='d4')
    )

    yield (
        api.status_check.test('trigger-mismatch', status='failure')
        + properties(submodule_path='a1')
        + trigger('a1')
        + gitmodules(a1='b2')
    )

    yield (
        api.status_check.test('trigger-mismatch-equivalent')
        + properties(
            submodule_path='a1',
            **api.checkout.git_properties(
                equivalent_remotes=(
                    (
                        'https://foo.googlesource.com/a1',
                        'https://foo.googlesource.com/b2',
                    ),
                ),
            )
        )
        + trigger('a1')
        + commit_data('a1', prefix='')
        + gitmodules(a1='b2')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('with-newrev-prop-cc-reviewers')
        + properties(
            submodule_path='a1',
            new_revision='c' * 40,
            cc_reviewers_on_rolls=True,
            always_cc=True,
        )
        + commit_data('a1', prefix='')
        + gitmodules(a1='a1')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('with-branch-prop-filter-emails')
        + properties(
            submodule_path='a1',
            submodule_branch='branch',
            cc_authors_on_rolls=True,
            cc_reviewers_on_rolls=True,
            cc_domains=['google.com'],
        )
        + commit_data('a1', prefix='')
        + gitmodules(a1='a1', a1_branch='not_used')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('no-revision')
        + properties(submodule_path='a1')
        + commit_data('a1', prefix='')
        + gitmodules(a1='a1', a1_branch='custom')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('backwards')
        + properties(submodule_path='a1')
        + trigger('a1')
        + gitmodules(a1='a1')
        + api.roll_util.backward_roll()
    )

    def assert_too_many():
        return api.post_process(
            post_process.MustRun,
            'too many commits, not processing dependencies',
        )

    atoz = 'abcdefghijklmnopqrstuvwxyz'

    yield (
        api.status_check.test('too-many-skip-deps')
        + properties(submodule_path='a1', cc_authors_on_rolls=True)
        + trigger('a1')
        + api.roll_util.commit_data(
            'a1', *[api.roll_util.commit(x * 40, x) for x in atoz]
        )
        + gitmodules(a1='sso://foo/a1')
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
        + assert_too_many()
    )

    # Much of the step data in the tests using "Requires:" is sufficient to
    # test the logic that processes the immediate result of the the
    # corresponding step, but does not make sense as a whole.
    def requires_test(name, *requires, **kwargs):
        assert requires
        status = kwargs.pop('status', 'success')
        assert not kwargs
        return (
            api.status_check.test(name, status=status)
            + properties(submodule_path='spam')
            + trigger('spam', revision='2' * 40)
            + gitmodules(spam='spam', ham='ham')
            + api.checkout.submodules(
                spam='https://foo.googlesource.com/spam',
                ham='https://foo.googlesource.com/ham',
                eggs='https://foo.googlesource.com/eggs',
                prefix='',
            )
            + api.cq_deps.details(
                'foo:2000', message='Requires: {}'.format(','.join(requires)),
            )
            + api.roll_util.commit_data(
                'spam', api.roll_util.commit('2' * 40), prefix='',
            )
            + api.roll_util.forward_roll()
        )

    # CL 2000 requires CL 444 in ham which has not rolled.
    yield (
        requires_test('with-requires', 'foo:444')
        + api.cq_deps.details('foo:444', status='MERGED', project='ham')
        + api.roll_util.commit_data(
            'ham', api.roll_util.commit('2' * 40), prefix='applying foo:444.',
        )
        + api.roll_util.forward_roll('applying foo:444.')
        + api.auto_roller.dry_run_success()
    )

    # CL 2000 requires CL 444 in ham which has already rolled.
    yield (
        requires_test('with-requires-already-applied', 'foo:444')
        + api.cq_deps.details('foo:444', status='MERGED', project='ham')
        + api.roll_util.noop_roll('applying foo:444.')
        + api.auto_roller.dry_run_success()
    )

    # CL 2000 requires CL 444 which is forbidden.
    yield (
        requires_test('with-requires-forbidden', 'foo:444')
        + api.cq_deps.forbidden('foo:444')
        + api.auto_roller.dry_run_success()
    )

    # CL 2000 requires CL 444 which is not in this checkout.
    yield (
        requires_test('with-requires-not-in-checkout', 'foo:444')
        + api.cq_deps.details(
            'foo:444', status='MERGED', project='not-in-this-checkout',
        )
        + api.auto_roller.dry_run_success()
    )

    # CL 2000 requires CL 444 in ham which requires CL 555 in eggs.
    yield (
        requires_test('with-requires-transitive', 'foo:444')
        + api.cq_deps.details(
            'foo:444',
            status='MERGED',
            project='ham',
            message='Requires: foo:555',
        )
        + api.roll_util.commit_data(
            'ham', api.roll_util.commit('2' * 40), prefix='applying foo:444.',
        )
        + api.roll_util.forward_roll('applying foo:444.')
        + api.cq_deps.details('foo:555', status='MERGED', project='eggs')
        + api.roll_util.commit_data(
            'eggs', api.roll_util.commit('2' * 40), prefix='applying foo:555.',
        )
        + api.roll_util.forward_roll('applying foo:555.')
        + api.auto_roller.dry_run_success()
    )

    # CL 2000 requires CL 444 in ham which requires CL 2000.
    yield (
        requires_test('with-requires-loop', 'foo:444')
        + api.cq_deps.details(
            'foo:444',
            status='MERGED',
            project='ham',
            message='Requires: foo:2000',
        )
        + api.roll_util.commit_data(
            'ham', api.roll_util.commit('2' * 40), prefix='applying foo:444.',
        )
        + api.roll_util.forward_roll('applying foo:444.')
        + api.auto_roller.dry_run_success()
    )

    # CL 2000 requires CL 444 in ham and CL 555 in ham, both of which are
    # submitted.
    def parent_child_test(*args, **kwargs):
        return (
            requires_test(*args, **kwargs)
            + api.cq_deps.details('foo:444', status='MERGED', project='ham',)
            + api.roll_util.commit_data(
                'ham',
                api.roll_util.commit('4' * 40),
                prefix='applying foo:444.',
            )
            + api.roll_util.forward_roll('applying foo:444.')
            + api.cq_deps.details('foo:555', status='MERGED', project='ham',)
        )

    # CL 2000 requires CL 444 in ham and CL 555 in ham, both of which are
    # submitted. CL 444 is a parent of CL 555.
    yield (
        parent_child_test('with-requires-child', 'foo:444', 'foo:555')
        + api.roll_util.forward_roll('applying foo:555.')
        + api.roll_util.commit_data(
            'ham', api.roll_util.commit('5' * 40), prefix='applying foo:555.',
        )
        + api.auto_roller.dry_run_success()
    )

    # CL 2000 requires CL 444 in ham and CL 555 in ham, both of which are
    # submitted. CL 555 is a parent of CL 444.
    yield (
        parent_child_test('with-requires-parent', 'foo:444', 'foo:555')
        + api.roll_util.backward_roll('applying foo:555.')
        + api.auto_roller.dry_run_success()
    )
