[darcs-users] Exporting darcs changes as patches

Alberto Bertogli albertito at blitiri.com.ar
Sun Aug 3 15:30:55 UTC 2008


I've accidentally commited some stuff into a darcs 2.0 repository, and
moving it to a darcs 1.0 one using regular darcs tools (push, send)
seems not to be possible (I know darcs warned me about this when
converting the repo, that's why I used the word "accidentally").

So I've resurrected an old script to export darcs' changes as regular
patches. Because it may be useful for other people, I've uploaded it to
http://blitiri.com.ar/p/other/darcs-export (and attached it, as a
special bonus).

For example, to export the last 4 patches you can (from inside a darcs
repository) use

  darcs changes --last=4 --xml-output | darcs-export list

to verify what you're going to export, and then

  darcs changes --last=4 --xml-output | darcs-export export /tmp

to export the four patches into four different nicely-named files inside
/tmp.

Thanks,
		Alberto

-------------- next part --------------
#!/usr/bin/python

# Simple script to export darcs' changes as regular patches
# Alberto Bertogli (albertito at blitiri.com.ar), 2008-08-03
#
# The latest version should be available at
# http://blitiri.com.ar/p/other/darcs-export

import sys
import os
from xml.sax import saxutils
from xml.sax import make_parser
from xml.sax.handler import feature_namespaces, ContentHandler

def run_darcs(*params):
	cmd = 'darcs ' + ' '.join(params)
	os.environ['DARCS_DONT_ESCAPE_8BIT'] = '1'
	inf, outf = os.popen4(cmd, 't')
	return outf

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]

		fd = open("%s/%.2d - %s.patch" % (path, order, name), 'w')
		out = run_darcs("diff", "-u", '--match "hash %s"' % self.hash)

		buf = out.read()
		while buf:
			fd.write(buf)
			buf = out.read()


class BuildPatchList(ContentHandler):
	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: darcs-export [xmlfile|-] [list|export destdir]"

Examples:
 $ darcs changes --last=4 --xml-output | darcs-export list
 $ darcs changes --last=4 --xml-output | darcs-export export /tmp
 	"""
	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"



More information about the darcs-users mailing list