# hg.py - hg backend for convert extension
#
#  Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

# 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.
#
# * Using "--config convert.hg.saverev=true" will make the source
#   identifier to be stored in the converted revision. This will cause
#   the converted revision to have a different identity than the
#   source.


import os, time, cStringIO
from mercurial.i18n import _
from mercurial.node import bin, hex, nullid
from mercurial import hg, util, context, bookmarks, error

from common import NoRepo, commit, converter_source, converter_sink

class mercurial_sink(converter_sink):
    def __init__(self, ui, path):
        converter_sink.__init__(self, ui, path)
        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
        if os.path.isdir(path) and len(os.listdir(path)) > 0:
            try:
                self.repo = hg.repository(self.ui, path)
                if not self.repo.local():
                    raise NoRepo(_('%s is not a local Mercurial repository')
                                 % path)
            except error.RepoError, err:
                ui.traceback()
                raise NoRepo(err.args[0])
        else:
            try:
                ui.status(_('initializing destination %s repository\n') % path)
                self.repo = hg.repository(self.ui, path, create=True)
                if not self.repo.local():
                    raise NoRepo(_('%s is not a local Mercurial repository')
                                 % path)
                self.created.append(path)
            except error.RepoError:
                ui.traceback()
                raise NoRepo(_("could not create hg repository %s as sink")
                             % path)
        self.lock = None
        self.wlock = None
        self.filemapmode = False

    def before(self):
        self.ui.debug('run hg sink pre-conversion action\n')
        self.wlock = self.repo.wlock()
        self.lock = self.repo.lock()

    def after(self):
        self.ui.debug('run hg sink post-conversion action\n')
        if self.lock:
            self.lock.release()
        if self.wlock:
            self.wlock.release()

    def revmapfile(self):
        return self.repo.join("shamap")

    def authorfile(self):
        return self.repo.join("authormap")

    def getheads(self):
        h = self.repo.changelog.heads()
        return [hex(x) for x in h]

    def setbranch(self, branch, pbranches):
        if not self.clonebranches:
            return

        setbranch = (branch != self.lastbranch)
        self.lastbranch = branch
        if not branch:
            branch = 'default'
        pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
        pbranch = pbranches and pbranches[0][1] or 'default'

        branchpath = os.path.join(self.path, branch)
        if setbranch:
            self.after()
            try:
                self.repo = hg.repository(self.ui, branchpath)
            except Exception:
                self.repo = hg.repository(self.ui, branchpath, create=True)
            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 Exception:
                missings.setdefault(b[1], []).append(b[0])

        if missings:
            self.after()
            for pbranch, heads in sorted(missings.iteritems()):
                pbranchpath = os.path.join(self.path, pbranch)
                prepo = hg.peer(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()

    def _rewritetags(self, source, revmap, data):
        fp = cStringIO.StringIO()
        for line in data.splitlines():
            s = line.split(' ', 1)
            if len(s) != 2:
                continue
            revid = revmap.get(source.lookuprev(s[0]))
            if not revid:
                continue
            fp.write('%s %s\n' % (revid, s[1]))
        return fp.getvalue()

    def putcommit(self, files, copies, parents, commit, source, revmap):

        files = dict(files)
        def getfilectx(repo, memctx, f):
            v = files[f]
            data, mode = source.getfile(f, v)
            if f == '.hgtags':
                data = self._rewritetags(source, revmap, data)
            return context.memfilectx(f, data, 'l' in mode, 'x' in mode,
                                      copies.get(f))

        pl = []
        for p in parents:
            if p not in pl:
                pl.append(p)
        parents = pl
        nparents = len(parents)
        if self.filemapmode and nparents == 1:
            m1node = self.repo.changelog.read(bin(parents[0]))[0]
            parent = parents[0]

        if len(parents) < 2:
            parents.append(nullid)
        if len(parents) < 2:
            parents.append(nullid)
        p2 = parents.pop(0)

        text = commit.desc
        extra = commit.extra.copy()
        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)
            ctx = context.memctx(self.repo, (p1, p2), text, files.keys(),
                                 getfilectx, commit.author, commit.date, extra)
            self.repo.commitctx(ctx)
            text = "(octopus merge fixup)\n"
            p2 = hex(self.repo.changelog.tip())

        if self.filemapmode and nparents == 1:
            man = self.repo.manifest
            mnode = self.repo.changelog.read(bin(p2))[0]
            closed = 'close' in commit.extra
            if not closed and not man.cmp(m1node, man.revision(mnode)):
                self.ui.status(_("filtering out empty revision\n"))
                self.repo.rollback(force=True)
                return parent
        return p2

    def puttags(self, tags):
        try:
            parentctx = self.repo[self.tagsbranch]
            tagparent = parentctx.node()
        except error.RepoError:
            parentctx = None
            tagparent = nullid

        try:
            oldlines = sorted(parentctx['.hgtags'].data().splitlines(True))
        except Exception:
            oldlines = []

        newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
        if newlines == oldlines:
            return None, None
        data = "".join(newlines)
        def getfilectx(repo, memctx, f):
            return context.memfilectx(f, data, False, False, None)

        self.ui.status(_("updating tags\n"))
        date = "%s 0" % int(time.mktime(time.gmtime()))
        extra = {'branch': self.tagsbranch}
        ctx = context.memctx(self.repo, (tagparent, None), "update tags",
                             [".hgtags"], getfilectx, "convert-repo", date,
                             extra)
        self.repo.commitctx(ctx)
        return hex(self.repo.changelog.tip()), hex(tagparent)

    def setfilemapmode(self, active):
        self.filemapmode = active

    def putbookmarks(self, updatedbookmark):
        if not len(updatedbookmark):
            return

        self.ui.status(_("updating bookmarks\n"))
        destmarks = self.repo._bookmarks
        for bookmark in updatedbookmark:
            destmarks[bookmark] = bin(updatedbookmark[bookmark])
        destmarks.write()

    def hascommit(self, rev):
        if rev not in self.repo and self.clonebranches:
            raise util.Abort(_('revision %s not found in destination '
                               'repository (lookups with clonebranches=true '
                               'are not implemented)') % rev)
        return rev in self.repo

