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-rundon'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