275 lines
7.8 KiB
Text
275 lines
7.8 KiB
Text
|
#! /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:
|
||
|
t, e, traceback = sys.exc_info()
|
||
|
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)
|
||
|
)
|
||
|
old_recipients = old.get_all(name, default=None)
|
||
|
old_recipients = ', '.join(o.strip() for o in old_recipients)
|
||
|
new.set_recipients(name, old_recipients)
|
||
|
|
||
|
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:])
|