blob: 06fec4e0d7fa6a5078d9295192040ada90a35ec9 [file] [log] [blame]
#! /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()