#!/usr/bin/env python3

#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""A command line utility to pull multiple change lists from Gerrit."""

from __future__ import print_function

import argparse
import collections
import itertools
import json
import multiprocessing
import os
import os.path
import re
import sys
import xml.dom.minidom

from gerrit import (
    create_url_opener_from_args, find_gerrit_name, query_change_lists, run
)
from subprocess import PIPE

try:
    # pylint: disable=redefined-builtin
    from __builtin__ import raw_input as input  # PY2
except ImportError:
    pass

try:
    from shlex import quote as _sh_quote  # PY3.3
except ImportError:
    # Shell language simple string pattern.  If a string matches this pattern,
    # it doesn't have to be quoted.
    _SHELL_SIMPLE_PATTERN = re.compile('^[a-zA-Z90-9_./-]+$')

    def _sh_quote(txt):
        """Quote a string if it contains special characters."""
        return txt if _SHELL_SIMPLE_PATTERN.match(txt) else json.dumps(txt)


if bytes is str:
    def write_bytes(data, file):  # PY2
        """Write bytes to a file."""
        # pylint: disable=redefined-builtin
        file.write(data)
else:
    def write_bytes(data, file):  # PY3
        """Write bytes to a file."""
        # pylint: disable=redefined-builtin
        file.buffer.write(data)


def _confirm(question, default, file=sys.stderr):
    """Prompt a yes/no question and convert the answer to a boolean value."""
    # pylint: disable=redefined-builtin
    answers = {'': default, 'y': True, 'yes': True, 'n': False, 'no': False}
    suffix = '[Y/n] ' if default else ' [y/N] '
    while True:
        file.write(question + suffix)
        file.flush()
        ans = answers.get(input().lower())
        if ans is not None:
            return ans


class ChangeList(object):
    """A ChangeList to be checked out."""
    # pylint: disable=too-few-public-methods,too-many-instance-attributes

    def __init__(self, project, fetch, commit_sha1, commit, change_list):
        """Initialize a ChangeList instance."""
        # pylint: disable=too-many-arguments

        self.project = project
        self.number = change_list['_number']

        self.fetch = fetch

        fetch_git = None
        for protocol in ('http', 'sso', 'rpc'):
            fetch_git = fetch.get(protocol)
            if fetch_git:
                break

        if not fetch_git:
            raise ValueError(
                'unknown fetch protocols: ' + str(list(fetch.keys())))

        self.fetch_url = fetch_git['url']
        self.fetch_ref = fetch_git['ref']

        self.commit_sha1 = commit_sha1
        self.commit = commit
        self.parents = commit['parents']

        self.change_list = change_list


    def is_merge(self):
        """Check whether this change list a merge commit."""
        return len(self.parents) > 1


def find_repo_top(curdir):
    """Find the top directory for this git-repo source tree."""
    olddir = None
    while curdir != olddir:
        if os.path.exists(os.path.join(curdir, '.repo')):
            return curdir
        olddir = curdir
        curdir = os.path.dirname(curdir)
    raise ValueError('.repo dir not found')


def build_project_name_dir_dict(manifest_name):
    """Build the mapping from Gerrit project name to source tree project
    directory path."""
    manifest_cmd = ['repo', 'manifest']
    if manifest_name:
        manifest_cmd.extend(['-m', manifest_name])
    raw_manifest_xml = run(manifest_cmd, stdout=PIPE, check=True).stdout

    manifest_xml = xml.dom.minidom.parseString(raw_manifest_xml)
    project_dirs = {}
    for project in manifest_xml.getElementsByTagName('project'):
        name = project.getAttribute('name')
        path = project.getAttribute('path')
        if path:
            project_dirs[name] = path
        else:
            project_dirs[name] = name

    return project_dirs


