1#! /usr/bin/env python 2 3"""Migrate a post-receive-email configuration to be usable with git_multimail.py. 4 5See README.migrate-from-post-receive-email for more information. 6 7""" 8 9import sys 10import optparse 11 12from git_multimail import CommandError 13from git_multimail import Config 14from git_multimail import read_output 15 16 17OLD_NAMES = [ 18'mailinglist', 19'announcelist', 20'envelopesender', 21'emailprefix', 22'showrev', 23'emailmaxlines', 24'diffopts', 25'scancommitforcc', 26] 27 28NEW_NAMES = [ 29'environment', 30'reponame', 31'mailinglist', 32'refchangelist', 33'commitlist', 34'announcelist', 35'announceshortlog', 36'envelopesender', 37'administrator', 38'emailprefix', 39'emailmaxlines', 40'diffopts', 41'emaildomain', 42'scancommitforcc', 43] 44 45 46INFO ="""\ 47 48SUCCESS! 49 50Your post-receive-email configuration has been converted to 51git-multimail format. Please see README and 52README.migrate-from-post-receive-email to learn about other 53git-multimail configuration possibilities. 54 55For example, git-multimail has the following new options with no 56equivalent in post-receive-email. You might want to read about them 57to see if they would be useful in your situation: 58 59""" 60 61 62def_check_old_config_exists(old): 63"""Check that at least one old configuration value is set.""" 64 65for name in OLD_NAMES: 66if name in old: 67return True 68 69return False 70 71 72def_check_new_config_clear(new): 73"""Check that none of the new configuration names are set.""" 74 75 retval =True 76for name in NEW_NAMES: 77if name in new: 78if retval: 79 sys.stderr.write('INFO: The following configuration values already exist:\n\n') 80 sys.stderr.write(' "%s.%s"\n'% (new.section, name)) 81 retval =False 82 83return retval 84 85 86deferase_values(config, names): 87for name in names: 88if name in config: 89try: 90 sys.stderr.write('...unsetting "%s.%s"\n'% (config.section, name)) 91 config.unset_all(name) 92except CommandError: 93 sys.stderr.write( 94'\nWARNING: could not unset "%s.%s". ' 95'Perhaps it is not set at the --local level?\n\n' 96% (config.section, name) 97) 98 99 100defis_section_empty(section, local): 101"""Return True iff the specified configuration section is empty. 102 103 Iff local is True, use the --local option when invoking 'git 104 config'.""" 105 106if local: 107 local_option = ['--local'] 108else: 109 local_option = [] 110 111try: 112read_output( 113['git','config'] + 114 local_option + 115['--get-regexp','^%s\.'% (section,)] 116) 117except CommandError: 118 t, e, traceback = sys.exc_info() 119if e.retcode ==1: 120# This means that no settings were found. 121return True 122else: 123raise 124else: 125return False 126 127 128defremove_section_if_empty(section): 129"""If the specified configuration section is empty, delete it.""" 130 131try: 132 empty =is_section_empty(section, local=True) 133except CommandError: 134# Older versions of git do not support the --local option, so 135# if the first attempt fails, try without --local. 136try: 137 empty =is_section_empty(section, local=False) 138except CommandError: 139 sys.stderr.write( 140'\nINFO: If configuration section "%s.*" is empty, you might want ' 141'to delete it.\n\n' 142% (section,) 143) 144return 145 146if empty: 147 sys.stderr.write('...removing section "%s.*"\n'% (section,)) 148read_output(['git','config','--remove-section', section]) 149else: 150 sys.stderr.write( 151'\nINFO: Configuration section "%s.*" still has contents. ' 152'It will not be deleted.\n\n' 153% (section,) 154) 155 156 157defmigrate_config(strict=False, retain=False, overwrite=False): 158 old =Config('hooks') 159 new =Config('multimailhook') 160if not_check_old_config_exists(old): 161 sys.exit( 162'Your repository has no post-receive-email configuration. ' 163'Nothing to do.' 164) 165if not_check_new_config_clear(new): 166if overwrite: 167 sys.stderr.write('\nWARNING: Erasing the above values...\n\n') 168erase_values(new, NEW_NAMES) 169else: 170 sys.exit( 171'\nERROR: Refusing to overwrite existing values. Use the --overwrite\n' 172'option to continue anyway.' 173) 174 175 name ='showrev' 176if name in old: 177 msg ='git-multimail does not support "%s.%s"'% (old.section, name,) 178if strict: 179 sys.exit( 180'ERROR:%s.\n' 181'Please unset that value then try again, or run without --strict.' 182% (msg,) 183) 184else: 185 sys.stderr.write('\nWARNING:%s(ignoring).\n\n'% (msg,)) 186 187for name in['mailinglist','announcelist']: 188if name in old: 189 sys.stderr.write( 190'...copying "%s.%s" to "%s.%s"\n'% (old.section, name, new.section, name) 191) 192 old_recipients = old.get_all(name, default=None) 193 old_recipients =', '.join(o.strip()for o in old_recipients) 194 new.set_recipients(name, old_recipients) 195 196if strict: 197 sys.stderr.write( 198'...setting "%s.commitlist" to the empty string\n'% (new.section,) 199) 200 new.set_recipients('commitlist','') 201 sys.stderr.write( 202'...setting "%s.announceshortlog" to "true"\n'% (new.section,) 203) 204 new.set('announceshortlog','true') 205 206for name in['envelopesender','emailmaxlines','diffopts','scancommitforcc']: 207if name in old: 208 sys.stderr.write( 209'...copying "%s.%s" to "%s.%s"\n'% (old.section, name, new.section, name) 210) 211 new.set(name, old.get(name)) 212 213 name ='emailprefix' 214if name in old: 215 sys.stderr.write( 216'...copying "%s.%s" to "%s.%s"\n'% (old.section, name, new.section, name) 217) 218 new.set(name, old.get(name)) 219elif strict: 220 sys.stderr.write( 221'...setting "%s.%s" to "[SCM]" to preserve old subject lines\n' 222% (new.section, name) 223) 224 new.set(name,'[SCM]') 225 226if not retain: 227erase_values(old, OLD_NAMES) 228remove_section_if_empty(old.section) 229 230 sys.stderr.write(INFO) 231for name in NEW_NAMES: 232if name not in OLD_NAMES: 233 sys.stderr.write(' "%s.%s"\n'% (new.section, name,)) 234 sys.stderr.write('\n') 235 236 237defmain(args): 238 parser = optparse.OptionParser( 239 description=__doc__, 240 usage='%prog [OPTIONS]', 241) 242 243 parser.add_option( 244'--strict', action='store_true', default=False, 245help=( 246'Slavishly configure git-multimail as closely as possible to ' 247'the post-receive-email configuration. Default is to turn ' 248'on some new features that have no equivalent in post-receive-email.' 249), 250) 251 parser.add_option( 252'--retain', action='store_true', default=False, 253help=( 254'Retain the post-receive-email configuration values. ' 255'Default is to delete them after the new values are set.' 256), 257) 258 parser.add_option( 259'--overwrite', action='store_true', default=False, 260help=( 261'Overwrite any existing git-multimail configuration settings. ' 262'Default is to abort if such settings already exist.' 263), 264) 265 266(options, args) = parser.parse_args(args) 267 268if args: 269 parser.error('Unexpected arguments:%s'% (' '.join(args),)) 270 271migrate_config(strict=options.strict, retain=options.retain, overwrite=options.overwrite) 272 273 274main(sys.argv[1:])