Mercurial > hg > mercurial-crew-with-dirclash
view hgext/convert/hg.py @ 5377:756a43a30e34
convert: readd --filemap
To handle merges correctly, this revision adds a filemap_source class
that wraps a converter_source and does the work necessary to calculate
the subgraph we're interested in.
The wrapped converter_source must provide a new getchangedfiles method
that, given a revision rev, and an index N, returns the list of files
that are different in rev and its Nth parent.
The implementation depends on the ability to skip some revisions and to
change the parents field of the commit objects that we returned earlier.
To make the conversion restartable, we assume the revisons in the
revmapfile are topologically sorted.
author | Alexis S. L. Carvalho <alexis@cecm.usp.br> |
---|---|
date | Thu, 04 Oct 2007 23:21:37 -0300 |
parents | b98c377b3c16 |
children | 8a2915f57dfc |
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() self.repo.dirstate.clear() def after(self): self.repo.dirstate.invalidate() 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: util.unlink(self.repo.wjoin(f)) #self.repo.remove([f]) except OSError: 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) try: self.repo = hg.repository(self.ui, path) except: raise NoRepo("could not open hg repo %s as source" % 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, m + a)) def getcopies(self, ctx, files): copies = {} for name in files: 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])