# HG changeset patch # User Matt Mackall # Date 2008-02-04 01:29:05 # Node ID 7855b88ba838c8092d28c8d0c5eb4c6bdfb6a7ec # Parent abd66eb0889e3efaca4f960e0eacd719c18880dd filemerge: pull file-merging code into its own module diff --git a/hgext/imerge.py b/hgext/imerge.py --- a/hgext/imerge.py +++ b/hgext/imerge.py @@ -7,7 +7,8 @@ imerge - interactive merge from mercurial.i18n import _ from mercurial.node import * -from mercurial import commands, cmdutil, dispatch, fancyopts, hg, merge, util +from mercurial import commands, cmdutil, dispatch, fancyopts +from mercurial import hg, filemerge, util import os, tarfile class InvalidStateFileException(Exception): pass @@ -126,7 +127,7 @@ class Imerge(object): self.wctx._parents.pop() try: # TODO: we should probably revert the file if merge fails - return merge.filemerge(self.repo, fn, fd, fo, self.wctx, p2) + return filemerge.filemerge(self.repo, fn, fd, fo, self.wctx, p2) finally: self.wctx._parents.append(p2) if realmerge: @@ -135,13 +136,13 @@ class Imerge(object): del os.environ['HGMERGE'] def start(self, rev=None): - _filemerge = merge.filemerge - def filemerge(repo, fw, fd, fo, wctx, mctx): + _filemerge = filemerge.filemerge + def filemerge_(repo, fw, fd, fo, wctx, mctx): self.conflicts[fw] = (fd, fo) - merge.filemerge = filemerge + filemerge.filemerge = filemerge_ commands.merge(self.ui, self.repo, rev=rev) - merge.filemerge = _filemerge + filemerge.filemerge = _filemerge self.wctx = self.repo.workingctx() self.save() diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py new file mode 100644 --- /dev/null +++ b/mercurial/filemerge.py @@ -0,0 +1,65 @@ +# filemerge.py - file-level merge handling for Mercurial +# +# Copyright 2006, 2007, 2008 Matt Mackall +# +# 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 diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -7,62 +7,7 @@ from node import * from i18n import _ -import errno, util, os, tempfile, context, heapq - -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 +import errno, util, os, heapq, filemerge def checkunknown(wctx, mctx): "check for collisions between unknown files and files in mctx" @@ -514,7 +459,7 @@ def applyupdates(repo, action, wctx, mct removed += 1 elif m == "m": # merge f2, fd, flags, move = a[2:] - r = filemerge(repo, f, fd, f2, wctx, mctx) + r = filemerge.filemerge(repo, f, fd, f2, wctx, mctx) if r > 0: unresolved += 1 else: