On 09/17/2010 10:28 AM, Adam Young wrote:
Here’s a little ditty I wrote to et patches in the format we use for the FreeIPA mailing list:
Attached is my python script to do something similar. It keeps all the patches I've generated in a patch directory, numbers them, sends them as a properly formatted email (optional).
-- John Dennis <jden...@redhat.com> Looking to carve out IT costs? www.redhat.com/carveoutcosts/
#!/usr/bin/python import getopt import os import errno import sys import subprocess import re import smtplib import email from cStringIO import StringIO from email.generator import Generator from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase #------------------------------------------------------------------------------- prog_name = sys.argv[0] config = { 'patch_dir' : '/home/jdennis/freeipa-patches', 'smtp_server' : 'smtp.corp.redhat.com', 'email_from_addr' : 'John Dennis <jden...@redhat.com>', #'email_to_addrs' : ['jden...@redhat.com'], 'email_to_addrs' : ['freeipa-devel@redhat.com'], 'start_number_basename' : 'StartNumber', 'default_number' : 2, 'number' : None, 'send' : False, 'run_format' : True, 'dry_run' : False, 'verbose' : False, } signature = ''' -- John Dennis <jden...@redhat.com> Looking to carve out IT costs? www.redhat.com/carveoutcosts/ ''' #------------------------------------------------------------------------------- class CommandError(Exception): def __init__(self, cmd, msg): self.cmd = cmd self.msg = msg def __str__(self): return "COMMAND ERROR: cmd='%s'\n%s" % (self.cmd, self.msg) def run_cmd(cmd): if config['dry_run']: print >>sys.stdout, cmd return p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) status = os.waitpid(p.pid, 0)[1] msg = p.stdout.read().strip() if (status != 0): err_msg = p.stderr.read().strip() raise CommandError(cmd, err_msg) print >>sys.stdout, msg def next_number(): try: f = open(config['start_number_filepath'], 'r') number = int(f.read()) f.close() if config['verbose']: print "number %d read from '%s'" % (number, config['start_number_filepath']) except Exception, e: if e.errno == errno.ENOENT: number = config['default_number'] if config['verbose']: print "'%s' does not exist yet, using default %d" % (config['start_number_filepath'], number) else: raise if not config['dry_run']: f = open(config['start_number_filepath'], 'w') f.write('%d\n' % (number + 1)) f.close() return number def find_patch(number): filename_re = re.compile('^0*%d-(.*).patch$' % number) for filename in os.listdir(config['patch_dir']): match = filename_re.search(filename) if match: patch_filename = filename return os.path.join(config['patch_dir'], patch_filename) return None def send_patch(filename): f = open(filename) patch = email.email.message_from_file(f) f.close() patch_name = os.path.basename(filename) # Get the entire raw message, including headers if False: f = StringIO() g = Generator(f, mangle_from_=False, maxheaderlen=0) g.flatten(patch) raw_msg = f.getvalue() else: f = open(filename) raw_msg = f.read() f.close() payload = patch.get_payload() i = payload.find('\n---\n') if i == -1: commit_msg = '' else: commit_msg = payload[:i] msg = MIMEMultipart() mime_part = MIMEText(commit_msg + '\n' + signature) msg.attach(mime_part) mime_part = MIMEBase('text', 'x-patch', name=patch_name) mime_part.set_charset('utf-8') mime_part.add_header('Content-Disposition', 'attachment', filename=patch_name) mime_part.set_payload(raw_msg) email.encoders.encode_base64(mime_part) msg.attach(mime_part) msg['Subject'] = patch['subject'] msg['From'] = config['email_from_addr'] msg['To'] = ', '.join(config['email_to_addrs']) if config['dry_run']: print msg else: s = smtplib.SMTP(config['smtp_server']) s.sendmail(config['email_from_addr'], config['email_to_addrs'], msg.as_string()) s.quit() def usage(): ''' Print command help. ''' print '''\ -h --help print help -n --number nn use this number for patch instead of next sequence number -s --send send patch using git send-email -N --dry-run don't execute, just report what would have been done -F --no-format don't run git format-patch Examples: Run command at minutes after the hour %(prog_name)s -n 10 ''' % {'prog_name' : prog_name, } #------------------------------------------------------------------------------- def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'hn:sNF', ['help', 'number=', 'send', 'dry-run', 'no-format']) except getopt.GetoptError, err: print >>sys.stderr, str(err) usage() sys.exit(2) for o, a in opts: if o in ('-h', '--help'): usage() sys.exit() elif o in ('-n', '--number'): config['number'] = int(a) elif o in ('-s', '--send'): config['send'] = True elif o in ('-N', '--dry-run'): config['dry_run'] = True elif o in ('-F', '--no-format'): config['run_format'] = False else: assert False, 'unhandled option' config['start_number_filepath'] = os.path.join(config['patch_dir'], config['start_number_basename']) try: if config['number'] is None: number = next_number() else: number = config['number'] if config['run_format']: if len(args) > 0: extra_args = ' '.join(args) else: extra_args = '-1' cmd = 'git format-patch --start-number %d -n -o %s' % (number, config['patch_dir']) cmd += ' ' + extra_args run_cmd(cmd) if config['send']: patch_file = find_patch(number) if patch_file is None: print >>sys.stderr, "cannot find patch file for patch %d" % (number) else: send_patch(patch_file) except Exception, e: print >>sys.stderr, e #------------------------------------------------------------------------------- if __name__ == '__main__': main()
_______________________________________________ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel