| #! /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:]) |