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, e: 118if e.retcode ==1: 119# This means that no settings were found. 120return True 121else: 122raise 123else: 124return False 125 126 127defremove_section_if_empty(section): 128"""If the specified configuration section is empty, delete it.""" 129 130try: 131 empty =is_section_empty(section, local=True) 132except CommandError: 133# Older versions of git do not support the --local option, so 134# if the first attempt fails, try without --local. 135try: 136 empty =is_section_empty(section, local=False) 137except CommandError: 138 sys.stderr.write( 139'\nINFO: If configuration section "%s.*" is empty, you might want ' 140'to delete it.\n\n' 141% (section,) 142) 143return 144 145if empty: 146 sys.stderr.write('...removing section "%s.*"\n'% (section,)) 147read_output(['git','config','--remove-section', section]) 148else: 149 sys.stderr.write( 150'\nINFO: Configuration section "%s.*" still has contents. ' 151'It will not be deleted.\n\n' 152% (section,) 153) 154 155 156defmigrate_config(strict=False, retain=False, overwrite=False): 157 old =Config('hooks') 158 new =Config('multimailhook') 159if not_check_old_config_exists(old): 160 sys.exit( 161'Your repository has no post-receive-email configuration. ' 162'Nothing to do.' 163) 164if not_check_new_config_clear(new): 165if overwrite: 166 sys.stderr.write('\nWARNING: Erasing the above values...\n\n') 167erase_values(new, NEW_NAMES) 168else: 169 sys.exit( 170'\nERROR: Refusing to overwrite existing values. Use the --overwrite\n' 171'option to continue anyway.' 172) 173 174 name ='showrev' 175if name in old: 176 msg ='git-multimail does not support "%s.%s"'% (old.section, name,) 177if strict: 178 sys.exit( 179'ERROR:%s.\n' 180'Please unset that value then try again, or run without --strict.' 181% (msg,) 182) 183else: 184 sys.stderr.write('\nWARNING:%s(ignoring).\n\n'% (msg,)) 185 186for name in['mailinglist','announcelist']: 187if name in old: 188 sys.stderr.write( 189'...copying "%s.%s" to "%s.%s"\n'% (old.section, name, new.section, name) 190) 191 new.set_recipients(name, old.get_recipients(name)) 192 193if strict: 194 sys.stderr.write( 195'...setting "%s.commitlist" to the empty string\n'% (new.section,) 196) 197 new.set_recipients('commitlist','') 198 sys.stderr.write( 199'...setting "%s.announceshortlog" to "true"\n'% (new.section,) 200) 201 new.set('announceshortlog','true') 202 203for name in['envelopesender','emailmaxlines','diffopts','scancommitforcc']: 204if name in old: 205 sys.stderr.write( 206'...copying "%s.%s" to "%s.%s"\n'% (old.section, name, new.section, name) 207) 208 new.set(name, old.get(name)) 209 210 name ='emailprefix' 211if name in old: 212 sys.stderr.write( 213'...copying "%s.%s" to "%s.%s"\n'% (old.section, name, new.section, name) 214) 215 new.set(name, old.get(name)) 216elif strict: 217 sys.stderr.write( 218'...setting "%s.%s" to "[SCM]" to preserve old subject lines\n' 219% (new.section, name) 220) 221 new.set(name,'[SCM]') 222 223if not retain: 224erase_values(old, OLD_NAMES) 225remove_section_if_empty(old.section) 226 227 sys.stderr.write(INFO) 228for name in NEW_NAMES: 229if name not in OLD_NAMES: 230 sys.stderr.write(' "%s.%s"\n'% (new.section, name,)) 231 sys.stderr.write('\n') 232 233 234defmain(args): 235 parser = optparse.OptionParser( 236 description=__doc__, 237 usage='%prog [OPTIONS]', 238) 239 240 parser.add_option( 241'--strict', action='store_true', default=False, 242help=( 243'Slavishly configure git-multimail as closely as possible to ' 244'the post-receive-email configuration. Default is to turn ' 245'on some new features that have no equivalent in post-receive-email.' 246), 247) 248 parser.add_option( 249'--retain', action='store_true', default=False, 250help=( 251'Retain the post-receive-email configuration values. ' 252'Default is to delete them after the new values are set.' 253), 254) 255 parser.add_option( 256'--overwrite', action='store_true', default=False, 257help=( 258'Overwrite any existing git-multimail configuration settings. ' 259'Default is to abort if such settings already exist.' 260), 261) 262 263(options, args) = parser.parse_args(args) 264 265if args: 266 parser.error('Unexpected arguments:%s'% (' '.join(args),)) 267 268migrate_config(strict=options.strict, retain=options.retain, overwrite=options.overwrite) 269 270 271main(sys.argv[1:])