# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""A command to download new baselines for NeedsRebaseline tests.

This command checks the list of tests with NeedsRebaseline expectations,
and downloads the latest baselines for those tests from the results archived
by the continuous builders.
"""

import logging
import optparse
import re
import sys
import time
import traceback
import urllib2

from webkitpy.common.net.buildbot import Build, current_build_link
from webkitpy.layout_tests.models.test_expectations import TestExpectations, BASELINE_SUFFIX_LIST
from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand


_log = logging.getLogger(__name__)


class AutoRebaseline(AbstractParallelRebaselineCommand):
    name = 'auto-rebaseline'
    help_text = 'Rebaselines any NeedsRebaseline lines in TestExpectations that have cycled through all the bots.'
    AUTO_REBASELINE_BRANCH_NAME = 'auto-rebaseline-temporary-branch'
    AUTO_REBASELINE_ALT_BRANCH_NAME = 'auto-rebaseline-alt-temporary-branch'

    # Rietveld uploader stinks. Limit the number of rebaselines in a given patch to keep upload from failing.
    # FIXME: http://crbug.com/263676 Obviously we should fix the uploader here.
    MAX_LINES_TO_REBASELINE = 200

    SECONDS_BEFORE_GIVING_UP = 300

    def __init__(self):
        super(AutoRebaseline, self).__init__(options=[
            # FIXME: Remove this option.
            self.no_optimize_option,
            # FIXME: Remove this option.
            self.results_directory_option,
            optparse.make_option('--auth-refresh-token-json', help='Rietveld auth refresh JSON token.'),
            optparse.make_option('--dry-run', action='store_true', default=False,
                                 help='Run without creating a temporary branch, committing locally, or uploading/landing '
                                 'changes to the remote repository.')
        ])
        self._blame_regex = re.compile(r'''
                ^(\S*)      # Commit hash
                [^(]* \(    # Whitespace and open parenthesis
                <           # Email address is surrounded by <>
                (
                    [^@]+   # Username preceding @
                    @
                    [^@>]+  # Domain terminated by @ or >, some lines have an additional @ fragment after the email.
                )
                .*?([^ ]*)  # Test file name
                \ \[        # Single space followed by opening [ for expectation specifier
                [^[]*$      # Prevents matching previous [ for version specifiers instead of expectation specifiers
            ''', re.VERBOSE)

    def bot_revision_data(self, git):
        revisions = []
        for builder_name in self._release_builders():
            result = self._tool.buildbot.fetch_results(Build(builder_name))
            if result.run_was_interrupted():
                _log.error("Can't rebaseline because the latest run on %s exited early.", result.builder_name())
                return []
            revisions.append({
                'builder': result.builder_name(),
                'revision': result.chromium_revision(git),
            })
        return revisions

    @staticmethod
    def _strip_comments(line):
        comment_index = line.find('#')
        if comment_index == -1:
            comment_index = len(line)
        return re.sub(r"\s+", ' ', line[:comment_index].strip())

    def tests_to_rebaseline(self, tool, min_revision, print_revisions):
        port = tool.port_factory.get()
        expectations_file_path = port.path_to_generic_test_expectations_file()

        tests = set()
        revision = None
        commit = None
        author = None
        bugs = set()
        has_any_needs_rebaseline_lines = False

        for line in tool.git().blame(expectations_file_path).split('\n'):
            line = self._strip_comments(line)
            if 'NeedsRebaseline' not in line:
                continue

            has_any_needs_rebaseline_lines = True

            parsed_line = self._blame_regex.match(line)
            if not parsed_line:
                # Deal gracefully with inability to parse blame info for a line in TestExpectations.
                # Parsing could fail if for example during local debugging the developer modifies
                # TestExpectations and does not commit.
                _log.info("Couldn't find blame info for expectations line, skipping [line=%s].", line)
                continue

            commit_hash = parsed_line.group(1)
            commit_position = tool.git().commit_position_from_git_commit(commit_hash)

            test = parsed_line.group(3)
            if print_revisions:
                _log.info('%s is waiting for r%s', test, commit_position)

            if not commit_position or commit_position > min_revision:
                continue

            if revision and commit_position != revision:
                continue

            if not revision:
                revision = commit_position
                commit = commit_hash
                author = parsed_line.group(2)

            bugs.update(re.findall(r"crbug\.com\/(\d+)", line))
            tests.add(test)

            if len(tests) >= self.MAX_LINES_TO_REBASELINE:
                _log.info('Too many tests to rebaseline in one patch. Doing the first %d.', self.MAX_LINES_TO_REBASELINE)
                break

        return tests, revision, commit, author, bugs, has_any_needs_rebaseline_lines

    def commit_message(self, author, revision, commit, bugs):
        message = 'Auto-rebaseline for r%s\n\n' % revision
        build_link = current_build_link(self._tool)
        if build_link:
            message += 'Build: %s\n\n' % build_link
        message += '%s\n\n' % self.link_to_patch(commit)
        if bugs:
            message += 'BUG=%s\n' % ','.join(bugs)
        message += 'TBR=%s\n' % author
        return message

    @staticmethod
    def link_to_patch(commit):
        return 'https://chromium.googlesource.com/chromium/src/+/' + commit

    def get_test_prefix_list(self, tests):
        test_prefix_list = {}
        lines_to_remove = {}

        for builder_name in self._release_builders():
            port_name = self._tool.builders.port_name_for_builder_name(builder_name)
            port = self._tool.port_factory.get(port_name)
            expectations = TestExpectations(port, include_overrides=True)
            for test in expectations.get_needs_rebaseline_failures():
                if test not in tests:
                    continue

                if test not in test_prefix_list:
                    lines_to_remove[test] = []
                    test_prefix_list[test] = {}
                lines_to_remove[test].append(builder_name)
                test_prefix_list[test][Build(builder_name)] = BASELINE_SUFFIX_LIST

        return test_prefix_list, lines_to_remove

    def _run_git_cl_command(self, options, command):
        subprocess_command = ['git', 'cl'] + command
        if options.verbose:
            subprocess_command.append('--verbose')
        if options.auth_refresh_token_json:
            subprocess_command.append('--auth-refresh-token-json')
            subprocess_command.append(options.auth_refresh_token_json)

        process = self._tool.executive.popen(subprocess_command, stdout=self._tool.executive.PIPE,
                                             stderr=self._tool.executive.STDOUT)
        last_output_time = time.time()

        # git cl sometimes completely hangs. Bail if we haven't gotten any output to stdout/stderr in a while.
        while process.poll() is None and time.time() < last_output_time + self.SECONDS_BEFORE_GIVING_UP:
            # FIXME: This doesn't make any sense. readline blocks, so all this code to
            # try and bail is useless. Instead, we should do the readline calls on a
            # subthread. Then the rest of this code would make sense.
            out = process.stdout.readline().rstrip('\n')
            if out:
                last_output_time = time.time()
                _log.info(out)

        if process.poll() is None:
            _log.error('Command hung: %s', subprocess_command)
            return False
        return True

    # FIXME: Move this somewhere more general.
    @staticmethod
    def tree_status():
        blink_tree_status_url = 'http://chromium-status.appspot.com/status'
        status = urllib2.urlopen(blink_tree_status_url).read().lower()
        if 'closed' in status or status == '0':
            return 'closed'
        elif 'open' in status or status == '1':
            return 'open'
        return 'unknown'

    def execute(self, options, args, tool):
        self._tool = tool
        if tool.git().executable_name == 'svn':
            _log.error('Auto rebaseline only works with a git checkout.')
            return

        if not options.dry_run and tool.git().has_working_directory_changes():
            _log.error('Cannot proceed with working directory changes. Clean working directory first.')
            return

        revision_data = self.bot_revision_data(tool.git())
        if not revision_data:
            return

        min_revision = int(min([item['revision'] for item in revision_data]))
        tests, revision, commit, author, bugs, _ = self.tests_to_rebaseline(
            tool, min_revision, print_revisions=options.verbose)

        if options.verbose:
            _log.info('Min revision across all bots is %s.', min_revision)
            for item in revision_data:
                _log.info('%s: r%s', item['builder'], item['revision'])

        if not tests:
            _log.debug('No tests to rebaseline.')
            return

        if self.tree_status() == 'closed':
            _log.info('Cannot proceed. Tree is closed.')
            return

        _log.info('Rebaselining %s for r%s by %s.', list(tests), revision, author)

        test_prefix_list, _ = self.get_test_prefix_list(tests)

        did_switch_branches = False
        did_finish = False
        old_branch_name_or_ref = ''
        rebaseline_branch_name = self.AUTO_REBASELINE_BRANCH_NAME
        try:
            # Save the current branch name and check out a clean branch for the patch.
            old_branch_name_or_ref = tool.git().current_branch_or_ref()
            if old_branch_name_or_ref == self.AUTO_REBASELINE_BRANCH_NAME:
                rebaseline_branch_name = self.AUTO_REBASELINE_ALT_BRANCH_NAME
            if not options.dry_run:
                tool.git().delete_branch(rebaseline_branch_name)
                tool.git().create_clean_branch(rebaseline_branch_name)
                did_switch_branches = True

            if test_prefix_list:
                self.rebaseline(options, test_prefix_list)

            if options.dry_run:
                return

            tool.git().commit_locally_with_message(
                self.commit_message(author, revision, commit, bugs))

            # FIXME: It would be nice if we could dcommit the patch without uploading, but still
            # go through all the precommit hooks. For rebaselines with lots of files, uploading
            # takes a long time and sometimes fails, but we don't want to commit if, e.g. the
            # tree is closed.
            did_finish = self._run_git_cl_command(options, ['upload', '-f'])

            if did_finish:
                # Uploading can take a very long time. Do another pull to make sure TestExpectations is up to date,
                # so the dcommit can go through.
                # FIXME: Log the pull and dcommit stdout/stderr to the log-server.
                tool.executive.run_command(['git', 'pull'])

                self._run_git_cl_command(options, ['land', '-f', '-v'])
        except OSError:
            traceback.print_exc(file=sys.stderr)
        finally:
            if did_switch_branches:
                if did_finish:
                    # Close the issue if dcommit failed.
                    issue_already_closed = tool.executive.run_command(
                        ['git', 'config', 'branch.%s.rietveldissue' % rebaseline_branch_name],
                        return_exit_code=True)
                    if not issue_already_closed:
                        self._run_git_cl_command(options, ['set_close'])

                tool.git().ensure_cleanly_tracking_remote_master()
                if old_branch_name_or_ref:
                    tool.git().checkout_branch(old_branch_name_or_ref)
                tool.git().delete_branch(rebaseline_branch_name)