class mercurial_source(converter_source):
    def __init__(self, ui, path, rev=None):
        converter_source.__init__(self, ui, path, rev)
        self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
        self.ignored = set()
        self.saverev = ui.configbool('convert', 'hg.saverev', False)
        try:
            self.repo = hg.repository(self.ui, path)
            # try to provoke an exception if this isn't really a hg
            # repo, but some other bogus compatible-looking url
            if not self.repo.local():
                raise error.RepoError
        except error.RepoError:
            ui.traceback()
            raise NoRepo(_("%s is not a local Mercurial repository") % path)
        self.lastrev = None
        self.lastctx = None
        self._changescache = None
        self.convertfp = None
        # Restrict converted revisions to startrev descendants
        startnode = ui.config('convert', 'hg.startrev')
        if startnode is not None:
            try:
                startnode = self.repo.lookup(startnode)
            except error.RepoError:
                raise util.Abort(_('%s is not a valid start revision')
                                 % startnode)
            startrev = self.repo.changelog.rev(startnode)
            children = {startnode: 1}
            for rev in self.repo.changelog.descendants([startrev]):
                children[self.repo.changelog.node(rev)] = 1
            self.keep = children.__contains__
        else:
            self.keep = util.always

    def changectx(self, rev):
        if self.lastrev != rev:
            self.lastctx = self.repo[rev]
            self.lastrev = rev
        return self.lastctx

    def parents(self, ctx):
        return [p for p in ctx.parents() if p and self.keep(p.node())]

    def getheads(self):
        if self.rev:
            heads = [self.repo[self.rev].node()]
        else:
            heads = self.repo.heads()
        return [hex(h) for h in heads if self.keep(h)]

    def getfile(self, name, rev):
        try:
            fctx = self.changectx(rev)[name]
            return fctx.data(), fctx.flags()
        except error.LookupError, err:
            raise IOError(err)

    def getchanges(self, rev):
        ctx = self.changectx(rev)
        parents = self.parents(ctx)
        if not parents:
            files = sorted(ctx.manifest())
            # getcopies() is not needed for roots, but it is a simple way to
            # detect missing revlogs and abort on errors or populate
            # self.ignored
            self.getcopies(ctx, parents, files)
            return [(f, rev) for f in files if f not in self.ignored], {}
        if self._changescache and self._changescache[0] == rev:
            m, a, r = self._changescache[1]
        else:
            m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
        # getcopies() detects missing revlogs early, run it before
        # filtering the changes.
        copies = self.getcopies(ctx, parents, m + a)
        changes = [(name, rev) for name in m + a + r
                   if name not in self.ignored]
        return sorted(changes), copies

    def getcopies(self, ctx, parents, files):
        copies = {}
        for name in files:
            if name in self.ignored:
                continue
            try:
                copysource, copynode = ctx.filectx(name).renamed()
                if copysource in self.ignored or not self.keep(copynode):
                    continue
                # Ignore copy sources not in parent revisions
                found = False
                for p in parents:
                    if copysource in p:
                        found = True
                        break
                if not found:
                    continue
                copies[name] = copysource
            except TypeError:
                pass
            except error.LookupError, e:
                if not self.ignoreerrors:
                    raise
                self.ignored.add(name)
                self.ui.warn(_('ignoring: %s\n') % e)
        return copies

    def getcommit(self, rev):
        ctx = self.changectx(rev)
        parents = [p.hex() for p in self.parents(ctx)]
        if self.saverev:
            crev = rev
        else:
            crev = None
        return commit(author=ctx.user(),
                      date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
                      desc=ctx.description(), rev=crev, parents=parents,
                      branch=ctx.branch(), extra=ctx.extra(),
                      sortkey=ctx.rev())

    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
                     if self.keep(node)])

    def getchangedfiles(self, rev, i):
        ctx = self.changectx(rev)
        parents = self.parents(ctx)
        if not parents and i is None:
            i = 0
            changes = [], ctx.manifest().keys(), []
        else:
            i = i or 0
            changes = self.repo.status(parents[i].node(), ctx.node())[:3]
        changes = [[f for f in l if f not in self.ignored] for l in changes]

        if i == 0:
            self._changescache = (rev, changes)

        return changes[0] + changes[1] + changes[2]

    def converted(self, rev, destrev):
        if self.convertfp is None:
            self.convertfp = open(self.repo.join('shamap'), 'a')
        self.convertfp.write('%s %s\n' % (destrev, rev))
        self.convertfp.flush()

    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')

    def hasnativeorder(self):
        return True

    def hasnativeclose(self):
        return True

    def lookuprev(self, rev):
        try:
            return hex(self.repo.lookup(rev))
        except error.RepoError:
            return None

    def getbookmarks(self):
        return bookmarks.listbookmarks(self.repo)
