10 from darcs import darcs_source |
10 from darcs import darcs_source |
11 from git import convert_git |
11 from git import convert_git |
12 from hg import mercurial_source, mercurial_sink |
12 from hg import mercurial_source, mercurial_sink |
13 from subversion import convert_svn, debugsvnlog |
13 from subversion import convert_svn, debugsvnlog |
14 |
14 |
15 import os, shlex, shutil |
15 import os, shutil |
16 from mercurial import hg, ui, util, commands |
16 from mercurial import hg, ui, util, commands |
17 from mercurial.i18n import _ |
17 from mercurial.i18n import _ |
18 |
18 |
19 commands.norepo += " convert debugsvnlog" |
19 commands.norepo += " convert debugsvnlog" |
20 |
20 |
283 finally: |
283 finally: |
284 self.source.after() |
284 self.source.after() |
285 if self.revmapfilefd: |
285 if self.revmapfilefd: |
286 self.revmapfilefd.close() |
286 self.revmapfilefd.close() |
287 |
287 |
288 def rpairs(name): |
|
289 e = len(name) |
|
290 while e != -1: |
|
291 yield name[:e], name[e+1:] |
|
292 e = name.rfind('/', 0, e) |
|
293 |
|
294 class filemapper(object): |
|
295 '''Map and filter filenames when importing. |
|
296 A name can be mapped to itself, a new name, or None (omit from new |
|
297 repository).''' |
|
298 |
|
299 def __init__(self, ui, path=None): |
|
300 self.ui = ui |
|
301 self.include = {} |
|
302 self.exclude = {} |
|
303 self.rename = {} |
|
304 if path: |
|
305 if self.parse(path): |
|
306 raise util.Abort(_('errors in filemap')) |
|
307 |
|
308 def parse(self, path): |
|
309 errs = 0 |
|
310 def check(name, mapping, listname): |
|
311 if name in mapping: |
|
312 self.ui.warn(_('%s:%d: %r already in %s list\n') % |
|
313 (lex.infile, lex.lineno, name, listname)) |
|
314 return 1 |
|
315 return 0 |
|
316 lex = shlex.shlex(open(path), path, True) |
|
317 lex.wordchars += '!@#$%^&*()-=+[]{}|;:,./<>?' |
|
318 cmd = lex.get_token() |
|
319 while cmd: |
|
320 if cmd == 'include': |
|
321 name = lex.get_token() |
|
322 errs += check(name, self.exclude, 'exclude') |
|
323 self.include[name] = name |
|
324 elif cmd == 'exclude': |
|
325 name = lex.get_token() |
|
326 errs += check(name, self.include, 'include') |
|
327 errs += check(name, self.rename, 'rename') |
|
328 self.exclude[name] = name |
|
329 elif cmd == 'rename': |
|
330 src = lex.get_token() |
|
331 dest = lex.get_token() |
|
332 errs += check(src, self.exclude, 'exclude') |
|
333 self.rename[src] = dest |
|
334 elif cmd == 'source': |
|
335 errs += self.parse(lex.get_token()) |
|
336 else: |
|
337 self.ui.warn(_('%s:%d: unknown directive %r\n') % |
|
338 (lex.infile, lex.lineno, cmd)) |
|
339 errs += 1 |
|
340 cmd = lex.get_token() |
|
341 return errs |
|
342 |
|
343 def lookup(self, name, mapping): |
|
344 for pre, suf in rpairs(name): |
|
345 try: |
|
346 return mapping[pre], pre, suf |
|
347 except KeyError, err: |
|
348 pass |
|
349 return '', name, '' |
|
350 |
|
351 def __call__(self, name): |
|
352 if self.include: |
|
353 inc = self.lookup(name, self.include)[0] |
|
354 else: |
|
355 inc = name |
|
356 if self.exclude: |
|
357 exc = self.lookup(name, self.exclude)[0] |
|
358 else: |
|
359 exc = '' |
|
360 if not inc or exc: |
|
361 return None |
|
362 newpre, pre, suf = self.lookup(name, self.rename) |
|
363 if newpre: |
|
364 if newpre == '.': |
|
365 return suf |
|
366 if suf: |
|
367 return newpre + '/' + suf |
|
368 return newpre |
|
369 return name |
|
370 |
|
371 def active(self): |
|
372 return bool(self.include or self.exclude or self.rename) |
|
373 |
|
374 def convert(ui, src, dest=None, revmapfile=None, **opts): |
288 def convert(ui, src, dest=None, revmapfile=None, **opts): |
375 """Convert a foreign SCM repository to a Mercurial one. |
289 """Convert a foreign SCM repository to a Mercurial one. |
376 |
290 |
377 Accepted source formats: |
291 Accepted source formats: |
378 - CVS |
292 - CVS |