#!/usr/bin/env python3

from __future__ import print_function

import argparse
import generate_amalgamation
import hashlib
import os
import string
import subprocess
import sys


class UnstagedFiles(Exception):
    pass


class UnknownHash(Exception):
    pass


class IncorrectType(Exception):
    pass


class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'


def _print_command(cmd):
    """Print the command to be executed to the console.

    Use a different color so that it can be easily seen amongst the output
    commands.
    """
    if (isinstance(cmd, list)):
        cmd = ' '.join(cmd)
    print('{}{}{}'.format(bcolors.OKBLUE, cmd, bcolors.ENDC))


class ManifestEntry(object):
    """Represents a single entry in a SQLite manifest."""

    def __init__(self, entry_type, items):
        if not len(entry_type) == 1:
            raise IncorrectType(entry_type)
        self.entry_type = entry_type
        self.items = items

    def get_hash_type(self):
        """Return the type of hash used for this entry."""
        last_item = self.items[-1]
        if not all(c in string.hexdigits for c in last_item):
            print(
                '"{}" doesn\'t appear to be a hash.'.format(last_item),
                file=sys.stderr)
            raise UnknownHash()
        elif len(last_item) == 40:
            return 'sha1'
        elif len(last_item) == 64:
            return 'sha3'
        else:
            raise UnknownHash('Incorrect length {} for {}'.format(
                len(last_item), last_item))

    @staticmethod
    def calc_hash(data, method):
        """Return the string sha1 or sha3 hash digest for the given data."""
        if method == 'sha3':
            h = hashlib.sha3_256()
        elif method == 'sha1':
            h = hashlib.sha1()
        else:
            assert False
        h.update(data)
        return h.hexdigest()

    @staticmethod
    def calc_file_hash(fname, method):
        """Return the string sha1 or sha3 hash digest for the given file."""
        with open(fname, 'rb') as input_file:
            return ManifestEntry.calc_hash(input_file.read(), method)

    def update_file_hash(self):
        """Calculates a new file hash for this entry."""
        self.items[1] = ManifestEntry.calc_file_hash(self.items[0],
                                                     self.get_hash_type())

    def __str__(self):
        return '{} {}'.format(self.entry_type, ' '.join(self.items))


class Manifest(object):
    """A deserialized SQLite manifest."""

    def __init__(self):
        self.entries = []

    def find_file_entry(self, fname):
        """Given a file path return the entry. Returns None if none found."""
        for entry in self.entries:
            if entry.entry_type == 'F' and entry.items[0] == fname:
                return entry
        return None


class ManifestSerializer(object):
    """De/serialize SQLite manifests."""

    @staticmethod
    def read_stream(input_stream):
        """Deserialize a manifest from an input stream and return a Manifest
        object."""
        _manifest = Manifest()
        for line in input_stream.readlines():
            items = line.split()
            if not items:
                continue
            _manifest.entries.append(ManifestEntry(items[0], items[1:]))
        return _manifest

    @staticmethod
    def read_file(fname):
        """Deserialize a manifest file and return a Manifest object."""
        with open(fname) as input_stream:
            return ManifestSerializer.read_stream(input_stream)

    @staticmethod
    def write_stream(manifest, output_stream):
        """Serialize the given manifest to the given stream."""
        for entry in manifest.entries:
            print(str(entry), file=output_stream)

    @staticmethod
    def write_file(manifest, fname):
        """Serialize the given manifest to the specified file."""
        with open(fname, 'w') as output_stream:
            ManifestSerializer.write_stream(manifest, output_stream)


class Git(object):
    @staticmethod
    def _get_status():
        changes = []
        for line in subprocess.check_output(['git', 'status',
                                             '--porcelain']).splitlines():
            changes.append(line.decode('utf-8'))
        return changes

    @staticmethod
    def get_staged_changes():
        changes = []
        for line in Git._get_status():
            entry = line[0:2]
            if entry == 'M ':
                changes.append(line.split()[1])
        return changes

    @staticmethod
    def get_unstaged_changes():
        changes = []
        for line in Git._get_status():
            entry = line[0:2]
            if entry == ' M':
                changes.append(line.split()[1])
        return changes

    @staticmethod
    def get_unmerged_changes():
        changes = []
        for line in Git._get_status():
            entry = line[0:2]
            if entry == 'UU':
                changes.append(line.split()[1])
        return changes


