view mercurial/filemerge.py @ 6003:7855b88ba838

filemerge: pull file-merging code into its own module
author Matt Mackall <mpm@selenic.com>
date Sun, 03 Feb 2008 19:29:05 -0600
parents
children 5af5f0f9d724
line wrap: on
line source

# filemerge.py - file-level merge handling for Mercurial
#
# Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.

from node import *
from i18n import _
import util, os, tempfile, context

def filemerge(repo, fw, fd, fo, wctx, mctx):
    """perform a 3-way merge in the working directory

    fw = original filename in the working directory
    fd = destination filename in the working directory
    fo = filename in other parent
    wctx, mctx = working and merge changecontexts
    """

    def temp(prefix, ctx):
        pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
        (fd, name) = tempfile.mkstemp(prefix=pre)
        data = repo.wwritedata(ctx.path(), ctx.data())
        f = os.fdopen(fd, "wb")
        f.write(data)
        f.close()
        return name

    fcm = wctx.filectx(fw)
    fcmdata = wctx.filectx(fd).data()
    fco = mctx.filectx(fo)

    if not fco.cmp(fcmdata): # files identical?
        return None

    fca = fcm.ancestor(fco)
    if not fca:
        fca = repo.filectx(fw, fileid=nullrev)
    a = repo.wjoin(fd)
    b = temp("base", fca)
    c = temp("other", fco)

    if fw != fo:
        repo.ui.status(_("merging %s and %s\n") % (fw, fo))
    else:
        repo.ui.status(_("merging %s\n") % fw)

    repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))

    cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
           or "hgmerge")
    r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
                    environ={'HG_FILE': fd,
                             'HG_MY_NODE': str(wctx.parents()[0]),
                             'HG_OTHER_NODE': str(mctx),
                             'HG_MY_ISLINK': fcm.islink(),
                             'HG_OTHER_ISLINK': fco.islink(),
                             'HG_BASE_ISLINK': fca.islink(),})
    if r:
        repo.ui.warn(_("merging %s failed!\n") % fd)

    os.unlink(b)
    os.unlink(c)
    return r