Merge with crew.
authorBryan O'Sullivan <bos@serpentine.com>
Sat, 29 Sep 2007 20:55:36 -0700
changeset 5351 c8d6f8510bf4
parent 5338 f87685355c9c (current diff)
parent 5350 bd706eb8bc25 (diff)
child 5352 cc34be74eeec
Merge with crew.
--- a/contrib/darcs2hg.py	Wed Sep 26 01:58:45 2007 -0300
+++ b/contrib/darcs2hg.py	Sat Sep 29 20:55:36 2007 -0700
@@ -15,6 +15,7 @@
 import tempfile
 import xml.dom.minidom as xml_dom
 from time import strptime, mktime
+import re
 
 DARCS_REPO = None
 HG_REPO    = None
@@ -93,11 +94,50 @@
 def darcs_pull(hg_repo, darcs_repo, chash):
 	old_tip = darcs_tip(darcs_repo)
 	res     = cmd("darcs pull \"%s\" --all --match=\"hash %s\"" % (darcs_repo, chash), hg_repo)
+	if re.search('^We have conflicts in the following files:$', res, re.MULTILINE):
+		print "Trying to revert files to work around conflict..."
+		rev_res = cmd ("darcs revert --all", hg_repo)
+		print rev_res
 	print res
 	new_tip = darcs_tip(darcs_repo)
 	if not new_tip != old_tip + 1:
 		error("Darcs pull did not work as expected: " + res)
 
+def darcs_changes_summary(darcs_repo, chash):
+	"""Gets the changes from the darcs summary. This returns the chronological
+	list of changes as (change_type, args). Eg. ('add_file', 'foo.txt') or
+	('move', ['foo.txt','bar.txt'])."""
+	change = cmd("darcs changes --summary --xml-output --match=\"hash %s\"" % (chash), darcs_repo)
+	doc = xml_dom.parseString(change)
+	for patch_node in doc.childNodes[0].childNodes:
+		summary_nodes = filter(lambda n: n.nodeName == "summary" and n.nodeType == n.ELEMENT_NODE, patch_node.childNodes)
+		for summary_node in summary_nodes:
+			change_nodes = filter(lambda n: n.nodeType == n.ELEMENT_NODE, summary_node.childNodes)
+			if len(change_nodes) == 0:
+				name = filter(lambda n: n.nodeName == "name", patch_node.childNodes)
+				if not name:
+					error("Darcs patch has an empty summary node and no name: " + patch_node.toxml())
+				name = name[0].childNodes[0].data.strip()
+				(tag, sub_count) = re.subn('^TAG ', '', name, 1)
+				if sub_count != 1:
+					error("Darcs patch has an empty summary node but doesn't look like a tag: " + patch_node.toxml());
+			for change_node in change_nodes:
+				change = change_node.nodeName
+				if change == 'modify_file':
+					yield change, change_node.childNodes[0].data.strip()
+				elif change == 'add_file':
+					yield change, change_node.childNodes[0].data.strip()
+				elif change == 'remove_file':
+					yield change, change_node.childNodes[0].data.strip()
+				elif change == 'add_directory':
+					yield change, change_node.childNodes[0].data.strip()
+				elif change == 'remove_directory':
+					yield change, change_node.childNodes[0].data.strip()
+				elif change == 'move':
+					yield change, (change_node.getAttribute('from'), change_node.getAttribute('to'))
+				else:
+					error('Problem parsing summary xml: Unexpected element: ' + change_node.toxml())
+
 # ------------------------------------------------------------------------------
 #
 # Mercurial interface
@@ -127,6 +167,36 @@
 	tip = tip.split("\n")[0].split(":")[1].strip()
 	return int(tip)
 
+def hg_rename( hg_repo, from_file, to_file ):
+	cmd("hg rename --after \"%s\" \"%s\"" % (from_file, to_file), hg_repo);
+	
+def hg_tag ( hg_repo, text, author, date ):
+	old_tip = hg_tip(hg_repo)
+	res = cmd("hg tag -u \"%s\" -d \"%s 0\" \"%s\""	 % (author, date, text), hg_repo)
+	new_tip = hg_tip(hg_repo)
+	if not new_tip == old_tip + 1:
+		error("Mercurial tag did not work as expected: " + res)
+
+def hg_handle_change( hg_repo, author, date, change, arg ):
+	"""Processes a change event as output by darcs_changes_summary. These
+	consist of file move/rename/add/delete commands."""
+	if change == 'modify_file':
+		pass
+	elif change == 'add_file':
+		pass
+	elif change =='remove_file':
+		pass
+	elif change == 'add_directory':
+		pass
+	elif change == 'remove_directory':
+		pass
+	elif change == 'move':
+		hg_rename(hg_repo, arg[0], arg[1])
+	elif change == 'tag':
+		hg_tag(hg_repo, arg, author, date)
+	else:
+		error('Unknown change type ' + change + ': ' + arg)
+
 # ------------------------------------------------------------------------------
 #
 # Main
@@ -167,11 +237,13 @@
 			print "(skipping)"
 		else:
 			text = summary + "\n" + description
-			darcs_pull(hg_repo, darcs_repo, chash)
 			# The commit hash has a date like 20021020201112
 			# --------------------------------YYYYMMDDHHMMSS
 			date = chash.split("-")[0]
 			epoch = int(mktime(strptime(date, '%Y%m%d%H%M%S')))
+			darcs_pull(hg_repo, darcs_repo, chash)
+			for change, arg in darcs_changes_summary(darcs_repo, chash):
+				hg_handle_change(hg_repo, author, epoch, change, arg)
 			hg_commit(hg_repo, text, author, epoch)
 		change_number += 1
 	print "Darcs repository (_darcs) was not deleted. You can keep or remove it."