def group_and_sort_change_lists(change_lists):
    """Build a dict that maps projects to a list of topologically sorted change
    lists."""

    # Build a dict that map projects to dicts that map commits to changes.
    projects = collections.defaultdict(dict)
    for change_list in change_lists:
        commit_sha1 = None
        for commit_sha1, value in change_list['revisions'].items():
            fetch = value['fetch']
            commit = value['commit']

        if not commit_sha1:
            raise ValueError('bad revision')

        project = change_list['project']

        project_changes = projects[project]
        if commit_sha1 in project_changes:
            raise KeyError('repeated commit sha1 "{}" in project "{}"'.format(
                commit_sha1, project))

        project_changes[commit_sha1] = ChangeList(
            project, fetch, commit_sha1, commit, change_list)

    # Sort all change lists in a project in post ordering.
    def _sort_project_change_lists(changes):
        visited_changes = set()
        sorted_changes = []

        def _post_order_traverse(change):
            visited_changes.add(change)
            for parent in change.parents:
                parent_change = changes.get(parent['commit'])
                if parent_change and parent_change not in visited_changes:
                    _post_order_traverse(parent_change)
            sorted_changes.append(change)

        for change in sorted(changes.values(), key=lambda x: x.number):
            if change not in visited_changes:
                _post_order_traverse(change)

        return sorted_changes

    # Sort changes in each projects
    sorted_changes = []
    for project in sorted(projects.keys()):
        sorted_changes.append(_sort_project_change_lists(projects[project]))

    return sorted_changes


def _main_json(args):
    """Print the change lists in JSON format."""
    change_lists = _get_change_lists_from_args(args)
    json.dump(change_lists, sys.stdout, indent=4, separators=(', ', ': '))
    print()  # Print the end-of-line


# Git commands for merge commits
_MERGE_COMMANDS = {
    'merge': ['git', 'merge', '--no-edit'],
    'merge-ff-only': ['git', 'merge', '--no-edit', '--ff-only'],
    'merge-no-ff': ['git', 'merge', '--no-edit', '--no-ff'],
    'reset': ['git', 'reset', '--hard'],
    'checkout': ['git', 'checkout'],
}


# Git commands for non-merge commits
_PICK_COMMANDS = {
    'pick': ['git', 'cherry-pick', '--allow-empty'],
    'merge': ['git', 'merge', '--no-edit'],
    'merge-ff-only': ['git', 'merge', '--no-edit', '--ff-only'],
    'merge-no-ff': ['git', 'merge', '--no-edit', '--no-ff'],
    'reset': ['git', 'reset', '--hard'],
    'checkout': ['git', 'checkout'],
}


def build_pull_commands(change, branch_name, merge_opt, pick_opt):
    """Build command lines for each change.  The command lines will be passed
    to subprocess.run()."""

    cmds = []
    if branch_name is not None:
        cmds.append(['repo', 'start', branch_name])
    cmds.append(['git', 'fetch', change.fetch_url, change.fetch_ref])
    if change.is_merge():
        cmds.append(_MERGE_COMMANDS[merge_opt] + ['FETCH_HEAD'])
    else:
        cmds.append(_PICK_COMMANDS[pick_opt] + ['FETCH_HEAD'])
    return cmds


def _sh_quote_command(cmd):
    """Convert a command (an argument to subprocess.run()) to a shell command
    string."""
    return ' '.join(_sh_quote(x) for x in cmd)


def _sh_quote_commands(cmds):
    """Convert multiple commands (arguments to subprocess.run()) to shell
    command strings."""
    return ' && '.join(_sh_quote_command(cmd) for cmd in cmds)


def _main_bash(args):
    """Print the bash command to pull the change lists."""
    repo_top = find_repo_top(os.getcwd())
    project_dirs = build_project_name_dir_dict(args.manifest)
    branch_name = _get_local_branch_name_from_args(args)

    change_lists = _get_change_lists_from_args(args)
    change_list_groups = group_and_sort_change_lists(change_lists)

    print(_sh_quote_command(['pushd', repo_top]))
    for changes in change_list_groups:
        for change in changes:
            project_dir = project_dirs.get(change.project, change.project)
            cmds = []
            cmds.append(['pushd', project_dir])
            cmds.extend(build_pull_commands(
                change, branch_name, args.merge, args.pick))
            cmds.append(['popd'])
            print(_sh_quote_commands(cmds))
    print(_sh_quote_command(['popd']))


def _do_pull_change_lists_for_project(task):
    """Pick a list of changes (usually under a project directory)."""
    changes, task_opts = task

    branch_name = task_opts['branch_name']
    merge_opt = task_opts['merge_opt']
    pick_opt = task_opts['pick_opt']
    project_dirs = task_opts['project_dirs']
    repo_top = task_opts['repo_top']

    for i, change in enumerate(changes):
        try:
            cwd = project_dirs[change.project]
        except KeyError:
            err_msg = 'error: project "{}" cannot be found in manifest.xml\n'
            err_msg = err_msg.format(change.project).encode('utf-8')
            return (change, changes[i + 1:], [], err_msg)

        print(change.commit_sha1[0:10], i + 1, cwd)
        cmds = build_pull_commands(change, branch_name, merge_opt, pick_opt)
        for cmd in cmds:
            proc = run(cmd, cwd=os.path.join(repo_top, cwd), stderr=PIPE)
            if proc.returncode != 0:
                return (change, changes[i + 1:], cmd, proc.stderr)
    return None


