##// END OF EJS Templates
issue1577: fix broken test by assuming less about CVS output....
issue1577: fix broken test by assuming less about CVS output. Specifically, output of "cvs ci" varies unpredictably across CVS versions, so any test that includes the output of "cvs ci" is doomed to fail some of the time. This fixes that by discarding the output of "cvs ci".

File last commit:

r7968:43b70a96 default
r8081:6c3b8132 default
Show More
convcmd.py
341 lines | 10.9 KiB | text/x-python | PythonLexer
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 # convcmd - convert extension commands definition
#
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
Patrick Mezard
convert: allow missing tools not to stop source type detection
r6332 from common import NoRepo, MissingTool, SKIPREV, mapfile
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 from cvs import convert_cvs
from darcs import darcs_source
from git import convert_git
from hg import mercurial_source, mercurial_sink
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5631 from subversion import debugsvnlog, svn_source, svn_sink
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 from monotone import monotone_source
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 from gnuarch import gnuarch_source
Marek Kubica
convert: add bzr source
r7053 from bzr import bzr_source
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 from p4 import p4_source
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 import filemap
import os, shutil
from mercurial import hg, util
from mercurial.i18n import _
Patrick Mezard
convert: improve cycles detection message
r6131 orig_encoding = 'ascii'
def recode(s):
if isinstance(s, unicode):
return s.encode(orig_encoding, 'replace')
else:
return s.decode('utf-8').encode(orig_encoding, 'replace')
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 source_converters = [
('cvs', convert_cvs),
('git', convert_git),
('svn', svn_source),
('hg', mercurial_source),
('darcs', darcs_source),
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 ('mtn', monotone_source),
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 ('gnuarch', gnuarch_source),
Marek Kubica
convert: add bzr source
r7053 ('bzr', bzr_source),
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 ('p4', p4_source),
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 ]
sink_converters = [
('hg', mercurial_sink),
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5631 ('svn', svn_sink),
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 ]
def convertsource(ui, path, type, rev):
exceptions = []
for name, source in source_converters:
try:
if not type or name == type:
return source(ui, path, rev)
Patrick Mezard
convert: allow missing tools not to stop source type detection
r6332 except (NoRepo, MissingTool), inst:
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 exceptions.append(inst)
if not ui.quiet:
for inst in exceptions:
Martin Geisler
move % out of translatable strings...
r6913 ui.write("%s\n" % inst)
Patrick Mezard
convert: document source and sink identifiers, fix error message
r6976 raise util.Abort(_('%s: missing or unsupported repository') % path)
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
def convertsink(ui, path, type):
for name, sink in sink_converters:
try:
if not type or name == type:
return sink(ui, path)
except NoRepo, inst:
ui.note(_("convert: %s\n") % inst)
Martin Geisler
move % out of translatable strings...
r6913 raise util.Abort(_('%s: unknown repository type') % path)
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
class converter(object):
def __init__(self, ui, source, dest, revmapfile, opts):
self.source = source
self.dest = dest
self.ui = ui
self.opts = opts
self.commitcache = {}
self.authors = {}
self.authorfile = None
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5631 self.map = mapfile(ui, revmapfile)
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
# Read first the dst author map if any
authorfile = self.dest.authorfile()
if authorfile and os.path.exists(authorfile):
self.readauthormap(authorfile)
# Extend/Override with new author map if necessary
if opts.get('authors'):
self.readauthormap(opts.get('authors'))
self.authorfile = self.dest.authorfile()
Bryan O'Sullivan
convert: document splicemap, allow setting of multiple parents
r6143 self.splicemap = mapfile(ui, opts.get('splicemap'))
Bryan O'Sullivan
convert: allow synthetic history to be spliced in....
r5996
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 def walktree(self, heads):
'''Return a mapping that identifies the uncommitted parents of every
uncommitted changeset.'''
visit = heads
known = {}
parents = {}
while visit:
n = visit.pop(0)
if n in known or n in self.map: continue
known[n] = 1
commit = self.cachecommit(n)
parents[n] = []
for p in commit.parents:
parents[n].append(p)
visit.append(p)
return parents
def toposort(self, parents):
'''Return an ordering such that every uncommitted changeset is
preceeded by all its uncommitted ancestors.'''
visit = parents.keys()
seen = {}
children = {}
Patrick Mezard
convert: fix --datesort ordering...
r6100 actives = []
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
while visit:
n = visit.pop(0)
if n in seen: continue
seen[n] = 1
# Ensure that nodes without parents are present in the 'children'
# mapping.
children.setdefault(n, [])
Patrick Mezard
convert: fix --datesort ordering...
r6100 hasparent = False
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 for p in parents[n]:
if not p in self.map:
visit.append(p)
Patrick Mezard
convert: fix --datesort ordering...
r6100 hasparent = True
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 children.setdefault(p, []).append(n)
Patrick Mezard
convert: fix --datesort ordering...
r6100 if not hasparent:
actives.append(n)
del seen
del visit
if self.opts.get('datesort'):
dates = {}
def getdate(n):
if n not in dates:
dates[n] = util.parsedate(self.commitcache[n].date)
return dates[n]
def picknext(nodes):
return min([(getdate(n), n) for n in nodes])[1]
else:
prev = [None]
def picknext(nodes):
# Return the first eligible child of the previously converted
# revision, or any of them.
next = nodes[0]
for n in nodes:
if prev[0] in parents[n]:
next = n
break
prev[0] = next
return next
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
s = []
Patrick Mezard
convert: fix --datesort ordering...
r6100 pendings = {}
while actives:
n = picknext(actives)
actives.remove(n)
s.append(n)
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
Patrick Mezard
convert: fix --datesort ordering...
r6100 # Update dependents list
for c in children.get(n, []):
if c not in pendings:
pendings[c] = [p for p in parents[c] if p not in self.map]
Patrick Mezard
convert: improve cycles detection message
r6131 try:
pendings[c].remove(n)
except ValueError:
raise util.Abort(_('cycle detected between %s and %s')
% (recode(c), recode(n)))
Patrick Mezard
convert: fix --datesort ordering...
r6100 if not pendings[c]:
# Parents are converted, node is eligible
actives.insert(0, c)
pendings[c] = None
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
Patrick Mezard
convert: fix --datesort ordering...
r6100 if len(s) != len(parents):
raise util.Abort(_("not all revisions were sorted"))
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
return s
def writeauthormap(self):
authorfile = self.authorfile
if authorfile:
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 self.ui.status(_('Writing author map file %s\n') % authorfile)
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 ofile = open(authorfile, 'w+')
for author in self.authors:
ofile.write("%s=%s\n" % (author, self.authors[author]))
ofile.close()
def readauthormap(self, authorfile):
afile = open(authorfile, 'r')
for line in afile:
Marti Raudsepp
convert: Ignore empty lines in authormap file.
r6184 if line.strip() == '':
continue
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 try:
Marti Raudsepp
convert: Clean up authormap key=value splitting....
r6186 srcauthor, dstauthor = line.split('=', 1)
srcauthor = srcauthor.strip()
dstauthor = dstauthor.strip()
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 if srcauthor in self.authors and dstauthor != self.authors[srcauthor]:
self.ui.status(
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 _('Overriding mapping for author %s, was %s, will be %s\n')
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 % (srcauthor, self.authors[srcauthor], dstauthor))
else:
Martin Geisler
lowercase ui.debug and assert output...
r7599 self.ui.debug(_('mapping author %s to %s\n')
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 % (srcauthor, dstauthor))
self.authors[srcauthor] = dstauthor
except IndexError:
self.ui.warn(
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 _('Ignoring bad line in author map file %s: %s\n')
Marti Raudsepp
convert: Avoid redundant newline on authormap errors....
r6185 % (authorfile, line.rstrip()))
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 afile.close()
def cachecommit(self, rev):
commit = self.source.getcommit(rev)
commit.author = self.authors.get(commit.author, commit.author)
self.commitcache[rev] = commit
return commit
def copy(self, rev):
commit = self.commitcache[rev]
changes = self.source.getchanges(rev)
if isinstance(changes, basestring):
if changes == SKIPREV:
dest = SKIPREV
else:
dest = self.map[changes]
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5631 self.map[rev] = dest
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 return
files, copies = changes
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 pbranches = []
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 if commit.parents:
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 for prev in commit.parents:
if prev not in self.commitcache:
self.cachecommit(prev)
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210 pbranches.append((self.map[prev],
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 self.commitcache[prev].branch))
self.dest.setbranch(commit.branch, pbranches)
Bryan O'Sullivan
convert: allow synthetic history to be spliced in....
r5996 try:
Bryan O'Sullivan
convert: document splicemap, allow setting of multiple parents
r6143 parents = self.splicemap[rev].replace(',', ' ').split()
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 self.ui.status(_('spliced in %s as parents of %s\n') %
Bryan O'Sullivan
convert: document splicemap, allow setting of multiple parents
r6143 (parents, rev))
parents = [self.map.get(p, p) for p in parents]
Bryan O'Sullivan
convert: allow synthetic history to be spliced in....
r5996 except KeyError:
parents = [b[0] for b in pbranches]
Patrick Mezard
convert: reintegrate file retrieval code in sinks...
r6716 newnode = self.dest.putcommit(files, copies, parents, commit, self.source)
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5631 self.source.converted(rev, newnode)
self.map[rev] = newnode
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
def convert(self):
Patrick Mezard
convert: display source revision id with --verbose
r5954
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 try:
self.source.before()
self.dest.before()
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5631 self.source.setrevmap(self.map)
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 self.ui.status(_("scanning source...\n"))
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 heads = self.source.getheads()
parents = self.walktree(heads)
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 self.ui.status(_("sorting...\n"))
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 t = self.toposort(parents)
num = len(t)
c = None
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 self.ui.status(_("converting...\n"))
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 for c in t:
num -= 1
desc = self.commitcache[c].desc
if "\n" in desc:
desc = desc.splitlines()[0]
Shun-ichi GOTO
convert: print commit log message with local encoding correctly.
r5794 # convert log message to local encoding without using
# tolocal() because util._encoding conver() use it as
# 'utf-8'
Patrick Mezard
convert: display source revision id with --verbose
r5954 self.ui.status("%d %s\n" % (num, recode(desc)))
Martin Geisler
move % out of translatable strings...
r6913 self.ui.note(_("source: %s\n") % recode(c))
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 self.copy(c)
tags = self.source.gettags()
ctags = {}
for k in tags:
v = tags[k]
if self.map.get(v, SKIPREV) != SKIPREV:
ctags[k] = self.map[v]
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:
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5631 self.map[c] = nrev
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
self.writeauthormap()
finally:
self.cleanup()
def cleanup(self):
try:
self.dest.after()
finally:
self.source.after()
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5631 self.map.close()
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
def convert(ui, src, dest=None, revmapfile=None, **opts):
Shun-ichi GOTO
convert: print commit log message with local encoding correctly.
r5794 global orig_encoding
orig_encoding = util._encoding
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621 util._encoding = 'UTF-8'
if not dest:
dest = hg.defaultdest(src) + "-hg"
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 ui.status(_("assuming destination %s\n") % dest)
Patrick Mezard
convert: move commands definition to ease demandload job (issue 860)
r5621
destc = convertsink(ui, dest, opts.get('dest_type'))
try:
srcc = convertsource(ui, src, opts.get('source_type'),
opts.get('rev'))
except Exception:
for path in destc.created:
shutil.rmtree(path, True)
raise
fmap = opts.get('filemap')
if fmap:
srcc = filemap.filemap_source(ui, srcc, fmap)
destc.setfilemapmode(True)
if not revmapfile:
try:
revmapfile = destc.revmapfile()
except:
revmapfile = os.path.join(destc, "map")
c = converter(ui, srcc, destc, revmapfile, opts)
c.convert()