annotate mercurial/merge.py @ 5909:f45f7390c1c5

strip: calculate list of extra nodes to save and pass it to changegroupsubset When we remove revision N from the repository, all revisions >= N are affected: either it's a descendant from N and will also be removed, or it's not a descendant of N and will be renumbered. As a consequence, we have to (at least temporarily) remove all filelog and manifest revisions that have a linkrev >= N, readding some of them later. Unfortunately, it's possible to have a revlog with two revisions r1 and r2 such that r1 < r2, but linkrev(r1) > linkrev(r2). If we try to strip revision linkrev(r1) from the repository, we'll also lose revision r2 when we truncate this revlog. We already use changegroupsubset to create a temporary changegroup containing the revisions that have to be restored, but that function is unable to detect that we also wanted to save the r2 in the case above. So we manually calculate these extra nodes and pass it to changegroupsubset. This should fix issue764.
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Sat, 19 Jan 2008 18:01:16 -0200
parents c704b03884ef
children 7855b88ba838
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1 # merge.py - directory-level update/merge handling for Mercurial
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
2 #
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4633
diff changeset
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
4 #
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
6 # of the GNU General Public License, incorporated herein by reference.
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
8 from node import *
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
9 from i18n import _
5096
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
10 import errno, util, os, tempfile, context, heapq
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
11
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
12 def filemerge(repo, fw, fd, fo, wctx, mctx):
3211
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
13 """perform a 3-way merge in the working directory
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
14
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
15 fw = original filename in the working directory
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
16 fd = destination filename in the working directory
3211
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
17 fo = filename in other parent
3297
69b9471f26bb merge: pass contexts to applyupdates
Matt Mackall <mpm@selenic.com>
parents: 3296
diff changeset
18 wctx, mctx = working and merge changecontexts
3211
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
19 """
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
20
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
21 def temp(prefix, ctx):
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
22 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
23 (fd, name) = tempfile.mkstemp(prefix=pre)
4005
656e06eebda7 replace filehandle version of wwrite with wwritedata
Matt Mackall <mpm@selenic.com>
parents: 3891
diff changeset
24 data = repo.wwritedata(ctx.path(), ctx.data())
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
25 f = os.fdopen(fd, "wb")
4005
656e06eebda7 replace filehandle version of wwrite with wwritedata
Matt Mackall <mpm@selenic.com>
parents: 3891
diff changeset
26 f.write(data)
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
27 f.close()
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
28 return name
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
29
3299
e7abcf3a7c5f filemerge: use contexts rather than my and other
Matt Mackall <mpm@selenic.com>
parents: 3297
diff changeset
30 fcm = wctx.filectx(fw)
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
31 fcmdata = wctx.filectx(fd).data()
3299
e7abcf3a7c5f filemerge: use contexts rather than my and other
Matt Mackall <mpm@selenic.com>
parents: 3297
diff changeset
32 fco = mctx.filectx(fo)
3311
966632304dde merge: shortcircuit filemerge for identical files
Matt Mackall <mpm@selenic.com>
parents: 3309
diff changeset
33
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
34 if not fco.cmp(fcmdata): # files identical?
3400
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
35 return None
3311
966632304dde merge: shortcircuit filemerge for identical files
Matt Mackall <mpm@selenic.com>
parents: 3309
diff changeset
36
3211
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
37 fca = fcm.ancestor(fco)
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
38 if not fca:
3578
3b4e00cba57a Define and use nullrev (revision of nullid) instead of -1.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3442
diff changeset
39 fca = repo.filectx(fw, fileid=nullrev)
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
40 a = repo.wjoin(fd)
3211
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
41 b = temp("base", fca)
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
42 c = temp("other", fco)
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
43
3311
966632304dde merge: shortcircuit filemerge for identical files
Matt Mackall <mpm@selenic.com>
parents: 3309
diff changeset
44 if fw != fo:
966632304dde merge: shortcircuit filemerge for identical files
Matt Mackall <mpm@selenic.com>
parents: 3309
diff changeset
45 repo.ui.status(_("merging %s and %s\n") % (fw, fo))
966632304dde merge: shortcircuit filemerge for identical files
Matt Mackall <mpm@selenic.com>
parents: 3309
diff changeset
46 else:
966632304dde merge: shortcircuit filemerge for identical files
Matt Mackall <mpm@selenic.com>
parents: 3309
diff changeset
47 repo.ui.status(_("merging %s\n") % fw)
966632304dde merge: shortcircuit filemerge for identical files
Matt Mackall <mpm@selenic.com>
parents: 3309
diff changeset
48
3211
3fd098e0902d merge: extend file merge function for renames
Matt Mackall <mpm@selenic.com>
parents: 3169
diff changeset
49 repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
50
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
51 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
52 or "hgmerge")
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
53 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
54 environ={'HG_FILE': fd,
3297
69b9471f26bb merge: pass contexts to applyupdates
Matt Mackall <mpm@selenic.com>
parents: 3296
diff changeset
55 'HG_MY_NODE': str(wctx.parents()[0]),
5390
36c46e20976a merge: provide *_ISLINK environment vars to merge helper
Patrick Mezard <pmezard@gmail.com>
parents: 5371
diff changeset
56 'HG_OTHER_NODE': str(mctx),
36c46e20976a merge: provide *_ISLINK environment vars to merge helper
Patrick Mezard <pmezard@gmail.com>
parents: 5371
diff changeset
57 'HG_MY_ISLINK': fcm.islink(),
36c46e20976a merge: provide *_ISLINK environment vars to merge helper
Patrick Mezard <pmezard@gmail.com>
parents: 5371
diff changeset
58 'HG_OTHER_ISLINK': fco.islink(),
36c46e20976a merge: provide *_ISLINK environment vars to merge helper
Patrick Mezard <pmezard@gmail.com>
parents: 5371
diff changeset
59 'HG_BASE_ISLINK': fca.islink(),})
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
60 if r:
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
61 repo.ui.warn(_("merging %s failed!\n") % fd)
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
62
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
63 os.unlink(b)
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
64 os.unlink(c)
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
65 return r
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
66
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
67 def checkunknown(wctx, mctx):
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
68 "check for collisions between unknown files and files in mctx"
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
69 man = mctx.manifest()
3218
8d4855fd9d7b merge: use new working context object in update
Matt Mackall <mpm@selenic.com>
parents: 3212
diff changeset
70 for f in wctx.unknown():
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
71 if f in man:
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
72 if mctx.filectx(f).cmp(wctx.filectx(f).data()):
5670
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
73 raise util.Abort(_("untracked file in working directory differs"
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
74 " from file in requested revision: '%s'")
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
75 % f)
3107
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
76
3785
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
77 def checkcollision(mctx):
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
78 "check for case folding collisions in the destination context"
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
79 folded = {}
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
80 for fn in mctx.manifest():
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
81 fold = fn.lower()
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
82 if fold in folded:
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
83 raise util.Abort(_("case-folding collision between %s and %s")
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
84 % (fn, folded[fold]))
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
85 folded[fold] = fn
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
86
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
87 def forgetremoved(wctx, mctx):
3107
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
88 """
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
89 Forget removed files
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
90
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
91 If we're jumping between revisions (as opposed to merging), and if
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
92 neither the working directory nor the target rev has the file,
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
93 then we need to remove it from the dirstate, to prevent the
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
94 dirstate from listing the file when it is no longer in the
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
95 manifest.
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
96 """
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
97
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
98 action = []
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
99 man = mctx.manifest()
3218
8d4855fd9d7b merge: use new working context object in update
Matt Mackall <mpm@selenic.com>
parents: 3212
diff changeset
100 for f in wctx.deleted() + wctx.removed():
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
101 if f not in man:
3107
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
102 action.append((f, "f"))
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
103
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
104 return action
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
105
3371
8c36b33a27c7 merge: turn followcopies on by default
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
106 def findcopies(repo, m1, m2, ma, limit):
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
107 """
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
108 Find moves and copies between m1 and m2 back to limit linkrev
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
109 """
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
110
4400
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
111 def nonoverlap(d1, d2, d3):
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
112 "Return list of elements in d1 not in d2 or d3"
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
113 l = [d for d in d1 if d not in d3 and d not in d2]
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
114 l.sort()
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
115 return l
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
116
4397
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
117 def dirname(f):
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
118 s = f.rfind("/")
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
119 if s == -1:
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
120 return ""
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
121 return f[:s]
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
122
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
123 def dirs(files):
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
124 d = {}
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
125 for f in files:
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
126 f = dirname(f)
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
127 while f not in d:
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
128 d[f] = True
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
129 f = dirname(f)
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
130 return d
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
131
4416
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
132 wctx = repo.workingctx()
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
133
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
134 def makectx(f, n):
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
135 if len(n) == 20:
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
136 return repo.filectx(f, fileid=n)
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
137 return wctx.filectx(f)
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
138 ctx = util.cachefunc(makectx)
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
139
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
140 def findold(fctx):
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
141 "find files that path was copied from, back to linkrev limit"
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
142 old = {}
4350
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
143 seen = {}
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
144 orig = fctx.path()
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
145 visit = [fctx]
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
146 while visit:
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
147 fc = visit.pop()
4350
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
148 s = str(fc)
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
149 if s in seen:
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
150 continue
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
151 seen[s] = 1
3875
c0a12e6441a5 Fix copy detection corner case
Matt Mackall <mpm@selenic.com>
parents: 3862
diff changeset
152 if fc.path() != orig and fc.path() not in old:
c0a12e6441a5 Fix copy detection corner case
Matt Mackall <mpm@selenic.com>
parents: 3862
diff changeset
153 old[fc.path()] = 1
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
154 if fc.rev() < limit:
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
155 continue
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
156 visit += fc.parents()
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
157
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
158 old = old.keys()
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
159 old.sort()
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
160 return old
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
161
4400
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
162 copy = {}
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
163 fullcopy = {}
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
164 diverge = {}
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
165
4884
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
166 def checkcopies(c, man, aman):
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
167 '''check possible copies for filectx c'''
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
168 for of in findold(c):
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
169 fullcopy[c.path()] = of # remember for dir rename detection
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
170 if of not in man: # original file not in other manifest?
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
171 if of in ma:
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
172 diverge.setdefault(of, []).append(c.path())
4304
4787e2b0dd03 merge: fix a bug where copies were ignored
Matt Mackall <mpm@selenic.com>
parents: 4179
diff changeset
173 continue
4884
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
174 # if the original file is unchanged on the other branch,
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
175 # no merge needed
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
176 if man[of] == aman.get(of):
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
177 continue
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
178 c2 = ctx(of, man[of])
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
179 ca = c.ancestor(c2)
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
180 if not ca: # unrelated?
4304
4787e2b0dd03 merge: fix a bug where copies were ignored
Matt Mackall <mpm@selenic.com>
parents: 4179
diff changeset
181 continue
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
182 # named changed on only one side?
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
183 if ca.path() == c.path() or ca.path() == c2.path():
5433
f9b0e4f023c4 findcopies: fix rename bug
Matt Mackall <mpm@selenic.com>
parents: 5096
diff changeset
184 if c == ca and c2 == ca: # no merge needed, ignore copy
4304
4787e2b0dd03 merge: fix a bug where copies were ignored
Matt Mackall <mpm@selenic.com>
parents: 4179
diff changeset
185 continue
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
186 copy[c.path()] = of
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
187
3371
8c36b33a27c7 merge: turn followcopies on by default
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
188 if not repo.ui.configbool("merge", "followcopies", True):
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
189 return {}, {}
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
190
3160
1839e6e91c3a findcopies: shortcut for empty working dir
Matt Mackall <mpm@selenic.com>
parents: 3155
diff changeset
191 # avoid silly behavior for update from empty dir
3731
b4af5f92e04b merge: move check for empty ancestor into findcopies
Matt Mackall <mpm@selenic.com>
parents: 3730
diff changeset
192 if not m1 or not m2 or not ma:
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
193 return {}, {}
3160
1839e6e91c3a findcopies: shortcut for empty working dir
Matt Mackall <mpm@selenic.com>
parents: 3155
diff changeset
194
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
195 repo.ui.debug(_(" searching for copies back to rev %d\n") % limit)
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
196
3371
8c36b33a27c7 merge: turn followcopies on by default
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
197 u1 = nonoverlap(m1, m2, ma)
8c36b33a27c7 merge: turn followcopies on by default
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
198 u2 = nonoverlap(m2, m1, ma)
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
199
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
200 if u1:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
201 repo.ui.debug(_(" unmatched files in local:\n %s\n")
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
202 % "\n ".join(u1))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
203 if u2:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
204 repo.ui.debug(_(" unmatched files in other:\n %s\n")
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
205 % "\n ".join(u2))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
206
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
207 for f in u1:
4884
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
208 checkcopies(ctx(f, m1[f]), m2, ma)
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
209
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
210 for f in u2:
4884
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
211 checkcopies(ctx(f, m2[f]), m1, ma)
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
212
5857
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
213 diverge2 = {}
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
214 for of, fl in diverge.items():
5857
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
215 if len(fl) == 1:
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
216 del diverge[of] # not actually divergent
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
217 else:
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
218 diverge2.update(dict.fromkeys(fl)) # reverse map for below
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
219
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
220 if fullcopy:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
221 repo.ui.debug(_(" all copies found (* = to merge, ! = divergent):\n"))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
222 for f in fullcopy:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
223 note = ""
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
224 if f in copy: note += "*"
5857
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
225 if f in diverge2: note += "!"
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
226 repo.ui.debug(_(" %s -> %s %s\n") % (f, fullcopy[f], note))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
227
5857
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
228 del diverge2
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
229
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
230 if not fullcopy or not repo.ui.configbool("merge", "followdirs", True):
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
231 return copy, diverge
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
232
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
233 repo.ui.debug(_(" checking for directory renames\n"))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
234
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
235 # generate a directory move map
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
236 d1, d2 = dirs(m1), dirs(m2)
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
237 invalid = {}
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
238 dirmove = {}
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
239
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
240 # examine each file copy for a potential directory move, which is
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
241 # when all the files in a directory are moved to a new directory
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
242 for dst, src in fullcopy.items():
4397
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
243 dsrc, ddst = dirname(src), dirname(dst)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
244 if dsrc in invalid:
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
245 # already seen to be uninteresting
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
246 continue
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
247 elif dsrc in d1 and ddst in d1:
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
248 # directory wasn't entirely moved locally
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
249 invalid[dsrc] = True
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
250 elif dsrc in d2 and ddst in d2:
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
251 # directory wasn't entirely moved remotely
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
252 invalid[dsrc] = True
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
253 elif dsrc in dirmove and dirmove[dsrc] != ddst:
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
254 # files from the same directory moved to two different places
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
255 invalid[dsrc] = True
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
256 else:
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
257 # looks good so far
4115
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
258 dirmove[dsrc + "/"] = ddst + "/"
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
259
4398
3b7e284b8f28 merge: expand and simplify the invalid handling for directory moves
Matt Mackall <mpm@selenic.com>
parents: 4397
diff changeset
260 for i in invalid:
3b7e284b8f28 merge: expand and simplify the invalid handling for directory moves
Matt Mackall <mpm@selenic.com>
parents: 4397
diff changeset
261 if i in dirmove:
3b7e284b8f28 merge: expand and simplify the invalid handling for directory moves
Matt Mackall <mpm@selenic.com>
parents: 4397
diff changeset
262 del dirmove[i]
3b7e284b8f28 merge: expand and simplify the invalid handling for directory moves
Matt Mackall <mpm@selenic.com>
parents: 4397
diff changeset
263
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
264 del d1, d2, invalid
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
265
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
266 if not dirmove:
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
267 return copy, diverge
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
268
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
269 for d in dirmove:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
270 repo.ui.debug(_(" dir %s -> %s\n") % (d, dirmove[d]))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
271
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
272 # check unaccounted nonoverlapping files against directory moves
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
273 for f in u1 + u2:
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
274 if f not in fullcopy:
4115
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
275 for d in dirmove:
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
276 if f.startswith(d):
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
277 # new file added in a directory that was moved, move it
4115
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
278 copy[f] = dirmove[d] + f[len(d):]
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
279 repo.ui.debug(_(" file %s -> %s\n") % (f, copy[f]))
4115
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
280 break
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
281
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
282 return copy, diverge
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
283
5096
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
284 def symmetricdifference(repo, rev1, rev2):
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
285 """symmetric difference of the sets of ancestors of rev1 and rev2
5433
f9b0e4f023c4 findcopies: fix rename bug
Matt Mackall <mpm@selenic.com>
parents: 5096
diff changeset
286
5096
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
287 I.e. revisions that are ancestors of rev1 or rev2, but not both.
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
288 """
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
289 # basic idea:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
290 # - mark rev1 and rev2 with different colors
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
291 # - walk the graph in topological order with the help of a heap;
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
292 # for each revision r:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
293 # - if r has only one color, we want to return it
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
294 # - add colors[r] to its parents
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
295 #
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
296 # We keep track of the number of revisions in the heap that
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
297 # we may be interested in. We stop walking the graph as soon
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
298 # as this number reaches 0.
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
299 WHITE = 1
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
300 BLACK = 2
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
301 ALLCOLORS = WHITE | BLACK
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
302 colors = {rev1: WHITE, rev2: BLACK}
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
303
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
304 cl = repo.changelog
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
305
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
306 visit = [-rev1, -rev2]
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
307 heapq.heapify(visit)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
308 n_wanted = len(visit)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
309 ret = []
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
310
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
311 while n_wanted:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
312 r = -heapq.heappop(visit)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
313 wanted = colors[r] != ALLCOLORS
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
314 n_wanted -= wanted
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
315 if wanted:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
316 ret.append(r)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
317
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
318 for p in cl.parentrevs(r):
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
319 if p == nullrev:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
320 continue
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
321 if p not in colors:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
322 # first time we see p; add it to visit
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
323 n_wanted += wanted
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
324 colors[p] = colors[r]
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
325 heapq.heappush(visit, -p)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
326 elif colors[p] != ALLCOLORS and colors[p] != colors[r]:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
327 # at first we thought we wanted p, but now
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
328 # we know we don't really want it
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
329 n_wanted -= 1
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
330 colors[p] |= colors[r]
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
331
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
332 del colors[r]
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
333
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
334 return ret
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
335
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
336 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
337 """
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
338 Merge p1 and p2 with ancestor ma and generate merge action list
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
339
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
340 overwrite = whether we clobber working files
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
341 partial = function to filter file lists
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
342 """
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
343
3314
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
344 repo.ui.note(_("resolving manifests\n"))
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
345 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
346 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
347
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
348 m1 = p1.manifest()
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
349 m2 = p2.manifest()
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
350 ma = pa.manifest()
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
351 backwards = (pa == p2)
3314
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
352 action = []
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
353 copy = {}
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
354 diverge = {}
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
355
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
356 def fmerge(f, f2=None, fa=None):
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
357 """merge flags"""
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
358 if not f2:
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
359 f2 = f
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
360 fa = f
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
361 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
362 if m == n: # flags agree
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
363 return m # unchanged
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
364 if m and n: # flags are set but don't agree
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
365 if not a: # both differ from parent
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
366 r = repo.ui.prompt(
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
367 _(" conflicting flags for %s\n"
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
368 "(n)one, e(x)ec or sym(l)ink?") % f, "[nxl]", "n")
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
369 return r != "n" and r or ''
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
370 if m == a:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
371 return n # changed from m to n
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
372 return m # changed from n to m
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
373 if m and m != a: # changed from a to m
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
374 return m
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
375 if n and n != a: # changed from a to n
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
376 return n
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
377 return '' # flag was cleared
3118
5644a05a608c merge: simplify exec flag handling
Matt Mackall <mpm@selenic.com>
parents: 3117
diff changeset
378
3307
f009a6f12a59 merge: swap file and mode args for act()
Matt Mackall <mpm@selenic.com>
parents: 3306
diff changeset
379 def act(msg, m, f, *args):
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
380 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
3121
2ef0b3aae186 merge: simplify actions with helper function
Matt Mackall <mpm@selenic.com>
parents: 3120
diff changeset
381 action.append((f, m) + args)
2ef0b3aae186 merge: simplify actions with helper function
Matt Mackall <mpm@selenic.com>
parents: 3120
diff changeset
382
3731
b4af5f92e04b merge: move check for empty ancestor into findcopies
Matt Mackall <mpm@selenic.com>
parents: 3730
diff changeset
383 if not (backwards or overwrite):
5096
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
384 rev1 = p1.rev()
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
385 if rev1 is None:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
386 # p1 is a workingctx
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
387 rev1 = p1.parents()[0].rev()
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
388 limit = min(symmetricdifference(repo, rev1, p2.rev()))
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
389 copy, diverge = findcopies(repo, m1, m2, ma, limit)
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
390
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
391 for of, fl in diverge.items():
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
392 act("divergent renames", "dr", of, fl)
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
393
3730
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
394 copied = dict.fromkeys(copy.values())
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
395
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
396 # Compare manifests
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
397 for f, n in m1.iteritems():
3248
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
398 if partial and not partial(f):
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
399 continue
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
400 if f in m2:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
401 if overwrite or backwards:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
402 rflags = m2.flags(f)
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
403 else:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
404 rflags = fmerge(f)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
405 # are files different?
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
406 if n != m2[f]:
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
407 a = ma.get(f, nullid)
5700
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
408 # are we clobbering?
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
409 if overwrite:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
410 act("clobbering", "g", f, rflags)
5700
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
411 # or are we going back in time and clean?
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
412 elif backwards and not n[20:]:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
413 act("reverting", "g", f, rflags)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
414 # are both different from the ancestor?
5700
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
415 elif n != a and m2[f] != a:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
416 act("versions differ", "m", f, f, f, rflags, False)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
417 # is remote's version newer?
5700
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
418 elif m2[f] != a:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
419 act("remote is newer", "g", f, rflags)
3113
d1d1cd5b9484 merge: eliminate confusing queued variable
Matt Mackall <mpm@selenic.com>
parents: 3112
diff changeset
420 # local is newer, not overwrite, check mode bits
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
421 elif m1.flags(f) != rflags:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
422 act("update permissions", "e", f, rflags)
3113
d1d1cd5b9484 merge: eliminate confusing queued variable
Matt Mackall <mpm@selenic.com>
parents: 3112
diff changeset
423 # contents same, check mode bits
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
424 elif m1.flags(f) != rflags:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
425 act("update permissions", "e", f, rflags)
3730
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
426 elif f in copied:
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
427 continue
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
428 elif f in copy:
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
429 f2 = copy[f]
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
430 if f2 not in m2: # directory rename
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
431 act("remote renamed directory to " + f2, "d",
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
432 f, None, f2, m1.flags(f))
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
433 elif f2 in m1: # case 2 A,B/B/B
3730
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
434 act("local copied to " + f2, "m",
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
435 f, f2, f, fmerge(f, f2, f2), False)
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
436 else: # case 4,21 A/B/B
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
437 act("local moved to " + f2, "m",
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
438 f, f2, f, fmerge(f, f2, f2), False)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
439 elif f in ma:
3117
7a635ef25132 merge: simplify tests for local changed/remote deleted
Matt Mackall <mpm@selenic.com>
parents: 3116
diff changeset
440 if n != ma[f] and not overwrite:
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
441 if repo.ui.prompt(
5670
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
442 _(" local changed %s which remote deleted\n"
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
443 "use (c)hanged version or (d)elete?") % f,
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
444 _("[cd]"), _("c")) == _("d"):
3307
f009a6f12a59 merge: swap file and mode args for act()
Matt Mackall <mpm@selenic.com>
parents: 3306
diff changeset
445 act("prompt delete", "r", f)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
446 else:
3307
f009a6f12a59 merge: swap file and mode args for act()
Matt Mackall <mpm@selenic.com>
parents: 3306
diff changeset
447 act("other deleted", "r", f)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
448 else:
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
449 # file is created on branch or in working directory
3120
1c1e59aac82a merge: simplify local created logic
Matt Mackall <mpm@selenic.com>
parents: 3119
diff changeset
450 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
3307
f009a6f12a59 merge: swap file and mode args for act()
Matt Mackall <mpm@selenic.com>
parents: 3306
diff changeset
451 act("remote deleted", "r", f)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
452
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
453 for f, n in m2.iteritems():
3248
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
454 if partial and not partial(f):
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
455 continue
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
456 if f in m1:
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
457 continue
3729
581d20773326 merge: add copied hash to simplify copy logic
Matt Mackall <mpm@selenic.com>
parents: 3728
diff changeset
458 if f in copied:
581d20773326 merge: add copied hash to simplify copy logic
Matt Mackall <mpm@selenic.com>
parents: 3728
diff changeset
459 continue
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
460 if f in copy:
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
461 f2 = copy[f]
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
462 if f2 not in m1: # directory rename
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
463 act("local renamed directory to " + f2, "d",
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
464 None, f, f2, m2.flags(f))
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
465 elif f2 in m2: # rename case 1, A/A,B/A
3730
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
466 act("remote copied to " + f, "m",
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
467 f2, f, f, fmerge(f2, f, f2), False)
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
468 else: # case 3,20 A/B/A
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
469 act("remote moved to " + f, "m",
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
470 f2, f, f, fmerge(f2, f, f2), True)
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
471 elif f in ma:
3116
920f54a2249e merge: more simplification of m2 manifest scanning
Matt Mackall <mpm@selenic.com>
parents: 3115
diff changeset
472 if overwrite or backwards:
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
473 act("recreating", "g", f, m2.flags(f))
3116
920f54a2249e merge: more simplification of m2 manifest scanning
Matt Mackall <mpm@selenic.com>
parents: 3115
diff changeset
474 elif n != ma[f]:
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
475 if repo.ui.prompt(
5670
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
476 _("remote changed %s which local deleted\n"
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
477 "use (c)hanged version or leave (d)eleted?") % f,
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
478 _("[cd]"), _("c")) == _("c"):
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
479 act("prompt recreating", "g", f, m2.flags(f))
3115
bb74f809bc95 merge: reorder tests on m2 items in manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3114
diff changeset
480 else:
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
481 act("remote created", "g", f, m2.flags(f))
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
482
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
483 return action
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
484
3297
69b9471f26bb merge: pass contexts to applyupdates
Matt Mackall <mpm@selenic.com>
parents: 3296
diff changeset
485 def applyupdates(repo, action, wctx, mctx):
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
486 "apply the merge action list to the working directory"
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
487
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
488 updated, merged, removed, unresolved = 0, 0, 0, 0
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
489 action.sort()
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
490 # prescan for copy/renames
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
491 for a in action:
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
492 f, m = a[:2]
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
493 if m == 'm': # merge
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
494 f2, fd, flags, move = a[2:]
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
495 if f != fd:
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
496 repo.ui.debug(_("copying %s to %s\n") % (f, fd))
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
497 repo.wwrite(fd, repo.wread(f), flags)
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
498
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5060
diff changeset
499 audit_path = util.path_auditor(repo.root)
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5060
diff changeset
500
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
501 for a in action:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
502 f, m = a[:2]
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
503 if f and f[0] == "/":
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
504 continue
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
505 if m == "r": # remove
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
506 repo.ui.note(_("removing %s\n") % f)
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5060
diff changeset
507 audit_path(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
508 try:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
509 util.unlink(repo.wjoin(f))
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
510 except OSError, inst:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
511 if inst.errno != errno.ENOENT:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
512 repo.ui.warn(_("update failed to remove %s: %s!\n") %
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
513 (f, inst.strerror))
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3618
diff changeset
514 removed += 1
3308
ecc1bf27378c merge: unify merge and copy actions
Matt Mackall <mpm@selenic.com>
parents: 3307
diff changeset
515 elif m == "m": # merge
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
516 f2, fd, flags, move = a[2:]
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
517 r = filemerge(repo, f, fd, f2, wctx, mctx)
3400
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
518 if r > 0:
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
519 unresolved += 1
3309
e8be5942335d merge: pull file copy/move out of filemerge
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
520 else:
3400
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
521 if r is None:
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
522 updated += 1
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
523 else:
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
524 merged += 1
5704
5049bbf988e1 merge: use util.set_flags
Matt Mackall <mpm@selenic.com>
parents: 5700
diff changeset
525 util.set_flags(repo.wjoin(fd), flags)
5059
8d9bdcbb2b18 merge: avoid double deletion mentioned in issue636
Matt Mackall <mpm@selenic.com>
parents: 5042
diff changeset
526 if f != fd and move and util.lexists(repo.wjoin(f)):
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
527 repo.ui.debug(_("removing %s\n") % f)
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
528 os.unlink(repo.wjoin(f))
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
529 elif m == "g": # get
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
530 flags = a[2]
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
531 repo.ui.note(_("getting %s\n") % f)
3303
488d3062d225 merge: eliminate nodes from action list
Matt Mackall <mpm@selenic.com>
parents: 3299
diff changeset
532 t = mctx.filectx(f).data()
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
533 repo.wwrite(f, t, flags)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
534 updated += 1
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
535 elif m == "d": # directory rename
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
536 f2, fd, flags = a[2:]
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
537 if f:
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
538 repo.ui.note(_("moving %s to %s\n") % (f, fd))
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
539 t = wctx.filectx(f).data()
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
540 repo.wwrite(fd, t, flags)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
541 util.unlink(repo.wjoin(f))
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
542 if f2:
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
543 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
544 t = mctx.filectx(f2).data()
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
545 repo.wwrite(fd, t, flags)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
546 updated += 1
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
547 elif m == "dr": # divergent renames
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
548 fl = a[2]
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
549 repo.ui.warn("warning: detected divergent renames of %s to:\n" % f)
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
550 for nf in fl:
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
551 repo.ui.warn(" %s\n" % nf)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
552 elif m == "e": # exec
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
553 flags = a[2]
5704
5049bbf988e1 merge: use util.set_flags
Matt Mackall <mpm@selenic.com>
parents: 5700
diff changeset
554 util.set_flags(repo.wjoin(f), flags)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
555
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
556 return updated, merged, removed, unresolved
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
557
3372
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
558 def recordupdates(repo, action, branchmerge):
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
559 "record merge actions to the dirstate"
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
560
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
561 for a in action:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
562 f, m = a[:2]
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
563 if m == "r": # remove
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
564 if branchmerge:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
565 repo.dirstate.remove(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
566 else:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
567 repo.dirstate.forget(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
568 elif m == "f": # forget
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
569 repo.dirstate.forget(f)
4997
60c54154ec4c merge: don't forget to update the dirstate for exec bit changes
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
570 elif m in "ge": # get or exec change
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
571 if branchmerge:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
572 repo.dirstate.normaldirty(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
573 else:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
574 repo.dirstate.normal(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
575 elif m == "m": # merge
3303
488d3062d225 merge: eliminate nodes from action list
Matt Mackall <mpm@selenic.com>
parents: 3299
diff changeset
576 f2, fd, flag, move = a[2:]
3251
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
577 if branchmerge:
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
578 # We've done a branch merge, mark this file as merged
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
579 # so that we properly record the merger later
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
580 repo.dirstate.merge(fd)
3372
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
581 if f != f2: # copy/rename
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
582 if move:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
583 repo.dirstate.remove(f)
3372
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
584 if f != fd:
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
585 repo.dirstate.copy(f, fd)
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
586 else:
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
587 repo.dirstate.copy(f2, fd)
3251
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
588 else:
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
589 # We've update-merged a locally modified file, so
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
590 # we set the dirstate to emulate a normal checkout
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
591 # of that file some time in the past. Thus our
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
592 # merge will appear as a normal local file
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
593 # modification.
5210
90d9ec0dc69d merge: forcefully mark files that we get from the second parent as dirty
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5161
diff changeset
594 repo.dirstate.normallookup(fd)
3308
ecc1bf27378c merge: unify merge and copy actions
Matt Mackall <mpm@selenic.com>
parents: 3307
diff changeset
595 if move:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
596 repo.dirstate.forget(f)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
597 elif m == "d": # directory rename
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
598 f2, fd, flag = a[2:]
4819
9797124581c9 merge: fix adding untracked files on directory rename (issue612)
Matt Mackall <mpm@selenic.com>
parents: 4748
diff changeset
599 if not f2 and f not in repo.dirstate:
9797124581c9 merge: fix adding untracked files on directory rename (issue612)
Matt Mackall <mpm@selenic.com>
parents: 4748
diff changeset
600 # untracked file moved
9797124581c9 merge: fix adding untracked files on directory rename (issue612)
Matt Mackall <mpm@selenic.com>
parents: 4748
diff changeset
601 continue
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
602 if branchmerge:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
603 repo.dirstate.add(fd)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
604 if f:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
605 repo.dirstate.remove(f)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
606 repo.dirstate.copy(f, fd)
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
607 if f2:
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
608 repo.dirstate.copy(f2, fd)
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
609 else:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
610 repo.dirstate.normal(fd)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
611 if f:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
612 repo.dirstate.forget(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
613
4917
126f527b3ba3 Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents: 4915
diff changeset
614 def update(repo, node, branchmerge, force, partial):
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
615 """
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
616 Perform a merge between the working directory and the given node
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
617
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
618 branchmerge = whether to merge between branches
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
619 force = whether to force branch merging or file overwriting
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
620 partial = a function to filter file lists (dirstate not updated)
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
621 """
2815
4870f795f681 Merge: combine force and forcemerge arguments
Matt Mackall <mpm@selenic.com>
parents: 2814
diff changeset
622
4917
126f527b3ba3 Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents: 4915
diff changeset
623 wlock = repo.wlock()
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
624 try:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
625 wc = repo.workingctx()
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
626 if node is None:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
627 # tip of current branch
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
628 try:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
629 node = repo.branchtags()[wc.branch()]
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
630 except KeyError:
5570
78a6b985882f update: default to tipmost branch if default branch doesn't exist
Matt Mackall <mpm@selenic.com>
parents: 5489
diff changeset
631 if wc.branch() == "default": # no default branch!
78a6b985882f update: default to tipmost branch if default branch doesn't exist
Matt Mackall <mpm@selenic.com>
parents: 5489
diff changeset
632 node = repo.lookup("tip") # update to tip
78a6b985882f update: default to tipmost branch if default branch doesn't exist
Matt Mackall <mpm@selenic.com>
parents: 5489
diff changeset
633 else:
78a6b985882f update: default to tipmost branch if default branch doesn't exist
Matt Mackall <mpm@selenic.com>
parents: 5489
diff changeset
634 raise util.Abort(_("branch %s not found") % wc.branch())
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
635 overwrite = force and not branchmerge
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
636 forcemerge = force and branchmerge
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
637 pl = wc.parents()
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
638 p1, p2 = pl[0], repo.changectx(node)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
639 pa = p1.ancestor(p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
640 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
641 fastforward = False
3314
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
642
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
643 ### check phase
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
644 if not overwrite and len(pl) > 1:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
645 raise util.Abort(_("outstanding uncommitted merges"))
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
646 if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
647 if branchmerge:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
648 if p1.branch() != p2.branch() and pa != p2:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
649 fastforward = True
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
650 else:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
651 raise util.Abort(_("there is nothing to merge, just use "
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
652 "'hg update' or look at 'hg heads'"))
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
653 elif not (overwrite or branchmerge):
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
654 raise util.Abort(_("update spans branches, use 'hg merge' "
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
655 "or 'hg update -C' to lose changes"))
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
656 if branchmerge and not forcemerge:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
657 if wc.files():
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
658 raise util.Abort(_("outstanding uncommitted changes"))
2814
0f787997e3c2 Merge: move most tests to the beginning
Matt Mackall <mpm@selenic.com>
parents: 2813
diff changeset
659
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
660 ### calculate phase
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
661 action = []
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
662 if not force:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
663 checkunknown(wc, p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
664 if not util.checkfolding(repo.path):
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
665 checkcollision(p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
666 if not branchmerge:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
667 action += forgetremoved(wc, p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
668 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
669
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
670 ### apply phase
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
671 if not branchmerge: # just jump to the new rev
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
672 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
673 if not partial:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
674 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
675
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
676 stats = applyupdates(repo, action, wc, p2)
2899
8743188f4d2e merge: consolidate dirstate updates
Matt Mackall <mpm@selenic.com>
parents: 2898
diff changeset
677
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
678 if not partial:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
679 recordupdates(repo, action, branchmerge)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
680 repo.dirstate.setparents(fp1, fp2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
681 if not branchmerge and not fastforward:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
682 repo.dirstate.setbranch(p2.branch())
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
683 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
3314
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
684
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
685 return stats
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
686 finally:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
687 del wlock