# 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 project in an Android Repo Tool workspace."""

import collections
import re
import xml.etree.ElementTree

from PB.recipes.pigweed.repo_roller import InputProperties
from six.moves import urllib

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/sso',
    'fuchsia/status_check',
    'pigweed/checkout',
    'pigweed/roll_util',
    'recipe_engine/buildbucket',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/raw_io',
    'recipe_engine/step',
]

PROPERTIES = InputProperties

PYTHON_VERSION_COMPATIBILITY = "PY3"


class _TreeBuilder(xml.etree.ElementTree.TreeBuilder):
    def comment(self, data):
        self.start(xml.etree.ElementTree.Comment, {})
        self.data(data)
        self.end(xml.etree.ElementTree.Comment)


def _is_branch(revision):
    """Return True if revision appears to be a branch name."""
    if re.search(r'^[0-9a-fA-F]{40}$', revision):
        return False
    return not revision.startswith('refs/tags/')


# ElementTree orders attributes differently in Python 2 and 3, but if given
# attributes in a specific order it preserves that order.
def _order_attributes(root):
    for el in root.iter():
        if len(el.attrib) > 1:
            new_attrib = sorted(el.attrib.items())
            el.attrib.clear()
            el.attrib.update(new_attrib)


def RunSteps(api, props):  # pylint: disable=invalid-name
    path_to_update = str(props.path_to_update)
    new_revision = str(props.new_revision) 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)
    filepath = api.checkout.root.join(api.checkout.manifest_file)

    # If new_revision wasn't supplied in a property try to get it from the
    # trigger. If it's not in the trigger it will be retrieved later.
    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)

    tree = _TreeBuilder()
    parser = xml.etree.ElementTree.XMLParser(target=tree)
    parser.feed(api.file.read_text('read manifest', filepath))
    parser.close()
    root = tree.close()

    defaults = {}
    for default in root.findall('default'):
        defaults.update(default.attrib)

    remotes = {}
    for rem in root.findall('remote'):
        remotes[rem.attrib['name']] = rem.attrib

    # Search for path_to_update and check the repository it refers to matches
    # the triggering repository. This check is mostly a config check and
    # shouldn't be triggered in real runs unless somebody moves around project
    # paths in the manifest without updating the builder definition.
    paths_found = []
    proj = None
    proj_attrib = {}
    for proj in root.findall('project'):
        # Sometimes projects don't define something in which case we need to
        # fall back on the remote specified by the project or the default for
        # the entire manifest.
        proj_attrib = {}
        proj_attrib.update(defaults)
        remote_name = proj.attrib.get('remote', defaults.get('remote', None))
        assert remote_name
        proj_attrib.update(remotes[remote_name])
        proj_attrib.update(proj.attrib)
        proj_attrib['fetch'] = api.sso.sso_to_https(proj_attrib['fetch'])

        # Apparently if path is left off name is used. This is mildly
        # infuriating, but easy to work around.
        if 'path' not in proj_attrib:
            proj_attrib['path'] = proj_attrib['name']

        paths_found.append(proj_attrib['path'])
        if proj_attrib['path'] == path_to_update:
            fetch_host = proj_attrib['fetch'].strip('/')
            if fetch_host.startswith('..'):
                parsed = urllib.parse.urlparse(api.checkout.props.remote)
                fetch_host = '{}://{}{}'.format(
                    parsed.scheme, parsed.netloc, fetch_host[2:]
                )

            manifest_remote = fetch_host + '/' + proj_attrib['name'].strip('/')
            if bb_remote and not api.checkout.remotes_equivalent(
                manifest_remote, bb_remote
            ):
                raise api.step.StepFailure(
                    "repo paths don't match: {} from manifest "
                    "and {} from buildbucket".format(manifest_remote, bb_remote)
                )
            break

        # Reset proj_attrib to None if this entry wasn't a match, so if this is
        # the last iteration the condition a few lines down will work.
        proj_attrib = {}

    if not proj_attrib:
        raise api.step.StepFailure(
            'cannot find "{}" in manifest (found {})'.format(
                path_to_update, ', '.join('"{}"'.format(x) for x in paths_found)
            )
        )

    if 'upstream' in proj_attrib:
        proj_branch = proj_attrib['upstream']
    elif 'revision' in proj_attrib and _is_branch(proj_attrib['revision']):
        proj_branch = proj_attrib['revision']
    else:
        proj_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 need
    # to determine the latest revision of this repository. The use_trigger flag
    # should have no effect but using it to be explicit. Checking out even if
    # not needed so commit messages can be collected later.
    proj_dir = api.path['start_dir'].join('project')
    api.checkout(
        manifest_remote, branch=proj_branch, root=proj_dir, use_trigger=False
    )
    if new_revision is None:
        new_revision = api.checkout.get_revision(proj_dir)

    assert new_revision
    new_revision = str(new_revision)

    # If upstream not set we may be transitioning from tracking a branch to
    # rolling. In that case set upstream to be the revision, but only if the
    # revision appears to be a branch.
    if 'upstream' not in proj_attrib:
        if _is_branch(proj_attrib['revision']):
            # Explicitly update both proj.attrib and proj_attrib to minimize
            # confusion if these statements are moved around later.
            proj.attrib['upstream'] = proj_attrib['revision']
            proj_attrib['upstream'] = proj.attrib['upstream']
        else:
            raise api.step.StepFailure(
                'upstream not set and revision is not a branch, aborting'
            )

    old_revision = proj_attrib['revision']
    # Explicitly update both proj.attrib and proj_attrib to minimize confusion.
    proj_attrib['revision'] = proj.attrib['revision'] = new_revision

    direction = api.roll_util.Direction.FORWARD
    if not _is_branch(old_revision):
        direction = api.roll_util.get_roll_direction(
            proj_dir, old_revision, new_revision
        )

    if not api.roll_util.can_roll(direction):
        api.roll_util.skip_roll_step(
            manifest_remote, old_revision, new_revision
        )
        return

    _order_attributes(root)

    api.file.write_text(
        'write manifest',
        filepath,
        '<?xml version="1.0" encoding="UTF-8"?>\n{}\n'.format(
            xml.etree.ElementTree.tostring(root).decode(),
        ),
    )

    roll = api.roll_util.Roll(
        project_name=path_to_update,
        old_revision=old_revision,
        new_revision=new_revision,
        proj_dir=proj_dir,
        direction=direction,
    )

    cc = set()
    if cc_authors_on_rolls:
        cc.update(api.roll_util.authors(roll))
    if cc_reviewers_on_rolls:
        cc.update(api.roll_util.reviewers(roll))

    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(roll),
        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 properties(api, path, dry_run=True, equivalent_remotes=(), **kwargs):
        props = api.checkout.git_properties(
            remote='https://host.googlesource.com/manifest',
            equivalent_remotes=equivalent_remotes,
        )
        props['path_to_update'] = path
        props['dry_run'] = dry_run
        props.update(**kwargs)
        return api.properties(**props)

    def read_step_data():
        return api.step_data(
            'read manifest',
            api.file.read_text(
                """
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <!-- single-line comment -->
  <remote name="foo" fetch="sso://foo" review="sso://foo" />
  <remote name="bar" fetch="sso://bar" review="sso://bar" />
  <remote name="host" fetch=".." review="sso://host" />
  <remote name="dotdot-prefix" fetch="../prefix" review="sso://host/prefix" />
  <remote name="host-prefix" fetch="sso://host/prefix"
    review="sso://host/prefix" />
  <default remote="bar" />
  <project name="a" path="a1" remote="foo"
    revision="1111111111111111111111111111111111111111" upstream="main"/>
  <project name="b" path="b2"
    revision="2222222222222222222222222222222222222222" upstream="main"/>
  <!--
  multi
  line
  comment
  -->
  <project name="c" path="c3" revision="main"/>
  <project name="d" path="d4"
    revision="0000000000111111111122222222223333333333"/>
  <project name="e5" revision="refs/tags/e"/>
  <project name="f" path="f6" remote="host" revision="main"/>
  <project name="g" path="g7" remote="dotdot-prefix" revision="main"/>
  <project name="h" path="h8" remote="host-prefix" revision="main"/>
</manifest>
""".lstrip()
            ),
        )

    def commit_data(name):
        return api.roll_util.commit_data(
            name, api.roll_util.commit('a' * 40, 'foo\nbar')
        )

    yield (
        api.status_check.test('success')
        + properties(api, path='a1', cc_authors_on_rolls=True, always_cc=True)
        + api.checkout.ci_test_data(git_repo='https://foo.googlesource.com/a')
        + commit_data('a1')
        + read_step_data()
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('name-not-found', status='failure')
        + properties(api, path='missing')
        + api.checkout.ci_test_data(git_repo='https://bar.googlesource.com/b')
        + read_step_data()
    )

    yield (
        api.status_check.test('equivalent')
        + properties(
            api,
            path='b2',
            equivalent_remotes=(
                (
                    'https://equiv.googlesource.com/b',
                    'https://bar.googlesource.com/b',
                ),
            ),
            cc_reviewers_on_rolls=True,
        )
        + api.checkout.ci_test_data(git_repo='https://equiv.googlesource.com/b')
        + commit_data('b2')
        + read_step_data()
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('upstream-not-set')
        + properties(api, path='c3')
        + api.checkout.ci_test_data(git_repo='https://bar.googlesource.com/c')
        + commit_data('c3')
        + read_step_data()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test(
            'upstream-not-set-revision-not-branch', status='failure'
        )
        + properties(api, path='d4')
        + api.checkout.ci_test_data(git_repo='https://bar.googlesource.com/c')
        + read_step_data()
    )

    yield (
        api.status_check.test('no-trigger-with-upstream')
        + properties(api, path='a1')
        + commit_data('a1')
        + read_step_data()
        + api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        )
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('no-trigger-with-revision-branch')
        + properties(api, path='c3')
        + commit_data('c3')
        + read_step_data()
        + api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        )
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('no-trigger-with-revision-hash', status='failure')
        + properties(api, path='d4')
        + read_step_data()
        + api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        )
    )

    yield (
        api.status_check.test('no-trigger-with-revision-tag', status='failure')
        + properties(api, path='e5')
        + read_step_data()
        + api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        )
    )

    yield (
        api.status_check.test('backwards')
        + properties(api, path='a1')
        + api.checkout.ci_test_data(git_repo='https://foo.googlesource.com/a')
        + read_step_data()
        + api.roll_util.backward_roll()
    )

    yield (
        api.status_check.test('host-dot-dot')
        + properties(api, path='f6')
        + api.checkout.ci_test_data(git_repo='https://host.googlesource.com/f')
        + commit_data('f6')
        + read_step_data()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('dotdot-prefix')
        + properties(api, path='g7')
        + api.checkout.ci_test_data(
            git_repo='https://host.googlesource.com/prefix/g'
        )
        + commit_data('g7')
        + read_step_data()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('host-prefix')
        + properties(api, path='h8')
        + api.checkout.ci_test_data(
            git_repo='https://host.googlesource.com/prefix/h'
        )
        + commit_data('h8')
        + read_step_data()
        + api.auto_roller.dry_run_success()
    )
