#! /usr/bin/env python

"""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:])
