Mercurial > hg
view hgext/convert/hg.py @ 5278:70e9a527cc61
convert: avoid dirstate checks; add a test
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.
author | Alexis S. L. Carvalho <alexis@cecm.usp.br> |
---|---|
date | Sat, 01 Sep 2007 02:49:18 -0300 |
parents | be4835ad9a85 |
children | 2dbd750b3ddd |
line wrap: on
line source
# 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])