#! /usr/bin/env python2

"""Migrate a post-receive-email configuration to be usable with git_multimail.py.

See README.migrate-from-post-receive-email for more information.

"""

import sys
import optparse

from git_multimail import CommandError
from git_multimail import Config
from git_multimail import read_output


OLD_NAMES = [
    'mailinglist',
    'announcelist',
    'envelopesender',
    'emailprefix',
    'showrev',
    'emailmaxlines',
    'diffopts',
    'scancommitforcc',
    ]

NEW_NAMES = [
    'environment',
    'reponame',
    'mailinglist',
    'refchangelist',
    'commitlist',
    'announcelist',
    'announceshortlog',
    'envelopesender',
    'administrator',
    'emailprefix',
    'emailmaxlines',
    'diffopts',
    'emaildomain',
    'scancommitforcc',
    ]


INFO = """\

SUCCESS!

Your post-receive-email configuration has been converted to
git-multimail format.  Please see README and
README.migrate-from-post-receive-email to learn about other
git-multimail configuration possibilities.

For example, git-multimail has the following new options with no
equivalent in post-receive-email.  You might want to read about them
to see if they would be useful in your situation:

"""


def _check_old_config_exists(old):
    """Check that at least one old configuration value is set."""

    for name in OLD_NAMES:
        if name in old:
            return True

    return False


def _check_new_config_clear(new):
    """Check that none of the new configuration names are set."""

    retval = True
    for name in NEW_NAMES:
        if name in new:
            if retval:
                sys.stderr.write('INFO: The following configuration values already exist:\n\n')
            sys.stderr.write('    "%s.%s"\n' % (new.section, name))
            retval = False

    return retval


def erase_values(config, names):
    for name in names:
        if name in config:
            try:
                sys.stderr.write('...unsetting "%s.%s"\n' % (config.section, name))
                config.unset_all(name)
            except CommandError:
                sys.stderr.write(
                    '\nWARNING: could not unset "%s.%s".  '
                    'Perhaps it is not set at the --local level?\n\n'
                    % (config.section, name)
                    )


def is_section_empty(section, local):
    """Return True iff the specified configuration section is empty.

    Iff local is True, use the --local option when invoking 'git
    config'."""

    if local:
        local_option = ['--local']
    else:
        local_option = []

    try:
        read_output(
            ['git', 'config']
            + local_option
            + ['--get-regexp', '^%s\.' % (section,)]
            )
    except CommandError, e:
        if e.retcode == 1:
            # This means that no settings were found.
            return True
        else:
            raise
    else:
        return False


def remove_section_if_empty(section):
    """If the specified configuration section is empty, delete it."""

    try:
        empty = is_section_empty(section, local=True)
    except CommandError:
        # Older versions of git do not support the --local option, so
        # if the first attempt fails, try without --local.
        try:
            empty = is_section_empty(section, local=False)
        except CommandError:
            sys.stderr.write(
                '\nINFO: If configuration section "%s.*" is empty, you might want '
                'to delete it.\n\n'
                % (section,)
                )
            return

    if empty:
        sys.stderr.write('...removing section "%s.*"\n' % (section,))
        read_output(['git', 'config', '--remove-section', section])
    else:
        sys.stderr.write(
            '\nINFO: Configuration section "%s.*" still has contents.  '
            'It will not be deleted.\n\n'
            % (section,)
            )


def migrate_config(strict=False, retain=False, overwrite=False):
    old = Config('hooks')
    new = Config('multimailhook')
    if not _check_old_config_exists(old):
        sys.exit(
            'Your repository has no post-receive-email configuration.  '
            'Nothing to do.'
            )
    if not _check_new_config_clear(new):
        if overwrite:
            sys.stderr.write('\nWARNING: Erasing the above values...\n\n')
            erase_values(new, NEW_NAMES)
        else:
            sys.exit(
                '\nERROR: Refusing to overwrite existing values.  Use the --overwrite\n'
                'option to continue anyway.'
                )

    name = 'showrev'
    if name in old:
        msg = 'git-multimail does not support "%s.%s"' % (old.section, name,)
        if strict:
            sys.exit(
                'ERROR: %s.\n'
                'Please unset that value then try again, or run without --strict.'
                % (msg,)
                )
        else:
            sys.stderr.write('\nWARNING: %s (ignoring).\n\n' % (msg,))

    for name in ['mailinglist', 'announcelist']:
        if name in old:
            sys.stderr.write(
                '...copying "%s.%s" to "%s.%s"\n' % (old.section, name, new.section, name)
                )
            new.set_recipients(name, old.get_recipients(name))

    if strict:
        sys.stderr.write(
            '...setting "%s.commitlist" to the empty string\n' % (new.section,)
            )
        new.set_recipients('commitlist', '')
        sys.stderr.write(
            '...setting "%s.announceshortlog" to "true"\n' % (new.section,)
            )
        new.set('announceshortlog', 'true')

    for name in ['envelopesender', 'emailmaxlines', 'diffopts', 'scancommitforcc']:
        if name in old:
            sys.stderr.write(
                '...copying "%s.%s" to "%s.%s"\n' % (old.section, name, new.section, name)
                )
            new.set(name, old.get(name))

    name = 'emailprefix'
    if name in old:
        sys.stderr.write(
            '...copying "%s.%s" to "%s.%s"\n' % (old.section, name, new.section, name)
            )
        new.set(name, old.get(name))
    elif strict:
        sys.stderr.write(
            '...setting "%s.%s" to "[SCM]" to preserve old subject lines\n'
            % (new.section, name)
            )
        new.set(name, '[SCM]')

    if not retain:
        erase_values(old, OLD_NAMES)
        remove_section_if_empty(old.section)

    sys.stderr.write(INFO)
    for name in NEW_NAMES:
        if name not in OLD_NAMES:
            sys.stderr.write('    "%s.%s"\n' % (new.section, name,))
    sys.stderr.write('\n')


def main(args):
    parser = optparse.OptionParser(
        description=__doc__,
        usage='%prog [OPTIONS]',
        )

    parser.add_option(
        '--strict', action='store_true', default=False,
        help=(
            'Slavishly configure git-multimail as closely as possible to '
            'the post-receive-email configuration.  Default is to turn '
            'on some new features that have no equivalent in post-receive-email.'
            ),
        )
    parser.add_option(
        '--retain', action='store_true', default=False,
        help=(
            'Retain the post-receive-email configuration values.  '
            'Default is to delete them after the new values are set.'
            ),
        )
    parser.add_option(
        '--overwrite', action='store_true', default=False,
        help=(
            'Overwrite any existing git-multimail configuration settings.  '
            'Default is to abort if such settings already exist.'
            ),
        )

    (options, args) = parser.parse_args(args)

    if args:
        parser.error('Unexpected arguments: %s' % (' '.join(args),))

    migrate_config(strict=options.strict, retain=options.retain, overwrite=options.overwrite)


main(sys.argv[1:])