class CherryPicker(object):
    """Class to cherry pick commits in a SQLite Git repository."""

    # The binary file extenions for files committed to the SQLite repository.
    # This is used as a simple way of detecting files that cannot (simply) be
    # resolved in a merge conflict. This script will automatically ignore
    # all conflicted files with any of these extensions. If, in the future, new
    # binary types are added then a conflict will arise during cherry-pick and
    # the user will need to resolve it.
    binary_extensions = (
        '.data',
        '.db',
        '.ico',
        '.jpg',
        '.png',
    )

    def __init__(self):
        self._print_cmds = True
        self._update_amangamation = True

    def _take_head_version(self, file_path):
        subprocess.call(
            'git show HEAD:{} > {}'.format(file_path, file_path), shell=True)
        subprocess.call('git add {}'.format(file_path), shell=True)

    @staticmethod
    def _is_binary_file(file_path):
        _, file_extension = os.path.splitext(file_path)
        return file_extension in CherryPicker.binary_extensions

    @staticmethod
    def _append_cherry_pick_comments(comments):
        # TODO(cmumford): Figure out how to append comments on cherry picks
        pass

    def _cherry_pick_git_commit(self, commit_id):
        """Cherry-pick a given Git commit into the current branch."""
        cmd = ['git', 'cherry-pick', '-x', commit_id]
        if self._print_cmds:
            _print_command(' '.join(cmd))
        returncode = subprocess.call(cmd)
        # The manifest and manifest.uuid contain Fossil hashes. Restore to
        # HEAD version and update only when all conflicts have been resolved.
        comments = None
        self._take_head_version('manifest')
        self._take_head_version('manifest.uuid')
        for unmerged_file in Git.get_unmerged_changes():
            if CherryPicker._is_binary_file(unmerged_file):
                print('{} is a binary file, keeping branch version.'.format(
                    unmerged_file))
                self._take_head_version(unmerged_file)
                if not comments:
                    comments = [
                        'Cherry-pick notes', '=============================='
                    ]
                comments.append(
                    '{} is binary file (with conflict). Keeping branch version'
                    .format(unmerged_file))
        if comments:
            CherryPicker._append_cherry_pick_comments(comments)
        self.continue_cherry_pick()

    @staticmethod
    def _is_git_commit_id(commit_id):
        return len(commit_id) == 40

    def _find_git_commit_id(self, fossil_commit_id):
        cmd = [
            'git', '--no-pager', 'log', '--color=never', '--all',
            '--pretty=format:%H', '--grep={}'.format(fossil_commit_id),
        ]
        if self._print_cmds:
            _print_command(' '.join(cmd))
        for line in subprocess.check_output(cmd).splitlines():
            return line.decode('utf-8')
        # Not found.
        assert False

    def cherry_pick(self, commit_id):
        """Cherry-pick a given commit into the current branch.

        Can cherry-pick a given Git or a Fossil commit.
        """
        if not CherryPicker._is_git_commit_id(commit_id):
            commit_id = self._find_git_commit_id(commit_id)
        self._cherry_pick_git_commit(commit_id)

    def _generate_amalgamation(self):
        for config_name in ['chromium', 'dev']:
            generate_amalgamation.make_aggregate(config_name)
            generate_amalgamation.extract_sqlite_api(config_name)

    def _add_amalgamation(self):
        os.chdir(generate_amalgamation._SQLITE_SRC_DIR)
        for config_name in ['chromium', 'dev']:
            cmd = [
                'git', 'add',
                generate_amalgamation.get_amalgamation_dir(config_name)
            ]
            if self._print_cmds:
                _print_command(' '.join(cmd))
            subprocess.check_call(cmd)

    def _update_manifests(self):
        """Update the SQLite's Fossil manifest files.

        This isn't strictly necessary as the manifest isn't used during
        any build, and manifest.uuid is the Fossil commit ID (which
        has no meaning in a Git repo). However, keeping these updated
        helps make it more obvious that a commit originated in
        Git and not Fossil.
        """
        manifest = ManifestSerializer.read_file('manifest')
        files_not_in_manifest = ('manifest', 'manifest.uuid')
        for fname in Git.get_staged_changes():
            if fname in files_not_in_manifest:
                continue
            entry = manifest.find_file_entry(fname)
            if not entry:
                print(
                    'Cannot find manifest entry for "{}"'.format(fname),
                    file=sys.stderr)
                sys.exit(1)
            manifest.find_file_entry(fname).update_file_hash()
        ManifestSerializer.write_file(manifest, 'manifest')
        cmd = ['git', 'add', 'manifest']
        if self._print_cmds:
            _print_command(' '.join(cmd))
        subprocess.check_call(cmd)
        # manifest.uuid contains the hash from the Fossil repository which
        # doesn't make sense in a Git branch. Just write all zeros.
        with open('manifest.uuid', 'w') as output_file:
            print('0' * 64, file=output_file)
        cmd = ['git', 'add', 'manifest.uuid']
        if self._print_cmds:
            _print_command(' '.join(cmd))
        subprocess.check_call(cmd)

    def continue_cherry_pick(self):
        if Git.get_unstaged_changes() or Git.get_unmerged_changes():
            raise UnstagedFiles()
        self._update_manifests()
        if self._update_amangamation:
            self._generate_amalgamation()
            self._add_amalgamation()
        cmd = ['git', 'cherry-pick', '--continue']
        if self._print_cmds:
            _print_command(' '.join(cmd))
        subprocess.check_call(cmd)


if __name__ == '__main__':
    desc = 'A script for cherry-picking commits from the SQLite repo.'
    parser = argparse.ArgumentParser(description=desc)
    parser.add_argument(
        'commit', nargs='*', help='The commit ids to cherry pick (in order)')
    parser.add_argument(
        '--continue',
        dest='cont',
        action='store_true',
        help='Continue the cherry-pick once conflicts have been resolved')
    namespace = parser.parse_args()
    cherry_picker = CherryPicker()
    if namespace.cont:
        try:
            cherry_picker.continue_cherry_pick()
            sys.exit(0)
        except UnstagedFiles:
            print(
                'There are still unstaged files to resolve before continuing.')
            sys.exit(1)
    num_picked = 0
    for commit_id in namespace.commit:
        try:
            cherry_picker.cherry_pick(commit_id)
            num_picked += 1
        except UnstagedFiles:
            print(
                '\nThis cherry-pick contains conflicts. Please resolve them ')
            print('(e.g git mergetool) and rerun this script '
                  '`sqlite_cherry_picker.py --continue`')
            print('or `git cherry-pick --abort`.')
            if commit_id != namespace.commit[-1]:
                msg = (
                    'NOTE: You have only successfully cherry-picked {} out of '
                    '{} commits.')
                print(msg.format(num_picked, len(namespace.commit)))
            sys.exit(1)
