#! /usr/bin/python # Basic instructions # # 1. Save patch email to file [patch.email] # # 2. Go to the svn directory to which you want to apply the patch. # # 3. Run "selinux-maint split patch.email". This will run vi on the # logmsg (pulled out of the email) to allow you to add anything (ack # messages). When you quit vi the current directory will have files # called "patch" and "logmsg". # # 4. Run "selinux-maint apply" (optionally with a strip level as # the last argument). This will do a dry run of applying the patch # showing the results and ask if you want to apply the patch. If you # say yes it will apply the patch and attempt to detect file adds (by # comparing svn status and the output of patch). If it finds adds it # will ask if you want to add each file. # # 5. Run "selinux-maint commit" to commit that patch with the log # message. # # 6. Repeat 4 and 5 as often as necessary for a set of patch emails. # # 7. Run "selinux-maint rev packagename" where packagename is # something like "libsepol". This will prompt for the new version # number (showing the current), update VERSION, add a Changelog entry # with the version and date, and vi the changelog for you to add # entries. # # 8. Run "selinux-maint commit" again to commit the revision change # (rev adds a simple log message - I just fixed this as my last # checkin had the wrong log message). import sys import subprocess import shutil import os import os.path import datetime dir = "/tmp/selinux-maint/" def usage(): print "selinux-maint [command] [options]" print "" print "commands:" print "\tsplit patch-email: split patch-email into a patch and log message" print "\tapply [patch-level]: apply the patch and logmsg with optional level" print "\tcommit username: commit the changes" print "\trev package: update the version number and changelog of package" print "\tmerge reva:revb source-branch: merge changes to the current branch" def create_tmpdir(): try: os.mkdir(dir) except OSError: if not os.path.isdir(dir): print "path %s exists and is not a directory" % dir sys.exit(1) def split_email(args): # Get an absolute path for the patch email since we are going to # change the working directory patch_path = os.path.abspath(args[0]) create_tmpdir() prevdir = os.getcwd() os.chdir(dir) infd = open(patch_path) outfd = open("info", "w") retcode = subprocess.call(["git-mailinfo", "msg", "patch"], stdin=infd, stdout=outfd) if retcode != 0: sys.exit(1) msgfd = open("logmsg", "w") retcode = subprocess.call(["cat", "info", "msg"], stdout=msgfd) msgfd.close() retcode = subprocess.call(["vi", "logmsg"]) shutil.copyfile("logmsg", prevdir + "/logmsg") shutil.copyfile("patch", prevdir + "/patch") def apply(args): if len(args) >= 1: patch_level = "-p%d" % int(args[0]) else: patch_level = "-p1" if len(args) == 2: patch_name = "../patch" patch_dir = args[1] else: patch_name = "patch" patch_dir = None print "Test applying patch:" if patch_dir: os.chdir(patch_dir) patchfd = open(patch_name) retcode = subprocess.call(["patch", patch_level, "--dry-run", "-l"], stdin=patchfd) resp = raw_input("apply [y/n]: ") if resp != "y": sys.exit(0) patchfd = open(patch_name) patch_output = subprocess.Popen(["patch", patch_level, "-l"], stdin=patchfd, stdout=subprocess.PIPE).communicate()[0] status_output = subprocess.Popen(["svn", "status"], stdout=subprocess.PIPE).communicate()[0] # Detect adds unknown_files = [] for status_line in status_output.split("\n"): try: status, fname = status_line.split() except ValueError: continue if status == "?": unknown_files.append(fname) added_files = [] for patch_line in patch_output.split("\n"): try: patched_fname = patch_line.split(" ")[2] except: continue if patched_fname in unknown_files: added_files.append(patched_fname) for fname in added_files: input = raw_input("add file %s [y/n]: " % fname) if input == "y": subprocess.call(["svn", "add", fname]) def commit(args): if len(args) == 1: retcode = subprocess.call(["svn", "commit", "--username", args[0], "-F", "logmsg"]) else: retcode = subprocess.call(["svn", "commit", "-F", "logmsg"]) def rev(args): if len(args) != 1: print "you must provide a package name" usage() sys.exit(1) package = args[0] ver_fd = open("%s/VERSION" % package, "r") cur = ver_fd.read() cur = cur.split("\n")[0] ver_fd.close() input = raw_input("new version [current is %s]: " % cur) new_fd = open("%s/VERSION.new" % package, "w") new_fd.write(input + "\n") new_fd.close() shutil.copyfile("%s/VERSION.new" % package, "%s/VERSION" % package) old_changelog = "%s/ChangeLog" % package new_changelog = "%s/ChangeLog.new" % package n = open(new_changelog, "w") entry = "%s %s\n" % (input, str(datetime.date.today())) n.write(entry) n.write("\t*\n\n") o = open(old_changelog) n.write(o.read()) n.close() o.close() subprocess.call(["vi", new_changelog]) shutil.copyfile(new_changelog, old_changelog) logmsg = open("logmsg", "w") logmsg.write("updated %s to version %s\n" % (package, input)) def merge(args): if len(args) != 2: print "you must provide a revision pair and source branch" usage() sys.exit(1) rev = args[0] branch = args[1] if branch == "trunk": url = "https://selinux.svn.sourceforge.net/svnroot/selinux/trunk" elif branch == "stable": url = "https://selinux.svn.sourceforge.net/svnroot/selinux/branches/stable/1_0" else: url = "https://selinux.svn.sourceforge.net/svnroot/selinux/branches/%s" % branch subprocess.call(["svn", "diff", "-r%s" % rev, url]) input = raw_input("apply these changes [y/n]? ") if input != "y": sys.exit(0) subprocess.call(["svn", "merge", "-r%s" % rev, url]) logmsg = open("logmsg", "w") logmsg.write("applied r%s from %s\n" % (rev, branch)) def main(): if len(sys.argv) < 2: usage() sys.exit(1) command = sys.argv[1] if command == "split": split_email(sys.argv[2:]) elif command == "apply": apply(sys.argv[2:]) elif command == "commit": commit(sys.argv[2:]) elif command == "rev": rev(sys.argv[2:]) elif command == "merge": merge(sys.argv[2:]) else: usage() main()