def _print_pull_failures(failures, file=sys.stderr):
    """Print pull failures and tracebacks."""
    # pylint: disable=redefined-builtin

    separator = '=' * 78
    separator_sub = '-' * 78

    print(separator, file=file)
    for failed_change, skipped_changes, cmd, errors in failures:
        print('PROJECT:', failed_change.project, file=file)
        print('FAILED COMMIT:', failed_change.commit_sha1, file=file)
        for change in skipped_changes:
            print('PENDING COMMIT:', change.commit_sha1, file=file)
        print(separator_sub, file=sys.stderr)
        print('FAILED COMMAND:', _sh_quote_command(cmd), file=file)
        write_bytes(errors, file=sys.stderr)
        print(separator, file=sys.stderr)


def _main_pull(args):
    """Pull the change lists."""
    repo_top = find_repo_top(os.getcwd())
    project_dirs = build_project_name_dir_dict(args.manifest)
    branch_name = _get_local_branch_name_from_args(args)

    # Collect change lists
    change_lists = _get_change_lists_from_args(args)
    change_list_groups = group_and_sort_change_lists(change_lists)

    # Build the options list for tasks
    task_opts = {
        'branch_name': branch_name,
        'merge_opt': args.merge,
        'pick_opt': args.pick,
        'project_dirs': project_dirs,
        'repo_top': repo_top,
    }

    # Run the commands to pull the change lists
    if args.parallel <= 1:
        results = [_do_pull_change_lists_for_project((changes, task_opts))
                   for changes in change_list_groups]
    else:
        pool = multiprocessing.Pool(processes=args.parallel)
        results = pool.map(_do_pull_change_lists_for_project,
                           zip(change_list_groups, itertools.repeat(task_opts)))

    # Print failures and tracebacks
    failures = [result for result in results if result]
    if failures:
        _print_pull_failures(failures)
        sys.exit(1)


def _parse_args():
    """Parse command line options."""
    parser = argparse.ArgumentParser()

    parser.add_argument('command', choices=['pull', 'bash', 'json'],
                        help='Commands')

    parser.add_argument('query', help='Change list query string')
    parser.add_argument('-g', '--gerrit', help='Gerrit review URL')

    parser.add_argument('--gitcookies',
                        default=os.path.expanduser('~/.gitcookies'),
                        help='Gerrit cookie file')
    parser.add_argument('--manifest', help='Manifest')
    parser.add_argument('--limits', default=1000,
                        help='Max number of change lists')

    parser.add_argument('-m', '--merge',
                        choices=sorted(_MERGE_COMMANDS.keys()),
                        default='merge-ff-only',
                        help='Method to pull merge commits')

    parser.add_argument('-p', '--pick',
                        choices=sorted(_PICK_COMMANDS.keys()),
                        default='pick',
                        help='Method to pull merge commits')

    parser.add_argument('-b', '--branch',
                        help='Local branch name for `repo start`')

    parser.add_argument('-j', '--parallel', default=1, type=int,
                        help='Number of parallel running commands')

    return parser.parse_args()


def _get_change_lists_from_args(args):
    """Query the change lists by args."""
    url_opener = create_url_opener_from_args(args)
    return query_change_lists(url_opener, args.gerrit, args.query, args.limits)


def _get_local_branch_name_from_args(args):
    """Get the local branch name from args."""
    if not args.branch and not _confirm(
            'Do you want to continue without local branch name?', False):
        print('error: `-b` or `--branch` must be specified', file=sys.stderr)
        sys.exit(1)
    return args.branch


def main():
    """Main function"""
    args = _parse_args()

    if not args.gerrit:
        try:
            args.gerrit = find_gerrit_name()
        # pylint: disable=bare-except
        except:
            print('gerrit instance not found, use [-g GERRIT]')
            sys.exit(1)

    if args.command == 'json':
        _main_json(args)
    elif args.command == 'bash':
        _main_bash(args)
    elif args.command == 'pull':
        _main_pull(args)
    else:
        raise KeyError('unknown command')

if __name__ == '__main__':
    main()
