##// END OF EJS Templates
mq: add a little documentation on qpush -f
mq: add a little documentation on qpush -f

File last commit:

r6217:fe8dbbe9 default
r6552:315b36ce default
Show More
hg.py
302 lines | 10.4 KiB | text/x-python | PythonLexer
Brendan Cully
Split convert extension into common and repository type modules
r4536 # hg backend for convert extension
Bryan O'Sullivan
convert: some tidyups, doc improvements, and test fixes...
r5556 # Notes for hg->hg conversion:
#
# * Old versions of Mercurial didn't trim the whitespace from the ends
# of commit messages, but new versions do. Changesets created by
# those older versions, then converted, may thus have different
# hashes for changesets that are otherwise identical.
#
# * By default, the source revision is stored in the converted
# revision. This will cause the converted revision to have a
# different identity than the source. To avoid this, use the
# following option: "--config convert.hg.saverev=false"
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
Brendan Cully
Split convert extension into common and repository type modules
r4536 import os, time
Bryan O'Sullivan
convert: acquire/release locks periodically
r5014 from mercurial.i18n import _
Joel Rosdahl
Avoid importing mercurial.node/mercurial.repo stuff from mercurial.hg
r6217 from mercurial.repo import RepoError
Joel Rosdahl
Expand import * to allow Pyflakes to find problems
r6211 from mercurial.node import bin, hex, nullid
Joel Rosdahl
Remove unused imports
r6212 from mercurial import hg, revlog, util
Brendan Cully
Split convert extension into common and repository type modules
r4536
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 from common import NoRepo, commit, converter_source, converter_sink
Brendan Cully
Split convert extension into common and repository type modules
r4536
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 class mercurial_sink(converter_sink):
Brendan Cully
convert: split converter into convertsource and convertsink
r4763 def __init__(self, ui, path):
Bryan O'Sullivan
convert: add default constructor for converter_sink
r5440 converter_sink.__init__(self, ui, path)
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
Brendan Cully
convert: new config variable hg.tagsbranch controls which branch tags are committed to
r5260 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 self.lastbranch = None
Bryan O'Sullivan
convert: refactor sink initialisation, to remove hardcoding of hg...
r5441 if os.path.isdir(path) and len(os.listdir(path)) > 0:
try:
self.repo = hg.repository(self.ui, path)
Patrick Mezard
convert: mercurial sink must be local
r5918 if not self.repo.local():
raise NoRepo(_('%s is not a local Mercurial repo') % path)
Joel Rosdahl
Avoid importing mercurial.node/mercurial.repo stuff from mercurial.hg
r6217 except RepoError, err:
Bryan O'Sullivan
convert: refactor sink initialisation, to remove hardcoding of hg...
r5441 ui.print_exc()
raise NoRepo(err.args[0])
else:
try:
ui.status(_('initializing destination %s repository\n') % path)
self.repo = hg.repository(self.ui, path, create=True)
Patrick Mezard
convert: mercurial sink must be local
r5918 if not self.repo.local():
raise NoRepo(_('%s is not a local Mercurial repo') % path)
Bryan O'Sullivan
convert: refactor sink initialisation, to remove hardcoding of hg...
r5441 self.created.append(path)
Joel Rosdahl
Avoid importing mercurial.node/mercurial.repo stuff from mercurial.hg
r6217 except RepoError, err:
Bryan O'Sullivan
convert: refactor sink initialisation, to remove hardcoding of hg...
r5441 ui.print_exc()
raise NoRepo("could not create hg repo %s as sink" % path)
Bryan O'Sullivan
convert: acquire/release locks periodically
r5014 self.lock = None
self.wlock = None
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 self.filemapmode = False
Bryan O'Sullivan
convert: acquire/release locks periodically
r5014
def before(self):
Patrick Mezard
test-convert: test before() and after() conversion actions
r5805 self.ui.debug(_('run hg sink pre-conversion action\n'))
Alexis S. L. Carvalho
convert: fix locking order
r5052 self.wlock = self.repo.wlock()
Bryan O'Sullivan
convert: acquire/release locks periodically
r5014 self.lock = self.repo.lock()
Alexis S. L. Carvalho
convert: clear the dirstate before a conversion, invalidate it afterwards...
r5279 self.repo.dirstate.clear()
Bryan O'Sullivan
convert: acquire/release locks periodically
r5014
def after(self):
Patrick Mezard
test-convert: test before() and after() conversion actions
r5805 self.ui.debug(_('run hg sink post-conversion action\n'))
Alexis S. L. Carvalho
convert: clear the dirstate before a conversion, invalidate it afterwards...
r5279 self.repo.dirstate.invalidate()
Bryan O'Sullivan
convert: acquire/release locks periodically
r5014 self.lock = None
self.wlock = None
Brendan Cully
Split convert extension into common and repository type modules
r4536
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 return os.path.join(self.path, ".hg", "shamap")
Edouard Gomez
convert extension: Add support for username mapping...
r4589 def authorfile(self):
return os.path.join(self.path, ".hg", "authormap")
Brendan Cully
Split convert extension into common and repository type modules
r4536 def getheads(self):
h = self.repo.changelog.heads()
Bryan O'Sullivan
convert: get rid of "hg." prefix where not needed
r5017 return [ hex(x) for x in h ]
Brendan Cully
Split convert extension into common and repository type modules
r4536
def putfile(self, f, e, data):
self.repo.wwrite(f, data, e)
Matt Mackall
dirstate: add __contains__ and make __getitem__ more useful...
r4906 if f not in self.repo.dirstate:
Alexis S. L. Carvalho
convert: avoid dirstate checks; add a test...
r5278 self.repo.dirstate.normallookup(f)
Brendan Cully
Split convert extension into common and repository type modules
r4536
Daniel Holth
convert extension: Add SVN converter
r4765 def copyfile(self, source, dest):
self.repo.copy(source, dest)
Brendan Cully
Split convert extension into common and repository type modules
r4536 def delfile(self, f):
try:
Bryan O'Sullivan
convert: delete empty directories if deleting a file (bug 754)
r5343 util.unlink(self.repo.wjoin(f))
Brendan Cully
Split convert extension into common and repository type modules
r4536 #self.repo.remove([f])
Patrick Mezard
convert: fix missing import
r5344 except OSError:
Brendan Cully
Split convert extension into common and repository type modules
r4536 pass
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 def setbranch(self, branch, pbranches):
if not self.clonebranches:
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 return
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 setbranch = (branch != self.lastbranch)
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 self.lastbranch = branch
if not branch:
branch = 'default'
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
pbranch = pbranches and pbranches[0][1] or 'default'
Brendan Cully
convert: hg: optionally create branches as clones...
r5173
branchpath = os.path.join(self.path, branch)
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 if setbranch:
self.after()
try:
self.repo = hg.repository(self.ui, branchpath)
except:
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 self.repo = hg.repository(self.ui, branchpath, create=True)
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 self.before()
# pbranches may bring revisions from other branches (merge parents)
# Make sure we have them, or pull them.
missings = {}
for b in pbranches:
try:
self.repo.lookup(b[0])
except:
missings.setdefault(b[1], []).append(b[0])
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 if missings:
self.after()
for pbranch, heads in missings.iteritems():
pbranchpath = os.path.join(self.path, pbranch)
prepo = hg.repository(self.ui, pbranchpath)
self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
self.before()
Brendan Cully
convert: hg: optionally create branches as clones...
r5173
Brendan Cully
Split convert extension into common and repository type modules
r4536 def putcommit(self, files, parents, commit):
Alexis S. L. Carvalho
convert: fix mercurial_sink.putcommit...
r5195 seen = {}
Brendan Cully
Split convert extension into common and repository type modules
r4536 pl = []
for p in parents:
if p not in seen:
pl.append(p)
seen[p] = 1
parents = pl
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 nparents = len(parents)
if self.filemapmode and nparents == 1:
m1node = self.repo.changelog.read(bin(parents[0]))[0]
parent = parents[0]
Brendan Cully
Split convert extension into common and repository type modules
r4536
if len(parents) < 2: parents.append("0" * 40)
if len(parents) < 2: parents.append("0" * 40)
p2 = parents.pop(0)
text = commit.desc
Bryan O'Sullivan
convert: make contents of "extra" dict available from sources, for sinks....
r5439 extra = commit.extra.copy()
Bryan O'Sullivan
convert: add config option to turn off use of branch names
r5038 if self.branchnames and commit.branch:
Brendan Cully
convert: record the source revision in the changelog
r4873 extra['branch'] = commit.branch
if commit.rev:
extra['convert_revision'] = commit.rev
Thomas Arendsen Hein
removed trailing whitespace
r4957
Brendan Cully
Split convert extension into common and repository type modules
r4536 while parents:
p1 = p2
p2 = parents.pop(0)
a = self.repo.rawcommit(files, text, commit.author, commit.date,
Bryan O'Sullivan
convert: get rid of "hg." prefix where not needed
r5017 bin(p1), bin(p2), extra=extra)
Alexis S. L. Carvalho
convert: avoid dirstate checks; add a test...
r5278 self.repo.dirstate.clear()
Brendan Cully
Split convert extension into common and repository type modules
r4536 text = "(octopus merge fixup)\n"
Joel Rosdahl
Avoid importing mercurial.node/mercurial.repo stuff from mercurial.hg
r6217 p2 = hex(self.repo.changelog.tip())
Brendan Cully
Split convert extension into common and repository type modules
r4536
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 if self.filemapmode and nparents == 1:
man = self.repo.manifest
mnode = self.repo.changelog.read(bin(p2))[0]
if not man.cmp(m1node, man.revision(mnode)):
self.repo.rollback()
self.repo.dirstate.clear()
return parent
Brendan Cully
Split convert extension into common and repository type modules
r4536 return p2
def puttags(self, tags):
try:
old = self.repo.wfile(".hgtags").read()
oldlines = old.splitlines(1)
oldlines.sort()
except:
oldlines = []
k = tags.keys()
k.sort()
newlines = []
for tag in k:
newlines.append("%s %s\n" % (tags[tag], tag))
newlines.sort()
if newlines != oldlines:
self.ui.status("updating tags\n")
f = self.repo.wfile(".hgtags", "w")
f.write("".join(newlines))
f.close()
if not oldlines: self.repo.add([".hgtags"])
date = "%s 0" % int(time.mktime(time.gmtime()))
Brendan Cully
convert: new config variable hg.tagsbranch controls which branch tags are committed to
r5260 extra = {}
if self.tagsbranch != 'default':
extra['branch'] = self.tagsbranch
try:
tagparent = self.repo.changectx(self.tagsbranch).node()
Joel Rosdahl
Avoid importing mercurial.node/mercurial.repo stuff from mercurial.hg
r6217 except RepoError, inst:
Brendan Cully
convert: new config variable hg.tagsbranch controls which branch tags are committed to
r5260 tagparent = nullid
Brendan Cully
Split convert extension into common and repository type modules
r4536 self.repo.rawcommit([".hgtags"], "update tags", "convert-repo",
Edouard Gomez
convert: respect hg.tagsbranch setting
r5838 date, tagparent, nullid, extra=extra)
Bryan O'Sullivan
convert: get rid of "hg." prefix where not needed
r5017 return hex(self.repo.changelog.tip())
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 def setfilemapmode(self, active):
self.filemapmode = active
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 class mercurial_source(converter_source):
def __init__(self, ui, path, rev=None):
converter_source.__init__(self, ui, path, rev)
Bryan O'Sullivan
convert: some tidyups, doc improvements, and test fixes...
r5556 self.saverev = ui.configbool('convert', 'hg.saverev', True)
Bryan O'Sullivan
convert: fail properly if we can't read a source hg repository
r5358 try:
self.repo = hg.repository(self.ui, path)
Bryan O'Sullivan
convert: report errors more meaningfully if run with --traceback
r5437 # try to provoke an exception if this isn't really a hg
# repo, but some other bogus compatible-looking url
Alexis S. L. Carvalho
convert: make sure mercurial_source has a local hg repo
r5522 if not self.repo.local():
Joel Rosdahl
Avoid importing mercurial.node/mercurial.repo stuff from mercurial.hg
r6217 raise RepoError()
except RepoError:
Bryan O'Sullivan
convert: report errors more meaningfully if run with --traceback
r5437 ui.print_exc()
Alexis S. L. Carvalho
convert: make sure mercurial_source has a local hg repo
r5522 raise NoRepo("%s is not a local Mercurial repo" % path)
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 self.lastrev = None
self.lastctx = None
Alexis S. L. Carvalho
mercurial_source: add --filemap support
r5379 self._changescache = None
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 self.convertfp = None
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
def changectx(self, rev):
if self.lastrev != rev:
self.lastctx = self.repo.changectx(rev)
self.lastrev = rev
return self.lastctx
def getheads(self):
Bryan O'Sullivan
convert: only get history for requested revs when converting hg repo
r5131 if self.rev:
return [hex(self.repo.changectx(self.rev).node())]
else:
return [hex(node) for node in self.repo.heads()]
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
def getfile(self, name, rev):
try:
return self.changectx(rev).filectx(name).data()
except revlog.LookupError, err:
raise IOError(err)
def getmode(self, name, rev):
m = self.changectx(rev).manifest()
return (m.execf(name) and 'x' or '') + (m.linkf(name) and 'l' or '')
def getchanges(self, rev):
ctx = self.changectx(rev)
Alexis S. L. Carvalho
mercurial_source: add --filemap support
r5379 if self._changescache and self._changescache[0] == rev:
m, a, r = self._changescache[1]
else:
m, a, r = self.repo.status(ctx.parents()[0].node(), ctx.node())[:3]
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 changes = [(name, rev) for name in m + a + r]
changes.sort()
Alexis S. L. Carvalho
convert: mercurial_source: also search for copies in modified files...
r5280 return (changes, self.getcopies(ctx, m + a))
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
Alexis S. L. Carvalho
convert: mercurial_source: also search for copies in modified files...
r5280 def getcopies(self, ctx, files):
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 copies = {}
Alexis S. L. Carvalho
convert: mercurial_source: also search for copies in modified files...
r5280 for name in files:
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 try:
copies[name] = ctx.filectx(name).renamed()[0]
except TypeError:
pass
return copies
Thomas Arendsen Hein
Remove trailing spaces, fix indentation
r5143
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 def getcommit(self, rev):
ctx = self.changectx(rev)
parents = [hex(p.node()) for p in ctx.parents() if p.node() != nullid]
Bryan O'Sullivan
convert: some tidyups, doc improvements, and test fixes...
r5556 if self.saverev:
crev = rev
else:
crev = None
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 return commit(author=ctx.user(), date=util.datestr(ctx.date()),
Bryan O'Sullivan
convert: some tidyups, doc improvements, and test fixes...
r5556 desc=ctx.description(), rev=crev, parents=parents,
Bryan O'Sullivan
convert: make contents of "extra" dict available from sources, for sinks....
r5439 branch=ctx.branch(), extra=ctx.extra())
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
def gettags(self):
tags = [t for t in self.repo.tagslist() if t[0] != 'tip']
return dict([(name, hex(node)) for name, node in tags])
Alexis S. L. Carvalho
mercurial_source: add --filemap support
r5379
def getchangedfiles(self, rev, i):
ctx = self.changectx(rev)
i = i or 0
changes = self.repo.status(ctx.parents()[i].node(), ctx.node())[:3]
if i == 0:
self._changescache = (rev, changes)
return changes[0] + changes[1] + changes[2]
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 def converted(self, rev, destrev):
if self.convertfp is None:
self.convertfp = open(os.path.join(self.path, '.hg', 'shamap'),
'a')
self.convertfp.write('%s %s\n' % (destrev, rev))
self.convertfp.flush()
Patrick Mezard
test-convert: test before() and after() conversion actions
r5805
def before(self):
self.ui.debug(_('run hg source pre-conversion action\n'))
def after(self):
self.ui.debug(_('run hg source post-conversion action\n'))