mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 08:18:15 +03:00
41b6be949d
During a conversion, the dirstate contents are not consistent - there are files that may be missing from the dirstate and there may be files that shouldn't be in the dirstate. While this is not fixed, don't mark files as added - put them directly in state 'n'ormal.
210 lines
6.7 KiB
Python
210 lines
6.7 KiB
Python
# hg backend for convert extension
|
|
|
|
# Note 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.
|
|
|
|
|
|
import os, time
|
|
from mercurial.i18n import _
|
|
from mercurial.node import *
|
|
from mercurial import hg, lock, revlog, util
|
|
|
|
from common import NoRepo, commit, converter_source, converter_sink
|
|
|
|
class mercurial_sink(converter_sink):
|
|
def __init__(self, ui, path):
|
|
self.path = path
|
|
self.ui = ui
|
|
self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
|
|
self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
|
|
self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
|
|
self.lastbranch = None
|
|
try:
|
|
self.repo = hg.repository(self.ui, path)
|
|
except:
|
|
raise NoRepo("could not open hg repo %s as sink" % path)
|
|
self.lock = None
|
|
self.wlock = None
|
|
|
|
def before(self):
|
|
self.wlock = self.repo.wlock()
|
|
self.lock = self.repo.lock()
|
|
|
|
def after(self):
|
|
self.lock = None
|
|
self.wlock = None
|
|
|
|
def revmapfile(self):
|
|
return os.path.join(self.path, ".hg", "shamap")
|
|
|
|
def authorfile(self):
|
|
return os.path.join(self.path, ".hg", "authormap")
|
|
|
|
def getheads(self):
|
|
h = self.repo.changelog.heads()
|
|
return [ hex(x) for x in h ]
|
|
|
|
def putfile(self, f, e, data):
|
|
self.repo.wwrite(f, data, e)
|
|
if f not in self.repo.dirstate:
|
|
self.repo.dirstate.normallookup(f)
|
|
|
|
def copyfile(self, source, dest):
|
|
self.repo.copy(source, dest)
|
|
|
|
def delfile(self, f):
|
|
try:
|
|
os.unlink(self.repo.wjoin(f))
|
|
#self.repo.remove([f])
|
|
except:
|
|
pass
|
|
|
|
def setbranch(self, branch, pbranch, parents):
|
|
if (not self.clonebranches) or (branch == self.lastbranch):
|
|
return
|
|
|
|
self.lastbranch = branch
|
|
self.after()
|
|
if not branch:
|
|
branch = 'default'
|
|
if not pbranch:
|
|
pbranch = 'default'
|
|
|
|
branchpath = os.path.join(self.path, branch)
|
|
try:
|
|
self.repo = hg.repository(self.ui, branchpath)
|
|
except:
|
|
if not parents:
|
|
self.repo = hg.repository(self.ui, branchpath, create=True)
|
|
else:
|
|
self.ui.note(_('cloning branch %s to %s\n') % (pbranch, branch))
|
|
hg.clone(self.ui, os.path.join(self.path, pbranch),
|
|
branchpath, rev=parents, update=False,
|
|
stream=True)
|
|
self.repo = hg.repository(self.ui, branchpath)
|
|
|
|
def putcommit(self, files, parents, commit):
|
|
seen = {}
|
|
pl = []
|
|
for p in parents:
|
|
if p not in seen:
|
|
pl.append(p)
|
|
seen[p] = 1
|
|
parents = pl
|
|
|
|
if len(parents) < 2: parents.append("0" * 40)
|
|
if len(parents) < 2: parents.append("0" * 40)
|
|
p2 = parents.pop(0)
|
|
|
|
text = commit.desc
|
|
extra = {}
|
|
if self.branchnames and commit.branch:
|
|
extra['branch'] = commit.branch
|
|
if commit.rev:
|
|
extra['convert_revision'] = commit.rev
|
|
|
|
while parents:
|
|
p1 = p2
|
|
p2 = parents.pop(0)
|
|
a = self.repo.rawcommit(files, text, commit.author, commit.date,
|
|
bin(p1), bin(p2), extra=extra)
|
|
self.repo.dirstate.clear()
|
|
text = "(octopus merge fixup)\n"
|
|
p2 = hg.hex(self.repo.changelog.tip())
|
|
|
|
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()))
|
|
extra = {}
|
|
if self.tagsbranch != 'default':
|
|
extra['branch'] = self.tagsbranch
|
|
try:
|
|
tagparent = self.repo.changectx(self.tagsbranch).node()
|
|
except hg.RepoError, inst:
|
|
tagparent = nullid
|
|
self.repo.rawcommit([".hgtags"], "update tags", "convert-repo",
|
|
date, tagparent, nullid)
|
|
return hex(self.repo.changelog.tip())
|
|
|
|
class mercurial_source(converter_source):
|
|
def __init__(self, ui, path, rev=None):
|
|
converter_source.__init__(self, ui, path, rev)
|
|
self.repo = hg.repository(self.ui, path)
|
|
self.lastrev = None
|
|
self.lastctx = None
|
|
|
|
def changectx(self, rev):
|
|
if self.lastrev != rev:
|
|
self.lastctx = self.repo.changectx(rev)
|
|
self.lastrev = rev
|
|
return self.lastctx
|
|
|
|
def getheads(self):
|
|
if self.rev:
|
|
return [hex(self.repo.changectx(self.rev).node())]
|
|
else:
|
|
return [hex(node) for node in self.repo.heads()]
|
|
|
|
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)
|
|
m, a, r = self.repo.status(ctx.parents()[0].node(), ctx.node())[:3]
|
|
changes = [(name, rev) for name in m + a + r]
|
|
changes.sort()
|
|
return (changes, self.getcopies(ctx))
|
|
|
|
def getcopies(self, ctx):
|
|
added = self.repo.status(ctx.parents()[0].node(), ctx.node())[1]
|
|
copies = {}
|
|
for name in added:
|
|
try:
|
|
copies[name] = ctx.filectx(name).renamed()[0]
|
|
except TypeError:
|
|
pass
|
|
return copies
|
|
|
|
def getcommit(self, rev):
|
|
ctx = self.changectx(rev)
|
|
parents = [hex(p.node()) for p in ctx.parents() if p.node() != nullid]
|
|
return commit(author=ctx.user(), date=util.datestr(ctx.date()),
|
|
desc=ctx.description(), parents=parents,
|
|
branch=ctx.branch())
|
|
|
|
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])
|