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

File last commit:

r5556:61fdf255 default
r5557:c47484fa merge default
Show More
common.py
297 lines | 8.7 KiB | text/x-python | PythonLexer
Brendan Cully
Split convert extension into common and repository type modules
r4536 # common code for the convert extension
Bryan O'Sullivan
convert: abstract map files into a class
r5510 import base64, errno
Patrick Mezard
convert: replace fork with subprocess call.
r5127 import cPickle as pickle
Patrick Mezard
convert: fail if an external required tool is not found
r5497 from mercurial import util
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 from mercurial.i18n import _
Patrick Mezard
convert: replace fork with subprocess call.
r5127
def encodeargs(args):
def encodearg(s):
lines = base64.encodestring(s)
lines = [l.splitlines()[0] for l in lines]
return ''.join(lines)
Thomas Arendsen Hein
Remove trailing spaces, fix indentation
r5143
Patrick Mezard
convert: replace fork with subprocess call.
r5127 s = pickle.dumps(args)
return encodearg(s)
def decodeargs(s):
s = base64.decodestring(s)
return pickle.loads(s)
Brendan Cully
Split convert extension into common and repository type modules
r4536
Patrick Mezard
convert: fail if an external required tool is not found
r5497 def checktool(exe, name=None):
name = name or exe
if not util.find_exe(exe):
raise util.Abort('cannot find required "%s" tool' % name)
Brendan Cully
Split convert extension into common and repository type modules
r4536 class NoRepo(Exception): pass
Alexis S. L. Carvalho
convert: change SKIPREV to 'SKIP'
r5400 SKIPREV = 'SKIP'
Alexis S. L. Carvalho
convert: allow the converter_source to say "skip this revision"...
r5374
Brendan Cully
Split convert extension into common and repository type modules
r4536 class commit(object):
Bryan O'Sullivan
convert: make contents of "extra" dict available from sources, for sinks....
r5439 def __init__(self, author, date, desc, parents, branch=None, rev=None,
extra={}):
Bryan O'Sullivan
convert: make commit constructor clearer and less magical
r5012 self.author = author
self.date = date
Bryan O'Sullivan
convert: empty log messages are OK as of 7f5c3fb0a37d
r5024 self.desc = desc
Bryan O'Sullivan
convert: make commit constructor clearer and less magical
r5012 self.parents = parents
self.branch = branch
self.rev = rev
Bryan O'Sullivan
convert: make contents of "extra" dict available from sources, for sinks....
r5439 self.extra = extra
Brendan Cully
Split convert extension into common and repository type modules
r4536
class converter_source(object):
"""Conversion source interface"""
Bryan O'Sullivan
convert: some tidyups, doc improvements, and test fixes...
r5556 def __init__(self, ui, path=None, rev=None):
Brendan Cully
Split convert extension into common and repository type modules
r4536 """Initialize conversion source (or raise NoRepo("message")
exception if path is not a valid repository)"""
Brendan Cully
convert: move some code into common init function
r4810 self.ui = ui
self.path = path
self.rev = rev
self.encoding = 'utf-8'
Brendan Cully
convert: export revmap to source....
r4812
Bryan O'Sullivan
convert: add before/after hooks for converter sources
r5356 def before(self):
pass
def after(self):
pass
Bryan O'Sullivan
convert: abstract map files into a class
r5510 def setrevmap(self, revmap):
"""set the map of already-converted revisions"""
Brendan Cully
convert: svn: use revmap to parse only new revisions in incremental conversions
r4813 pass
Brendan Cully
Split convert extension into common and repository type modules
r4536
def getheads(self):
"""Return a list of this repository's heads"""
raise NotImplementedError()
def getfile(self, name, rev):
"""Return file contents as a string"""
raise NotImplementedError()
def getmode(self, name, rev):
"""Return file mode, eg. '', 'x', or 'l'"""
raise NotImplementedError()
def getchanges(self, version):
Brendan Cully
convert: look up copies in getchanges instead of getcommit...
r5121 """Returns a tuple of (files, copies)
Files is a sorted list of (filename, id) tuples for all files changed
in version, where id is the source revision id of the file.
Brendan Cully
Split convert extension into common and repository type modules
r4536
Brendan Cully
convert: look up copies in getchanges instead of getcommit...
r5121 copies is a dictionary of dest: source
"""
Brendan Cully
Split convert extension into common and repository type modules
r4536 raise NotImplementedError()
def getcommit(self, version):
"""Return the commit object for version"""
raise NotImplementedError()
def gettags(self):
"""Return the tags as a dictionary of name: revision"""
raise NotImplementedError()
Brendan Cully
convert: ove recode method into converter_source
r4759 def recode(self, s, encoding=None):
if not encoding:
Brendan Cully
convert: move some code into common init function
r4810 encoding = self.encoding or 'utf-8'
Thomas Arendsen Hein
removed trailing whitespace
r4957
Thomas Arendsen Hein
Don't decode unicode strings....
r5287 if isinstance(s, unicode):
return s.encode("utf-8")
Brendan Cully
convert: ove recode method into converter_source
r4759 try:
return s.decode(encoding).encode("utf-8")
except:
try:
return s.decode("latin-1").encode("utf-8")
except:
return s.decode(encoding, "replace").encode("utf-8")
Alexis S. L. Carvalho
convert: readd --filemap...
r5377 def getchangedfiles(self, rev, i):
"""Return the files changed by rev compared to parent[i].
i is an index selecting one of the parents of rev. The return
value should be the list of files that are different in rev and
this parent.
If rev has no parents, i is None.
This function is only needed to support --filemap
"""
raise NotImplementedError()
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 def converted(self, rev, sinkrev):
'''Notify the source that a revision has been converted.'''
pass
Brendan Cully
Split convert extension into common and repository type modules
r4536 class converter_sink(object):
"""Conversion sink (target) interface"""
def __init__(self, ui, path):
"""Initialize conversion sink (or raise NoRepo("message")
Bryan O'Sullivan
convert: refactor sink initialisation, to remove hardcoding of hg...
r5441 exception if path is not a valid repository)
created is a list of paths to remove if a fatal error occurs
later"""
self.ui = ui
Bryan O'Sullivan
convert: add default constructor for converter_sink
r5440 self.path = path
Bryan O'Sullivan
convert: refactor sink initialisation, to remove hardcoding of hg...
r5441 self.created = []
Brendan Cully
Split convert extension into common and repository type modules
r4536
def getheads(self):
"""Return a list of this repository's heads"""
raise NotImplementedError()
Bryan O'Sullivan
convert: rename mapfile to revmapfile, so we can map more than just revs
r5011 def revmapfile(self):
Brendan Cully
Split convert extension into common and repository type modules
r4536 """Path to a file that will contain lines
source_rev_id sink_rev_id
mapping equivalent revision identifiers for each system."""
raise NotImplementedError()
Edouard Gomez
convert extension: Add support for username mapping...
r4589 def authorfile(self):
"""Path to a file that will contain lines
srcauthor=dstauthor
mapping equivalent authors identifiers for each system."""
Brendan Cully
convert: fix various authormap handling bugs
r4590 return None
Edouard Gomez
convert extension: Add support for username mapping...
r4589
Brendan Cully
Split convert extension into common and repository type modules
r4536 def putfile(self, f, e, data):
"""Put file for next putcommit().
f: path to file
e: '', 'x', or 'l' (regular file, executable, or symlink)
data: file contents"""
raise NotImplementedError()
def delfile(self, f):
"""Delete file for next putcommit().
f: path to file"""
raise NotImplementedError()
def putcommit(self, files, parents, commit):
"""Create a revision with all changed files listed in 'files'
and having listed parents. 'commit' is a commit object containing
at a minimum the author, date, and message for this changeset.
Called after putfile() and delfile() calls. Note that the sink
repository is not told to update itself to a particular revision
(or even what that revision would be) before it receives the
file data."""
raise NotImplementedError()
def puttags(self, tags):
"""Put tags into sink.
tags: {tagname: sink_rev_id, ...}"""
raise NotImplementedError()
Patrick Mezard
convert: replace fork with subprocess call.
r5127
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 def setbranch(self, branch, pbranch, parents):
"""Set the current branch name. Called before the first putfile
on the branch.
branch: branch name for subsequent commits
pbranch: branch name of parent commit
parents: destination revisions of parent"""
pass
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378
def setfilemapmode(self, active):
"""Tell the destination that we're using a filemap
Some converter_sources (svn in particular) can claim that a file
was changed in a revision, even if there was no change. This method
tells the destination that we're using a filemap and that it should
filter empty revisions.
"""
pass
Bryan O'Sullivan
convert: abstract map files into a class
r5510
Bryan O'Sullivan
convert: abstract darcs's commandline handling
r5512 def before(self):
pass
def after(self):
pass
class commandline(object):
def __init__(self, ui, command):
self.ui = ui
self.command = command
def prerun(self):
pass
def postrun(self):
pass
def _run(self, cmd, *args, **kwargs):
cmdline = [self.command, cmd] + list(args)
for k, v in kwargs.iteritems():
if len(k) == 1:
cmdline.append('-' + k)
else:
cmdline.append('--' + k.replace('_', '-'))
try:
if len(k) == 1:
cmdline.append('' + v)
else:
cmdline[-1] += '=' + v
except TypeError:
pass
cmdline = [util.shellquote(arg) for arg in cmdline]
cmdline += ['<', util.nulldev]
Patrick Mezard
convert: fix util.popen regression in darcs converter
r5529 cmdline = ' '.join(cmdline)
Bryan O'Sullivan
convert: abstract darcs's commandline handling
r5512 self.ui.debug(cmdline, '\n')
self.prerun()
try:
return util.popen(cmdline)
finally:
self.postrun()
def run(self, cmd, *args, **kwargs):
fp = self._run(cmd, *args, **kwargs)
output = fp.read()
self.ui.debug(output)
return output, fp.close()
def checkexit(self, status, output=''):
if status:
if output:
self.ui.warn(_('%s error:\n') % self.command)
self.ui.warn(output)
msg = util.explain_exit(status)[0]
raise util.Abort(_('%s %s') % (self.command, msg))
def run0(self, cmd, *args, **kwargs):
output, status = self.run(cmd, *args, **kwargs)
self.checkexit(status, output)
return output
Bryan O'Sullivan
convert: abstract map files into a class
r5510
class mapfile(dict):
def __init__(self, ui, path):
super(mapfile, self).__init__()
self.ui = ui
self.path = path
self.fp = None
self.order = []
self._read()
def _read(self):
try:
fp = open(self.path, 'r')
except IOError, err:
if err.errno != errno.ENOENT:
raise
return
for line in fp:
key, value = line[:-1].split(' ', 1)
if key not in self:
self.order.append(key)
super(mapfile, self).__setitem__(key, value)
fp.close()
def __setitem__(self, key, value):
if self.fp is None:
try:
self.fp = open(self.path, 'a')
except IOError, err:
raise util.Abort(_('could not open map file %r: %s') %
(self.path, err.strerror))
self.fp.write('%s %s\n' % (key, value))
self.fp.flush()
super(mapfile, self).__setitem__(key, value)
def close(self):
Bryan O'Sullivan
convert: abstract darcs's commandline handling
r5512 if self.fp:
self.fp.close()
self.fp = None