##// END OF EJS Templates
merge: add a bit more sanity to divergent copy checks
Matt Mackall -
r5857:c704b038 default
parent child Browse files
Show More
@@ -1,685 +1,687 b''
1 # merge.py - directory-level update/merge handling for Mercurial
1 # merge.py - directory-level update/merge handling for Mercurial
2 #
2 #
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import *
8 from node import *
9 from i18n import _
9 from i18n import _
10 import errno, util, os, tempfile, context, heapq
10 import errno, util, os, tempfile, context, heapq
11
11
12 def filemerge(repo, fw, fd, fo, wctx, mctx):
12 def filemerge(repo, fw, fd, fo, wctx, mctx):
13 """perform a 3-way merge in the working directory
13 """perform a 3-way merge in the working directory
14
14
15 fw = original filename in the working directory
15 fw = original filename in the working directory
16 fd = destination filename in the working directory
16 fd = destination filename in the working directory
17 fo = filename in other parent
17 fo = filename in other parent
18 wctx, mctx = working and merge changecontexts
18 wctx, mctx = working and merge changecontexts
19 """
19 """
20
20
21 def temp(prefix, ctx):
21 def temp(prefix, ctx):
22 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
22 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
23 (fd, name) = tempfile.mkstemp(prefix=pre)
23 (fd, name) = tempfile.mkstemp(prefix=pre)
24 data = repo.wwritedata(ctx.path(), ctx.data())
24 data = repo.wwritedata(ctx.path(), ctx.data())
25 f = os.fdopen(fd, "wb")
25 f = os.fdopen(fd, "wb")
26 f.write(data)
26 f.write(data)
27 f.close()
27 f.close()
28 return name
28 return name
29
29
30 fcm = wctx.filectx(fw)
30 fcm = wctx.filectx(fw)
31 fcmdata = wctx.filectx(fd).data()
31 fcmdata = wctx.filectx(fd).data()
32 fco = mctx.filectx(fo)
32 fco = mctx.filectx(fo)
33
33
34 if not fco.cmp(fcmdata): # files identical?
34 if not fco.cmp(fcmdata): # files identical?
35 return None
35 return None
36
36
37 fca = fcm.ancestor(fco)
37 fca = fcm.ancestor(fco)
38 if not fca:
38 if not fca:
39 fca = repo.filectx(fw, fileid=nullrev)
39 fca = repo.filectx(fw, fileid=nullrev)
40 a = repo.wjoin(fd)
40 a = repo.wjoin(fd)
41 b = temp("base", fca)
41 b = temp("base", fca)
42 c = temp("other", fco)
42 c = temp("other", fco)
43
43
44 if fw != fo:
44 if fw != fo:
45 repo.ui.status(_("merging %s and %s\n") % (fw, fo))
45 repo.ui.status(_("merging %s and %s\n") % (fw, fo))
46 else:
46 else:
47 repo.ui.status(_("merging %s\n") % fw)
47 repo.ui.status(_("merging %s\n") % fw)
48
48
49 repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
49 repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
50
50
51 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
51 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
52 or "hgmerge")
52 or "hgmerge")
53 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
53 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
54 environ={'HG_FILE': fd,
54 environ={'HG_FILE': fd,
55 'HG_MY_NODE': str(wctx.parents()[0]),
55 'HG_MY_NODE': str(wctx.parents()[0]),
56 'HG_OTHER_NODE': str(mctx),
56 'HG_OTHER_NODE': str(mctx),
57 'HG_MY_ISLINK': fcm.islink(),
57 'HG_MY_ISLINK': fcm.islink(),
58 'HG_OTHER_ISLINK': fco.islink(),
58 'HG_OTHER_ISLINK': fco.islink(),
59 'HG_BASE_ISLINK': fca.islink(),})
59 'HG_BASE_ISLINK': fca.islink(),})
60 if r:
60 if r:
61 repo.ui.warn(_("merging %s failed!\n") % fd)
61 repo.ui.warn(_("merging %s failed!\n") % fd)
62
62
63 os.unlink(b)
63 os.unlink(b)
64 os.unlink(c)
64 os.unlink(c)
65 return r
65 return r
66
66
67 def checkunknown(wctx, mctx):
67 def checkunknown(wctx, mctx):
68 "check for collisions between unknown files and files in mctx"
68 "check for collisions between unknown files and files in mctx"
69 man = mctx.manifest()
69 man = mctx.manifest()
70 for f in wctx.unknown():
70 for f in wctx.unknown():
71 if f in man:
71 if f in man:
72 if mctx.filectx(f).cmp(wctx.filectx(f).data()):
72 if mctx.filectx(f).cmp(wctx.filectx(f).data()):
73 raise util.Abort(_("untracked file in working directory differs"
73 raise util.Abort(_("untracked file in working directory differs"
74 " from file in requested revision: '%s'")
74 " from file in requested revision: '%s'")
75 % f)
75 % f)
76
76
77 def checkcollision(mctx):
77 def checkcollision(mctx):
78 "check for case folding collisions in the destination context"
78 "check for case folding collisions in the destination context"
79 folded = {}
79 folded = {}
80 for fn in mctx.manifest():
80 for fn in mctx.manifest():
81 fold = fn.lower()
81 fold = fn.lower()
82 if fold in folded:
82 if fold in folded:
83 raise util.Abort(_("case-folding collision between %s and %s")
83 raise util.Abort(_("case-folding collision between %s and %s")
84 % (fn, folded[fold]))
84 % (fn, folded[fold]))
85 folded[fold] = fn
85 folded[fold] = fn
86
86
87 def forgetremoved(wctx, mctx):
87 def forgetremoved(wctx, mctx):
88 """
88 """
89 Forget removed files
89 Forget removed files
90
90
91 If we're jumping between revisions (as opposed to merging), and if
91 If we're jumping between revisions (as opposed to merging), and if
92 neither the working directory nor the target rev has the file,
92 neither the working directory nor the target rev has the file,
93 then we need to remove it from the dirstate, to prevent the
93 then we need to remove it from the dirstate, to prevent the
94 dirstate from listing the file when it is no longer in the
94 dirstate from listing the file when it is no longer in the
95 manifest.
95 manifest.
96 """
96 """
97
97
98 action = []
98 action = []
99 man = mctx.manifest()
99 man = mctx.manifest()
100 for f in wctx.deleted() + wctx.removed():
100 for f in wctx.deleted() + wctx.removed():
101 if f not in man:
101 if f not in man:
102 action.append((f, "f"))
102 action.append((f, "f"))
103
103
104 return action
104 return action
105
105
106 def findcopies(repo, m1, m2, ma, limit):
106 def findcopies(repo, m1, m2, ma, limit):
107 """
107 """
108 Find moves and copies between m1 and m2 back to limit linkrev
108 Find moves and copies between m1 and m2 back to limit linkrev
109 """
109 """
110
110
111 def nonoverlap(d1, d2, d3):
111 def nonoverlap(d1, d2, d3):
112 "Return list of elements in d1 not in d2 or d3"
112 "Return list of elements in d1 not in d2 or d3"
113 l = [d for d in d1 if d not in d3 and d not in d2]
113 l = [d for d in d1 if d not in d3 and d not in d2]
114 l.sort()
114 l.sort()
115 return l
115 return l
116
116
117 def dirname(f):
117 def dirname(f):
118 s = f.rfind("/")
118 s = f.rfind("/")
119 if s == -1:
119 if s == -1:
120 return ""
120 return ""
121 return f[:s]
121 return f[:s]
122
122
123 def dirs(files):
123 def dirs(files):
124 d = {}
124 d = {}
125 for f in files:
125 for f in files:
126 f = dirname(f)
126 f = dirname(f)
127 while f not in d:
127 while f not in d:
128 d[f] = True
128 d[f] = True
129 f = dirname(f)
129 f = dirname(f)
130 return d
130 return d
131
131
132 wctx = repo.workingctx()
132 wctx = repo.workingctx()
133
133
134 def makectx(f, n):
134 def makectx(f, n):
135 if len(n) == 20:
135 if len(n) == 20:
136 return repo.filectx(f, fileid=n)
136 return repo.filectx(f, fileid=n)
137 return wctx.filectx(f)
137 return wctx.filectx(f)
138 ctx = util.cachefunc(makectx)
138 ctx = util.cachefunc(makectx)
139
139
140 def findold(fctx):
140 def findold(fctx):
141 "find files that path was copied from, back to linkrev limit"
141 "find files that path was copied from, back to linkrev limit"
142 old = {}
142 old = {}
143 seen = {}
143 seen = {}
144 orig = fctx.path()
144 orig = fctx.path()
145 visit = [fctx]
145 visit = [fctx]
146 while visit:
146 while visit:
147 fc = visit.pop()
147 fc = visit.pop()
148 s = str(fc)
148 s = str(fc)
149 if s in seen:
149 if s in seen:
150 continue
150 continue
151 seen[s] = 1
151 seen[s] = 1
152 if fc.path() != orig and fc.path() not in old:
152 if fc.path() != orig and fc.path() not in old:
153 old[fc.path()] = 1
153 old[fc.path()] = 1
154 if fc.rev() < limit:
154 if fc.rev() < limit:
155 continue
155 continue
156 visit += fc.parents()
156 visit += fc.parents()
157
157
158 old = old.keys()
158 old = old.keys()
159 old.sort()
159 old.sort()
160 return old
160 return old
161
161
162 copy = {}
162 copy = {}
163 fullcopy = {}
163 fullcopy = {}
164 diverge = {}
164 diverge = {}
165
165
166 def checkcopies(c, man, aman):
166 def checkcopies(c, man, aman):
167 '''check possible copies for filectx c'''
167 '''check possible copies for filectx c'''
168 for of in findold(c):
168 for of in findold(c):
169 fullcopy[c.path()] = of # remember for dir rename detection
169 fullcopy[c.path()] = of # remember for dir rename detection
170 if of not in man: # original file not in other manifest?
170 if of not in man: # original file not in other manifest?
171 if of in ma:
171 if of in ma:
172 diverge.setdefault(of, []).append(c.path())
172 diverge.setdefault(of, []).append(c.path())
173 continue
173 continue
174 # if the original file is unchanged on the other branch,
174 # if the original file is unchanged on the other branch,
175 # no merge needed
175 # no merge needed
176 if man[of] == aman.get(of):
176 if man[of] == aman.get(of):
177 continue
177 continue
178 c2 = ctx(of, man[of])
178 c2 = ctx(of, man[of])
179 ca = c.ancestor(c2)
179 ca = c.ancestor(c2)
180 if not ca: # unrelated?
180 if not ca: # unrelated?
181 continue
181 continue
182 # named changed on only one side?
182 # named changed on only one side?
183 if ca.path() == c.path() or ca.path() == c2.path():
183 if ca.path() == c.path() or ca.path() == c2.path():
184 if c == ca and c2 == ca: # no merge needed, ignore copy
184 if c == ca and c2 == ca: # no merge needed, ignore copy
185 continue
185 continue
186 copy[c.path()] = of
186 copy[c.path()] = of
187
187
188 if not repo.ui.configbool("merge", "followcopies", True):
188 if not repo.ui.configbool("merge", "followcopies", True):
189 return {}, {}
189 return {}, {}
190
190
191 # avoid silly behavior for update from empty dir
191 # avoid silly behavior for update from empty dir
192 if not m1 or not m2 or not ma:
192 if not m1 or not m2 or not ma:
193 return {}, {}
193 return {}, {}
194
194
195 repo.ui.debug(_(" searching for copies back to rev %d\n") % limit)
195 repo.ui.debug(_(" searching for copies back to rev %d\n") % limit)
196
196
197 u1 = nonoverlap(m1, m2, ma)
197 u1 = nonoverlap(m1, m2, ma)
198 u2 = nonoverlap(m2, m1, ma)
198 u2 = nonoverlap(m2, m1, ma)
199
199
200 if u1:
200 if u1:
201 repo.ui.debug(_(" unmatched files in local:\n %s\n")
201 repo.ui.debug(_(" unmatched files in local:\n %s\n")
202 % "\n ".join(u1))
202 % "\n ".join(u1))
203 if u2:
203 if u2:
204 repo.ui.debug(_(" unmatched files in other:\n %s\n")
204 repo.ui.debug(_(" unmatched files in other:\n %s\n")
205 % "\n ".join(u2))
205 % "\n ".join(u2))
206
206
207 for f in u1:
207 for f in u1:
208 checkcopies(ctx(f, m1[f]), m2, ma)
208 checkcopies(ctx(f, m1[f]), m2, ma)
209
209
210 for f in u2:
210 for f in u2:
211 checkcopies(ctx(f, m2[f]), m1, ma)
211 checkcopies(ctx(f, m2[f]), m1, ma)
212
212
213 d2 = {}
213 diverge2 = {}
214 for of, fl in diverge.items():
214 for of, fl in diverge.items():
215 for f in fl:
215 if len(fl) == 1:
216 fo = list(fl)
216 del diverge[of] # not actually divergent
217 fo.remove(f)
217 else:
218 d2[f] = (of, fo)
218 diverge2.update(dict.fromkeys(fl)) # reverse map for below
219
219
220 if fullcopy:
220 if fullcopy:
221 repo.ui.debug(_(" all copies found (* = to merge, ! = divergent):\n"))
221 repo.ui.debug(_(" all copies found (* = to merge, ! = divergent):\n"))
222 for f in fullcopy:
222 for f in fullcopy:
223 note = ""
223 note = ""
224 if f in copy: note += "*"
224 if f in copy: note += "*"
225 if f in diverge: note += "!"
225 if f in diverge2: note += "!"
226 repo.ui.debug(_(" %s -> %s %s\n") % (f, fullcopy[f], note))
226 repo.ui.debug(_(" %s -> %s %s\n") % (f, fullcopy[f], note))
227
227
228 del diverge2
229
228 if not fullcopy or not repo.ui.configbool("merge", "followdirs", True):
230 if not fullcopy or not repo.ui.configbool("merge", "followdirs", True):
229 return copy, diverge
231 return copy, diverge
230
232
231 repo.ui.debug(_(" checking for directory renames\n"))
233 repo.ui.debug(_(" checking for directory renames\n"))
232
234
233 # generate a directory move map
235 # generate a directory move map
234 d1, d2 = dirs(m1), dirs(m2)
236 d1, d2 = dirs(m1), dirs(m2)
235 invalid = {}
237 invalid = {}
236 dirmove = {}
238 dirmove = {}
237
239
238 # examine each file copy for a potential directory move, which is
240 # examine each file copy for a potential directory move, which is
239 # when all the files in a directory are moved to a new directory
241 # when all the files in a directory are moved to a new directory
240 for dst, src in fullcopy.items():
242 for dst, src in fullcopy.items():
241 dsrc, ddst = dirname(src), dirname(dst)
243 dsrc, ddst = dirname(src), dirname(dst)
242 if dsrc in invalid:
244 if dsrc in invalid:
243 # already seen to be uninteresting
245 # already seen to be uninteresting
244 continue
246 continue
245 elif dsrc in d1 and ddst in d1:
247 elif dsrc in d1 and ddst in d1:
246 # directory wasn't entirely moved locally
248 # directory wasn't entirely moved locally
247 invalid[dsrc] = True
249 invalid[dsrc] = True
248 elif dsrc in d2 and ddst in d2:
250 elif dsrc in d2 and ddst in d2:
249 # directory wasn't entirely moved remotely
251 # directory wasn't entirely moved remotely
250 invalid[dsrc] = True
252 invalid[dsrc] = True
251 elif dsrc in dirmove and dirmove[dsrc] != ddst:
253 elif dsrc in dirmove and dirmove[dsrc] != ddst:
252 # files from the same directory moved to two different places
254 # files from the same directory moved to two different places
253 invalid[dsrc] = True
255 invalid[dsrc] = True
254 else:
256 else:
255 # looks good so far
257 # looks good so far
256 dirmove[dsrc + "/"] = ddst + "/"
258 dirmove[dsrc + "/"] = ddst + "/"
257
259
258 for i in invalid:
260 for i in invalid:
259 if i in dirmove:
261 if i in dirmove:
260 del dirmove[i]
262 del dirmove[i]
261
263
262 del d1, d2, invalid
264 del d1, d2, invalid
263
265
264 if not dirmove:
266 if not dirmove:
265 return copy, diverge
267 return copy, diverge
266
268
267 for d in dirmove:
269 for d in dirmove:
268 repo.ui.debug(_(" dir %s -> %s\n") % (d, dirmove[d]))
270 repo.ui.debug(_(" dir %s -> %s\n") % (d, dirmove[d]))
269
271
270 # check unaccounted nonoverlapping files against directory moves
272 # check unaccounted nonoverlapping files against directory moves
271 for f in u1 + u2:
273 for f in u1 + u2:
272 if f not in fullcopy:
274 if f not in fullcopy:
273 for d in dirmove:
275 for d in dirmove:
274 if f.startswith(d):
276 if f.startswith(d):
275 # new file added in a directory that was moved, move it
277 # new file added in a directory that was moved, move it
276 copy[f] = dirmove[d] + f[len(d):]
278 copy[f] = dirmove[d] + f[len(d):]
277 repo.ui.debug(_(" file %s -> %s\n") % (f, copy[f]))
279 repo.ui.debug(_(" file %s -> %s\n") % (f, copy[f]))
278 break
280 break
279
281
280 return copy, diverge
282 return copy, diverge
281
283
282 def symmetricdifference(repo, rev1, rev2):
284 def symmetricdifference(repo, rev1, rev2):
283 """symmetric difference of the sets of ancestors of rev1 and rev2
285 """symmetric difference of the sets of ancestors of rev1 and rev2
284
286
285 I.e. revisions that are ancestors of rev1 or rev2, but not both.
287 I.e. revisions that are ancestors of rev1 or rev2, but not both.
286 """
288 """
287 # basic idea:
289 # basic idea:
288 # - mark rev1 and rev2 with different colors
290 # - mark rev1 and rev2 with different colors
289 # - walk the graph in topological order with the help of a heap;
291 # - walk the graph in topological order with the help of a heap;
290 # for each revision r:
292 # for each revision r:
291 # - if r has only one color, we want to return it
293 # - if r has only one color, we want to return it
292 # - add colors[r] to its parents
294 # - add colors[r] to its parents
293 #
295 #
294 # We keep track of the number of revisions in the heap that
296 # We keep track of the number of revisions in the heap that
295 # we may be interested in. We stop walking the graph as soon
297 # we may be interested in. We stop walking the graph as soon
296 # as this number reaches 0.
298 # as this number reaches 0.
297 WHITE = 1
299 WHITE = 1
298 BLACK = 2
300 BLACK = 2
299 ALLCOLORS = WHITE | BLACK
301 ALLCOLORS = WHITE | BLACK
300 colors = {rev1: WHITE, rev2: BLACK}
302 colors = {rev1: WHITE, rev2: BLACK}
301
303
302 cl = repo.changelog
304 cl = repo.changelog
303
305
304 visit = [-rev1, -rev2]
306 visit = [-rev1, -rev2]
305 heapq.heapify(visit)
307 heapq.heapify(visit)
306 n_wanted = len(visit)
308 n_wanted = len(visit)
307 ret = []
309 ret = []
308
310
309 while n_wanted:
311 while n_wanted:
310 r = -heapq.heappop(visit)
312 r = -heapq.heappop(visit)
311 wanted = colors[r] != ALLCOLORS
313 wanted = colors[r] != ALLCOLORS
312 n_wanted -= wanted
314 n_wanted -= wanted
313 if wanted:
315 if wanted:
314 ret.append(r)
316 ret.append(r)
315
317
316 for p in cl.parentrevs(r):
318 for p in cl.parentrevs(r):
317 if p == nullrev:
319 if p == nullrev:
318 continue
320 continue
319 if p not in colors:
321 if p not in colors:
320 # first time we see p; add it to visit
322 # first time we see p; add it to visit
321 n_wanted += wanted
323 n_wanted += wanted
322 colors[p] = colors[r]
324 colors[p] = colors[r]
323 heapq.heappush(visit, -p)
325 heapq.heappush(visit, -p)
324 elif colors[p] != ALLCOLORS and colors[p] != colors[r]:
326 elif colors[p] != ALLCOLORS and colors[p] != colors[r]:
325 # at first we thought we wanted p, but now
327 # at first we thought we wanted p, but now
326 # we know we don't really want it
328 # we know we don't really want it
327 n_wanted -= 1
329 n_wanted -= 1
328 colors[p] |= colors[r]
330 colors[p] |= colors[r]
329
331
330 del colors[r]
332 del colors[r]
331
333
332 return ret
334 return ret
333
335
334 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
336 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
335 """
337 """
336 Merge p1 and p2 with ancestor ma and generate merge action list
338 Merge p1 and p2 with ancestor ma and generate merge action list
337
339
338 overwrite = whether we clobber working files
340 overwrite = whether we clobber working files
339 partial = function to filter file lists
341 partial = function to filter file lists
340 """
342 """
341
343
342 repo.ui.note(_("resolving manifests\n"))
344 repo.ui.note(_("resolving manifests\n"))
343 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
345 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
344 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
346 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
345
347
346 m1 = p1.manifest()
348 m1 = p1.manifest()
347 m2 = p2.manifest()
349 m2 = p2.manifest()
348 ma = pa.manifest()
350 ma = pa.manifest()
349 backwards = (pa == p2)
351 backwards = (pa == p2)
350 action = []
352 action = []
351 copy = {}
353 copy = {}
352 diverge = {}
354 diverge = {}
353
355
354 def fmerge(f, f2=None, fa=None):
356 def fmerge(f, f2=None, fa=None):
355 """merge flags"""
357 """merge flags"""
356 if not f2:
358 if not f2:
357 f2 = f
359 f2 = f
358 fa = f
360 fa = f
359 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
361 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
360 if m == n: # flags agree
362 if m == n: # flags agree
361 return m # unchanged
363 return m # unchanged
362 if m and n: # flags are set but don't agree
364 if m and n: # flags are set but don't agree
363 if not a: # both differ from parent
365 if not a: # both differ from parent
364 r = repo.ui.prompt(
366 r = repo.ui.prompt(
365 _(" conflicting flags for %s\n"
367 _(" conflicting flags for %s\n"
366 "(n)one, e(x)ec or sym(l)ink?") % f, "[nxl]", "n")
368 "(n)one, e(x)ec or sym(l)ink?") % f, "[nxl]", "n")
367 return r != "n" and r or ''
369 return r != "n" and r or ''
368 if m == a:
370 if m == a:
369 return n # changed from m to n
371 return n # changed from m to n
370 return m # changed from n to m
372 return m # changed from n to m
371 if m and m != a: # changed from a to m
373 if m and m != a: # changed from a to m
372 return m
374 return m
373 if n and n != a: # changed from a to n
375 if n and n != a: # changed from a to n
374 return n
376 return n
375 return '' # flag was cleared
377 return '' # flag was cleared
376
378
377 def act(msg, m, f, *args):
379 def act(msg, m, f, *args):
378 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
380 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
379 action.append((f, m) + args)
381 action.append((f, m) + args)
380
382
381 if not (backwards or overwrite):
383 if not (backwards or overwrite):
382 rev1 = p1.rev()
384 rev1 = p1.rev()
383 if rev1 is None:
385 if rev1 is None:
384 # p1 is a workingctx
386 # p1 is a workingctx
385 rev1 = p1.parents()[0].rev()
387 rev1 = p1.parents()[0].rev()
386 limit = min(symmetricdifference(repo, rev1, p2.rev()))
388 limit = min(symmetricdifference(repo, rev1, p2.rev()))
387 copy, diverge = findcopies(repo, m1, m2, ma, limit)
389 copy, diverge = findcopies(repo, m1, m2, ma, limit)
388
390
389 for of, fl in diverge.items():
391 for of, fl in diverge.items():
390 act("divergent renames", "dr", of, fl)
392 act("divergent renames", "dr", of, fl)
391
393
392 copied = dict.fromkeys(copy.values())
394 copied = dict.fromkeys(copy.values())
393
395
394 # Compare manifests
396 # Compare manifests
395 for f, n in m1.iteritems():
397 for f, n in m1.iteritems():
396 if partial and not partial(f):
398 if partial and not partial(f):
397 continue
399 continue
398 if f in m2:
400 if f in m2:
399 if overwrite or backwards:
401 if overwrite or backwards:
400 rflags = m2.flags(f)
402 rflags = m2.flags(f)
401 else:
403 else:
402 rflags = fmerge(f)
404 rflags = fmerge(f)
403 # are files different?
405 # are files different?
404 if n != m2[f]:
406 if n != m2[f]:
405 a = ma.get(f, nullid)
407 a = ma.get(f, nullid)
406 # are we clobbering?
408 # are we clobbering?
407 if overwrite:
409 if overwrite:
408 act("clobbering", "g", f, rflags)
410 act("clobbering", "g", f, rflags)
409 # or are we going back in time and clean?
411 # or are we going back in time and clean?
410 elif backwards and not n[20:]:
412 elif backwards and not n[20:]:
411 act("reverting", "g", f, rflags)
413 act("reverting", "g", f, rflags)
412 # are both different from the ancestor?
414 # are both different from the ancestor?
413 elif n != a and m2[f] != a:
415 elif n != a and m2[f] != a:
414 act("versions differ", "m", f, f, f, rflags, False)
416 act("versions differ", "m", f, f, f, rflags, False)
415 # is remote's version newer?
417 # is remote's version newer?
416 elif m2[f] != a:
418 elif m2[f] != a:
417 act("remote is newer", "g", f, rflags)
419 act("remote is newer", "g", f, rflags)
418 # local is newer, not overwrite, check mode bits
420 # local is newer, not overwrite, check mode bits
419 elif m1.flags(f) != rflags:
421 elif m1.flags(f) != rflags:
420 act("update permissions", "e", f, rflags)
422 act("update permissions", "e", f, rflags)
421 # contents same, check mode bits
423 # contents same, check mode bits
422 elif m1.flags(f) != rflags:
424 elif m1.flags(f) != rflags:
423 act("update permissions", "e", f, rflags)
425 act("update permissions", "e", f, rflags)
424 elif f in copied:
426 elif f in copied:
425 continue
427 continue
426 elif f in copy:
428 elif f in copy:
427 f2 = copy[f]
429 f2 = copy[f]
428 if f2 not in m2: # directory rename
430 if f2 not in m2: # directory rename
429 act("remote renamed directory to " + f2, "d",
431 act("remote renamed directory to " + f2, "d",
430 f, None, f2, m1.flags(f))
432 f, None, f2, m1.flags(f))
431 elif f2 in m1: # case 2 A,B/B/B
433 elif f2 in m1: # case 2 A,B/B/B
432 act("local copied to " + f2, "m",
434 act("local copied to " + f2, "m",
433 f, f2, f, fmerge(f, f2, f2), False)
435 f, f2, f, fmerge(f, f2, f2), False)
434 else: # case 4,21 A/B/B
436 else: # case 4,21 A/B/B
435 act("local moved to " + f2, "m",
437 act("local moved to " + f2, "m",
436 f, f2, f, fmerge(f, f2, f2), False)
438 f, f2, f, fmerge(f, f2, f2), False)
437 elif f in ma:
439 elif f in ma:
438 if n != ma[f] and not overwrite:
440 if n != ma[f] and not overwrite:
439 if repo.ui.prompt(
441 if repo.ui.prompt(
440 _(" local changed %s which remote deleted\n"
442 _(" local changed %s which remote deleted\n"
441 "use (c)hanged version or (d)elete?") % f,
443 "use (c)hanged version or (d)elete?") % f,
442 _("[cd]"), _("c")) == _("d"):
444 _("[cd]"), _("c")) == _("d"):
443 act("prompt delete", "r", f)
445 act("prompt delete", "r", f)
444 else:
446 else:
445 act("other deleted", "r", f)
447 act("other deleted", "r", f)
446 else:
448 else:
447 # file is created on branch or in working directory
449 # file is created on branch or in working directory
448 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
450 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
449 act("remote deleted", "r", f)
451 act("remote deleted", "r", f)
450
452
451 for f, n in m2.iteritems():
453 for f, n in m2.iteritems():
452 if partial and not partial(f):
454 if partial and not partial(f):
453 continue
455 continue
454 if f in m1:
456 if f in m1:
455 continue
457 continue
456 if f in copied:
458 if f in copied:
457 continue
459 continue
458 if f in copy:
460 if f in copy:
459 f2 = copy[f]
461 f2 = copy[f]
460 if f2 not in m1: # directory rename
462 if f2 not in m1: # directory rename
461 act("local renamed directory to " + f2, "d",
463 act("local renamed directory to " + f2, "d",
462 None, f, f2, m2.flags(f))
464 None, f, f2, m2.flags(f))
463 elif f2 in m2: # rename case 1, A/A,B/A
465 elif f2 in m2: # rename case 1, A/A,B/A
464 act("remote copied to " + f, "m",
466 act("remote copied to " + f, "m",
465 f2, f, f, fmerge(f2, f, f2), False)
467 f2, f, f, fmerge(f2, f, f2), False)
466 else: # case 3,20 A/B/A
468 else: # case 3,20 A/B/A
467 act("remote moved to " + f, "m",
469 act("remote moved to " + f, "m",
468 f2, f, f, fmerge(f2, f, f2), True)
470 f2, f, f, fmerge(f2, f, f2), True)
469 elif f in ma:
471 elif f in ma:
470 if overwrite or backwards:
472 if overwrite or backwards:
471 act("recreating", "g", f, m2.flags(f))
473 act("recreating", "g", f, m2.flags(f))
472 elif n != ma[f]:
474 elif n != ma[f]:
473 if repo.ui.prompt(
475 if repo.ui.prompt(
474 _("remote changed %s which local deleted\n"
476 _("remote changed %s which local deleted\n"
475 "use (c)hanged version or leave (d)eleted?") % f,
477 "use (c)hanged version or leave (d)eleted?") % f,
476 _("[cd]"), _("c")) == _("c"):
478 _("[cd]"), _("c")) == _("c"):
477 act("prompt recreating", "g", f, m2.flags(f))
479 act("prompt recreating", "g", f, m2.flags(f))
478 else:
480 else:
479 act("remote created", "g", f, m2.flags(f))
481 act("remote created", "g", f, m2.flags(f))
480
482
481 return action
483 return action
482
484
483 def applyupdates(repo, action, wctx, mctx):
485 def applyupdates(repo, action, wctx, mctx):
484 "apply the merge action list to the working directory"
486 "apply the merge action list to the working directory"
485
487
486 updated, merged, removed, unresolved = 0, 0, 0, 0
488 updated, merged, removed, unresolved = 0, 0, 0, 0
487 action.sort()
489 action.sort()
488 # prescan for copy/renames
490 # prescan for copy/renames
489 for a in action:
491 for a in action:
490 f, m = a[:2]
492 f, m = a[:2]
491 if m == 'm': # merge
493 if m == 'm': # merge
492 f2, fd, flags, move = a[2:]
494 f2, fd, flags, move = a[2:]
493 if f != fd:
495 if f != fd:
494 repo.ui.debug(_("copying %s to %s\n") % (f, fd))
496 repo.ui.debug(_("copying %s to %s\n") % (f, fd))
495 repo.wwrite(fd, repo.wread(f), flags)
497 repo.wwrite(fd, repo.wread(f), flags)
496
498
497 audit_path = util.path_auditor(repo.root)
499 audit_path = util.path_auditor(repo.root)
498
500
499 for a in action:
501 for a in action:
500 f, m = a[:2]
502 f, m = a[:2]
501 if f and f[0] == "/":
503 if f and f[0] == "/":
502 continue
504 continue
503 if m == "r": # remove
505 if m == "r": # remove
504 repo.ui.note(_("removing %s\n") % f)
506 repo.ui.note(_("removing %s\n") % f)
505 audit_path(f)
507 audit_path(f)
506 try:
508 try:
507 util.unlink(repo.wjoin(f))
509 util.unlink(repo.wjoin(f))
508 except OSError, inst:
510 except OSError, inst:
509 if inst.errno != errno.ENOENT:
511 if inst.errno != errno.ENOENT:
510 repo.ui.warn(_("update failed to remove %s: %s!\n") %
512 repo.ui.warn(_("update failed to remove %s: %s!\n") %
511 (f, inst.strerror))
513 (f, inst.strerror))
512 removed += 1
514 removed += 1
513 elif m == "m": # merge
515 elif m == "m": # merge
514 f2, fd, flags, move = a[2:]
516 f2, fd, flags, move = a[2:]
515 r = filemerge(repo, f, fd, f2, wctx, mctx)
517 r = filemerge(repo, f, fd, f2, wctx, mctx)
516 if r > 0:
518 if r > 0:
517 unresolved += 1
519 unresolved += 1
518 else:
520 else:
519 if r is None:
521 if r is None:
520 updated += 1
522 updated += 1
521 else:
523 else:
522 merged += 1
524 merged += 1
523 util.set_flags(repo.wjoin(fd), flags)
525 util.set_flags(repo.wjoin(fd), flags)
524 if f != fd and move and util.lexists(repo.wjoin(f)):
526 if f != fd and move and util.lexists(repo.wjoin(f)):
525 repo.ui.debug(_("removing %s\n") % f)
527 repo.ui.debug(_("removing %s\n") % f)
526 os.unlink(repo.wjoin(f))
528 os.unlink(repo.wjoin(f))
527 elif m == "g": # get
529 elif m == "g": # get
528 flags = a[2]
530 flags = a[2]
529 repo.ui.note(_("getting %s\n") % f)
531 repo.ui.note(_("getting %s\n") % f)
530 t = mctx.filectx(f).data()
532 t = mctx.filectx(f).data()
531 repo.wwrite(f, t, flags)
533 repo.wwrite(f, t, flags)
532 updated += 1
534 updated += 1
533 elif m == "d": # directory rename
535 elif m == "d": # directory rename
534 f2, fd, flags = a[2:]
536 f2, fd, flags = a[2:]
535 if f:
537 if f:
536 repo.ui.note(_("moving %s to %s\n") % (f, fd))
538 repo.ui.note(_("moving %s to %s\n") % (f, fd))
537 t = wctx.filectx(f).data()
539 t = wctx.filectx(f).data()
538 repo.wwrite(fd, t, flags)
540 repo.wwrite(fd, t, flags)
539 util.unlink(repo.wjoin(f))
541 util.unlink(repo.wjoin(f))
540 if f2:
542 if f2:
541 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
543 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
542 t = mctx.filectx(f2).data()
544 t = mctx.filectx(f2).data()
543 repo.wwrite(fd, t, flags)
545 repo.wwrite(fd, t, flags)
544 updated += 1
546 updated += 1
545 elif m == "dr": # divergent renames
547 elif m == "dr": # divergent renames
546 fl = a[2]
548 fl = a[2]
547 repo.ui.warn("warning: detected divergent renames of %s to:\n" % f)
549 repo.ui.warn("warning: detected divergent renames of %s to:\n" % f)
548 for nf in fl:
550 for nf in fl:
549 repo.ui.warn(" %s\n" % nf)
551 repo.ui.warn(" %s\n" % nf)
550 elif m == "e": # exec
552 elif m == "e": # exec
551 flags = a[2]
553 flags = a[2]
552 util.set_flags(repo.wjoin(f), flags)
554 util.set_flags(repo.wjoin(f), flags)
553
555
554 return updated, merged, removed, unresolved
556 return updated, merged, removed, unresolved
555
557
556 def recordupdates(repo, action, branchmerge):
558 def recordupdates(repo, action, branchmerge):
557 "record merge actions to the dirstate"
559 "record merge actions to the dirstate"
558
560
559 for a in action:
561 for a in action:
560 f, m = a[:2]
562 f, m = a[:2]
561 if m == "r": # remove
563 if m == "r": # remove
562 if branchmerge:
564 if branchmerge:
563 repo.dirstate.remove(f)
565 repo.dirstate.remove(f)
564 else:
566 else:
565 repo.dirstate.forget(f)
567 repo.dirstate.forget(f)
566 elif m == "f": # forget
568 elif m == "f": # forget
567 repo.dirstate.forget(f)
569 repo.dirstate.forget(f)
568 elif m in "ge": # get or exec change
570 elif m in "ge": # get or exec change
569 if branchmerge:
571 if branchmerge:
570 repo.dirstate.normaldirty(f)
572 repo.dirstate.normaldirty(f)
571 else:
573 else:
572 repo.dirstate.normal(f)
574 repo.dirstate.normal(f)
573 elif m == "m": # merge
575 elif m == "m": # merge
574 f2, fd, flag, move = a[2:]
576 f2, fd, flag, move = a[2:]
575 if branchmerge:
577 if branchmerge:
576 # We've done a branch merge, mark this file as merged
578 # We've done a branch merge, mark this file as merged
577 # so that we properly record the merger later
579 # so that we properly record the merger later
578 repo.dirstate.merge(fd)
580 repo.dirstate.merge(fd)
579 if f != f2: # copy/rename
581 if f != f2: # copy/rename
580 if move:
582 if move:
581 repo.dirstate.remove(f)
583 repo.dirstate.remove(f)
582 if f != fd:
584 if f != fd:
583 repo.dirstate.copy(f, fd)
585 repo.dirstate.copy(f, fd)
584 else:
586 else:
585 repo.dirstate.copy(f2, fd)
587 repo.dirstate.copy(f2, fd)
586 else:
588 else:
587 # We've update-merged a locally modified file, so
589 # We've update-merged a locally modified file, so
588 # we set the dirstate to emulate a normal checkout
590 # we set the dirstate to emulate a normal checkout
589 # of that file some time in the past. Thus our
591 # of that file some time in the past. Thus our
590 # merge will appear as a normal local file
592 # merge will appear as a normal local file
591 # modification.
593 # modification.
592 repo.dirstate.normallookup(fd)
594 repo.dirstate.normallookup(fd)
593 if move:
595 if move:
594 repo.dirstate.forget(f)
596 repo.dirstate.forget(f)
595 elif m == "d": # directory rename
597 elif m == "d": # directory rename
596 f2, fd, flag = a[2:]
598 f2, fd, flag = a[2:]
597 if not f2 and f not in repo.dirstate:
599 if not f2 and f not in repo.dirstate:
598 # untracked file moved
600 # untracked file moved
599 continue
601 continue
600 if branchmerge:
602 if branchmerge:
601 repo.dirstate.add(fd)
603 repo.dirstate.add(fd)
602 if f:
604 if f:
603 repo.dirstate.remove(f)
605 repo.dirstate.remove(f)
604 repo.dirstate.copy(f, fd)
606 repo.dirstate.copy(f, fd)
605 if f2:
607 if f2:
606 repo.dirstate.copy(f2, fd)
608 repo.dirstate.copy(f2, fd)
607 else:
609 else:
608 repo.dirstate.normal(fd)
610 repo.dirstate.normal(fd)
609 if f:
611 if f:
610 repo.dirstate.forget(f)
612 repo.dirstate.forget(f)
611
613
612 def update(repo, node, branchmerge, force, partial):
614 def update(repo, node, branchmerge, force, partial):
613 """
615 """
614 Perform a merge between the working directory and the given node
616 Perform a merge between the working directory and the given node
615
617
616 branchmerge = whether to merge between branches
618 branchmerge = whether to merge between branches
617 force = whether to force branch merging or file overwriting
619 force = whether to force branch merging or file overwriting
618 partial = a function to filter file lists (dirstate not updated)
620 partial = a function to filter file lists (dirstate not updated)
619 """
621 """
620
622
621 wlock = repo.wlock()
623 wlock = repo.wlock()
622 try:
624 try:
623 wc = repo.workingctx()
625 wc = repo.workingctx()
624 if node is None:
626 if node is None:
625 # tip of current branch
627 # tip of current branch
626 try:
628 try:
627 node = repo.branchtags()[wc.branch()]
629 node = repo.branchtags()[wc.branch()]
628 except KeyError:
630 except KeyError:
629 if wc.branch() == "default": # no default branch!
631 if wc.branch() == "default": # no default branch!
630 node = repo.lookup("tip") # update to tip
632 node = repo.lookup("tip") # update to tip
631 else:
633 else:
632 raise util.Abort(_("branch %s not found") % wc.branch())
634 raise util.Abort(_("branch %s not found") % wc.branch())
633 overwrite = force and not branchmerge
635 overwrite = force and not branchmerge
634 forcemerge = force and branchmerge
636 forcemerge = force and branchmerge
635 pl = wc.parents()
637 pl = wc.parents()
636 p1, p2 = pl[0], repo.changectx(node)
638 p1, p2 = pl[0], repo.changectx(node)
637 pa = p1.ancestor(p2)
639 pa = p1.ancestor(p2)
638 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
640 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
639 fastforward = False
641 fastforward = False
640
642
641 ### check phase
643 ### check phase
642 if not overwrite and len(pl) > 1:
644 if not overwrite and len(pl) > 1:
643 raise util.Abort(_("outstanding uncommitted merges"))
645 raise util.Abort(_("outstanding uncommitted merges"))
644 if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
646 if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
645 if branchmerge:
647 if branchmerge:
646 if p1.branch() != p2.branch() and pa != p2:
648 if p1.branch() != p2.branch() and pa != p2:
647 fastforward = True
649 fastforward = True
648 else:
650 else:
649 raise util.Abort(_("there is nothing to merge, just use "
651 raise util.Abort(_("there is nothing to merge, just use "
650 "'hg update' or look at 'hg heads'"))
652 "'hg update' or look at 'hg heads'"))
651 elif not (overwrite or branchmerge):
653 elif not (overwrite or branchmerge):
652 raise util.Abort(_("update spans branches, use 'hg merge' "
654 raise util.Abort(_("update spans branches, use 'hg merge' "
653 "or 'hg update -C' to lose changes"))
655 "or 'hg update -C' to lose changes"))
654 if branchmerge and not forcemerge:
656 if branchmerge and not forcemerge:
655 if wc.files():
657 if wc.files():
656 raise util.Abort(_("outstanding uncommitted changes"))
658 raise util.Abort(_("outstanding uncommitted changes"))
657
659
658 ### calculate phase
660 ### calculate phase
659 action = []
661 action = []
660 if not force:
662 if not force:
661 checkunknown(wc, p2)
663 checkunknown(wc, p2)
662 if not util.checkfolding(repo.path):
664 if not util.checkfolding(repo.path):
663 checkcollision(p2)
665 checkcollision(p2)
664 if not branchmerge:
666 if not branchmerge:
665 action += forgetremoved(wc, p2)
667 action += forgetremoved(wc, p2)
666 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
668 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
667
669
668 ### apply phase
670 ### apply phase
669 if not branchmerge: # just jump to the new rev
671 if not branchmerge: # just jump to the new rev
670 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
672 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
671 if not partial:
673 if not partial:
672 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
674 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
673
675
674 stats = applyupdates(repo, action, wc, p2)
676 stats = applyupdates(repo, action, wc, p2)
675
677
676 if not partial:
678 if not partial:
677 recordupdates(repo, action, branchmerge)
679 recordupdates(repo, action, branchmerge)
678 repo.dirstate.setparents(fp1, fp2)
680 repo.dirstate.setparents(fp1, fp2)
679 if not branchmerge and not fastforward:
681 if not branchmerge and not fastforward:
680 repo.dirstate.setbranch(p2.branch())
682 repo.dirstate.setbranch(p2.branch())
681 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
683 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
682
684
683 return stats
685 return stats
684 finally:
686 finally:
685 del wlock
687 del wlock
@@ -1,40 +1,40 b''
1 checkout
1 checkout
2 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
2 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
3 merge
3 merge
4 resolving manifests
4 resolving manifests
5 overwrite None partial False
5 overwrite None partial False
6 ancestor af1939970a1c local f26ec4fc3fa3+ remote 8e765a822af2
6 ancestor af1939970a1c local f26ec4fc3fa3+ remote 8e765a822af2
7 searching for copies back to rev 1
7 searching for copies back to rev 1
8 unmatched files in local:
8 unmatched files in local:
9 c2
9 c2
10 unmatched files in other:
10 unmatched files in other:
11 b
11 b
12 b2
12 b2
13 all copies found (* = to merge, ! = divergent):
13 all copies found (* = to merge, ! = divergent):
14 c2 -> a2
14 c2 -> a2 !
15 b -> a *
15 b -> a *
16 b2 -> a2
16 b2 -> a2 !
17 checking for directory renames
17 checking for directory renames
18 a2: divergent renames -> dr
18 a2: divergent renames -> dr
19 a: remote moved to b -> m
19 a: remote moved to b -> m
20 b2: remote created -> g
20 b2: remote created -> g
21 copying a to b
21 copying a to b
22 merging a and b
22 merging a and b
23 my a@f26ec4fc3fa3+ other b@8e765a822af2 ancestor a@af1939970a1c
23 my a@f26ec4fc3fa3+ other b@8e765a822af2 ancestor a@af1939970a1c
24 removing a
24 removing a
25 warning: detected divergent renames of a2 to:
25 warning: detected divergent renames of a2 to:
26 c2
26 c2
27 b2
27 b2
28 getting b2
28 getting b2
29 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
29 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
30 (branch merge, don't forget to commit)
30 (branch merge, don't forget to commit)
31 M b
31 M b
32 a
32 a
33 M b2
33 M b2
34 R a
34 R a
35 C c2
35 C c2
36 blahblah
36 blahblah
37 rev offset length base linkrev nodeid p1 p2
37 rev offset length base linkrev nodeid p1 p2
38 0 0 67 0 1 dc51707dfc98 000000000000 000000000000
38 0 0 67 0 1 dc51707dfc98 000000000000 000000000000
39 1 67 72 1 3 b2494a44f0a9 000000000000 dc51707dfc98
39 1 67 72 1 3 b2494a44f0a9 000000000000 dc51707dfc98
40 b renamed from a:dd03b83622e78778b403775d0d074b9ac7387a66
40 b renamed from a:dd03b83622e78778b403775d0d074b9ac7387a66
@@ -1,499 +1,499 b''
1 --------------
1 --------------
2 test L:up a R:nc a b W: - 1 get local a to b
2 test L:up a R:nc a b W: - 1 get local a to b
3 --------------
3 --------------
4 resolving manifests
4 resolving manifests
5 overwrite None partial False
5 overwrite None partial False
6 ancestor 924404dff337 local e300d1c794ec+ remote 735846fee2d7
6 ancestor 924404dff337 local e300d1c794ec+ remote 735846fee2d7
7 searching for copies back to rev 1
7 searching for copies back to rev 1
8 unmatched files in other:
8 unmatched files in other:
9 b
9 b
10 all copies found (* = to merge, ! = divergent):
10 all copies found (* = to merge, ! = divergent):
11 b -> a *
11 b -> a *
12 checking for directory renames
12 checking for directory renames
13 rev: versions differ -> m
13 rev: versions differ -> m
14 a: remote copied to b -> m
14 a: remote copied to b -> m
15 copying a to b
15 copying a to b
16 merging a and b
16 merging a and b
17 my a@e300d1c794ec+ other b@735846fee2d7 ancestor a@924404dff337
17 my a@e300d1c794ec+ other b@735846fee2d7 ancestor a@924404dff337
18 merging rev
18 merging rev
19 my rev@e300d1c794ec+ other rev@735846fee2d7 ancestor rev@924404dff337
19 my rev@e300d1c794ec+ other rev@735846fee2d7 ancestor rev@924404dff337
20 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
20 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
21 (branch merge, don't forget to commit)
21 (branch merge, don't forget to commit)
22 --------------
22 --------------
23 M b
23 M b
24 a
24 a
25 C a
25 C a
26 --------------
26 --------------
27
27
28 --------------
28 --------------
29 test L:nc a b R:up a W: - 2 get rem change to a and b
29 test L:nc a b R:up a W: - 2 get rem change to a and b
30 --------------
30 --------------
31 resolving manifests
31 resolving manifests
32 overwrite None partial False
32 overwrite None partial False
33 ancestor 924404dff337 local ac809aeed39a+ remote f4db7e329e71
33 ancestor 924404dff337 local ac809aeed39a+ remote f4db7e329e71
34 searching for copies back to rev 1
34 searching for copies back to rev 1
35 unmatched files in local:
35 unmatched files in local:
36 b
36 b
37 all copies found (* = to merge, ! = divergent):
37 all copies found (* = to merge, ! = divergent):
38 b -> a *
38 b -> a *
39 checking for directory renames
39 checking for directory renames
40 a: remote is newer -> g
40 a: remote is newer -> g
41 b: local copied to a -> m
41 b: local copied to a -> m
42 rev: versions differ -> m
42 rev: versions differ -> m
43 getting a
43 getting a
44 merging b and a
44 merging b and a
45 my b@ac809aeed39a+ other a@f4db7e329e71 ancestor a@924404dff337
45 my b@ac809aeed39a+ other a@f4db7e329e71 ancestor a@924404dff337
46 merging rev
46 merging rev
47 my rev@ac809aeed39a+ other rev@f4db7e329e71 ancestor rev@924404dff337
47 my rev@ac809aeed39a+ other rev@f4db7e329e71 ancestor rev@924404dff337
48 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
48 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
49 (branch merge, don't forget to commit)
49 (branch merge, don't forget to commit)
50 --------------
50 --------------
51 M a
51 M a
52 M b
52 M b
53 a
53 a
54 --------------
54 --------------
55
55
56 --------------
56 --------------
57 test L:up a R:nm a b W: - 3 get local a change to b, remove a
57 test L:up a R:nm a b W: - 3 get local a change to b, remove a
58 --------------
58 --------------
59 resolving manifests
59 resolving manifests
60 overwrite None partial False
60 overwrite None partial False
61 ancestor 924404dff337 local e300d1c794ec+ remote e03727d2d66b
61 ancestor 924404dff337 local e300d1c794ec+ remote e03727d2d66b
62 searching for copies back to rev 1
62 searching for copies back to rev 1
63 unmatched files in other:
63 unmatched files in other:
64 b
64 b
65 all copies found (* = to merge, ! = divergent):
65 all copies found (* = to merge, ! = divergent):
66 b -> a *
66 b -> a *
67 checking for directory renames
67 checking for directory renames
68 rev: versions differ -> m
68 rev: versions differ -> m
69 a: remote moved to b -> m
69 a: remote moved to b -> m
70 copying a to b
70 copying a to b
71 merging a and b
71 merging a and b
72 my a@e300d1c794ec+ other b@e03727d2d66b ancestor a@924404dff337
72 my a@e300d1c794ec+ other b@e03727d2d66b ancestor a@924404dff337
73 removing a
73 removing a
74 merging rev
74 merging rev
75 my rev@e300d1c794ec+ other rev@e03727d2d66b ancestor rev@924404dff337
75 my rev@e300d1c794ec+ other rev@e03727d2d66b ancestor rev@924404dff337
76 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
76 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
77 (branch merge, don't forget to commit)
77 (branch merge, don't forget to commit)
78 --------------
78 --------------
79 M b
79 M b
80 a
80 a
81 --------------
81 --------------
82
82
83 --------------
83 --------------
84 test L:nm a b R:up a W: - 4 get remote change to b
84 test L:nm a b R:up a W: - 4 get remote change to b
85 --------------
85 --------------
86 resolving manifests
86 resolving manifests
87 overwrite None partial False
87 overwrite None partial False
88 ancestor 924404dff337 local ecf3cb2a4219+ remote f4db7e329e71
88 ancestor 924404dff337 local ecf3cb2a4219+ remote f4db7e329e71
89 searching for copies back to rev 1
89 searching for copies back to rev 1
90 unmatched files in local:
90 unmatched files in local:
91 b
91 b
92 all copies found (* = to merge, ! = divergent):
92 all copies found (* = to merge, ! = divergent):
93 b -> a *
93 b -> a *
94 checking for directory renames
94 checking for directory renames
95 b: local moved to a -> m
95 b: local moved to a -> m
96 rev: versions differ -> m
96 rev: versions differ -> m
97 merging b and a
97 merging b and a
98 my b@ecf3cb2a4219+ other a@f4db7e329e71 ancestor a@924404dff337
98 my b@ecf3cb2a4219+ other a@f4db7e329e71 ancestor a@924404dff337
99 merging rev
99 merging rev
100 my rev@ecf3cb2a4219+ other rev@f4db7e329e71 ancestor rev@924404dff337
100 my rev@ecf3cb2a4219+ other rev@f4db7e329e71 ancestor rev@924404dff337
101 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
101 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
102 (branch merge, don't forget to commit)
102 (branch merge, don't forget to commit)
103 --------------
103 --------------
104 M b
104 M b
105 a
105 a
106 --------------
106 --------------
107
107
108 --------------
108 --------------
109 test L: R:nc a b W: - 5 get b
109 test L: R:nc a b W: - 5 get b
110 --------------
110 --------------
111 resolving manifests
111 resolving manifests
112 overwrite None partial False
112 overwrite None partial False
113 ancestor 924404dff337 local 94b33a1b7f2d+ remote 735846fee2d7
113 ancestor 924404dff337 local 94b33a1b7f2d+ remote 735846fee2d7
114 searching for copies back to rev 1
114 searching for copies back to rev 1
115 unmatched files in other:
115 unmatched files in other:
116 b
116 b
117 all copies found (* = to merge, ! = divergent):
117 all copies found (* = to merge, ! = divergent):
118 b -> a
118 b -> a
119 checking for directory renames
119 checking for directory renames
120 rev: versions differ -> m
120 rev: versions differ -> m
121 b: remote created -> g
121 b: remote created -> g
122 getting b
122 getting b
123 merging rev
123 merging rev
124 my rev@94b33a1b7f2d+ other rev@735846fee2d7 ancestor rev@924404dff337
124 my rev@94b33a1b7f2d+ other rev@735846fee2d7 ancestor rev@924404dff337
125 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
125 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
126 (branch merge, don't forget to commit)
126 (branch merge, don't forget to commit)
127 --------------
127 --------------
128 M b
128 M b
129 C a
129 C a
130 --------------
130 --------------
131
131
132 --------------
132 --------------
133 test L:nc a b R: W: - 6 nothing
133 test L:nc a b R: W: - 6 nothing
134 --------------
134 --------------
135 resolving manifests
135 resolving manifests
136 overwrite None partial False
136 overwrite None partial False
137 ancestor 924404dff337 local ac809aeed39a+ remote 97c705ade336
137 ancestor 924404dff337 local ac809aeed39a+ remote 97c705ade336
138 searching for copies back to rev 1
138 searching for copies back to rev 1
139 unmatched files in local:
139 unmatched files in local:
140 b
140 b
141 all copies found (* = to merge, ! = divergent):
141 all copies found (* = to merge, ! = divergent):
142 b -> a
142 b -> a
143 checking for directory renames
143 checking for directory renames
144 rev: versions differ -> m
144 rev: versions differ -> m
145 merging rev
145 merging rev
146 my rev@ac809aeed39a+ other rev@97c705ade336 ancestor rev@924404dff337
146 my rev@ac809aeed39a+ other rev@97c705ade336 ancestor rev@924404dff337
147 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
147 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
148 (branch merge, don't forget to commit)
148 (branch merge, don't forget to commit)
149 --------------
149 --------------
150 C a
150 C a
151 C b
151 C b
152 --------------
152 --------------
153
153
154 --------------
154 --------------
155 test L: R:nm a b W: - 7 get b
155 test L: R:nm a b W: - 7 get b
156 --------------
156 --------------
157 resolving manifests
157 resolving manifests
158 overwrite None partial False
158 overwrite None partial False
159 ancestor 924404dff337 local 94b33a1b7f2d+ remote e03727d2d66b
159 ancestor 924404dff337 local 94b33a1b7f2d+ remote e03727d2d66b
160 searching for copies back to rev 1
160 searching for copies back to rev 1
161 unmatched files in other:
161 unmatched files in other:
162 b
162 b
163 all copies found (* = to merge, ! = divergent):
163 all copies found (* = to merge, ! = divergent):
164 b -> a
164 b -> a
165 checking for directory renames
165 checking for directory renames
166 a: other deleted -> r
166 a: other deleted -> r
167 rev: versions differ -> m
167 rev: versions differ -> m
168 b: remote created -> g
168 b: remote created -> g
169 removing a
169 removing a
170 getting b
170 getting b
171 merging rev
171 merging rev
172 my rev@94b33a1b7f2d+ other rev@e03727d2d66b ancestor rev@924404dff337
172 my rev@94b33a1b7f2d+ other rev@e03727d2d66b ancestor rev@924404dff337
173 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
173 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
174 (branch merge, don't forget to commit)
174 (branch merge, don't forget to commit)
175 --------------
175 --------------
176 M b
176 M b
177 --------------
177 --------------
178
178
179 --------------
179 --------------
180 test L:nm a b R: W: - 8 nothing
180 test L:nm a b R: W: - 8 nothing
181 --------------
181 --------------
182 resolving manifests
182 resolving manifests
183 overwrite None partial False
183 overwrite None partial False
184 ancestor 924404dff337 local ecf3cb2a4219+ remote 97c705ade336
184 ancestor 924404dff337 local ecf3cb2a4219+ remote 97c705ade336
185 searching for copies back to rev 1
185 searching for copies back to rev 1
186 unmatched files in local:
186 unmatched files in local:
187 b
187 b
188 all copies found (* = to merge, ! = divergent):
188 all copies found (* = to merge, ! = divergent):
189 b -> a
189 b -> a
190 checking for directory renames
190 checking for directory renames
191 rev: versions differ -> m
191 rev: versions differ -> m
192 merging rev
192 merging rev
193 my rev@ecf3cb2a4219+ other rev@97c705ade336 ancestor rev@924404dff337
193 my rev@ecf3cb2a4219+ other rev@97c705ade336 ancestor rev@924404dff337
194 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
194 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
195 (branch merge, don't forget to commit)
195 (branch merge, don't forget to commit)
196 --------------
196 --------------
197 C b
197 C b
198 --------------
198 --------------
199
199
200 --------------
200 --------------
201 test L:um a b R:um a b W: - 9 do merge with ancestor in a
201 test L:um a b R:um a b W: - 9 do merge with ancestor in a
202 --------------
202 --------------
203 resolving manifests
203 resolving manifests
204 overwrite None partial False
204 overwrite None partial False
205 ancestor 924404dff337 local ec03c2ca8642+ remote 79cc6877a3b7
205 ancestor 924404dff337 local ec03c2ca8642+ remote 79cc6877a3b7
206 searching for copies back to rev 1
206 searching for copies back to rev 1
207 b: versions differ -> m
207 b: versions differ -> m
208 rev: versions differ -> m
208 rev: versions differ -> m
209 merging b
209 merging b
210 my b@ec03c2ca8642+ other b@79cc6877a3b7 ancestor a@924404dff337
210 my b@ec03c2ca8642+ other b@79cc6877a3b7 ancestor a@924404dff337
211 merging rev
211 merging rev
212 my rev@ec03c2ca8642+ other rev@79cc6877a3b7 ancestor rev@924404dff337
212 my rev@ec03c2ca8642+ other rev@79cc6877a3b7 ancestor rev@924404dff337
213 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
213 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
214 (branch merge, don't forget to commit)
214 (branch merge, don't forget to commit)
215 --------------
215 --------------
216 M b
216 M b
217 --------------
217 --------------
218
218
219 --------------
219 --------------
220 test L:nm a b R:nm a c W: - 11 get c, keep b
220 test L:nm a b R:nm a c W: - 11 get c, keep b
221 --------------
221 --------------
222 resolving manifests
222 resolving manifests
223 overwrite None partial False
223 overwrite None partial False
224 ancestor 924404dff337 local ecf3cb2a4219+ remote e6abcc1a30c2
224 ancestor 924404dff337 local ecf3cb2a4219+ remote e6abcc1a30c2
225 searching for copies back to rev 1
225 searching for copies back to rev 1
226 unmatched files in local:
226 unmatched files in local:
227 b
227 b
228 unmatched files in other:
228 unmatched files in other:
229 c
229 c
230 all copies found (* = to merge, ! = divergent):
230 all copies found (* = to merge, ! = divergent):
231 c -> a
231 c -> a !
232 b -> a
232 b -> a !
233 checking for directory renames
233 checking for directory renames
234 a: divergent renames -> dr
234 a: divergent renames -> dr
235 rev: versions differ -> m
235 rev: versions differ -> m
236 c: remote created -> g
236 c: remote created -> g
237 warning: detected divergent renames of a to:
237 warning: detected divergent renames of a to:
238 b
238 b
239 c
239 c
240 getting c
240 getting c
241 merging rev
241 merging rev
242 my rev@ecf3cb2a4219+ other rev@e6abcc1a30c2 ancestor rev@924404dff337
242 my rev@ecf3cb2a4219+ other rev@e6abcc1a30c2 ancestor rev@924404dff337
243 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
243 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
244 (branch merge, don't forget to commit)
244 (branch merge, don't forget to commit)
245 --------------
245 --------------
246 M c
246 M c
247 C b
247 C b
248 --------------
248 --------------
249
249
250 --------------
250 --------------
251 test L:nc a b R:up b W: - 12 merge b no ancestor
251 test L:nc a b R:up b W: - 12 merge b no ancestor
252 --------------
252 --------------
253 resolving manifests
253 resolving manifests
254 overwrite None partial False
254 overwrite None partial False
255 ancestor 924404dff337 local ac809aeed39a+ remote af30c7647fc7
255 ancestor 924404dff337 local ac809aeed39a+ remote af30c7647fc7
256 searching for copies back to rev 1
256 searching for copies back to rev 1
257 b: versions differ -> m
257 b: versions differ -> m
258 rev: versions differ -> m
258 rev: versions differ -> m
259 merging b
259 merging b
260 my b@ac809aeed39a+ other b@af30c7647fc7 ancestor b@000000000000
260 my b@ac809aeed39a+ other b@af30c7647fc7 ancestor b@000000000000
261 merging rev
261 merging rev
262 my rev@ac809aeed39a+ other rev@af30c7647fc7 ancestor rev@924404dff337
262 my rev@ac809aeed39a+ other rev@af30c7647fc7 ancestor rev@924404dff337
263 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
263 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
264 (branch merge, don't forget to commit)
264 (branch merge, don't forget to commit)
265 --------------
265 --------------
266 M b
266 M b
267 C a
267 C a
268 --------------
268 --------------
269
269
270 --------------
270 --------------
271 test L:up b R:nm a b W: - 13 merge b no ancestor
271 test L:up b R:nm a b W: - 13 merge b no ancestor
272 --------------
272 --------------
273 resolving manifests
273 resolving manifests
274 overwrite None partial False
274 overwrite None partial False
275 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
275 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
276 searching for copies back to rev 1
276 searching for copies back to rev 1
277 a: other deleted -> r
277 a: other deleted -> r
278 b: versions differ -> m
278 b: versions differ -> m
279 rev: versions differ -> m
279 rev: versions differ -> m
280 removing a
280 removing a
281 merging b
281 merging b
282 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
282 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
283 merging rev
283 merging rev
284 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
284 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
285 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
285 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
286 (branch merge, don't forget to commit)
286 (branch merge, don't forget to commit)
287 --------------
287 --------------
288 M b
288 M b
289 --------------
289 --------------
290
290
291 --------------
291 --------------
292 test L:nc a b R:up a b W: - 14 merge b no ancestor
292 test L:nc a b R:up a b W: - 14 merge b no ancestor
293 --------------
293 --------------
294 resolving manifests
294 resolving manifests
295 overwrite None partial False
295 overwrite None partial False
296 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
296 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
297 searching for copies back to rev 1
297 searching for copies back to rev 1
298 a: remote is newer -> g
298 a: remote is newer -> g
299 b: versions differ -> m
299 b: versions differ -> m
300 rev: versions differ -> m
300 rev: versions differ -> m
301 getting a
301 getting a
302 merging b
302 merging b
303 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
303 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
304 merging rev
304 merging rev
305 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
305 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
306 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
306 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
307 (branch merge, don't forget to commit)
307 (branch merge, don't forget to commit)
308 --------------
308 --------------
309 M a
309 M a
310 M b
310 M b
311 --------------
311 --------------
312
312
313 --------------
313 --------------
314 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
314 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
315 --------------
315 --------------
316 resolving manifests
316 resolving manifests
317 overwrite None partial False
317 overwrite None partial False
318 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
318 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
319 searching for copies back to rev 1
319 searching for copies back to rev 1
320 a: other deleted -> r
320 a: other deleted -> r
321 b: versions differ -> m
321 b: versions differ -> m
322 rev: versions differ -> m
322 rev: versions differ -> m
323 removing a
323 removing a
324 merging b
324 merging b
325 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
325 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
326 merging rev
326 merging rev
327 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
327 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
328 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
328 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
329 (branch merge, don't forget to commit)
329 (branch merge, don't forget to commit)
330 --------------
330 --------------
331 M b
331 M b
332 --------------
332 --------------
333
333
334 --------------
334 --------------
335 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
335 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
336 --------------
336 --------------
337 resolving manifests
337 resolving manifests
338 overwrite None partial False
338 overwrite None partial False
339 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
339 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
340 searching for copies back to rev 1
340 searching for copies back to rev 1
341 a: remote is newer -> g
341 a: remote is newer -> g
342 b: versions differ -> m
342 b: versions differ -> m
343 rev: versions differ -> m
343 rev: versions differ -> m
344 getting a
344 getting a
345 merging b
345 merging b
346 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
346 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
347 merging rev
347 merging rev
348 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
348 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
349 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
349 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
350 (branch merge, don't forget to commit)
350 (branch merge, don't forget to commit)
351 --------------
351 --------------
352 M a
352 M a
353 M b
353 M b
354 --------------
354 --------------
355
355
356 --------------
356 --------------
357 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
357 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
358 --------------
358 --------------
359 resolving manifests
359 resolving manifests
360 overwrite None partial False
360 overwrite None partial False
361 ancestor 924404dff337 local 0b76e65c8289+ remote 735846fee2d7
361 ancestor 924404dff337 local 0b76e65c8289+ remote 735846fee2d7
362 searching for copies back to rev 1
362 searching for copies back to rev 1
363 b: versions differ -> m
363 b: versions differ -> m
364 rev: versions differ -> m
364 rev: versions differ -> m
365 merging b
365 merging b
366 my b@0b76e65c8289+ other b@735846fee2d7 ancestor b@000000000000
366 my b@0b76e65c8289+ other b@735846fee2d7 ancestor b@000000000000
367 merging rev
367 merging rev
368 my rev@0b76e65c8289+ other rev@735846fee2d7 ancestor rev@924404dff337
368 my rev@0b76e65c8289+ other rev@735846fee2d7 ancestor rev@924404dff337
369 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
369 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
370 (branch merge, don't forget to commit)
370 (branch merge, don't forget to commit)
371 --------------
371 --------------
372 M b
372 M b
373 C a
373 C a
374 --------------
374 --------------
375
375
376 --------------
376 --------------
377 test L:nm a b R:up a b W: - 18 merge b no ancestor
377 test L:nm a b R:up a b W: - 18 merge b no ancestor
378 --------------
378 --------------
379 resolving manifests
379 resolving manifests
380 overwrite None partial False
380 overwrite None partial False
381 ancestor 924404dff337 local ecf3cb2a4219+ remote 8dbce441892a
381 ancestor 924404dff337 local ecf3cb2a4219+ remote 8dbce441892a
382 searching for copies back to rev 1
382 searching for copies back to rev 1
383 b: versions differ -> m
383 b: versions differ -> m
384 rev: versions differ -> m
384 rev: versions differ -> m
385 a: prompt recreating -> g
385 a: prompt recreating -> g
386 getting a
386 getting a
387 merging b
387 merging b
388 my b@ecf3cb2a4219+ other b@8dbce441892a ancestor b@000000000000
388 my b@ecf3cb2a4219+ other b@8dbce441892a ancestor b@000000000000
389 merging rev
389 merging rev
390 my rev@ecf3cb2a4219+ other rev@8dbce441892a ancestor rev@924404dff337
390 my rev@ecf3cb2a4219+ other rev@8dbce441892a ancestor rev@924404dff337
391 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
391 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
392 (branch merge, don't forget to commit)
392 (branch merge, don't forget to commit)
393 --------------
393 --------------
394 M a
394 M a
395 M b
395 M b
396 --------------
396 --------------
397
397
398 --------------
398 --------------
399 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
399 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
400 --------------
400 --------------
401 resolving manifests
401 resolving manifests
402 overwrite None partial False
402 overwrite None partial False
403 ancestor 924404dff337 local 0b76e65c8289+ remote e03727d2d66b
403 ancestor 924404dff337 local 0b76e65c8289+ remote e03727d2d66b
404 searching for copies back to rev 1
404 searching for copies back to rev 1
405 b: versions differ -> m
405 b: versions differ -> m
406 rev: versions differ -> m
406 rev: versions differ -> m
407 merging b
407 merging b
408 my b@0b76e65c8289+ other b@e03727d2d66b ancestor b@000000000000
408 my b@0b76e65c8289+ other b@e03727d2d66b ancestor b@000000000000
409 merging rev
409 merging rev
410 my rev@0b76e65c8289+ other rev@e03727d2d66b ancestor rev@924404dff337
410 my rev@0b76e65c8289+ other rev@e03727d2d66b ancestor rev@924404dff337
411 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
411 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
412 (branch merge, don't forget to commit)
412 (branch merge, don't forget to commit)
413 --------------
413 --------------
414 M b
414 M b
415 C a
415 C a
416 --------------
416 --------------
417
417
418 --------------
418 --------------
419 test L:up a R:um a b W: - 20 merge a and b to b, remove a
419 test L:up a R:um a b W: - 20 merge a and b to b, remove a
420 --------------
420 --------------
421 resolving manifests
421 resolving manifests
422 overwrite None partial False
422 overwrite None partial False
423 ancestor 924404dff337 local e300d1c794ec+ remote 79cc6877a3b7
423 ancestor 924404dff337 local e300d1c794ec+ remote 79cc6877a3b7
424 searching for copies back to rev 1
424 searching for copies back to rev 1
425 unmatched files in other:
425 unmatched files in other:
426 b
426 b
427 all copies found (* = to merge, ! = divergent):
427 all copies found (* = to merge, ! = divergent):
428 b -> a *
428 b -> a *
429 checking for directory renames
429 checking for directory renames
430 rev: versions differ -> m
430 rev: versions differ -> m
431 a: remote moved to b -> m
431 a: remote moved to b -> m
432 copying a to b
432 copying a to b
433 merging a and b
433 merging a and b
434 my a@e300d1c794ec+ other b@79cc6877a3b7 ancestor a@924404dff337
434 my a@e300d1c794ec+ other b@79cc6877a3b7 ancestor a@924404dff337
435 removing a
435 removing a
436 merging rev
436 merging rev
437 my rev@e300d1c794ec+ other rev@79cc6877a3b7 ancestor rev@924404dff337
437 my rev@e300d1c794ec+ other rev@79cc6877a3b7 ancestor rev@924404dff337
438 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
438 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
439 (branch merge, don't forget to commit)
439 (branch merge, don't forget to commit)
440 --------------
440 --------------
441 M b
441 M b
442 a
442 a
443 --------------
443 --------------
444
444
445 --------------
445 --------------
446 test L:um a b R:up a W: - 21 merge a and b to b
446 test L:um a b R:up a W: - 21 merge a and b to b
447 --------------
447 --------------
448 resolving manifests
448 resolving manifests
449 overwrite None partial False
449 overwrite None partial False
450 ancestor 924404dff337 local ec03c2ca8642+ remote f4db7e329e71
450 ancestor 924404dff337 local ec03c2ca8642+ remote f4db7e329e71
451 searching for copies back to rev 1
451 searching for copies back to rev 1
452 unmatched files in local:
452 unmatched files in local:
453 b
453 b
454 all copies found (* = to merge, ! = divergent):
454 all copies found (* = to merge, ! = divergent):
455 b -> a *
455 b -> a *
456 checking for directory renames
456 checking for directory renames
457 b: local moved to a -> m
457 b: local moved to a -> m
458 rev: versions differ -> m
458 rev: versions differ -> m
459 merging b and a
459 merging b and a
460 my b@ec03c2ca8642+ other a@f4db7e329e71 ancestor a@924404dff337
460 my b@ec03c2ca8642+ other a@f4db7e329e71 ancestor a@924404dff337
461 merging rev
461 merging rev
462 my rev@ec03c2ca8642+ other rev@f4db7e329e71 ancestor rev@924404dff337
462 my rev@ec03c2ca8642+ other rev@f4db7e329e71 ancestor rev@924404dff337
463 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
463 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
464 (branch merge, don't forget to commit)
464 (branch merge, don't forget to commit)
465 --------------
465 --------------
466 M b
466 M b
467 a
467 a
468 --------------
468 --------------
469
469
470 --------------
470 --------------
471 test L:nm a b R:up a c W: - 23 get c, keep b
471 test L:nm a b R:up a c W: - 23 get c, keep b
472 --------------
472 --------------
473 resolving manifests
473 resolving manifests
474 overwrite None partial False
474 overwrite None partial False
475 ancestor 924404dff337 local ecf3cb2a4219+ remote 2b958612230f
475 ancestor 924404dff337 local ecf3cb2a4219+ remote 2b958612230f
476 searching for copies back to rev 1
476 searching for copies back to rev 1
477 unmatched files in local:
477 unmatched files in local:
478 b
478 b
479 unmatched files in other:
479 unmatched files in other:
480 c
480 c
481 all copies found (* = to merge, ! = divergent):
481 all copies found (* = to merge, ! = divergent):
482 b -> a *
482 b -> a *
483 checking for directory renames
483 checking for directory renames
484 b: local moved to a -> m
484 b: local moved to a -> m
485 rev: versions differ -> m
485 rev: versions differ -> m
486 c: remote created -> g
486 c: remote created -> g
487 merging b and a
487 merging b and a
488 my b@ecf3cb2a4219+ other a@2b958612230f ancestor a@924404dff337
488 my b@ecf3cb2a4219+ other a@2b958612230f ancestor a@924404dff337
489 getting c
489 getting c
490 merging rev
490 merging rev
491 my rev@ecf3cb2a4219+ other rev@2b958612230f ancestor rev@924404dff337
491 my rev@ecf3cb2a4219+ other rev@2b958612230f ancestor rev@924404dff337
492 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
492 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
493 (branch merge, don't forget to commit)
493 (branch merge, don't forget to commit)
494 --------------
494 --------------
495 M b
495 M b
496 a
496 a
497 M c
497 M c
498 --------------
498 --------------
499
499
General Comments 0
You need to be logged in to leave comments. Login now