Created
August 25, 2011 10:21
-
-
Save jezdez/1170386 to your computer and use it in GitHub Desktop.
A helper script to apply patches from Django's trac
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
Obviously this is only useful if you have to deal with Django's | |
Trac a lot. | |
Mostly stolen from Jacob Kaplan-Moss, but improved by Jannis Leidel | |
and Aymeric Augustin. | |
Reads a config file at ~/.djpatchrc, e.g.: | |
[djpatch] | |
username = django | |
password = guitar | |
""" | |
import os | |
import sys | |
import argparse | |
import xmlrpclib | |
import subprocess | |
import ConfigParser | |
import urlparse | |
# Turn off help, so we print all options in response to -h | |
conf_parser = argparse.ArgumentParser(add_help=False) | |
conf_parser.add_argument("-c", "--conf", | |
metavar="FILE", help="Specify config file", | |
default=os.path.expanduser('~/.djpatchrc')) | |
args, remaining_argv = conf_parser.parse_known_args() | |
defaults = { | |
"patchlevel": -1, # -1 = autodetect | |
"download_only": False, | |
"url": "https://code.djangoproject.com/login/xmlrpc", | |
} | |
if args.conf: | |
if not os.path.exists(args.conf): | |
print "Couldn't find config file %s" % args.conf | |
raise | |
config = ConfigParser.SafeConfigParser() | |
config.read([args.conf]) | |
try: | |
items = config.items("djpatch") | |
defaults.update(dict(items)) | |
except ConfigParser.NoSectionError, e: | |
print "Error while loading config file %s: %s" % (args.conf, e) | |
parser = argparse.ArgumentParser( | |
# Inherit options from config_parser | |
parents=[conf_parser], | |
# Don't mess with format of description | |
formatter_class=argparse.RawDescriptionHelpFormatter, | |
) | |
parser.set_defaults(**defaults) | |
parser.add_argument("-d", | |
dest="download_only", action="store_true", | |
help="Only download the patch file") | |
parser.add_argument("-p", | |
dest="patchlevel", type=int, metavar="NUM", | |
help="Strip NUM leading components from file names") | |
parser.add_argument("-U", "--username", | |
dest="username", type=str, help="Trac username") | |
parser.add_argument("-P", "--password", | |
dest="password", nargs=1, type=str, help="Trac password") | |
parser.add_argument("--url", | |
dest="url", type=str, help="Trac XMLRPC URL") | |
parser.add_argument("ticket", | |
nargs=1, type=int, help="Ticket ID", metavar="TICKET") | |
args = parser.parse_args(remaining_argv) | |
if not args.username or not args.password: | |
raise SystemExit('No username or password given.') | |
credentials = ("%s:%s@" % (args.username, args.password)) | |
url = list(urlparse.urlsplit(args.url)) | |
url[1] = credentials + url[1] | |
url_with_credentials = urlparse.urlunsplit(url) | |
s = xmlrpclib.Server(url_with_credentials) | |
attachments = s.ticket.listAttachments(args.ticket[0]) | |
attachments.sort(key=lambda rec: rec[3]) | |
name = attachments[-1][0] | |
patch = s.ticket.getAttachment(args.ticket[0], name) | |
if args.patchlevel == -1: | |
if "\n--- a/" in patch.data and "\n+++ b/" in patch.data: | |
args.patchlevel = 1 | |
else: | |
args.patchlevel = 0 | |
if args.download_only: | |
with open(name, 'w') as p: | |
p.write(patch.data) | |
print u"Saved '%s'" % name | |
else: | |
cmd = ["git", "apply", "-p%s" % str(args.patchlevel), "-"] | |
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=sys.stdout) | |
proc.communicate(patch.data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment