##// END OF EJS Templates
merge: don't indent "local changed %s which remote deleted" prompt...
Mads Kiilerich -
r18543:c8ba98bf default
parent child Browse files
Show More
@@ -1,643 +1,643 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 of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import nullid, nullrev, hex, bin
8 from node import nullid, nullrev, hex, bin
9 from i18n import _
9 from i18n import _
10 import error, util, filemerge, copies, subrepo
10 import error, util, filemerge, copies, subrepo
11 import errno, os, shutil
11 import errno, os, shutil
12
12
13 class mergestate(object):
13 class mergestate(object):
14 '''track 3-way merge state of individual files'''
14 '''track 3-way merge state of individual files'''
15 def __init__(self, repo):
15 def __init__(self, repo):
16 self._repo = repo
16 self._repo = repo
17 self._dirty = False
17 self._dirty = False
18 self._read()
18 self._read()
19 def reset(self, node=None):
19 def reset(self, node=None):
20 self._state = {}
20 self._state = {}
21 if node:
21 if node:
22 self._local = node
22 self._local = node
23 shutil.rmtree(self._repo.join("merge"), True)
23 shutil.rmtree(self._repo.join("merge"), True)
24 self._dirty = False
24 self._dirty = False
25 def _read(self):
25 def _read(self):
26 self._state = {}
26 self._state = {}
27 try:
27 try:
28 f = self._repo.opener("merge/state")
28 f = self._repo.opener("merge/state")
29 for i, l in enumerate(f):
29 for i, l in enumerate(f):
30 if i == 0:
30 if i == 0:
31 self._local = bin(l[:-1])
31 self._local = bin(l[:-1])
32 else:
32 else:
33 bits = l[:-1].split("\0")
33 bits = l[:-1].split("\0")
34 self._state[bits[0]] = bits[1:]
34 self._state[bits[0]] = bits[1:]
35 f.close()
35 f.close()
36 except IOError, err:
36 except IOError, err:
37 if err.errno != errno.ENOENT:
37 if err.errno != errno.ENOENT:
38 raise
38 raise
39 self._dirty = False
39 self._dirty = False
40 def commit(self):
40 def commit(self):
41 if self._dirty:
41 if self._dirty:
42 f = self._repo.opener("merge/state", "w")
42 f = self._repo.opener("merge/state", "w")
43 f.write(hex(self._local) + "\n")
43 f.write(hex(self._local) + "\n")
44 for d, v in self._state.iteritems():
44 for d, v in self._state.iteritems():
45 f.write("\0".join([d] + v) + "\n")
45 f.write("\0".join([d] + v) + "\n")
46 f.close()
46 f.close()
47 self._dirty = False
47 self._dirty = False
48 def add(self, fcl, fco, fca, fd):
48 def add(self, fcl, fco, fca, fd):
49 hash = util.sha1(fcl.path()).hexdigest()
49 hash = util.sha1(fcl.path()).hexdigest()
50 self._repo.opener.write("merge/" + hash, fcl.data())
50 self._repo.opener.write("merge/" + hash, fcl.data())
51 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
51 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
52 hex(fca.filenode()), fco.path(), fcl.flags()]
52 hex(fca.filenode()), fco.path(), fcl.flags()]
53 self._dirty = True
53 self._dirty = True
54 def __contains__(self, dfile):
54 def __contains__(self, dfile):
55 return dfile in self._state
55 return dfile in self._state
56 def __getitem__(self, dfile):
56 def __getitem__(self, dfile):
57 return self._state[dfile][0]
57 return self._state[dfile][0]
58 def __iter__(self):
58 def __iter__(self):
59 l = self._state.keys()
59 l = self._state.keys()
60 l.sort()
60 l.sort()
61 for f in l:
61 for f in l:
62 yield f
62 yield f
63 def mark(self, dfile, state):
63 def mark(self, dfile, state):
64 self._state[dfile][0] = state
64 self._state[dfile][0] = state
65 self._dirty = True
65 self._dirty = True
66 def resolve(self, dfile, wctx, octx):
66 def resolve(self, dfile, wctx, octx):
67 if self[dfile] == 'r':
67 if self[dfile] == 'r':
68 return 0
68 return 0
69 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
69 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
70 fcd = wctx[dfile]
70 fcd = wctx[dfile]
71 fco = octx[ofile]
71 fco = octx[ofile]
72 fca = self._repo.filectx(afile, fileid=anode)
72 fca = self._repo.filectx(afile, fileid=anode)
73 # "premerge" x flags
73 # "premerge" x flags
74 flo = fco.flags()
74 flo = fco.flags()
75 fla = fca.flags()
75 fla = fca.flags()
76 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
76 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
77 if fca.node() == nullid:
77 if fca.node() == nullid:
78 self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
78 self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
79 afile)
79 afile)
80 elif flags == fla:
80 elif flags == fla:
81 flags = flo
81 flags = flo
82 # restore local
82 # restore local
83 f = self._repo.opener("merge/" + hash)
83 f = self._repo.opener("merge/" + hash)
84 self._repo.wwrite(dfile, f.read(), flags)
84 self._repo.wwrite(dfile, f.read(), flags)
85 f.close()
85 f.close()
86 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
86 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
87 if r is None:
87 if r is None:
88 # no real conflict
88 # no real conflict
89 del self._state[dfile]
89 del self._state[dfile]
90 elif not r:
90 elif not r:
91 self.mark(dfile, 'r')
91 self.mark(dfile, 'r')
92 return r
92 return r
93
93
94 def _checkunknownfile(repo, wctx, mctx, f):
94 def _checkunknownfile(repo, wctx, mctx, f):
95 return (not repo.dirstate._ignore(f)
95 return (not repo.dirstate._ignore(f)
96 and os.path.isfile(repo.wjoin(f))
96 and os.path.isfile(repo.wjoin(f))
97 and repo.dirstate.normalize(f) not in repo.dirstate
97 and repo.dirstate.normalize(f) not in repo.dirstate
98 and mctx[f].cmp(wctx[f]))
98 and mctx[f].cmp(wctx[f]))
99
99
100 def _checkunknown(repo, wctx, mctx):
100 def _checkunknown(repo, wctx, mctx):
101 "check for collisions between unknown files and files in mctx"
101 "check for collisions between unknown files and files in mctx"
102
102
103 error = False
103 error = False
104 for f in mctx:
104 for f in mctx:
105 if f not in wctx and _checkunknownfile(repo, wctx, mctx, f):
105 if f not in wctx and _checkunknownfile(repo, wctx, mctx, f):
106 error = True
106 error = True
107 wctx._repo.ui.warn(_("%s: untracked file differs\n") % f)
107 wctx._repo.ui.warn(_("%s: untracked file differs\n") % f)
108 if error:
108 if error:
109 raise util.Abort(_("untracked files in working directory differ "
109 raise util.Abort(_("untracked files in working directory differ "
110 "from files in requested revision"))
110 "from files in requested revision"))
111
111
112 def _remains(f, m, ma, workingctx=False):
112 def _remains(f, m, ma, workingctx=False):
113 """check whether specified file remains after merge.
113 """check whether specified file remains after merge.
114
114
115 It is assumed that specified file is not contained in the manifest
115 It is assumed that specified file is not contained in the manifest
116 of the other context.
116 of the other context.
117 """
117 """
118 if f in ma:
118 if f in ma:
119 n = m[f]
119 n = m[f]
120 if n != ma[f]:
120 if n != ma[f]:
121 return True # because it is changed locally
121 return True # because it is changed locally
122 # even though it doesn't remain, if "remote deleted" is
122 # even though it doesn't remain, if "remote deleted" is
123 # chosen in manifestmerge()
123 # chosen in manifestmerge()
124 elif workingctx and n[20:] == "a":
124 elif workingctx and n[20:] == "a":
125 return True # because it is added locally (linear merge specific)
125 return True # because it is added locally (linear merge specific)
126 else:
126 else:
127 return False # because it is removed remotely
127 return False # because it is removed remotely
128 else:
128 else:
129 return True # because it is added locally
129 return True # because it is added locally
130
130
131 def _checkcollision(mctx, extractxs):
131 def _checkcollision(mctx, extractxs):
132 "check for case folding collisions in the destination context"
132 "check for case folding collisions in the destination context"
133 folded = {}
133 folded = {}
134 for fn in mctx:
134 for fn in mctx:
135 fold = util.normcase(fn)
135 fold = util.normcase(fn)
136 if fold in folded:
136 if fold in folded:
137 raise util.Abort(_("case-folding collision between %s and %s")
137 raise util.Abort(_("case-folding collision between %s and %s")
138 % (fn, folded[fold]))
138 % (fn, folded[fold]))
139 folded[fold] = fn
139 folded[fold] = fn
140
140
141 if extractxs:
141 if extractxs:
142 wctx, actx = extractxs
142 wctx, actx = extractxs
143 # class to delay looking up copy mapping
143 # class to delay looking up copy mapping
144 class pathcopies(object):
144 class pathcopies(object):
145 @util.propertycache
145 @util.propertycache
146 def map(self):
146 def map(self):
147 # {dst@mctx: src@wctx} copy mapping
147 # {dst@mctx: src@wctx} copy mapping
148 return copies.pathcopies(wctx, mctx)
148 return copies.pathcopies(wctx, mctx)
149 pc = pathcopies()
149 pc = pathcopies()
150
150
151 for fn in wctx:
151 for fn in wctx:
152 fold = util.normcase(fn)
152 fold = util.normcase(fn)
153 mfn = folded.get(fold, None)
153 mfn = folded.get(fold, None)
154 if (mfn and mfn != fn and pc.map.get(mfn) != fn and
154 if (mfn and mfn != fn and pc.map.get(mfn) != fn and
155 _remains(fn, wctx.manifest(), actx.manifest(), True) and
155 _remains(fn, wctx.manifest(), actx.manifest(), True) and
156 _remains(mfn, mctx.manifest(), actx.manifest())):
156 _remains(mfn, mctx.manifest(), actx.manifest())):
157 raise util.Abort(_("case-folding collision between %s and %s")
157 raise util.Abort(_("case-folding collision between %s and %s")
158 % (mfn, fn))
158 % (mfn, fn))
159
159
160 def _forgetremoved(wctx, mctx, branchmerge):
160 def _forgetremoved(wctx, mctx, branchmerge):
161 """
161 """
162 Forget removed files
162 Forget removed files
163
163
164 If we're jumping between revisions (as opposed to merging), and if
164 If we're jumping between revisions (as opposed to merging), and if
165 neither the working directory nor the target rev has the file,
165 neither the working directory nor the target rev has the file,
166 then we need to remove it from the dirstate, to prevent the
166 then we need to remove it from the dirstate, to prevent the
167 dirstate from listing the file when it is no longer in the
167 dirstate from listing the file when it is no longer in the
168 manifest.
168 manifest.
169
169
170 If we're merging, and the other revision has removed a file
170 If we're merging, and the other revision has removed a file
171 that is not present in the working directory, we need to mark it
171 that is not present in the working directory, we need to mark it
172 as removed.
172 as removed.
173 """
173 """
174
174
175 actions = []
175 actions = []
176 state = branchmerge and 'r' or 'f'
176 state = branchmerge and 'r' or 'f'
177 for f in wctx.deleted():
177 for f in wctx.deleted():
178 if f not in mctx:
178 if f not in mctx:
179 actions.append((f, state, None, "forget deleted"))
179 actions.append((f, state, None, "forget deleted"))
180
180
181 if not branchmerge:
181 if not branchmerge:
182 for f in wctx.removed():
182 for f in wctx.removed():
183 if f not in mctx:
183 if f not in mctx:
184 actions.append((f, "f", None, "forget removed"))
184 actions.append((f, "f", None, "forget removed"))
185
185
186 return actions
186 return actions
187
187
188 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
188 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
189 """
189 """
190 Merge p1 and p2 with ancestor pa and generate merge action list
190 Merge p1 and p2 with ancestor pa and generate merge action list
191
191
192 overwrite = whether we clobber working files
192 overwrite = whether we clobber working files
193 partial = function to filter file lists
193 partial = function to filter file lists
194 """
194 """
195
195
196 def act(msg, m, f, *args):
196 def act(msg, m, f, *args):
197 actions.append((f, m, args, msg))
197 actions.append((f, m, args, msg))
198
198
199 actions, copy, movewithdir = [], {}, {}
199 actions, copy, movewithdir = [], {}, {}
200
200
201 if overwrite:
201 if overwrite:
202 pa = p1
202 pa = p1
203 elif pa == p2: # backwards
203 elif pa == p2: # backwards
204 pa = p1.p1()
204 pa = p1.p1()
205 elif pa and repo.ui.configbool("merge", "followcopies", True):
205 elif pa and repo.ui.configbool("merge", "followcopies", True):
206 ret = copies.mergecopies(repo, p1, p2, pa)
206 ret = copies.mergecopies(repo, p1, p2, pa)
207 copy, movewithdir, diverge, renamedelete = ret
207 copy, movewithdir, diverge, renamedelete = ret
208 for of, fl in diverge.iteritems():
208 for of, fl in diverge.iteritems():
209 act("divergent renames", "dr", of, fl)
209 act("divergent renames", "dr", of, fl)
210 for of, fl in renamedelete.iteritems():
210 for of, fl in renamedelete.iteritems():
211 act("rename and delete", "rd", of, fl)
211 act("rename and delete", "rd", of, fl)
212
212
213 repo.ui.note(_("resolving manifests\n"))
213 repo.ui.note(_("resolving manifests\n"))
214 repo.ui.debug(" overwrite: %s, partial: %s\n"
214 repo.ui.debug(" overwrite: %s, partial: %s\n"
215 % (bool(overwrite), bool(partial)))
215 % (bool(overwrite), bool(partial)))
216 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, p1, p2))
216 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, p1, p2))
217
217
218 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
218 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
219 copied = set(copy.values())
219 copied = set(copy.values())
220 copied.update(movewithdir.values())
220 copied.update(movewithdir.values())
221
221
222 if '.hgsubstate' in m1:
222 if '.hgsubstate' in m1:
223 # check whether sub state is modified
223 # check whether sub state is modified
224 for s in sorted(p1.substate):
224 for s in sorted(p1.substate):
225 if p1.sub(s).dirty():
225 if p1.sub(s).dirty():
226 m1['.hgsubstate'] += "+"
226 m1['.hgsubstate'] += "+"
227 break
227 break
228
228
229 prompts = []
229 prompts = []
230 # Compare manifests
230 # Compare manifests
231 for f, n in m1.iteritems():
231 for f, n in m1.iteritems():
232 if partial and not partial(f):
232 if partial and not partial(f):
233 continue
233 continue
234 if f in m2:
234 if f in m2:
235 n2 = m2[f]
235 n2 = m2[f]
236 fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
236 fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
237 nol = 'l' not in fl1 + fl2 + fla
237 nol = 'l' not in fl1 + fl2 + fla
238 a = ma.get(f, nullid)
238 a = ma.get(f, nullid)
239 if n == n2 and fl1 == fl2:
239 if n == n2 and fl1 == fl2:
240 pass # same - keep local
240 pass # same - keep local
241 elif n2 == a and fl2 == fla:
241 elif n2 == a and fl2 == fla:
242 pass # remote unchanged - keep local
242 pass # remote unchanged - keep local
243 elif n == a and fl1 == fla: # local unchanged - use remote
243 elif n == a and fl1 == fla: # local unchanged - use remote
244 if n == n2: # optimization: keep local content
244 if n == n2: # optimization: keep local content
245 act("update permissions", "e", f, fl2)
245 act("update permissions", "e", f, fl2)
246 else:
246 else:
247 act("remote is newer", "g", f, fl2)
247 act("remote is newer", "g", f, fl2)
248 elif nol and n2 == a: # remote only changed 'x'
248 elif nol and n2 == a: # remote only changed 'x'
249 act("update permissions", "e", f, fl2)
249 act("update permissions", "e", f, fl2)
250 elif nol and n == a: # local only changed 'x'
250 elif nol and n == a: # local only changed 'x'
251 act("remote is newer", "g", f, fl1)
251 act("remote is newer", "g", f, fl1)
252 else: # both changed something
252 else: # both changed something
253 act("versions differ", "m", f, f, f, False)
253 act("versions differ", "m", f, f, f, False)
254 elif f in copied: # files we'll deal with on m2 side
254 elif f in copied: # files we'll deal with on m2 side
255 pass
255 pass
256 elif f in movewithdir: # directory rename
256 elif f in movewithdir: # directory rename
257 f2 = movewithdir[f]
257 f2 = movewithdir[f]
258 act("remote renamed directory to " + f2, "d", f, None, f2,
258 act("remote renamed directory to " + f2, "d", f, None, f2,
259 m1.flags(f))
259 m1.flags(f))
260 elif f in copy:
260 elif f in copy:
261 f2 = copy[f]
261 f2 = copy[f]
262 act("local copied/moved to " + f2, "m", f, f2, f, False)
262 act("local copied/moved to " + f2, "m", f, f2, f, False)
263 elif f in ma: # clean, a different, no remote
263 elif f in ma: # clean, a different, no remote
264 if n != ma[f]:
264 if n != ma[f]:
265 prompts.append((f, "cd")) # prompt changed/deleted
265 prompts.append((f, "cd")) # prompt changed/deleted
266 elif n[20:] == "a": # added, no remote
266 elif n[20:] == "a": # added, no remote
267 act("remote deleted", "f", f)
267 act("remote deleted", "f", f)
268 else:
268 else:
269 act("other deleted", "r", f)
269 act("other deleted", "r", f)
270
270
271 for f, n in m2.iteritems():
271 for f, n in m2.iteritems():
272 if partial and not partial(f):
272 if partial and not partial(f):
273 continue
273 continue
274 if f in m1 or f in copied: # files already visited
274 if f in m1 or f in copied: # files already visited
275 continue
275 continue
276 if f in movewithdir:
276 if f in movewithdir:
277 f2 = movewithdir[f]
277 f2 = movewithdir[f]
278 act("local renamed directory to " + f2, "d", None, f, f2,
278 act("local renamed directory to " + f2, "d", None, f, f2,
279 m2.flags(f))
279 m2.flags(f))
280 elif f in copy:
280 elif f in copy:
281 f2 = copy[f]
281 f2 = copy[f]
282 if f2 in m2:
282 if f2 in m2:
283 act("remote copied to " + f, "m",
283 act("remote copied to " + f, "m",
284 f2, f, f, False)
284 f2, f, f, False)
285 else:
285 else:
286 act("remote moved to " + f, "m",
286 act("remote moved to " + f, "m",
287 f2, f, f, True)
287 f2, f, f, True)
288 elif f not in ma:
288 elif f not in ma:
289 if (not overwrite
289 if (not overwrite
290 and _checkunknownfile(repo, p1, p2, f)):
290 and _checkunknownfile(repo, p1, p2, f)):
291 act("remote differs from untracked local",
291 act("remote differs from untracked local",
292 "m", f, f, f, False)
292 "m", f, f, f, False)
293 else:
293 else:
294 act("remote created", "g", f, m2.flags(f))
294 act("remote created", "g", f, m2.flags(f))
295 elif n != ma[f]:
295 elif n != ma[f]:
296 prompts.append((f, "dc")) # prompt deleted/changed
296 prompts.append((f, "dc")) # prompt deleted/changed
297
297
298 for f, m in sorted(prompts):
298 for f, m in sorted(prompts):
299 if m == "cd":
299 if m == "cd":
300 if repo.ui.promptchoice(
300 if repo.ui.promptchoice(
301 _(" local changed %s which remote deleted\n"
301 _("local changed %s which remote deleted\n"
302 "use (c)hanged version or (d)elete?") % f,
302 "use (c)hanged version or (d)elete?") % f,
303 (_("&Changed"), _("&Delete")), 0):
303 (_("&Changed"), _("&Delete")), 0):
304 act("prompt delete", "r", f)
304 act("prompt delete", "r", f)
305 else:
305 else:
306 act("prompt keep", "a", f)
306 act("prompt keep", "a", f)
307 elif m == "dc":
307 elif m == "dc":
308 if repo.ui.promptchoice(
308 if repo.ui.promptchoice(
309 _("remote changed %s which local deleted\n"
309 _("remote changed %s which local deleted\n"
310 "use (c)hanged version or leave (d)eleted?") % f,
310 "use (c)hanged version or leave (d)eleted?") % f,
311 (_("&Changed"), _("&Deleted")), 0) == 0:
311 (_("&Changed"), _("&Deleted")), 0) == 0:
312 act("prompt recreating", "g", f, m2.flags(f))
312 act("prompt recreating", "g", f, m2.flags(f))
313 else: assert False, m
313 else: assert False, m
314 return actions
314 return actions
315
315
316 def actionkey(a):
316 def actionkey(a):
317 return a[1] == "r" and -1 or 0, a
317 return a[1] == "r" and -1 or 0, a
318
318
319 def applyupdates(repo, actions, wctx, mctx, actx, overwrite):
319 def applyupdates(repo, actions, wctx, mctx, actx, overwrite):
320 """apply the merge action list to the working directory
320 """apply the merge action list to the working directory
321
321
322 wctx is the working copy context
322 wctx is the working copy context
323 mctx is the context to be merged into the working copy
323 mctx is the context to be merged into the working copy
324 actx is the context of the common ancestor
324 actx is the context of the common ancestor
325
325
326 Return a tuple of counts (updated, merged, removed, unresolved) that
326 Return a tuple of counts (updated, merged, removed, unresolved) that
327 describes how many files were affected by the update.
327 describes how many files were affected by the update.
328 """
328 """
329
329
330 updated, merged, removed, unresolved = 0, 0, 0, 0
330 updated, merged, removed, unresolved = 0, 0, 0, 0
331 ms = mergestate(repo)
331 ms = mergestate(repo)
332 ms.reset(wctx.p1().node())
332 ms.reset(wctx.p1().node())
333 moves = []
333 moves = []
334 actions.sort(key=actionkey)
334 actions.sort(key=actionkey)
335
335
336 # prescan for merges
336 # prescan for merges
337 for a in actions:
337 for a in actions:
338 f, m, args, msg = a
338 f, m, args, msg = a
339 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
339 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
340 if m == "m": # merge
340 if m == "m": # merge
341 f2, fd, move = args
341 f2, fd, move = args
342 if fd == '.hgsubstate': # merged internally
342 if fd == '.hgsubstate': # merged internally
343 continue
343 continue
344 repo.ui.debug(" preserving %s for resolve of %s\n" % (f, fd))
344 repo.ui.debug(" preserving %s for resolve of %s\n" % (f, fd))
345 fcl = wctx[f]
345 fcl = wctx[f]
346 fco = mctx[f2]
346 fco = mctx[f2]
347 if mctx == actx: # backwards, use working dir parent as ancestor
347 if mctx == actx: # backwards, use working dir parent as ancestor
348 if fcl.parents():
348 if fcl.parents():
349 fca = fcl.p1()
349 fca = fcl.p1()
350 else:
350 else:
351 fca = repo.filectx(f, fileid=nullrev)
351 fca = repo.filectx(f, fileid=nullrev)
352 else:
352 else:
353 fca = fcl.ancestor(fco, actx)
353 fca = fcl.ancestor(fco, actx)
354 if not fca:
354 if not fca:
355 fca = repo.filectx(f, fileid=nullrev)
355 fca = repo.filectx(f, fileid=nullrev)
356 ms.add(fcl, fco, fca, fd)
356 ms.add(fcl, fco, fca, fd)
357 if f != fd and move:
357 if f != fd and move:
358 moves.append(f)
358 moves.append(f)
359
359
360 audit = repo.wopener.audit
360 audit = repo.wopener.audit
361
361
362 # remove renamed files after safely stored
362 # remove renamed files after safely stored
363 for f in moves:
363 for f in moves:
364 if os.path.lexists(repo.wjoin(f)):
364 if os.path.lexists(repo.wjoin(f)):
365 repo.ui.debug("removing %s\n" % f)
365 repo.ui.debug("removing %s\n" % f)
366 audit(f)
366 audit(f)
367 util.unlinkpath(repo.wjoin(f))
367 util.unlinkpath(repo.wjoin(f))
368
368
369 numupdates = len(actions)
369 numupdates = len(actions)
370 for i, a in enumerate(actions):
370 for i, a in enumerate(actions):
371 f, m, args, msg = a
371 f, m, args, msg = a
372 repo.ui.progress(_('updating'), i + 1, item=f, total=numupdates,
372 repo.ui.progress(_('updating'), i + 1, item=f, total=numupdates,
373 unit=_('files'))
373 unit=_('files'))
374 if m == "r": # remove
374 if m == "r": # remove
375 repo.ui.note(_("removing %s\n") % f)
375 repo.ui.note(_("removing %s\n") % f)
376 audit(f)
376 audit(f)
377 if f == '.hgsubstate': # subrepo states need updating
377 if f == '.hgsubstate': # subrepo states need updating
378 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
378 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
379 try:
379 try:
380 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
380 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
381 except OSError, inst:
381 except OSError, inst:
382 repo.ui.warn(_("update failed to remove %s: %s!\n") %
382 repo.ui.warn(_("update failed to remove %s: %s!\n") %
383 (f, inst.strerror))
383 (f, inst.strerror))
384 removed += 1
384 removed += 1
385 elif m == "m": # merge
385 elif m == "m": # merge
386 if fd == '.hgsubstate': # subrepo states need updating
386 if fd == '.hgsubstate': # subrepo states need updating
387 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
387 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
388 overwrite)
388 overwrite)
389 continue
389 continue
390 f2, fd, move = args
390 f2, fd, move = args
391 audit(fd)
391 audit(fd)
392 r = ms.resolve(fd, wctx, mctx)
392 r = ms.resolve(fd, wctx, mctx)
393 if r is not None and r > 0:
393 if r is not None and r > 0:
394 unresolved += 1
394 unresolved += 1
395 else:
395 else:
396 if r is None:
396 if r is None:
397 updated += 1
397 updated += 1
398 else:
398 else:
399 merged += 1
399 merged += 1
400 elif m == "g": # get
400 elif m == "g": # get
401 flags, = args
401 flags, = args
402 repo.ui.note(_("getting %s\n") % f)
402 repo.ui.note(_("getting %s\n") % f)
403 repo.wwrite(f, mctx.filectx(f).data(), flags)
403 repo.wwrite(f, mctx.filectx(f).data(), flags)
404 updated += 1
404 updated += 1
405 if f == '.hgsubstate': # subrepo states need updating
405 if f == '.hgsubstate': # subrepo states need updating
406 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
406 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
407 elif m == "d": # directory rename
407 elif m == "d": # directory rename
408 f2, fd, flags = args
408 f2, fd, flags = args
409 if f:
409 if f:
410 repo.ui.note(_("moving %s to %s\n") % (f, fd))
410 repo.ui.note(_("moving %s to %s\n") % (f, fd))
411 audit(f)
411 audit(f)
412 repo.wwrite(fd, wctx.filectx(f).data(), flags)
412 repo.wwrite(fd, wctx.filectx(f).data(), flags)
413 util.unlinkpath(repo.wjoin(f))
413 util.unlinkpath(repo.wjoin(f))
414 if f2:
414 if f2:
415 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
415 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
416 repo.wwrite(fd, mctx.filectx(f2).data(), flags)
416 repo.wwrite(fd, mctx.filectx(f2).data(), flags)
417 updated += 1
417 updated += 1
418 elif m == "dr": # divergent renames
418 elif m == "dr": # divergent renames
419 fl, = args
419 fl, = args
420 repo.ui.warn(_("note: possible conflict - %s was renamed "
420 repo.ui.warn(_("note: possible conflict - %s was renamed "
421 "multiple times to:\n") % f)
421 "multiple times to:\n") % f)
422 for nf in fl:
422 for nf in fl:
423 repo.ui.warn(" %s\n" % nf)
423 repo.ui.warn(" %s\n" % nf)
424 elif m == "rd": # rename and delete
424 elif m == "rd": # rename and delete
425 fl, = args
425 fl, = args
426 repo.ui.warn(_("note: possible conflict - %s was deleted "
426 repo.ui.warn(_("note: possible conflict - %s was deleted "
427 "and renamed to:\n") % f)
427 "and renamed to:\n") % f)
428 for nf in fl:
428 for nf in fl:
429 repo.ui.warn(" %s\n" % nf)
429 repo.ui.warn(" %s\n" % nf)
430 elif m == "e": # exec
430 elif m == "e": # exec
431 flags, = args
431 flags, = args
432 audit(f)
432 audit(f)
433 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
433 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
434 updated += 1
434 updated += 1
435 ms.commit()
435 ms.commit()
436 repo.ui.progress(_('updating'), None, total=numupdates, unit=_('files'))
436 repo.ui.progress(_('updating'), None, total=numupdates, unit=_('files'))
437
437
438 return updated, merged, removed, unresolved
438 return updated, merged, removed, unresolved
439
439
440 def calculateupdates(repo, tctx, mctx, ancestor, branchmerge, force, partial):
440 def calculateupdates(repo, tctx, mctx, ancestor, branchmerge, force, partial):
441 "Calculate the actions needed to merge mctx into tctx"
441 "Calculate the actions needed to merge mctx into tctx"
442 actions = []
442 actions = []
443 folding = not util.checkcase(repo.path)
443 folding = not util.checkcase(repo.path)
444 if folding:
444 if folding:
445 # collision check is not needed for clean update
445 # collision check is not needed for clean update
446 if (not branchmerge and
446 if (not branchmerge and
447 (force or not tctx.dirty(missing=True, branch=False))):
447 (force or not tctx.dirty(missing=True, branch=False))):
448 _checkcollision(mctx, None)
448 _checkcollision(mctx, None)
449 else:
449 else:
450 _checkcollision(mctx, (tctx, ancestor))
450 _checkcollision(mctx, (tctx, ancestor))
451 if not force:
451 if not force:
452 _checkunknown(repo, tctx, mctx)
452 _checkunknown(repo, tctx, mctx)
453 if tctx.rev() is None:
453 if tctx.rev() is None:
454 actions += _forgetremoved(tctx, mctx, branchmerge)
454 actions += _forgetremoved(tctx, mctx, branchmerge)
455 actions += manifestmerge(repo, tctx, mctx,
455 actions += manifestmerge(repo, tctx, mctx,
456 ancestor,
456 ancestor,
457 force and not branchmerge,
457 force and not branchmerge,
458 partial)
458 partial)
459 return actions
459 return actions
460
460
461 def recordupdates(repo, actions, branchmerge):
461 def recordupdates(repo, actions, branchmerge):
462 "record merge actions to the dirstate"
462 "record merge actions to the dirstate"
463
463
464 for a in actions:
464 for a in actions:
465 f, m, args, msg = a
465 f, m, args, msg = a
466 if m == "r": # remove
466 if m == "r": # remove
467 if branchmerge:
467 if branchmerge:
468 repo.dirstate.remove(f)
468 repo.dirstate.remove(f)
469 else:
469 else:
470 repo.dirstate.drop(f)
470 repo.dirstate.drop(f)
471 elif m == "a": # re-add
471 elif m == "a": # re-add
472 if not branchmerge:
472 if not branchmerge:
473 repo.dirstate.add(f)
473 repo.dirstate.add(f)
474 elif m == "f": # forget
474 elif m == "f": # forget
475 repo.dirstate.drop(f)
475 repo.dirstate.drop(f)
476 elif m == "e": # exec change
476 elif m == "e": # exec change
477 repo.dirstate.normallookup(f)
477 repo.dirstate.normallookup(f)
478 elif m == "g": # get
478 elif m == "g": # get
479 if branchmerge:
479 if branchmerge:
480 repo.dirstate.otherparent(f)
480 repo.dirstate.otherparent(f)
481 else:
481 else:
482 repo.dirstate.normal(f)
482 repo.dirstate.normal(f)
483 elif m == "m": # merge
483 elif m == "m": # merge
484 f2, fd, move = args
484 f2, fd, move = args
485 if branchmerge:
485 if branchmerge:
486 # We've done a branch merge, mark this file as merged
486 # We've done a branch merge, mark this file as merged
487 # so that we properly record the merger later
487 # so that we properly record the merger later
488 repo.dirstate.merge(fd)
488 repo.dirstate.merge(fd)
489 if f != f2: # copy/rename
489 if f != f2: # copy/rename
490 if move:
490 if move:
491 repo.dirstate.remove(f)
491 repo.dirstate.remove(f)
492 if f != fd:
492 if f != fd:
493 repo.dirstate.copy(f, fd)
493 repo.dirstate.copy(f, fd)
494 else:
494 else:
495 repo.dirstate.copy(f2, fd)
495 repo.dirstate.copy(f2, fd)
496 else:
496 else:
497 # We've update-merged a locally modified file, so
497 # We've update-merged a locally modified file, so
498 # we set the dirstate to emulate a normal checkout
498 # we set the dirstate to emulate a normal checkout
499 # of that file some time in the past. Thus our
499 # of that file some time in the past. Thus our
500 # merge will appear as a normal local file
500 # merge will appear as a normal local file
501 # modification.
501 # modification.
502 if f2 == fd: # file not locally copied/moved
502 if f2 == fd: # file not locally copied/moved
503 repo.dirstate.normallookup(fd)
503 repo.dirstate.normallookup(fd)
504 if move:
504 if move:
505 repo.dirstate.drop(f)
505 repo.dirstate.drop(f)
506 elif m == "d": # directory rename
506 elif m == "d": # directory rename
507 f2, fd, flag = args
507 f2, fd, flag = args
508 if not f2 and f not in repo.dirstate:
508 if not f2 and f not in repo.dirstate:
509 # untracked file moved
509 # untracked file moved
510 continue
510 continue
511 if branchmerge:
511 if branchmerge:
512 repo.dirstate.add(fd)
512 repo.dirstate.add(fd)
513 if f:
513 if f:
514 repo.dirstate.remove(f)
514 repo.dirstate.remove(f)
515 repo.dirstate.copy(f, fd)
515 repo.dirstate.copy(f, fd)
516 if f2:
516 if f2:
517 repo.dirstate.copy(f2, fd)
517 repo.dirstate.copy(f2, fd)
518 else:
518 else:
519 repo.dirstate.normal(fd)
519 repo.dirstate.normal(fd)
520 if f:
520 if f:
521 repo.dirstate.drop(f)
521 repo.dirstate.drop(f)
522
522
523 def update(repo, node, branchmerge, force, partial, ancestor=None,
523 def update(repo, node, branchmerge, force, partial, ancestor=None,
524 mergeancestor=False):
524 mergeancestor=False):
525 """
525 """
526 Perform a merge between the working directory and the given node
526 Perform a merge between the working directory and the given node
527
527
528 node = the node to update to, or None if unspecified
528 node = the node to update to, or None if unspecified
529 branchmerge = whether to merge between branches
529 branchmerge = whether to merge between branches
530 force = whether to force branch merging or file overwriting
530 force = whether to force branch merging or file overwriting
531 partial = a function to filter file lists (dirstate not updated)
531 partial = a function to filter file lists (dirstate not updated)
532 mergeancestor = if false, merging with an ancestor (fast-forward)
532 mergeancestor = if false, merging with an ancestor (fast-forward)
533 is only allowed between different named branches. This flag
533 is only allowed between different named branches. This flag
534 is used by rebase extension as a temporary fix and should be
534 is used by rebase extension as a temporary fix and should be
535 avoided in general.
535 avoided in general.
536
536
537 The table below shows all the behaviors of the update command
537 The table below shows all the behaviors of the update command
538 given the -c and -C or no options, whether the working directory
538 given the -c and -C or no options, whether the working directory
539 is dirty, whether a revision is specified, and the relationship of
539 is dirty, whether a revision is specified, and the relationship of
540 the parent rev to the target rev (linear, on the same named
540 the parent rev to the target rev (linear, on the same named
541 branch, or on another named branch).
541 branch, or on another named branch).
542
542
543 This logic is tested by test-update-branches.t.
543 This logic is tested by test-update-branches.t.
544
544
545 -c -C dirty rev | linear same cross
545 -c -C dirty rev | linear same cross
546 n n n n | ok (1) x
546 n n n n | ok (1) x
547 n n n y | ok ok ok
547 n n n y | ok ok ok
548 n n y * | merge (2) (2)
548 n n y * | merge (2) (2)
549 n y * * | --- discard ---
549 n y * * | --- discard ---
550 y n y * | --- (3) ---
550 y n y * | --- (3) ---
551 y n n * | --- ok ---
551 y n n * | --- ok ---
552 y y * * | --- (4) ---
552 y y * * | --- (4) ---
553
553
554 x = can't happen
554 x = can't happen
555 * = don't-care
555 * = don't-care
556 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
556 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
557 2 = abort: crosses branches (use 'hg merge' to merge or
557 2 = abort: crosses branches (use 'hg merge' to merge or
558 use 'hg update -C' to discard changes)
558 use 'hg update -C' to discard changes)
559 3 = abort: uncommitted local changes
559 3 = abort: uncommitted local changes
560 4 = incompatible options (checked in commands.py)
560 4 = incompatible options (checked in commands.py)
561
561
562 Return the same tuple as applyupdates().
562 Return the same tuple as applyupdates().
563 """
563 """
564
564
565 onode = node
565 onode = node
566 wlock = repo.wlock()
566 wlock = repo.wlock()
567 try:
567 try:
568 wc = repo[None]
568 wc = repo[None]
569 if node is None:
569 if node is None:
570 # tip of current branch
570 # tip of current branch
571 try:
571 try:
572 node = repo.branchtip(wc.branch())
572 node = repo.branchtip(wc.branch())
573 except error.RepoLookupError:
573 except error.RepoLookupError:
574 if wc.branch() == "default": # no default branch!
574 if wc.branch() == "default": # no default branch!
575 node = repo.lookup("tip") # update to tip
575 node = repo.lookup("tip") # update to tip
576 else:
576 else:
577 raise util.Abort(_("branch %s not found") % wc.branch())
577 raise util.Abort(_("branch %s not found") % wc.branch())
578 overwrite = force and not branchmerge
578 overwrite = force and not branchmerge
579 pl = wc.parents()
579 pl = wc.parents()
580 p1, p2 = pl[0], repo[node]
580 p1, p2 = pl[0], repo[node]
581 if ancestor:
581 if ancestor:
582 pa = repo[ancestor]
582 pa = repo[ancestor]
583 else:
583 else:
584 pa = p1.ancestor(p2)
584 pa = p1.ancestor(p2)
585
585
586 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
586 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
587
587
588 ### check phase
588 ### check phase
589 if not overwrite and len(pl) > 1:
589 if not overwrite and len(pl) > 1:
590 raise util.Abort(_("outstanding uncommitted merges"))
590 raise util.Abort(_("outstanding uncommitted merges"))
591 if branchmerge:
591 if branchmerge:
592 if pa == p2:
592 if pa == p2:
593 raise util.Abort(_("merging with a working directory ancestor"
593 raise util.Abort(_("merging with a working directory ancestor"
594 " has no effect"))
594 " has no effect"))
595 elif pa == p1:
595 elif pa == p1:
596 if not mergeancestor and p1.branch() == p2.branch():
596 if not mergeancestor and p1.branch() == p2.branch():
597 raise util.Abort(_("nothing to merge"),
597 raise util.Abort(_("nothing to merge"),
598 hint=_("use 'hg update' "
598 hint=_("use 'hg update' "
599 "or check 'hg heads'"))
599 "or check 'hg heads'"))
600 if not force and (wc.files() or wc.deleted()):
600 if not force and (wc.files() or wc.deleted()):
601 raise util.Abort(_("outstanding uncommitted changes"),
601 raise util.Abort(_("outstanding uncommitted changes"),
602 hint=_("use 'hg status' to list changes"))
602 hint=_("use 'hg status' to list changes"))
603 for s in sorted(wc.substate):
603 for s in sorted(wc.substate):
604 if wc.sub(s).dirty():
604 if wc.sub(s).dirty():
605 raise util.Abort(_("outstanding uncommitted changes in "
605 raise util.Abort(_("outstanding uncommitted changes in "
606 "subrepository '%s'") % s)
606 "subrepository '%s'") % s)
607
607
608 elif not overwrite:
608 elif not overwrite:
609 if pa == p1 or pa == p2: # linear
609 if pa == p1 or pa == p2: # linear
610 pass # all good
610 pass # all good
611 elif wc.dirty(missing=True):
611 elif wc.dirty(missing=True):
612 raise util.Abort(_("crosses branches (merge branches or use"
612 raise util.Abort(_("crosses branches (merge branches or use"
613 " --clean to discard changes)"))
613 " --clean to discard changes)"))
614 elif onode is None:
614 elif onode is None:
615 raise util.Abort(_("crosses branches (merge branches or update"
615 raise util.Abort(_("crosses branches (merge branches or update"
616 " --check to force update)"))
616 " --check to force update)"))
617 else:
617 else:
618 # Allow jumping branches if clean and specific rev given
618 # Allow jumping branches if clean and specific rev given
619 pa = p1
619 pa = p1
620
620
621 ### calculate phase
621 ### calculate phase
622 actions = calculateupdates(repo, wc, p2, pa,
622 actions = calculateupdates(repo, wc, p2, pa,
623 branchmerge, force, partial)
623 branchmerge, force, partial)
624
624
625 ### apply phase
625 ### apply phase
626 if not branchmerge: # just jump to the new rev
626 if not branchmerge: # just jump to the new rev
627 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
627 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
628 if not partial:
628 if not partial:
629 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
629 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
630
630
631 stats = applyupdates(repo, actions, wc, p2, pa, overwrite)
631 stats = applyupdates(repo, actions, wc, p2, pa, overwrite)
632
632
633 if not partial:
633 if not partial:
634 repo.setparents(fp1, fp2)
634 repo.setparents(fp1, fp2)
635 recordupdates(repo, actions, branchmerge)
635 recordupdates(repo, actions, branchmerge)
636 if not branchmerge:
636 if not branchmerge:
637 repo.dirstate.setbranch(p2.branch())
637 repo.dirstate.setbranch(p2.branch())
638 finally:
638 finally:
639 wlock.release()
639 wlock.release()
640
640
641 if not partial:
641 if not partial:
642 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
642 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
643 return stats
643 return stats
@@ -1,142 +1,142 b''
1 Test for
1 Test for
2 b5605d88dc27: Make ui.prompt repeat on "unrecognized response" again
2 b5605d88dc27: Make ui.prompt repeat on "unrecognized response" again
3 (issue897)
3 (issue897)
4
4
5 840e2b315c1f: Fix misleading error and prompts during update/merge
5 840e2b315c1f: Fix misleading error and prompts during update/merge
6 (issue556)
6 (issue556)
7
7
8 $ status() {
8 $ status() {
9 > echo "--- status ---"
9 > echo "--- status ---"
10 > hg st -A file1 file2
10 > hg st -A file1 file2
11 > for file in file1 file2; do
11 > for file in file1 file2; do
12 > if [ -f $file ]; then
12 > if [ -f $file ]; then
13 > echo "--- $file ---"
13 > echo "--- $file ---"
14 > cat $file
14 > cat $file
15 > else
15 > else
16 > echo "*** $file does not exist"
16 > echo "*** $file does not exist"
17 > fi
17 > fi
18 > done
18 > done
19 > }
19 > }
20
20
21 $ hg init
21 $ hg init
22
22
23 $ echo 1 > file1
23 $ echo 1 > file1
24 $ echo 2 > file2
24 $ echo 2 > file2
25 $ hg ci -Am 'added file1 and file2'
25 $ hg ci -Am 'added file1 and file2'
26 adding file1
26 adding file1
27 adding file2
27 adding file2
28
28
29 $ hg rm file1
29 $ hg rm file1
30 $ echo changed >> file2
30 $ echo changed >> file2
31 $ hg ci -m 'removed file1, changed file2'
31 $ hg ci -m 'removed file1, changed file2'
32
32
33 $ hg co 0
33 $ hg co 0
34 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
35
35
36 $ echo changed >> file1
36 $ echo changed >> file1
37 $ hg rm file2
37 $ hg rm file2
38 $ hg ci -m 'changed file1, removed file2'
38 $ hg ci -m 'changed file1, removed file2'
39 created new head
39 created new head
40
40
41
41
42 Non-interactive merge:
42 Non-interactive merge:
43
43
44 $ hg merge -y
44 $ hg merge -y
45 local changed file1 which remote deleted
45 local changed file1 which remote deleted
46 use (c)hanged version or (d)elete? c
46 use (c)hanged version or (d)elete? c
47 remote changed file2 which local deleted
47 remote changed file2 which local deleted
48 use (c)hanged version or leave (d)eleted? c
48 use (c)hanged version or leave (d)eleted? c
49 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 (branch merge, don't forget to commit)
50 (branch merge, don't forget to commit)
51
51
52 $ status
52 $ status
53 --- status ---
53 --- status ---
54 M file2
54 M file2
55 C file1
55 C file1
56 --- file1 ---
56 --- file1 ---
57 1
57 1
58 changed
58 changed
59 --- file2 ---
59 --- file2 ---
60 2
60 2
61 changed
61 changed
62
62
63
63
64 Interactive merge:
64 Interactive merge:
65
65
66 $ hg co -C
66 $ hg co -C
67 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
67 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
68
68
69 $ hg merge --config ui.interactive=true <<EOF
69 $ hg merge --config ui.interactive=true <<EOF
70 > c
70 > c
71 > d
71 > d
72 > EOF
72 > EOF
73 local changed file1 which remote deleted
73 local changed file1 which remote deleted
74 use (c)hanged version or (d)elete? remote changed file2 which local deleted
74 use (c)hanged version or (d)elete? remote changed file2 which local deleted
75 use (c)hanged version or leave (d)eleted? 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 use (c)hanged version or leave (d)eleted? 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 (branch merge, don't forget to commit)
76 (branch merge, don't forget to commit)
77
77
78 $ status
78 $ status
79 --- status ---
79 --- status ---
80 file2: * (glob)
80 file2: * (glob)
81 C file1
81 C file1
82 --- file1 ---
82 --- file1 ---
83 1
83 1
84 changed
84 changed
85 *** file2 does not exist
85 *** file2 does not exist
86
86
87
87
88 Interactive merge with bad input:
88 Interactive merge with bad input:
89
89
90 $ hg co -C
90 $ hg co -C
91 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
92
92
93 $ hg merge --config ui.interactive=true <<EOF
93 $ hg merge --config ui.interactive=true <<EOF
94 > foo
94 > foo
95 > bar
95 > bar
96 > d
96 > d
97 > baz
97 > baz
98 > c
98 > c
99 > EOF
99 > EOF
100 local changed file1 which remote deleted
100 local changed file1 which remote deleted
101 use (c)hanged version or (d)elete? unrecognized response
101 use (c)hanged version or (d)elete? unrecognized response
102 local changed file1 which remote deleted
102 local changed file1 which remote deleted
103 use (c)hanged version or (d)elete? unrecognized response
103 use (c)hanged version or (d)elete? unrecognized response
104 local changed file1 which remote deleted
104 local changed file1 which remote deleted
105 use (c)hanged version or (d)elete? remote changed file2 which local deleted
105 use (c)hanged version or (d)elete? remote changed file2 which local deleted
106 use (c)hanged version or leave (d)eleted? unrecognized response
106 use (c)hanged version or leave (d)eleted? unrecognized response
107 remote changed file2 which local deleted
107 remote changed file2 which local deleted
108 use (c)hanged version or leave (d)eleted? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
108 use (c)hanged version or leave (d)eleted? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
109 (branch merge, don't forget to commit)
109 (branch merge, don't forget to commit)
110
110
111 $ status
111 $ status
112 --- status ---
112 --- status ---
113 M file2
113 M file2
114 R file1
114 R file1
115 *** file1 does not exist
115 *** file1 does not exist
116 --- file2 ---
116 --- file2 ---
117 2
117 2
118 changed
118 changed
119
119
120
120
121 Interactive merge with not enough input:
121 Interactive merge with not enough input:
122
122
123 $ hg co -C
123 $ hg co -C
124 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
124 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
125
125
126 $ hg merge --config ui.interactive=true <<EOF
126 $ hg merge --config ui.interactive=true <<EOF
127 > d
127 > d
128 > EOF
128 > EOF
129 local changed file1 which remote deleted
129 local changed file1 which remote deleted
130 use (c)hanged version or (d)elete? remote changed file2 which local deleted
130 use (c)hanged version or (d)elete? remote changed file2 which local deleted
131 use (c)hanged version or leave (d)eleted? abort: response expected
131 use (c)hanged version or leave (d)eleted? abort: response expected
132 [255]
132 [255]
133
133
134 $ status
134 $ status
135 --- status ---
135 --- status ---
136 file2: * (glob)
136 file2: * (glob)
137 C file1
137 C file1
138 --- file1 ---
138 --- file1 ---
139 1
139 1
140 changed
140 changed
141 *** file2 does not exist
141 *** file2 does not exist
142
142
@@ -1,754 +1,754 b''
1
1
2 $ mkdir -p t
2 $ mkdir -p t
3 $ cd t
3 $ cd t
4 $ cat <<EOF > merge
4 $ cat <<EOF > merge
5 > import sys, os
5 > import sys, os
6 > f = open(sys.argv[1], "wb")
6 > f = open(sys.argv[1], "wb")
7 > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3]))
7 > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3]))
8 > f.close()
8 > f.close()
9 > EOF
9 > EOF
10
10
11 perform a test merge with possible renaming
11 perform a test merge with possible renaming
12 args:
12 args:
13 $1 = action in local branch
13 $1 = action in local branch
14 $2 = action in remote branch
14 $2 = action in remote branch
15 $3 = action in working dir
15 $3 = action in working dir
16 $4 = expected result
16 $4 = expected result
17
17
18 $ tm()
18 $ tm()
19 > {
19 > {
20 > hg init t
20 > hg init t
21 > cd t
21 > cd t
22 > echo "[merge]" >> .hg/hgrc
22 > echo "[merge]" >> .hg/hgrc
23 > echo "followcopies = 1" >> .hg/hgrc
23 > echo "followcopies = 1" >> .hg/hgrc
24 >
24 >
25 > # base
25 > # base
26 > echo base > a
26 > echo base > a
27 > echo base > rev # used to force commits
27 > echo base > rev # used to force commits
28 > hg add a rev
28 > hg add a rev
29 > hg ci -m "base"
29 > hg ci -m "base"
30 >
30 >
31 > # remote
31 > # remote
32 > echo remote > rev
32 > echo remote > rev
33 > if [ "$2" != "" ] ; then $2 ; fi
33 > if [ "$2" != "" ] ; then $2 ; fi
34 > hg ci -m "remote"
34 > hg ci -m "remote"
35 >
35 >
36 > # local
36 > # local
37 > hg co -q 0
37 > hg co -q 0
38 > echo local > rev
38 > echo local > rev
39 > if [ "$1" != "" ] ; then $1 ; fi
39 > if [ "$1" != "" ] ; then $1 ; fi
40 > hg ci -m "local"
40 > hg ci -m "local"
41 >
41 >
42 > # working dir
42 > # working dir
43 > echo local > rev
43 > echo local > rev
44 > if [ "$3" != "" ] ; then $3 ; fi
44 > if [ "$3" != "" ] ; then $3 ; fi
45 >
45 >
46 > # merge
46 > # merge
47 > echo "--------------"
47 > echo "--------------"
48 > echo "test L:$1 R:$2 W:$3 - $4"
48 > echo "test L:$1 R:$2 W:$3 - $4"
49 > echo "--------------"
49 > echo "--------------"
50 > hg merge -y --debug --traceback --tool="python ../merge"
50 > hg merge -y --debug --traceback --tool="python ../merge"
51 >
51 >
52 > echo "--------------"
52 > echo "--------------"
53 > hg status -camC -X rev
53 > hg status -camC -X rev
54 >
54 >
55 > hg ci -m "merge"
55 > hg ci -m "merge"
56 >
56 >
57 > echo "--------------"
57 > echo "--------------"
58 > echo
58 > echo
59 >
59 >
60 > cd ..
60 > cd ..
61 > rm -r t
61 > rm -r t
62 > }
62 > }
63 $ up() {
63 $ up() {
64 > cp rev $1
64 > cp rev $1
65 > hg add $1 2> /dev/null
65 > hg add $1 2> /dev/null
66 > if [ "$2" != "" ] ; then
66 > if [ "$2" != "" ] ; then
67 > cp rev $2
67 > cp rev $2
68 > hg add $2 2> /dev/null
68 > hg add $2 2> /dev/null
69 > fi
69 > fi
70 > }
70 > }
71 $ uc() { up $1; hg cp $1 $2; } # update + copy
71 $ uc() { up $1; hg cp $1 $2; } # update + copy
72 $ um() { up $1; hg mv $1 $2; }
72 $ um() { up $1; hg mv $1 $2; }
73 $ nc() { hg cp $1 $2; } # just copy
73 $ nc() { hg cp $1 $2; } # just copy
74 $ nm() { hg mv $1 $2; } # just move
74 $ nm() { hg mv $1 $2; } # just move
75 $ tm "up a " "nc a b" " " "1 get local a to b"
75 $ tm "up a " "nc a b" " " "1 get local a to b"
76 created new head
76 created new head
77 --------------
77 --------------
78 test L:up a R:nc a b W: - 1 get local a to b
78 test L:up a R:nc a b W: - 1 get local a to b
79 --------------
79 --------------
80 searching for copies back to rev 1
80 searching for copies back to rev 1
81 unmatched files in other:
81 unmatched files in other:
82 b
82 b
83 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
83 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
84 src: 'a' -> dst: 'b' *
84 src: 'a' -> dst: 'b' *
85 checking for directory renames
85 checking for directory renames
86 resolving manifests
86 resolving manifests
87 overwrite: False, partial: False
87 overwrite: False, partial: False
88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
89 a: remote copied to b -> m
89 a: remote copied to b -> m
90 preserving a for resolve of b
90 preserving a for resolve of b
91 rev: versions differ -> m
91 rev: versions differ -> m
92 preserving rev for resolve of rev
92 preserving rev for resolve of rev
93 updating: a 1/2 files (50.00%)
93 updating: a 1/2 files (50.00%)
94 picked tool 'python ../merge' for b (binary False symlink False)
94 picked tool 'python ../merge' for b (binary False symlink False)
95 merging a and b to b
95 merging a and b to b
96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
97 premerge successful
97 premerge successful
98 updating: rev 2/2 files (100.00%)
98 updating: rev 2/2 files (100.00%)
99 picked tool 'python ../merge' for rev (binary False symlink False)
99 picked tool 'python ../merge' for rev (binary False symlink False)
100 merging rev
100 merging rev
101 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
101 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
102 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
102 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
103 (branch merge, don't forget to commit)
103 (branch merge, don't forget to commit)
104 --------------
104 --------------
105 M b
105 M b
106 a
106 a
107 C a
107 C a
108 --------------
108 --------------
109
109
110 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
110 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
111 created new head
111 created new head
112 --------------
112 --------------
113 test L:nc a b R:up a W: - 2 get rem change to a and b
113 test L:nc a b R:up a W: - 2 get rem change to a and b
114 --------------
114 --------------
115 searching for copies back to rev 1
115 searching for copies back to rev 1
116 unmatched files in local:
116 unmatched files in local:
117 b
117 b
118 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
118 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
119 src: 'a' -> dst: 'b' *
119 src: 'a' -> dst: 'b' *
120 checking for directory renames
120 checking for directory renames
121 resolving manifests
121 resolving manifests
122 overwrite: False, partial: False
122 overwrite: False, partial: False
123 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
123 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
124 a: remote is newer -> g
124 a: remote is newer -> g
125 b: local copied/moved to a -> m
125 b: local copied/moved to a -> m
126 preserving b for resolve of b
126 preserving b for resolve of b
127 rev: versions differ -> m
127 rev: versions differ -> m
128 preserving rev for resolve of rev
128 preserving rev for resolve of rev
129 updating: a 1/3 files (33.33%)
129 updating: a 1/3 files (33.33%)
130 getting a
130 getting a
131 updating: b 2/3 files (66.67%)
131 updating: b 2/3 files (66.67%)
132 picked tool 'python ../merge' for b (binary False symlink False)
132 picked tool 'python ../merge' for b (binary False symlink False)
133 merging b and a to b
133 merging b and a to b
134 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
134 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
135 premerge successful
135 premerge successful
136 updating: rev 3/3 files (100.00%)
136 updating: rev 3/3 files (100.00%)
137 picked tool 'python ../merge' for rev (binary False symlink False)
137 picked tool 'python ../merge' for rev (binary False symlink False)
138 merging rev
138 merging rev
139 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
139 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
140 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
140 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
141 (branch merge, don't forget to commit)
141 (branch merge, don't forget to commit)
142 --------------
142 --------------
143 M a
143 M a
144 M b
144 M b
145 a
145 a
146 --------------
146 --------------
147
147
148 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
148 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
149 created new head
149 created new head
150 --------------
150 --------------
151 test L:up a R:nm a b W: - 3 get local a change to b, remove a
151 test L:up a R:nm a b W: - 3 get local a change to b, remove a
152 --------------
152 --------------
153 searching for copies back to rev 1
153 searching for copies back to rev 1
154 unmatched files in other:
154 unmatched files in other:
155 b
155 b
156 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
156 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
157 src: 'a' -> dst: 'b' *
157 src: 'a' -> dst: 'b' *
158 checking for directory renames
158 checking for directory renames
159 resolving manifests
159 resolving manifests
160 overwrite: False, partial: False
160 overwrite: False, partial: False
161 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
161 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
162 a: remote moved to b -> m
162 a: remote moved to b -> m
163 preserving a for resolve of b
163 preserving a for resolve of b
164 rev: versions differ -> m
164 rev: versions differ -> m
165 preserving rev for resolve of rev
165 preserving rev for resolve of rev
166 removing a
166 removing a
167 updating: a 1/2 files (50.00%)
167 updating: a 1/2 files (50.00%)
168 picked tool 'python ../merge' for b (binary False symlink False)
168 picked tool 'python ../merge' for b (binary False symlink False)
169 merging a and b to b
169 merging a and b to b
170 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
170 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
171 premerge successful
171 premerge successful
172 updating: rev 2/2 files (100.00%)
172 updating: rev 2/2 files (100.00%)
173 picked tool 'python ../merge' for rev (binary False symlink False)
173 picked tool 'python ../merge' for rev (binary False symlink False)
174 merging rev
174 merging rev
175 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
175 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
176 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
176 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
177 (branch merge, don't forget to commit)
177 (branch merge, don't forget to commit)
178 --------------
178 --------------
179 M b
179 M b
180 a
180 a
181 --------------
181 --------------
182
182
183 $ tm "nm a b" "up a " " " "4 get remote change to b"
183 $ tm "nm a b" "up a " " " "4 get remote change to b"
184 created new head
184 created new head
185 --------------
185 --------------
186 test L:nm a b R:up a W: - 4 get remote change to b
186 test L:nm a b R:up a W: - 4 get remote change to b
187 --------------
187 --------------
188 searching for copies back to rev 1
188 searching for copies back to rev 1
189 unmatched files in local:
189 unmatched files in local:
190 b
190 b
191 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
191 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
192 src: 'a' -> dst: 'b' *
192 src: 'a' -> dst: 'b' *
193 checking for directory renames
193 checking for directory renames
194 resolving manifests
194 resolving manifests
195 overwrite: False, partial: False
195 overwrite: False, partial: False
196 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
196 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
197 b: local copied/moved to a -> m
197 b: local copied/moved to a -> m
198 preserving b for resolve of b
198 preserving b for resolve of b
199 rev: versions differ -> m
199 rev: versions differ -> m
200 preserving rev for resolve of rev
200 preserving rev for resolve of rev
201 updating: b 1/2 files (50.00%)
201 updating: b 1/2 files (50.00%)
202 picked tool 'python ../merge' for b (binary False symlink False)
202 picked tool 'python ../merge' for b (binary False symlink False)
203 merging b and a to b
203 merging b and a to b
204 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
204 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
205 premerge successful
205 premerge successful
206 updating: rev 2/2 files (100.00%)
206 updating: rev 2/2 files (100.00%)
207 picked tool 'python ../merge' for rev (binary False symlink False)
207 picked tool 'python ../merge' for rev (binary False symlink False)
208 merging rev
208 merging rev
209 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
209 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
210 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
210 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
211 (branch merge, don't forget to commit)
211 (branch merge, don't forget to commit)
212 --------------
212 --------------
213 M b
213 M b
214 a
214 a
215 --------------
215 --------------
216
216
217 $ tm " " "nc a b" " " "5 get b"
217 $ tm " " "nc a b" " " "5 get b"
218 created new head
218 created new head
219 --------------
219 --------------
220 test L: R:nc a b W: - 5 get b
220 test L: R:nc a b W: - 5 get b
221 --------------
221 --------------
222 searching for copies back to rev 1
222 searching for copies back to rev 1
223 unmatched files in other:
223 unmatched files in other:
224 b
224 b
225 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
225 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
226 src: 'a' -> dst: 'b'
226 src: 'a' -> dst: 'b'
227 checking for directory renames
227 checking for directory renames
228 resolving manifests
228 resolving manifests
229 overwrite: False, partial: False
229 overwrite: False, partial: False
230 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
230 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
231 b: remote created -> g
231 b: remote created -> g
232 rev: versions differ -> m
232 rev: versions differ -> m
233 preserving rev for resolve of rev
233 preserving rev for resolve of rev
234 updating: b 1/2 files (50.00%)
234 updating: b 1/2 files (50.00%)
235 getting b
235 getting b
236 updating: rev 2/2 files (100.00%)
236 updating: rev 2/2 files (100.00%)
237 picked tool 'python ../merge' for rev (binary False symlink False)
237 picked tool 'python ../merge' for rev (binary False symlink False)
238 merging rev
238 merging rev
239 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
239 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
240 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
240 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
241 (branch merge, don't forget to commit)
241 (branch merge, don't forget to commit)
242 --------------
242 --------------
243 M b
243 M b
244 C a
244 C a
245 --------------
245 --------------
246
246
247 $ tm "nc a b" " " " " "6 nothing"
247 $ tm "nc a b" " " " " "6 nothing"
248 created new head
248 created new head
249 --------------
249 --------------
250 test L:nc a b R: W: - 6 nothing
250 test L:nc a b R: W: - 6 nothing
251 --------------
251 --------------
252 searching for copies back to rev 1
252 searching for copies back to rev 1
253 unmatched files in local:
253 unmatched files in local:
254 b
254 b
255 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
255 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
256 src: 'a' -> dst: 'b'
256 src: 'a' -> dst: 'b'
257 checking for directory renames
257 checking for directory renames
258 resolving manifests
258 resolving manifests
259 overwrite: False, partial: False
259 overwrite: False, partial: False
260 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
260 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
261 rev: versions differ -> m
261 rev: versions differ -> m
262 preserving rev for resolve of rev
262 preserving rev for resolve of rev
263 updating: rev 1/1 files (100.00%)
263 updating: rev 1/1 files (100.00%)
264 picked tool 'python ../merge' for rev (binary False symlink False)
264 picked tool 'python ../merge' for rev (binary False symlink False)
265 merging rev
265 merging rev
266 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
266 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
267 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
267 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
268 (branch merge, don't forget to commit)
268 (branch merge, don't forget to commit)
269 --------------
269 --------------
270 C a
270 C a
271 C b
271 C b
272 --------------
272 --------------
273
273
274 $ tm " " "nm a b" " " "7 get b"
274 $ tm " " "nm a b" " " "7 get b"
275 created new head
275 created new head
276 --------------
276 --------------
277 test L: R:nm a b W: - 7 get b
277 test L: R:nm a b W: - 7 get b
278 --------------
278 --------------
279 searching for copies back to rev 1
279 searching for copies back to rev 1
280 unmatched files in other:
280 unmatched files in other:
281 b
281 b
282 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
282 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
283 src: 'a' -> dst: 'b'
283 src: 'a' -> dst: 'b'
284 checking for directory renames
284 checking for directory renames
285 resolving manifests
285 resolving manifests
286 overwrite: False, partial: False
286 overwrite: False, partial: False
287 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
287 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
288 a: other deleted -> r
288 a: other deleted -> r
289 b: remote created -> g
289 b: remote created -> g
290 rev: versions differ -> m
290 rev: versions differ -> m
291 preserving rev for resolve of rev
291 preserving rev for resolve of rev
292 updating: a 1/3 files (33.33%)
292 updating: a 1/3 files (33.33%)
293 removing a
293 removing a
294 updating: b 2/3 files (66.67%)
294 updating: b 2/3 files (66.67%)
295 getting b
295 getting b
296 updating: rev 3/3 files (100.00%)
296 updating: rev 3/3 files (100.00%)
297 picked tool 'python ../merge' for rev (binary False symlink False)
297 picked tool 'python ../merge' for rev (binary False symlink False)
298 merging rev
298 merging rev
299 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
299 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
300 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
300 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
301 (branch merge, don't forget to commit)
301 (branch merge, don't forget to commit)
302 --------------
302 --------------
303 M b
303 M b
304 --------------
304 --------------
305
305
306 $ tm "nm a b" " " " " "8 nothing"
306 $ tm "nm a b" " " " " "8 nothing"
307 created new head
307 created new head
308 --------------
308 --------------
309 test L:nm a b R: W: - 8 nothing
309 test L:nm a b R: W: - 8 nothing
310 --------------
310 --------------
311 searching for copies back to rev 1
311 searching for copies back to rev 1
312 unmatched files in local:
312 unmatched files in local:
313 b
313 b
314 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
314 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
315 src: 'a' -> dst: 'b'
315 src: 'a' -> dst: 'b'
316 checking for directory renames
316 checking for directory renames
317 resolving manifests
317 resolving manifests
318 overwrite: False, partial: False
318 overwrite: False, partial: False
319 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
319 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
320 rev: versions differ -> m
320 rev: versions differ -> m
321 preserving rev for resolve of rev
321 preserving rev for resolve of rev
322 updating: rev 1/1 files (100.00%)
322 updating: rev 1/1 files (100.00%)
323 picked tool 'python ../merge' for rev (binary False symlink False)
323 picked tool 'python ../merge' for rev (binary False symlink False)
324 merging rev
324 merging rev
325 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
325 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
326 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
326 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
327 (branch merge, don't forget to commit)
327 (branch merge, don't forget to commit)
328 --------------
328 --------------
329 C b
329 C b
330 --------------
330 --------------
331
331
332 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
332 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
333 created new head
333 created new head
334 --------------
334 --------------
335 test L:um a b R:um a b W: - 9 do merge with ancestor in a
335 test L:um a b R:um a b W: - 9 do merge with ancestor in a
336 --------------
336 --------------
337 searching for copies back to rev 1
337 searching for copies back to rev 1
338 resolving manifests
338 resolving manifests
339 overwrite: False, partial: False
339 overwrite: False, partial: False
340 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
340 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
341 b: versions differ -> m
341 b: versions differ -> m
342 preserving b for resolve of b
342 preserving b for resolve of b
343 rev: versions differ -> m
343 rev: versions differ -> m
344 preserving rev for resolve of rev
344 preserving rev for resolve of rev
345 updating: b 1/2 files (50.00%)
345 updating: b 1/2 files (50.00%)
346 picked tool 'python ../merge' for b (binary False symlink False)
346 picked tool 'python ../merge' for b (binary False symlink False)
347 merging b
347 merging b
348 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
348 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
349 updating: rev 2/2 files (100.00%)
349 updating: rev 2/2 files (100.00%)
350 picked tool 'python ../merge' for rev (binary False symlink False)
350 picked tool 'python ../merge' for rev (binary False symlink False)
351 merging rev
351 merging rev
352 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
352 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
353 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
353 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
354 (branch merge, don't forget to commit)
354 (branch merge, don't forget to commit)
355 --------------
355 --------------
356 M b
356 M b
357 --------------
357 --------------
358
358
359
359
360 m "um a c" "um x c" " " "10 do merge with no ancestor"
360 m "um a c" "um x c" " " "10 do merge with no ancestor"
361
361
362 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
362 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
363 created new head
363 created new head
364 --------------
364 --------------
365 test L:nm a b R:nm a c W: - 11 get c, keep b
365 test L:nm a b R:nm a c W: - 11 get c, keep b
366 --------------
366 --------------
367 searching for copies back to rev 1
367 searching for copies back to rev 1
368 unmatched files in local:
368 unmatched files in local:
369 b
369 b
370 unmatched files in other:
370 unmatched files in other:
371 c
371 c
372 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
372 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
373 src: 'a' -> dst: 'b' !
373 src: 'a' -> dst: 'b' !
374 src: 'a' -> dst: 'c' !
374 src: 'a' -> dst: 'c' !
375 checking for directory renames
375 checking for directory renames
376 resolving manifests
376 resolving manifests
377 overwrite: False, partial: False
377 overwrite: False, partial: False
378 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
378 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
379 a: divergent renames -> dr
379 a: divergent renames -> dr
380 c: remote created -> g
380 c: remote created -> g
381 rev: versions differ -> m
381 rev: versions differ -> m
382 preserving rev for resolve of rev
382 preserving rev for resolve of rev
383 updating: a 1/3 files (33.33%)
383 updating: a 1/3 files (33.33%)
384 note: possible conflict - a was renamed multiple times to:
384 note: possible conflict - a was renamed multiple times to:
385 b
385 b
386 c
386 c
387 updating: c 2/3 files (66.67%)
387 updating: c 2/3 files (66.67%)
388 getting c
388 getting c
389 updating: rev 3/3 files (100.00%)
389 updating: rev 3/3 files (100.00%)
390 picked tool 'python ../merge' for rev (binary False symlink False)
390 picked tool 'python ../merge' for rev (binary False symlink False)
391 merging rev
391 merging rev
392 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
392 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
393 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
393 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
394 (branch merge, don't forget to commit)
394 (branch merge, don't forget to commit)
395 --------------
395 --------------
396 M c
396 M c
397 C b
397 C b
398 --------------
398 --------------
399
399
400 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
400 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
401 created new head
401 created new head
402 --------------
402 --------------
403 test L:nc a b R:up b W: - 12 merge b no ancestor
403 test L:nc a b R:up b W: - 12 merge b no ancestor
404 --------------
404 --------------
405 searching for copies back to rev 1
405 searching for copies back to rev 1
406 resolving manifests
406 resolving manifests
407 overwrite: False, partial: False
407 overwrite: False, partial: False
408 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
408 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
409 b: versions differ -> m
409 b: versions differ -> m
410 preserving b for resolve of b
410 preserving b for resolve of b
411 rev: versions differ -> m
411 rev: versions differ -> m
412 preserving rev for resolve of rev
412 preserving rev for resolve of rev
413 updating: b 1/2 files (50.00%)
413 updating: b 1/2 files (50.00%)
414 picked tool 'python ../merge' for b (binary False symlink False)
414 picked tool 'python ../merge' for b (binary False symlink False)
415 merging b
415 merging b
416 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
416 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
417 updating: rev 2/2 files (100.00%)
417 updating: rev 2/2 files (100.00%)
418 picked tool 'python ../merge' for rev (binary False symlink False)
418 picked tool 'python ../merge' for rev (binary False symlink False)
419 merging rev
419 merging rev
420 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
420 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
421 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
421 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
422 (branch merge, don't forget to commit)
422 (branch merge, don't forget to commit)
423 --------------
423 --------------
424 M b
424 M b
425 C a
425 C a
426 --------------
426 --------------
427
427
428 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
428 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
429 created new head
429 created new head
430 --------------
430 --------------
431 test L:up b R:nm a b W: - 13 merge b no ancestor
431 test L:up b R:nm a b W: - 13 merge b no ancestor
432 --------------
432 --------------
433 searching for copies back to rev 1
433 searching for copies back to rev 1
434 resolving manifests
434 resolving manifests
435 overwrite: False, partial: False
435 overwrite: False, partial: False
436 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
436 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
437 a: other deleted -> r
437 a: other deleted -> r
438 b: versions differ -> m
438 b: versions differ -> m
439 preserving b for resolve of b
439 preserving b for resolve of b
440 rev: versions differ -> m
440 rev: versions differ -> m
441 preserving rev for resolve of rev
441 preserving rev for resolve of rev
442 updating: a 1/3 files (33.33%)
442 updating: a 1/3 files (33.33%)
443 removing a
443 removing a
444 updating: b 2/3 files (66.67%)
444 updating: b 2/3 files (66.67%)
445 picked tool 'python ../merge' for b (binary False symlink False)
445 picked tool 'python ../merge' for b (binary False symlink False)
446 merging b
446 merging b
447 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
447 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
448 updating: rev 3/3 files (100.00%)
448 updating: rev 3/3 files (100.00%)
449 picked tool 'python ../merge' for rev (binary False symlink False)
449 picked tool 'python ../merge' for rev (binary False symlink False)
450 merging rev
450 merging rev
451 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
451 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
452 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
452 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
453 (branch merge, don't forget to commit)
453 (branch merge, don't forget to commit)
454 --------------
454 --------------
455 M b
455 M b
456 --------------
456 --------------
457
457
458 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
458 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
459 created new head
459 created new head
460 --------------
460 --------------
461 test L:nc a b R:up a b W: - 14 merge b no ancestor
461 test L:nc a b R:up a b W: - 14 merge b no ancestor
462 --------------
462 --------------
463 searching for copies back to rev 1
463 searching for copies back to rev 1
464 resolving manifests
464 resolving manifests
465 overwrite: False, partial: False
465 overwrite: False, partial: False
466 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
466 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
467 a: remote is newer -> g
467 a: remote is newer -> g
468 b: versions differ -> m
468 b: versions differ -> m
469 preserving b for resolve of b
469 preserving b for resolve of b
470 rev: versions differ -> m
470 rev: versions differ -> m
471 preserving rev for resolve of rev
471 preserving rev for resolve of rev
472 updating: a 1/3 files (33.33%)
472 updating: a 1/3 files (33.33%)
473 getting a
473 getting a
474 updating: b 2/3 files (66.67%)
474 updating: b 2/3 files (66.67%)
475 picked tool 'python ../merge' for b (binary False symlink False)
475 picked tool 'python ../merge' for b (binary False symlink False)
476 merging b
476 merging b
477 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
477 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
478 updating: rev 3/3 files (100.00%)
478 updating: rev 3/3 files (100.00%)
479 picked tool 'python ../merge' for rev (binary False symlink False)
479 picked tool 'python ../merge' for rev (binary False symlink False)
480 merging rev
480 merging rev
481 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
481 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
482 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
482 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
483 (branch merge, don't forget to commit)
483 (branch merge, don't forget to commit)
484 --------------
484 --------------
485 M a
485 M a
486 M b
486 M b
487 --------------
487 --------------
488
488
489 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
489 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
490 created new head
490 created new head
491 --------------
491 --------------
492 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
492 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
493 --------------
493 --------------
494 searching for copies back to rev 1
494 searching for copies back to rev 1
495 resolving manifests
495 resolving manifests
496 overwrite: False, partial: False
496 overwrite: False, partial: False
497 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
497 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
498 a: other deleted -> r
498 a: other deleted -> r
499 b: versions differ -> m
499 b: versions differ -> m
500 preserving b for resolve of b
500 preserving b for resolve of b
501 rev: versions differ -> m
501 rev: versions differ -> m
502 preserving rev for resolve of rev
502 preserving rev for resolve of rev
503 updating: a 1/3 files (33.33%)
503 updating: a 1/3 files (33.33%)
504 removing a
504 removing a
505 updating: b 2/3 files (66.67%)
505 updating: b 2/3 files (66.67%)
506 picked tool 'python ../merge' for b (binary False symlink False)
506 picked tool 'python ../merge' for b (binary False symlink False)
507 merging b
507 merging b
508 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
508 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
509 updating: rev 3/3 files (100.00%)
509 updating: rev 3/3 files (100.00%)
510 picked tool 'python ../merge' for rev (binary False symlink False)
510 picked tool 'python ../merge' for rev (binary False symlink False)
511 merging rev
511 merging rev
512 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
512 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
513 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
513 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
514 (branch merge, don't forget to commit)
514 (branch merge, don't forget to commit)
515 --------------
515 --------------
516 M b
516 M b
517 --------------
517 --------------
518
518
519 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
519 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
520 created new head
520 created new head
521 --------------
521 --------------
522 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
522 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
523 --------------
523 --------------
524 searching for copies back to rev 1
524 searching for copies back to rev 1
525 resolving manifests
525 resolving manifests
526 overwrite: False, partial: False
526 overwrite: False, partial: False
527 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
527 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
528 a: remote is newer -> g
528 a: remote is newer -> g
529 b: versions differ -> m
529 b: versions differ -> m
530 preserving b for resolve of b
530 preserving b for resolve of b
531 rev: versions differ -> m
531 rev: versions differ -> m
532 preserving rev for resolve of rev
532 preserving rev for resolve of rev
533 updating: a 1/3 files (33.33%)
533 updating: a 1/3 files (33.33%)
534 getting a
534 getting a
535 updating: b 2/3 files (66.67%)
535 updating: b 2/3 files (66.67%)
536 picked tool 'python ../merge' for b (binary False symlink False)
536 picked tool 'python ../merge' for b (binary False symlink False)
537 merging b
537 merging b
538 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
538 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
539 updating: rev 3/3 files (100.00%)
539 updating: rev 3/3 files (100.00%)
540 picked tool 'python ../merge' for rev (binary False symlink False)
540 picked tool 'python ../merge' for rev (binary False symlink False)
541 merging rev
541 merging rev
542 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
542 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
543 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
543 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
544 (branch merge, don't forget to commit)
544 (branch merge, don't forget to commit)
545 --------------
545 --------------
546 M a
546 M a
547 M b
547 M b
548 --------------
548 --------------
549
549
550 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
550 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
551 created new head
551 created new head
552 --------------
552 --------------
553 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
553 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
554 --------------
554 --------------
555 searching for copies back to rev 1
555 searching for copies back to rev 1
556 resolving manifests
556 resolving manifests
557 overwrite: False, partial: False
557 overwrite: False, partial: False
558 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
558 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
559 b: versions differ -> m
559 b: versions differ -> m
560 preserving b for resolve of b
560 preserving b for resolve of b
561 rev: versions differ -> m
561 rev: versions differ -> m
562 preserving rev for resolve of rev
562 preserving rev for resolve of rev
563 updating: b 1/2 files (50.00%)
563 updating: b 1/2 files (50.00%)
564 picked tool 'python ../merge' for b (binary False symlink False)
564 picked tool 'python ../merge' for b (binary False symlink False)
565 merging b
565 merging b
566 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
566 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
567 updating: rev 2/2 files (100.00%)
567 updating: rev 2/2 files (100.00%)
568 picked tool 'python ../merge' for rev (binary False symlink False)
568 picked tool 'python ../merge' for rev (binary False symlink False)
569 merging rev
569 merging rev
570 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
570 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
571 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
571 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
572 (branch merge, don't forget to commit)
572 (branch merge, don't forget to commit)
573 --------------
573 --------------
574 M b
574 M b
575 C a
575 C a
576 --------------
576 --------------
577
577
578 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
578 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
579 created new head
579 created new head
580 --------------
580 --------------
581 test L:nm a b R:up a b W: - 18 merge b no ancestor
581 test L:nm a b R:up a b W: - 18 merge b no ancestor
582 --------------
582 --------------
583 searching for copies back to rev 1
583 searching for copies back to rev 1
584 resolving manifests
584 resolving manifests
585 overwrite: False, partial: False
585 overwrite: False, partial: False
586 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
586 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
587 remote changed a which local deleted
587 remote changed a which local deleted
588 use (c)hanged version or leave (d)eleted? c
588 use (c)hanged version or leave (d)eleted? c
589 a: prompt recreating -> g
589 a: prompt recreating -> g
590 b: versions differ -> m
590 b: versions differ -> m
591 preserving b for resolve of b
591 preserving b for resolve of b
592 rev: versions differ -> m
592 rev: versions differ -> m
593 preserving rev for resolve of rev
593 preserving rev for resolve of rev
594 updating: a 1/3 files (33.33%)
594 updating: a 1/3 files (33.33%)
595 getting a
595 getting a
596 updating: b 2/3 files (66.67%)
596 updating: b 2/3 files (66.67%)
597 picked tool 'python ../merge' for b (binary False symlink False)
597 picked tool 'python ../merge' for b (binary False symlink False)
598 merging b
598 merging b
599 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
599 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
600 updating: rev 3/3 files (100.00%)
600 updating: rev 3/3 files (100.00%)
601 picked tool 'python ../merge' for rev (binary False symlink False)
601 picked tool 'python ../merge' for rev (binary False symlink False)
602 merging rev
602 merging rev
603 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
603 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
604 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
604 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
605 (branch merge, don't forget to commit)
605 (branch merge, don't forget to commit)
606 --------------
606 --------------
607 M a
607 M a
608 M b
608 M b
609 --------------
609 --------------
610
610
611 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
611 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
612 created new head
612 created new head
613 --------------
613 --------------
614 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
614 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
615 --------------
615 --------------
616 searching for copies back to rev 1
616 searching for copies back to rev 1
617 resolving manifests
617 resolving manifests
618 overwrite: False, partial: False
618 overwrite: False, partial: False
619 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
619 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
620 local changed a which remote deleted
620 local changed a which remote deleted
621 use (c)hanged version or (d)elete? c
621 use (c)hanged version or (d)elete? c
622 a: prompt keep -> a
622 a: prompt keep -> a
623 b: versions differ -> m
623 b: versions differ -> m
624 preserving b for resolve of b
624 preserving b for resolve of b
625 rev: versions differ -> m
625 rev: versions differ -> m
626 preserving rev for resolve of rev
626 preserving rev for resolve of rev
627 updating: a 1/3 files (33.33%)
627 updating: a 1/3 files (33.33%)
628 updating: b 2/3 files (66.67%)
628 updating: b 2/3 files (66.67%)
629 picked tool 'python ../merge' for b (binary False symlink False)
629 picked tool 'python ../merge' for b (binary False symlink False)
630 merging b
630 merging b
631 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
631 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
632 updating: rev 3/3 files (100.00%)
632 updating: rev 3/3 files (100.00%)
633 picked tool 'python ../merge' for rev (binary False symlink False)
633 picked tool 'python ../merge' for rev (binary False symlink False)
634 merging rev
634 merging rev
635 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
635 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
636 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
636 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
637 (branch merge, don't forget to commit)
637 (branch merge, don't forget to commit)
638 --------------
638 --------------
639 M b
639 M b
640 C a
640 C a
641 --------------
641 --------------
642
642
643 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
643 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
644 created new head
644 created new head
645 --------------
645 --------------
646 test L:up a R:um a b W: - 20 merge a and b to b, remove a
646 test L:up a R:um a b W: - 20 merge a and b to b, remove a
647 --------------
647 --------------
648 searching for copies back to rev 1
648 searching for copies back to rev 1
649 unmatched files in other:
649 unmatched files in other:
650 b
650 b
651 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
651 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
652 src: 'a' -> dst: 'b' *
652 src: 'a' -> dst: 'b' *
653 checking for directory renames
653 checking for directory renames
654 resolving manifests
654 resolving manifests
655 overwrite: False, partial: False
655 overwrite: False, partial: False
656 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
656 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
657 a: remote moved to b -> m
657 a: remote moved to b -> m
658 preserving a for resolve of b
658 preserving a for resolve of b
659 rev: versions differ -> m
659 rev: versions differ -> m
660 preserving rev for resolve of rev
660 preserving rev for resolve of rev
661 removing a
661 removing a
662 updating: a 1/2 files (50.00%)
662 updating: a 1/2 files (50.00%)
663 picked tool 'python ../merge' for b (binary False symlink False)
663 picked tool 'python ../merge' for b (binary False symlink False)
664 merging a and b to b
664 merging a and b to b
665 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
665 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
666 updating: rev 2/2 files (100.00%)
666 updating: rev 2/2 files (100.00%)
667 picked tool 'python ../merge' for rev (binary False symlink False)
667 picked tool 'python ../merge' for rev (binary False symlink False)
668 merging rev
668 merging rev
669 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
669 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
670 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
670 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
671 (branch merge, don't forget to commit)
671 (branch merge, don't forget to commit)
672 --------------
672 --------------
673 M b
673 M b
674 a
674 a
675 --------------
675 --------------
676
676
677 $ tm "um a b" "up a " " " "21 merge a and b to b"
677 $ tm "um a b" "up a " " " "21 merge a and b to b"
678 created new head
678 created new head
679 --------------
679 --------------
680 test L:um a b R:up a W: - 21 merge a and b to b
680 test L:um a b R:up a W: - 21 merge a and b to b
681 --------------
681 --------------
682 searching for copies back to rev 1
682 searching for copies back to rev 1
683 unmatched files in local:
683 unmatched files in local:
684 b
684 b
685 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
685 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
686 src: 'a' -> dst: 'b' *
686 src: 'a' -> dst: 'b' *
687 checking for directory renames
687 checking for directory renames
688 resolving manifests
688 resolving manifests
689 overwrite: False, partial: False
689 overwrite: False, partial: False
690 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
690 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
691 b: local copied/moved to a -> m
691 b: local copied/moved to a -> m
692 preserving b for resolve of b
692 preserving b for resolve of b
693 rev: versions differ -> m
693 rev: versions differ -> m
694 preserving rev for resolve of rev
694 preserving rev for resolve of rev
695 updating: b 1/2 files (50.00%)
695 updating: b 1/2 files (50.00%)
696 picked tool 'python ../merge' for b (binary False symlink False)
696 picked tool 'python ../merge' for b (binary False symlink False)
697 merging b and a to b
697 merging b and a to b
698 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
698 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
699 updating: rev 2/2 files (100.00%)
699 updating: rev 2/2 files (100.00%)
700 picked tool 'python ../merge' for rev (binary False symlink False)
700 picked tool 'python ../merge' for rev (binary False symlink False)
701 merging rev
701 merging rev
702 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
702 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
703 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
703 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
704 (branch merge, don't forget to commit)
704 (branch merge, don't forget to commit)
705 --------------
705 --------------
706 M b
706 M b
707 a
707 a
708 --------------
708 --------------
709
709
710
710
711 m "nm a b" "um x a" " " "22 get a, keep b"
711 m "nm a b" "um x a" " " "22 get a, keep b"
712
712
713 $ tm "nm a b" "up a c" " " "23 get c, keep b"
713 $ tm "nm a b" "up a c" " " "23 get c, keep b"
714 created new head
714 created new head
715 --------------
715 --------------
716 test L:nm a b R:up a c W: - 23 get c, keep b
716 test L:nm a b R:up a c W: - 23 get c, keep b
717 --------------
717 --------------
718 searching for copies back to rev 1
718 searching for copies back to rev 1
719 unmatched files in local:
719 unmatched files in local:
720 b
720 b
721 unmatched files in other:
721 unmatched files in other:
722 c
722 c
723 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
723 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
724 src: 'a' -> dst: 'b' *
724 src: 'a' -> dst: 'b' *
725 checking for directory renames
725 checking for directory renames
726 resolving manifests
726 resolving manifests
727 overwrite: False, partial: False
727 overwrite: False, partial: False
728 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
728 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
729 b: local copied/moved to a -> m
729 b: local copied/moved to a -> m
730 preserving b for resolve of b
730 preserving b for resolve of b
731 c: remote created -> g
731 c: remote created -> g
732 rev: versions differ -> m
732 rev: versions differ -> m
733 preserving rev for resolve of rev
733 preserving rev for resolve of rev
734 updating: b 1/3 files (33.33%)
734 updating: b 1/3 files (33.33%)
735 picked tool 'python ../merge' for b (binary False symlink False)
735 picked tool 'python ../merge' for b (binary False symlink False)
736 merging b and a to b
736 merging b and a to b
737 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
737 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
738 premerge successful
738 premerge successful
739 updating: c 2/3 files (66.67%)
739 updating: c 2/3 files (66.67%)
740 getting c
740 getting c
741 updating: rev 3/3 files (100.00%)
741 updating: rev 3/3 files (100.00%)
742 picked tool 'python ../merge' for rev (binary False symlink False)
742 picked tool 'python ../merge' for rev (binary False symlink False)
743 merging rev
743 merging rev
744 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
744 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
745 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
745 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
746 (branch merge, don't forget to commit)
746 (branch merge, don't forget to commit)
747 --------------
747 --------------
748 M b
748 M b
749 a
749 a
750 M c
750 M c
751 --------------
751 --------------
752
752
753
753
754 $ cd ..
754 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now