##// END OF EJS Templates
Merge with crew
Merge with crew

File last commit:

r4958:71fed370 default
r4965:4106dde1 merge default
Show More
__init__.py
353 lines | 11.5 KiB | text/x-python | PythonLexer
Edouard Gomez
Turns convert.py into a real extension
r4513 # convert.py Foreign SCM converter
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 #
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 #
Edouard Gomez
Turns convert.py into a real extension
r4513 # This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
Brendan Cully
convert: split converter into convertsource and convertsink
r4763 from common import NoRepo, converter_source, converter_sink
Brendan Cully
Split convert extension into common and repository type modules
r4536 from cvs import convert_cvs
from git import convert_git
from hg import convert_mercurial
Brendan Cully
convert: activate subversion engine...
r4766 from subversion import convert_svn
Brendan Cully
Split convert extension into common and repository type modules
r4536
Brendan Cully
convert: initialize source after destination, cleaning up if source is unusable
r4761 import os, shutil
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 from mercurial import hg, ui, util, commands
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
Edouard Gomez
Turns convert.py into a real extension
r4513 commands.norepo += " convert"
Brendan Cully
convert: activate subversion engine...
r4766 converters = [convert_cvs, convert_git, convert_svn, convert_mercurial]
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
Brendan Cully
convert: make convertsource option handling transparent
r4780 def convertsource(ui, path, **opts):
Brendan Cully
convert: split converter into convertsource and convertsink
r4763 for c in converters:
Brendan Cully
convert: activate subversion engine...
r4766 if not hasattr(c, 'getcommit'):
continue
Brendan Cully
convert: split converter into convertsource and convertsink
r4763 try:
Brendan Cully
convert: make convertsource option handling transparent
r4780 return c(ui, path, **opts)
Brendan Cully
convert: split converter into convertsource and convertsink
r4763 except NoRepo:
pass
raise util.Abort('%s: unknown repository type' % path)
def convertsink(ui, path):
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 if not os.path.isdir(path):
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 raise util.Abort("%s: not a directory" % path)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 for c in converters:
Brendan Cully
convert: activate subversion engine...
r4766 if not hasattr(c, 'putcommit'):
continue
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 try:
Edouard Gomez
Turns convert.py into a real extension
r4513 return c(ui, path)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 except NoRepo:
pass
Brendan Cully
convert: split converter into convertsource and convertsink
r4763 raise util.Abort('%s: unknown repository type' % path)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
class convert(object):
Edouard Gomez
Turns convert.py into a real extension
r4513 def __init__(self, ui, source, dest, mapfile, opts):
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
self.source = source
self.dest = dest
Edouard Gomez
Turns convert.py into a real extension
r4513 self.ui = ui
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 self.opts = opts
self.commitcache = {}
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 self.mapfile = mapfile
self.mapfilefd = None
Edouard Gomez
convert extension: Add support for username mapping...
r4589 self.authors = {}
Brendan Cully
convert: fix various authormap handling bugs
r4590 self.authorfile = None
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
self.map = {}
try:
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 origmapfile = open(self.mapfile, 'r')
for l in origmapfile:
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 sv, dv = l[:-1].split()
self.map[sv] = dv
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 origmapfile.close()
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 except IOError:
pass
Edouard Gomez
convert extension: Add support for username mapping...
r4589 # Read first the dst author map if any
Brendan Cully
convert: fix various authormap handling bugs
r4590 authorfile = self.dest.authorfile()
if authorfile and os.path.exists(authorfile):
self.readauthormap(authorfile)
Edouard Gomez
convert extension: Add support for username mapping...
r4589 # Extend/Override with new author map if necessary
Brendan Cully
convert: fix various authormap handling bugs
r4590 if opts.get('authors'):
Edouard Gomez
convert extension: Add support for username mapping...
r4589 self.readauthormap(opts.get('authors'))
Brendan Cully
convert: fix various authormap handling bugs
r4590 self.authorfile = self.dest.authorfile()
Edouard Gomez
convert extension: Add support for username mapping...
r4589
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 def walktree(self, heads):
Hollis Blanchard
fix 'convert' with single commit repositories...
r4719 '''Return a mapping that identifies the uncommitted parents of every
uncommitted changeset.'''
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 visit = heads
known = {}
parents = {}
while visit:
n = visit.pop(0)
if n in known or n in self.map: continue
known[n] = 1
self.commitcache[n] = self.source.getcommit(n)
cp = self.commitcache[n].parents
Hollis Blanchard
fix 'convert' with single commit repositories...
r4719 parents[n] = []
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 for p in cp:
Hollis Blanchard
fix 'convert' with single commit repositories...
r4719 parents[n].append(p)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 visit.append(p)
return parents
def toposort(self, parents):
Hollis Blanchard
fix 'convert' with single commit repositories...
r4719 '''Return an ordering such that every uncommitted changeset is
preceeded by all its uncommitted ancestors.'''
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 visit = parents.keys()
seen = {}
children = {}
while visit:
n = visit.pop(0)
if n in seen: continue
seen[n] = 1
Hollis Blanchard
fix 'convert' with single commit repositories...
r4719 # Ensure that nodes without parents are present in the 'children'
# mapping.
children.setdefault(n, [])
for p in parents[n]:
if not p in self.map:
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 visit.append(p)
Hollis Blanchard
fix 'convert' with single commit repositories...
r4719 children.setdefault(p, []).append(n)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
s = []
removed = {}
visit = children.keys()
while visit:
n = visit.pop(0)
if n in removed: continue
dep = 0
if n in parents:
for p in parents[n]:
if p in self.map: continue
if p not in removed:
# we're still dependent
visit.append(n)
dep = 1
break
if not dep:
# all n's parents are in the list
removed[n] = 1
if n not in self.map:
s.append(n)
if n in children:
for c in children[n]:
visit.insert(0, c)
Edouard Gomez
Turns convert.py into a real extension
r4513 if self.opts.get('datesort'):
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 depth = {}
for n in s:
depth[n] = 0
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 pl = [p for p in self.commitcache[n].parents
if p not in self.map]
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 if pl:
depth[n] = max([depth[p] for p in pl]) + 1
s = [(depth[n], self.commitcache[n].date, n) for n in s]
s.sort()
s = [e[2] for e in s]
return s
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 def mapentry(self, src, dst):
if self.mapfilefd is None:
try:
self.mapfilefd = open(self.mapfile, "a")
except IOError, (errno, strerror):
raise util.Abort("Could not open map file %s: %s, %s\n" % (self.mapfile, errno, strerror))
self.map[src] = dst
self.mapfilefd.write("%s %s\n" % (src, dst))
self.mapfilefd.flush()
Edouard Gomez
convert extension: Add support for username mapping...
r4589 def writeauthormap(self):
Brendan Cully
convert: fix various authormap handling bugs
r4590 authorfile = self.authorfile
if authorfile:
Edouard Gomez
convert extension: Add support for username mapping...
r4589 self.ui.status('Writing author map file %s\n' % authorfile)
ofile = open(authorfile, 'w+')
for author in self.authors:
ofile.write("%s=%s\n" % (author, self.authors[author]))
ofile.close()
def readauthormap(self, authorfile):
Brendan Cully
convert: fix various authormap handling bugs
r4590 afile = open(authorfile, 'r')
for line in afile:
try:
srcauthor = line.split('=')[0].strip()
dstauthor = line.split('=')[1].strip()
if srcauthor in self.authors and dstauthor != self.authors[srcauthor]:
self.ui.status(
'Overriding mapping for author %s, was %s, will be %s\n'
% (srcauthor, self.authors[srcauthor], dstauthor))
else:
self.ui.debug('Mapping author %s to %s\n'
% (srcauthor, dstauthor))
Edouard Gomez
convert extension: Add support for username mapping...
r4589 self.authors[srcauthor] = dstauthor
Brendan Cully
convert: fix various authormap handling bugs
r4590 except IndexError:
self.ui.warn(
'Ignoring bad line in author file map %s: %s\n'
% (authorfile, line))
afile.close()
Edouard Gomez
convert extension: Add support for username mapping...
r4589
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 def copy(self, rev):
c = self.commitcache[rev]
files = self.source.getchanges(rev)
Thomas Arendsen Hein
removed trailing whitespace
r4957
Daniel Holth
convert extension: Add SVN converter
r4765 do_copies = (hasattr(c, 'copies') and hasattr(self.dest, 'copyfile'))
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 for f, v in files:
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 try:
data = self.source.getfile(f, v)
except IOError, inst:
self.dest.delfile(f)
else:
e = self.source.getmode(f, v)
self.dest.putfile(f, e, data)
Daniel Holth
convert extension: Add SVN converter
r4765 if do_copies:
if f in c.copies:
# Merely marks that a copy happened.
self.dest.copyfile(c.copies[f], f)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
r = [self.map[v] for v in c.parents]
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 f = [f for f, v in files]
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 newnode = self.dest.putcommit(f, r, c)
self.mapentry(rev, newnode)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
def convert(self):
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 try:
Brendan Cully
convert: export revmap to source....
r4812 self.source.setrevmap(self.map)
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 self.ui.status("scanning source...\n")
heads = self.source.getheads()
parents = self.walktree(heads)
self.ui.status("sorting...\n")
t = self.toposort(parents)
num = len(t)
c = None
self.ui.status("converting...\n")
for c in t:
num -= 1
desc = self.commitcache[c].desc
if "\n" in desc:
desc = desc.splitlines()[0]
Edouard Gomez
convert extension: Add support for username mapping...
r4589 author = self.commitcache[c].author
author = self.authors.get(author, author)
self.commitcache[c].author = author
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 self.ui.status("%d %s\n" % (num, desc))
self.copy(c)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 tags = self.source.gettags()
ctags = {}
for k in tags:
v = tags[k]
if v in self.map:
ctags[k] = self.map[v]
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 if c and ctags:
nrev = self.dest.puttags(ctags)
# write another hash correspondence to override the previous
# one so we don't end up with extra tag heads
if nrev:
self.mapentry(c, nrev)
Edouard Gomez
convert extension: Add support for username mapping...
r4589
self.writeauthormap()
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 finally:
self.cleanup()
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
Edouard Gomez
convert extension: Save a few opens on the map file...
r4588 def cleanup(self):
if self.mapfilefd:
self.mapfilefd.close()
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
Edouard Gomez
Turns convert.py into a real extension
r4513 def _convert(ui, src, dest=None, mapfile=None, **opts):
Thomas Arendsen Hein
Backout ad09ce1d393c and replace ''' with """ to make some highlighting happy....
r4958 """Convert a foreign SCM repository to a Mercurial one.
Edouard Gomez
Turns convert.py into a real extension
r4513
Accepted source formats:
- GIT
- CVS
Daniel Holth
convert extension: Add SVN converter
r4765 - SVN
Edouard Gomez
Turns convert.py into a real extension
r4513
Accepted destination formats:
- Mercurial
Brendan Cully
convert: add -r argument specifying latest revision to convert
r4760 If no revision is given, all revisions will be converted. Otherwise,
convert will only import up to the named revision (given in a format
understood by the source).
Thomas Arendsen Hein
convert: Use clone's behaviour for the default destionation name....
r4883 If no destination directory name is specified, it defaults to the
Thomas Arendsen Hein
Backout ad09ce1d393c and replace ''' with """ to make some highlighting happy....
r4958 basename of the source with '-hg' appended. If the destination
repository doesn't exist, it will be created.
Edouard Gomez
Turns convert.py into a real extension
r4513
Thomas Arendsen Hein
Backout ad09ce1d393c and replace ''' with """ to make some highlighting happy....
r4958 If <mapfile> isn't given, it will be put in a default location
Thomas Arendsen Hein
convert: Use clone's behaviour for the default destionation name....
r4883 (<dest>/.hg/shamap by default). The <mapfile> is a simple text
file that maps each source commit ID to the destination ID for
that revision, like so:
Edouard Gomez
Turns convert.py into a real extension
r4513 <source ID> <destination ID>
Thomas Arendsen Hein
Backout ad09ce1d393c and replace ''' with """ to make some highlighting happy....
r4958 If the file doesn't exist, it's automatically created. It's updated
Edouard Gomez
Turns convert.py into a real extension
r4513 on each commit copied, so convert-repo can be interrupted and can
be run repeatedly to copy new commits.
Edouard Gomez
convert extension: Add support for username mapping...
r4589
The [username mapping] file is a simple text file that maps each source
commit author to a destination commit author. It is handy for source SCMs
that use unix logins to identify authors (eg: CVS). One line per author
mapping and the line format is:
srcauthor=whatever string you want
Thomas Arendsen Hein
Backout ad09ce1d393c and replace ''' with """ to make some highlighting happy....
r4958 """
Edouard Gomez
Turns convert.py into a real extension
r4513
Alexis S. L. Carvalho
convert: manually set encoding to UTF-8...
r4895 util._encoding = 'UTF-8'
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 if not dest:
Thomas Arendsen Hein
convert: Use clone's behaviour for the default destionation name....
r4883 dest = hg.defaultdest(src) + "-hg"
Edouard Gomez
Turns convert.py into a real extension
r4513 ui.status("assuming destination %s\n" % dest)
Edouard Gomez
Add some more smart when initializing destination repository
r4521
# Try to be smart and initalize things when required
Brendan Cully
convert: initialize source after destination, cleaning up if source is unusable
r4761 created = False
Edouard Gomez
Add some more smart when initializing destination repository
r4521 if os.path.isdir(dest):
if len(os.listdir(dest)) > 0:
try:
hg.repository(ui, dest)
ui.status("destination %s is a Mercurial repository\n" % dest)
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 except hg.RepoError:
Edouard Gomez
Add some more smart when initializing destination repository
r4521 raise util.Abort(
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 "destination directory %s is not empty.\n"
"Please specify an empty directory to be initialized\n"
"or an already initialized mercurial repository"
% dest)
Edouard Gomez
Add some more smart when initializing destination repository
r4521 else:
ui.status("initializing destination %s repository\n" % dest)
hg.repository(ui, dest, create=True)
Brendan Cully
convert: initialize source after destination, cleaning up if source is unusable
r4761 created = True
Edouard Gomez
Add some more smart when initializing destination repository
r4521 elif os.path.exists(dest):
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 raise util.Abort("destination %s exists and is not a directory" % dest)
Edouard Gomez
Add some more smart when initializing destination repository
r4521 else:
ui.status("initializing destination %s repository\n" % dest)
hg.repository(ui, dest, create=True)
Brendan Cully
convert: initialize source after destination, cleaning up if source is unusable
r4761 created = True
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532
Brendan Cully
convert: split converter into convertsource and convertsink
r4763 destc = convertsink(ui, dest)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
Brendan Cully
convert: initialize source after destination, cleaning up if source is unusable
r4761 try:
Brendan Cully
convert: split converter into convertsource and convertsink
r4763 srcc = convertsource(ui, src, rev=opts.get('rev'))
Brendan Cully
convert: initialize source after destination, cleaning up if source is unusable
r4761 except Exception:
if created:
shutil.rmtree(dest, True)
raise
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512
if not mapfile:
try:
mapfile = destc.mapfile()
except:
mapfile = os.path.join(destc, "map")
Edouard Gomez
Turns convert.py into a real extension
r4513 c = convert(ui, srcc, destc, mapfile, opts)
Thomas Arendsen Hein
Move convert-repo to hgext/convert/__init__.py
r4512 c.convert()
Edouard Gomez
Turns convert.py into a real extension
r4513 cmdtable = {
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 "convert":
(_convert,
Edouard Gomez
convert extension: Add support for username mapping...
r4589 [('A', 'authors', '', 'username mapping filename'),
Brendan Cully
convert: add -r argument specifying latest revision to convert
r4760 ('r', 'rev', '', 'import up to target revision REV'),
Edouard Gomez
convert extension: Add support for username mapping...
r4589 ('', 'datesort', None, 'try to sort changesets by date')],
Thomas Arendsen Hein
Some small cleanups for convert extension:...
r4532 'hg convert [OPTION]... SOURCE [DEST [MAPFILE]]'),
Edouard Gomez
Turns convert.py into a real extension
r4513 }