#!/usr/bin/env python # # Scan a mbox of CVS commit Mailinglist and display the # patches (including the patch --dry-run messages), # convert CVS users to real names, create patchscripts # to apply to the mtd git repository .... # # (C) 2005 Thomas Gleixner # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # import os import sys import getopt import difflib import email import mailbox import string from Tkinter import * # The script should be invoked from mtd cvs root mtdusers = "scripts/mtdusers.txt" # Should be a commandline argument mtdrepo = "~/work/git-repos/mtd-2.6" userhash = {} # Make this configurable !! mysign = ["Thomas Gleixner", "tglx@linutronix.de"] # Fix me: read this from the treewalk/patchin xml config includepaths = ["drivers", "fs", "include"] excludepatterns = ["jffs3","ecos"] # Print the usage information def usage(res): print "USAGE:" print "creatediffs.py <-m mtdusers> mailbox mailnr" print "-m mtdusers supply a list of mtd users (default:scripts/mtdusers.txt)" print "mailbox containing MTD CVS Mailinglist" # print "targetdir to put the diffs and logs" sys.exit(res) # Helper to run a shell command def doShellCommand(cmd, data=None): (inp, out, err) = os.popen3(cmd) if data: inp.write(data) inp.close() res = out.read() out.close() res = res + "\n" + err.read() err.close() return res # The commit class class commitView: def __init__(self, root, mbox): self.root = root fd = open(mbox,"r") mbx = mailbox.PortableUnixMailbox(fd, email.message_from_file) #mbx = mailbox.Maildir(mbox, email.message_from_file) self.entries= [] msg = mbx.next() while msg: self.entries.append(msg) msg = mbx.next() self.entries.reverse() fd.close() f1 = Frame(root) f1.pack() f2 = Frame(root) f2.pack() f3 = Frame(root) f3.pack() f4 = Frame(root) f4.pack() f5 = Frame(root) f5.pack() self.subject = StringVar() self.user = StringVar() self.realuser = StringVar() self.date = StringVar() Button(f1, text="Back", command=self.back).grid(row=0,column=0) Button(f1, text="Next", command=self.next).grid(row=0,column=1) Button(f1, text="Apply", command=self.apply).grid(row=0,column=2) self.signAuthor = IntVar() Checkbutton(f1, text="Add Author Signed-off", variable=self.signAuthor).grid(row=0,column=3) self.signOwn = IntVar() Checkbutton(f1, text="Add own Signed-off", variable=self.signOwn).grid(row=0,column=4) Label(f2, text="What").grid(row=0, column=0, sticky=W) Label(f2, textvariable = self.subject, justify=LEFT, relief=SUNKEN).grid(row=0, column=1, sticky=W) Label(f2, text="User").grid(row=1, column=0, sticky=W) Label(f2, textvariable = self.user, justify=LEFT, relief=SUNKEN).grid(row=1, column=1, sticky=W) Label(f2, text="Real user").grid(row=1, column=2, sticky=W) Label(f2, textvariable = self.realuser, justify=LEFT, relief=SUNKEN).grid(row=1, column=3, sticky=W) Label(f2, text="Date").grid(row=2, column=0, sticky=W) Label(f2, textvariable = self.date, justify=LEFT, relief=SUNKEN).grid(row=2, column=1, sticky=W) self.log = Text(f3) self.patch = Text(f4) self.patchres = Text(f5) self.curnr = -1 self.next() def getMsg(self): self.log.delete(1.0,END) self.patch.delete(1.0,END) self.patchres.delete(1.0,END) print self.curnr msg = self.entries[self.curnr] subj = msg.get("Subject") print subj files = subj.split(" ", 1) self.patchpath = files[0].split("/",1)[1] self.files = files[1] print self.patchpath for p in excludepatterns: if subj.find(p) > 0: return 1 valid = 0 for p in includepaths: if self.patchpath.startswith(p): valid = 1 break if valid == 0: return 1 self.subject.set(subj) usr = msg.get("From") self.user.set(usr) if usr.find("<") > 0: usr = usr.split("<")[1][:-1] print usr self.usr = userhash.get(usr.split("@")[0],"???") self.realuser.set("%s %s" %(self.usr[0],self.usr[1])) self.cdate = msg.get("Date") self.date.set(self.cdate) body = msg.get_payload().splitlines() while len(body): line = body.pop(0).strip() if line.startswith("Log Message:"): break self.logmsg = "" while len(body): line = body.pop(0) if line.startswith("Index:"): break self.logmsg = self.logmsg + line + "\n" self.log.insert(END, self.logmsg) self.log.pack() self.patchmsg = "" while len(body): self.patchmsg = self.patchmsg + \ body.pop(0).replace("Makefile.common", "Makefile") + "\n" self.patch.insert(END, self.patchmsg) self.patch.pack() # Try to apply the patch and display the results cmd = "patch -d %s/%s -p0 -f --verbose --dry-run" %(mtdrepo,self.patchpath) print cmd self.pres = doShellCommand(cmd, self.patchmsg) self.patchres.insert(END, self.pres) self.patchres.pack() return 0 def apply(self): fd = open("%s/patchfromcvs.sh" %(mtdrepo), "w") files = self.files.strip() while len(files) > 0: try: fname, files = files.strip().split(",", 1) frev1, files = files.strip().split(",", 1) files = files.strip() if files.find(" ") > 0: frev2, files = files.strip().split(" ", 1) else: frev2 = files files = "" except: break if frev1 == "NONE": fd.write("pushd %s\n" %(os.getcwd())) fd.write("cvs up -p -r%s %s/%s >%s/%s/%s\n" %( frev2 ,self.patchpath, fname, mtdrepo, self.patchpath, fname)) fd.write("popd\n") fd.write("cg-add %s/%s\n" %(self.patchpath, fname)) elif frev2 == "NONE": fd.write("cg-rm %s/%s\n" %(self.patchpath, fname)) else: fd.write("pushd %s\n" %(os.getcwd())) fd.write("cvs diff -u -r%s -r%s %s/%s >%s/cvspatch\n" %( frev1, frev2, self.patchpath, fname, mtdrepo)) fd.write("popd\n") fd.write("patch -p0 \n" %(self.usr[0], self.usr[1])) if self.signOwn.get() == 1: fd.write("Signed-off-by: %s <%s>\n" %(mysign[0], mysign[1])) fd.close() self.next() def next(self): if self.curnr == len(self.entries) - 1: return self.curnr = self.curnr + 1 while self.getMsg() > 0: self.curnr = self.curnr + 1 def back(self): if self.curnr == 0: return self.curnr = self.curnr - 1 while self.getMsg() > 0: self.curnr = self.curnr - 1 # Here we go # Parse the commandline try: (options, arguments) = getopt.getopt(sys.argv[1:],'m:') except getopt.GetoptError, ex: print print "ERROR:" print ex.msg usage(1) for option, value in options: if option == "-m": mtdusers = value elif option == '-h': usage(0) if len(arguments) != 1: usage(1) # Get filenames mbox = arguments[0] # Read the user list fd = open(mtdusers,"r") lines = fd.readlines() fd.close() for line in lines: if line.startswith("#"): continue if len(line) > 0: usr,name,mail=line.strip().split(":") userhash[usr] = [name,mail] root = Tk() viewer = commitView(root, mbox) root.mainloop()