##// END OF EJS Templates
merge: change priority / ordering of merge actions...
Mads Kiilerich -
r21389:e7419720 default
parent child Browse files
Show More
@@ -1,1109 +1,1112 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 import struct
8 import struct
9
9
10 from node import nullid, nullrev, hex, bin
10 from node import nullid, nullrev, hex, bin
11 from i18n import _
11 from i18n import _
12 from mercurial import obsolete
12 from mercurial import obsolete
13 import error, util, filemerge, copies, subrepo, worker, dicthelpers
13 import error, util, filemerge, copies, subrepo, worker, dicthelpers
14 import errno, os, shutil
14 import errno, os, shutil
15
15
16 _pack = struct.pack
16 _pack = struct.pack
17 _unpack = struct.unpack
17 _unpack = struct.unpack
18
18
19 def _droponode(data):
19 def _droponode(data):
20 # used for compatibility for v1
20 # used for compatibility for v1
21 bits = data.split("\0")
21 bits = data.split("\0")
22 bits = bits[:-2] + bits[-1:]
22 bits = bits[:-2] + bits[-1:]
23 return "\0".join(bits)
23 return "\0".join(bits)
24
24
25 class mergestate(object):
25 class mergestate(object):
26 '''track 3-way merge state of individual files
26 '''track 3-way merge state of individual files
27
27
28 it is stored on disk when needed. Two file are used, one with an old
28 it is stored on disk when needed. Two file are used, one with an old
29 format, one with a new format. Both contains similar data, but the new
29 format, one with a new format. Both contains similar data, but the new
30 format can store new kind of field.
30 format can store new kind of field.
31
31
32 Current new format is a list of arbitrary record of the form:
32 Current new format is a list of arbitrary record of the form:
33
33
34 [type][length][content]
34 [type][length][content]
35
35
36 Type is a single character, length is a 4 bytes integer, content is an
36 Type is a single character, length is a 4 bytes integer, content is an
37 arbitrary suites of bytes of length `length`.
37 arbitrary suites of bytes of length `length`.
38
38
39 Type should be a letter. Capital letter are mandatory record, Mercurial
39 Type should be a letter. Capital letter are mandatory record, Mercurial
40 should abort if they are unknown. lower case record can be safely ignored.
40 should abort if they are unknown. lower case record can be safely ignored.
41
41
42 Currently known record:
42 Currently known record:
43
43
44 L: the node of the "local" part of the merge (hexified version)
44 L: the node of the "local" part of the merge (hexified version)
45 O: the node of the "other" part of the merge (hexified version)
45 O: the node of the "other" part of the merge (hexified version)
46 F: a file to be merged entry
46 F: a file to be merged entry
47 '''
47 '''
48 statepathv1 = "merge/state"
48 statepathv1 = "merge/state"
49 statepathv2 = "merge/state2"
49 statepathv2 = "merge/state2"
50
50
51 def __init__(self, repo):
51 def __init__(self, repo):
52 self._repo = repo
52 self._repo = repo
53 self._dirty = False
53 self._dirty = False
54 self._read()
54 self._read()
55
55
56 def reset(self, node=None, other=None):
56 def reset(self, node=None, other=None):
57 self._state = {}
57 self._state = {}
58 self._local = None
58 self._local = None
59 self._other = None
59 self._other = None
60 if node:
60 if node:
61 self._local = node
61 self._local = node
62 self._other = other
62 self._other = other
63 shutil.rmtree(self._repo.join("merge"), True)
63 shutil.rmtree(self._repo.join("merge"), True)
64 self._dirty = False
64 self._dirty = False
65
65
66 def _read(self):
66 def _read(self):
67 """Analyse each record content to restore a serialized state from disk
67 """Analyse each record content to restore a serialized state from disk
68
68
69 This function process "record" entry produced by the de-serialization
69 This function process "record" entry produced by the de-serialization
70 of on disk file.
70 of on disk file.
71 """
71 """
72 self._state = {}
72 self._state = {}
73 self._local = None
73 self._local = None
74 self._other = None
74 self._other = None
75 records = self._readrecords()
75 records = self._readrecords()
76 for rtype, record in records:
76 for rtype, record in records:
77 if rtype == 'L':
77 if rtype == 'L':
78 self._local = bin(record)
78 self._local = bin(record)
79 elif rtype == 'O':
79 elif rtype == 'O':
80 self._other = bin(record)
80 self._other = bin(record)
81 elif rtype == "F":
81 elif rtype == "F":
82 bits = record.split("\0")
82 bits = record.split("\0")
83 self._state[bits[0]] = bits[1:]
83 self._state[bits[0]] = bits[1:]
84 elif not rtype.islower():
84 elif not rtype.islower():
85 raise util.Abort(_('unsupported merge state record: %s')
85 raise util.Abort(_('unsupported merge state record: %s')
86 % rtype)
86 % rtype)
87 self._dirty = False
87 self._dirty = False
88
88
89 def _readrecords(self):
89 def _readrecords(self):
90 """Read merge state from disk and return a list of record (TYPE, data)
90 """Read merge state from disk and return a list of record (TYPE, data)
91
91
92 We read data from both v1 and v2 files and decide which one to use.
92 We read data from both v1 and v2 files and decide which one to use.
93
93
94 V1 has been used by version prior to 2.9.1 and contains less data than
94 V1 has been used by version prior to 2.9.1 and contains less data than
95 v2. We read both versions and check if no data in v2 contradicts
95 v2. We read both versions and check if no data in v2 contradicts
96 v1. If there is not contradiction we can safely assume that both v1
96 v1. If there is not contradiction we can safely assume that both v1
97 and v2 were written at the same time and use the extract data in v2. If
97 and v2 were written at the same time and use the extract data in v2. If
98 there is contradiction we ignore v2 content as we assume an old version
98 there is contradiction we ignore v2 content as we assume an old version
99 of Mercurial has overwritten the mergestate file and left an old v2
99 of Mercurial has overwritten the mergestate file and left an old v2
100 file around.
100 file around.
101
101
102 returns list of record [(TYPE, data), ...]"""
102 returns list of record [(TYPE, data), ...]"""
103 v1records = self._readrecordsv1()
103 v1records = self._readrecordsv1()
104 v2records = self._readrecordsv2()
104 v2records = self._readrecordsv2()
105 oldv2 = set() # old format version of v2 record
105 oldv2 = set() # old format version of v2 record
106 for rec in v2records:
106 for rec in v2records:
107 if rec[0] == 'L':
107 if rec[0] == 'L':
108 oldv2.add(rec)
108 oldv2.add(rec)
109 elif rec[0] == 'F':
109 elif rec[0] == 'F':
110 # drop the onode data (not contained in v1)
110 # drop the onode data (not contained in v1)
111 oldv2.add(('F', _droponode(rec[1])))
111 oldv2.add(('F', _droponode(rec[1])))
112 for rec in v1records:
112 for rec in v1records:
113 if rec not in oldv2:
113 if rec not in oldv2:
114 # v1 file is newer than v2 file, use it
114 # v1 file is newer than v2 file, use it
115 # we have to infer the "other" changeset of the merge
115 # we have to infer the "other" changeset of the merge
116 # we cannot do better than that with v1 of the format
116 # we cannot do better than that with v1 of the format
117 mctx = self._repo[None].parents()[-1]
117 mctx = self._repo[None].parents()[-1]
118 v1records.append(('O', mctx.hex()))
118 v1records.append(('O', mctx.hex()))
119 # add place holder "other" file node information
119 # add place holder "other" file node information
120 # nobody is using it yet so we do no need to fetch the data
120 # nobody is using it yet so we do no need to fetch the data
121 # if mctx was wrong `mctx[bits[-2]]` may fails.
121 # if mctx was wrong `mctx[bits[-2]]` may fails.
122 for idx, r in enumerate(v1records):
122 for idx, r in enumerate(v1records):
123 if r[0] == 'F':
123 if r[0] == 'F':
124 bits = r[1].split("\0")
124 bits = r[1].split("\0")
125 bits.insert(-2, '')
125 bits.insert(-2, '')
126 v1records[idx] = (r[0], "\0".join(bits))
126 v1records[idx] = (r[0], "\0".join(bits))
127 return v1records
127 return v1records
128 else:
128 else:
129 return v2records
129 return v2records
130
130
131 def _readrecordsv1(self):
131 def _readrecordsv1(self):
132 """read on disk merge state for version 1 file
132 """read on disk merge state for version 1 file
133
133
134 returns list of record [(TYPE, data), ...]
134 returns list of record [(TYPE, data), ...]
135
135
136 Note: the "F" data from this file are one entry short
136 Note: the "F" data from this file are one entry short
137 (no "other file node" entry)
137 (no "other file node" entry)
138 """
138 """
139 records = []
139 records = []
140 try:
140 try:
141 f = self._repo.opener(self.statepathv1)
141 f = self._repo.opener(self.statepathv1)
142 for i, l in enumerate(f):
142 for i, l in enumerate(f):
143 if i == 0:
143 if i == 0:
144 records.append(('L', l[:-1]))
144 records.append(('L', l[:-1]))
145 else:
145 else:
146 records.append(('F', l[:-1]))
146 records.append(('F', l[:-1]))
147 f.close()
147 f.close()
148 except IOError, err:
148 except IOError, err:
149 if err.errno != errno.ENOENT:
149 if err.errno != errno.ENOENT:
150 raise
150 raise
151 return records
151 return records
152
152
153 def _readrecordsv2(self):
153 def _readrecordsv2(self):
154 """read on disk merge state for version 2 file
154 """read on disk merge state for version 2 file
155
155
156 returns list of record [(TYPE, data), ...]
156 returns list of record [(TYPE, data), ...]
157 """
157 """
158 records = []
158 records = []
159 try:
159 try:
160 f = self._repo.opener(self.statepathv2)
160 f = self._repo.opener(self.statepathv2)
161 data = f.read()
161 data = f.read()
162 off = 0
162 off = 0
163 end = len(data)
163 end = len(data)
164 while off < end:
164 while off < end:
165 rtype = data[off]
165 rtype = data[off]
166 off += 1
166 off += 1
167 length = _unpack('>I', data[off:(off + 4)])[0]
167 length = _unpack('>I', data[off:(off + 4)])[0]
168 off += 4
168 off += 4
169 record = data[off:(off + length)]
169 record = data[off:(off + length)]
170 off += length
170 off += length
171 records.append((rtype, record))
171 records.append((rtype, record))
172 f.close()
172 f.close()
173 except IOError, err:
173 except IOError, err:
174 if err.errno != errno.ENOENT:
174 if err.errno != errno.ENOENT:
175 raise
175 raise
176 return records
176 return records
177
177
178 def active(self):
178 def active(self):
179 """Whether mergestate is active.
179 """Whether mergestate is active.
180
180
181 Returns True if there appears to be mergestate. This is a rough proxy
181 Returns True if there appears to be mergestate. This is a rough proxy
182 for "is a merge in progress."
182 for "is a merge in progress."
183 """
183 """
184 # Check local variables before looking at filesystem for performance
184 # Check local variables before looking at filesystem for performance
185 # reasons.
185 # reasons.
186 return bool(self._local) or bool(self._state) or \
186 return bool(self._local) or bool(self._state) or \
187 self._repo.opener.exists(self.statepathv1) or \
187 self._repo.opener.exists(self.statepathv1) or \
188 self._repo.opener.exists(self.statepathv2)
188 self._repo.opener.exists(self.statepathv2)
189
189
190 def commit(self):
190 def commit(self):
191 """Write current state on disk (if necessary)"""
191 """Write current state on disk (if necessary)"""
192 if self._dirty:
192 if self._dirty:
193 records = []
193 records = []
194 records.append(("L", hex(self._local)))
194 records.append(("L", hex(self._local)))
195 records.append(("O", hex(self._other)))
195 records.append(("O", hex(self._other)))
196 for d, v in self._state.iteritems():
196 for d, v in self._state.iteritems():
197 records.append(("F", "\0".join([d] + v)))
197 records.append(("F", "\0".join([d] + v)))
198 self._writerecords(records)
198 self._writerecords(records)
199 self._dirty = False
199 self._dirty = False
200
200
201 def _writerecords(self, records):
201 def _writerecords(self, records):
202 """Write current state on disk (both v1 and v2)"""
202 """Write current state on disk (both v1 and v2)"""
203 self._writerecordsv1(records)
203 self._writerecordsv1(records)
204 self._writerecordsv2(records)
204 self._writerecordsv2(records)
205
205
206 def _writerecordsv1(self, records):
206 def _writerecordsv1(self, records):
207 """Write current state on disk in a version 1 file"""
207 """Write current state on disk in a version 1 file"""
208 f = self._repo.opener(self.statepathv1, "w")
208 f = self._repo.opener(self.statepathv1, "w")
209 irecords = iter(records)
209 irecords = iter(records)
210 lrecords = irecords.next()
210 lrecords = irecords.next()
211 assert lrecords[0] == 'L'
211 assert lrecords[0] == 'L'
212 f.write(hex(self._local) + "\n")
212 f.write(hex(self._local) + "\n")
213 for rtype, data in irecords:
213 for rtype, data in irecords:
214 if rtype == "F":
214 if rtype == "F":
215 f.write("%s\n" % _droponode(data))
215 f.write("%s\n" % _droponode(data))
216 f.close()
216 f.close()
217
217
218 def _writerecordsv2(self, records):
218 def _writerecordsv2(self, records):
219 """Write current state on disk in a version 2 file"""
219 """Write current state on disk in a version 2 file"""
220 f = self._repo.opener(self.statepathv2, "w")
220 f = self._repo.opener(self.statepathv2, "w")
221 for key, data in records:
221 for key, data in records:
222 assert len(key) == 1
222 assert len(key) == 1
223 format = ">sI%is" % len(data)
223 format = ">sI%is" % len(data)
224 f.write(_pack(format, key, len(data), data))
224 f.write(_pack(format, key, len(data), data))
225 f.close()
225 f.close()
226
226
227 def add(self, fcl, fco, fca, fd):
227 def add(self, fcl, fco, fca, fd):
228 """add a new (potentially?) conflicting file the merge state
228 """add a new (potentially?) conflicting file the merge state
229 fcl: file context for local,
229 fcl: file context for local,
230 fco: file context for remote,
230 fco: file context for remote,
231 fca: file context for ancestors,
231 fca: file context for ancestors,
232 fd: file path of the resulting merge.
232 fd: file path of the resulting merge.
233
233
234 note: also write the local version to the `.hg/merge` directory.
234 note: also write the local version to the `.hg/merge` directory.
235 """
235 """
236 hash = util.sha1(fcl.path()).hexdigest()
236 hash = util.sha1(fcl.path()).hexdigest()
237 self._repo.opener.write("merge/" + hash, fcl.data())
237 self._repo.opener.write("merge/" + hash, fcl.data())
238 self._state[fd] = ['u', hash, fcl.path(),
238 self._state[fd] = ['u', hash, fcl.path(),
239 fca.path(), hex(fca.filenode()),
239 fca.path(), hex(fca.filenode()),
240 fco.path(), hex(fco.filenode()),
240 fco.path(), hex(fco.filenode()),
241 fcl.flags()]
241 fcl.flags()]
242 self._dirty = True
242 self._dirty = True
243
243
244 def __contains__(self, dfile):
244 def __contains__(self, dfile):
245 return dfile in self._state
245 return dfile in self._state
246
246
247 def __getitem__(self, dfile):
247 def __getitem__(self, dfile):
248 return self._state[dfile][0]
248 return self._state[dfile][0]
249
249
250 def __iter__(self):
250 def __iter__(self):
251 return iter(sorted(self._state))
251 return iter(sorted(self._state))
252
252
253 def files(self):
253 def files(self):
254 return self._state.keys()
254 return self._state.keys()
255
255
256 def mark(self, dfile, state):
256 def mark(self, dfile, state):
257 self._state[dfile][0] = state
257 self._state[dfile][0] = state
258 self._dirty = True
258 self._dirty = True
259
259
260 def unresolved(self):
260 def unresolved(self):
261 """Obtain the paths of unresolved files."""
261 """Obtain the paths of unresolved files."""
262
262
263 for f, entry in self._state.items():
263 for f, entry in self._state.items():
264 if entry[0] == 'u':
264 if entry[0] == 'u':
265 yield f
265 yield f
266
266
267 def resolve(self, dfile, wctx):
267 def resolve(self, dfile, wctx):
268 """rerun merge process for file path `dfile`"""
268 """rerun merge process for file path `dfile`"""
269 if self[dfile] == 'r':
269 if self[dfile] == 'r':
270 return 0
270 return 0
271 stateentry = self._state[dfile]
271 stateentry = self._state[dfile]
272 state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
272 state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
273 octx = self._repo[self._other]
273 octx = self._repo[self._other]
274 fcd = wctx[dfile]
274 fcd = wctx[dfile]
275 fco = octx[ofile]
275 fco = octx[ofile]
276 fca = self._repo.filectx(afile, fileid=anode)
276 fca = self._repo.filectx(afile, fileid=anode)
277 # "premerge" x flags
277 # "premerge" x flags
278 flo = fco.flags()
278 flo = fco.flags()
279 fla = fca.flags()
279 fla = fca.flags()
280 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
280 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
281 if fca.node() == nullid:
281 if fca.node() == nullid:
282 self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
282 self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
283 afile)
283 afile)
284 elif flags == fla:
284 elif flags == fla:
285 flags = flo
285 flags = flo
286 # restore local
286 # restore local
287 f = self._repo.opener("merge/" + hash)
287 f = self._repo.opener("merge/" + hash)
288 self._repo.wwrite(dfile, f.read(), flags)
288 self._repo.wwrite(dfile, f.read(), flags)
289 f.close()
289 f.close()
290 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
290 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
291 if r is None:
291 if r is None:
292 # no real conflict
292 # no real conflict
293 del self._state[dfile]
293 del self._state[dfile]
294 self._dirty = True
294 self._dirty = True
295 elif not r:
295 elif not r:
296 self.mark(dfile, 'r')
296 self.mark(dfile, 'r')
297 return r
297 return r
298
298
299 def _checkunknownfile(repo, wctx, mctx, f):
299 def _checkunknownfile(repo, wctx, mctx, f):
300 return (not repo.dirstate._ignore(f)
300 return (not repo.dirstate._ignore(f)
301 and os.path.isfile(repo.wjoin(f))
301 and os.path.isfile(repo.wjoin(f))
302 and repo.wopener.audit.check(f)
302 and repo.wopener.audit.check(f)
303 and repo.dirstate.normalize(f) not in repo.dirstate
303 and repo.dirstate.normalize(f) not in repo.dirstate
304 and mctx[f].cmp(wctx[f]))
304 and mctx[f].cmp(wctx[f]))
305
305
306 def _checkunknown(repo, wctx, mctx):
306 def _checkunknown(repo, wctx, mctx):
307 "check for collisions between unknown files and files in mctx"
307 "check for collisions between unknown files and files in mctx"
308
308
309 error = False
309 error = False
310 for f in mctx:
310 for f in mctx:
311 if f not in wctx and _checkunknownfile(repo, wctx, mctx, f):
311 if f not in wctx and _checkunknownfile(repo, wctx, mctx, f):
312 error = True
312 error = True
313 wctx._repo.ui.warn(_("%s: untracked file differs\n") % f)
313 wctx._repo.ui.warn(_("%s: untracked file differs\n") % f)
314 if error:
314 if error:
315 raise util.Abort(_("untracked files in working directory differ "
315 raise util.Abort(_("untracked files in working directory differ "
316 "from files in requested revision"))
316 "from files in requested revision"))
317
317
318 def _forgetremoved(wctx, mctx, branchmerge):
318 def _forgetremoved(wctx, mctx, branchmerge):
319 """
319 """
320 Forget removed files
320 Forget removed files
321
321
322 If we're jumping between revisions (as opposed to merging), and if
322 If we're jumping between revisions (as opposed to merging), and if
323 neither the working directory nor the target rev has the file,
323 neither the working directory nor the target rev has the file,
324 then we need to remove it from the dirstate, to prevent the
324 then we need to remove it from the dirstate, to prevent the
325 dirstate from listing the file when it is no longer in the
325 dirstate from listing the file when it is no longer in the
326 manifest.
326 manifest.
327
327
328 If we're merging, and the other revision has removed a file
328 If we're merging, and the other revision has removed a file
329 that is not present in the working directory, we need to mark it
329 that is not present in the working directory, we need to mark it
330 as removed.
330 as removed.
331 """
331 """
332
332
333 actions = []
333 actions = []
334 state = branchmerge and 'r' or 'f'
334 state = branchmerge and 'r' or 'f'
335 for f in wctx.deleted():
335 for f in wctx.deleted():
336 if f not in mctx:
336 if f not in mctx:
337 actions.append((f, state, None, "forget deleted"))
337 actions.append((f, state, None, "forget deleted"))
338
338
339 if not branchmerge:
339 if not branchmerge:
340 for f in wctx.removed():
340 for f in wctx.removed():
341 if f not in mctx:
341 if f not in mctx:
342 actions.append((f, "f", None, "forget removed"))
342 actions.append((f, "f", None, "forget removed"))
343
343
344 return actions
344 return actions
345
345
346 def _checkcollision(repo, wmf, actions):
346 def _checkcollision(repo, wmf, actions):
347 # build provisional merged manifest up
347 # build provisional merged manifest up
348 pmmf = set(wmf)
348 pmmf = set(wmf)
349
349
350 def addop(f, args):
350 def addop(f, args):
351 pmmf.add(f)
351 pmmf.add(f)
352 def removeop(f, args):
352 def removeop(f, args):
353 pmmf.discard(f)
353 pmmf.discard(f)
354 def nop(f, args):
354 def nop(f, args):
355 pass
355 pass
356
356
357 def renamemoveop(f, args):
357 def renamemoveop(f, args):
358 f2, flags = args
358 f2, flags = args
359 pmmf.discard(f2)
359 pmmf.discard(f2)
360 pmmf.add(f)
360 pmmf.add(f)
361 def renamegetop(f, args):
361 def renamegetop(f, args):
362 f2, flags = args
362 f2, flags = args
363 pmmf.add(f)
363 pmmf.add(f)
364 def mergeop(f, args):
364 def mergeop(f, args):
365 f1, f2, fa, move, anc = args
365 f1, f2, fa, move, anc = args
366 if move:
366 if move:
367 pmmf.discard(f1)
367 pmmf.discard(f1)
368 pmmf.add(f)
368 pmmf.add(f)
369
369
370 opmap = {
370 opmap = {
371 "a": addop,
371 "a": addop,
372 "dm": renamemoveop,
372 "dm": renamemoveop,
373 "dg": renamegetop,
373 "dg": renamegetop,
374 "dr": nop,
374 "dr": nop,
375 "e": nop,
375 "e": nop,
376 "k": nop,
376 "k": nop,
377 "f": addop, # untracked file should be kept in working directory
377 "f": addop, # untracked file should be kept in working directory
378 "g": addop,
378 "g": addop,
379 "m": mergeop,
379 "m": mergeop,
380 "r": removeop,
380 "r": removeop,
381 "rd": nop,
381 "rd": nop,
382 "cd": addop,
382 "cd": addop,
383 "dc": addop,
383 "dc": addop,
384 }
384 }
385 for f, m, args, msg in actions:
385 for f, m, args, msg in actions:
386 op = opmap.get(m)
386 op = opmap.get(m)
387 assert op, m
387 assert op, m
388 op(f, args)
388 op(f, args)
389
389
390 # check case-folding collision in provisional merged manifest
390 # check case-folding collision in provisional merged manifest
391 foldmap = {}
391 foldmap = {}
392 for f in sorted(pmmf):
392 for f in sorted(pmmf):
393 fold = util.normcase(f)
393 fold = util.normcase(f)
394 if fold in foldmap:
394 if fold in foldmap:
395 raise util.Abort(_("case-folding collision between %s and %s")
395 raise util.Abort(_("case-folding collision between %s and %s")
396 % (f, foldmap[fold]))
396 % (f, foldmap[fold]))
397 foldmap[fold] = f
397 foldmap[fold] = f
398
398
399 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
399 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
400 acceptremote, followcopies):
400 acceptremote, followcopies):
401 """
401 """
402 Merge p1 and p2 with ancestor pa and generate merge action list
402 Merge p1 and p2 with ancestor pa and generate merge action list
403
403
404 branchmerge and force are as passed in to update
404 branchmerge and force are as passed in to update
405 partial = function to filter file lists
405 partial = function to filter file lists
406 acceptremote = accept the incoming changes without prompting
406 acceptremote = accept the incoming changes without prompting
407 """
407 """
408
408
409 actions, copy, movewithdir = [], {}, {}
409 actions, copy, movewithdir = [], {}, {}
410
410
411 # manifests fetched in order are going to be faster, so prime the caches
411 # manifests fetched in order are going to be faster, so prime the caches
412 [x.manifest() for x in
412 [x.manifest() for x in
413 sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())]
413 sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())]
414
414
415 if followcopies:
415 if followcopies:
416 ret = copies.mergecopies(repo, wctx, p2, pa)
416 ret = copies.mergecopies(repo, wctx, p2, pa)
417 copy, movewithdir, diverge, renamedelete = ret
417 copy, movewithdir, diverge, renamedelete = ret
418 for of, fl in diverge.iteritems():
418 for of, fl in diverge.iteritems():
419 actions.append((of, "dr", (fl,), "divergent renames"))
419 actions.append((of, "dr", (fl,), "divergent renames"))
420 for of, fl in renamedelete.iteritems():
420 for of, fl in renamedelete.iteritems():
421 actions.append((of, "rd", (fl,), "rename and delete"))
421 actions.append((of, "rd", (fl,), "rename and delete"))
422
422
423 repo.ui.note(_("resolving manifests\n"))
423 repo.ui.note(_("resolving manifests\n"))
424 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
424 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
425 % (bool(branchmerge), bool(force), bool(partial)))
425 % (bool(branchmerge), bool(force), bool(partial)))
426 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
426 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
427
427
428 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
428 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
429 copied = set(copy.values())
429 copied = set(copy.values())
430 copied.update(movewithdir.values())
430 copied.update(movewithdir.values())
431
431
432 if '.hgsubstate' in m1:
432 if '.hgsubstate' in m1:
433 # check whether sub state is modified
433 # check whether sub state is modified
434 for s in sorted(wctx.substate):
434 for s in sorted(wctx.substate):
435 if wctx.sub(s).dirty():
435 if wctx.sub(s).dirty():
436 m1['.hgsubstate'] += "+"
436 m1['.hgsubstate'] += "+"
437 break
437 break
438
438
439 aborts = []
439 aborts = []
440 # Compare manifests
440 # Compare manifests
441 fdiff = dicthelpers.diff(m1, m2)
441 fdiff = dicthelpers.diff(m1, m2)
442 flagsdiff = m1.flagsdiff(m2)
442 flagsdiff = m1.flagsdiff(m2)
443 diff12 = dicthelpers.join(fdiff, flagsdiff)
443 diff12 = dicthelpers.join(fdiff, flagsdiff)
444
444
445 for f, (n12, fl12) in diff12.iteritems():
445 for f, (n12, fl12) in diff12.iteritems():
446 if n12:
446 if n12:
447 n1, n2 = n12
447 n1, n2 = n12
448 else: # file contents didn't change, but flags did
448 else: # file contents didn't change, but flags did
449 n1 = n2 = m1.get(f, None)
449 n1 = n2 = m1.get(f, None)
450 if n1 is None:
450 if n1 is None:
451 # Since n1 == n2, the file isn't present in m2 either. This
451 # Since n1 == n2, the file isn't present in m2 either. This
452 # means that the file was removed or deleted locally and
452 # means that the file was removed or deleted locally and
453 # removed remotely, but that residual entries remain in flags.
453 # removed remotely, but that residual entries remain in flags.
454 # This can happen in manifests generated by workingctx.
454 # This can happen in manifests generated by workingctx.
455 continue
455 continue
456 if fl12:
456 if fl12:
457 fl1, fl2 = fl12
457 fl1, fl2 = fl12
458 else: # flags didn't change, file contents did
458 else: # flags didn't change, file contents did
459 fl1 = fl2 = m1.flags(f)
459 fl1 = fl2 = m1.flags(f)
460
460
461 if partial and not partial(f):
461 if partial and not partial(f):
462 continue
462 continue
463 if n1 and n2:
463 if n1 and n2:
464 fa = f
464 fa = f
465 a = ma.get(f, nullid)
465 a = ma.get(f, nullid)
466 if a == nullid:
466 if a == nullid:
467 fa = copy.get(f, f)
467 fa = copy.get(f, f)
468 # Note: f as default is wrong - we can't really make a 3-way
468 # Note: f as default is wrong - we can't really make a 3-way
469 # merge without an ancestor file.
469 # merge without an ancestor file.
470 fla = ma.flags(fa)
470 fla = ma.flags(fa)
471 nol = 'l' not in fl1 + fl2 + fla
471 nol = 'l' not in fl1 + fl2 + fla
472 if n2 == a and fl2 == fla:
472 if n2 == a and fl2 == fla:
473 actions.append((f, "k", (), "keep")) # remote unchanged
473 actions.append((f, "k", (), "keep")) # remote unchanged
474 elif n1 == a and fl1 == fla: # local unchanged - use remote
474 elif n1 == a and fl1 == fla: # local unchanged - use remote
475 if n1 == n2: # optimization: keep local content
475 if n1 == n2: # optimization: keep local content
476 actions.append((f, "e", (fl2,), "update permissions"))
476 actions.append((f, "e", (fl2,), "update permissions"))
477 else:
477 else:
478 actions.append((f, "g", (fl2,), "remote is newer"))
478 actions.append((f, "g", (fl2,), "remote is newer"))
479 elif nol and n2 == a: # remote only changed 'x'
479 elif nol and n2 == a: # remote only changed 'x'
480 actions.append((f, "e", (fl2,), "update permissions"))
480 actions.append((f, "e", (fl2,), "update permissions"))
481 elif nol and n1 == a: # local only changed 'x'
481 elif nol and n1 == a: # local only changed 'x'
482 actions.append((f, "g", (fl1,), "remote is newer"))
482 actions.append((f, "g", (fl1,), "remote is newer"))
483 else: # both changed something
483 else: # both changed something
484 actions.append((f, "m", (f, f, fa, False, pa.node()),
484 actions.append((f, "m", (f, f, fa, False, pa.node()),
485 "versions differ"))
485 "versions differ"))
486 elif f in copied: # files we'll deal with on m2 side
486 elif f in copied: # files we'll deal with on m2 side
487 pass
487 pass
488 elif n1 and f in movewithdir: # directory rename, move local
488 elif n1 and f in movewithdir: # directory rename, move local
489 f2 = movewithdir[f]
489 f2 = movewithdir[f]
490 actions.append((f2, "dm", (f, fl1),
490 actions.append((f2, "dm", (f, fl1),
491 "remote directory rename - move from " + f))
491 "remote directory rename - move from " + f))
492 elif n1 and f in copy:
492 elif n1 and f in copy:
493 f2 = copy[f]
493 f2 = copy[f]
494 actions.append((f, "m", (f, f2, f2, False, pa.node()),
494 actions.append((f, "m", (f, f2, f2, False, pa.node()),
495 "local copied/moved from " + f2))
495 "local copied/moved from " + f2))
496 elif n1 and f in ma: # clean, a different, no remote
496 elif n1 and f in ma: # clean, a different, no remote
497 if n1 != ma[f]:
497 if n1 != ma[f]:
498 if acceptremote:
498 if acceptremote:
499 actions.append((f, "r", None, "remote delete"))
499 actions.append((f, "r", None, "remote delete"))
500 else:
500 else:
501 actions.append((f, "cd", None, "prompt changed/deleted"))
501 actions.append((f, "cd", None, "prompt changed/deleted"))
502 elif n1[20:] == "a": # added, no remote
502 elif n1[20:] == "a": # added, no remote
503 actions.append((f, "f", None, "remote deleted"))
503 actions.append((f, "f", None, "remote deleted"))
504 else:
504 else:
505 actions.append((f, "r", None, "other deleted"))
505 actions.append((f, "r", None, "other deleted"))
506 elif n2 and f in movewithdir:
506 elif n2 and f in movewithdir:
507 f2 = movewithdir[f]
507 f2 = movewithdir[f]
508 actions.append((f2, "dg", (f, fl2),
508 actions.append((f2, "dg", (f, fl2),
509 "local directory rename - get from " + f))
509 "local directory rename - get from " + f))
510 elif n2 and f in copy:
510 elif n2 and f in copy:
511 f2 = copy[f]
511 f2 = copy[f]
512 if f2 in m2:
512 if f2 in m2:
513 actions.append((f, "m", (f2, f, f2, False, pa.node()),
513 actions.append((f, "m", (f2, f, f2, False, pa.node()),
514 "remote copied from " + f2))
514 "remote copied from " + f2))
515 else:
515 else:
516 actions.append((f, "m", (f2, f, f2, True, pa.node()),
516 actions.append((f, "m", (f2, f, f2, True, pa.node()),
517 "remote moved from " + f2))
517 "remote moved from " + f2))
518 elif n2 and f not in ma:
518 elif n2 and f not in ma:
519 # local unknown, remote created: the logic is described by the
519 # local unknown, remote created: the logic is described by the
520 # following table:
520 # following table:
521 #
521 #
522 # force branchmerge different | action
522 # force branchmerge different | action
523 # n * n | get
523 # n * n | get
524 # n * y | abort
524 # n * y | abort
525 # y n * | get
525 # y n * | get
526 # y y n | get
526 # y y n | get
527 # y y y | merge
527 # y y y | merge
528 #
528 #
529 # Checking whether the files are different is expensive, so we
529 # Checking whether the files are different is expensive, so we
530 # don't do that when we can avoid it.
530 # don't do that when we can avoid it.
531 if force and not branchmerge:
531 if force and not branchmerge:
532 actions.append((f, "g", (fl2,), "remote created"))
532 actions.append((f, "g", (fl2,), "remote created"))
533 else:
533 else:
534 different = _checkunknownfile(repo, wctx, p2, f)
534 different = _checkunknownfile(repo, wctx, p2, f)
535 if force and branchmerge and different:
535 if force and branchmerge and different:
536 # FIXME: This is wrong - f is not in ma ...
536 # FIXME: This is wrong - f is not in ma ...
537 actions.append((f, "m", (f, f, f, False, pa.node()),
537 actions.append((f, "m", (f, f, f, False, pa.node()),
538 "remote differs from untracked local"))
538 "remote differs from untracked local"))
539 elif not force and different:
539 elif not force and different:
540 aborts.append((f, "ud"))
540 aborts.append((f, "ud"))
541 else:
541 else:
542 actions.append((f, "g", (fl2,), "remote created"))
542 actions.append((f, "g", (fl2,), "remote created"))
543 elif n2 and n2 != ma[f]:
543 elif n2 and n2 != ma[f]:
544 different = _checkunknownfile(repo, wctx, p2, f)
544 different = _checkunknownfile(repo, wctx, p2, f)
545 if not force and different:
545 if not force and different:
546 aborts.append((f, "ud"))
546 aborts.append((f, "ud"))
547 else:
547 else:
548 # if different: old untracked f may be overwritten and lost
548 # if different: old untracked f may be overwritten and lost
549 if acceptremote:
549 if acceptremote:
550 actions.append((f, "g", (m2.flags(f),),
550 actions.append((f, "g", (m2.flags(f),),
551 "remote recreating"))
551 "remote recreating"))
552 else:
552 else:
553 actions.append((f, "dc", (m2.flags(f),),
553 actions.append((f, "dc", (m2.flags(f),),
554 "prompt deleted/changed"))
554 "prompt deleted/changed"))
555
555
556 for f, m in sorted(aborts):
556 for f, m in sorted(aborts):
557 if m == "ud":
557 if m == "ud":
558 repo.ui.warn(_("%s: untracked file differs\n") % f)
558 repo.ui.warn(_("%s: untracked file differs\n") % f)
559 else: assert False, m
559 else: assert False, m
560 if aborts:
560 if aborts:
561 raise util.Abort(_("untracked files in working directory differ "
561 raise util.Abort(_("untracked files in working directory differ "
562 "from files in requested revision"))
562 "from files in requested revision"))
563
563
564 if not util.checkcase(repo.path):
564 if not util.checkcase(repo.path):
565 # check collision between files only in p2 for clean update
565 # check collision between files only in p2 for clean update
566 if (not branchmerge and
566 if (not branchmerge and
567 (force or not wctx.dirty(missing=True, branch=False))):
567 (force or not wctx.dirty(missing=True, branch=False))):
568 _checkcollision(repo, m2, [])
568 _checkcollision(repo, m2, [])
569 else:
569 else:
570 _checkcollision(repo, m1, actions)
570 _checkcollision(repo, m1, actions)
571
571
572 return actions
572 return actions
573
573
574 actionpriority = dict((m, p) for p, m in enumerate(
575 ['r', 'f', 'g', 'a', 'k', 'm', 'dm', 'dg', 'dr', 'cd', 'dc', 'rd', 'e']))
576
574 def actionkey(a):
577 def actionkey(a):
575 return a[1] in "rf" and -1 or 0, a
578 return actionpriority[a[1]], a
576
579
577 def getremove(repo, mctx, overwrite, args):
580 def getremove(repo, mctx, overwrite, args):
578 """apply usually-non-interactive updates to the working directory
581 """apply usually-non-interactive updates to the working directory
579
582
580 mctx is the context to be merged into the working copy
583 mctx is the context to be merged into the working copy
581
584
582 yields tuples for progress updates
585 yields tuples for progress updates
583 """
586 """
584 verbose = repo.ui.verbose
587 verbose = repo.ui.verbose
585 unlink = util.unlinkpath
588 unlink = util.unlinkpath
586 wjoin = repo.wjoin
589 wjoin = repo.wjoin
587 fctx = mctx.filectx
590 fctx = mctx.filectx
588 wwrite = repo.wwrite
591 wwrite = repo.wwrite
589 audit = repo.wopener.audit
592 audit = repo.wopener.audit
590 i = 0
593 i = 0
591 for arg in args:
594 for arg in args:
592 f = arg[0]
595 f = arg[0]
593 if arg[1] == 'r':
596 if arg[1] == 'r':
594 if verbose:
597 if verbose:
595 repo.ui.note(_("removing %s\n") % f)
598 repo.ui.note(_("removing %s\n") % f)
596 audit(f)
599 audit(f)
597 try:
600 try:
598 unlink(wjoin(f), ignoremissing=True)
601 unlink(wjoin(f), ignoremissing=True)
599 except OSError, inst:
602 except OSError, inst:
600 repo.ui.warn(_("update failed to remove %s: %s!\n") %
603 repo.ui.warn(_("update failed to remove %s: %s!\n") %
601 (f, inst.strerror))
604 (f, inst.strerror))
602 else:
605 else:
603 if verbose:
606 if verbose:
604 repo.ui.note(_("getting %s\n") % f)
607 repo.ui.note(_("getting %s\n") % f)
605 wwrite(f, fctx(f).data(), arg[2][0])
608 wwrite(f, fctx(f).data(), arg[2][0])
606 if i == 100:
609 if i == 100:
607 yield i, f
610 yield i, f
608 i = 0
611 i = 0
609 i += 1
612 i += 1
610 if i > 0:
613 if i > 0:
611 yield i, f
614 yield i, f
612
615
613 def applyupdates(repo, actions, wctx, mctx, overwrite):
616 def applyupdates(repo, actions, wctx, mctx, overwrite):
614 """apply the merge action list to the working directory
617 """apply the merge action list to the working directory
615
618
616 wctx is the working copy context
619 wctx is the working copy context
617 mctx is the context to be merged into the working copy
620 mctx is the context to be merged into the working copy
618
621
619 Return a tuple of counts (updated, merged, removed, unresolved) that
622 Return a tuple of counts (updated, merged, removed, unresolved) that
620 describes how many files were affected by the update.
623 describes how many files were affected by the update.
621 """
624 """
622
625
623 updated, merged, removed, unresolved = 0, 0, 0, 0
626 updated, merged, removed, unresolved = 0, 0, 0, 0
624 ms = mergestate(repo)
627 ms = mergestate(repo)
625 ms.reset(wctx.p1().node(), mctx.node())
628 ms.reset(wctx.p1().node(), mctx.node())
626 moves = []
629 moves = []
627 actions.sort(key=actionkey)
630 actions.sort(key=actionkey)
628
631
629 # prescan for merges
632 # prescan for merges
630 for a in actions:
633 for a in actions:
631 f, m, args, msg = a
634 f, m, args, msg = a
632 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
635 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
633 if m == "m": # merge
636 if m == "m": # merge
634 f1, f2, fa, move, anc = args
637 f1, f2, fa, move, anc = args
635 if f == '.hgsubstate': # merged internally
638 if f == '.hgsubstate': # merged internally
636 continue
639 continue
637 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
640 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
638 fcl = wctx[f1]
641 fcl = wctx[f1]
639 fco = mctx[f2]
642 fco = mctx[f2]
640 actx = repo[anc]
643 actx = repo[anc]
641 if fa in actx:
644 if fa in actx:
642 fca = actx[fa]
645 fca = actx[fa]
643 else:
646 else:
644 fca = repo.filectx(f1, fileid=nullrev)
647 fca = repo.filectx(f1, fileid=nullrev)
645 ms.add(fcl, fco, fca, f)
648 ms.add(fcl, fco, fca, f)
646 if f1 != f and move:
649 if f1 != f and move:
647 moves.append(f1)
650 moves.append(f1)
648
651
649 audit = repo.wopener.audit
652 audit = repo.wopener.audit
650
653
651 # remove renamed files after safely stored
654 # remove renamed files after safely stored
652 for f in moves:
655 for f in moves:
653 if os.path.lexists(repo.wjoin(f)):
656 if os.path.lexists(repo.wjoin(f)):
654 repo.ui.debug("removing %s\n" % f)
657 repo.ui.debug("removing %s\n" % f)
655 audit(f)
658 audit(f)
656 util.unlinkpath(repo.wjoin(f))
659 util.unlinkpath(repo.wjoin(f))
657
660
658 numupdates = len([a for a in actions if a[1] != 'k'])
661 numupdates = len([a for a in actions if a[1] != 'k'])
659 workeractions = [a for a in actions if a[1] in 'gr']
662 workeractions = [a for a in actions if a[1] in 'gr']
660 updateactions = [a for a in workeractions if a[1] == 'g']
663 updateactions = [a for a in workeractions if a[1] == 'g']
661 updated = len(updateactions)
664 updated = len(updateactions)
662 removeactions = [a for a in workeractions if a[1] == 'r']
665 removeactions = [a for a in workeractions if a[1] == 'r']
663 removed = len(removeactions)
666 removed = len(removeactions)
664 actions = [a for a in actions if a[1] not in 'grk']
667 actions = [a for a in actions if a[1] not in 'grk']
665
668
666 hgsub = [a[1] for a in workeractions if a[0] == '.hgsubstate']
669 hgsub = [a[1] for a in workeractions if a[0] == '.hgsubstate']
667 if hgsub and hgsub[0] == 'r':
670 if hgsub and hgsub[0] == 'r':
668 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
671 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
669
672
670 z = 0
673 z = 0
671 prog = worker.worker(repo.ui, 0.001, getremove, (repo, mctx, overwrite),
674 prog = worker.worker(repo.ui, 0.001, getremove, (repo, mctx, overwrite),
672 removeactions)
675 removeactions)
673 for i, item in prog:
676 for i, item in prog:
674 z += i
677 z += i
675 repo.ui.progress(_('updating'), z, item=item, total=numupdates,
678 repo.ui.progress(_('updating'), z, item=item, total=numupdates,
676 unit=_('files'))
679 unit=_('files'))
677 prog = worker.worker(repo.ui, 0.001, getremove, (repo, mctx, overwrite),
680 prog = worker.worker(repo.ui, 0.001, getremove, (repo, mctx, overwrite),
678 updateactions)
681 updateactions)
679 for i, item in prog:
682 for i, item in prog:
680 z += i
683 z += i
681 repo.ui.progress(_('updating'), z, item=item, total=numupdates,
684 repo.ui.progress(_('updating'), z, item=item, total=numupdates,
682 unit=_('files'))
685 unit=_('files'))
683
686
684 if hgsub and hgsub[0] == 'g':
687 if hgsub and hgsub[0] == 'g':
685 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
688 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
686
689
687 _updating = _('updating')
690 _updating = _('updating')
688 _files = _('files')
691 _files = _('files')
689 progress = repo.ui.progress
692 progress = repo.ui.progress
690
693
691 for i, a in enumerate(actions):
694 for i, a in enumerate(actions):
692 f, m, args, msg = a
695 f, m, args, msg = a
693 progress(_updating, z + i + 1, item=f, total=numupdates, unit=_files)
696 progress(_updating, z + i + 1, item=f, total=numupdates, unit=_files)
694 if m == "m": # merge
697 if m == "m": # merge
695 f1, f2, fa, move, anc = args
698 f1, f2, fa, move, anc = args
696 if f == '.hgsubstate': # subrepo states need updating
699 if f == '.hgsubstate': # subrepo states need updating
697 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
700 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
698 overwrite)
701 overwrite)
699 continue
702 continue
700 audit(f)
703 audit(f)
701 r = ms.resolve(f, wctx)
704 r = ms.resolve(f, wctx)
702 if r is not None and r > 0:
705 if r is not None and r > 0:
703 unresolved += 1
706 unresolved += 1
704 else:
707 else:
705 if r is None:
708 if r is None:
706 updated += 1
709 updated += 1
707 else:
710 else:
708 merged += 1
711 merged += 1
709 elif m == "dm": # directory rename, move local
712 elif m == "dm": # directory rename, move local
710 f0, flags = args
713 f0, flags = args
711 repo.ui.note(_("moving %s to %s\n") % (f0, f))
714 repo.ui.note(_("moving %s to %s\n") % (f0, f))
712 audit(f)
715 audit(f)
713 repo.wwrite(f, wctx.filectx(f0).data(), flags)
716 repo.wwrite(f, wctx.filectx(f0).data(), flags)
714 util.unlinkpath(repo.wjoin(f0))
717 util.unlinkpath(repo.wjoin(f0))
715 updated += 1
718 updated += 1
716 elif m == "dg": # local directory rename, get
719 elif m == "dg": # local directory rename, get
717 f0, flags = args
720 f0, flags = args
718 repo.ui.note(_("getting %s to %s\n") % (f0, f))
721 repo.ui.note(_("getting %s to %s\n") % (f0, f))
719 repo.wwrite(f, mctx.filectx(f0).data(), flags)
722 repo.wwrite(f, mctx.filectx(f0).data(), flags)
720 updated += 1
723 updated += 1
721 elif m == "dr": # divergent renames
724 elif m == "dr": # divergent renames
722 fl, = args
725 fl, = args
723 repo.ui.warn(_("note: possible conflict - %s was renamed "
726 repo.ui.warn(_("note: possible conflict - %s was renamed "
724 "multiple times to:\n") % f)
727 "multiple times to:\n") % f)
725 for nf in fl:
728 for nf in fl:
726 repo.ui.warn(" %s\n" % nf)
729 repo.ui.warn(" %s\n" % nf)
727 elif m == "rd": # rename and delete
730 elif m == "rd": # rename and delete
728 fl, = args
731 fl, = args
729 repo.ui.warn(_("note: possible conflict - %s was deleted "
732 repo.ui.warn(_("note: possible conflict - %s was deleted "
730 "and renamed to:\n") % f)
733 "and renamed to:\n") % f)
731 for nf in fl:
734 for nf in fl:
732 repo.ui.warn(" %s\n" % nf)
735 repo.ui.warn(" %s\n" % nf)
733 elif m == "e": # exec
736 elif m == "e": # exec
734 flags, = args
737 flags, = args
735 audit(f)
738 audit(f)
736 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
739 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
737 updated += 1
740 updated += 1
738 ms.commit()
741 ms.commit()
739 progress(_updating, None, total=numupdates, unit=_files)
742 progress(_updating, None, total=numupdates, unit=_files)
740
743
741 return updated, merged, removed, unresolved
744 return updated, merged, removed, unresolved
742
745
743 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial,
746 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial,
744 acceptremote, followcopies):
747 acceptremote, followcopies):
745 "Calculate the actions needed to merge mctx into wctx using ancestors"
748 "Calculate the actions needed to merge mctx into wctx using ancestors"
746
749
747 if len(ancestors) == 1: # default
750 if len(ancestors) == 1: # default
748 actions = manifestmerge(repo, wctx, mctx, ancestors[0],
751 actions = manifestmerge(repo, wctx, mctx, ancestors[0],
749 branchmerge, force,
752 branchmerge, force,
750 partial, acceptremote, followcopies)
753 partial, acceptremote, followcopies)
751
754
752 else: # only when merge.preferancestor=* - experimentalish code
755 else: # only when merge.preferancestor=* - experimentalish code
753 repo.ui.status(
756 repo.ui.status(
754 _("note: merging %s and %s using bids from ancestors %s\n") %
757 _("note: merging %s and %s using bids from ancestors %s\n") %
755 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors)))
758 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors)))
756
759
757 # Call for bids
760 # Call for bids
758 fbids = {} # mapping filename to list af action bids
761 fbids = {} # mapping filename to list af action bids
759 for ancestor in ancestors:
762 for ancestor in ancestors:
760 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
763 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
761 actions = manifestmerge(repo, wctx, mctx, ancestor,
764 actions = manifestmerge(repo, wctx, mctx, ancestor,
762 branchmerge, force,
765 branchmerge, force,
763 partial, acceptremote, followcopies)
766 partial, acceptremote, followcopies)
764 for a in sorted(actions):
767 for a in sorted(actions):
765 f, m, args, msg = a
768 f, m, args, msg = a
766 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
769 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
767 if f in fbids:
770 if f in fbids:
768 fbids[f].append(a)
771 fbids[f].append(a)
769 else:
772 else:
770 fbids[f] = [a]
773 fbids[f] = [a]
771
774
772 # Pick the best bid for each file
775 # Pick the best bid for each file
773 repo.ui.note(_('\nauction for merging merge bids\n'))
776 repo.ui.note(_('\nauction for merging merge bids\n'))
774 actions = []
777 actions = []
775 for f, bidsl in sorted(fbids.items()):
778 for f, bidsl in sorted(fbids.items()):
776 # Consensus?
779 # Consensus?
777 a0 = bidsl[0]
780 a0 = bidsl[0]
778 if util.all(a == a0 for a in bidsl[1:]): # len(bidsl) is > 1
781 if util.all(a == a0 for a in bidsl[1:]): # len(bidsl) is > 1
779 repo.ui.note(" %s: consensus for %s\n" % (f, a0[1]))
782 repo.ui.note(" %s: consensus for %s\n" % (f, a0[1]))
780 actions.append(a0)
783 actions.append(a0)
781 continue
784 continue
782 # Group bids by kind of action
785 # Group bids by kind of action
783 bids = {}
786 bids = {}
784 for a in bidsl:
787 for a in bidsl:
785 m = a[1]
788 m = a[1]
786 if m in bids:
789 if m in bids:
787 bids[m].append(a)
790 bids[m].append(a)
788 else:
791 else:
789 bids[m] = [a]
792 bids[m] = [a]
790 # If keep is an option, just do it.
793 # If keep is an option, just do it.
791 if "k" in bids:
794 if "k" in bids:
792 repo.ui.note(" %s: picking 'keep' action\n" % f)
795 repo.ui.note(" %s: picking 'keep' action\n" % f)
793 actions.append(bids["k"][0])
796 actions.append(bids["k"][0])
794 continue
797 continue
795 # If all gets agree [how could they not?], just do it.
798 # If all gets agree [how could they not?], just do it.
796 if "g" in bids:
799 if "g" in bids:
797 ga0 = bids["g"][0]
800 ga0 = bids["g"][0]
798 if util.all(a == ga0 for a in bids["g"][1:]):
801 if util.all(a == ga0 for a in bids["g"][1:]):
799 repo.ui.note(" %s: picking 'get' action\n" % f)
802 repo.ui.note(" %s: picking 'get' action\n" % f)
800 actions.append(ga0)
803 actions.append(ga0)
801 continue
804 continue
802 # TODO: Consider other simple actions such as mode changes
805 # TODO: Consider other simple actions such as mode changes
803 # Handle inefficient democrazy.
806 # Handle inefficient democrazy.
804 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
807 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
805 for _f, m, args, msg in bidsl:
808 for _f, m, args, msg in bidsl:
806 repo.ui.note(' %s -> %s\n' % (msg, m))
809 repo.ui.note(' %s -> %s\n' % (msg, m))
807 # Pick random action. TODO: Instead, prompt user when resolving
810 # Pick random action. TODO: Instead, prompt user when resolving
808 a0 = bidsl[0]
811 a0 = bidsl[0]
809 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
812 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
810 (f, a0[1]))
813 (f, a0[1]))
811 actions.append(a0)
814 actions.append(a0)
812 continue
815 continue
813 repo.ui.note(_('end of auction\n\n'))
816 repo.ui.note(_('end of auction\n\n'))
814
817
815 # Filter out prompts.
818 # Filter out prompts.
816 newactions, prompts = [], []
819 newactions, prompts = [], []
817 for a in actions:
820 for a in actions:
818 if a[1] in ("cd", "dc"):
821 if a[1] in ("cd", "dc"):
819 prompts.append(a)
822 prompts.append(a)
820 else:
823 else:
821 newactions.append(a)
824 newactions.append(a)
822 # Prompt and create actions. TODO: Move this towards resolve phase.
825 # Prompt and create actions. TODO: Move this towards resolve phase.
823 for f, m, args, msg in sorted(prompts):
826 for f, m, args, msg in sorted(prompts):
824 if m == "cd":
827 if m == "cd":
825 if repo.ui.promptchoice(
828 if repo.ui.promptchoice(
826 _("local changed %s which remote deleted\n"
829 _("local changed %s which remote deleted\n"
827 "use (c)hanged version or (d)elete?"
830 "use (c)hanged version or (d)elete?"
828 "$$ &Changed $$ &Delete") % f, 0):
831 "$$ &Changed $$ &Delete") % f, 0):
829 newactions.append((f, "r", None, "prompt delete"))
832 newactions.append((f, "r", None, "prompt delete"))
830 else:
833 else:
831 newactions.append((f, "a", None, "prompt keep"))
834 newactions.append((f, "a", None, "prompt keep"))
832 elif m == "dc":
835 elif m == "dc":
833 flags, = args
836 flags, = args
834 if repo.ui.promptchoice(
837 if repo.ui.promptchoice(
835 _("remote changed %s which local deleted\n"
838 _("remote changed %s which local deleted\n"
836 "use (c)hanged version or leave (d)eleted?"
839 "use (c)hanged version or leave (d)eleted?"
837 "$$ &Changed $$ &Deleted") % f, 0) == 0:
840 "$$ &Changed $$ &Deleted") % f, 0) == 0:
838 newactions.append((f, "g", (flags,), "prompt recreating"))
841 newactions.append((f, "g", (flags,), "prompt recreating"))
839 else: assert False, m
842 else: assert False, m
840
843
841 if wctx.rev() is None:
844 if wctx.rev() is None:
842 newactions += _forgetremoved(wctx, mctx, branchmerge)
845 newactions += _forgetremoved(wctx, mctx, branchmerge)
843
846
844 return newactions
847 return newactions
845
848
846 def recordupdates(repo, actions, branchmerge):
849 def recordupdates(repo, actions, branchmerge):
847 "record merge actions to the dirstate"
850 "record merge actions to the dirstate"
848
851
849 for a in actions:
852 for a in actions:
850 f, m, args, msg = a
853 f, m, args, msg = a
851 if m == "r": # remove
854 if m == "r": # remove (must come first)
852 if branchmerge:
855 if branchmerge:
853 repo.dirstate.remove(f)
856 repo.dirstate.remove(f)
854 else:
857 else:
855 repo.dirstate.drop(f)
858 repo.dirstate.drop(f)
859 elif m == "f": # forget (must come first)
860 repo.dirstate.drop(f)
856 elif m == "a": # re-add
861 elif m == "a": # re-add
857 if not branchmerge:
862 if not branchmerge:
858 repo.dirstate.add(f)
863 repo.dirstate.add(f)
859 elif m == "f": # forget
860 repo.dirstate.drop(f)
861 elif m == "e": # exec change
864 elif m == "e": # exec change
862 repo.dirstate.normallookup(f)
865 repo.dirstate.normallookup(f)
863 elif m == "k": # keep
866 elif m == "k": # keep
864 pass
867 pass
865 elif m == "g": # get
868 elif m == "g": # get
866 if branchmerge:
869 if branchmerge:
867 repo.dirstate.otherparent(f)
870 repo.dirstate.otherparent(f)
868 else:
871 else:
869 repo.dirstate.normal(f)
872 repo.dirstate.normal(f)
870 elif m == "m": # merge
873 elif m == "m": # merge
871 f1, f2, fa, move, anc = args
874 f1, f2, fa, move, anc = args
872 if branchmerge:
875 if branchmerge:
873 # We've done a branch merge, mark this file as merged
876 # We've done a branch merge, mark this file as merged
874 # so that we properly record the merger later
877 # so that we properly record the merger later
875 repo.dirstate.merge(f)
878 repo.dirstate.merge(f)
876 if f1 != f2: # copy/rename
879 if f1 != f2: # copy/rename
877 if move:
880 if move:
878 repo.dirstate.remove(f1)
881 repo.dirstate.remove(f1)
879 if f1 != f:
882 if f1 != f:
880 repo.dirstate.copy(f1, f)
883 repo.dirstate.copy(f1, f)
881 else:
884 else:
882 repo.dirstate.copy(f2, f)
885 repo.dirstate.copy(f2, f)
883 else:
886 else:
884 # We've update-merged a locally modified file, so
887 # We've update-merged a locally modified file, so
885 # we set the dirstate to emulate a normal checkout
888 # we set the dirstate to emulate a normal checkout
886 # of that file some time in the past. Thus our
889 # of that file some time in the past. Thus our
887 # merge will appear as a normal local file
890 # merge will appear as a normal local file
888 # modification.
891 # modification.
889 if f2 == f: # file not locally copied/moved
892 if f2 == f: # file not locally copied/moved
890 repo.dirstate.normallookup(f)
893 repo.dirstate.normallookup(f)
891 if move:
894 if move:
892 repo.dirstate.drop(f1)
895 repo.dirstate.drop(f1)
893 elif m == "dm": # directory rename, move local
896 elif m == "dm": # directory rename, move local
894 f0, flag = args
897 f0, flag = args
895 if f0 not in repo.dirstate:
898 if f0 not in repo.dirstate:
896 # untracked file moved
899 # untracked file moved
897 continue
900 continue
898 if branchmerge:
901 if branchmerge:
899 repo.dirstate.add(f)
902 repo.dirstate.add(f)
900 repo.dirstate.remove(f0)
903 repo.dirstate.remove(f0)
901 repo.dirstate.copy(f0, f)
904 repo.dirstate.copy(f0, f)
902 else:
905 else:
903 repo.dirstate.normal(f)
906 repo.dirstate.normal(f)
904 repo.dirstate.drop(f0)
907 repo.dirstate.drop(f0)
905 elif m == "dg": # directory rename, get
908 elif m == "dg": # directory rename, get
906 f0, flag = args
909 f0, flag = args
907 if branchmerge:
910 if branchmerge:
908 repo.dirstate.add(f)
911 repo.dirstate.add(f)
909 repo.dirstate.copy(f0, f)
912 repo.dirstate.copy(f0, f)
910 else:
913 else:
911 repo.dirstate.normal(f)
914 repo.dirstate.normal(f)
912
915
913 def update(repo, node, branchmerge, force, partial, ancestor=None,
916 def update(repo, node, branchmerge, force, partial, ancestor=None,
914 mergeancestor=False):
917 mergeancestor=False):
915 """
918 """
916 Perform a merge between the working directory and the given node
919 Perform a merge between the working directory and the given node
917
920
918 node = the node to update to, or None if unspecified
921 node = the node to update to, or None if unspecified
919 branchmerge = whether to merge between branches
922 branchmerge = whether to merge between branches
920 force = whether to force branch merging or file overwriting
923 force = whether to force branch merging or file overwriting
921 partial = a function to filter file lists (dirstate not updated)
924 partial = a function to filter file lists (dirstate not updated)
922 mergeancestor = whether it is merging with an ancestor. If true,
925 mergeancestor = whether it is merging with an ancestor. If true,
923 we should accept the incoming changes for any prompts that occur.
926 we should accept the incoming changes for any prompts that occur.
924 If false, merging with an ancestor (fast-forward) is only allowed
927 If false, merging with an ancestor (fast-forward) is only allowed
925 between different named branches. This flag is used by rebase extension
928 between different named branches. This flag is used by rebase extension
926 as a temporary fix and should be avoided in general.
929 as a temporary fix and should be avoided in general.
927
930
928 The table below shows all the behaviors of the update command
931 The table below shows all the behaviors of the update command
929 given the -c and -C or no options, whether the working directory
932 given the -c and -C or no options, whether the working directory
930 is dirty, whether a revision is specified, and the relationship of
933 is dirty, whether a revision is specified, and the relationship of
931 the parent rev to the target rev (linear, on the same named
934 the parent rev to the target rev (linear, on the same named
932 branch, or on another named branch).
935 branch, or on another named branch).
933
936
934 This logic is tested by test-update-branches.t.
937 This logic is tested by test-update-branches.t.
935
938
936 -c -C dirty rev | linear same cross
939 -c -C dirty rev | linear same cross
937 n n n n | ok (1) x
940 n n n n | ok (1) x
938 n n n y | ok ok ok
941 n n n y | ok ok ok
939 n n y n | merge (2) (2)
942 n n y n | merge (2) (2)
940 n n y y | merge (3) (3)
943 n n y y | merge (3) (3)
941 n y * * | --- discard ---
944 n y * * | --- discard ---
942 y n y * | --- (4) ---
945 y n y * | --- (4) ---
943 y n n * | --- ok ---
946 y n n * | --- ok ---
944 y y * * | --- (5) ---
947 y y * * | --- (5) ---
945
948
946 x = can't happen
949 x = can't happen
947 * = don't-care
950 * = don't-care
948 1 = abort: not a linear update (merge or update --check to force update)
951 1 = abort: not a linear update (merge or update --check to force update)
949 2 = abort: uncommitted changes (commit and merge, or update --clean to
952 2 = abort: uncommitted changes (commit and merge, or update --clean to
950 discard changes)
953 discard changes)
951 3 = abort: uncommitted changes (commit or update --clean to discard changes)
954 3 = abort: uncommitted changes (commit or update --clean to discard changes)
952 4 = abort: uncommitted changes (checked in commands.py)
955 4 = abort: uncommitted changes (checked in commands.py)
953 5 = incompatible options (checked in commands.py)
956 5 = incompatible options (checked in commands.py)
954
957
955 Return the same tuple as applyupdates().
958 Return the same tuple as applyupdates().
956 """
959 """
957
960
958 onode = node
961 onode = node
959 wlock = repo.wlock()
962 wlock = repo.wlock()
960 try:
963 try:
961 wc = repo[None]
964 wc = repo[None]
962 pl = wc.parents()
965 pl = wc.parents()
963 p1 = pl[0]
966 p1 = pl[0]
964 pas = [None]
967 pas = [None]
965 if ancestor:
968 if ancestor:
966 pas = [repo[ancestor]]
969 pas = [repo[ancestor]]
967
970
968 if node is None:
971 if node is None:
969 # Here is where we should consider bookmarks, divergent bookmarks,
972 # Here is where we should consider bookmarks, divergent bookmarks,
970 # foreground changesets (successors), and tip of current branch;
973 # foreground changesets (successors), and tip of current branch;
971 # but currently we are only checking the branch tips.
974 # but currently we are only checking the branch tips.
972 try:
975 try:
973 node = repo.branchtip(wc.branch())
976 node = repo.branchtip(wc.branch())
974 except error.RepoLookupError:
977 except error.RepoLookupError:
975 if wc.branch() == "default": # no default branch!
978 if wc.branch() == "default": # no default branch!
976 node = repo.lookup("tip") # update to tip
979 node = repo.lookup("tip") # update to tip
977 else:
980 else:
978 raise util.Abort(_("branch %s not found") % wc.branch())
981 raise util.Abort(_("branch %s not found") % wc.branch())
979
982
980 if p1.obsolete() and not p1.children():
983 if p1.obsolete() and not p1.children():
981 # allow updating to successors
984 # allow updating to successors
982 successors = obsolete.successorssets(repo, p1.node())
985 successors = obsolete.successorssets(repo, p1.node())
983
986
984 # behavior of certain cases is as follows,
987 # behavior of certain cases is as follows,
985 #
988 #
986 # divergent changesets: update to highest rev, similar to what
989 # divergent changesets: update to highest rev, similar to what
987 # is currently done when there are more than one head
990 # is currently done when there are more than one head
988 # (i.e. 'tip')
991 # (i.e. 'tip')
989 #
992 #
990 # replaced changesets: same as divergent except we know there
993 # replaced changesets: same as divergent except we know there
991 # is no conflict
994 # is no conflict
992 #
995 #
993 # pruned changeset: no update is done; though, we could
996 # pruned changeset: no update is done; though, we could
994 # consider updating to the first non-obsolete parent,
997 # consider updating to the first non-obsolete parent,
995 # similar to what is current done for 'hg prune'
998 # similar to what is current done for 'hg prune'
996
999
997 if successors:
1000 if successors:
998 # flatten the list here handles both divergent (len > 1)
1001 # flatten the list here handles both divergent (len > 1)
999 # and the usual case (len = 1)
1002 # and the usual case (len = 1)
1000 successors = [n for sub in successors for n in sub]
1003 successors = [n for sub in successors for n in sub]
1001
1004
1002 # get the max revision for the given successors set,
1005 # get the max revision for the given successors set,
1003 # i.e. the 'tip' of a set
1006 # i.e. the 'tip' of a set
1004 node = repo.revs("max(%ln)", successors)[0]
1007 node = repo.revs("max(%ln)", successors)[0]
1005 pas = [p1]
1008 pas = [p1]
1006
1009
1007 overwrite = force and not branchmerge
1010 overwrite = force and not branchmerge
1008
1011
1009 p2 = repo[node]
1012 p2 = repo[node]
1010 if pas[0] is None:
1013 if pas[0] is None:
1011 if repo.ui.config("merge", "preferancestor") == '*':
1014 if repo.ui.config("merge", "preferancestor") == '*':
1012 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
1015 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
1013 pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
1016 pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
1014 else:
1017 else:
1015 pas = [p1.ancestor(p2, warn=True)]
1018 pas = [p1.ancestor(p2, warn=True)]
1016
1019
1017 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
1020 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
1018
1021
1019 ### check phase
1022 ### check phase
1020 if not overwrite and len(pl) > 1:
1023 if not overwrite and len(pl) > 1:
1021 raise util.Abort(_("outstanding uncommitted merges"))
1024 raise util.Abort(_("outstanding uncommitted merges"))
1022 if branchmerge:
1025 if branchmerge:
1023 if pas == [p2]:
1026 if pas == [p2]:
1024 raise util.Abort(_("merging with a working directory ancestor"
1027 raise util.Abort(_("merging with a working directory ancestor"
1025 " has no effect"))
1028 " has no effect"))
1026 elif pas == [p1]:
1029 elif pas == [p1]:
1027 if not mergeancestor and p1.branch() == p2.branch():
1030 if not mergeancestor and p1.branch() == p2.branch():
1028 raise util.Abort(_("nothing to merge"),
1031 raise util.Abort(_("nothing to merge"),
1029 hint=_("use 'hg update' "
1032 hint=_("use 'hg update' "
1030 "or check 'hg heads'"))
1033 "or check 'hg heads'"))
1031 if not force and (wc.files() or wc.deleted()):
1034 if not force and (wc.files() or wc.deleted()):
1032 raise util.Abort(_("uncommitted changes"),
1035 raise util.Abort(_("uncommitted changes"),
1033 hint=_("use 'hg status' to list changes"))
1036 hint=_("use 'hg status' to list changes"))
1034 for s in sorted(wc.substate):
1037 for s in sorted(wc.substate):
1035 if wc.sub(s).dirty():
1038 if wc.sub(s).dirty():
1036 raise util.Abort(_("uncommitted changes in "
1039 raise util.Abort(_("uncommitted changes in "
1037 "subrepository '%s'") % s)
1040 "subrepository '%s'") % s)
1038
1041
1039 elif not overwrite:
1042 elif not overwrite:
1040 if p1 == p2: # no-op update
1043 if p1 == p2: # no-op update
1041 # call the hooks and exit early
1044 # call the hooks and exit early
1042 repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
1045 repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
1043 repo.hook('update', parent1=xp2, parent2='', error=0)
1046 repo.hook('update', parent1=xp2, parent2='', error=0)
1044 return 0, 0, 0, 0
1047 return 0, 0, 0, 0
1045
1048
1046 if pas not in ([p1], [p2]): # nonlinear
1049 if pas not in ([p1], [p2]): # nonlinear
1047 dirty = wc.dirty(missing=True)
1050 dirty = wc.dirty(missing=True)
1048 if dirty or onode is None:
1051 if dirty or onode is None:
1049 # Branching is a bit strange to ensure we do the minimal
1052 # Branching is a bit strange to ensure we do the minimal
1050 # amount of call to obsolete.background.
1053 # amount of call to obsolete.background.
1051 foreground = obsolete.foreground(repo, [p1.node()])
1054 foreground = obsolete.foreground(repo, [p1.node()])
1052 # note: the <node> variable contains a random identifier
1055 # note: the <node> variable contains a random identifier
1053 if repo[node].node() in foreground:
1056 if repo[node].node() in foreground:
1054 pas = [p1] # allow updating to successors
1057 pas = [p1] # allow updating to successors
1055 elif dirty:
1058 elif dirty:
1056 msg = _("uncommitted changes")
1059 msg = _("uncommitted changes")
1057 if onode is None:
1060 if onode is None:
1058 hint = _("commit and merge, or update --clean to"
1061 hint = _("commit and merge, or update --clean to"
1059 " discard changes")
1062 " discard changes")
1060 else:
1063 else:
1061 hint = _("commit or update --clean to discard"
1064 hint = _("commit or update --clean to discard"
1062 " changes")
1065 " changes")
1063 raise util.Abort(msg, hint=hint)
1066 raise util.Abort(msg, hint=hint)
1064 else: # node is none
1067 else: # node is none
1065 msg = _("not a linear update")
1068 msg = _("not a linear update")
1066 hint = _("merge or update --check to force update")
1069 hint = _("merge or update --check to force update")
1067 raise util.Abort(msg, hint=hint)
1070 raise util.Abort(msg, hint=hint)
1068 else:
1071 else:
1069 # Allow jumping branches if clean and specific rev given
1072 # Allow jumping branches if clean and specific rev given
1070 pas = [p1]
1073 pas = [p1]
1071
1074
1072 followcopies = False
1075 followcopies = False
1073 if overwrite:
1076 if overwrite:
1074 pas = [wc]
1077 pas = [wc]
1075 elif pas == [p2]: # backwards
1078 elif pas == [p2]: # backwards
1076 pas = [wc.p1()]
1079 pas = [wc.p1()]
1077 elif not branchmerge and not wc.dirty(missing=True):
1080 elif not branchmerge and not wc.dirty(missing=True):
1078 pass
1081 pass
1079 elif pas[0] and repo.ui.configbool("merge", "followcopies", True):
1082 elif pas[0] and repo.ui.configbool("merge", "followcopies", True):
1080 followcopies = True
1083 followcopies = True
1081
1084
1082 ### calculate phase
1085 ### calculate phase
1083 actions = calculateupdates(repo, wc, p2, pas, branchmerge, force,
1086 actions = calculateupdates(repo, wc, p2, pas, branchmerge, force,
1084 partial, mergeancestor, followcopies)
1087 partial, mergeancestor, followcopies)
1085
1088
1086 ### apply phase
1089 ### apply phase
1087 if not branchmerge: # just jump to the new rev
1090 if not branchmerge: # just jump to the new rev
1088 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
1091 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
1089 if not partial:
1092 if not partial:
1090 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
1093 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
1091 # note that we're in the middle of an update
1094 # note that we're in the middle of an update
1092 repo.vfs.write('updatestate', p2.hex())
1095 repo.vfs.write('updatestate', p2.hex())
1093
1096
1094 stats = applyupdates(repo, actions, wc, p2, overwrite)
1097 stats = applyupdates(repo, actions, wc, p2, overwrite)
1095
1098
1096 if not partial:
1099 if not partial:
1097 repo.setparents(fp1, fp2)
1100 repo.setparents(fp1, fp2)
1098 recordupdates(repo, actions, branchmerge)
1101 recordupdates(repo, actions, branchmerge)
1099 # update completed, clear state
1102 # update completed, clear state
1100 util.unlink(repo.join('updatestate'))
1103 util.unlink(repo.join('updatestate'))
1101
1104
1102 if not branchmerge:
1105 if not branchmerge:
1103 repo.dirstate.setbranch(p2.branch())
1106 repo.dirstate.setbranch(p2.branch())
1104 finally:
1107 finally:
1105 wlock.release()
1108 wlock.release()
1106
1109
1107 if not partial:
1110 if not partial:
1108 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1111 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1109 return stats
1112 return stats
@@ -1,587 +1,587 b''
1 Create a repo with some stuff in it:
1 Create a repo with some stuff in it:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ echo a > d
6 $ echo a > d
7 $ echo a > e
7 $ echo a > e
8 $ hg ci -qAm0
8 $ hg ci -qAm0
9 $ echo b > a
9 $ echo b > a
10 $ hg ci -m1 -u bar
10 $ hg ci -m1 -u bar
11 $ hg mv a b
11 $ hg mv a b
12 $ hg ci -m2
12 $ hg ci -m2
13 $ hg cp b c
13 $ hg cp b c
14 $ hg ci -m3 -u baz
14 $ hg ci -m3 -u baz
15 $ echo b > d
15 $ echo b > d
16 $ echo f > e
16 $ echo f > e
17 $ hg ci -m4
17 $ hg ci -m4
18 $ hg up -q 3
18 $ hg up -q 3
19 $ echo b > e
19 $ echo b > e
20 $ hg branch -q stable
20 $ hg branch -q stable
21 $ hg ci -m5
21 $ hg ci -m5
22 $ hg merge -q default --tool internal:local
22 $ hg merge -q default --tool internal:local
23 $ hg branch -q default
23 $ hg branch -q default
24 $ hg ci -m6
24 $ hg ci -m6
25 $ hg phase --public 3
25 $ hg phase --public 3
26 $ hg phase --force --secret 6
26 $ hg phase --force --secret 6
27
27
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
29 @ test@6.secret: 6
29 @ test@6.secret: 6
30 |\
30 |\
31 | o test@5.draft: 5
31 | o test@5.draft: 5
32 | |
32 | |
33 o | test@4.draft: 4
33 o | test@4.draft: 4
34 |/
34 |/
35 o baz@3.public: 3
35 o baz@3.public: 3
36 |
36 |
37 o test@2.public: 2
37 o test@2.public: 2
38 |
38 |
39 o bar@1.public: 1
39 o bar@1.public: 1
40 |
40 |
41 o test@0.public: 0
41 o test@0.public: 0
42
42
43
43
44 Need to specify a rev:
44 Need to specify a rev:
45
45
46 $ hg graft
46 $ hg graft
47 abort: no revisions specified
47 abort: no revisions specified
48 [255]
48 [255]
49
49
50 Can't graft ancestor:
50 Can't graft ancestor:
51
51
52 $ hg graft 1 2
52 $ hg graft 1 2
53 skipping ancestor revision 1
53 skipping ancestor revision 1
54 skipping ancestor revision 2
54 skipping ancestor revision 2
55 [255]
55 [255]
56
56
57 Specify revisions with -r:
57 Specify revisions with -r:
58
58
59 $ hg graft -r 1 -r 2
59 $ hg graft -r 1 -r 2
60 skipping ancestor revision 1
60 skipping ancestor revision 1
61 skipping ancestor revision 2
61 skipping ancestor revision 2
62 [255]
62 [255]
63
63
64 $ hg graft -r 1 2
64 $ hg graft -r 1 2
65 skipping ancestor revision 2
65 skipping ancestor revision 2
66 skipping ancestor revision 1
66 skipping ancestor revision 1
67 [255]
67 [255]
68
68
69 Can't graft with dirty wd:
69 Can't graft with dirty wd:
70
70
71 $ hg up -q 0
71 $ hg up -q 0
72 $ echo foo > a
72 $ echo foo > a
73 $ hg graft 1
73 $ hg graft 1
74 abort: uncommitted changes
74 abort: uncommitted changes
75 [255]
75 [255]
76 $ hg revert a
76 $ hg revert a
77
77
78 Graft a rename:
78 Graft a rename:
79
79
80 $ hg graft 2 -u foo
80 $ hg graft 2 -u foo
81 grafting revision 2
81 grafting revision 2
82 merging a and b to b
82 merging a and b to b
83 $ hg export tip --git
83 $ hg export tip --git
84 # HG changeset patch
84 # HG changeset patch
85 # User foo
85 # User foo
86 # Date 0 0
86 # Date 0 0
87 # Thu Jan 01 00:00:00 1970 +0000
87 # Thu Jan 01 00:00:00 1970 +0000
88 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
88 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
89 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
89 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
90 2
90 2
91
91
92 diff --git a/a b/b
92 diff --git a/a b/b
93 rename from a
93 rename from a
94 rename to b
94 rename to b
95
95
96 Look for extra:source
96 Look for extra:source
97
97
98 $ hg log --debug -r tip
98 $ hg log --debug -r tip
99 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
99 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
100 tag: tip
100 tag: tip
101 phase: draft
101 phase: draft
102 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
102 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
103 parent: -1:0000000000000000000000000000000000000000
103 parent: -1:0000000000000000000000000000000000000000
104 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
104 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
105 user: foo
105 user: foo
106 date: Thu Jan 01 00:00:00 1970 +0000
106 date: Thu Jan 01 00:00:00 1970 +0000
107 files+: b
107 files+: b
108 files-: a
108 files-: a
109 extra: branch=default
109 extra: branch=default
110 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
110 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
111 description:
111 description:
112 2
112 2
113
113
114
114
115
115
116 Graft out of order, skipping a merge and a duplicate
116 Graft out of order, skipping a merge and a duplicate
117
117
118 $ hg graft 1 5 4 3 'merge()' 2 -n
118 $ hg graft 1 5 4 3 'merge()' 2 -n
119 skipping ungraftable merge revision 6
119 skipping ungraftable merge revision 6
120 skipping revision 2 (already grafted to 7)
120 skipping revision 2 (already grafted to 7)
121 grafting revision 1
121 grafting revision 1
122 grafting revision 5
122 grafting revision 5
123 grafting revision 4
123 grafting revision 4
124 grafting revision 3
124 grafting revision 3
125
125
126 $ hg graft 1 5 4 3 'merge()' 2 --debug
126 $ hg graft 1 5 4 3 'merge()' 2 --debug
127 skipping ungraftable merge revision 6
127 skipping ungraftable merge revision 6
128 scanning for duplicate grafts
128 scanning for duplicate grafts
129 skipping revision 2 (already grafted to 7)
129 skipping revision 2 (already grafted to 7)
130 grafting revision 1
130 grafting revision 1
131 searching for copies back to rev 1
131 searching for copies back to rev 1
132 unmatched files in local:
132 unmatched files in local:
133 b
133 b
134 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
134 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
135 src: 'a' -> dst: 'b' *
135 src: 'a' -> dst: 'b' *
136 checking for directory renames
136 checking for directory renames
137 resolving manifests
137 resolving manifests
138 branchmerge: True, force: True, partial: False
138 branchmerge: True, force: True, partial: False
139 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
139 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
140 b: local copied/moved from a -> m
140 b: local copied/moved from a -> m
141 preserving b for resolve of b
141 preserving b for resolve of b
142 updating: b 1/1 files (100.00%)
142 updating: b 1/1 files (100.00%)
143 picked tool 'internal:merge' for b (binary False symlink False)
143 picked tool 'internal:merge' for b (binary False symlink False)
144 merging b and a to b
144 merging b and a to b
145 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
145 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
146 premerge successful
146 premerge successful
147 b
147 b
148 grafting revision 5
148 grafting revision 5
149 searching for copies back to rev 1
149 searching for copies back to rev 1
150 resolving manifests
150 resolving manifests
151 branchmerge: True, force: True, partial: False
151 branchmerge: True, force: True, partial: False
152 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
152 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
153 e: remote is newer -> g
153 b: keep -> k
154 b: keep -> k
154 e: remote is newer -> g
155 getting e
155 getting e
156 updating: e 1/1 files (100.00%)
156 updating: e 1/1 files (100.00%)
157 e
157 e
158 grafting revision 4
158 grafting revision 4
159 searching for copies back to rev 1
159 searching for copies back to rev 1
160 resolving manifests
160 resolving manifests
161 branchmerge: True, force: True, partial: False
161 branchmerge: True, force: True, partial: False
162 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
162 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
163 d: remote is newer -> g
163 b: keep -> k
164 b: keep -> k
164 d: remote is newer -> g
165 e: versions differ -> m
165 e: versions differ -> m
166 preserving e for resolve of e
166 preserving e for resolve of e
167 getting d
167 getting d
168 updating: d 1/2 files (50.00%)
168 updating: d 1/2 files (50.00%)
169 updating: e 2/2 files (100.00%)
169 updating: e 2/2 files (100.00%)
170 picked tool 'internal:merge' for e (binary False symlink False)
170 picked tool 'internal:merge' for e (binary False symlink False)
171 merging e
171 merging e
172 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
172 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
173 warning: conflicts during merge.
173 warning: conflicts during merge.
174 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
174 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
175 abort: unresolved conflicts, can't continue
175 abort: unresolved conflicts, can't continue
176 (use hg resolve and hg graft --continue)
176 (use hg resolve and hg graft --continue)
177 [255]
177 [255]
178
178
179 Commit while interrupted should fail:
179 Commit while interrupted should fail:
180
180
181 $ hg ci -m 'commit interrupted graft'
181 $ hg ci -m 'commit interrupted graft'
182 abort: graft in progress
182 abort: graft in progress
183 (use 'hg graft --continue' or 'hg update' to abort)
183 (use 'hg graft --continue' or 'hg update' to abort)
184 [255]
184 [255]
185
185
186 Abort the graft and try committing:
186 Abort the graft and try committing:
187
187
188 $ hg up -C .
188 $ hg up -C .
189 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 $ echo c >> e
190 $ echo c >> e
191 $ hg ci -mtest
191 $ hg ci -mtest
192
192
193 $ hg strip . --config extensions.mq=
193 $ hg strip . --config extensions.mq=
194 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
194 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
195 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
195 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
196
196
197 Graft again:
197 Graft again:
198
198
199 $ hg graft 1 5 4 3 'merge()' 2
199 $ hg graft 1 5 4 3 'merge()' 2
200 skipping ungraftable merge revision 6
200 skipping ungraftable merge revision 6
201 skipping revision 2 (already grafted to 7)
201 skipping revision 2 (already grafted to 7)
202 skipping revision 1 (already grafted to 8)
202 skipping revision 1 (already grafted to 8)
203 skipping revision 5 (already grafted to 9)
203 skipping revision 5 (already grafted to 9)
204 grafting revision 4
204 grafting revision 4
205 merging e
205 merging e
206 warning: conflicts during merge.
206 warning: conflicts during merge.
207 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
207 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
208 abort: unresolved conflicts, can't continue
208 abort: unresolved conflicts, can't continue
209 (use hg resolve and hg graft --continue)
209 (use hg resolve and hg graft --continue)
210 [255]
210 [255]
211
211
212 Continue without resolve should fail:
212 Continue without resolve should fail:
213
213
214 $ hg graft -c
214 $ hg graft -c
215 grafting revision 4
215 grafting revision 4
216 abort: unresolved merge conflicts (see hg help resolve)
216 abort: unresolved merge conflicts (see hg help resolve)
217 [255]
217 [255]
218
218
219 Fix up:
219 Fix up:
220
220
221 $ echo b > e
221 $ echo b > e
222 $ hg resolve -m e
222 $ hg resolve -m e
223 no more unresolved files
223 no more unresolved files
224
224
225 Continue with a revision should fail:
225 Continue with a revision should fail:
226
226
227 $ hg graft -c 6
227 $ hg graft -c 6
228 abort: can't specify --continue and revisions
228 abort: can't specify --continue and revisions
229 [255]
229 [255]
230
230
231 $ hg graft -c -r 6
231 $ hg graft -c -r 6
232 abort: can't specify --continue and revisions
232 abort: can't specify --continue and revisions
233 [255]
233 [255]
234
234
235 Continue for real, clobber usernames
235 Continue for real, clobber usernames
236
236
237 $ hg graft -c -U
237 $ hg graft -c -U
238 grafting revision 4
238 grafting revision 4
239 grafting revision 3
239 grafting revision 3
240
240
241 Compare with original:
241 Compare with original:
242
242
243 $ hg diff -r 6
243 $ hg diff -r 6
244 $ hg status --rev 0:. -C
244 $ hg status --rev 0:. -C
245 M d
245 M d
246 M e
246 M e
247 A b
247 A b
248 a
248 a
249 A c
249 A c
250 a
250 a
251 R a
251 R a
252
252
253 View graph:
253 View graph:
254
254
255 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
255 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
256 @ test@11.draft: 3
256 @ test@11.draft: 3
257 |
257 |
258 o test@10.draft: 4
258 o test@10.draft: 4
259 |
259 |
260 o test@9.draft: 5
260 o test@9.draft: 5
261 |
261 |
262 o bar@8.draft: 1
262 o bar@8.draft: 1
263 |
263 |
264 o foo@7.draft: 2
264 o foo@7.draft: 2
265 |
265 |
266 | o test@6.secret: 6
266 | o test@6.secret: 6
267 | |\
267 | |\
268 | | o test@5.draft: 5
268 | | o test@5.draft: 5
269 | | |
269 | | |
270 | o | test@4.draft: 4
270 | o | test@4.draft: 4
271 | |/
271 | |/
272 | o baz@3.public: 3
272 | o baz@3.public: 3
273 | |
273 | |
274 | o test@2.public: 2
274 | o test@2.public: 2
275 | |
275 | |
276 | o bar@1.public: 1
276 | o bar@1.public: 1
277 |/
277 |/
278 o test@0.public: 0
278 o test@0.public: 0
279
279
280 Graft again onto another branch should preserve the original source
280 Graft again onto another branch should preserve the original source
281 $ hg up -q 0
281 $ hg up -q 0
282 $ echo 'g'>g
282 $ echo 'g'>g
283 $ hg add g
283 $ hg add g
284 $ hg ci -m 7
284 $ hg ci -m 7
285 created new head
285 created new head
286 $ hg graft 7
286 $ hg graft 7
287 grafting revision 7
287 grafting revision 7
288
288
289 $ hg log -r 7 --template '{rev}:{node}\n'
289 $ hg log -r 7 --template '{rev}:{node}\n'
290 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
290 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
291 $ hg log -r 2 --template '{rev}:{node}\n'
291 $ hg log -r 2 --template '{rev}:{node}\n'
292 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
292 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
293
293
294 $ hg log --debug -r tip
294 $ hg log --debug -r tip
295 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
295 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
296 tag: tip
296 tag: tip
297 phase: draft
297 phase: draft
298 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
298 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
299 parent: -1:0000000000000000000000000000000000000000
299 parent: -1:0000000000000000000000000000000000000000
300 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
300 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
301 user: foo
301 user: foo
302 date: Thu Jan 01 00:00:00 1970 +0000
302 date: Thu Jan 01 00:00:00 1970 +0000
303 files+: b
303 files+: b
304 files-: a
304 files-: a
305 extra: branch=default
305 extra: branch=default
306 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
306 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
307 description:
307 description:
308 2
308 2
309
309
310
310
311 Disallow grafting an already grafted cset onto its original branch
311 Disallow grafting an already grafted cset onto its original branch
312 $ hg up -q 6
312 $ hg up -q 6
313 $ hg graft 7
313 $ hg graft 7
314 skipping already grafted revision 7 (was grafted from 2)
314 skipping already grafted revision 7 (was grafted from 2)
315 [255]
315 [255]
316
316
317 Disallow grafting already grafted csets with the same origin onto each other
317 Disallow grafting already grafted csets with the same origin onto each other
318 $ hg up -q 13
318 $ hg up -q 13
319 $ hg graft 2
319 $ hg graft 2
320 skipping revision 2 (already grafted to 13)
320 skipping revision 2 (already grafted to 13)
321 [255]
321 [255]
322 $ hg graft 7
322 $ hg graft 7
323 skipping already grafted revision 7 (13 also has origin 2)
323 skipping already grafted revision 7 (13 also has origin 2)
324 [255]
324 [255]
325
325
326 $ hg up -q 7
326 $ hg up -q 7
327 $ hg graft 2
327 $ hg graft 2
328 skipping revision 2 (already grafted to 7)
328 skipping revision 2 (already grafted to 7)
329 [255]
329 [255]
330 $ hg graft tip
330 $ hg graft tip
331 skipping already grafted revision 13 (7 also has origin 2)
331 skipping already grafted revision 13 (7 also has origin 2)
332 [255]
332 [255]
333
333
334 Graft with --log
334 Graft with --log
335
335
336 $ hg up -Cq 1
336 $ hg up -Cq 1
337 $ hg graft 3 --log -u foo
337 $ hg graft 3 --log -u foo
338 grafting revision 3
338 grafting revision 3
339 warning: can't find ancestor for 'c' copied from 'b'!
339 warning: can't find ancestor for 'c' copied from 'b'!
340 $ hg log --template '{rev} {parents} {desc}\n' -r tip
340 $ hg log --template '{rev} {parents} {desc}\n' -r tip
341 14 1:5d205f8b35b6 3
341 14 1:5d205f8b35b6 3
342 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
342 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
343
343
344 Resolve conflicted graft
344 Resolve conflicted graft
345 $ hg up -q 0
345 $ hg up -q 0
346 $ echo b > a
346 $ echo b > a
347 $ hg ci -m 8
347 $ hg ci -m 8
348 created new head
348 created new head
349 $ echo a > a
349 $ echo a > a
350 $ hg ci -m 9
350 $ hg ci -m 9
351 $ hg graft 1 --tool internal:fail
351 $ hg graft 1 --tool internal:fail
352 grafting revision 1
352 grafting revision 1
353 abort: unresolved conflicts, can't continue
353 abort: unresolved conflicts, can't continue
354 (use hg resolve and hg graft --continue)
354 (use hg resolve and hg graft --continue)
355 [255]
355 [255]
356 $ hg resolve --all
356 $ hg resolve --all
357 merging a
357 merging a
358 no more unresolved files
358 no more unresolved files
359 $ hg graft -c
359 $ hg graft -c
360 grafting revision 1
360 grafting revision 1
361 $ hg export tip --git
361 $ hg export tip --git
362 # HG changeset patch
362 # HG changeset patch
363 # User bar
363 # User bar
364 # Date 0 0
364 # Date 0 0
365 # Thu Jan 01 00:00:00 1970 +0000
365 # Thu Jan 01 00:00:00 1970 +0000
366 # Node ID 64ecd9071ce83c6e62f538d8ce7709d53f32ebf7
366 # Node ID 64ecd9071ce83c6e62f538d8ce7709d53f32ebf7
367 # Parent 4bdb9a9d0b84ffee1d30f0dfc7744cade17aa19c
367 # Parent 4bdb9a9d0b84ffee1d30f0dfc7744cade17aa19c
368 1
368 1
369
369
370 diff --git a/a b/a
370 diff --git a/a b/a
371 --- a/a
371 --- a/a
372 +++ b/a
372 +++ b/a
373 @@ -1,1 +1,1 @@
373 @@ -1,1 +1,1 @@
374 -a
374 -a
375 +b
375 +b
376
376
377 Resolve conflicted graft with rename
377 Resolve conflicted graft with rename
378 $ echo c > a
378 $ echo c > a
379 $ hg ci -m 10
379 $ hg ci -m 10
380 $ hg graft 2 --tool internal:fail
380 $ hg graft 2 --tool internal:fail
381 grafting revision 2
381 grafting revision 2
382 abort: unresolved conflicts, can't continue
382 abort: unresolved conflicts, can't continue
383 (use hg resolve and hg graft --continue)
383 (use hg resolve and hg graft --continue)
384 [255]
384 [255]
385 $ hg resolve --all
385 $ hg resolve --all
386 merging a and b to b
386 merging a and b to b
387 no more unresolved files
387 no more unresolved files
388 $ hg graft -c
388 $ hg graft -c
389 grafting revision 2
389 grafting revision 2
390 $ hg export tip --git
390 $ hg export tip --git
391 # HG changeset patch
391 # HG changeset patch
392 # User test
392 # User test
393 # Date 0 0
393 # Date 0 0
394 # Thu Jan 01 00:00:00 1970 +0000
394 # Thu Jan 01 00:00:00 1970 +0000
395 # Node ID 2e80e1351d6ed50302fe1e05f8bd1d4d412b6e11
395 # Node ID 2e80e1351d6ed50302fe1e05f8bd1d4d412b6e11
396 # Parent e5a51ae854a8bbaaf25cc5c6a57ff46042dadbb4
396 # Parent e5a51ae854a8bbaaf25cc5c6a57ff46042dadbb4
397 2
397 2
398
398
399 diff --git a/a b/b
399 diff --git a/a b/b
400 rename from a
400 rename from a
401 rename to b
401 rename to b
402
402
403 Test simple origin(), with and without args
403 Test simple origin(), with and without args
404 $ hg log -r 'origin()'
404 $ hg log -r 'origin()'
405 changeset: 1:5d205f8b35b6
405 changeset: 1:5d205f8b35b6
406 user: bar
406 user: bar
407 date: Thu Jan 01 00:00:00 1970 +0000
407 date: Thu Jan 01 00:00:00 1970 +0000
408 summary: 1
408 summary: 1
409
409
410 changeset: 2:5c095ad7e90f
410 changeset: 2:5c095ad7e90f
411 user: test
411 user: test
412 date: Thu Jan 01 00:00:00 1970 +0000
412 date: Thu Jan 01 00:00:00 1970 +0000
413 summary: 2
413 summary: 2
414
414
415 changeset: 3:4c60f11aa304
415 changeset: 3:4c60f11aa304
416 user: baz
416 user: baz
417 date: Thu Jan 01 00:00:00 1970 +0000
417 date: Thu Jan 01 00:00:00 1970 +0000
418 summary: 3
418 summary: 3
419
419
420 changeset: 4:9c233e8e184d
420 changeset: 4:9c233e8e184d
421 user: test
421 user: test
422 date: Thu Jan 01 00:00:00 1970 +0000
422 date: Thu Jan 01 00:00:00 1970 +0000
423 summary: 4
423 summary: 4
424
424
425 changeset: 5:97f8bfe72746
425 changeset: 5:97f8bfe72746
426 branch: stable
426 branch: stable
427 parent: 3:4c60f11aa304
427 parent: 3:4c60f11aa304
428 user: test
428 user: test
429 date: Thu Jan 01 00:00:00 1970 +0000
429 date: Thu Jan 01 00:00:00 1970 +0000
430 summary: 5
430 summary: 5
431
431
432 $ hg log -r 'origin(7)'
432 $ hg log -r 'origin(7)'
433 changeset: 2:5c095ad7e90f
433 changeset: 2:5c095ad7e90f
434 user: test
434 user: test
435 date: Thu Jan 01 00:00:00 1970 +0000
435 date: Thu Jan 01 00:00:00 1970 +0000
436 summary: 2
436 summary: 2
437
437
438 Now transplant a graft to test following through copies
438 Now transplant a graft to test following through copies
439 $ hg up -q 0
439 $ hg up -q 0
440 $ hg branch -q dev
440 $ hg branch -q dev
441 $ hg ci -qm "dev branch"
441 $ hg ci -qm "dev branch"
442 $ hg --config extensions.transplant= transplant -q 7
442 $ hg --config extensions.transplant= transplant -q 7
443 $ hg log -r 'origin(.)'
443 $ hg log -r 'origin(.)'
444 changeset: 2:5c095ad7e90f
444 changeset: 2:5c095ad7e90f
445 user: test
445 user: test
446 date: Thu Jan 01 00:00:00 1970 +0000
446 date: Thu Jan 01 00:00:00 1970 +0000
447 summary: 2
447 summary: 2
448
448
449 Test simple destination
449 Test simple destination
450 $ hg log -r 'destination()'
450 $ hg log -r 'destination()'
451 changeset: 7:ef0ef43d49e7
451 changeset: 7:ef0ef43d49e7
452 parent: 0:68795b066622
452 parent: 0:68795b066622
453 user: foo
453 user: foo
454 date: Thu Jan 01 00:00:00 1970 +0000
454 date: Thu Jan 01 00:00:00 1970 +0000
455 summary: 2
455 summary: 2
456
456
457 changeset: 8:6b9e5368ca4e
457 changeset: 8:6b9e5368ca4e
458 user: bar
458 user: bar
459 date: Thu Jan 01 00:00:00 1970 +0000
459 date: Thu Jan 01 00:00:00 1970 +0000
460 summary: 1
460 summary: 1
461
461
462 changeset: 9:1905859650ec
462 changeset: 9:1905859650ec
463 user: test
463 user: test
464 date: Thu Jan 01 00:00:00 1970 +0000
464 date: Thu Jan 01 00:00:00 1970 +0000
465 summary: 5
465 summary: 5
466
466
467 changeset: 10:52dc0b4c6907
467 changeset: 10:52dc0b4c6907
468 user: test
468 user: test
469 date: Thu Jan 01 00:00:00 1970 +0000
469 date: Thu Jan 01 00:00:00 1970 +0000
470 summary: 4
470 summary: 4
471
471
472 changeset: 11:882b35362a6b
472 changeset: 11:882b35362a6b
473 user: test
473 user: test
474 date: Thu Jan 01 00:00:00 1970 +0000
474 date: Thu Jan 01 00:00:00 1970 +0000
475 summary: 3
475 summary: 3
476
476
477 changeset: 13:9db0f28fd374
477 changeset: 13:9db0f28fd374
478 user: foo
478 user: foo
479 date: Thu Jan 01 00:00:00 1970 +0000
479 date: Thu Jan 01 00:00:00 1970 +0000
480 summary: 2
480 summary: 2
481
481
482 changeset: 14:f64defefacee
482 changeset: 14:f64defefacee
483 parent: 1:5d205f8b35b6
483 parent: 1:5d205f8b35b6
484 user: foo
484 user: foo
485 date: Thu Jan 01 00:00:00 1970 +0000
485 date: Thu Jan 01 00:00:00 1970 +0000
486 summary: 3
486 summary: 3
487
487
488 changeset: 17:64ecd9071ce8
488 changeset: 17:64ecd9071ce8
489 user: bar
489 user: bar
490 date: Thu Jan 01 00:00:00 1970 +0000
490 date: Thu Jan 01 00:00:00 1970 +0000
491 summary: 1
491 summary: 1
492
492
493 changeset: 19:2e80e1351d6e
493 changeset: 19:2e80e1351d6e
494 user: test
494 user: test
495 date: Thu Jan 01 00:00:00 1970 +0000
495 date: Thu Jan 01 00:00:00 1970 +0000
496 summary: 2
496 summary: 2
497
497
498 changeset: 21:7e61b508e709
498 changeset: 21:7e61b508e709
499 branch: dev
499 branch: dev
500 tag: tip
500 tag: tip
501 user: foo
501 user: foo
502 date: Thu Jan 01 00:00:00 1970 +0000
502 date: Thu Jan 01 00:00:00 1970 +0000
503 summary: 2
503 summary: 2
504
504
505 $ hg log -r 'destination(2)'
505 $ hg log -r 'destination(2)'
506 changeset: 7:ef0ef43d49e7
506 changeset: 7:ef0ef43d49e7
507 parent: 0:68795b066622
507 parent: 0:68795b066622
508 user: foo
508 user: foo
509 date: Thu Jan 01 00:00:00 1970 +0000
509 date: Thu Jan 01 00:00:00 1970 +0000
510 summary: 2
510 summary: 2
511
511
512 changeset: 13:9db0f28fd374
512 changeset: 13:9db0f28fd374
513 user: foo
513 user: foo
514 date: Thu Jan 01 00:00:00 1970 +0000
514 date: Thu Jan 01 00:00:00 1970 +0000
515 summary: 2
515 summary: 2
516
516
517 changeset: 19:2e80e1351d6e
517 changeset: 19:2e80e1351d6e
518 user: test
518 user: test
519 date: Thu Jan 01 00:00:00 1970 +0000
519 date: Thu Jan 01 00:00:00 1970 +0000
520 summary: 2
520 summary: 2
521
521
522 changeset: 21:7e61b508e709
522 changeset: 21:7e61b508e709
523 branch: dev
523 branch: dev
524 tag: tip
524 tag: tip
525 user: foo
525 user: foo
526 date: Thu Jan 01 00:00:00 1970 +0000
526 date: Thu Jan 01 00:00:00 1970 +0000
527 summary: 2
527 summary: 2
528
528
529 Transplants of grafts can find a destination...
529 Transplants of grafts can find a destination...
530 $ hg log -r 'destination(7)'
530 $ hg log -r 'destination(7)'
531 changeset: 21:7e61b508e709
531 changeset: 21:7e61b508e709
532 branch: dev
532 branch: dev
533 tag: tip
533 tag: tip
534 user: foo
534 user: foo
535 date: Thu Jan 01 00:00:00 1970 +0000
535 date: Thu Jan 01 00:00:00 1970 +0000
536 summary: 2
536 summary: 2
537
537
538 ... grafts of grafts unfortunately can't
538 ... grafts of grafts unfortunately can't
539 $ hg graft -q 13
539 $ hg graft -q 13
540 $ hg log -r 'destination(13)'
540 $ hg log -r 'destination(13)'
541 All copies of a cset
541 All copies of a cset
542 $ hg log -r 'origin(13) or destination(origin(13))'
542 $ hg log -r 'origin(13) or destination(origin(13))'
543 changeset: 2:5c095ad7e90f
543 changeset: 2:5c095ad7e90f
544 user: test
544 user: test
545 date: Thu Jan 01 00:00:00 1970 +0000
545 date: Thu Jan 01 00:00:00 1970 +0000
546 summary: 2
546 summary: 2
547
547
548 changeset: 7:ef0ef43d49e7
548 changeset: 7:ef0ef43d49e7
549 parent: 0:68795b066622
549 parent: 0:68795b066622
550 user: foo
550 user: foo
551 date: Thu Jan 01 00:00:00 1970 +0000
551 date: Thu Jan 01 00:00:00 1970 +0000
552 summary: 2
552 summary: 2
553
553
554 changeset: 13:9db0f28fd374
554 changeset: 13:9db0f28fd374
555 user: foo
555 user: foo
556 date: Thu Jan 01 00:00:00 1970 +0000
556 date: Thu Jan 01 00:00:00 1970 +0000
557 summary: 2
557 summary: 2
558
558
559 changeset: 19:2e80e1351d6e
559 changeset: 19:2e80e1351d6e
560 user: test
560 user: test
561 date: Thu Jan 01 00:00:00 1970 +0000
561 date: Thu Jan 01 00:00:00 1970 +0000
562 summary: 2
562 summary: 2
563
563
564 changeset: 21:7e61b508e709
564 changeset: 21:7e61b508e709
565 branch: dev
565 branch: dev
566 user: foo
566 user: foo
567 date: Thu Jan 01 00:00:00 1970 +0000
567 date: Thu Jan 01 00:00:00 1970 +0000
568 summary: 2
568 summary: 2
569
569
570 changeset: 22:1313d0a825e2
570 changeset: 22:1313d0a825e2
571 branch: dev
571 branch: dev
572 tag: tip
572 tag: tip
573 user: foo
573 user: foo
574 date: Thu Jan 01 00:00:00 1970 +0000
574 date: Thu Jan 01 00:00:00 1970 +0000
575 summary: 2
575 summary: 2
576
576
577
577
578 graft works on complex revset
578 graft works on complex revset
579
579
580 $ hg graft 'origin(13) or destination(origin(13))'
580 $ hg graft 'origin(13) or destination(origin(13))'
581 skipping ancestor revision 21
581 skipping ancestor revision 21
582 skipping ancestor revision 22
582 skipping ancestor revision 22
583 skipping revision 2 (already grafted to 22)
583 skipping revision 2 (already grafted to 22)
584 grafting revision 7
584 grafting revision 7
585 grafting revision 13
585 grafting revision 13
586 grafting revision 19
586 grafting revision 19
587 merging b
587 merging b
@@ -1,348 +1,348 b''
1 Criss cross merging
1 Criss cross merging
2
2
3 $ hg init criss-cross
3 $ hg init criss-cross
4 $ cd criss-cross
4 $ cd criss-cross
5 $ echo '0 base' > f1
5 $ echo '0 base' > f1
6 $ echo '0 base' > f2
6 $ echo '0 base' > f2
7 $ hg ci -Aqm '0 base'
7 $ hg ci -Aqm '0 base'
8
8
9 $ echo '1 first change' > f1
9 $ echo '1 first change' > f1
10 $ hg ci -m '1 first change f1'
10 $ hg ci -m '1 first change f1'
11
11
12 $ hg up -qr0
12 $ hg up -qr0
13 $ echo '2 first change' > f2
13 $ echo '2 first change' > f2
14 $ hg ci -qm '2 first change f2'
14 $ hg ci -qm '2 first change f2'
15
15
16 $ hg merge -qr 1
16 $ hg merge -qr 1
17 $ hg ci -m '3 merge'
17 $ hg ci -m '3 merge'
18
18
19 $ hg up -qr2
19 $ hg up -qr2
20 $ hg merge -qr1
20 $ hg merge -qr1
21 $ hg ci -qm '4 merge'
21 $ hg ci -qm '4 merge'
22
22
23 $ echo '5 second change' > f1
23 $ echo '5 second change' > f1
24 $ hg ci -m '5 second change f1'
24 $ hg ci -m '5 second change f1'
25
25
26 $ hg up -r3
26 $ hg up -r3
27 note: using 0f6b37dbe527 as ancestor of adfe50279922 and cf89f02107e5
27 note: using 0f6b37dbe527 as ancestor of adfe50279922 and cf89f02107e5
28 alternatively, use --config merge.preferancestor=40663881a6dd
28 alternatively, use --config merge.preferancestor=40663881a6dd
29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 $ echo '6 second change' > f2
30 $ echo '6 second change' > f2
31 $ hg ci -m '6 second change f2'
31 $ hg ci -m '6 second change f2'
32
32
33 $ hg log -G
33 $ hg log -G
34 @ changeset: 6:3b08d01b0ab5
34 @ changeset: 6:3b08d01b0ab5
35 | tag: tip
35 | tag: tip
36 | parent: 3:cf89f02107e5
36 | parent: 3:cf89f02107e5
37 | user: test
37 | user: test
38 | date: Thu Jan 01 00:00:00 1970 +0000
38 | date: Thu Jan 01 00:00:00 1970 +0000
39 | summary: 6 second change f2
39 | summary: 6 second change f2
40 |
40 |
41 | o changeset: 5:adfe50279922
41 | o changeset: 5:adfe50279922
42 | | user: test
42 | | user: test
43 | | date: Thu Jan 01 00:00:00 1970 +0000
43 | | date: Thu Jan 01 00:00:00 1970 +0000
44 | | summary: 5 second change f1
44 | | summary: 5 second change f1
45 | |
45 | |
46 | o changeset: 4:7d3e55501ae6
46 | o changeset: 4:7d3e55501ae6
47 | |\ parent: 2:40663881a6dd
47 | |\ parent: 2:40663881a6dd
48 | | | parent: 1:0f6b37dbe527
48 | | | parent: 1:0f6b37dbe527
49 | | | user: test
49 | | | user: test
50 | | | date: Thu Jan 01 00:00:00 1970 +0000
50 | | | date: Thu Jan 01 00:00:00 1970 +0000
51 | | | summary: 4 merge
51 | | | summary: 4 merge
52 | | |
52 | | |
53 o---+ changeset: 3:cf89f02107e5
53 o---+ changeset: 3:cf89f02107e5
54 | | | parent: 2:40663881a6dd
54 | | | parent: 2:40663881a6dd
55 |/ / parent: 1:0f6b37dbe527
55 |/ / parent: 1:0f6b37dbe527
56 | | user: test
56 | | user: test
57 | | date: Thu Jan 01 00:00:00 1970 +0000
57 | | date: Thu Jan 01 00:00:00 1970 +0000
58 | | summary: 3 merge
58 | | summary: 3 merge
59 | |
59 | |
60 | o changeset: 2:40663881a6dd
60 | o changeset: 2:40663881a6dd
61 | | parent: 0:40494bf2444c
61 | | parent: 0:40494bf2444c
62 | | user: test
62 | | user: test
63 | | date: Thu Jan 01 00:00:00 1970 +0000
63 | | date: Thu Jan 01 00:00:00 1970 +0000
64 | | summary: 2 first change f2
64 | | summary: 2 first change f2
65 | |
65 | |
66 o | changeset: 1:0f6b37dbe527
66 o | changeset: 1:0f6b37dbe527
67 |/ user: test
67 |/ user: test
68 | date: Thu Jan 01 00:00:00 1970 +0000
68 | date: Thu Jan 01 00:00:00 1970 +0000
69 | summary: 1 first change f1
69 | summary: 1 first change f1
70 |
70 |
71 o changeset: 0:40494bf2444c
71 o changeset: 0:40494bf2444c
72 user: test
72 user: test
73 date: Thu Jan 01 00:00:00 1970 +0000
73 date: Thu Jan 01 00:00:00 1970 +0000
74 summary: 0 base
74 summary: 0 base
75
75
76
76
77 $ hg merge -v --debug --tool internal:dump 5
77 $ hg merge -v --debug --tool internal:dump 5
78 note: using 0f6b37dbe527 as ancestor of 3b08d01b0ab5 and adfe50279922
78 note: using 0f6b37dbe527 as ancestor of 3b08d01b0ab5 and adfe50279922
79 alternatively, use --config merge.preferancestor=40663881a6dd
79 alternatively, use --config merge.preferancestor=40663881a6dd
80 searching for copies back to rev 3
80 searching for copies back to rev 3
81 resolving manifests
81 resolving manifests
82 branchmerge: True, force: False, partial: False
82 branchmerge: True, force: False, partial: False
83 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
83 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
84 f1: remote is newer -> g
84 f1: remote is newer -> g
85 f2: versions differ -> m
85 f2: versions differ -> m
86 preserving f2 for resolve of f2
86 preserving f2 for resolve of f2
87 getting f1
87 getting f1
88 updating: f1 1/2 files (50.00%)
88 updating: f1 1/2 files (50.00%)
89 updating: f2 2/2 files (100.00%)
89 updating: f2 2/2 files (100.00%)
90 picked tool 'internal:dump' for f2 (binary False symlink False)
90 picked tool 'internal:dump' for f2 (binary False symlink False)
91 merging f2
91 merging f2
92 my f2@3b08d01b0ab5+ other f2@adfe50279922 ancestor f2@40494bf2444c
92 my f2@3b08d01b0ab5+ other f2@adfe50279922 ancestor f2@40494bf2444c
93 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
93 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
94 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
94 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
95 [1]
95 [1]
96
96
97 $ head *
97 $ head *
98 ==> f1 <==
98 ==> f1 <==
99 5 second change
99 5 second change
100
100
101 ==> f2 <==
101 ==> f2 <==
102 6 second change
102 6 second change
103
103
104 ==> f2.base <==
104 ==> f2.base <==
105 0 base
105 0 base
106
106
107 ==> f2.local <==
107 ==> f2.local <==
108 6 second change
108 6 second change
109
109
110 ==> f2.orig <==
110 ==> f2.orig <==
111 6 second change
111 6 second change
112
112
113 ==> f2.other <==
113 ==> f2.other <==
114 2 first change
114 2 first change
115
115
116 $ hg up -qC .
116 $ hg up -qC .
117 $ hg merge -v --tool internal:dump 5 --config merge.preferancestor="null 40663881 3b08d"
117 $ hg merge -v --tool internal:dump 5 --config merge.preferancestor="null 40663881 3b08d"
118 note: using 40663881a6dd as ancestor of 3b08d01b0ab5 and adfe50279922
118 note: using 40663881a6dd as ancestor of 3b08d01b0ab5 and adfe50279922
119 alternatively, use --config merge.preferancestor=0f6b37dbe527
119 alternatively, use --config merge.preferancestor=0f6b37dbe527
120 resolving manifests
120 resolving manifests
121 merging f1
121 merging f1
122 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
122 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
123 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
123 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
124 [1]
124 [1]
125
125
126 Redo merge with merge.preferancestor="*" to enable bid merge
126 Redo merge with merge.preferancestor="*" to enable bid merge
127
127
128 $ rm f*
128 $ rm f*
129 $ hg up -qC .
129 $ hg up -qC .
130 $ hg merge -v --debug --tool internal:dump 5 --config merge.preferancestor="*"
130 $ hg merge -v --debug --tool internal:dump 5 --config merge.preferancestor="*"
131 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
131 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
132
132
133 calculating bids for ancestor 0f6b37dbe527
133 calculating bids for ancestor 0f6b37dbe527
134 searching for copies back to rev 3
134 searching for copies back to rev 3
135 resolving manifests
135 resolving manifests
136 branchmerge: True, force: False, partial: False
136 branchmerge: True, force: False, partial: False
137 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
137 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
138 f1: remote is newer -> g
138 f1: remote is newer -> g
139 f2: versions differ -> m
139 f2: versions differ -> m
140
140
141 calculating bids for ancestor 40663881a6dd
141 calculating bids for ancestor 40663881a6dd
142 searching for copies back to rev 3
142 searching for copies back to rev 3
143 resolving manifests
143 resolving manifests
144 branchmerge: True, force: False, partial: False
144 branchmerge: True, force: False, partial: False
145 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
145 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
146 f1: versions differ -> m
146 f1: versions differ -> m
147 f2: keep -> k
147 f2: keep -> k
148
148
149 auction for merging merge bids
149 auction for merging merge bids
150 f1: picking 'get' action
150 f1: picking 'get' action
151 f2: picking 'keep' action
151 f2: picking 'keep' action
152 end of auction
152 end of auction
153
153
154 f1: remote is newer -> g
154 f1: remote is newer -> g
155 f2: keep -> k
155 f2: keep -> k
156 getting f1
156 getting f1
157 updating: f1 1/1 files (100.00%)
157 updating: f1 1/1 files (100.00%)
158 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 (branch merge, don't forget to commit)
159 (branch merge, don't forget to commit)
160
160
161 $ head *
161 $ head *
162 ==> f1 <==
162 ==> f1 <==
163 5 second change
163 5 second change
164
164
165 ==> f2 <==
165 ==> f2 <==
166 6 second change
166 6 second change
167
167
168
168
169 The other way around:
169 The other way around:
170
170
171 $ hg up -C -r5
171 $ hg up -C -r5
172 note: using 0f6b37dbe527 as ancestor of 3b08d01b0ab5 and adfe50279922
172 note: using 0f6b37dbe527 as ancestor of 3b08d01b0ab5 and adfe50279922
173 alternatively, use --config merge.preferancestor=40663881a6dd
173 alternatively, use --config merge.preferancestor=40663881a6dd
174 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 $ hg merge -v --debug --config merge.preferancestor="*"
175 $ hg merge -v --debug --config merge.preferancestor="*"
176 note: merging adfe50279922+ and 3b08d01b0ab5 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
176 note: merging adfe50279922+ and 3b08d01b0ab5 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
177
177
178 calculating bids for ancestor 0f6b37dbe527
178 calculating bids for ancestor 0f6b37dbe527
179 searching for copies back to rev 3
179 searching for copies back to rev 3
180 resolving manifests
180 resolving manifests
181 branchmerge: True, force: False, partial: False
181 branchmerge: True, force: False, partial: False
182 ancestor: 0f6b37dbe527, local: adfe50279922+, remote: 3b08d01b0ab5
182 ancestor: 0f6b37dbe527, local: adfe50279922+, remote: 3b08d01b0ab5
183 f1: keep -> k
183 f1: keep -> k
184 f2: versions differ -> m
184 f2: versions differ -> m
185
185
186 calculating bids for ancestor 40663881a6dd
186 calculating bids for ancestor 40663881a6dd
187 searching for copies back to rev 3
187 searching for copies back to rev 3
188 resolving manifests
188 resolving manifests
189 branchmerge: True, force: False, partial: False
189 branchmerge: True, force: False, partial: False
190 ancestor: 40663881a6dd, local: adfe50279922+, remote: 3b08d01b0ab5
190 ancestor: 40663881a6dd, local: adfe50279922+, remote: 3b08d01b0ab5
191 f1: versions differ -> m
191 f1: versions differ -> m
192 f2: remote is newer -> g
192 f2: remote is newer -> g
193
193
194 auction for merging merge bids
194 auction for merging merge bids
195 f1: picking 'keep' action
195 f1: picking 'keep' action
196 f2: picking 'get' action
196 f2: picking 'get' action
197 end of auction
197 end of auction
198
198
199 f2: remote is newer -> g
199 f1: keep -> k
200 f1: keep -> k
200 f2: remote is newer -> g
201 getting f2
201 getting f2
202 updating: f2 1/1 files (100.00%)
202 updating: f2 1/1 files (100.00%)
203 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
203 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 (branch merge, don't forget to commit)
204 (branch merge, don't forget to commit)
205
205
206 $ head *
206 $ head *
207 ==> f1 <==
207 ==> f1 <==
208 5 second change
208 5 second change
209
209
210 ==> f2 <==
210 ==> f2 <==
211 6 second change
211 6 second change
212
212
213 Verify how the output looks and and how verbose it is:
213 Verify how the output looks and and how verbose it is:
214
214
215 $ hg up -qC
215 $ hg up -qC
216 $ hg merge --config merge.preferancestor="*"
216 $ hg merge --config merge.preferancestor="*"
217 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
217 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
218 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
218 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 (branch merge, don't forget to commit)
219 (branch merge, don't forget to commit)
220
220
221 $ hg up -qC
221 $ hg up -qC
222 $ hg merge -v --config merge.preferancestor="*"
222 $ hg merge -v --config merge.preferancestor="*"
223 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
223 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
224
224
225 calculating bids for ancestor 0f6b37dbe527
225 calculating bids for ancestor 0f6b37dbe527
226 resolving manifests
226 resolving manifests
227
227
228 calculating bids for ancestor 40663881a6dd
228 calculating bids for ancestor 40663881a6dd
229 resolving manifests
229 resolving manifests
230
230
231 auction for merging merge bids
231 auction for merging merge bids
232 f1: picking 'get' action
232 f1: picking 'get' action
233 f2: picking 'keep' action
233 f2: picking 'keep' action
234 end of auction
234 end of auction
235
235
236 getting f1
236 getting f1
237 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
237 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
238 (branch merge, don't forget to commit)
238 (branch merge, don't forget to commit)
239
239
240 $ hg up -qC
240 $ hg up -qC
241 $ hg merge -v --debug --config merge.preferancestor="*"
241 $ hg merge -v --debug --config merge.preferancestor="*"
242 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
242 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
243
243
244 calculating bids for ancestor 0f6b37dbe527
244 calculating bids for ancestor 0f6b37dbe527
245 searching for copies back to rev 3
245 searching for copies back to rev 3
246 resolving manifests
246 resolving manifests
247 branchmerge: True, force: False, partial: False
247 branchmerge: True, force: False, partial: False
248 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
248 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
249 f1: remote is newer -> g
249 f1: remote is newer -> g
250 f2: versions differ -> m
250 f2: versions differ -> m
251
251
252 calculating bids for ancestor 40663881a6dd
252 calculating bids for ancestor 40663881a6dd
253 searching for copies back to rev 3
253 searching for copies back to rev 3
254 resolving manifests
254 resolving manifests
255 branchmerge: True, force: False, partial: False
255 branchmerge: True, force: False, partial: False
256 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
256 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
257 f1: versions differ -> m
257 f1: versions differ -> m
258 f2: keep -> k
258 f2: keep -> k
259
259
260 auction for merging merge bids
260 auction for merging merge bids
261 f1: picking 'get' action
261 f1: picking 'get' action
262 f2: picking 'keep' action
262 f2: picking 'keep' action
263 end of auction
263 end of auction
264
264
265 f1: remote is newer -> g
265 f1: remote is newer -> g
266 f2: keep -> k
266 f2: keep -> k
267 getting f1
267 getting f1
268 updating: f1 1/1 files (100.00%)
268 updating: f1 1/1 files (100.00%)
269 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
270 (branch merge, don't forget to commit)
270 (branch merge, don't forget to commit)
271
271
272 $ cd ..
272 $ cd ..
273
273
274 http://stackoverflow.com/questions/9350005/how-do-i-specify-a-merge-base-to-use-in-a-hg-merge/9430810
274 http://stackoverflow.com/questions/9350005/how-do-i-specify-a-merge-base-to-use-in-a-hg-merge/9430810
275
275
276 $ hg init ancestor-merging
276 $ hg init ancestor-merging
277 $ cd ancestor-merging
277 $ cd ancestor-merging
278 $ echo a > x
278 $ echo a > x
279 $ hg commit -A -m a x
279 $ hg commit -A -m a x
280 $ hg update -q 0
280 $ hg update -q 0
281 $ echo b >> x
281 $ echo b >> x
282 $ hg commit -m b
282 $ hg commit -m b
283 $ hg update -q 0
283 $ hg update -q 0
284 $ echo c >> x
284 $ echo c >> x
285 $ hg commit -qm c
285 $ hg commit -qm c
286 $ hg update -q 1
286 $ hg update -q 1
287 $ hg merge -q --tool internal:local 2
287 $ hg merge -q --tool internal:local 2
288 $ echo c >> x
288 $ echo c >> x
289 $ hg commit -m bc
289 $ hg commit -m bc
290 $ hg update -q 2
290 $ hg update -q 2
291 $ hg merge -q --tool internal:local 1
291 $ hg merge -q --tool internal:local 1
292 $ echo b >> x
292 $ echo b >> x
293 $ hg commit -qm cb
293 $ hg commit -qm cb
294
294
295 $ hg merge
295 $ hg merge
296 note: using 70008a2163f6 as ancestor of 0d355fdef312 and 4b8b546a3eef
296 note: using 70008a2163f6 as ancestor of 0d355fdef312 and 4b8b546a3eef
297 alternatively, use --config merge.preferancestor=b211bbc6eb3c
297 alternatively, use --config merge.preferancestor=b211bbc6eb3c
298 merging x
298 merging x
299 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
299 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
300 (branch merge, don't forget to commit)
300 (branch merge, don't forget to commit)
301 $ cat x
301 $ cat x
302 a
302 a
303 c
303 c
304 b
304 b
305 c
305 c
306
306
307 $ hg up -qC .
307 $ hg up -qC .
308
308
309 $ hg merge --config merge.preferancestor=b211bbc6eb3c
309 $ hg merge --config merge.preferancestor=b211bbc6eb3c
310 note: using b211bbc6eb3c as ancestor of 0d355fdef312 and 4b8b546a3eef
310 note: using b211bbc6eb3c as ancestor of 0d355fdef312 and 4b8b546a3eef
311 alternatively, use --config merge.preferancestor=70008a2163f6
311 alternatively, use --config merge.preferancestor=70008a2163f6
312 merging x
312 merging x
313 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
313 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
314 (branch merge, don't forget to commit)
314 (branch merge, don't forget to commit)
315 $ cat x
315 $ cat x
316 a
316 a
317 b
317 b
318 c
318 c
319 b
319 b
320
320
321 $ hg up -qC .
321 $ hg up -qC .
322
322
323 $ hg merge -v --config merge.preferancestor="*"
323 $ hg merge -v --config merge.preferancestor="*"
324 note: merging 0d355fdef312+ and 4b8b546a3eef using bids from ancestors 70008a2163f6 and b211bbc6eb3c
324 note: merging 0d355fdef312+ and 4b8b546a3eef using bids from ancestors 70008a2163f6 and b211bbc6eb3c
325
325
326 calculating bids for ancestor 70008a2163f6
326 calculating bids for ancestor 70008a2163f6
327 resolving manifests
327 resolving manifests
328
328
329 calculating bids for ancestor b211bbc6eb3c
329 calculating bids for ancestor b211bbc6eb3c
330 resolving manifests
330 resolving manifests
331
331
332 auction for merging merge bids
332 auction for merging merge bids
333 x: multiple bids for merge action:
333 x: multiple bids for merge action:
334 versions differ -> m
334 versions differ -> m
335 versions differ -> m
335 versions differ -> m
336 x: ambiguous merge - picked m action
336 x: ambiguous merge - picked m action
337 end of auction
337 end of auction
338
338
339 merging x
339 merging x
340 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
340 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
341 (branch merge, don't forget to commit)
341 (branch merge, don't forget to commit)
342 $ cat x
342 $ cat x
343 a
343 a
344 c
344 c
345 b
345 b
346 c
346 c
347
347
348 $ cd ..
348 $ cd ..
@@ -1,195 +1,195 b''
1 $ hg init
1 $ hg init
2
2
3 $ echo "[merge]" >> .hg/hgrc
3 $ echo "[merge]" >> .hg/hgrc
4 $ echo "followcopies = 1" >> .hg/hgrc
4 $ echo "followcopies = 1" >> .hg/hgrc
5
5
6 $ echo foo > a
6 $ echo foo > a
7 $ echo foo > a2
7 $ echo foo > a2
8 $ hg add a a2
8 $ hg add a a2
9 $ hg ci -m "start"
9 $ hg ci -m "start"
10
10
11 $ hg mv a b
11 $ hg mv a b
12 $ hg mv a2 b2
12 $ hg mv a2 b2
13 $ hg ci -m "rename"
13 $ hg ci -m "rename"
14
14
15 $ hg co 0
15 $ hg co 0
16 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
16 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
17
17
18 $ echo blahblah > a
18 $ echo blahblah > a
19 $ echo blahblah > a2
19 $ echo blahblah > a2
20 $ hg mv a2 c2
20 $ hg mv a2 c2
21 $ hg ci -m "modify"
21 $ hg ci -m "modify"
22 created new head
22 created new head
23
23
24 $ hg merge -y --debug
24 $ hg merge -y --debug
25 searching for copies back to rev 1
25 searching for copies back to rev 1
26 unmatched files in local:
26 unmatched files in local:
27 c2
27 c2
28 unmatched files in other:
28 unmatched files in other:
29 b
29 b
30 b2
30 b2
31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
32 src: 'a' -> dst: 'b' *
32 src: 'a' -> dst: 'b' *
33 src: 'a2' -> dst: 'b2' !
33 src: 'a2' -> dst: 'b2' !
34 src: 'a2' -> dst: 'c2' !
34 src: 'a2' -> dst: 'c2' !
35 checking for directory renames
35 checking for directory renames
36 resolving manifests
36 resolving manifests
37 branchmerge: True, force: False, partial: False
37 branchmerge: True, force: False, partial: False
38 ancestor: af1939970a1c, local: 044f8520aeeb+, remote: 85c198ef2f6c
38 ancestor: af1939970a1c, local: 044f8520aeeb+, remote: 85c198ef2f6c
39 a2: divergent renames -> dr
39 b2: remote created -> g
40 b: remote moved from a -> m
40 b: remote moved from a -> m
41 preserving a for resolve of b
41 preserving a for resolve of b
42 b2: remote created -> g
42 a2: divergent renames -> dr
43 removing a
43 removing a
44 getting b2
44 getting b2
45 updating: b2 1/3 files (33.33%)
45 updating: b2 1/3 files (33.33%)
46 updating: a2 2/3 files (66.67%)
46 updating: b 2/3 files (66.67%)
47 note: possible conflict - a2 was renamed multiple times to:
48 c2
49 b2
50 updating: b 3/3 files (100.00%)
51 picked tool 'internal:merge' for b (binary False symlink False)
47 picked tool 'internal:merge' for b (binary False symlink False)
52 merging a and b to b
48 merging a and b to b
53 my b@044f8520aeeb+ other b@85c198ef2f6c ancestor a@af1939970a1c
49 my b@044f8520aeeb+ other b@85c198ef2f6c ancestor a@af1939970a1c
54 premerge successful
50 premerge successful
51 updating: a2 3/3 files (100.00%)
52 note: possible conflict - a2 was renamed multiple times to:
53 c2
54 b2
55 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
55 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
56 (branch merge, don't forget to commit)
56 (branch merge, don't forget to commit)
57
57
58 $ hg status -AC
58 $ hg status -AC
59 M b
59 M b
60 a
60 a
61 M b2
61 M b2
62 R a
62 R a
63 C c2
63 C c2
64
64
65 $ cat b
65 $ cat b
66 blahblah
66 blahblah
67
67
68 $ hg ci -m "merge"
68 $ hg ci -m "merge"
69
69
70 $ hg debugindex b
70 $ hg debugindex b
71 rev offset length ..... linkrev nodeid p1 p2 (re)
71 rev offset length ..... linkrev nodeid p1 p2 (re)
72 0 0 67 ..... 1 57eacc201a7f 000000000000 000000000000 (re)
72 0 0 67 ..... 1 57eacc201a7f 000000000000 000000000000 (re)
73 1 67 72 ..... 3 4727ba907962 000000000000 57eacc201a7f (re)
73 1 67 72 ..... 3 4727ba907962 000000000000 57eacc201a7f (re)
74
74
75 $ hg debugrename b
75 $ hg debugrename b
76 b renamed from a:dd03b83622e78778b403775d0d074b9ac7387a66
76 b renamed from a:dd03b83622e78778b403775d0d074b9ac7387a66
77
77
78 This used to trigger a "divergent renames" warning, despite no renames
78 This used to trigger a "divergent renames" warning, despite no renames
79
79
80 $ hg cp b b3
80 $ hg cp b b3
81 $ hg cp b b4
81 $ hg cp b b4
82 $ hg ci -A -m 'copy b twice'
82 $ hg ci -A -m 'copy b twice'
83 $ hg up eb92d88a9712
83 $ hg up eb92d88a9712
84 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
85 $ hg up
85 $ hg up
86 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
86 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 $ hg rm b3 b4
87 $ hg rm b3 b4
88 $ hg ci -m 'clean up a bit of our mess'
88 $ hg ci -m 'clean up a bit of our mess'
89
89
90 We'd rather not warn on divergent renames done in the same changeset (issue2113)
90 We'd rather not warn on divergent renames done in the same changeset (issue2113)
91
91
92 $ hg cp b b3
92 $ hg cp b b3
93 $ hg mv b b4
93 $ hg mv b b4
94 $ hg ci -A -m 'divergent renames in same changeset'
94 $ hg ci -A -m 'divergent renames in same changeset'
95 $ hg up c761c6948de0
95 $ hg up c761c6948de0
96 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
96 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
97 $ hg up
97 $ hg up
98 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
98 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
99
99
100 Check for issue2642
100 Check for issue2642
101
101
102 $ hg init t
102 $ hg init t
103 $ cd t
103 $ cd t
104
104
105 $ echo c0 > f1
105 $ echo c0 > f1
106 $ hg ci -Aqm0
106 $ hg ci -Aqm0
107
107
108 $ hg up null -q
108 $ hg up null -q
109 $ echo c1 > f1 # backport
109 $ echo c1 > f1 # backport
110 $ hg ci -Aqm1
110 $ hg ci -Aqm1
111 $ hg mv f1 f2
111 $ hg mv f1 f2
112 $ hg ci -qm2
112 $ hg ci -qm2
113
113
114 $ hg up 0 -q
114 $ hg up 0 -q
115 $ hg merge 1 -q --tool internal:local
115 $ hg merge 1 -q --tool internal:local
116 $ hg ci -qm3
116 $ hg ci -qm3
117
117
118 $ hg merge 2
118 $ hg merge 2
119 merging f1 and f2 to f2
119 merging f1 and f2 to f2
120 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
120 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
121 (branch merge, don't forget to commit)
121 (branch merge, don't forget to commit)
122
122
123 $ cat f2
123 $ cat f2
124 c0
124 c0
125
125
126 $ cd ..
126 $ cd ..
127
127
128 Check for issue2089
128 Check for issue2089
129
129
130 $ hg init repo2089
130 $ hg init repo2089
131 $ cd repo2089
131 $ cd repo2089
132
132
133 $ echo c0 > f1
133 $ echo c0 > f1
134 $ hg ci -Aqm0
134 $ hg ci -Aqm0
135
135
136 $ hg up null -q
136 $ hg up null -q
137 $ echo c1 > f1
137 $ echo c1 > f1
138 $ hg ci -Aqm1
138 $ hg ci -Aqm1
139
139
140 $ hg up 0 -q
140 $ hg up 0 -q
141 $ hg merge 1 -q --tool internal:local
141 $ hg merge 1 -q --tool internal:local
142 $ echo c2 > f1
142 $ echo c2 > f1
143 $ hg ci -qm2
143 $ hg ci -qm2
144
144
145 $ hg up 1 -q
145 $ hg up 1 -q
146 $ hg mv f1 f2
146 $ hg mv f1 f2
147 $ hg ci -Aqm3
147 $ hg ci -Aqm3
148
148
149 $ hg up 2 -q
149 $ hg up 2 -q
150 $ hg merge 3
150 $ hg merge 3
151 merging f1 and f2 to f2
151 merging f1 and f2 to f2
152 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
152 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
153 (branch merge, don't forget to commit)
153 (branch merge, don't forget to commit)
154
154
155 $ cat f2
155 $ cat f2
156 c2
156 c2
157
157
158 $ cd ..
158 $ cd ..
159
159
160 Check for issue3074
160 Check for issue3074
161
161
162 $ hg init repo3074
162 $ hg init repo3074
163 $ cd repo3074
163 $ cd repo3074
164 $ echo foo > file
164 $ echo foo > file
165 $ hg add file
165 $ hg add file
166 $ hg commit -m "added file"
166 $ hg commit -m "added file"
167 $ hg mv file newfile
167 $ hg mv file newfile
168 $ hg commit -m "renamed file"
168 $ hg commit -m "renamed file"
169 $ hg update 0
169 $ hg update 0
170 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
170 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
171 $ hg rm file
171 $ hg rm file
172 $ hg commit -m "deleted file"
172 $ hg commit -m "deleted file"
173 created new head
173 created new head
174 $ hg merge --debug
174 $ hg merge --debug
175 searching for copies back to rev 1
175 searching for copies back to rev 1
176 unmatched files in other:
176 unmatched files in other:
177 newfile
177 newfile
178 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
178 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
179 src: 'file' -> dst: 'newfile' %
179 src: 'file' -> dst: 'newfile' %
180 checking for directory renames
180 checking for directory renames
181 resolving manifests
181 resolving manifests
182 branchmerge: True, force: False, partial: False
182 branchmerge: True, force: False, partial: False
183 ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
183 ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
184 newfile: remote created -> g
184 file: rename and delete -> rd
185 file: rename and delete -> rd
185 newfile: remote created -> g
186 getting newfile
186 getting newfile
187 updating: newfile 1/2 files (50.00%)
187 updating: newfile 1/2 files (50.00%)
188 updating: file 2/2 files (100.00%)
188 updating: file 2/2 files (100.00%)
189 note: possible conflict - file was deleted and renamed to:
189 note: possible conflict - file was deleted and renamed to:
190 newfile
190 newfile
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 (branch merge, don't forget to commit)
192 (branch merge, don't forget to commit)
193 $ hg status
193 $ hg status
194 M newfile
194 M newfile
195 $ cd ..
195 $ cd ..
@@ -1,972 +1,972 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 branchmerge: True, force: False, partial: False
87 branchmerge: True, force: False, partial: False
88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
89 a: keep -> k
89 a: keep -> k
90 b: remote copied from a -> m
90 b: remote copied from a -> m
91 preserving a for resolve of b
91 preserving a for resolve of b
92 rev: versions differ -> m
92 rev: versions differ -> m
93 preserving rev for resolve of rev
93 preserving rev for resolve of rev
94 updating: b 1/2 files (50.00%)
94 updating: b 1/2 files (50.00%)
95 picked tool 'python ../merge' for b (binary False symlink False)
95 picked tool 'python ../merge' for b (binary False symlink False)
96 merging a and b to b
96 merging a and b to b
97 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
97 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
98 premerge successful
98 premerge successful
99 updating: rev 2/2 files (100.00%)
99 updating: rev 2/2 files (100.00%)
100 picked tool 'python ../merge' for rev (binary False symlink False)
100 picked tool 'python ../merge' for rev (binary False symlink False)
101 merging rev
101 merging rev
102 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
102 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
103 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
103 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
104 (branch merge, don't forget to commit)
104 (branch merge, don't forget to commit)
105 --------------
105 --------------
106 M b
106 M b
107 a
107 a
108 C a
108 C a
109 --------------
109 --------------
110
110
111 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
111 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
112 created new head
112 created new head
113 --------------
113 --------------
114 test L:nc a b R:up a W: - 2 get rem change to a and b
114 test L:nc a b R:up a W: - 2 get rem change to a and b
115 --------------
115 --------------
116 searching for copies back to rev 1
116 searching for copies back to rev 1
117 unmatched files in local:
117 unmatched files in local:
118 b
118 b
119 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
119 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
120 src: 'a' -> dst: 'b' *
120 src: 'a' -> dst: 'b' *
121 checking for directory renames
121 checking for directory renames
122 resolving manifests
122 resolving manifests
123 branchmerge: True, force: False, partial: False
123 branchmerge: True, force: False, partial: False
124 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
124 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
125 a: remote is newer -> g
125 a: remote is newer -> g
126 b: local copied/moved from a -> m
126 b: local copied/moved from a -> m
127 preserving b for resolve of b
127 preserving b for resolve of b
128 rev: versions differ -> m
128 rev: versions differ -> m
129 preserving rev for resolve of rev
129 preserving rev for resolve of rev
130 getting a
130 getting a
131 updating: a 1/3 files (33.33%)
131 updating: a 1/3 files (33.33%)
132 updating: b 2/3 files (66.67%)
132 updating: b 2/3 files (66.67%)
133 picked tool 'python ../merge' for b (binary False symlink False)
133 picked tool 'python ../merge' for b (binary False symlink False)
134 merging b and a to b
134 merging b and a to b
135 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
135 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
136 premerge successful
136 premerge successful
137 updating: rev 3/3 files (100.00%)
137 updating: rev 3/3 files (100.00%)
138 picked tool 'python ../merge' for rev (binary False symlink False)
138 picked tool 'python ../merge' for rev (binary False symlink False)
139 merging rev
139 merging rev
140 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
140 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
141 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
141 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
142 (branch merge, don't forget to commit)
142 (branch merge, don't forget to commit)
143 --------------
143 --------------
144 M a
144 M a
145 M b
145 M b
146 a
146 a
147 --------------
147 --------------
148
148
149 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
149 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
150 created new head
150 created new head
151 --------------
151 --------------
152 test L:up a R:nm a b W: - 3 get local a change to b, remove a
152 test L:up a R:nm a b W: - 3 get local a change to b, remove a
153 --------------
153 --------------
154 searching for copies back to rev 1
154 searching for copies back to rev 1
155 unmatched files in other:
155 unmatched files in other:
156 b
156 b
157 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
157 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
158 src: 'a' -> dst: 'b' *
158 src: 'a' -> dst: 'b' *
159 checking for directory renames
159 checking for directory renames
160 resolving manifests
160 resolving manifests
161 branchmerge: True, force: False, partial: False
161 branchmerge: True, force: False, partial: False
162 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
162 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
163 b: remote moved from a -> m
163 b: remote moved from a -> m
164 preserving a for resolve of b
164 preserving a for resolve of b
165 rev: versions differ -> m
165 rev: versions differ -> m
166 preserving rev for resolve of rev
166 preserving rev for resolve of rev
167 removing a
167 removing a
168 updating: b 1/2 files (50.00%)
168 updating: b 1/2 files (50.00%)
169 picked tool 'python ../merge' for b (binary False symlink False)
169 picked tool 'python ../merge' for b (binary False symlink False)
170 merging a and b to b
170 merging a and b to b
171 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
171 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
172 premerge successful
172 premerge successful
173 updating: rev 2/2 files (100.00%)
173 updating: rev 2/2 files (100.00%)
174 picked tool 'python ../merge' for rev (binary False symlink False)
174 picked tool 'python ../merge' for rev (binary False symlink False)
175 merging rev
175 merging rev
176 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
176 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
177 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
177 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
178 (branch merge, don't forget to commit)
178 (branch merge, don't forget to commit)
179 --------------
179 --------------
180 M b
180 M b
181 a
181 a
182 --------------
182 --------------
183
183
184 $ tm "nm a b" "up a " " " "4 get remote change to b"
184 $ tm "nm a b" "up a " " " "4 get remote change to b"
185 created new head
185 created new head
186 --------------
186 --------------
187 test L:nm a b R:up a W: - 4 get remote change to b
187 test L:nm a b R:up a W: - 4 get remote change to b
188 --------------
188 --------------
189 searching for copies back to rev 1
189 searching for copies back to rev 1
190 unmatched files in local:
190 unmatched files in local:
191 b
191 b
192 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
192 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
193 src: 'a' -> dst: 'b' *
193 src: 'a' -> dst: 'b' *
194 checking for directory renames
194 checking for directory renames
195 resolving manifests
195 resolving manifests
196 branchmerge: True, force: False, partial: False
196 branchmerge: True, force: False, partial: False
197 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
197 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
198 b: local copied/moved from a -> m
198 b: local copied/moved from a -> m
199 preserving b for resolve of b
199 preserving b for resolve of b
200 rev: versions differ -> m
200 rev: versions differ -> m
201 preserving rev for resolve of rev
201 preserving rev for resolve of rev
202 updating: b 1/2 files (50.00%)
202 updating: b 1/2 files (50.00%)
203 picked tool 'python ../merge' for b (binary False symlink False)
203 picked tool 'python ../merge' for b (binary False symlink False)
204 merging b and a to b
204 merging b and a to b
205 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
205 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
206 premerge successful
206 premerge successful
207 updating: rev 2/2 files (100.00%)
207 updating: rev 2/2 files (100.00%)
208 picked tool 'python ../merge' for rev (binary False symlink False)
208 picked tool 'python ../merge' for rev (binary False symlink False)
209 merging rev
209 merging rev
210 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
210 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
211 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
211 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
212 (branch merge, don't forget to commit)
212 (branch merge, don't forget to commit)
213 --------------
213 --------------
214 M b
214 M b
215 a
215 a
216 --------------
216 --------------
217
217
218 $ tm " " "nc a b" " " "5 get b"
218 $ tm " " "nc a b" " " "5 get b"
219 created new head
219 created new head
220 --------------
220 --------------
221 test L: R:nc a b W: - 5 get b
221 test L: R:nc a b W: - 5 get b
222 --------------
222 --------------
223 searching for copies back to rev 1
223 searching for copies back to rev 1
224 unmatched files in other:
224 unmatched files in other:
225 b
225 b
226 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
226 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
227 src: 'a' -> dst: 'b'
227 src: 'a' -> dst: 'b'
228 checking for directory renames
228 checking for directory renames
229 resolving manifests
229 resolving manifests
230 branchmerge: True, force: False, partial: False
230 branchmerge: True, force: False, partial: False
231 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
231 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
232 b: remote created -> g
232 b: remote created -> g
233 rev: versions differ -> m
233 rev: versions differ -> m
234 preserving rev for resolve of rev
234 preserving rev for resolve of rev
235 getting b
235 getting b
236 updating: b 1/2 files (50.00%)
236 updating: b 1/2 files (50.00%)
237 updating: rev 2/2 files (100.00%)
237 updating: rev 2/2 files (100.00%)
238 picked tool 'python ../merge' for rev (binary False symlink False)
238 picked tool 'python ../merge' for rev (binary False symlink False)
239 merging rev
239 merging rev
240 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
240 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
241 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
241 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
242 (branch merge, don't forget to commit)
242 (branch merge, don't forget to commit)
243 --------------
243 --------------
244 M b
244 M b
245 C a
245 C a
246 --------------
246 --------------
247
247
248 $ tm "nc a b" " " " " "6 nothing"
248 $ tm "nc a b" " " " " "6 nothing"
249 created new head
249 created new head
250 --------------
250 --------------
251 test L:nc a b R: W: - 6 nothing
251 test L:nc a b R: W: - 6 nothing
252 --------------
252 --------------
253 searching for copies back to rev 1
253 searching for copies back to rev 1
254 unmatched files in local:
254 unmatched files in local:
255 b
255 b
256 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
256 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
257 src: 'a' -> dst: 'b'
257 src: 'a' -> dst: 'b'
258 checking for directory renames
258 checking for directory renames
259 resolving manifests
259 resolving manifests
260 branchmerge: True, force: False, partial: False
260 branchmerge: True, force: False, partial: False
261 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
261 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
262 rev: versions differ -> m
262 rev: versions differ -> m
263 preserving rev for resolve of rev
263 preserving rev for resolve of rev
264 updating: rev 1/1 files (100.00%)
264 updating: rev 1/1 files (100.00%)
265 picked tool 'python ../merge' for rev (binary False symlink False)
265 picked tool 'python ../merge' for rev (binary False symlink False)
266 merging rev
266 merging rev
267 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
267 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
268 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
268 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
269 (branch merge, don't forget to commit)
269 (branch merge, don't forget to commit)
270 --------------
270 --------------
271 C a
271 C a
272 C b
272 C b
273 --------------
273 --------------
274
274
275 $ tm " " "nm a b" " " "7 get b"
275 $ tm " " "nm a b" " " "7 get b"
276 created new head
276 created new head
277 --------------
277 --------------
278 test L: R:nm a b W: - 7 get b
278 test L: R:nm a b W: - 7 get b
279 --------------
279 --------------
280 searching for copies back to rev 1
280 searching for copies back to rev 1
281 unmatched files in other:
281 unmatched files in other:
282 b
282 b
283 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
283 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
284 src: 'a' -> dst: 'b'
284 src: 'a' -> dst: 'b'
285 checking for directory renames
285 checking for directory renames
286 resolving manifests
286 resolving manifests
287 branchmerge: True, force: False, partial: False
287 branchmerge: True, force: False, partial: False
288 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
288 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
289 a: other deleted -> r
289 a: other deleted -> r
290 b: remote created -> g
290 b: remote created -> g
291 rev: versions differ -> m
291 rev: versions differ -> m
292 preserving rev for resolve of rev
292 preserving rev for resolve of rev
293 removing a
293 removing a
294 updating: a 1/3 files (33.33%)
294 updating: a 1/3 files (33.33%)
295 getting b
295 getting b
296 updating: b 2/3 files (66.67%)
296 updating: b 2/3 files (66.67%)
297 updating: rev 3/3 files (100.00%)
297 updating: rev 3/3 files (100.00%)
298 picked tool 'python ../merge' for rev (binary False symlink False)
298 picked tool 'python ../merge' for rev (binary False symlink False)
299 merging rev
299 merging rev
300 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
300 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
301 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
301 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
302 (branch merge, don't forget to commit)
302 (branch merge, don't forget to commit)
303 --------------
303 --------------
304 M b
304 M b
305 --------------
305 --------------
306
306
307 $ tm "nm a b" " " " " "8 nothing"
307 $ tm "nm a b" " " " " "8 nothing"
308 created new head
308 created new head
309 --------------
309 --------------
310 test L:nm a b R: W: - 8 nothing
310 test L:nm a b R: W: - 8 nothing
311 --------------
311 --------------
312 searching for copies back to rev 1
312 searching for copies back to rev 1
313 unmatched files in local:
313 unmatched files in local:
314 b
314 b
315 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
315 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
316 src: 'a' -> dst: 'b'
316 src: 'a' -> dst: 'b'
317 checking for directory renames
317 checking for directory renames
318 resolving manifests
318 resolving manifests
319 branchmerge: True, force: False, partial: False
319 branchmerge: True, force: False, partial: False
320 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
320 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
321 rev: versions differ -> m
321 rev: versions differ -> m
322 preserving rev for resolve of rev
322 preserving rev for resolve of rev
323 updating: rev 1/1 files (100.00%)
323 updating: rev 1/1 files (100.00%)
324 picked tool 'python ../merge' for rev (binary False symlink False)
324 picked tool 'python ../merge' for rev (binary False symlink False)
325 merging rev
325 merging rev
326 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
326 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
327 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
327 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
328 (branch merge, don't forget to commit)
328 (branch merge, don't forget to commit)
329 --------------
329 --------------
330 C b
330 C b
331 --------------
331 --------------
332
332
333 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
333 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
334 created new head
334 created new head
335 --------------
335 --------------
336 test L:um a b R:um a b W: - 9 do merge with ancestor in a
336 test L:um a b R:um a b W: - 9 do merge with ancestor in a
337 --------------
337 --------------
338 searching for copies back to rev 1
338 searching for copies back to rev 1
339 unmatched files new in both:
339 unmatched files new in both:
340 b
340 b
341 resolving manifests
341 resolving manifests
342 branchmerge: True, force: False, partial: False
342 branchmerge: True, force: False, partial: False
343 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
343 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
344 b: versions differ -> m
344 b: versions differ -> m
345 preserving b for resolve of b
345 preserving b for resolve of b
346 rev: versions differ -> m
346 rev: versions differ -> m
347 preserving rev for resolve of rev
347 preserving rev for resolve of rev
348 updating: b 1/2 files (50.00%)
348 updating: b 1/2 files (50.00%)
349 picked tool 'python ../merge' for b (binary False symlink False)
349 picked tool 'python ../merge' for b (binary False symlink False)
350 merging b
350 merging b
351 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
351 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
352 updating: rev 2/2 files (100.00%)
352 updating: rev 2/2 files (100.00%)
353 picked tool 'python ../merge' for rev (binary False symlink False)
353 picked tool 'python ../merge' for rev (binary False symlink False)
354 merging rev
354 merging rev
355 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
355 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
356 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
356 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
357 (branch merge, don't forget to commit)
357 (branch merge, don't forget to commit)
358 --------------
358 --------------
359 M b
359 M b
360 --------------
360 --------------
361
361
362
362
363 m "um a c" "um x c" " " "10 do merge with no ancestor"
363 m "um a c" "um x c" " " "10 do merge with no ancestor"
364
364
365 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
365 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
366 created new head
366 created new head
367 --------------
367 --------------
368 test L:nm a b R:nm a c W: - 11 get c, keep b
368 test L:nm a b R:nm a c W: - 11 get c, keep b
369 --------------
369 --------------
370 searching for copies back to rev 1
370 searching for copies back to rev 1
371 unmatched files in local:
371 unmatched files in local:
372 b
372 b
373 unmatched files in other:
373 unmatched files in other:
374 c
374 c
375 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
375 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
376 src: 'a' -> dst: 'b' !
376 src: 'a' -> dst: 'b' !
377 src: 'a' -> dst: 'c' !
377 src: 'a' -> dst: 'c' !
378 checking for directory renames
378 checking for directory renames
379 resolving manifests
379 resolving manifests
380 branchmerge: True, force: False, partial: False
380 branchmerge: True, force: False, partial: False
381 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
381 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
382 a: divergent renames -> dr
383 c: remote created -> g
382 c: remote created -> g
384 rev: versions differ -> m
383 rev: versions differ -> m
385 preserving rev for resolve of rev
384 preserving rev for resolve of rev
385 a: divergent renames -> dr
386 getting c
386 getting c
387 updating: c 1/3 files (33.33%)
387 updating: c 1/3 files (33.33%)
388 updating: a 2/3 files (66.67%)
388 updating: rev 2/3 files (66.67%)
389 picked tool 'python ../merge' for rev (binary False symlink False)
390 merging rev
391 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
392 updating: a 3/3 files (100.00%)
389 note: possible conflict - a was renamed multiple times to:
393 note: possible conflict - a was renamed multiple times to:
390 b
394 b
391 c
395 c
392 updating: rev 3/3 files (100.00%)
393 picked tool 'python ../merge' for rev (binary False symlink False)
394 merging rev
395 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
396 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
396 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
397 (branch merge, don't forget to commit)
397 (branch merge, don't forget to commit)
398 --------------
398 --------------
399 M c
399 M c
400 C b
400 C b
401 --------------
401 --------------
402
402
403 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
403 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
404 created new head
404 created new head
405 --------------
405 --------------
406 test L:nc a b R:up b W: - 12 merge b no ancestor
406 test L:nc a b R:up b W: - 12 merge b no ancestor
407 --------------
407 --------------
408 searching for copies back to rev 1
408 searching for copies back to rev 1
409 unmatched files new in both:
409 unmatched files new in both:
410 b
410 b
411 resolving manifests
411 resolving manifests
412 branchmerge: True, force: False, partial: False
412 branchmerge: True, force: False, partial: False
413 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
413 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
414 b: versions differ -> m
414 b: versions differ -> m
415 preserving b for resolve of b
415 preserving b for resolve of b
416 rev: versions differ -> m
416 rev: versions differ -> m
417 preserving rev for resolve of rev
417 preserving rev for resolve of rev
418 updating: b 1/2 files (50.00%)
418 updating: b 1/2 files (50.00%)
419 picked tool 'python ../merge' for b (binary False symlink False)
419 picked tool 'python ../merge' for b (binary False symlink False)
420 merging b
420 merging b
421 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
421 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
422 updating: rev 2/2 files (100.00%)
422 updating: rev 2/2 files (100.00%)
423 picked tool 'python ../merge' for rev (binary False symlink False)
423 picked tool 'python ../merge' for rev (binary False symlink False)
424 merging rev
424 merging rev
425 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
425 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
426 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
426 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
427 (branch merge, don't forget to commit)
427 (branch merge, don't forget to commit)
428 --------------
428 --------------
429 M b
429 M b
430 C a
430 C a
431 --------------
431 --------------
432
432
433 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
433 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
434 created new head
434 created new head
435 --------------
435 --------------
436 test L:up b R:nm a b W: - 13 merge b no ancestor
436 test L:up b R:nm a b W: - 13 merge b no ancestor
437 --------------
437 --------------
438 searching for copies back to rev 1
438 searching for copies back to rev 1
439 unmatched files new in both:
439 unmatched files new in both:
440 b
440 b
441 resolving manifests
441 resolving manifests
442 branchmerge: True, force: False, partial: False
442 branchmerge: True, force: False, partial: False
443 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
443 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
444 a: other deleted -> r
444 a: other deleted -> r
445 b: versions differ -> m
445 b: versions differ -> m
446 preserving b for resolve of b
446 preserving b for resolve of b
447 rev: versions differ -> m
447 rev: versions differ -> m
448 preserving rev for resolve of rev
448 preserving rev for resolve of rev
449 removing a
449 removing a
450 updating: a 1/3 files (33.33%)
450 updating: a 1/3 files (33.33%)
451 updating: b 2/3 files (66.67%)
451 updating: b 2/3 files (66.67%)
452 picked tool 'python ../merge' for b (binary False symlink False)
452 picked tool 'python ../merge' for b (binary False symlink False)
453 merging b
453 merging b
454 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
454 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
455 updating: rev 3/3 files (100.00%)
455 updating: rev 3/3 files (100.00%)
456 picked tool 'python ../merge' for rev (binary False symlink False)
456 picked tool 'python ../merge' for rev (binary False symlink False)
457 merging rev
457 merging rev
458 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
458 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
459 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
459 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
460 (branch merge, don't forget to commit)
460 (branch merge, don't forget to commit)
461 --------------
461 --------------
462 M b
462 M b
463 --------------
463 --------------
464
464
465 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
465 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
466 created new head
466 created new head
467 --------------
467 --------------
468 test L:nc a b R:up a b W: - 14 merge b no ancestor
468 test L:nc a b R:up a b W: - 14 merge b no ancestor
469 --------------
469 --------------
470 searching for copies back to rev 1
470 searching for copies back to rev 1
471 unmatched files new in both:
471 unmatched files new in both:
472 b
472 b
473 resolving manifests
473 resolving manifests
474 branchmerge: True, force: False, partial: False
474 branchmerge: True, force: False, partial: False
475 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
475 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
476 a: remote is newer -> g
476 a: remote is newer -> g
477 b: versions differ -> m
477 b: versions differ -> m
478 preserving b for resolve of b
478 preserving b for resolve of b
479 rev: versions differ -> m
479 rev: versions differ -> m
480 preserving rev for resolve of rev
480 preserving rev for resolve of rev
481 getting a
481 getting a
482 updating: a 1/3 files (33.33%)
482 updating: a 1/3 files (33.33%)
483 updating: b 2/3 files (66.67%)
483 updating: b 2/3 files (66.67%)
484 picked tool 'python ../merge' for b (binary False symlink False)
484 picked tool 'python ../merge' for b (binary False symlink False)
485 merging b
485 merging b
486 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
486 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
487 updating: rev 3/3 files (100.00%)
487 updating: rev 3/3 files (100.00%)
488 picked tool 'python ../merge' for rev (binary False symlink False)
488 picked tool 'python ../merge' for rev (binary False symlink False)
489 merging rev
489 merging rev
490 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
490 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
491 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
491 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
492 (branch merge, don't forget to commit)
492 (branch merge, don't forget to commit)
493 --------------
493 --------------
494 M a
494 M a
495 M b
495 M b
496 --------------
496 --------------
497
497
498 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
498 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
499 created new head
499 created new head
500 --------------
500 --------------
501 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
501 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
502 --------------
502 --------------
503 searching for copies back to rev 1
503 searching for copies back to rev 1
504 unmatched files new in both:
504 unmatched files new in both:
505 b
505 b
506 resolving manifests
506 resolving manifests
507 branchmerge: True, force: False, partial: False
507 branchmerge: True, force: False, partial: False
508 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
508 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
509 a: other deleted -> r
509 a: other deleted -> r
510 b: versions differ -> m
510 b: versions differ -> m
511 preserving b for resolve of b
511 preserving b for resolve of b
512 rev: versions differ -> m
512 rev: versions differ -> m
513 preserving rev for resolve of rev
513 preserving rev for resolve of rev
514 removing a
514 removing a
515 updating: a 1/3 files (33.33%)
515 updating: a 1/3 files (33.33%)
516 updating: b 2/3 files (66.67%)
516 updating: b 2/3 files (66.67%)
517 picked tool 'python ../merge' for b (binary False symlink False)
517 picked tool 'python ../merge' for b (binary False symlink False)
518 merging b
518 merging b
519 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
519 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
520 updating: rev 3/3 files (100.00%)
520 updating: rev 3/3 files (100.00%)
521 picked tool 'python ../merge' for rev (binary False symlink False)
521 picked tool 'python ../merge' for rev (binary False symlink False)
522 merging rev
522 merging rev
523 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
523 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
524 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
524 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
525 (branch merge, don't forget to commit)
525 (branch merge, don't forget to commit)
526 --------------
526 --------------
527 M b
527 M b
528 --------------
528 --------------
529
529
530 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
530 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
531 created new head
531 created new head
532 --------------
532 --------------
533 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
533 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
534 --------------
534 --------------
535 searching for copies back to rev 1
535 searching for copies back to rev 1
536 unmatched files new in both:
536 unmatched files new in both:
537 b
537 b
538 resolving manifests
538 resolving manifests
539 branchmerge: True, force: False, partial: False
539 branchmerge: True, force: False, partial: False
540 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
540 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
541 a: remote is newer -> g
541 a: remote is newer -> g
542 b: versions differ -> m
542 b: versions differ -> m
543 preserving b for resolve of b
543 preserving b for resolve of b
544 rev: versions differ -> m
544 rev: versions differ -> m
545 preserving rev for resolve of rev
545 preserving rev for resolve of rev
546 getting a
546 getting a
547 updating: a 1/3 files (33.33%)
547 updating: a 1/3 files (33.33%)
548 updating: b 2/3 files (66.67%)
548 updating: b 2/3 files (66.67%)
549 picked tool 'python ../merge' for b (binary False symlink False)
549 picked tool 'python ../merge' for b (binary False symlink False)
550 merging b
550 merging b
551 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
551 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
552 updating: rev 3/3 files (100.00%)
552 updating: rev 3/3 files (100.00%)
553 picked tool 'python ../merge' for rev (binary False symlink False)
553 picked tool 'python ../merge' for rev (binary False symlink False)
554 merging rev
554 merging rev
555 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
555 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
556 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
556 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
557 (branch merge, don't forget to commit)
557 (branch merge, don't forget to commit)
558 --------------
558 --------------
559 M a
559 M a
560 M b
560 M b
561 --------------
561 --------------
562
562
563 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
563 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
564 created new head
564 created new head
565 --------------
565 --------------
566 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
566 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
567 --------------
567 --------------
568 searching for copies back to rev 1
568 searching for copies back to rev 1
569 unmatched files new in both:
569 unmatched files new in both:
570 b
570 b
571 resolving manifests
571 resolving manifests
572 branchmerge: True, force: False, partial: False
572 branchmerge: True, force: False, partial: False
573 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
573 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
574 a: keep -> k
574 a: keep -> k
575 b: versions differ -> m
575 b: versions differ -> m
576 preserving b for resolve of b
576 preserving b for resolve of b
577 rev: versions differ -> m
577 rev: versions differ -> m
578 preserving rev for resolve of rev
578 preserving rev for resolve of rev
579 updating: b 1/2 files (50.00%)
579 updating: b 1/2 files (50.00%)
580 picked tool 'python ../merge' for b (binary False symlink False)
580 picked tool 'python ../merge' for b (binary False symlink False)
581 merging b
581 merging b
582 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
582 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
583 updating: rev 2/2 files (100.00%)
583 updating: rev 2/2 files (100.00%)
584 picked tool 'python ../merge' for rev (binary False symlink False)
584 picked tool 'python ../merge' for rev (binary False symlink False)
585 merging rev
585 merging rev
586 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
586 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
587 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
587 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
588 (branch merge, don't forget to commit)
588 (branch merge, don't forget to commit)
589 --------------
589 --------------
590 M b
590 M b
591 C a
591 C a
592 --------------
592 --------------
593
593
594 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
594 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
595 created new head
595 created new head
596 --------------
596 --------------
597 test L:nm a b R:up a b W: - 18 merge b no ancestor
597 test L:nm a b R:up a b W: - 18 merge b no ancestor
598 --------------
598 --------------
599 searching for copies back to rev 1
599 searching for copies back to rev 1
600 unmatched files new in both:
600 unmatched files new in both:
601 b
601 b
602 resolving manifests
602 resolving manifests
603 branchmerge: True, force: False, partial: False
603 branchmerge: True, force: False, partial: False
604 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
604 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
605 remote changed a which local deleted
605 remote changed a which local deleted
606 use (c)hanged version or leave (d)eleted? c
606 use (c)hanged version or leave (d)eleted? c
607 a: prompt recreating -> g
607 a: prompt recreating -> g
608 b: versions differ -> m
608 b: versions differ -> m
609 preserving b for resolve of b
609 preserving b for resolve of b
610 rev: versions differ -> m
610 rev: versions differ -> m
611 preserving rev for resolve of rev
611 preserving rev for resolve of rev
612 getting a
612 getting a
613 updating: a 1/3 files (33.33%)
613 updating: a 1/3 files (33.33%)
614 updating: b 2/3 files (66.67%)
614 updating: b 2/3 files (66.67%)
615 picked tool 'python ../merge' for b (binary False symlink False)
615 picked tool 'python ../merge' for b (binary False symlink False)
616 merging b
616 merging b
617 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
617 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
618 updating: rev 3/3 files (100.00%)
618 updating: rev 3/3 files (100.00%)
619 picked tool 'python ../merge' for rev (binary False symlink False)
619 picked tool 'python ../merge' for rev (binary False symlink False)
620 merging rev
620 merging rev
621 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
621 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
622 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
622 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
623 (branch merge, don't forget to commit)
623 (branch merge, don't forget to commit)
624 --------------
624 --------------
625 M a
625 M a
626 M b
626 M b
627 --------------
627 --------------
628
628
629 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
629 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
630 created new head
630 created new head
631 --------------
631 --------------
632 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
632 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
633 --------------
633 --------------
634 searching for copies back to rev 1
634 searching for copies back to rev 1
635 unmatched files new in both:
635 unmatched files new in both:
636 b
636 b
637 resolving manifests
637 resolving manifests
638 branchmerge: True, force: False, partial: False
638 branchmerge: True, force: False, partial: False
639 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
639 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
640 local changed a which remote deleted
640 local changed a which remote deleted
641 use (c)hanged version or (d)elete? c
641 use (c)hanged version or (d)elete? c
642 a: prompt keep -> a
642 a: prompt keep -> a
643 b: versions differ -> m
643 b: versions differ -> m
644 preserving b for resolve of b
644 preserving b for resolve of b
645 rev: versions differ -> m
645 rev: versions differ -> m
646 preserving rev for resolve of rev
646 preserving rev for resolve of rev
647 updating: a 1/3 files (33.33%)
647 updating: a 1/3 files (33.33%)
648 updating: b 2/3 files (66.67%)
648 updating: b 2/3 files (66.67%)
649 picked tool 'python ../merge' for b (binary False symlink False)
649 picked tool 'python ../merge' for b (binary False symlink False)
650 merging b
650 merging b
651 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
651 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
652 updating: rev 3/3 files (100.00%)
652 updating: rev 3/3 files (100.00%)
653 picked tool 'python ../merge' for rev (binary False symlink False)
653 picked tool 'python ../merge' for rev (binary False symlink False)
654 merging rev
654 merging rev
655 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
655 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
656 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
656 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
657 (branch merge, don't forget to commit)
657 (branch merge, don't forget to commit)
658 --------------
658 --------------
659 M b
659 M b
660 C a
660 C a
661 --------------
661 --------------
662
662
663 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
663 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
664 created new head
664 created new head
665 --------------
665 --------------
666 test L:up a R:um a b W: - 20 merge a and b to b, remove a
666 test L:up a R:um a b W: - 20 merge a and b to b, remove a
667 --------------
667 --------------
668 searching for copies back to rev 1
668 searching for copies back to rev 1
669 unmatched files in other:
669 unmatched files in other:
670 b
670 b
671 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
671 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
672 src: 'a' -> dst: 'b' *
672 src: 'a' -> dst: 'b' *
673 checking for directory renames
673 checking for directory renames
674 resolving manifests
674 resolving manifests
675 branchmerge: True, force: False, partial: False
675 branchmerge: True, force: False, partial: False
676 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
676 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
677 b: remote moved from a -> m
677 b: remote moved from a -> m
678 preserving a for resolve of b
678 preserving a for resolve of b
679 rev: versions differ -> m
679 rev: versions differ -> m
680 preserving rev for resolve of rev
680 preserving rev for resolve of rev
681 removing a
681 removing a
682 updating: b 1/2 files (50.00%)
682 updating: b 1/2 files (50.00%)
683 picked tool 'python ../merge' for b (binary False symlink False)
683 picked tool 'python ../merge' for b (binary False symlink False)
684 merging a and b to b
684 merging a and b to b
685 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
685 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
686 updating: rev 2/2 files (100.00%)
686 updating: rev 2/2 files (100.00%)
687 picked tool 'python ../merge' for rev (binary False symlink False)
687 picked tool 'python ../merge' for rev (binary False symlink False)
688 merging rev
688 merging rev
689 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
689 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
690 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
690 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
691 (branch merge, don't forget to commit)
691 (branch merge, don't forget to commit)
692 --------------
692 --------------
693 M b
693 M b
694 a
694 a
695 --------------
695 --------------
696
696
697 $ tm "um a b" "up a " " " "21 merge a and b to b"
697 $ tm "um a b" "up a " " " "21 merge a and b to b"
698 created new head
698 created new head
699 --------------
699 --------------
700 test L:um a b R:up a W: - 21 merge a and b to b
700 test L:um a b R:up a W: - 21 merge a and b to b
701 --------------
701 --------------
702 searching for copies back to rev 1
702 searching for copies back to rev 1
703 unmatched files in local:
703 unmatched files in local:
704 b
704 b
705 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
705 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
706 src: 'a' -> dst: 'b' *
706 src: 'a' -> dst: 'b' *
707 checking for directory renames
707 checking for directory renames
708 resolving manifests
708 resolving manifests
709 branchmerge: True, force: False, partial: False
709 branchmerge: True, force: False, partial: False
710 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
710 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
711 b: local copied/moved from a -> m
711 b: local copied/moved from a -> m
712 preserving b for resolve of b
712 preserving b for resolve of b
713 rev: versions differ -> m
713 rev: versions differ -> m
714 preserving rev for resolve of rev
714 preserving rev for resolve of rev
715 updating: b 1/2 files (50.00%)
715 updating: b 1/2 files (50.00%)
716 picked tool 'python ../merge' for b (binary False symlink False)
716 picked tool 'python ../merge' for b (binary False symlink False)
717 merging b and a to b
717 merging b and a to b
718 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
718 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
719 updating: rev 2/2 files (100.00%)
719 updating: rev 2/2 files (100.00%)
720 picked tool 'python ../merge' for rev (binary False symlink False)
720 picked tool 'python ../merge' for rev (binary False symlink False)
721 merging rev
721 merging rev
722 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
722 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
723 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
723 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
724 (branch merge, don't forget to commit)
724 (branch merge, don't forget to commit)
725 --------------
725 --------------
726 M b
726 M b
727 a
727 a
728 --------------
728 --------------
729
729
730
730
731 m "nm a b" "um x a" " " "22 get a, keep b"
731 m "nm a b" "um x a" " " "22 get a, keep b"
732
732
733 $ tm "nm a b" "up a c" " " "23 get c, keep b"
733 $ tm "nm a b" "up a c" " " "23 get c, keep b"
734 created new head
734 created new head
735 --------------
735 --------------
736 test L:nm a b R:up a c W: - 23 get c, keep b
736 test L:nm a b R:up a c W: - 23 get c, keep b
737 --------------
737 --------------
738 searching for copies back to rev 1
738 searching for copies back to rev 1
739 unmatched files in local:
739 unmatched files in local:
740 b
740 b
741 unmatched files in other:
741 unmatched files in other:
742 c
742 c
743 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
743 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
744 src: 'a' -> dst: 'b' *
744 src: 'a' -> dst: 'b' *
745 checking for directory renames
745 checking for directory renames
746 resolving manifests
746 resolving manifests
747 branchmerge: True, force: False, partial: False
747 branchmerge: True, force: False, partial: False
748 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
748 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
749 c: remote created -> g
749 b: local copied/moved from a -> m
750 b: local copied/moved from a -> m
750 preserving b for resolve of b
751 preserving b for resolve of b
751 c: remote created -> g
752 rev: versions differ -> m
752 rev: versions differ -> m
753 preserving rev for resolve of rev
753 preserving rev for resolve of rev
754 getting c
754 getting c
755 updating: c 1/3 files (33.33%)
755 updating: c 1/3 files (33.33%)
756 updating: b 2/3 files (66.67%)
756 updating: b 2/3 files (66.67%)
757 picked tool 'python ../merge' for b (binary False symlink False)
757 picked tool 'python ../merge' for b (binary False symlink False)
758 merging b and a to b
758 merging b and a to b
759 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
759 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
760 premerge successful
760 premerge successful
761 updating: rev 3/3 files (100.00%)
761 updating: rev 3/3 files (100.00%)
762 picked tool 'python ../merge' for rev (binary False symlink False)
762 picked tool 'python ../merge' for rev (binary False symlink False)
763 merging rev
763 merging rev
764 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
764 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
765 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
765 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
766 (branch merge, don't forget to commit)
766 (branch merge, don't forget to commit)
767 --------------
767 --------------
768 M b
768 M b
769 a
769 a
770 M c
770 M c
771 --------------
771 --------------
772
772
773
773
774 $ cd ..
774 $ cd ..
775
775
776
776
777 Systematic and terse testing of merge merges and ancestor calculation:
777 Systematic and terse testing of merge merges and ancestor calculation:
778
778
779 Expected result:
779 Expected result:
780
780
781 \ a m1 m2 dst
781 \ a m1 m2 dst
782 0 - f f f "versions differ"
782 0 - f f f "versions differ"
783 1 f g g g "versions differ"
783 1 f g g g "versions differ"
784 2 f f f f "versions differ"
784 2 f f f f "versions differ"
785 3 f f g f+g "remote copied to " + f
785 3 f f g f+g "remote copied to " + f
786 4 f f g g "remote moved to " + f
786 4 f f g g "remote moved to " + f
787 5 f g f f+g "local copied to " + f2
787 5 f g f f+g "local copied to " + f2
788 6 f g f g "local moved to " + f2
788 6 f g f g "local moved to " + f2
789 7 - (f) f f "remote differs from untracked local"
789 7 - (f) f f "remote differs from untracked local"
790 8 f (f) f f "remote differs from untracked local"
790 8 f (f) f f "remote differs from untracked local"
791
791
792 $ hg init ancestortest
792 $ hg init ancestortest
793 $ cd ancestortest
793 $ cd ancestortest
794 $ for x in 1 2 3 4 5 6 8; do mkdir $x; echo a > $x/f; done
794 $ for x in 1 2 3 4 5 6 8; do mkdir $x; echo a > $x/f; done
795 $ hg ci -Aqm "a"
795 $ hg ci -Aqm "a"
796 $ mkdir 0
796 $ mkdir 0
797 $ touch 0/f
797 $ touch 0/f
798 $ hg mv 1/f 1/g
798 $ hg mv 1/f 1/g
799 $ hg cp 5/f 5/g
799 $ hg cp 5/f 5/g
800 $ hg mv 6/f 6/g
800 $ hg mv 6/f 6/g
801 $ hg rm 8/f
801 $ hg rm 8/f
802 $ for x in */*; do echo m1 > $x; done
802 $ for x in */*; do echo m1 > $x; done
803 $ hg ci -Aqm "m1"
803 $ hg ci -Aqm "m1"
804 $ hg up -qr0
804 $ hg up -qr0
805 $ mkdir 0 7
805 $ mkdir 0 7
806 $ touch 0/f 7/f
806 $ touch 0/f 7/f
807 $ hg mv 1/f 1/g
807 $ hg mv 1/f 1/g
808 $ hg cp 3/f 3/g
808 $ hg cp 3/f 3/g
809 $ hg mv 4/f 4/g
809 $ hg mv 4/f 4/g
810 $ for x in */*; do echo m2 > $x; done
810 $ for x in */*; do echo m2 > $x; done
811 $ hg ci -Aqm "m2"
811 $ hg ci -Aqm "m2"
812 $ hg up -qr1
812 $ hg up -qr1
813 $ mkdir 7 8
813 $ mkdir 7 8
814 $ echo m > 7/f
814 $ echo m > 7/f
815 $ echo m > 8/f
815 $ echo m > 8/f
816 $ hg merge -f --tool internal:dump -v --debug -r2 | sed '/^updating:/,$d' 2> /dev/null
816 $ hg merge -f --tool internal:dump -v --debug -r2 | sed '/^updating:/,$d' 2> /dev/null
817 searching for copies back to rev 1
817 searching for copies back to rev 1
818 unmatched files in local:
818 unmatched files in local:
819 5/g
819 5/g
820 6/g
820 6/g
821 unmatched files in other:
821 unmatched files in other:
822 3/g
822 3/g
823 4/g
823 4/g
824 7/f
824 7/f
825 unmatched files new in both:
825 unmatched files new in both:
826 0/f
826 0/f
827 1/g
827 1/g
828 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
828 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
829 src: '3/f' -> dst: '3/g' *
829 src: '3/f' -> dst: '3/g' *
830 src: '4/f' -> dst: '4/g' *
830 src: '4/f' -> dst: '4/g' *
831 src: '5/f' -> dst: '5/g' *
831 src: '5/f' -> dst: '5/g' *
832 src: '6/f' -> dst: '6/g' *
832 src: '6/f' -> dst: '6/g' *
833 checking for directory renames
833 checking for directory renames
834 resolving manifests
834 resolving manifests
835 branchmerge: True, force: True, partial: False
835 branchmerge: True, force: True, partial: False
836 ancestor: e6cb3cf11019, local: ec44bf929ab5+, remote: c62e34d0b898
836 ancestor: e6cb3cf11019, local: ec44bf929ab5+, remote: c62e34d0b898
837 remote changed 8/f which local deleted
837 remote changed 8/f which local deleted
838 use (c)hanged version or leave (d)eleted? c
838 use (c)hanged version or leave (d)eleted? c
839 8/f: prompt recreating -> g
839 0/f: versions differ -> m
840 0/f: versions differ -> m
840 preserving 0/f for resolve of 0/f
841 preserving 0/f for resolve of 0/f
841 1/g: versions differ -> m
842 1/g: versions differ -> m
842 preserving 1/g for resolve of 1/g
843 preserving 1/g for resolve of 1/g
843 2/f: versions differ -> m
844 2/f: versions differ -> m
844 preserving 2/f for resolve of 2/f
845 preserving 2/f for resolve of 2/f
845 3/f: versions differ -> m
846 3/f: versions differ -> m
846 preserving 3/f for resolve of 3/f
847 preserving 3/f for resolve of 3/f
847 3/g: remote copied from 3/f -> m
848 3/g: remote copied from 3/f -> m
848 preserving 3/f for resolve of 3/g
849 preserving 3/f for resolve of 3/g
849 4/g: remote moved from 4/f -> m
850 4/g: remote moved from 4/f -> m
850 preserving 4/f for resolve of 4/g
851 preserving 4/f for resolve of 4/g
851 5/f: versions differ -> m
852 5/f: versions differ -> m
852 preserving 5/f for resolve of 5/f
853 preserving 5/f for resolve of 5/f
853 5/g: local copied/moved from 5/f -> m
854 5/g: local copied/moved from 5/f -> m
854 preserving 5/g for resolve of 5/g
855 preserving 5/g for resolve of 5/g
855 6/g: local copied/moved from 6/f -> m
856 6/g: local copied/moved from 6/f -> m
856 preserving 6/g for resolve of 6/g
857 preserving 6/g for resolve of 6/g
857 7/f: remote differs from untracked local -> m
858 7/f: remote differs from untracked local -> m
858 preserving 7/f for resolve of 7/f
859 preserving 7/f for resolve of 7/f
859 8/f: prompt recreating -> g
860 removing 4/f
860 removing 4/f
861 getting 8/f
861 getting 8/f
862 $ hg mani
862 $ hg mani
863 0/f
863 0/f
864 1/g
864 1/g
865 2/f
865 2/f
866 3/f
866 3/f
867 4/f
867 4/f
868 5/f
868 5/f
869 5/g
869 5/g
870 6/g
870 6/g
871 $ for f in */*; do echo $f:; cat $f; done
871 $ for f in */*; do echo $f:; cat $f; done
872 0/f:
872 0/f:
873 m1
873 m1
874 0/f.base:
874 0/f.base:
875 0/f.local:
875 0/f.local:
876 m1
876 m1
877 0/f.orig:
877 0/f.orig:
878 m1
878 m1
879 0/f.other:
879 0/f.other:
880 m2
880 m2
881 1/g:
881 1/g:
882 m1
882 m1
883 1/g.base:
883 1/g.base:
884 a
884 a
885 1/g.local:
885 1/g.local:
886 m1
886 m1
887 1/g.orig:
887 1/g.orig:
888 m1
888 m1
889 1/g.other:
889 1/g.other:
890 m2
890 m2
891 2/f:
891 2/f:
892 m1
892 m1
893 2/f.base:
893 2/f.base:
894 a
894 a
895 2/f.local:
895 2/f.local:
896 m1
896 m1
897 2/f.orig:
897 2/f.orig:
898 m1
898 m1
899 2/f.other:
899 2/f.other:
900 m2
900 m2
901 3/f:
901 3/f:
902 m1
902 m1
903 3/f.base:
903 3/f.base:
904 a
904 a
905 3/f.local:
905 3/f.local:
906 m1
906 m1
907 3/f.orig:
907 3/f.orig:
908 m1
908 m1
909 3/f.other:
909 3/f.other:
910 m2
910 m2
911 3/g:
911 3/g:
912 m1
912 m1
913 3/g.base:
913 3/g.base:
914 a
914 a
915 3/g.local:
915 3/g.local:
916 m1
916 m1
917 3/g.orig:
917 3/g.orig:
918 m1
918 m1
919 3/g.other:
919 3/g.other:
920 m2
920 m2
921 4/g:
921 4/g:
922 m1
922 m1
923 4/g.base:
923 4/g.base:
924 a
924 a
925 4/g.local:
925 4/g.local:
926 m1
926 m1
927 4/g.orig:
927 4/g.orig:
928 m1
928 m1
929 4/g.other:
929 4/g.other:
930 m2
930 m2
931 5/f:
931 5/f:
932 m1
932 m1
933 5/f.base:
933 5/f.base:
934 a
934 a
935 5/f.local:
935 5/f.local:
936 m1
936 m1
937 5/f.orig:
937 5/f.orig:
938 m1
938 m1
939 5/f.other:
939 5/f.other:
940 m2
940 m2
941 5/g:
941 5/g:
942 m1
942 m1
943 5/g.base:
943 5/g.base:
944 a
944 a
945 5/g.local:
945 5/g.local:
946 m1
946 m1
947 5/g.orig:
947 5/g.orig:
948 m1
948 m1
949 5/g.other:
949 5/g.other:
950 m2
950 m2
951 6/g:
951 6/g:
952 m1
952 m1
953 6/g.base:
953 6/g.base:
954 a
954 a
955 6/g.local:
955 6/g.local:
956 m1
956 m1
957 6/g.orig:
957 6/g.orig:
958 m1
958 m1
959 6/g.other:
959 6/g.other:
960 m2
960 m2
961 7/f:
961 7/f:
962 m
962 m
963 7/f.base:
963 7/f.base:
964 7/f.local:
964 7/f.local:
965 m
965 m
966 7/f.orig:
966 7/f.orig:
967 m
967 m
968 7/f.other:
968 7/f.other:
969 m2
969 m2
970 8/f:
970 8/f:
971 m2
971 m2
972 $ cd ..
972 $ cd ..
@@ -1,241 +1,241 b''
1 $ HGMERGE=true; export HGMERGE
1 $ HGMERGE=true; export HGMERGE
2
2
3 $ hg init r1
3 $ hg init r1
4 $ cd r1
4 $ cd r1
5 $ echo a > a
5 $ echo a > a
6 $ hg addremove
6 $ hg addremove
7 adding a
7 adding a
8 $ hg commit -m "1"
8 $ hg commit -m "1"
9
9
10 $ hg clone . ../r2
10 $ hg clone . ../r2
11 updating to branch default
11 updating to branch default
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 $ cd ../r2
13 $ cd ../r2
14 $ hg up
14 $ hg up
15 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 $ echo abc > a
16 $ echo abc > a
17 $ hg diff --nodates
17 $ hg diff --nodates
18 diff -r c19d34741b0a a
18 diff -r c19d34741b0a a
19 --- a/a
19 --- a/a
20 +++ b/a
20 +++ b/a
21 @@ -1,1 +1,1 @@
21 @@ -1,1 +1,1 @@
22 -a
22 -a
23 +abc
23 +abc
24
24
25 $ cd ../r1
25 $ cd ../r1
26 $ echo b > b
26 $ echo b > b
27 $ echo a2 > a
27 $ echo a2 > a
28 $ hg addremove
28 $ hg addremove
29 adding b
29 adding b
30 $ hg commit -m "2"
30 $ hg commit -m "2"
31
31
32 $ cd ../r2
32 $ cd ../r2
33 $ hg -q pull ../r1
33 $ hg -q pull ../r1
34 $ hg status
34 $ hg status
35 M a
35 M a
36 $ hg parents
36 $ hg parents
37 changeset: 0:c19d34741b0a
37 changeset: 0:c19d34741b0a
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 1
40 summary: 1
41
41
42 $ hg --debug up
42 $ hg --debug up
43 searching for copies back to rev 1
43 searching for copies back to rev 1
44 unmatched files in other:
44 unmatched files in other:
45 b
45 b
46 resolving manifests
46 resolving manifests
47 branchmerge: False, force: False, partial: False
47 branchmerge: False, force: False, partial: False
48 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
48 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
49 b: remote created -> g
49 a: versions differ -> m
50 a: versions differ -> m
50 preserving a for resolve of a
51 preserving a for resolve of a
51 b: remote created -> g
52 getting b
52 getting b
53 updating: b 1/2 files (50.00%)
53 updating: b 1/2 files (50.00%)
54 updating: a 2/2 files (100.00%)
54 updating: a 2/2 files (100.00%)
55 picked tool 'true' for a (binary False symlink False)
55 picked tool 'true' for a (binary False symlink False)
56 merging a
56 merging a
57 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
57 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
58 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
58 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
59 $ hg parents
59 $ hg parents
60 changeset: 1:1e71731e6fbb
60 changeset: 1:1e71731e6fbb
61 tag: tip
61 tag: tip
62 user: test
62 user: test
63 date: Thu Jan 01 00:00:00 1970 +0000
63 date: Thu Jan 01 00:00:00 1970 +0000
64 summary: 2
64 summary: 2
65
65
66 $ hg --debug up 0
66 $ hg --debug up 0
67 resolving manifests
67 resolving manifests
68 branchmerge: False, force: False, partial: False
68 branchmerge: False, force: False, partial: False
69 ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
69 ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
70 b: other deleted -> r
70 b: other deleted -> r
71 a: versions differ -> m
71 a: versions differ -> m
72 preserving a for resolve of a
72 preserving a for resolve of a
73 removing b
73 removing b
74 updating: b 1/2 files (50.00%)
74 updating: b 1/2 files (50.00%)
75 updating: a 2/2 files (100.00%)
75 updating: a 2/2 files (100.00%)
76 picked tool 'true' for a (binary False symlink False)
76 picked tool 'true' for a (binary False symlink False)
77 merging a
77 merging a
78 my a@1e71731e6fbb+ other a@c19d34741b0a ancestor a@1e71731e6fbb
78 my a@1e71731e6fbb+ other a@c19d34741b0a ancestor a@1e71731e6fbb
79 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
79 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
80 $ hg parents
80 $ hg parents
81 changeset: 0:c19d34741b0a
81 changeset: 0:c19d34741b0a
82 user: test
82 user: test
83 date: Thu Jan 01 00:00:00 1970 +0000
83 date: Thu Jan 01 00:00:00 1970 +0000
84 summary: 1
84 summary: 1
85
85
86 $ hg --debug merge
86 $ hg --debug merge
87 abort: nothing to merge
87 abort: nothing to merge
88 (use 'hg update' instead)
88 (use 'hg update' instead)
89 [255]
89 [255]
90 $ hg parents
90 $ hg parents
91 changeset: 0:c19d34741b0a
91 changeset: 0:c19d34741b0a
92 user: test
92 user: test
93 date: Thu Jan 01 00:00:00 1970 +0000
93 date: Thu Jan 01 00:00:00 1970 +0000
94 summary: 1
94 summary: 1
95
95
96 $ hg --debug up
96 $ hg --debug up
97 searching for copies back to rev 1
97 searching for copies back to rev 1
98 unmatched files in other:
98 unmatched files in other:
99 b
99 b
100 resolving manifests
100 resolving manifests
101 branchmerge: False, force: False, partial: False
101 branchmerge: False, force: False, partial: False
102 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
102 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
103 b: remote created -> g
103 a: versions differ -> m
104 a: versions differ -> m
104 preserving a for resolve of a
105 preserving a for resolve of a
105 b: remote created -> g
106 getting b
106 getting b
107 updating: b 1/2 files (50.00%)
107 updating: b 1/2 files (50.00%)
108 updating: a 2/2 files (100.00%)
108 updating: a 2/2 files (100.00%)
109 picked tool 'true' for a (binary False symlink False)
109 picked tool 'true' for a (binary False symlink False)
110 merging a
110 merging a
111 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
111 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
112 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
112 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
113 $ hg parents
113 $ hg parents
114 changeset: 1:1e71731e6fbb
114 changeset: 1:1e71731e6fbb
115 tag: tip
115 tag: tip
116 user: test
116 user: test
117 date: Thu Jan 01 00:00:00 1970 +0000
117 date: Thu Jan 01 00:00:00 1970 +0000
118 summary: 2
118 summary: 2
119
119
120 $ hg -v history
120 $ hg -v history
121 changeset: 1:1e71731e6fbb
121 changeset: 1:1e71731e6fbb
122 tag: tip
122 tag: tip
123 user: test
123 user: test
124 date: Thu Jan 01 00:00:00 1970 +0000
124 date: Thu Jan 01 00:00:00 1970 +0000
125 files: a b
125 files: a b
126 description:
126 description:
127 2
127 2
128
128
129
129
130 changeset: 0:c19d34741b0a
130 changeset: 0:c19d34741b0a
131 user: test
131 user: test
132 date: Thu Jan 01 00:00:00 1970 +0000
132 date: Thu Jan 01 00:00:00 1970 +0000
133 files: a
133 files: a
134 description:
134 description:
135 1
135 1
136
136
137
137
138 $ hg diff --nodates
138 $ hg diff --nodates
139 diff -r 1e71731e6fbb a
139 diff -r 1e71731e6fbb a
140 --- a/a
140 --- a/a
141 +++ b/a
141 +++ b/a
142 @@ -1,1 +1,1 @@
142 @@ -1,1 +1,1 @@
143 -a2
143 -a2
144 +abc
144 +abc
145
145
146
146
147 create a second head
147 create a second head
148
148
149 $ cd ../r1
149 $ cd ../r1
150 $ hg up 0
150 $ hg up 0
151 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
151 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
152 $ echo b2 > b
152 $ echo b2 > b
153 $ echo a3 > a
153 $ echo a3 > a
154 $ hg addremove
154 $ hg addremove
155 adding b
155 adding b
156 $ hg commit -m "3"
156 $ hg commit -m "3"
157 created new head
157 created new head
158
158
159 $ cd ../r2
159 $ cd ../r2
160 $ hg -q pull ../r1
160 $ hg -q pull ../r1
161 $ hg status
161 $ hg status
162 M a
162 M a
163 $ hg parents
163 $ hg parents
164 changeset: 1:1e71731e6fbb
164 changeset: 1:1e71731e6fbb
165 user: test
165 user: test
166 date: Thu Jan 01 00:00:00 1970 +0000
166 date: Thu Jan 01 00:00:00 1970 +0000
167 summary: 2
167 summary: 2
168
168
169 $ hg --debug up
169 $ hg --debug up
170 abort: uncommitted changes
170 abort: uncommitted changes
171 (commit and merge, or update --clean to discard changes)
171 (commit and merge, or update --clean to discard changes)
172 [255]
172 [255]
173 $ hg --debug merge
173 $ hg --debug merge
174 abort: uncommitted changes
174 abort: uncommitted changes
175 (use 'hg status' to list changes)
175 (use 'hg status' to list changes)
176 [255]
176 [255]
177 $ hg --debug merge -f
177 $ hg --debug merge -f
178 searching for copies back to rev 1
178 searching for copies back to rev 1
179 unmatched files new in both:
179 unmatched files new in both:
180 b
180 b
181 resolving manifests
181 resolving manifests
182 branchmerge: True, force: True, partial: False
182 branchmerge: True, force: True, partial: False
183 ancestor: c19d34741b0a, local: 1e71731e6fbb+, remote: 83c51d0caff4
183 ancestor: c19d34741b0a, local: 1e71731e6fbb+, remote: 83c51d0caff4
184 a: versions differ -> m
184 a: versions differ -> m
185 preserving a for resolve of a
185 preserving a for resolve of a
186 b: versions differ -> m
186 b: versions differ -> m
187 preserving b for resolve of b
187 preserving b for resolve of b
188 updating: a 1/2 files (50.00%)
188 updating: a 1/2 files (50.00%)
189 picked tool 'true' for a (binary False symlink False)
189 picked tool 'true' for a (binary False symlink False)
190 merging a
190 merging a
191 my a@1e71731e6fbb+ other a@83c51d0caff4 ancestor a@c19d34741b0a
191 my a@1e71731e6fbb+ other a@83c51d0caff4 ancestor a@c19d34741b0a
192 updating: b 2/2 files (100.00%)
192 updating: b 2/2 files (100.00%)
193 picked tool 'true' for b (binary False symlink False)
193 picked tool 'true' for b (binary False symlink False)
194 merging b
194 merging b
195 my b@1e71731e6fbb+ other b@83c51d0caff4 ancestor b@000000000000
195 my b@1e71731e6fbb+ other b@83c51d0caff4 ancestor b@000000000000
196 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
196 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
197 (branch merge, don't forget to commit)
197 (branch merge, don't forget to commit)
198 $ hg parents
198 $ hg parents
199 changeset: 1:1e71731e6fbb
199 changeset: 1:1e71731e6fbb
200 user: test
200 user: test
201 date: Thu Jan 01 00:00:00 1970 +0000
201 date: Thu Jan 01 00:00:00 1970 +0000
202 summary: 2
202 summary: 2
203
203
204 changeset: 2:83c51d0caff4
204 changeset: 2:83c51d0caff4
205 tag: tip
205 tag: tip
206 parent: 0:c19d34741b0a
206 parent: 0:c19d34741b0a
207 user: test
207 user: test
208 date: Thu Jan 01 00:00:00 1970 +0000
208 date: Thu Jan 01 00:00:00 1970 +0000
209 summary: 3
209 summary: 3
210
210
211 $ hg diff --nodates
211 $ hg diff --nodates
212 diff -r 1e71731e6fbb a
212 diff -r 1e71731e6fbb a
213 --- a/a
213 --- a/a
214 +++ b/a
214 +++ b/a
215 @@ -1,1 +1,1 @@
215 @@ -1,1 +1,1 @@
216 -a2
216 -a2
217 +abc
217 +abc
218
218
219
219
220 test a local add
220 test a local add
221
221
222 $ cd ..
222 $ cd ..
223 $ hg init a
223 $ hg init a
224 $ hg init b
224 $ hg init b
225 $ echo a > a/a
225 $ echo a > a/a
226 $ echo a > b/a
226 $ echo a > b/a
227 $ hg --cwd a commit -A -m a
227 $ hg --cwd a commit -A -m a
228 adding a
228 adding a
229 $ cd b
229 $ cd b
230 $ hg add a
230 $ hg add a
231 $ hg pull -u ../a
231 $ hg pull -u ../a
232 pulling from ../a
232 pulling from ../a
233 requesting all changes
233 requesting all changes
234 adding changesets
234 adding changesets
235 adding manifests
235 adding manifests
236 adding file changes
236 adding file changes
237 added 1 changesets with 1 changes to 1 files
237 added 1 changesets with 1 changes to 1 files
238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
239 $ hg st
239 $ hg st
240
240
241 $ cd ..
241 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now