#!/usr/bin/python import sys import os from xml.sax import saxutils from xml.sax import make_parser from xml.sax.handler import feature_namespaces class Patch: "Represents a single patch/record" def __init__(self): self.hash = '' self.author = '' self.date = '' self.local_date = '' self.name = '' self.comment = '' def tostr(self): s = "%s\n\tAuthor: %s\n\tDate: %s\n\tHash: %s\n" % \ (self.name, self.author, self.date, self.hash) return s def export(self, order, path): # '/'s are not allowed in filenames name = self.name.replace('/', '-') # avoid 'name..patch' if name[-1] == '.': name = name[:-1] file = "%s/%.2d - %s.patch" % (path, order, name) cmd = 'darcs diff -u --match "hash %s" > "%s"' % \ (self.hash, file) if os.system(cmd): print "Command failed: '%s'" % cmd class BuildPatchList(saxutils.DefaultHandler): def __init__(self): self.db = {} self.list = [] self.cur_hash = '' self.cur_elem = None self.cur_val = '' def startElement(self, name, attrs): if name == 'patch': p = Patch() p.author = attrs.get('author', None) p.date = attrs.get('date', None) p.local_date = attrs.get('local_date', None) p.hash = attrs.get('hash') self.db[p.hash] = p self.current = p.hash self.list.append(p.hash) elif name == 'name': self.db[self.current].name = '' self.cur_elem = 'name' elif name == 'comment': self.db[self.current].comment = '' self.cur_elem = 'name' else: self.cur_elem = None def characters(self, s): if not self.cur_elem: return self.cur_val += s def endElement(self, name): if name == 'name': self.db[self.current].name = self.cur_val elif name == 'comment': self.db[self.current].current = self.cur_val self.cur_elem = None self.cur_val = '' # main if len(sys.argv) < 3: print "Use: exporter [xmlfile|-] [list|export destdir]" print print "Examples:" print " # darcs changes --xml-output | exporter - export /tmp" print " # darcs changes --xml-output | exporter - list" sys.exit(1) if sys.argv[1] == '-': file = sys.stdin else: file = sys.argv[1] parser = make_parser() parser.setFeature(feature_namespaces, 0) handler = BuildPatchList() parser.setContentHandler(handler) parser.parse(file) # reverse the list so the oldest is the first, and the newest is the last handler.list.reverse() # we now have two main structures: handler.db is the hash table of Patches, # indexed by their hash, and handler.list is the ordered list of hashes. if sys.argv[2] == 'list': c = 1 for h in handler.list: print "%.2d:" % c, handler.db[h].tostr() c += 1 elif sys.argv[2] == 'export': if len(sys.argv) < 4: print "Destination directory missing" sys.exit(1) c = 1 for h in handler.list: p = handler.db[h] print "%.2d: %s" % (c, p.name) p.export(c, sys.argv[3]) c += 1 else: print "Unknown parameter"