##// END OF EJS Templates
darcs2hg: pause and resume support, date extraction from commit hash, does not break on empty commits
Sébastien Pierre -
r2587:fe3e8735 default
parent child Browse files
Show More
@@ -4,12 +4,11 b''
4 # -----------------------------------------------------------------------------
4 # -----------------------------------------------------------------------------
5 # Project : Basic Darcs to Mercurial conversion script
5 # Project : Basic Darcs to Mercurial conversion script
6 # -----------------------------------------------------------------------------
6 # -----------------------------------------------------------------------------
7 # Author : Sebastien Pierre <sebastien@xprima.com>
7 # Authors : Sebastien Pierre <sebastien@xprima.com>
8 # TK Soh <teekaysoh@gmail.com>
9 # -----------------------------------------------------------------------------
8 # Creation : 24-May-2006
10 # Creation : 24-May-2006
9 # Last mod : 26-May-2006
11 # Last mod : 05-Jun-2006
10 # History :
11 # 26-May-2006 - Updated
12 # 24-May-2006 - First implementation
13 # -----------------------------------------------------------------------------
12 # -----------------------------------------------------------------------------
14
13
15 import os, sys
14 import os, sys
@@ -21,12 +20,14 b' DARCS_REPO = None'
21 HG_REPO = None
20 HG_REPO = None
22
21
23 USAGE = """\
22 USAGE = """\
24 %s DARCSREPO HGREPO
23 %s DARCSREPO HGREPO [SKIP]
25
24
26 Converts the given Darcs repository to a new Mercurial repository. The given
25 Converts the given Darcs repository to a new Mercurial repository. The given
27 HGREPO must not exist, as it will be created and filled up (this will avoid
26 HGREPO must not exist, as it will be created and filled up (this will avoid
28 overwriting valuable data.
27 overwriting valuable data.
29
28
29 In case an error occurs within the process, you can resume the process by
30 giving the last successfuly applied change number.
30 """ % (os.path.basename(sys.argv[0]))
31 """ % (os.path.basename(sys.argv[0]))
31
32
32 # ------------------------------------------------------------------------------
33 # ------------------------------------------------------------------------------
@@ -35,7 +36,7 b' USAGE = """\\'
35 #
36 #
36 # ------------------------------------------------------------------------------
37 # ------------------------------------------------------------------------------
37
38
38 def cmd(text, path=None):
39 def cmd(text, path=None, silent=False):
39 """Executes a command, in the given directory (if any), and returns the
40 """Executes a command, in the given directory (if any), and returns the
40 command result as a string."""
41 command result as a string."""
41 cwd = None
42 cwd = None
@@ -43,7 +44,7 b' def cmd(text, path=None):'
43 path = os.path.abspath(path)
44 path = os.path.abspath(path)
44 cwd = os.getcwd()
45 cwd = os.getcwd()
45 os.chdir(path)
46 os.chdir(path)
46 print text
47 if not silent: print "> ", text
47 res = os.popen(text).read()
48 res = os.popen(text).read()
48 if path:
49 if path:
49 os.chdir(cwd)
50 os.chdir(cwd)
@@ -53,6 +54,14 b' def writefile(path, data):'
53 """Writes the given data into the given file."""
54 """Writes the given data into the given file."""
54 f = file(path, "w") ; f.write(data) ; f.close()
55 f = file(path, "w") ; f.write(data) ; f.close()
55
56
57 def error( *args ):
58 sys.stderr.write("ERROR: ")
59 for a in args: sys.stderr.write(str(a))
60 sys.stderr.write("\n")
61 sys.stderr.write("You can make manual fixes if necessary and then resume by"
62 " giving the last changeset number")
63 sys.exit(-1)
64
56 # ------------------------------------------------------------------------------
65 # ------------------------------------------------------------------------------
57 #
66 #
58 # Darcs interface
67 # Darcs interface
@@ -64,7 +73,6 b' def darcs_changes(darcsRepo):'
64 chronological list of changes as (change name, change summary)."""
73 chronological list of changes as (change name, change summary)."""
65 changes = cmd("darcs changes --reverse --xml-output", darcsRepo)
74 changes = cmd("darcs changes --reverse --xml-output", darcsRepo)
66 doc = xml_dom.parseString(changes)
75 doc = xml_dom.parseString(changes)
67 res = []
68 for patch_node in doc.childNodes[0].childNodes:
76 for patch_node in doc.childNodes[0].childNodes:
69 name = filter(lambda n:n.nodeName == "name", patch_node.childNodes)
77 name = filter(lambda n:n.nodeName == "name", patch_node.childNodes)
70 comm = filter(lambda n:n.nodeName == "comment", patch_node.childNodes)
78 comm = filter(lambda n:n.nodeName == "comment", patch_node.childNodes)
@@ -74,11 +82,21 b' def darcs_changes(darcsRepo):'
74 else: comm = comm[0].childNodes[0].data
82 else: comm = comm[0].childNodes[0].data
75 author = patch_node.getAttribute("author")
83 author = patch_node.getAttribute("author")
76 date = patch_node.getAttribute("date")
84 date = patch_node.getAttribute("date")
77 hash = patch_node.getAttribute("hash")
85 chash = os.path.splitext(patch_node.getAttribute("hash"))[0]
78 yield hash, author, date, name, comm
86 yield author, date, name, chash, comm
87
88 def darcs_tip(darcs_repo):
89 changes = cmd("darcs changes",darcs_repo,silent=True)
90 changes = filter(lambda l:l.strip().startswith("* "), changes.split("\n"))
91 return len(changes)
79
92
80 def darcs_pull(hg_repo, darcs_repo, change):
93 def darcs_pull(hg_repo, darcs_repo, chash):
81 cmd("darcs pull '%s' --all --patches='%s'" % (darcs_repo, change), hg_repo)
94 old_tip = darcs_tip(darcs_repo)
95 res = cmd("darcs pull '%s' --all --match='hash %s'" % (darcs_repo, chash), hg_repo)
96 print res
97 new_tip = darcs_tip(darcs_repo)
98 if not new_tip != old_tip + 1:
99 error("Darcs pull did not work as expected: " + res)
82
100
83 # ------------------------------------------------------------------------------
101 # ------------------------------------------------------------------------------
84 #
102 #
@@ -89,10 +107,24 b' def darcs_pull(hg_repo, darcs_repo, chan'
89 def hg_commit( hg_repo, text, author, date ):
107 def hg_commit( hg_repo, text, author, date ):
90 fd, tmpfile = tempfile.mkstemp(prefix="darcs2hg_")
108 fd, tmpfile = tempfile.mkstemp(prefix="darcs2hg_")
91 writefile(tmpfile, text)
109 writefile(tmpfile, text)
110 old_tip = hg_tip(hg_repo)
92 cmd("hg add -X _darcs", hg_repo)
111 cmd("hg add -X _darcs", hg_repo)
93 cmd("hg remove -X _darcs --after", hg_repo)
112 cmd("hg remove -X _darcs --after", hg_repo)
94 cmd("hg commit -l %s -u '%s' -d '%s 0'" % (tmpfile, author, date), hg_repo)
113 res = cmd("hg commit -l %s -u '%s' -d '%s 0'" % (tmpfile, author, date), hg_repo)
95 os.unlink(tmpfile)
114 os.unlink(tmpfile)
115 new_tip = hg_tip(hg_repo)
116 if not new_tip == old_tip + 1:
117 # Sometimes we may have empty commits, we simply skip them
118 if res.strip().lower().find("nothing changed") != -1:
119 pass
120 else:
121 error("Mercurial commit did not work as expected: " + res)
122
123 def hg_tip( hg_repo ):
124 """Returns the latest local revision number in the given repository."""
125 tip = cmd("hg tip", hg_repo, silent=True)
126 tip = tip.split("\n")[0].split(":")[1].strip()
127 return int(tip)
96
128
97 # ------------------------------------------------------------------------------
129 # ------------------------------------------------------------------------------
98 #
130 #
@@ -106,26 +138,41 b' if __name__ == "__main__":'
106 if len(args) == 2:
138 if len(args) == 2:
107 darcs_repo = os.path.abspath(args[0])
139 darcs_repo = os.path.abspath(args[0])
108 hg_repo = os.path.abspath(args[1])
140 hg_repo = os.path.abspath(args[1])
141 skip = None
142 elif len(args) == 3:
143 darcs_repo = os.path.abspath(args[0])
144 hg_repo = os.path.abspath(args[1])
145 skip = int(args[2])
109 else:
146 else:
110 print USAGE
147 print USAGE
111 sys.exit(-1)
148 sys.exit(-1)
112 # Initializes the target repo
149 # Initializes the target repo
113 if not os.path.isdir(darcs_repo + "/_darcs"):
150 if not os.path.isdir(darcs_repo + "/_darcs"):
114 print "No darcs directory found at: " + darc_repo
151 print "No darcs directory found at: " + darcs_repo
115 sys.exit(-1)
152 sys.exit(-1)
116 if not os.path.isdir(hg_repo):
153 if not os.path.isdir(hg_repo):
117 os.mkdir(hg_repo)
154 os.mkdir(hg_repo)
118 else:
155 elif skip == None:
119 print "Given HG repository must not exist. It will be created"
156 print "Given HG repository must not exist when no SKIP is specified."
120 sys.exit(-1)
157 sys.exit(-1)
158 if skip == None:
121 cmd("hg init '%s'" % (hg_repo))
159 cmd("hg init '%s'" % (hg_repo))
122 cmd("darcs initialize", hg_repo)
160 cmd("darcs initialize", hg_repo)
123 # Get the changes from the Darcs repository
161 # Get the changes from the Darcs repository
124 for hash, author, date, summary, description in darcs_changes(darcs_repo):
162 change_number = 0
163 for author, date, summary, chash, description in darcs_changes(darcs_repo):
164 print "== changeset", change_number,
165 if skip != None and change_number <= skip:
166 print "(skipping)"
167 else:
125 text = summary + "\n" + description
168 text = summary + "\n" + description
126 darcs_pull(hg_repo, darcs_repo, hash)
169 darcs_pull(hg_repo, darcs_repo, chash)
170 # The commit hash has a date like 20021020201112
171 # --------------------------------YYYYMMDDHHMMSS
172 date = chash.split("-")[0]
127 epoch = int(mktime(strptime(date, '%Y%m%d%H%M%S')))
173 epoch = int(mktime(strptime(date, '%Y%m%d%H%M%S')))
128 hg_commit(hg_repo, text, author, epoch)
174 hg_commit(hg_repo, text, author, epoch)
175 change_number += 1
176 print "Darcs repository (_darcs) was not deleted. You can keep or remove it."
129
177
130 # EOF
178 # EOF
131
General Comments 0
You need to be logged in to leave comments. Login now