##// END OF EJS Templates
convert: refactor sink initialisation, to remove hardcoding of hg...
Bryan O'Sullivan -
r5441:71e7c86a default
parent child Browse files
Show More
@@ -19,27 +19,32 b' from mercurial.i18n import _'
19
19
20 commands.norepo += " convert debugsvnlog"
20 commands.norepo += " convert debugsvnlog"
21
21
22 sink_converters = [mercurial_sink]
22 source_converters = [
23 source_converters = [convert_cvs, convert_git, svn_source,
23 ('cvs', convert_cvs),
24 mercurial_source, darcs_source]
24 ('git', convert_git),
25 def convertsource(ui, path, **opts):
25 ('svn', svn_source),
26 for c in source_converters:
26 ('hg', mercurial_source),
27 ('darcs', darcs_source),
28 ]
29
30 sink_converters = [
31 ('hg', mercurial_sink),
32 ]
33
34 def convertsource(ui, path, type, rev):
35 for name, source in source_converters:
27 try:
36 try:
28 return c.getcommit and c(ui, path, **opts)
37 if not type or name == type:
29 except AttributeError:
38 return source(ui, path, rev)
30 pass
31 except NoRepo, inst:
39 except NoRepo, inst:
32 ui.note(_("convert: %s\n") % inst)
40 ui.note(_("convert: %s\n") % inst)
33 raise util.Abort('%s: unknown repository type' % path)
41 raise util.Abort('%s: unknown repository type' % path)
34
42
35 def convertsink(ui, path):
43 def convertsink(ui, path, type):
36 if not os.path.isdir(path):
44 for name, sink in sink_converters:
37 raise util.Abort("%s: not a directory" % path)
38 for c in sink_converters:
39 try:
45 try:
40 return c.putcommit and c(ui, path)
46 if not type or name == type:
41 except AttributeError:
47 return sink(ui, path)
42 pass
43 except NoRepo, inst:
48 except NoRepo, inst:
44 ui.note(_("convert: %s\n") % inst)
49 ui.note(_("convert: %s\n") % inst)
45 raise util.Abort('%s: unknown repository type' % path)
50 raise util.Abort('%s: unknown repository type' % path)
@@ -350,37 +355,14 b' def convert(ui, src, dest=None, revmapfi'
350 dest = hg.defaultdest(src) + "-hg"
355 dest = hg.defaultdest(src) + "-hg"
351 ui.status("assuming destination %s\n" % dest)
356 ui.status("assuming destination %s\n" % dest)
352
357
353 # Try to be smart and initalize things when required
358 destc = convertsink(ui, dest, opts.get('dest_type'))
354 created = False
355 if os.path.isdir(dest):
356 if len(os.listdir(dest)) > 0:
357 try:
358 hg.repository(ui, dest)
359 ui.status("destination %s is a Mercurial repository\n" % dest)
360 except hg.RepoError:
361 raise util.Abort(
362 "destination directory %s is not empty.\n"
363 "Please specify an empty directory to be initialized\n"
364 "or an already initialized mercurial repository"
365 % dest)
366 else:
367 ui.status("initializing destination %s repository\n" % dest)
368 hg.repository(ui, dest, create=True)
369 created = True
370 elif os.path.exists(dest):
371 raise util.Abort("destination %s exists and is not a directory" % dest)
372 else:
373 ui.status("initializing destination %s repository\n" % dest)
374 hg.repository(ui, dest, create=True)
375 created = True
376
377 destc = convertsink(ui, dest)
378
359
379 try:
360 try:
380 srcc = convertsource(ui, src, rev=opts.get('rev'))
361 srcc = convertsource(ui, src, opts.get('source_type'),
362 opts.get('rev'))
381 except Exception:
363 except Exception:
382 if created:
364 for path in destc.created:
383 shutil.rmtree(dest, True)
365 shutil.rmtree(path, True)
384 raise
366 raise
385
367
386 fmap = opts.get('filemap')
368 fmap = opts.get('filemap')
@@ -402,8 +384,10 b' cmdtable = {'
402 "convert":
384 "convert":
403 (convert,
385 (convert,
404 [('A', 'authors', '', 'username mapping filename'),
386 [('A', 'authors', '', 'username mapping filename'),
387 ('d', 'dest-type', '', 'destination repository type'),
405 ('', 'filemap', '', 'remap file names using contents of file'),
388 ('', 'filemap', '', 'remap file names using contents of file'),
406 ('r', 'rev', '', 'import up to target revision REV'),
389 ('r', 'rev', '', 'import up to target revision REV'),
390 ('s', 'source-type', '', 'source repository type'),
407 ('', 'datesort', None, 'try to sort changesets by date')],
391 ('', 'datesort', None, 'try to sort changesets by date')],
408 'hg convert [OPTION]... SOURCE [DEST [MAPFILE]]'),
392 'hg convert [OPTION]... SOURCE [DEST [MAPFILE]]'),
409 "debugsvnlog":
393 "debugsvnlog":
@@ -116,9 +116,13 b' class converter_sink(object):'
116
116
117 def __init__(self, ui, path):
117 def __init__(self, ui, path):
118 """Initialize conversion sink (or raise NoRepo("message")
118 """Initialize conversion sink (or raise NoRepo("message")
119 exception if path is not a valid repository)"""
119 exception if path is not a valid repository)
120
121 created is a list of paths to remove if a fatal error occurs
122 later"""
123 self.ui = ui
120 self.path = path
124 self.path = path
121 self.ui = ui
125 self.created = []
122
126
123 def getheads(self):
127 def getheads(self):
124 """Return a list of this repository's heads"""
128 """Return a list of this repository's heads"""
@@ -21,10 +21,22 b' class mercurial_sink(converter_sink):'
21 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
21 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
22 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
22 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
23 self.lastbranch = None
23 self.lastbranch = None
24 if os.path.isdir(path) and len(os.listdir(path)) > 0:
24 try:
25 try:
25 self.repo = hg.repository(self.ui, path)
26 self.repo = hg.repository(self.ui, path)
26 except:
27 ui.status(_('destination %s is a Mercurial repository\n') %
27 raise NoRepo("could not open hg repo %s as sink" % path)
28 path)
29 except hg.RepoError, err:
30 ui.print_exc()
31 raise NoRepo(err.args[0])
32 else:
33 try:
34 ui.status(_('initializing destination %s repository\n') % path)
35 self.repo = hg.repository(self.ui, path, create=True)
36 self.created.append(path)
37 except hg.RepoError, err:
38 ui.print_exc()
39 raise NoRepo("could not create hg repo %s as sink" % path)
28 self.lock = None
40 self.lock = None
29 self.wlock = None
41 self.wlock = None
30 self.filemapmode = False
42 self.filemapmode = False
@@ -3,6 +3,8 b''
3 echo "[extensions]" >> $HGRCPATH
3 echo "[extensions]" >> $HGRCPATH
4 echo "convert=" >> $HGRCPATH
4 echo "convert=" >> $HGRCPATH
5
5
6 hg help convert
7
6 hg init a
8 hg init a
7 cd a
9 cd a
8 echo a > a
10 echo a > a
@@ -19,3 +21,17 b" hg ci -d'4 0' -me"
19 cd ..
21 cd ..
20 hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
22 hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
21 hg --cwd a-hg pull ../a
23 hg --cwd a-hg pull ../a
24
25 touch bogusfile
26 echo % should fail
27 hg convert a bogusfile
28
29 mkdir bogusdir
30 chmod 000 bogusdir
31
32 echo % should fail
33 hg convert a bogusdir
34
35 echo % should succeed
36 chmod 700 bogusdir
37 hg convert a bogusdir
@@ -1,3 +1,67 b''
1 hg convert [OPTION]... SOURCE [DEST [MAPFILE]]
2
3 Convert a foreign SCM repository to a Mercurial one.
4
5 Accepted source formats:
6 - CVS
7 - Darcs
8 - git
9 - Subversion
10
11 Accepted destination formats:
12 - Mercurial
13
14 If no revision is given, all revisions will be converted. Otherwise,
15 convert will only import up to the named revision (given in a format
16 understood by the source).
17
18 If no destination directory name is specified, it defaults to the
19 basename of the source with '-hg' appended. If the destination
20 repository doesn't exist, it will be created.
21
22 If <revmapfile> isn't given, it will be put in a default location
23 (<dest>/.hg/shamap by default). The <revmapfile> is a simple text
24 file that maps each source commit ID to the destination ID for
25 that revision, like so:
26 <source ID> <destination ID>
27
28 If the file doesn't exist, it's automatically created. It's updated
29 on each commit copied, so convert-repo can be interrupted and can
30 be run repeatedly to copy new commits.
31
32 The [username mapping] file is a simple text file that maps each source
33 commit author to a destination commit author. It is handy for source SCMs
34 that use unix logins to identify authors (eg: CVS). One line per author
35 mapping and the line format is:
36 srcauthor=whatever string you want
37
38 The filemap is a file that allows filtering and remapping of files
39 and directories. Comment lines start with '#'. Each line can
40 contain one of the following directives:
41
42 include path/to/file
43
44 exclude path/to/file
45
46 rename from/file to/file
47
48 The 'include' directive causes a file, or all files under a
49 directory, to be included in the destination repository. The
50 'exclude' directive causes files or directories to be omitted.
51 The 'rename' directive renames a file or directory. To rename
52 from a subdirectory into the root of the repository, use '.' as
53 the path to rename to.
54
55 options:
56
57 -A --authors username mapping filename
58 -d --dest-type destination repository type
59 --filemap remap file names using contents of file
60 -r --rev import up to target revision REV
61 -s --source-type source repository type
62 --datesort try to sort changesets by date
63
64 use "hg -v help convert" to show global options
1 adding a
65 adding a
2 assuming destination a-hg
66 assuming destination a-hg
3 initializing destination a-hg repository
67 initializing destination a-hg repository
@@ -12,3 +76,18 b' 0 e'
12 pulling from ../a
76 pulling from ../a
13 searching for changes
77 searching for changes
14 no changes found
78 no changes found
79 % should fail
80 initializing destination bogusfile repository
81 abort: cannot create new bundle repository
82 % should fail
83 abort: Permission denied: bogusdir
84 % should succeed
85 initializing destination bogusdir repository
86 scanning source...
87 sorting...
88 converting...
89 4 a
90 3 b
91 2 c
92 1 d
93 0 e
General Comments 0
You need to be logged in to leave comments. Login now