##// END OF EJS Templates
convert: move commands definition to ease demandload job (issue 860)
Patrick Mezard -
r5631:96e16af9 default
parent child Browse files
Show More
@@ -1,401 +1,108 b''
1 1 # convert.py Foreign SCM converter
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 from common import NoRepo, SKIPREV, converter_source, converter_sink, mapfile
9 from cvs import convert_cvs
10 from darcs import darcs_source
11 from git import convert_git
12 from hg import mercurial_source, mercurial_sink
13 from subversion import debugsvnlog, svn_source, svn_sink
14 import filemap
15
16 import os, shutil
17 from mercurial import hg, ui, util, commands
18 from mercurial.i18n import _
19
20 commands.norepo += " convert debugsvnlog"
21
22 source_converters = [
23 ('cvs', convert_cvs),
24 ('git', convert_git),
25 ('svn', svn_source),
26 ('hg', mercurial_source),
27 ('darcs', darcs_source),
28 ]
29
30 sink_converters = [
31 ('hg', mercurial_sink),
32 ('svn', svn_sink),
33 ]
34
35 def convertsource(ui, path, type, rev):
36 exceptions = []
37 for name, source in source_converters:
38 try:
39 if not type or name == type:
40 return source(ui, path, rev)
41 except NoRepo, inst:
42 exceptions.append(inst)
43 if not ui.quiet:
44 for inst in exceptions:
45 ui.write(_("%s\n") % inst)
46 raise util.Abort('%s: unknown repository type' % path)
47
48 def convertsink(ui, path, type):
49 for name, sink in sink_converters:
50 try:
51 if not type or name == type:
52 return sink(ui, path)
53 except NoRepo, inst:
54 ui.note(_("convert: %s\n") % inst)
55 raise util.Abort('%s: unknown repository type' % path)
56
57 class converter(object):
58 def __init__(self, ui, source, dest, revmapfile, opts):
59
60 self.source = source
61 self.dest = dest
62 self.ui = ui
63 self.opts = opts
64 self.commitcache = {}
65 self.authors = {}
66 self.authorfile = None
67
68 self.map = mapfile(ui, revmapfile)
69
70 # Read first the dst author map if any
71 authorfile = self.dest.authorfile()
72 if authorfile and os.path.exists(authorfile):
73 self.readauthormap(authorfile)
74 # Extend/Override with new author map if necessary
75 if opts.get('authors'):
76 self.readauthormap(opts.get('authors'))
77 self.authorfile = self.dest.authorfile()
78
79 def walktree(self, heads):
80 '''Return a mapping that identifies the uncommitted parents of every
81 uncommitted changeset.'''
82 visit = heads
83 known = {}
84 parents = {}
85 while visit:
86 n = visit.pop(0)
87 if n in known or n in self.map: continue
88 known[n] = 1
89 commit = self.cachecommit(n)
90 parents[n] = []
91 for p in commit.parents:
92 parents[n].append(p)
93 visit.append(p)
94
95 return parents
96
97 def toposort(self, parents):
98 '''Return an ordering such that every uncommitted changeset is
99 preceeded by all its uncommitted ancestors.'''
100 visit = parents.keys()
101 seen = {}
102 children = {}
103
104 while visit:
105 n = visit.pop(0)
106 if n in seen: continue
107 seen[n] = 1
108 # Ensure that nodes without parents are present in the 'children'
109 # mapping.
110 children.setdefault(n, [])
111 for p in parents[n]:
112 if not p in self.map:
113 visit.append(p)
114 children.setdefault(p, []).append(n)
115
116 s = []
117 removed = {}
118 visit = children.keys()
119 while visit:
120 n = visit.pop(0)
121 if n in removed: continue
122 dep = 0
123 if n in parents:
124 for p in parents[n]:
125 if p in self.map: continue
126 if p not in removed:
127 # we're still dependent
128 visit.append(n)
129 dep = 1
130 break
131
132 if not dep:
133 # all n's parents are in the list
134 removed[n] = 1
135 if n not in self.map:
136 s.append(n)
137 if n in children:
138 for c in children[n]:
139 visit.insert(0, c)
8 import convcmd
9 from mercurial import commands
140 10
141 if self.opts.get('datesort'):
142 depth = {}
143 for n in s:
144 depth[n] = 0
145 pl = [p for p in self.commitcache[n].parents
146 if p not in self.map]
147 if pl:
148 depth[n] = max([depth[p] for p in pl]) + 1
149
150 s = [(depth[n], self.commitcache[n].date, n) for n in s]
151 s.sort()
152 s = [e[2] for e in s]
153
154 return s
155
156 def writeauthormap(self):
157 authorfile = self.authorfile
158 if authorfile:
159 self.ui.status('Writing author map file %s\n' % authorfile)
160 ofile = open(authorfile, 'w+')
161 for author in self.authors:
162 ofile.write("%s=%s\n" % (author, self.authors[author]))
163 ofile.close()
164
165 def readauthormap(self, authorfile):
166 afile = open(authorfile, 'r')
167 for line in afile:
168 try:
169 srcauthor = line.split('=')[0].strip()
170 dstauthor = line.split('=')[1].strip()
171 if srcauthor in self.authors and dstauthor != self.authors[srcauthor]:
172 self.ui.status(
173 'Overriding mapping for author %s, was %s, will be %s\n'
174 % (srcauthor, self.authors[srcauthor], dstauthor))
175 else:
176 self.ui.debug('Mapping author %s to %s\n'
177 % (srcauthor, dstauthor))
178 self.authors[srcauthor] = dstauthor
179 except IndexError:
180 self.ui.warn(
181 'Ignoring bad line in author file map %s: %s\n'
182 % (authorfile, line))
183 afile.close()
184
185 def cachecommit(self, rev):
186 commit = self.source.getcommit(rev)
187 commit.author = self.authors.get(commit.author, commit.author)
188 self.commitcache[rev] = commit
189 return commit
190
191 def copy(self, rev):
192 commit = self.commitcache[rev]
193 do_copies = hasattr(self.dest, 'copyfile')
194 filenames = []
195
196 changes = self.source.getchanges(rev)
197 if isinstance(changes, basestring):
198 if changes == SKIPREV:
199 dest = SKIPREV
200 else:
201 dest = self.map[changes]
202 self.map[rev] = dest
203 return
204 files, copies = changes
205 parents = [self.map[r] for r in commit.parents]
206 if commit.parents:
207 prev = commit.parents[0]
208 if prev not in self.commitcache:
209 self.cachecommit(prev)
210 pbranch = self.commitcache[prev].branch
211 else:
212 pbranch = None
213 self.dest.setbranch(commit.branch, pbranch, parents)
214 for f, v in files:
215 filenames.append(f)
216 try:
217 data = self.source.getfile(f, v)
218 except IOError, inst:
219 self.dest.delfile(f)
220 else:
221 e = self.source.getmode(f, v)
222 self.dest.putfile(f, e, data)
223 if do_copies:
224 if f in copies:
225 copyf = copies[f]
226 # Merely marks that a copy happened.
227 self.dest.copyfile(copyf, f)
228
229 newnode = self.dest.putcommit(filenames, parents, commit)
230 self.source.converted(rev, newnode)
231 self.map[rev] = newnode
232
233 def convert(self):
234 try:
235 self.source.before()
236 self.dest.before()
237 self.source.setrevmap(self.map)
238 self.ui.status("scanning source...\n")
239 heads = self.source.getheads()
240 parents = self.walktree(heads)
241 self.ui.status("sorting...\n")
242 t = self.toposort(parents)
243 num = len(t)
244 c = None
245
246 self.ui.status("converting...\n")
247 for c in t:
248 num -= 1
249 desc = self.commitcache[c].desc
250 if "\n" in desc:
251 desc = desc.splitlines()[0]
252 self.ui.status("%d %s\n" % (num, desc))
253 self.copy(c)
254
255 tags = self.source.gettags()
256 ctags = {}
257 for k in tags:
258 v = tags[k]
259 if self.map.get(v, SKIPREV) != SKIPREV:
260 ctags[k] = self.map[v]
261
262 if c and ctags:
263 nrev = self.dest.puttags(ctags)
264 # write another hash correspondence to override the previous
265 # one so we don't end up with extra tag heads
266 if nrev:
267 self.map[c] = nrev
268
269 self.writeauthormap()
270 finally:
271 self.cleanup()
272
273 def cleanup(self):
274 try:
275 self.dest.after()
276 finally:
277 self.source.after()
278 self.map.close()
11 # Commands definition was moved elsewhere to ease demandload job.
279 12
280 13 def convert(ui, src, dest=None, revmapfile=None, **opts):
281 14 """Convert a foreign SCM repository to a Mercurial one.
282 15
283 16 Accepted source formats:
284 17 - Mercurial
285 18 - CVS
286 19 - Darcs
287 20 - git
288 21 - Subversion
289 22
290 23 Accepted destination formats:
291 24 - Mercurial
292 25 - Subversion (history on branches is not preserved)
293 26
294 27 If no revision is given, all revisions will be converted. Otherwise,
295 28 convert will only import up to the named revision (given in a format
296 29 understood by the source).
297 30
298 31 If no destination directory name is specified, it defaults to the
299 32 basename of the source with '-hg' appended. If the destination
300 33 repository doesn't exist, it will be created.
301 34
302 35 If <MAPFILE> isn't given, it will be put in a default location
303 36 (<dest>/.hg/shamap by default). The <MAPFILE> is a simple text
304 37 file that maps each source commit ID to the destination ID for
305 38 that revision, like so:
306 39 <source ID> <destination ID>
307 40
308 41 If the file doesn't exist, it's automatically created. It's updated
309 42 on each commit copied, so convert-repo can be interrupted and can
310 43 be run repeatedly to copy new commits.
311 44
312 45 The [username mapping] file is a simple text file that maps each source
313 46 commit author to a destination commit author. It is handy for source SCMs
314 47 that use unix logins to identify authors (eg: CVS). One line per author
315 48 mapping and the line format is:
316 49 srcauthor=whatever string you want
317 50
318 51 The filemap is a file that allows filtering and remapping of files
319 52 and directories. Comment lines start with '#'. Each line can
320 53 contain one of the following directives:
321 54
322 55 include path/to/file
323 56
324 57 exclude path/to/file
325 58
326 59 rename from/file to/file
327 60
328 61 The 'include' directive causes a file, or all files under a
329 62 directory, to be included in the destination repository, and the
330 63 exclusion of all other files and dirs not explicitely included.
331 64 The 'exclude' directive causes files or directories to be omitted.
332 65 The 'rename' directive renames a file or directory. To rename from a
333 66 subdirectory into the root of the repository, use '.' as the path to
334 67 rename to.
335 68
336 69 Back end options:
337 70
338 71 --config convert.hg.clonebranches=False (boolean)
339 72 hg target: XXX not documented
340 73 --config convert.hg.saverev=True (boolean)
341 74 hg source: allow target to preserve source revision ID
342 75 --config convert.hg.tagsbranch=default (branch name)
343 76 hg target: XXX not documented
344 77 --config convert.hg.usebranchnames=True (boolean)
345 78 hg target: preserve branch names
346 79
347 80 --config convert.svn.branches=branches (directory name)
348 81 svn source: specify the directory containing branches
349 82 --config convert.svn.tags=tags (directory name)
350 83 svn source: specify the directory containing tags
351 84 --config convert.svn.trunk=trunk (directory name)
352 85 svn source: specify the name of the trunk branch
353 86 """
354
355 util._encoding = 'UTF-8'
356
357 if not dest:
358 dest = hg.defaultdest(src) + "-hg"
359 ui.status("assuming destination %s\n" % dest)
360
361 destc = convertsink(ui, dest, opts.get('dest_type'))
87 return convcmd.convert(ui, src, dest, revmapfile, **opts)
362 88
363 try:
364 srcc = convertsource(ui, src, opts.get('source_type'),
365 opts.get('rev'))
366 except Exception:
367 for path in destc.created:
368 shutil.rmtree(path, True)
369 raise
89 def debugsvnlog(ui, **opts):
90 return convcmd.debugsvnlog(ui, **opts)
370 91
371 fmap = opts.get('filemap')
372 if fmap:
373 srcc = filemap.filemap_source(ui, srcc, fmap)
374 destc.setfilemapmode(True)
375
376 if not revmapfile:
377 try:
378 revmapfile = destc.revmapfile()
379 except:
380 revmapfile = os.path.join(destc, "map")
381
382 c = converter(ui, srcc, destc, revmapfile, opts)
383 c.convert()
384
92 commands.norepo += " convert debugsvnlog"
385 93
386 94 cmdtable = {
387 95 "convert":
388 96 (convert,
389 97 [('A', 'authors', '', 'username mapping filename'),
390 98 ('d', 'dest-type', '', 'destination repository type'),
391 99 ('', 'filemap', '', 'remap file names using contents of file'),
392 100 ('r', 'rev', '', 'import up to target revision REV'),
393 101 ('s', 'source-type', '', 'source repository type'),
394 102 ('', 'datesort', None, 'try to sort changesets by date')],
395 103 'hg convert [OPTION]... SOURCE [DEST [MAPFILE]]'),
396 104 "debugsvnlog":
397 105 (debugsvnlog,
398 106 [],
399 107 'hg debugsvnlog'),
400 108 }
401
@@ -1,401 +1,308 b''
1 # convert.py Foreign SCM converter
1 # convcmd - convert extension commands definition
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from common import NoRepo, SKIPREV, converter_source, converter_sink, mapfile
9 9 from cvs import convert_cvs
10 10 from darcs import darcs_source
11 11 from git import convert_git
12 12 from hg import mercurial_source, mercurial_sink
13 13 from subversion import debugsvnlog, svn_source, svn_sink
14 14 import filemap
15 15
16 16 import os, shutil
17 from mercurial import hg, ui, util, commands
17 from mercurial import hg, util
18 18 from mercurial.i18n import _
19 19
20 commands.norepo += " convert debugsvnlog"
21
22 20 source_converters = [
23 21 ('cvs', convert_cvs),
24 22 ('git', convert_git),
25 23 ('svn', svn_source),
26 24 ('hg', mercurial_source),
27 25 ('darcs', darcs_source),
28 26 ]
29 27
30 28 sink_converters = [
31 29 ('hg', mercurial_sink),
32 30 ('svn', svn_sink),
33 31 ]
34 32
35 33 def convertsource(ui, path, type, rev):
36 34 exceptions = []
37 35 for name, source in source_converters:
38 36 try:
39 37 if not type or name == type:
40 38 return source(ui, path, rev)
41 39 except NoRepo, inst:
42 40 exceptions.append(inst)
43 41 if not ui.quiet:
44 42 for inst in exceptions:
45 43 ui.write(_("%s\n") % inst)
46 44 raise util.Abort('%s: unknown repository type' % path)
47 45
48 46 def convertsink(ui, path, type):
49 47 for name, sink in sink_converters:
50 48 try:
51 49 if not type or name == type:
52 50 return sink(ui, path)
53 51 except NoRepo, inst:
54 52 ui.note(_("convert: %s\n") % inst)
55 53 raise util.Abort('%s: unknown repository type' % path)
56 54
57 55 class converter(object):
58 56 def __init__(self, ui, source, dest, revmapfile, opts):
59 57
60 58 self.source = source
61 59 self.dest = dest
62 60 self.ui = ui
63 61 self.opts = opts
64 62 self.commitcache = {}
65 63 self.authors = {}
66 64 self.authorfile = None
67 65
68 66 self.map = mapfile(ui, revmapfile)
69 67
70 68 # Read first the dst author map if any
71 69 authorfile = self.dest.authorfile()
72 70 if authorfile and os.path.exists(authorfile):
73 71 self.readauthormap(authorfile)
74 72 # Extend/Override with new author map if necessary
75 73 if opts.get('authors'):
76 74 self.readauthormap(opts.get('authors'))
77 75 self.authorfile = self.dest.authorfile()
78 76
79 77 def walktree(self, heads):
80 78 '''Return a mapping that identifies the uncommitted parents of every
81 79 uncommitted changeset.'''
82 80 visit = heads
83 81 known = {}
84 82 parents = {}
85 83 while visit:
86 84 n = visit.pop(0)
87 85 if n in known or n in self.map: continue
88 86 known[n] = 1
89 87 commit = self.cachecommit(n)
90 88 parents[n] = []
91 89 for p in commit.parents:
92 90 parents[n].append(p)
93 91 visit.append(p)
94 92
95 93 return parents
96 94
97 95 def toposort(self, parents):
98 96 '''Return an ordering such that every uncommitted changeset is
99 97 preceeded by all its uncommitted ancestors.'''
100 98 visit = parents.keys()
101 99 seen = {}
102 100 children = {}
103 101
104 102 while visit:
105 103 n = visit.pop(0)
106 104 if n in seen: continue
107 105 seen[n] = 1
108 106 # Ensure that nodes without parents are present in the 'children'
109 107 # mapping.
110 108 children.setdefault(n, [])
111 109 for p in parents[n]:
112 110 if not p in self.map:
113 111 visit.append(p)
114 112 children.setdefault(p, []).append(n)
115 113
116 114 s = []
117 115 removed = {}
118 116 visit = children.keys()
119 117 while visit:
120 118 n = visit.pop(0)
121 119 if n in removed: continue
122 120 dep = 0
123 121 if n in parents:
124 122 for p in parents[n]:
125 123 if p in self.map: continue
126 124 if p not in removed:
127 125 # we're still dependent
128 126 visit.append(n)
129 127 dep = 1
130 128 break
131 129
132 130 if not dep:
133 131 # all n's parents are in the list
134 132 removed[n] = 1
135 133 if n not in self.map:
136 134 s.append(n)
137 135 if n in children:
138 136 for c in children[n]:
139 137 visit.insert(0, c)
140 138
141 139 if self.opts.get('datesort'):
142 140 depth = {}
143 141 for n in s:
144 142 depth[n] = 0
145 143 pl = [p for p in self.commitcache[n].parents
146 144 if p not in self.map]
147 145 if pl:
148 146 depth[n] = max([depth[p] for p in pl]) + 1
149 147
150 148 s = [(depth[n], self.commitcache[n].date, n) for n in s]
151 149 s.sort()
152 150 s = [e[2] for e in s]
153 151
154 152 return s
155 153
156 154 def writeauthormap(self):
157 155 authorfile = self.authorfile
158 156 if authorfile:
159 157 self.ui.status('Writing author map file %s\n' % authorfile)
160 158 ofile = open(authorfile, 'w+')
161 159 for author in self.authors:
162 160 ofile.write("%s=%s\n" % (author, self.authors[author]))
163 161 ofile.close()
164 162
165 163 def readauthormap(self, authorfile):
166 164 afile = open(authorfile, 'r')
167 165 for line in afile:
168 166 try:
169 167 srcauthor = line.split('=')[0].strip()
170 168 dstauthor = line.split('=')[1].strip()
171 169 if srcauthor in self.authors and dstauthor != self.authors[srcauthor]:
172 170 self.ui.status(
173 171 'Overriding mapping for author %s, was %s, will be %s\n'
174 172 % (srcauthor, self.authors[srcauthor], dstauthor))
175 173 else:
176 174 self.ui.debug('Mapping author %s to %s\n'
177 175 % (srcauthor, dstauthor))
178 176 self.authors[srcauthor] = dstauthor
179 177 except IndexError:
180 178 self.ui.warn(
181 179 'Ignoring bad line in author file map %s: %s\n'
182 180 % (authorfile, line))
183 181 afile.close()
184 182
185 183 def cachecommit(self, rev):
186 184 commit = self.source.getcommit(rev)
187 185 commit.author = self.authors.get(commit.author, commit.author)
188 186 self.commitcache[rev] = commit
189 187 return commit
190 188
191 189 def copy(self, rev):
192 190 commit = self.commitcache[rev]
193 191 do_copies = hasattr(self.dest, 'copyfile')
194 192 filenames = []
195 193
196 194 changes = self.source.getchanges(rev)
197 195 if isinstance(changes, basestring):
198 196 if changes == SKIPREV:
199 197 dest = SKIPREV
200 198 else:
201 199 dest = self.map[changes]
202 200 self.map[rev] = dest
203 201 return
204 202 files, copies = changes
205 203 parents = [self.map[r] for r in commit.parents]
206 204 if commit.parents:
207 205 prev = commit.parents[0]
208 206 if prev not in self.commitcache:
209 207 self.cachecommit(prev)
210 208 pbranch = self.commitcache[prev].branch
211 209 else:
212 210 pbranch = None
213 211 self.dest.setbranch(commit.branch, pbranch, parents)
214 212 for f, v in files:
215 213 filenames.append(f)
216 214 try:
217 215 data = self.source.getfile(f, v)
218 216 except IOError, inst:
219 217 self.dest.delfile(f)
220 218 else:
221 219 e = self.source.getmode(f, v)
222 220 self.dest.putfile(f, e, data)
223 221 if do_copies:
224 222 if f in copies:
225 223 copyf = copies[f]
226 224 # Merely marks that a copy happened.
227 225 self.dest.copyfile(copyf, f)
228 226
229 227 newnode = self.dest.putcommit(filenames, parents, commit)
230 228 self.source.converted(rev, newnode)
231 229 self.map[rev] = newnode
232 230
233 231 def convert(self):
234 232 try:
235 233 self.source.before()
236 234 self.dest.before()
237 235 self.source.setrevmap(self.map)
238 236 self.ui.status("scanning source...\n")
239 237 heads = self.source.getheads()
240 238 parents = self.walktree(heads)
241 239 self.ui.status("sorting...\n")
242 240 t = self.toposort(parents)
243 241 num = len(t)
244 242 c = None
245 243
246 244 self.ui.status("converting...\n")
247 245 for c in t:
248 246 num -= 1
249 247 desc = self.commitcache[c].desc
250 248 if "\n" in desc:
251 249 desc = desc.splitlines()[0]
252 250 self.ui.status("%d %s\n" % (num, desc))
253 251 self.copy(c)
254 252
255 253 tags = self.source.gettags()
256 254 ctags = {}
257 255 for k in tags:
258 256 v = tags[k]
259 257 if self.map.get(v, SKIPREV) != SKIPREV:
260 258 ctags[k] = self.map[v]
261 259
262 260 if c and ctags:
263 261 nrev = self.dest.puttags(ctags)
264 262 # write another hash correspondence to override the previous
265 263 # one so we don't end up with extra tag heads
266 264 if nrev:
267 265 self.map[c] = nrev
268 266
269 267 self.writeauthormap()
270 268 finally:
271 269 self.cleanup()
272 270
273 271 def cleanup(self):
274 272 try:
275 273 self.dest.after()
276 274 finally:
277 275 self.source.after()
278 276 self.map.close()
279 277
280 278 def convert(ui, src, dest=None, revmapfile=None, **opts):
281 """Convert a foreign SCM repository to a Mercurial one.
282
283 Accepted source formats:
284 - Mercurial
285 - CVS
286 - Darcs
287 - git
288 - Subversion
289
290 Accepted destination formats:
291 - Mercurial
292 - Subversion (history on branches is not preserved)
293
294 If no revision is given, all revisions will be converted. Otherwise,
295 convert will only import up to the named revision (given in a format
296 understood by the source).
297
298 If no destination directory name is specified, it defaults to the
299 basename of the source with '-hg' appended. If the destination
300 repository doesn't exist, it will be created.
301
302 If <MAPFILE> isn't given, it will be put in a default location
303 (<dest>/.hg/shamap by default). The <MAPFILE> is a simple text
304 file that maps each source commit ID to the destination ID for
305 that revision, like so:
306 <source ID> <destination ID>
307
308 If the file doesn't exist, it's automatically created. It's updated
309 on each commit copied, so convert-repo can be interrupted and can
310 be run repeatedly to copy new commits.
311
312 The [username mapping] file is a simple text file that maps each source
313 commit author to a destination commit author. It is handy for source SCMs
314 that use unix logins to identify authors (eg: CVS). One line per author
315 mapping and the line format is:
316 srcauthor=whatever string you want
317
318 The filemap is a file that allows filtering and remapping of files
319 and directories. Comment lines start with '#'. Each line can
320 contain one of the following directives:
321
322 include path/to/file
323
324 exclude path/to/file
325
326 rename from/file to/file
327
328 The 'include' directive causes a file, or all files under a
329 directory, to be included in the destination repository, and the
330 exclusion of all other files and dirs not explicitely included.
331 The 'exclude' directive causes files or directories to be omitted.
332 The 'rename' directive renames a file or directory. To rename from a
333 subdirectory into the root of the repository, use '.' as the path to
334 rename to.
335
336 Back end options:
337
338 --config convert.hg.clonebranches=False (boolean)
339 hg target: XXX not documented
340 --config convert.hg.saverev=True (boolean)
341 hg source: allow target to preserve source revision ID
342 --config convert.hg.tagsbranch=default (branch name)
343 hg target: XXX not documented
344 --config convert.hg.usebranchnames=True (boolean)
345 hg target: preserve branch names
346
347 --config convert.svn.branches=branches (directory name)
348 svn source: specify the directory containing branches
349 --config convert.svn.tags=tags (directory name)
350 svn source: specify the directory containing tags
351 --config convert.svn.trunk=trunk (directory name)
352 svn source: specify the name of the trunk branch
353 """
354
355 279 util._encoding = 'UTF-8'
356 280
357 281 if not dest:
358 282 dest = hg.defaultdest(src) + "-hg"
359 283 ui.status("assuming destination %s\n" % dest)
360 284
361 285 destc = convertsink(ui, dest, opts.get('dest_type'))
362 286
363 287 try:
364 288 srcc = convertsource(ui, src, opts.get('source_type'),
365 289 opts.get('rev'))
366 290 except Exception:
367 291 for path in destc.created:
368 292 shutil.rmtree(path, True)
369 293 raise
370 294
371 295 fmap = opts.get('filemap')
372 296 if fmap:
373 297 srcc = filemap.filemap_source(ui, srcc, fmap)
374 298 destc.setfilemapmode(True)
375 299
376 300 if not revmapfile:
377 301 try:
378 302 revmapfile = destc.revmapfile()
379 303 except:
380 304 revmapfile = os.path.join(destc, "map")
381 305
382 306 c = converter(ui, srcc, destc, revmapfile, opts)
383 307 c.convert()
384 308
385
386 cmdtable = {
387 "convert":
388 (convert,
389 [('A', 'authors', '', 'username mapping filename'),
390 ('d', 'dest-type', '', 'destination repository type'),
391 ('', 'filemap', '', 'remap file names using contents of file'),
392 ('r', 'rev', '', 'import up to target revision REV'),
393 ('s', 'source-type', '', 'source repository type'),
394 ('', 'datesort', None, 'try to sort changesets by date')],
395 'hg convert [OPTION]... SOURCE [DEST [MAPFILE]]'),
396 "debugsvnlog":
397 (debugsvnlog,
398 [],
399 'hg debugsvnlog'),
400 }
401
General Comments 0
You need to be logged in to leave comments. Login now