contrib/darcs2hg.py
author Nils Decker <mercurial@ndecker.de>
Sun, 09 Jul 2006 21:41:00 -0700
changeset 2585 5ec2dded1bda
parent 2352 61909dfb316d
child 2586 bb63d29ce03d
child 2587 fe3e87358b47
permissions -rwxr-xr-x
darcs2hg.py: use darcs patch hash as patch identifier The use of the patch name is dangerous when duplicate names exist. In case of a duplicate name the second patch and all its dependancies are merged into a single mercurial patch. The patch identifier (hash) is always unique.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2349
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
     1
#!/usr/bin/env python
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
     2
# Encoding: iso-8859-1
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
     3
# vim: tw=80 ts=4 sw=4 noet
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
     4
# -----------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
     5
# Project   : Basic Darcs to Mercurial conversion script
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
     6
# -----------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
     7
# Author    : Sebastien Pierre <sebastien@xprima.com>
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
     8
# Creation  : 24-May-2006
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
     9
# Last mod  : 26-May-2006
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    10
# History   :
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    11
#             26-May-2006 - Updated
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    12
#             24-May-2006 - First implementation
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    13
# -----------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    14
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    15
import os, sys
2352
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    16
import tempfile
2349
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    17
import xml.dom.minidom as xml_dom
2352
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    18
from time import strptime, mktime
2349
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    19
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    20
DARCS_REPO = None
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    21
HG_REPO    = None
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    22
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    23
USAGE = """\
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    24
%s DARCSREPO HGREPO
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    25
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    26
    Converts the given Darcs repository to a new Mercurial repository. The given
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    27
    HGREPO must not exist, as it will be created and filled up (this will avoid
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    28
    overwriting valuable data.
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    29
2352
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    30
""" % (os.path.basename(sys.argv[0]))
2349
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    31
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    32
# ------------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    33
#
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    34
# Utilities
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    35
#
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    36
# ------------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    37
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    38
def cmd(text, path=None):
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    39
	"""Executes a command, in the given directory (if any), and returns the
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    40
	command result as a string."""
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    41
	cwd = None
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    42
	if path:
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    43
		path = os.path.abspath(path)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    44
		cwd  = os.getcwd()
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    45
		os.chdir(path)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    46
	print text
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    47
	res = os.popen(text).read()
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    48
	if path:
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    49
		os.chdir(cwd)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    50
	return res
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    51
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    52
def writefile(path, data):
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    53
	"""Writes the given data into the given file."""
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    54
	f = file(path, "w") ; f.write(data)  ; f.close()
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    55
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    56
# ------------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    57
#
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    58
# Darcs interface
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    59
#
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    60
# ------------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    61
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    62
def darcs_changes(darcsRepo):
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    63
	"""Gets the changes list from the given darcs repository. This returns the
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    64
	chronological list of changes as (change name, change summary)."""
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    65
	changes    = cmd("darcs changes --reverse --xml-output", darcsRepo)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    66
	doc        = xml_dom.parseString(changes)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    67
	res        = []
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    68
	for patch_node in doc.childNodes[0].childNodes:
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    69
		name = filter(lambda n:n.nodeName == "name", patch_node.childNodes)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    70
		comm = filter(lambda n:n.nodeName == "comment", patch_node.childNodes)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    71
		if not name:continue
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    72
		else: name = name[0].childNodes[0].data
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    73
		if not comm: comm = ""
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    74
		else: comm = comm[0].childNodes[0].data
2352
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    75
		author = patch_node.getAttribute("author")
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    76
		date = patch_node.getAttribute("date")
2585
5ec2dded1bda darcs2hg.py: use darcs patch hash as patch identifier
Nils Decker <mercurial@ndecker.de>
parents: 2352
diff changeset
    77
        hash = patch_node.getAttribute("hash")
5ec2dded1bda darcs2hg.py: use darcs patch hash as patch identifier
Nils Decker <mercurial@ndecker.de>
parents: 2352
diff changeset
    78
        yield hash, author, date, name, comm
2349
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    79
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    80
def darcs_pull(hg_repo, darcs_repo, change):
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    81
	cmd("darcs pull '%s' --all --patches='%s'" % (darcs_repo, change), hg_repo)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    82
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    83
# ------------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    84
#
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    85
# Mercurial interface
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    86
#
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    87
# ------------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    88
2352
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    89
def hg_commit( hg_repo, text, author, date ):
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    90
	fd, tmpfile = tempfile.mkstemp(prefix="darcs2hg_")
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    91
	writefile(tmpfile, text)
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    92
	cmd("hg add -X _darcs", hg_repo)
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    93
	cmd("hg remove -X _darcs --after", hg_repo)
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    94
	cmd("hg commit -l %s -u '%s' -d '%s 0'"  % (tmpfile, author, date), hg_repo)
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
    95
	os.unlink(tmpfile)
2349
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    96
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    97
# ------------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    98
#
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
    99
# Main
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   100
#
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   101
# ------------------------------------------------------------------------------
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   102
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   103
if __name__ == "__main__":
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   104
	args = sys.argv[1:]
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   105
	# We parse the arguments
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   106
	if len(args)   == 2:
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   107
		darcs_repo = os.path.abspath(args[0])
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   108
		hg_repo    = os.path.abspath(args[1])
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   109
	else:
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   110
		print USAGE
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   111
		sys.exit(-1)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   112
	# Initializes the target repo
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   113
	if not os.path.isdir(darcs_repo + "/_darcs"):
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   114
		print "No darcs directory found at: " + darc_repo
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   115
		sys.exit(-1)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   116
	if not os.path.isdir(hg_repo):
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   117
		os.mkdir(hg_repo)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   118
	else:
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   119
		print "Given HG repository must not exist. It will be created"
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   120
		sys.exit(-1)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   121
	cmd("hg init '%s'" % (hg_repo))
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   122
	cmd("darcs initialize", hg_repo)
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   123
	# Get the changes from the Darcs repository
2585
5ec2dded1bda darcs2hg.py: use darcs patch hash as patch identifier
Nils Decker <mercurial@ndecker.de>
parents: 2352
diff changeset
   124
	for hash, author, date, summary, description in darcs_changes(darcs_repo):
2349
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   125
		text = summary + "\n" + description
2585
5ec2dded1bda darcs2hg.py: use darcs patch hash as patch identifier
Nils Decker <mercurial@ndecker.de>
parents: 2352
diff changeset
   126
		darcs_pull(hg_repo, darcs_repo, hash)
2352
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
   127
		epoch = int(mktime(strptime(date, '%Y%m%d%H%M%S')))
61909dfb316d various fixes to darcs conversion script
TK Soh <teekaysoh@yahoo.com>
parents: 2349
diff changeset
   128
		hg_commit(hg_repo, text, author, epoch)
2349
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   129
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   130
# EOF
88c881bda888 darcs2hg.py: import darcs project into mercurial
Sébastien Pierre <sebastien@xprima.com>
parents:
diff changeset
   131