##// END OF EJS Templates
convert: add support for specifying multiple revs...
Durham Goode -
r25748:baea47ca default
parent child Browse files
Show More
@@ -29,7 +29,7 testedwith = 'internal'
29 _('FILE')),
29 _('FILE')),
30 ('s', 'source-type', '', _('source repository type'), _('TYPE')),
30 ('s', 'source-type', '', _('source repository type'), _('TYPE')),
31 ('d', 'dest-type', '', _('destination repository type'), _('TYPE')),
31 ('d', 'dest-type', '', _('destination repository type'), _('TYPE')),
32 ('r', 'rev', '', _('import up to source revision REV'), _('REV')),
32 ('r', 'rev', [], _('import up to source revision REV'), _('REV')),
33 ('A', 'authormap', '', _('remap usernames using this file'), _('FILE')),
33 ('A', 'authormap', '', _('remap usernames using this file'), _('FILE')),
34 ('', 'filemap', '', _('remap file names using contents of file'),
34 ('', 'filemap', '', _('remap file names using contents of file'),
35 _('FILE')),
35 _('FILE')),
@@ -33,8 +33,8 supportedkinds = ('file', 'symlink')
33 class bzr_source(converter_source):
33 class bzr_source(converter_source):
34 """Reads Bazaar repositories by using the Bazaar Python libraries"""
34 """Reads Bazaar repositories by using the Bazaar Python libraries"""
35
35
36 def __init__(self, ui, path, rev=None):
36 def __init__(self, ui, path, revs=None):
37 super(bzr_source, self).__init__(ui, path, rev=rev)
37 super(bzr_source, self).__init__(ui, path, revs=revs)
38
38
39 if not os.path.exists(os.path.join(path, '.bzr')):
39 if not os.path.exists(os.path.join(path, '.bzr')):
40 raise NoRepo(_('%s does not look like a Bazaar repository')
40 raise NoRepo(_('%s does not look like a Bazaar repository')
@@ -95,20 +95,20 class bzr_source(converter_source):
95 return self.sourcerepo.find_branches(using=True)
95 return self.sourcerepo.find_branches(using=True)
96
96
97 def getheads(self):
97 def getheads(self):
98 if not self.rev:
98 if not self.revs:
99 # Set using=True to avoid nested repositories (see issue3254)
99 # Set using=True to avoid nested repositories (see issue3254)
100 heads = sorted([b.last_revision() for b in self._bzrbranches()])
100 heads = sorted([b.last_revision() for b in self._bzrbranches()])
101 else:
101 else:
102 revid = None
102 revid = None
103 for branch in self._bzrbranches():
103 for branch in self._bzrbranches():
104 try:
104 try:
105 r = RevisionSpec.from_string(self.rev)
105 r = RevisionSpec.from_string(self.revs[0])
106 info = r.in_history(branch)
106 info = r.in_history(branch)
107 except errors.BzrError:
107 except errors.BzrError:
108 pass
108 pass
109 revid = info.rev_id
109 revid = info.rev_id
110 if revid is None:
110 if revid is None:
111 raise util.Abort(_('%s is not a valid revision') % self.rev)
111 raise util.Abort(_('%s is not a valid revision') % self.revs[0])
112 heads = [revid]
112 heads = [revid]
113 # Empty repositories return 'null:', which cannot be retrieved
113 # Empty repositories return 'null:', which cannot be retrieved
114 heads = [h for h in heads if h != 'null:']
114 heads = [h for h in heads if h != 'null:']
@@ -59,12 +59,12 class commit(object):
59 class converter_source(object):
59 class converter_source(object):
60 """Conversion source interface"""
60 """Conversion source interface"""
61
61
62 def __init__(self, ui, path=None, rev=None):
62 def __init__(self, ui, path=None, revs=None):
63 """Initialize conversion source (or raise NoRepo("message")
63 """Initialize conversion source (or raise NoRepo("message")
64 exception if path is not a valid repository)"""
64 exception if path is not a valid repository)"""
65 self.ui = ui
65 self.ui = ui
66 self.path = path
66 self.path = path
67 self.rev = rev
67 self.revs = revs
68
68
69 self.encoding = 'utf-8'
69 self.encoding = 'utf-8'
70
70
@@ -46,14 +46,14 sink_converters = [
46 ('svn', svn_sink),
46 ('svn', svn_sink),
47 ]
47 ]
48
48
49 def convertsource(ui, path, type, rev):
49 def convertsource(ui, path, type, revs):
50 exceptions = []
50 exceptions = []
51 if type and type not in [s[0] for s in source_converters]:
51 if type and type not in [s[0] for s in source_converters]:
52 raise util.Abort(_('%s: invalid source repository type') % type)
52 raise util.Abort(_('%s: invalid source repository type') % type)
53 for name, source, sortmode in source_converters:
53 for name, source, sortmode in source_converters:
54 try:
54 try:
55 if not type or name == type:
55 if not type or name == type:
56 return source(ui, path, rev), sortmode
56 return source(ui, path, revs), sortmode
57 except (NoRepo, MissingTool) as inst:
57 except (NoRepo, MissingTool) as inst:
58 exceptions.append(inst)
58 exceptions.append(inst)
59 if not ui.quiet:
59 if not ui.quiet:
@@ -15,8 +15,8 from common import makedatetimestamp
15 import cvsps
15 import cvsps
16
16
17 class convert_cvs(converter_source):
17 class convert_cvs(converter_source):
18 def __init__(self, ui, path, rev=None):
18 def __init__(self, ui, path, revs=None):
19 super(convert_cvs, self).__init__(ui, path, rev=rev)
19 super(convert_cvs, self).__init__(ui, path, revs=revs)
20
20
21 cvs = os.path.join(path, "CVS")
21 cvs = os.path.join(path, "CVS")
22 if not os.path.exists(cvs):
22 if not os.path.exists(cvs):
@@ -41,14 +41,17 class convert_cvs(converter_source):
41 self.changeset = {}
41 self.changeset = {}
42
42
43 maxrev = 0
43 maxrev = 0
44 if self.rev:
44 if self.revs:
45 if len(self.revs) > 1:
46 raise util.Abort(_('cvs source does not support specifying '
47 'multiple revs'))
45 # TODO: handle tags
48 # TODO: handle tags
46 try:
49 try:
47 # patchset number?
50 # patchset number?
48 maxrev = int(self.rev)
51 maxrev = int(self.revs[0])
49 except ValueError:
52 except ValueError:
50 raise util.Abort(_('revision %s is not a patchset number')
53 raise util.Abort(_('revision %s is not a patchset number')
51 % self.rev)
54 % self.revs[0])
52
55
53 d = os.getcwd()
56 d = os.getcwd()
54 try:
57 try:
@@ -27,8 +27,8 except ImportError:
27 pass
27 pass
28
28
29 class darcs_source(converter_source, commandline):
29 class darcs_source(converter_source, commandline):
30 def __init__(self, ui, path, rev=None):
30 def __init__(self, ui, path, revs=None):
31 converter_source.__init__(self, ui, path, rev=rev)
31 converter_source.__init__(self, ui, path, revs=revs)
32 commandline.__init__(self, ui, 'darcs')
32 commandline.__init__(self, ui, 'darcs')
33
33
34 # check for _darcs, ElementTree so that we can easily skip
34 # check for _darcs, ElementTree so that we can easily skip
@@ -86,8 +86,12 class convert_git(converter_source):
86 data = fh.read()
86 data = fh.read()
87 return data, fh.close()
87 return data, fh.close()
88
88
89 def __init__(self, ui, path, rev=None):
89 def __init__(self, ui, path, revs=None):
90 super(convert_git, self).__init__(ui, path, rev=rev)
90 super(convert_git, self).__init__(ui, path, revs=revs)
91
92 if revs and len(revs) > 1:
93 raise util.Abort(_("git source does not support specifying "
94 "multiple revs"))
91
95
92 if os.path.isdir(path + "/.git"):
96 if os.path.isdir(path + "/.git"):
93 path += "/.git"
97 path += "/.git"
@@ -119,11 +123,12 class convert_git(converter_source):
119 f.close()
123 f.close()
120
124
121 def getheads(self):
125 def getheads(self):
122 if not self.rev:
126 if not self.revs:
123 heads, ret = self.gitread('git rev-parse --branches --remotes')
127 heads, ret = self.gitread('git rev-parse --branches --remotes')
124 heads = heads.splitlines()
128 heads = heads.splitlines()
125 else:
129 else:
126 heads, ret = self.gitread("git rev-parse --verify %s" % self.rev)
130 heads, ret = self.gitread("git rev-parse --verify %s" %
131 self.revs[0])
127 heads = [heads[:-1]]
132 heads = [heads[:-1]]
128 if ret:
133 if ret:
129 raise util.Abort(_('cannot retrieve git heads'))
134 raise util.Abort(_('cannot retrieve git heads'))
@@ -27,8 +27,8 class gnuarch_source(converter_source, c
27 self.ren_files = {}
27 self.ren_files = {}
28 self.ren_dirs = {}
28 self.ren_dirs = {}
29
29
30 def __init__(self, ui, path, rev=None):
30 def __init__(self, ui, path, revs=None):
31 super(gnuarch_source, self).__init__(ui, path, rev=rev)
31 super(gnuarch_source, self).__init__(ui, path, revs=revs)
32
32
33 if not os.path.exists(os.path.join(path, '{arch}')):
33 if not os.path.exists(os.path.join(path, '{arch}')):
34 raise NoRepo(_("%s does not look like a GNU Arch repository")
34 raise NoRepo(_("%s does not look like a GNU Arch repository")
@@ -372,8 +372,11 class mercurial_sink(converter_sink):
372 return rev in self.repo
372 return rev in self.repo
373
373
374 class mercurial_source(converter_source):
374 class mercurial_source(converter_source):
375 def __init__(self, ui, path, rev=None):
375 def __init__(self, ui, path, revs=None):
376 converter_source.__init__(self, ui, path, rev)
376 converter_source.__init__(self, ui, path, revs)
377 if revs and len(revs) > 1:
378 raise util.Abort(_("mercurial source does not support specifying "
379 "multiple revisions"))
377 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
380 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
378 self.ignored = set()
381 self.ignored = set()
379 self.saverev = ui.configbool('convert', 'hg.saverev', False)
382 self.saverev = ui.configbool('convert', 'hg.saverev', False)
@@ -407,12 +410,12 class mercurial_source(converter_source)
407 self.keep = children.__contains__
410 self.keep = children.__contains__
408 else:
411 else:
409 self.keep = util.always
412 self.keep = util.always
410 if rev:
413 if revs:
411 self._heads = [self.repo[rev].node()]
414 self._heads = [self.repo[revs[0]].node()]
412 else:
415 else:
413 self._heads = self.repo.heads()
416 self._heads = self.repo.heads()
414 else:
417 else:
415 if rev or startnode is not None:
418 if revs or startnode is not None:
416 raise util.Abort(_('hg.revs cannot be combined with '
419 raise util.Abort(_('hg.revs cannot be combined with '
417 'hg.startrev or --rev'))
420 'hg.startrev or --rev'))
418 nodes = set()
421 nodes = set()
@@ -13,14 +13,17 from common import commandline
13 from mercurial.i18n import _
13 from mercurial.i18n import _
14
14
15 class monotone_source(converter_source, commandline):
15 class monotone_source(converter_source, commandline):
16 def __init__(self, ui, path=None, rev=None):
16 def __init__(self, ui, path=None, revs=None):
17 converter_source.__init__(self, ui, path, rev)
17 converter_source.__init__(self, ui, path, revs)
18 if revs and len(revs) > 1:
19 raise util.Abort(_('monotone source does not support specifying '
20 'multiple revs'))
18 commandline.__init__(self, ui, 'mtn')
21 commandline.__init__(self, ui, 'mtn')
19
22
20 self.ui = ui
23 self.ui = ui
21 self.path = path
24 self.path = path
22 self.automatestdio = False
25 self.automatestdio = False
23 self.rev = rev
26 self.revs = revs
24
27
25 norepo = NoRepo(_("%s does not look like a monotone repository")
28 norepo = NoRepo(_("%s does not look like a monotone repository")
26 % path)
29 % path)
@@ -219,10 +222,10 class monotone_source(converter_source,
219 # implement the converter_source interface:
222 # implement the converter_source interface:
220
223
221 def getheads(self):
224 def getheads(self):
222 if not self.rev:
225 if not self.revs:
223 return self.mtnrun("leaves").splitlines()
226 return self.mtnrun("leaves").splitlines()
224 else:
227 else:
225 return [self.rev]
228 return self.revs
226
229
227 def getchanges(self, rev, full):
230 def getchanges(self, rev, full):
228 if full:
231 if full:
@@ -24,8 +24,8 def loaditer(f):
24 pass
24 pass
25
25
26 class p4_source(converter_source):
26 class p4_source(converter_source):
27 def __init__(self, ui, path, rev=None):
27 def __init__(self, ui, path, revs=None):
28 super(p4_source, self).__init__(ui, path, rev=rev)
28 super(p4_source, self).__init__(ui, path, revs=revs)
29
29
30 if "/" in path and not path.startswith('//'):
30 if "/" in path and not path.startswith('//'):
31 raise NoRepo(_('%s does not look like a P4 repository') % path)
31 raise NoRepo(_('%s does not look like a P4 repository') % path)
@@ -49,6 +49,9 class p4_source(converter_source):
49 r":[^$\n]*\$")
49 r":[^$\n]*\$")
50 self.re_keywords_old = re.compile("\$(Id|Header):[^$\n]*\$")
50 self.re_keywords_old = re.compile("\$(Id|Header):[^$\n]*\$")
51
51
52 if revs and len(revs) > 1:
53 raise util.Abort(_("p4 source does not support specifying "
54 "multiple revisions"))
52 self._parse(ui, path)
55 self._parse(ui, path)
53
56
54 def _parse_view(self, path):
57 def _parse_view(self, path):
@@ -99,7 +102,7 class p4_source(converter_source):
99 startrev = self.ui.config('convert', 'p4.startrev', default=0)
102 startrev = self.ui.config('convert', 'p4.startrev', default=0)
100 self.p4changes = [x for x in self.p4changes
103 self.p4changes = [x for x in self.p4changes
101 if ((not startrev or int(x) >= int(startrev)) and
104 if ((not startrev or int(x) >= int(startrev)) and
102 (not self.rev or int(x) <= int(self.rev)))]
105 (not self.revs or int(x) <= int(self.revs[0])))]
103
106
104 # now read the full changelists to get the list of file revisions
107 # now read the full changelists to get the list of file revisions
105 ui.status(_('collecting p4 changelists\n'))
108 ui.status(_('collecting p4 changelists\n'))
@@ -268,8 +268,8 def issvnurl(ui, url):
268 # the parent module. A revision has at most one parent.
268 # the parent module. A revision has at most one parent.
269 #
269 #
270 class svn_source(converter_source):
270 class svn_source(converter_source):
271 def __init__(self, ui, url, rev=None):
271 def __init__(self, ui, url, revs=None):
272 super(svn_source, self).__init__(ui, url, rev=rev)
272 super(svn_source, self).__init__(ui, url, revs=revs)
273
273
274 if not (url.startswith('svn://') or url.startswith('svn+ssh://') or
274 if not (url.startswith('svn://') or url.startswith('svn+ssh://') or
275 (os.path.exists(url) and
275 (os.path.exists(url) and
@@ -325,11 +325,15 class svn_source(converter_source):
325 "to libsvn version %s")
325 "to libsvn version %s")
326 % (self.url, svnversion))
326 % (self.url, svnversion))
327
327
328 if rev:
328 if revs:
329 if len(revs) > 1:
330 raise util.Abort(_('subversion source does not support '
331 'specifying multiple revisions'))
329 try:
332 try:
330 latest = int(rev)
333 latest = int(revs[0])
331 except ValueError:
334 except ValueError:
332 raise util.Abort(_('svn: revision %s is not an integer') % rev)
335 raise util.Abort(_('svn: revision %s is not an integer') %
336 revs[0])
333
337
334 self.trunkname = self.ui.config('convert', 'svn.trunk',
338 self.trunkname = self.ui.config('convert', 'svn.trunk',
335 'trunk').strip('/')
339 'trunk').strip('/')
@@ -304,11 +304,11
304 does not convert tags from the source repo to the target
304 does not convert tags from the source repo to the target
305 repo. The default is False.
305 repo. The default is False.
306
306
307 options:
307 options ([+] can be repeated):
308
308
309 -s --source-type TYPE source repository type
309 -s --source-type TYPE source repository type
310 -d --dest-type TYPE destination repository type
310 -d --dest-type TYPE destination repository type
311 -r --rev REV import up to source revision REV
311 -r --rev REV [+] import up to source revision REV
312 -A --authormap FILE remap usernames using this file
312 -A --authormap FILE remap usernames using this file
313 --filemap FILE remap file names using contents of file
313 --filemap FILE remap file names using contents of file
314 --full apply filemap changes by converting all files again
314 --full apply filemap changes by converting all files again
General Comments 0
You need to be logged in to leave comments. Login now