bc501f69fc
Add git-multimail, a tool for generating notification emails for pushes to a Git repository. It is largely plug-in compatible with post-receive-email, and is proposed to eventually replace that script. The advantages of git-multimail relative to post-receive-email are described in README.migrate-from-post-receive-email. git-multimail is organized in a directory contrib/hooks/multimail. The directory contains: * git_multimail.py -- a Python module that can generate notification emails for pushes to a Git repository. The file can be used directly as a post-receive script (configured via git config settings), or it can be imported as a Python module and configured via arbitrary Python code. * README -- user-level documentation for configuring and using git-multimail. * post-receive -- an example of building a post-receive script that imports git_multimail.py as a Python module, with an example of how to change the email templates. * README.migrate-from-post-receive-email -- documentation targeted at current users of post-receive-email, explaining the differences and how to migrate a post-receive-email configuration to git-multimail. * migrate-mailhook-config -- a script that can migrate a user's post-receive-email configuration options to the equivalent git-multimail options. * README.Git -- a short explanation of the relationship between git-multimail and the rest of the Git project, plus the exact date and revision when this version was taken from the upstream project. All but the last file are taken verbatim from the upstream git-multimail project. git-multimail is originally derived from post-receive-email and also incorporates suggestions from the mailing list as well as patches by the people listed below. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Contributions-by: Matthieu Moy <Matthieu.Moy@imag.fr> Contributions-by: Ramkumar Ramachandra <artagnon@gmail.com> Contributions-by: Chris Hiestand <chrishiestand@gmail.com> Contributions-by: Michiel Holtkamp <git@elfstone.nl> Contributions-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
270 lines
7.6 KiB
Python
Executable File
270 lines
7.6 KiB
Python
Executable File
#! /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',
|
|
]
|
|
|
|
NEW_NAMES = [
|
|
'environment',
|
|
'reponame',
|
|
'mailinglist',
|
|
'refchangelist',
|
|
'commitlist',
|
|
'announcelist',
|
|
'announceshortlog',
|
|
'envelopesender',
|
|
'administrator',
|
|
'emailprefix',
|
|
'emailmaxlines',
|
|
'diffopts',
|
|
'emaildomain',
|
|
]
|
|
|
|
|
|
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 old.has_key(name):
|
|
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 new.has_key(name):
|
|
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 config.has_key(name):
|
|
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 old.has_key(name):
|
|
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 old.has_key(name):
|
|
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']:
|
|
if old.has_key(name):
|
|
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 old.has_key(name):
|
|
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:])
|