##// END OF EJS Templates
avoid unnecessary copy merges
Matt Mackall -
r3674:9103dab9 default
parent child Browse files
Show More
@@ -1,418 +1,420
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 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006 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 gettext as _
9 from i18n import gettext as _
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "errno util os tempfile")
11 demandload(globals(), "errno util os tempfile")
12
12
13 def filemerge(repo, fw, fo, wctx, mctx):
13 def filemerge(repo, fw, fo, wctx, mctx):
14 """perform a 3-way merge in the working directory
14 """perform a 3-way merge in the working directory
15
15
16 fw = filename in the working directory
16 fw = 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 f = os.fdopen(fd, "wb")
24 f = os.fdopen(fd, "wb")
25 repo.wwrite(ctx.path(), ctx.data(), f)
25 repo.wwrite(ctx.path(), ctx.data(), f)
26 f.close()
26 f.close()
27 return name
27 return name
28
28
29 fcm = wctx.filectx(fw)
29 fcm = wctx.filectx(fw)
30 fco = mctx.filectx(fo)
30 fco = mctx.filectx(fo)
31
31
32 if not fco.cmp(fcm.data()): # files identical?
32 if not fco.cmp(fcm.data()): # files identical?
33 return None
33 return None
34
34
35 fca = fcm.ancestor(fco)
35 fca = fcm.ancestor(fco)
36 if not fca:
36 if not fca:
37 fca = repo.filectx(fw, fileid=nullrev)
37 fca = repo.filectx(fw, fileid=nullrev)
38 a = repo.wjoin(fw)
38 a = repo.wjoin(fw)
39 b = temp("base", fca)
39 b = temp("base", fca)
40 c = temp("other", fco)
40 c = temp("other", fco)
41
41
42 if fw != fo:
42 if fw != fo:
43 repo.ui.status(_("merging %s and %s\n") % (fw, fo))
43 repo.ui.status(_("merging %s and %s\n") % (fw, fo))
44 else:
44 else:
45 repo.ui.status(_("merging %s\n") % fw)
45 repo.ui.status(_("merging %s\n") % fw)
46
46
47 repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
47 repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
48
48
49 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
49 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
50 or "hgmerge")
50 or "hgmerge")
51 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
51 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
52 environ={'HG_FILE': fw,
52 environ={'HG_FILE': fw,
53 'HG_MY_NODE': str(wctx.parents()[0]),
53 'HG_MY_NODE': str(wctx.parents()[0]),
54 'HG_OTHER_NODE': str(mctx)})
54 'HG_OTHER_NODE': str(mctx)})
55 if r:
55 if r:
56 repo.ui.warn(_("merging %s failed!\n") % fw)
56 repo.ui.warn(_("merging %s failed!\n") % fw)
57
57
58 os.unlink(b)
58 os.unlink(b)
59 os.unlink(c)
59 os.unlink(c)
60 return r
60 return r
61
61
62 def checkunknown(wctx, mctx):
62 def checkunknown(wctx, mctx):
63 "check for collisions between unknown files and files in mctx"
63 "check for collisions between unknown files and files in mctx"
64 man = mctx.manifest()
64 man = mctx.manifest()
65 for f in wctx.unknown():
65 for f in wctx.unknown():
66 if f in man:
66 if f in man:
67 if mctx.filectx(f).cmp(wctx.filectx(f).data()):
67 if mctx.filectx(f).cmp(wctx.filectx(f).data()):
68 raise util.Abort(_("untracked local file '%s' differs"\
68 raise util.Abort(_("untracked local file '%s' differs"\
69 " from remote version") % f)
69 " from remote version") % f)
70
70
71 def forgetremoved(wctx, mctx):
71 def forgetremoved(wctx, mctx):
72 """
72 """
73 Forget removed files
73 Forget removed files
74
74
75 If we're jumping between revisions (as opposed to merging), and if
75 If we're jumping between revisions (as opposed to merging), and if
76 neither the working directory nor the target rev has the file,
76 neither the working directory nor the target rev has the file,
77 then we need to remove it from the dirstate, to prevent the
77 then we need to remove it from the dirstate, to prevent the
78 dirstate from listing the file when it is no longer in the
78 dirstate from listing the file when it is no longer in the
79 manifest.
79 manifest.
80 """
80 """
81
81
82 action = []
82 action = []
83 man = mctx.manifest()
83 man = mctx.manifest()
84 for f in wctx.deleted() + wctx.removed():
84 for f in wctx.deleted() + wctx.removed():
85 if f not in man:
85 if f not in man:
86 action.append((f, "f"))
86 action.append((f, "f"))
87
87
88 return action
88 return action
89
89
90 def nonoverlap(d1, d2, d3):
90 def nonoverlap(d1, d2, d3):
91 "Return list of elements in d1 not in d2 or d3"
91 "Return list of elements in d1 not in d2 or d3"
92
92
93 l = []
93 l = []
94 for d in d1:
94 for d in d1:
95 if d not in d3 and d not in d2:
95 if d not in d3 and d not in d2:
96 l.append(d)
96 l.append(d)
97
97
98 l.sort()
98 l.sort()
99 return l
99 return l
100
100
101 def findold(fctx, limit):
101 def findold(fctx, limit):
102 "find files that path was copied from, back to linkrev limit"
102 "find files that path was copied from, back to linkrev limit"
103
103
104 old = {}
104 old = {}
105 orig = fctx.path()
105 orig = fctx.path()
106 visit = [fctx]
106 visit = [fctx]
107 while visit:
107 while visit:
108 fc = visit.pop()
108 fc = visit.pop()
109 if fc.rev() < limit:
109 if fc.rev() < limit:
110 continue
110 continue
111 if fc.path() != orig and fc.path() not in old:
111 if fc.path() != orig and fc.path() not in old:
112 old[fc.path()] = 1
112 old[fc.path()] = 1
113 visit += fc.parents()
113 visit += fc.parents()
114
114
115 old = old.keys()
115 old = old.keys()
116 old.sort()
116 old.sort()
117 return old
117 return old
118
118
119 def findcopies(repo, m1, m2, ma, limit):
119 def findcopies(repo, m1, m2, ma, limit):
120 """
120 """
121 Find moves and copies between m1 and m2 back to limit linkrev
121 Find moves and copies between m1 and m2 back to limit linkrev
122 """
122 """
123
123
124 if not repo.ui.configbool("merge", "followcopies", True):
124 if not repo.ui.configbool("merge", "followcopies", True):
125 return {}
125 return {}
126
126
127 # avoid silly behavior for update from empty dir
127 # avoid silly behavior for update from empty dir
128 if not m1:
128 if not m1:
129 return {}
129 return {}
130
130
131 dcopies = repo.dirstate.copies()
131 dcopies = repo.dirstate.copies()
132 copy = {}
132 copy = {}
133 match = {}
133 match = {}
134 u1 = nonoverlap(m1, m2, ma)
134 u1 = nonoverlap(m1, m2, ma)
135 u2 = nonoverlap(m2, m1, ma)
135 u2 = nonoverlap(m2, m1, ma)
136 ctx = util.cachefunc(lambda f, n: repo.filectx(f, fileid=n[:20]))
136 ctx = util.cachefunc(lambda f, n: repo.filectx(f, fileid=n[:20]))
137
137
138 def checkpair(c, f2, man):
138 def checkpair(c, f2, man):
139 ''' check if an apparent pair actually matches '''
139 ''' check if an apparent pair actually matches '''
140 c2 = ctx(f2, man[f2])
140 c2 = ctx(f2, man[f2])
141 ca = c.ancestor(c2)
141 ca = c.ancestor(c2)
142 if c == ca or c2 == ca:
143 return
142 if ca and ca.path() == c.path() or ca.path() == c2.path():
144 if ca and ca.path() == c.path() or ca.path() == c2.path():
143 copy[c.path()] = f2
145 copy[c.path()] = f2
144 copy[f2] = c.path()
146 copy[f2] = c.path()
145
147
146 for f in u1:
148 for f in u1:
147 c = ctx(dcopies.get(f, f), m1[f])
149 c = ctx(dcopies.get(f, f), m1[f])
148 for of in findold(c, limit):
150 for of in findold(c, limit):
149 if of in m2:
151 if of in m2:
150 checkpair(c, of, m2)
152 checkpair(c, of, m2)
151 else:
153 else:
152 match.setdefault(of, []).append(f)
154 match.setdefault(of, []).append(f)
153
155
154 for f in u2:
156 for f in u2:
155 c = ctx(f, m2[f])
157 c = ctx(f, m2[f])
156 for of in findold(c, limit):
158 for of in findold(c, limit):
157 if of in m1:
159 if of in m1:
158 checkpair(c, of, m1)
160 checkpair(c, of, m1)
159 elif of in match:
161 elif of in match:
160 for mf in match[of]:
162 for mf in match[of]:
161 checkpair(c, mf, m1)
163 checkpair(c, mf, m1)
162
164
163 return copy
165 return copy
164
166
165 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
167 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
166 """
168 """
167 Merge p1 and p2 with ancestor ma and generate merge action list
169 Merge p1 and p2 with ancestor ma and generate merge action list
168
170
169 overwrite = whether we clobber working files
171 overwrite = whether we clobber working files
170 partial = function to filter file lists
172 partial = function to filter file lists
171 """
173 """
172
174
173 repo.ui.note(_("resolving manifests\n"))
175 repo.ui.note(_("resolving manifests\n"))
174 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
176 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
175 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
177 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
176
178
177 m1 = p1.manifest()
179 m1 = p1.manifest()
178 m2 = p2.manifest()
180 m2 = p2.manifest()
179 ma = pa.manifest()
181 ma = pa.manifest()
180 backwards = (pa == p2)
182 backwards = (pa == p2)
181 action = []
183 action = []
182 copy = {}
184 copy = {}
183
185
184 def fmerge(f, f2=None, fa=None):
186 def fmerge(f, f2=None, fa=None):
185 """merge executable flags"""
187 """merge executable flags"""
186 if not f2:
188 if not f2:
187 f2 = f
189 f2 = f
188 fa = f
190 fa = f
189 a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2)
191 a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2)
190 return ((a^b) | (a^c)) ^ a
192 return ((a^b) | (a^c)) ^ a
191
193
192 def act(msg, m, f, *args):
194 def act(msg, m, f, *args):
193 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
195 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
194 action.append((f, m) + args)
196 action.append((f, m) + args)
195
197
196 if not (backwards or overwrite):
198 if not (backwards or overwrite):
197 copy = findcopies(repo, m1, m2, ma, pa.rev())
199 copy = findcopies(repo, m1, m2, ma, pa.rev())
198
200
199 # Compare manifests
201 # Compare manifests
200 for f, n in m1.iteritems():
202 for f, n in m1.iteritems():
201 if partial and not partial(f):
203 if partial and not partial(f):
202 continue
204 continue
203 if f in m2:
205 if f in m2:
204 # are files different?
206 # are files different?
205 if n != m2[f]:
207 if n != m2[f]:
206 a = ma.get(f, nullid)
208 a = ma.get(f, nullid)
207 # are both different from the ancestor?
209 # are both different from the ancestor?
208 if not overwrite and n != a and m2[f] != a:
210 if not overwrite and n != a and m2[f] != a:
209 act("versions differ", "m", f, f, f, fmerge(f), False)
211 act("versions differ", "m", f, f, f, fmerge(f), False)
210 # are we clobbering?
212 # are we clobbering?
211 # is remote's version newer?
213 # is remote's version newer?
212 # or are we going back in time and clean?
214 # or are we going back in time and clean?
213 elif overwrite or m2[f] != a or (backwards and not n[20:]):
215 elif overwrite or m2[f] != a or (backwards and not n[20:]):
214 act("remote is newer", "g", f, m2.execf(f))
216 act("remote is newer", "g", f, m2.execf(f))
215 # local is newer, not overwrite, check mode bits
217 # local is newer, not overwrite, check mode bits
216 elif fmerge(f) != m1.execf(f):
218 elif fmerge(f) != m1.execf(f):
217 act("update permissions", "e", f, m2.execf(f))
219 act("update permissions", "e", f, m2.execf(f))
218 # contents same, check mode bits
220 # contents same, check mode bits
219 elif m1.execf(f) != m2.execf(f):
221 elif m1.execf(f) != m2.execf(f):
220 if overwrite or fmerge(f) != m1.execf(f):
222 if overwrite or fmerge(f) != m1.execf(f):
221 act("update permissions", "e", f, m2.execf(f))
223 act("update permissions", "e", f, m2.execf(f))
222 elif f in copy:
224 elif f in copy:
223 f2 = copy[f]
225 f2 = copy[f]
224 if f in ma: # case 3,20 A/B/A
226 if f in ma: # case 3,20 A/B/A
225 act("remote moved", "m", f, f2, f2, fmerge(f, f2, f), True)
227 act("remote moved", "m", f, f2, f2, fmerge(f, f2, f), True)
226 else:
228 else:
227 if f2 in m1: # case 2 A,B/B/B
229 if f2 in m1: # case 2 A,B/B/B
228 act("local copied", "m",
230 act("local copied", "m",
229 f, f2, f, fmerge(f, f2, f2), False)
231 f, f2, f, fmerge(f, f2, f2), False)
230 else: # case 4,21 A/B/B
232 else: # case 4,21 A/B/B
231 act("local moved", "m",
233 act("local moved", "m",
232 f, f2, f, fmerge(f, f2, f2), False)
234 f, f2, f, fmerge(f, f2, f2), False)
233 elif f in ma:
235 elif f in ma:
234 if n != ma[f] and not overwrite:
236 if n != ma[f] and not overwrite:
235 if repo.ui.prompt(
237 if repo.ui.prompt(
236 (_(" local changed %s which remote deleted\n") % f) +
238 (_(" local changed %s which remote deleted\n") % f) +
237 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"):
239 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"):
238 act("prompt delete", "r", f)
240 act("prompt delete", "r", f)
239 else:
241 else:
240 act("other deleted", "r", f)
242 act("other deleted", "r", f)
241 else:
243 else:
242 # file is created on branch or in working directory
244 # file is created on branch or in working directory
243 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
245 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
244 act("remote deleted", "r", f)
246 act("remote deleted", "r", f)
245
247
246 for f, n in m2.iteritems():
248 for f, n in m2.iteritems():
247 if partial and not partial(f):
249 if partial and not partial(f):
248 continue
250 continue
249 if f in m1:
251 if f in m1:
250 continue
252 continue
251 if f in copy:
253 if f in copy:
252 f2 = copy[f]
254 f2 = copy[f]
253 if f2 not in m2: # already seen
255 if f2 not in m2: # already seen
254 continue
256 continue
255 # rename case 1, A/A,B/A
257 # rename case 1, A/A,B/A
256 act("remote copied", "m", f2, f, f, fmerge(f2, f, f2), False)
258 act("remote copied", "m", f2, f, f, fmerge(f2, f, f2), False)
257 elif f in ma:
259 elif f in ma:
258 if overwrite or backwards:
260 if overwrite or backwards:
259 act("recreating", "g", f, m2.execf(f))
261 act("recreating", "g", f, m2.execf(f))
260 elif n != ma[f]:
262 elif n != ma[f]:
261 if repo.ui.prompt(
263 if repo.ui.prompt(
262 (_("remote changed %s which local deleted\n") % f) +
264 (_("remote changed %s which local deleted\n") % f) +
263 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"):
265 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"):
264 act("prompt recreating", "g", f, m2.execf(f))
266 act("prompt recreating", "g", f, m2.execf(f))
265 else:
267 else:
266 act("remote created", "g", f, m2.execf(f))
268 act("remote created", "g", f, m2.execf(f))
267
269
268 return action
270 return action
269
271
270 def applyupdates(repo, action, wctx, mctx):
272 def applyupdates(repo, action, wctx, mctx):
271 "apply the merge action list to the working directory"
273 "apply the merge action list to the working directory"
272
274
273 updated, merged, removed, unresolved = 0, 0, 0, 0
275 updated, merged, removed, unresolved = 0, 0, 0, 0
274 action.sort()
276 action.sort()
275 for a in action:
277 for a in action:
276 f, m = a[:2]
278 f, m = a[:2]
277 if f[0] == "/":
279 if f[0] == "/":
278 continue
280 continue
279 if m == "r": # remove
281 if m == "r": # remove
280 repo.ui.note(_("removing %s\n") % f)
282 repo.ui.note(_("removing %s\n") % f)
281 util.audit_path(f)
283 util.audit_path(f)
282 try:
284 try:
283 util.unlink(repo.wjoin(f))
285 util.unlink(repo.wjoin(f))
284 except OSError, inst:
286 except OSError, inst:
285 if inst.errno != errno.ENOENT:
287 if inst.errno != errno.ENOENT:
286 repo.ui.warn(_("update failed to remove %s: %s!\n") %
288 repo.ui.warn(_("update failed to remove %s: %s!\n") %
287 (f, inst.strerror))
289 (f, inst.strerror))
288 removed += 1
290 removed += 1
289 elif m == "m": # merge
291 elif m == "m": # merge
290 f2, fd, flag, move = a[2:]
292 f2, fd, flag, move = a[2:]
291 r = filemerge(repo, f, f2, wctx, mctx)
293 r = filemerge(repo, f, f2, wctx, mctx)
292 if r > 0:
294 if r > 0:
293 unresolved += 1
295 unresolved += 1
294 else:
296 else:
295 if r is None:
297 if r is None:
296 updated += 1
298 updated += 1
297 else:
299 else:
298 merged += 1
300 merged += 1
299 if f != fd:
301 if f != fd:
300 repo.ui.debug(_("copying %s to %s\n") % (f, fd))
302 repo.ui.debug(_("copying %s to %s\n") % (f, fd))
301 repo.wwrite(fd, repo.wread(f))
303 repo.wwrite(fd, repo.wread(f))
302 if move:
304 if move:
303 repo.ui.debug(_("removing %s\n") % f)
305 repo.ui.debug(_("removing %s\n") % f)
304 os.unlink(repo.wjoin(f))
306 os.unlink(repo.wjoin(f))
305 util.set_exec(repo.wjoin(fd), flag)
307 util.set_exec(repo.wjoin(fd), flag)
306 elif m == "g": # get
308 elif m == "g": # get
307 flag = a[2]
309 flag = a[2]
308 repo.ui.note(_("getting %s\n") % f)
310 repo.ui.note(_("getting %s\n") % f)
309 t = mctx.filectx(f).data()
311 t = mctx.filectx(f).data()
310 repo.wwrite(f, t)
312 repo.wwrite(f, t)
311 util.set_exec(repo.wjoin(f), flag)
313 util.set_exec(repo.wjoin(f), flag)
312 updated += 1
314 updated += 1
313 elif m == "e": # exec
315 elif m == "e": # exec
314 flag = a[2]
316 flag = a[2]
315 util.set_exec(repo.wjoin(f), flag)
317 util.set_exec(repo.wjoin(f), flag)
316
318
317 return updated, merged, removed, unresolved
319 return updated, merged, removed, unresolved
318
320
319 def recordupdates(repo, action, branchmerge):
321 def recordupdates(repo, action, branchmerge):
320 "record merge actions to the dirstate"
322 "record merge actions to the dirstate"
321
323
322 for a in action:
324 for a in action:
323 f, m = a[:2]
325 f, m = a[:2]
324 if m == "r": # remove
326 if m == "r": # remove
325 if branchmerge:
327 if branchmerge:
326 repo.dirstate.update([f], 'r')
328 repo.dirstate.update([f], 'r')
327 else:
329 else:
328 repo.dirstate.forget([f])
330 repo.dirstate.forget([f])
329 elif m == "f": # forget
331 elif m == "f": # forget
330 repo.dirstate.forget([f])
332 repo.dirstate.forget([f])
331 elif m == "g": # get
333 elif m == "g": # get
332 if branchmerge:
334 if branchmerge:
333 repo.dirstate.update([f], 'n', st_mtime=-1)
335 repo.dirstate.update([f], 'n', st_mtime=-1)
334 else:
336 else:
335 repo.dirstate.update([f], 'n')
337 repo.dirstate.update([f], 'n')
336 elif m == "m": # merge
338 elif m == "m": # merge
337 f2, fd, flag, move = a[2:]
339 f2, fd, flag, move = a[2:]
338 if branchmerge:
340 if branchmerge:
339 # We've done a branch merge, mark this file as merged
341 # We've done a branch merge, mark this file as merged
340 # so that we properly record the merger later
342 # so that we properly record the merger later
341 repo.dirstate.update([fd], 'm')
343 repo.dirstate.update([fd], 'm')
342 if f != f2: # copy/rename
344 if f != f2: # copy/rename
343 if move:
345 if move:
344 repo.dirstate.update([f], 'r')
346 repo.dirstate.update([f], 'r')
345 if f != fd:
347 if f != fd:
346 repo.dirstate.copy(f, fd)
348 repo.dirstate.copy(f, fd)
347 else:
349 else:
348 repo.dirstate.copy(f2, fd)
350 repo.dirstate.copy(f2, fd)
349 else:
351 else:
350 # We've update-merged a locally modified file, so
352 # We've update-merged a locally modified file, so
351 # we set the dirstate to emulate a normal checkout
353 # we set the dirstate to emulate a normal checkout
352 # of that file some time in the past. Thus our
354 # of that file some time in the past. Thus our
353 # merge will appear as a normal local file
355 # merge will appear as a normal local file
354 # modification.
356 # modification.
355 repo.dirstate.update([fd], 'n', st_size=-1, st_mtime=-1)
357 repo.dirstate.update([fd], 'n', st_size=-1, st_mtime=-1)
356 if move:
358 if move:
357 repo.dirstate.forget([f])
359 repo.dirstate.forget([f])
358
360
359 def update(repo, node, branchmerge, force, partial, wlock):
361 def update(repo, node, branchmerge, force, partial, wlock):
360 """
362 """
361 Perform a merge between the working directory and the given node
363 Perform a merge between the working directory and the given node
362
364
363 branchmerge = whether to merge between branches
365 branchmerge = whether to merge between branches
364 force = whether to force branch merging or file overwriting
366 force = whether to force branch merging or file overwriting
365 partial = a function to filter file lists (dirstate not updated)
367 partial = a function to filter file lists (dirstate not updated)
366 wlock = working dir lock, if already held
368 wlock = working dir lock, if already held
367 """
369 """
368
370
369 if not wlock:
371 if not wlock:
370 wlock = repo.wlock()
372 wlock = repo.wlock()
371
373
372 overwrite = force and not branchmerge
374 overwrite = force and not branchmerge
373 forcemerge = force and branchmerge
375 forcemerge = force and branchmerge
374 wc = repo.workingctx()
376 wc = repo.workingctx()
375 pl = wc.parents()
377 pl = wc.parents()
376 p1, p2 = pl[0], repo.changectx(node)
378 p1, p2 = pl[0], repo.changectx(node)
377 pa = p1.ancestor(p2)
379 pa = p1.ancestor(p2)
378 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
380 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
379
381
380 ### check phase
382 ### check phase
381 if not overwrite and len(pl) > 1:
383 if not overwrite and len(pl) > 1:
382 raise util.Abort(_("outstanding uncommitted merges"))
384 raise util.Abort(_("outstanding uncommitted merges"))
383 if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
385 if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
384 if branchmerge:
386 if branchmerge:
385 raise util.Abort(_("there is nothing to merge, just use "
387 raise util.Abort(_("there is nothing to merge, just use "
386 "'hg update' or look at 'hg heads'"))
388 "'hg update' or look at 'hg heads'"))
387 elif not (overwrite or branchmerge):
389 elif not (overwrite or branchmerge):
388 raise util.Abort(_("update spans branches, use 'hg merge' "
390 raise util.Abort(_("update spans branches, use 'hg merge' "
389 "or 'hg update -C' to lose changes"))
391 "or 'hg update -C' to lose changes"))
390 if branchmerge and not forcemerge:
392 if branchmerge and not forcemerge:
391 if wc.files():
393 if wc.files():
392 raise util.Abort(_("outstanding uncommitted changes"))
394 raise util.Abort(_("outstanding uncommitted changes"))
393
395
394 ### calculate phase
396 ### calculate phase
395 action = []
397 action = []
396 if not force:
398 if not force:
397 checkunknown(wc, p2)
399 checkunknown(wc, p2)
398 if not branchmerge:
400 if not branchmerge:
399 action += forgetremoved(wc, p2)
401 action += forgetremoved(wc, p2)
400 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
402 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
401
403
402 ### apply phase
404 ### apply phase
403 if not branchmerge: # just jump to the new rev
405 if not branchmerge: # just jump to the new rev
404 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
406 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
405 if not partial:
407 if not partial:
406 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
408 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
407
409
408 stats = applyupdates(repo, action, wc, p2)
410 stats = applyupdates(repo, action, wc, p2)
409
411
410 if not partial:
412 if not partial:
411 recordupdates(repo, action, branchmerge)
413 recordupdates(repo, action, branchmerge)
412 repo.dirstate.setparents(fp1, fp2)
414 repo.dirstate.setparents(fp1, fp2)
413 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
415 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
414 if not branchmerge:
416 if not branchmerge:
415 repo.opener("branch", "w").write(p2.branch() + "\n")
417 repo.opener("branch", "w").write(p2.branch() + "\n")
416
418
417 return stats
419 return stats
418
420
@@ -1,10 +1,9
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 pulling from ../a
2 pulling from ../a
3 searching for changes
3 searching for changes
4 adding changesets
4 adding changesets
5 adding manifests
5 adding manifests
6 adding file changes
6 adding file changes
7 added 2 changesets with 2 changes to 1 files
7 added 2 changesets with 2 changes to 1 files
8 (run 'hg update' to get a working copy)
8 (run 'hg update' to get a working copy)
9 merging a and b
9 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
10 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
@@ -1,414 +1,409
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 rev: versions differ -> m
7 rev: versions differ -> m
8 a: remote copied -> m
8 a: remote copied -> m
9 merging a and b
9 merging a and b
10 my a@e300d1c794ec+ other b@735846fee2d7 ancestor a@924404dff337
10 my a@e300d1c794ec+ other b@735846fee2d7 ancestor a@924404dff337
11 copying a to b
11 copying a to b
12 merging rev
12 merging rev
13 my rev@e300d1c794ec+ other rev@735846fee2d7 ancestor rev@924404dff337
13 my rev@e300d1c794ec+ other rev@735846fee2d7 ancestor rev@924404dff337
14 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
14 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
15 (branch merge, don't forget to commit)
15 (branch merge, don't forget to commit)
16 --------------
16 --------------
17 M a
17 M a
18 M b
18 M b
19 a
19 a
20 --------------
20 --------------
21
21
22 --------------
22 --------------
23 test L:nc a b R:up a W: - 2 get rem change to a and b
23 test L:nc a b R:up a W: - 2 get rem change to a and b
24 --------------
24 --------------
25 resolving manifests
25 resolving manifests
26 overwrite None partial False
26 overwrite None partial False
27 ancestor 924404dff337 local ac809aeed39a+ remote f4db7e329e71
27 ancestor 924404dff337 local ac809aeed39a+ remote f4db7e329e71
28 a: remote is newer -> g
28 a: remote is newer -> g
29 b: local copied -> m
29 b: local copied -> m
30 rev: versions differ -> m
30 rev: versions differ -> m
31 getting a
31 getting a
32 merging b and a
32 merging b and a
33 my b@ac809aeed39a+ other a@f4db7e329e71 ancestor a@924404dff337
33 my b@ac809aeed39a+ other a@f4db7e329e71 ancestor a@924404dff337
34 merging rev
34 merging rev
35 my rev@ac809aeed39a+ other rev@f4db7e329e71 ancestor rev@924404dff337
35 my rev@ac809aeed39a+ other rev@f4db7e329e71 ancestor rev@924404dff337
36 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
36 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
37 (branch merge, don't forget to commit)
37 (branch merge, don't forget to commit)
38 --------------
38 --------------
39 M a
39 M a
40 M b
40 M b
41 a
41 a
42 --------------
42 --------------
43
43
44 --------------
44 --------------
45 test L:up a R:nm a b W: - 3 get local a change to b, remove a
45 test L:up a R:nm a b W: - 3 get local a change to b, remove a
46 --------------
46 --------------
47 resolving manifests
47 resolving manifests
48 overwrite None partial False
48 overwrite None partial False
49 ancestor 924404dff337 local e300d1c794ec+ remote e03727d2d66b
49 ancestor 924404dff337 local e300d1c794ec+ remote e03727d2d66b
50 a: remote moved -> m
50 a: remote moved -> m
51 rev: versions differ -> m
51 rev: versions differ -> m
52 merging a and b
52 merging a and b
53 my a@e300d1c794ec+ other b@e03727d2d66b ancestor a@924404dff337
53 my a@e300d1c794ec+ other b@e03727d2d66b ancestor a@924404dff337
54 copying a to b
54 copying a to b
55 removing a
55 removing a
56 merging rev
56 merging rev
57 my rev@e300d1c794ec+ other rev@e03727d2d66b ancestor rev@924404dff337
57 my rev@e300d1c794ec+ other rev@e03727d2d66b ancestor rev@924404dff337
58 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
58 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
59 (branch merge, don't forget to commit)
59 (branch merge, don't forget to commit)
60 --------------
60 --------------
61 M b
61 M b
62 a
62 a
63 --------------
63 --------------
64
64
65 --------------
65 --------------
66 test L:nm a b R:up a W: - 4 get remote change to b
66 test L:nm a b R:up a W: - 4 get remote change to b
67 --------------
67 --------------
68 resolving manifests
68 resolving manifests
69 overwrite None partial False
69 overwrite None partial False
70 ancestor 924404dff337 local ecf3cb2a4219+ remote f4db7e329e71
70 ancestor 924404dff337 local ecf3cb2a4219+ remote f4db7e329e71
71 b: local moved -> m
71 b: local moved -> m
72 rev: versions differ -> m
72 rev: versions differ -> m
73 merging b and a
73 merging b and a
74 my b@ecf3cb2a4219+ other a@f4db7e329e71 ancestor a@924404dff337
74 my b@ecf3cb2a4219+ other a@f4db7e329e71 ancestor a@924404dff337
75 merging rev
75 merging rev
76 my rev@ecf3cb2a4219+ other rev@f4db7e329e71 ancestor rev@924404dff337
76 my rev@ecf3cb2a4219+ other rev@f4db7e329e71 ancestor rev@924404dff337
77 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
77 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
78 (branch merge, don't forget to commit)
78 (branch merge, don't forget to commit)
79 --------------
79 --------------
80 M b
80 M b
81 a
81 a
82 --------------
82 --------------
83
83
84 --------------
84 --------------
85 test L: R:nc a b W: - 5 get b
85 test L: R:nc a b W: - 5 get b
86 --------------
86 --------------
87 resolving manifests
87 resolving manifests
88 overwrite None partial False
88 overwrite None partial False
89 ancestor 924404dff337 local 94b33a1b7f2d+ remote 735846fee2d7
89 ancestor 924404dff337 local 94b33a1b7f2d+ remote 735846fee2d7
90 rev: versions differ -> m
90 rev: versions differ -> m
91 a: remote copied -> m
91 b: remote created -> g
92 copying a to b
92 getting b
93 merging rev
93 merging rev
94 my rev@94b33a1b7f2d+ other rev@735846fee2d7 ancestor rev@924404dff337
94 my rev@94b33a1b7f2d+ other rev@735846fee2d7 ancestor rev@924404dff337
95 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
95 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
96 (branch merge, don't forget to commit)
96 (branch merge, don't forget to commit)
97 --------------
97 --------------
98 M b
98 M b
99 a
100 C a
99 C a
101 --------------
100 --------------
102
101
103 --------------
102 --------------
104 test L:nc a b R: W: - 6 nothing
103 test L:nc a b R: W: - 6 nothing
105 --------------
104 --------------
106 resolving manifests
105 resolving manifests
107 overwrite None partial False
106 overwrite None partial False
108 ancestor 924404dff337 local ac809aeed39a+ remote 97c705ade336
107 ancestor 924404dff337 local ac809aeed39a+ remote 97c705ade336
109 b: local copied -> m
110 rev: versions differ -> m
108 rev: versions differ -> m
111 merging rev
109 merging rev
112 my rev@ac809aeed39a+ other rev@97c705ade336 ancestor rev@924404dff337
110 my rev@ac809aeed39a+ other rev@97c705ade336 ancestor rev@924404dff337
113 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
111 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
114 (branch merge, don't forget to commit)
112 (branch merge, don't forget to commit)
115 --------------
113 --------------
116 M b
117 a
118 C a
114 C a
115 C b
119 --------------
116 --------------
120
117
121 --------------
118 --------------
122 test L: R:nm a b W: - 7 get b
119 test L: R:nm a b W: - 7 get b
123 --------------
120 --------------
124 resolving manifests
121 resolving manifests
125 overwrite None partial False
122 overwrite None partial False
126 ancestor 924404dff337 local 94b33a1b7f2d+ remote e03727d2d66b
123 ancestor 924404dff337 local 94b33a1b7f2d+ remote e03727d2d66b
127 a: remote moved -> m
124 a: other deleted -> r
128 rev: versions differ -> m
125 rev: versions differ -> m
129 copying a to b
126 b: remote created -> g
130 removing a
127 removing a
128 getting b
131 merging rev
129 merging rev
132 my rev@94b33a1b7f2d+ other rev@e03727d2d66b ancestor rev@924404dff337
130 my rev@94b33a1b7f2d+ other rev@e03727d2d66b ancestor rev@924404dff337
133 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
131 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
134 (branch merge, don't forget to commit)
132 (branch merge, don't forget to commit)
135 --------------
133 --------------
136 M b
134 M b
137 a
138 --------------
135 --------------
139
136
140 --------------
137 --------------
141 test L:nm a b R: W: - 8 nothing
138 test L:nm a b R: W: - 8 nothing
142 --------------
139 --------------
143 resolving manifests
140 resolving manifests
144 overwrite None partial False
141 overwrite None partial False
145 ancestor 924404dff337 local ecf3cb2a4219+ remote 97c705ade336
142 ancestor 924404dff337 local ecf3cb2a4219+ remote 97c705ade336
146 b: local moved -> m
147 rev: versions differ -> m
143 rev: versions differ -> m
148 merging rev
144 merging rev
149 my rev@ecf3cb2a4219+ other rev@97c705ade336 ancestor rev@924404dff337
145 my rev@ecf3cb2a4219+ other rev@97c705ade336 ancestor rev@924404dff337
150 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
146 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
151 (branch merge, don't forget to commit)
147 (branch merge, don't forget to commit)
152 --------------
148 --------------
153 M b
149 C b
154 a
155 --------------
150 --------------
156
151
157 --------------
152 --------------
158 test L:um a b R:um a b W: - 9 do merge with ancestor in a
153 test L:um a b R:um a b W: - 9 do merge with ancestor in a
159 --------------
154 --------------
160 resolving manifests
155 resolving manifests
161 overwrite None partial False
156 overwrite None partial False
162 ancestor 924404dff337 local ec03c2ca8642+ remote 79cc6877a3b7
157 ancestor 924404dff337 local ec03c2ca8642+ remote 79cc6877a3b7
163 b: versions differ -> m
158 b: versions differ -> m
164 rev: versions differ -> m
159 rev: versions differ -> m
165 merging b
160 merging b
166 my b@ec03c2ca8642+ other b@79cc6877a3b7 ancestor a@924404dff337
161 my b@ec03c2ca8642+ other b@79cc6877a3b7 ancestor a@924404dff337
167 merging rev
162 merging rev
168 my rev@ec03c2ca8642+ other rev@79cc6877a3b7 ancestor rev@924404dff337
163 my rev@ec03c2ca8642+ other rev@79cc6877a3b7 ancestor rev@924404dff337
169 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
164 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
170 (branch merge, don't forget to commit)
165 (branch merge, don't forget to commit)
171 --------------
166 --------------
172 M b
167 M b
173 --------------
168 --------------
174
169
175 --------------
170 --------------
176 test L:nm a b R:nm a c W: - 11 get c, keep b
171 test L:nm a b R:nm a c W: - 11 get c, keep b
177 --------------
172 --------------
178 resolving manifests
173 resolving manifests
179 overwrite None partial False
174 overwrite None partial False
180 ancestor 924404dff337 local ecf3cb2a4219+ remote e6abcc1a30c2
175 ancestor 924404dff337 local ecf3cb2a4219+ remote e6abcc1a30c2
181 rev: versions differ -> m
176 rev: versions differ -> m
182 c: remote created -> g
177 c: remote created -> g
183 getting c
178 getting c
184 merging rev
179 merging rev
185 my rev@ecf3cb2a4219+ other rev@e6abcc1a30c2 ancestor rev@924404dff337
180 my rev@ecf3cb2a4219+ other rev@e6abcc1a30c2 ancestor rev@924404dff337
186 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
181 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
187 (branch merge, don't forget to commit)
182 (branch merge, don't forget to commit)
188 --------------
183 --------------
189 M c
184 M c
190 C b
185 C b
191 --------------
186 --------------
192
187
193 --------------
188 --------------
194 test L:nc a b R:up b W: - 12 merge b no ancestor
189 test L:nc a b R:up b W: - 12 merge b no ancestor
195 --------------
190 --------------
196 resolving manifests
191 resolving manifests
197 overwrite None partial False
192 overwrite None partial False
198 ancestor 924404dff337 local ac809aeed39a+ remote af30c7647fc7
193 ancestor 924404dff337 local ac809aeed39a+ remote af30c7647fc7
199 b: versions differ -> m
194 b: versions differ -> m
200 rev: versions differ -> m
195 rev: versions differ -> m
201 merging b
196 merging b
202 my b@ac809aeed39a+ other b@af30c7647fc7 ancestor b@000000000000
197 my b@ac809aeed39a+ other b@af30c7647fc7 ancestor b@000000000000
203 merging rev
198 merging rev
204 my rev@ac809aeed39a+ other rev@af30c7647fc7 ancestor rev@924404dff337
199 my rev@ac809aeed39a+ other rev@af30c7647fc7 ancestor rev@924404dff337
205 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
200 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
206 (branch merge, don't forget to commit)
201 (branch merge, don't forget to commit)
207 --------------
202 --------------
208 M b
203 M b
209 C a
204 C a
210 --------------
205 --------------
211
206
212 --------------
207 --------------
213 test L:up b R:nm a b W: - 13 merge b no ancestor
208 test L:up b R:nm a b W: - 13 merge b no ancestor
214 --------------
209 --------------
215 resolving manifests
210 resolving manifests
216 overwrite None partial False
211 overwrite None partial False
217 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
212 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
218 a: other deleted -> r
213 a: other deleted -> r
219 b: versions differ -> m
214 b: versions differ -> m
220 rev: versions differ -> m
215 rev: versions differ -> m
221 removing a
216 removing a
222 merging b
217 merging b
223 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
218 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
224 merging rev
219 merging rev
225 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
220 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
226 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
221 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
227 (branch merge, don't forget to commit)
222 (branch merge, don't forget to commit)
228 --------------
223 --------------
229 M b
224 M b
230 --------------
225 --------------
231
226
232 --------------
227 --------------
233 test L:nc a b R:up a b W: - 14 merge b no ancestor
228 test L:nc a b R:up a b W: - 14 merge b no ancestor
234 --------------
229 --------------
235 resolving manifests
230 resolving manifests
236 overwrite None partial False
231 overwrite None partial False
237 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
232 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
238 a: remote is newer -> g
233 a: remote is newer -> g
239 b: versions differ -> m
234 b: versions differ -> m
240 rev: versions differ -> m
235 rev: versions differ -> m
241 getting a
236 getting a
242 merging b
237 merging b
243 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
238 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
244 merging rev
239 merging rev
245 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
240 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
246 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
241 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
247 (branch merge, don't forget to commit)
242 (branch merge, don't forget to commit)
248 --------------
243 --------------
249 M a
244 M a
250 M b
245 M b
251 --------------
246 --------------
252
247
253 --------------
248 --------------
254 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
249 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
255 --------------
250 --------------
256 resolving manifests
251 resolving manifests
257 overwrite None partial False
252 overwrite None partial False
258 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
253 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
259 a: other deleted -> r
254 a: other deleted -> r
260 b: versions differ -> m
255 b: versions differ -> m
261 rev: versions differ -> m
256 rev: versions differ -> m
262 removing a
257 removing a
263 merging b
258 merging b
264 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
259 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
265 merging rev
260 merging rev
266 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
261 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
267 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
262 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
268 (branch merge, don't forget to commit)
263 (branch merge, don't forget to commit)
269 --------------
264 --------------
270 M b
265 M b
271 --------------
266 --------------
272
267
273 --------------
268 --------------
274 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
269 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
275 --------------
270 --------------
276 resolving manifests
271 resolving manifests
277 overwrite None partial False
272 overwrite None partial False
278 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
273 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
279 a: remote is newer -> g
274 a: remote is newer -> g
280 b: versions differ -> m
275 b: versions differ -> m
281 rev: versions differ -> m
276 rev: versions differ -> m
282 getting a
277 getting a
283 merging b
278 merging b
284 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
279 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
285 merging rev
280 merging rev
286 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
281 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
287 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
282 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
288 (branch merge, don't forget to commit)
283 (branch merge, don't forget to commit)
289 --------------
284 --------------
290 M a
285 M a
291 M b
286 M b
292 --------------
287 --------------
293
288
294 --------------
289 --------------
295 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
290 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
296 --------------
291 --------------
297 resolving manifests
292 resolving manifests
298 overwrite None partial False
293 overwrite None partial False
299 ancestor 924404dff337 local 0b76e65c8289+ remote 735846fee2d7
294 ancestor 924404dff337 local 0b76e65c8289+ remote 735846fee2d7
300 b: versions differ -> m
295 b: versions differ -> m
301 rev: versions differ -> m
296 rev: versions differ -> m
302 merging b
297 merging b
303 my b@0b76e65c8289+ other b@735846fee2d7 ancestor b@000000000000
298 my b@0b76e65c8289+ other b@735846fee2d7 ancestor b@000000000000
304 merging rev
299 merging rev
305 my rev@0b76e65c8289+ other rev@735846fee2d7 ancestor rev@924404dff337
300 my rev@0b76e65c8289+ other rev@735846fee2d7 ancestor rev@924404dff337
306 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
301 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
307 (branch merge, don't forget to commit)
302 (branch merge, don't forget to commit)
308 --------------
303 --------------
309 M b
304 M b
310 C a
305 C a
311 --------------
306 --------------
312
307
313 --------------
308 --------------
314 test L:nm a b R:up a b W: - 18 merge b no ancestor
309 test L:nm a b R:up a b W: - 18 merge b no ancestor
315 --------------
310 --------------
316 resolving manifests
311 resolving manifests
317 overwrite None partial False
312 overwrite None partial False
318 ancestor 924404dff337 local ecf3cb2a4219+ remote 8dbce441892a
313 ancestor 924404dff337 local ecf3cb2a4219+ remote 8dbce441892a
319 b: versions differ -> m
314 b: versions differ -> m
320 rev: versions differ -> m
315 rev: versions differ -> m
321 a: prompt recreating -> g
316 a: prompt recreating -> g
322 getting a
317 getting a
323 merging b
318 merging b
324 my b@ecf3cb2a4219+ other b@8dbce441892a ancestor b@000000000000
319 my b@ecf3cb2a4219+ other b@8dbce441892a ancestor b@000000000000
325 merging rev
320 merging rev
326 my rev@ecf3cb2a4219+ other rev@8dbce441892a ancestor rev@924404dff337
321 my rev@ecf3cb2a4219+ other rev@8dbce441892a ancestor rev@924404dff337
327 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
322 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
328 (branch merge, don't forget to commit)
323 (branch merge, don't forget to commit)
329 --------------
324 --------------
330 M a
325 M a
331 M b
326 M b
332 --------------
327 --------------
333
328
334 --------------
329 --------------
335 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
330 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
336 --------------
331 --------------
337 resolving manifests
332 resolving manifests
338 overwrite None partial False
333 overwrite None partial False
339 ancestor 924404dff337 local 0b76e65c8289+ remote e03727d2d66b
334 ancestor 924404dff337 local 0b76e65c8289+ remote e03727d2d66b
340 b: versions differ -> m
335 b: versions differ -> m
341 rev: versions differ -> m
336 rev: versions differ -> m
342 merging b
337 merging b
343 my b@0b76e65c8289+ other b@e03727d2d66b ancestor b@000000000000
338 my b@0b76e65c8289+ other b@e03727d2d66b ancestor b@000000000000
344 merging rev
339 merging rev
345 my rev@0b76e65c8289+ other rev@e03727d2d66b ancestor rev@924404dff337
340 my rev@0b76e65c8289+ other rev@e03727d2d66b ancestor rev@924404dff337
346 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
341 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
347 (branch merge, don't forget to commit)
342 (branch merge, don't forget to commit)
348 --------------
343 --------------
349 M b
344 M b
350 C a
345 C a
351 --------------
346 --------------
352
347
353 --------------
348 --------------
354 test L:up a R:um a b W: - 20 merge a and b to b, remove a
349 test L:up a R:um a b W: - 20 merge a and b to b, remove a
355 --------------
350 --------------
356 resolving manifests
351 resolving manifests
357 overwrite None partial False
352 overwrite None partial False
358 ancestor 924404dff337 local e300d1c794ec+ remote 79cc6877a3b7
353 ancestor 924404dff337 local e300d1c794ec+ remote 79cc6877a3b7
359 a: remote moved -> m
354 a: remote moved -> m
360 rev: versions differ -> m
355 rev: versions differ -> m
361 merging a and b
356 merging a and b
362 my a@e300d1c794ec+ other b@79cc6877a3b7 ancestor a@924404dff337
357 my a@e300d1c794ec+ other b@79cc6877a3b7 ancestor a@924404dff337
363 copying a to b
358 copying a to b
364 removing a
359 removing a
365 merging rev
360 merging rev
366 my rev@e300d1c794ec+ other rev@79cc6877a3b7 ancestor rev@924404dff337
361 my rev@e300d1c794ec+ other rev@79cc6877a3b7 ancestor rev@924404dff337
367 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
362 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
368 (branch merge, don't forget to commit)
363 (branch merge, don't forget to commit)
369 --------------
364 --------------
370 M b
365 M b
371 a
366 a
372 --------------
367 --------------
373
368
374 --------------
369 --------------
375 test L:um a b R:up a W: - 21 merge a and b to b
370 test L:um a b R:up a W: - 21 merge a and b to b
376 --------------
371 --------------
377 resolving manifests
372 resolving manifests
378 overwrite None partial False
373 overwrite None partial False
379 ancestor 924404dff337 local ec03c2ca8642+ remote f4db7e329e71
374 ancestor 924404dff337 local ec03c2ca8642+ remote f4db7e329e71
380 b: local moved -> m
375 b: local moved -> m
381 rev: versions differ -> m
376 rev: versions differ -> m
382 merging b and a
377 merging b and a
383 my b@ec03c2ca8642+ other a@f4db7e329e71 ancestor a@924404dff337
378 my b@ec03c2ca8642+ other a@f4db7e329e71 ancestor a@924404dff337
384 merging rev
379 merging rev
385 my rev@ec03c2ca8642+ other rev@f4db7e329e71 ancestor rev@924404dff337
380 my rev@ec03c2ca8642+ other rev@f4db7e329e71 ancestor rev@924404dff337
386 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
381 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
387 (branch merge, don't forget to commit)
382 (branch merge, don't forget to commit)
388 --------------
383 --------------
389 M b
384 M b
390 a
385 a
391 --------------
386 --------------
392
387
393 --------------
388 --------------
394 test L:nm a b R:up a c W: - 23 get c, keep b
389 test L:nm a b R:up a c W: - 23 get c, keep b
395 --------------
390 --------------
396 resolving manifests
391 resolving manifests
397 overwrite None partial False
392 overwrite None partial False
398 ancestor 924404dff337 local ecf3cb2a4219+ remote 2b958612230f
393 ancestor 924404dff337 local ecf3cb2a4219+ remote 2b958612230f
399 b: local moved -> m
394 b: local moved -> m
400 rev: versions differ -> m
395 rev: versions differ -> m
401 c: remote created -> g
396 c: remote created -> g
402 merging b and a
397 merging b and a
403 my b@ecf3cb2a4219+ other a@2b958612230f ancestor a@924404dff337
398 my b@ecf3cb2a4219+ other a@2b958612230f ancestor a@924404dff337
404 getting c
399 getting c
405 merging rev
400 merging rev
406 my rev@ecf3cb2a4219+ other rev@2b958612230f ancestor rev@924404dff337
401 my rev@ecf3cb2a4219+ other rev@2b958612230f ancestor rev@924404dff337
407 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
402 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
408 (branch merge, don't forget to commit)
403 (branch merge, don't forget to commit)
409 --------------
404 --------------
410 M b
405 M b
411 a
406 a
412 M c
407 M c
413 --------------
408 --------------
414
409
General Comments 0
You need to be logged in to leave comments. Login now