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 |
|
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, |
|
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