##// END OF EJS Templates
filemerge: pull file-merging code into its own module
Matt Mackall -
r6003:7855b88b default
parent child Browse files
Show More
@@ -0,0 +1,65 b''
1 # filemerge.py - file-level merge handling for Mercurial
2 #
3 # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
4 #
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
7
8 from node import *
9 from i18n import _
10 import util, os, tempfile, context
11
12 def filemerge(repo, fw, fd, fo, wctx, mctx):
13 """perform a 3-way merge in the working directory
14
15 fw = original filename in the working directory
16 fd = destination filename in the working directory
17 fo = filename in other parent
18 wctx, mctx = working and merge changecontexts
19 """
20
21 def temp(prefix, ctx):
22 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
23 (fd, name) = tempfile.mkstemp(prefix=pre)
24 data = repo.wwritedata(ctx.path(), ctx.data())
25 f = os.fdopen(fd, "wb")
26 f.write(data)
27 f.close()
28 return name
29
30 fcm = wctx.filectx(fw)
31 fcmdata = wctx.filectx(fd).data()
32 fco = mctx.filectx(fo)
33
34 if not fco.cmp(fcmdata): # files identical?
35 return None
36
37 fca = fcm.ancestor(fco)
38 if not fca:
39 fca = repo.filectx(fw, fileid=nullrev)
40 a = repo.wjoin(fd)
41 b = temp("base", fca)
42 c = temp("other", fco)
43
44 if fw != fo:
45 repo.ui.status(_("merging %s and %s\n") % (fw, fo))
46 else:
47 repo.ui.status(_("merging %s\n") % fw)
48
49 repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
50
51 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
52 or "hgmerge")
53 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
54 environ={'HG_FILE': fd,
55 'HG_MY_NODE': str(wctx.parents()[0]),
56 'HG_OTHER_NODE': str(mctx),
57 'HG_MY_ISLINK': fcm.islink(),
58 'HG_OTHER_ISLINK': fco.islink(),
59 'HG_BASE_ISLINK': fca.islink(),})
60 if r:
61 repo.ui.warn(_("merging %s failed!\n") % fd)
62
63 os.unlink(b)
64 os.unlink(c)
65 return r
@@ -7,7 +7,8 b' imerge - interactive merge'
7
7
8 from mercurial.i18n import _
8 from mercurial.i18n import _
9 from mercurial.node import *
9 from mercurial.node import *
10 from mercurial import commands, cmdutil, dispatch, fancyopts, hg, merge, util
10 from mercurial import commands, cmdutil, dispatch, fancyopts
11 from mercurial import hg, filemerge, util
11 import os, tarfile
12 import os, tarfile
12
13
13 class InvalidStateFileException(Exception): pass
14 class InvalidStateFileException(Exception): pass
@@ -126,7 +127,7 b' class Imerge(object):'
126 self.wctx._parents.pop()
127 self.wctx._parents.pop()
127 try:
128 try:
128 # TODO: we should probably revert the file if merge fails
129 # TODO: we should probably revert the file if merge fails
129 return merge.filemerge(self.repo, fn, fd, fo, self.wctx, p2)
130 return filemerge.filemerge(self.repo, fn, fd, fo, self.wctx, p2)
130 finally:
131 finally:
131 self.wctx._parents.append(p2)
132 self.wctx._parents.append(p2)
132 if realmerge:
133 if realmerge:
@@ -135,13 +136,13 b' class Imerge(object):'
135 del os.environ['HGMERGE']
136 del os.environ['HGMERGE']
136
137
137 def start(self, rev=None):
138 def start(self, rev=None):
138 _filemerge = merge.filemerge
139 _filemerge = filemerge.filemerge
139 def filemerge(repo, fw, fd, fo, wctx, mctx):
140 def filemerge_(repo, fw, fd, fo, wctx, mctx):
140 self.conflicts[fw] = (fd, fo)
141 self.conflicts[fw] = (fd, fo)
141
142
142 merge.filemerge = filemerge
143 filemerge.filemerge = filemerge_
143 commands.merge(self.ui, self.repo, rev=rev)
144 commands.merge(self.ui, self.repo, rev=rev)
144 merge.filemerge = _filemerge
145 filemerge.filemerge = _filemerge
145
146
146 self.wctx = self.repo.workingctx()
147 self.wctx = self.repo.workingctx()
147 self.save()
148 self.save()
@@ -7,62 +7,7 b''
7
7
8 from node import *
8 from node import *
9 from i18n import _
9 from i18n import _
10 import errno, util, os, tempfile, context, heapq
10 import errno, util, os, heapq, filemerge
11
12 def filemerge(repo, fw, fd, fo, wctx, mctx):
13 """perform a 3-way merge in the working directory
14
15 fw = original filename in the working directory
16 fd = destination filename in the working directory
17 fo = filename in other parent
18 wctx, mctx = working and merge changecontexts
19 """
20
21 def temp(prefix, ctx):
22 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
23 (fd, name) = tempfile.mkstemp(prefix=pre)
24 data = repo.wwritedata(ctx.path(), ctx.data())
25 f = os.fdopen(fd, "wb")
26 f.write(data)
27 f.close()
28 return name
29
30 fcm = wctx.filectx(fw)
31 fcmdata = wctx.filectx(fd).data()
32 fco = mctx.filectx(fo)
33
34 if not fco.cmp(fcmdata): # files identical?
35 return None
36
37 fca = fcm.ancestor(fco)
38 if not fca:
39 fca = repo.filectx(fw, fileid=nullrev)
40 a = repo.wjoin(fd)
41 b = temp("base", fca)
42 c = temp("other", fco)
43
44 if fw != fo:
45 repo.ui.status(_("merging %s and %s\n") % (fw, fo))
46 else:
47 repo.ui.status(_("merging %s\n") % fw)
48
49 repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
50
51 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
52 or "hgmerge")
53 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
54 environ={'HG_FILE': fd,
55 'HG_MY_NODE': str(wctx.parents()[0]),
56 'HG_OTHER_NODE': str(mctx),
57 'HG_MY_ISLINK': fcm.islink(),
58 'HG_OTHER_ISLINK': fco.islink(),
59 'HG_BASE_ISLINK': fca.islink(),})
60 if r:
61 repo.ui.warn(_("merging %s failed!\n") % fd)
62
63 os.unlink(b)
64 os.unlink(c)
65 return r
66
11
67 def checkunknown(wctx, mctx):
12 def checkunknown(wctx, mctx):
68 "check for collisions between unknown files and files in mctx"
13 "check for collisions between unknown files and files in mctx"
@@ -514,7 +459,7 b' def applyupdates(repo, action, wctx, mct'
514 removed += 1
459 removed += 1
515 elif m == "m": # merge
460 elif m == "m": # merge
516 f2, fd, flags, move = a[2:]
461 f2, fd, flags, move = a[2:]
517 r = filemerge(repo, f, fd, f2, wctx, mctx)
462 r = filemerge.filemerge(repo, f, fd, f2, wctx, mctx)
518 if r > 0:
463 if r > 0:
519 unresolved += 1
464 unresolved += 1
520 else:
465 else:
General Comments 0
You need to be logged in to leave comments. Login now