##// END OF EJS Templates
merge: make 'keep' message more descriptive...
Martin von Zweigbergk -
r23482:208ec8ca default
parent child Browse files
Show More
@@ -1,1165 +1,1165 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 as errormod, util, filemerge, copies, subrepo, worker
13 import error as errormod, util, filemerge, copies, subrepo, worker
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, labels=None):
267 def resolve(self, dfile, wctx, labels=None):
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 labels=labels)
291 labels=labels)
292 if r is None:
292 if r is None:
293 # no real conflict
293 # no real conflict
294 del self._state[dfile]
294 del self._state[dfile]
295 self._dirty = True
295 self._dirty = True
296 elif not r:
296 elif not r:
297 self.mark(dfile, 'r')
297 self.mark(dfile, 'r')
298 return r
298 return r
299
299
300 def _checkunknownfile(repo, wctx, mctx, f):
300 def _checkunknownfile(repo, wctx, mctx, f):
301 return (os.path.isfile(repo.wjoin(f))
301 return (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 _forgetremoved(wctx, mctx, branchmerge):
306 def _forgetremoved(wctx, mctx, branchmerge):
307 """
307 """
308 Forget removed files
308 Forget removed files
309
309
310 If we're jumping between revisions (as opposed to merging), and if
310 If we're jumping between revisions (as opposed to merging), and if
311 neither the working directory nor the target rev has the file,
311 neither the working directory nor the target rev has the file,
312 then we need to remove it from the dirstate, to prevent the
312 then we need to remove it from the dirstate, to prevent the
313 dirstate from listing the file when it is no longer in the
313 dirstate from listing the file when it is no longer in the
314 manifest.
314 manifest.
315
315
316 If we're merging, and the other revision has removed a file
316 If we're merging, and the other revision has removed a file
317 that is not present in the working directory, we need to mark it
317 that is not present in the working directory, we need to mark it
318 as removed.
318 as removed.
319 """
319 """
320
320
321 ractions = []
321 ractions = []
322 factions = xactions = []
322 factions = xactions = []
323 if branchmerge:
323 if branchmerge:
324 xactions = ractions
324 xactions = ractions
325 for f in wctx.deleted():
325 for f in wctx.deleted():
326 if f not in mctx:
326 if f not in mctx:
327 xactions.append((f, None, "forget deleted"))
327 xactions.append((f, None, "forget deleted"))
328
328
329 if not branchmerge:
329 if not branchmerge:
330 for f in wctx.removed():
330 for f in wctx.removed():
331 if f not in mctx:
331 if f not in mctx:
332 factions.append((f, None, "forget removed"))
332 factions.append((f, None, "forget removed"))
333
333
334 return ractions, factions
334 return ractions, factions
335
335
336 def _checkcollision(repo, wmf, actions):
336 def _checkcollision(repo, wmf, actions):
337 # build provisional merged manifest up
337 # build provisional merged manifest up
338 pmmf = set(wmf)
338 pmmf = set(wmf)
339
339
340 if actions:
340 if actions:
341 # k, dr, e and rd are no-op
341 # k, dr, e and rd are no-op
342 for m in 'a', 'f', 'g', 'cd', 'dc':
342 for m in 'a', 'f', 'g', 'cd', 'dc':
343 for f, args, msg in actions[m]:
343 for f, args, msg in actions[m]:
344 pmmf.add(f)
344 pmmf.add(f)
345 for f, args, msg in actions['r']:
345 for f, args, msg in actions['r']:
346 pmmf.discard(f)
346 pmmf.discard(f)
347 for f, args, msg in actions['dm']:
347 for f, args, msg in actions['dm']:
348 f2, flags = args
348 f2, flags = args
349 pmmf.discard(f2)
349 pmmf.discard(f2)
350 pmmf.add(f)
350 pmmf.add(f)
351 for f, args, msg in actions['dg']:
351 for f, args, msg in actions['dg']:
352 pmmf.add(f)
352 pmmf.add(f)
353 for f, args, msg in actions['m']:
353 for f, args, msg in actions['m']:
354 f1, f2, fa, move, anc = args
354 f1, f2, fa, move, anc = args
355 if move:
355 if move:
356 pmmf.discard(f1)
356 pmmf.discard(f1)
357 pmmf.add(f)
357 pmmf.add(f)
358
358
359 # check case-folding collision in provisional merged manifest
359 # check case-folding collision in provisional merged manifest
360 foldmap = {}
360 foldmap = {}
361 for f in sorted(pmmf):
361 for f in sorted(pmmf):
362 fold = util.normcase(f)
362 fold = util.normcase(f)
363 if fold in foldmap:
363 if fold in foldmap:
364 raise util.Abort(_("case-folding collision between %s and %s")
364 raise util.Abort(_("case-folding collision between %s and %s")
365 % (f, foldmap[fold]))
365 % (f, foldmap[fold]))
366 foldmap[fold] = f
366 foldmap[fold] = f
367
367
368 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
368 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
369 acceptremote, followcopies):
369 acceptremote, followcopies):
370 """
370 """
371 Merge p1 and p2 with ancestor pa and generate merge action list
371 Merge p1 and p2 with ancestor pa and generate merge action list
372
372
373 branchmerge and force are as passed in to update
373 branchmerge and force are as passed in to update
374 partial = function to filter file lists
374 partial = function to filter file lists
375 acceptremote = accept the incoming changes without prompting
375 acceptremote = accept the incoming changes without prompting
376 """
376 """
377
377
378 actions = dict((m, []) for m in 'a f g cd dc r dm dg m dr e rd k'.split())
378 actions = dict((m, []) for m in 'a f g cd dc r dm dg m dr e rd k'.split())
379 copy, movewithdir = {}, {}
379 copy, movewithdir = {}, {}
380
380
381 # manifests fetched in order are going to be faster, so prime the caches
381 # manifests fetched in order are going to be faster, so prime the caches
382 [x.manifest() for x in
382 [x.manifest() for x in
383 sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())]
383 sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())]
384
384
385 if followcopies:
385 if followcopies:
386 ret = copies.mergecopies(repo, wctx, p2, pa)
386 ret = copies.mergecopies(repo, wctx, p2, pa)
387 copy, movewithdir, diverge, renamedelete = ret
387 copy, movewithdir, diverge, renamedelete = ret
388 for of, fl in diverge.iteritems():
388 for of, fl in diverge.iteritems():
389 actions['dr'].append((of, (fl,), "divergent renames"))
389 actions['dr'].append((of, (fl,), "divergent renames"))
390 for of, fl in renamedelete.iteritems():
390 for of, fl in renamedelete.iteritems():
391 actions['rd'].append((of, (fl,), "rename and delete"))
391 actions['rd'].append((of, (fl,), "rename and delete"))
392
392
393 repo.ui.note(_("resolving manifests\n"))
393 repo.ui.note(_("resolving manifests\n"))
394 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
394 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
395 % (bool(branchmerge), bool(force), bool(partial)))
395 % (bool(branchmerge), bool(force), bool(partial)))
396 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
396 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
397
397
398 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
398 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
399 copied = set(copy.values())
399 copied = set(copy.values())
400 copied.update(movewithdir.values())
400 copied.update(movewithdir.values())
401
401
402 if '.hgsubstate' in m1:
402 if '.hgsubstate' in m1:
403 # check whether sub state is modified
403 # check whether sub state is modified
404 for s in sorted(wctx.substate):
404 for s in sorted(wctx.substate):
405 if wctx.sub(s).dirty():
405 if wctx.sub(s).dirty():
406 m1['.hgsubstate'] += '+'
406 m1['.hgsubstate'] += '+'
407 break
407 break
408
408
409 aborts = []
409 aborts = []
410 # Compare manifests
410 # Compare manifests
411 diff = m1.diff(m2)
411 diff = m1.diff(m2)
412
412
413 for f, ((n1, fl1), (n2, fl2)) in diff.iteritems():
413 for f, ((n1, fl1), (n2, fl2)) in diff.iteritems():
414 if partial and not partial(f):
414 if partial and not partial(f):
415 continue
415 continue
416 if n1 and n2: # file exists on both local and remote side
416 if n1 and n2: # file exists on both local and remote side
417 if f not in ma:
417 if f not in ma:
418 fa = copy.get(f, None)
418 fa = copy.get(f, None)
419 if fa is not None:
419 if fa is not None:
420 actions['m'].append((f, (f, f, fa, False, pa.node()),
420 actions['m'].append((f, (f, f, fa, False, pa.node()),
421 "both renamed from " + fa))
421 "both renamed from " + fa))
422 else:
422 else:
423 actions['m'].append((f, (f, f, None, False, pa.node()),
423 actions['m'].append((f, (f, f, None, False, pa.node()),
424 "both created"))
424 "both created"))
425 else:
425 else:
426 a = ma[f]
426 a = ma[f]
427 fla = ma.flags(f)
427 fla = ma.flags(f)
428 nol = 'l' not in fl1 + fl2 + fla
428 nol = 'l' not in fl1 + fl2 + fla
429 if n2 == a and fl2 == fla:
429 if n2 == a and fl2 == fla:
430 actions['k'].append((f, (), "keep")) # remote unchanged
430 actions['k'].append((f, (), "remote unchanged"))
431 elif n1 == a and fl1 == fla: # local unchanged - use remote
431 elif n1 == a and fl1 == fla: # local unchanged - use remote
432 if n1 == n2: # optimization: keep local content
432 if n1 == n2: # optimization: keep local content
433 actions['e'].append((f, (fl2,), "update permissions"))
433 actions['e'].append((f, (fl2,), "update permissions"))
434 else:
434 else:
435 actions['g'].append((f, (fl2,), "remote is newer"))
435 actions['g'].append((f, (fl2,), "remote is newer"))
436 elif nol and n2 == a: # remote only changed 'x'
436 elif nol and n2 == a: # remote only changed 'x'
437 actions['e'].append((f, (fl2,), "update permissions"))
437 actions['e'].append((f, (fl2,), "update permissions"))
438 elif nol and n1 == a: # local only changed 'x'
438 elif nol and n1 == a: # local only changed 'x'
439 actions['g'].append((f, (fl1,), "remote is newer"))
439 actions['g'].append((f, (fl1,), "remote is newer"))
440 else: # both changed something
440 else: # both changed something
441 actions['m'].append((f, (f, f, f, False, pa.node()),
441 actions['m'].append((f, (f, f, f, False, pa.node()),
442 "versions differ"))
442 "versions differ"))
443 elif n1: # file exists only on local side
443 elif n1: # file exists only on local side
444 if f in copied:
444 if f in copied:
445 pass # we'll deal with it on m2 side
445 pass # we'll deal with it on m2 side
446 elif f in movewithdir: # directory rename, move local
446 elif f in movewithdir: # directory rename, move local
447 f2 = movewithdir[f]
447 f2 = movewithdir[f]
448 if f2 in m2:
448 if f2 in m2:
449 actions['m'].append((f2, (f, f2, None, True, pa.node()),
449 actions['m'].append((f2, (f, f2, None, True, pa.node()),
450 "remote directory rename, both created"))
450 "remote directory rename, both created"))
451 else:
451 else:
452 actions['dm'].append((f2, (f, fl1),
452 actions['dm'].append((f2, (f, fl1),
453 "remote directory rename - move from " + f))
453 "remote directory rename - move from " + f))
454 elif f in copy:
454 elif f in copy:
455 f2 = copy[f]
455 f2 = copy[f]
456 actions['m'].append((f, (f, f2, f2, False, pa.node()),
456 actions['m'].append((f, (f, f2, f2, False, pa.node()),
457 "local copied/moved from " + f2))
457 "local copied/moved from " + f2))
458 elif f in ma: # clean, a different, no remote
458 elif f in ma: # clean, a different, no remote
459 if n1 != ma[f]:
459 if n1 != ma[f]:
460 if acceptremote:
460 if acceptremote:
461 actions['r'].append((f, None, "remote delete"))
461 actions['r'].append((f, None, "remote delete"))
462 else:
462 else:
463 actions['cd'].append((f, None,
463 actions['cd'].append((f, None,
464 "prompt changed/deleted"))
464 "prompt changed/deleted"))
465 elif n1[20:] == 'a':
465 elif n1[20:] == 'a':
466 # This extra 'a' is added by working copy manifest to mark
466 # This extra 'a' is added by working copy manifest to mark
467 # the file as locally added. We should forget it instead of
467 # the file as locally added. We should forget it instead of
468 # deleting it.
468 # deleting it.
469 actions['f'].append((f, None, "remote deleted"))
469 actions['f'].append((f, None, "remote deleted"))
470 else:
470 else:
471 actions['r'].append((f, None, "other deleted"))
471 actions['r'].append((f, None, "other deleted"))
472 elif n2: # file exists only on remote side
472 elif n2: # file exists only on remote side
473 if f in copied:
473 if f in copied:
474 pass # we'll deal with it on m1 side
474 pass # we'll deal with it on m1 side
475 elif f in movewithdir:
475 elif f in movewithdir:
476 f2 = movewithdir[f]
476 f2 = movewithdir[f]
477 if f2 in m1:
477 if f2 in m1:
478 actions['m'].append((f2, (f2, f, None, False, pa.node()),
478 actions['m'].append((f2, (f2, f, None, False, pa.node()),
479 "local directory rename, both created"))
479 "local directory rename, both created"))
480 else:
480 else:
481 actions['dg'].append((f2, (f, fl2),
481 actions['dg'].append((f2, (f, fl2),
482 "local directory rename - get from " + f))
482 "local directory rename - get from " + f))
483 elif f in copy:
483 elif f in copy:
484 f2 = copy[f]
484 f2 = copy[f]
485 if f2 in m2:
485 if f2 in m2:
486 actions['m'].append((f, (f2, f, f2, False, pa.node()),
486 actions['m'].append((f, (f2, f, f2, False, pa.node()),
487 "remote copied from " + f2))
487 "remote copied from " + f2))
488 else:
488 else:
489 actions['m'].append((f, (f2, f, f2, True, pa.node()),
489 actions['m'].append((f, (f2, f, f2, True, pa.node()),
490 "remote moved from " + f2))
490 "remote moved from " + f2))
491 elif f not in ma:
491 elif f not in ma:
492 # local unknown, remote created: the logic is described by the
492 # local unknown, remote created: the logic is described by the
493 # following table:
493 # following table:
494 #
494 #
495 # force branchmerge different | action
495 # force branchmerge different | action
496 # n * n | get
496 # n * n | get
497 # n * y | abort
497 # n * y | abort
498 # y n * | get
498 # y n * | get
499 # y y n | get
499 # y y n | get
500 # y y y | merge
500 # y y y | merge
501 #
501 #
502 # Checking whether the files are different is expensive, so we
502 # Checking whether the files are different is expensive, so we
503 # don't do that when we can avoid it.
503 # don't do that when we can avoid it.
504 if force and not branchmerge:
504 if force and not branchmerge:
505 actions['g'].append((f, (fl2,), "remote created"))
505 actions['g'].append((f, (fl2,), "remote created"))
506 else:
506 else:
507 different = _checkunknownfile(repo, wctx, p2, f)
507 different = _checkunknownfile(repo, wctx, p2, f)
508 if force and branchmerge and different:
508 if force and branchmerge and different:
509 actions['m'].append((f, (f, f, None, False, pa.node()),
509 actions['m'].append((f, (f, f, None, False, pa.node()),
510 "remote differs from untracked local"))
510 "remote differs from untracked local"))
511 elif not force and different:
511 elif not force and different:
512 aborts.append((f, 'ud'))
512 aborts.append((f, 'ud'))
513 else:
513 else:
514 actions['g'].append((f, (fl2,), "remote created"))
514 actions['g'].append((f, (fl2,), "remote created"))
515 elif n2 != ma[f]:
515 elif n2 != ma[f]:
516 different = _checkunknownfile(repo, wctx, p2, f)
516 different = _checkunknownfile(repo, wctx, p2, f)
517 if not force and different:
517 if not force and different:
518 aborts.append((f, 'ud'))
518 aborts.append((f, 'ud'))
519 else:
519 else:
520 if acceptremote:
520 if acceptremote:
521 actions['g'].append((f, (fl2,), "remote recreating"))
521 actions['g'].append((f, (fl2,), "remote recreating"))
522 else:
522 else:
523 actions['dc'].append((f, (fl2,),
523 actions['dc'].append((f, (fl2,),
524 "prompt deleted/changed"))
524 "prompt deleted/changed"))
525
525
526 for f, m in sorted(aborts):
526 for f, m in sorted(aborts):
527 if m == 'ud':
527 if m == 'ud':
528 repo.ui.warn(_("%s: untracked file differs\n") % f)
528 repo.ui.warn(_("%s: untracked file differs\n") % f)
529 else: assert False, m
529 else: assert False, m
530 if aborts:
530 if aborts:
531 raise util.Abort(_("untracked files in working directory differ "
531 raise util.Abort(_("untracked files in working directory differ "
532 "from files in requested revision"))
532 "from files in requested revision"))
533
533
534 if not util.checkcase(repo.path):
534 if not util.checkcase(repo.path):
535 # check collision between files only in p2 for clean update
535 # check collision between files only in p2 for clean update
536 if (not branchmerge and
536 if (not branchmerge and
537 (force or not wctx.dirty(missing=True, branch=False))):
537 (force or not wctx.dirty(missing=True, branch=False))):
538 _checkcollision(repo, m2, None)
538 _checkcollision(repo, m2, None)
539 else:
539 else:
540 _checkcollision(repo, m1, actions)
540 _checkcollision(repo, m1, actions)
541
541
542 return actions
542 return actions
543
543
544 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial,
544 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial,
545 acceptremote, followcopies):
545 acceptremote, followcopies):
546 "Calculate the actions needed to merge mctx into wctx using ancestors"
546 "Calculate the actions needed to merge mctx into wctx using ancestors"
547
547
548 if len(ancestors) == 1: # default
548 if len(ancestors) == 1: # default
549 actions = manifestmerge(repo, wctx, mctx, ancestors[0],
549 actions = manifestmerge(repo, wctx, mctx, ancestors[0],
550 branchmerge, force,
550 branchmerge, force,
551 partial, acceptremote, followcopies)
551 partial, acceptremote, followcopies)
552
552
553 else: # only when merge.preferancestor=* - the default
553 else: # only when merge.preferancestor=* - the default
554 repo.ui.note(
554 repo.ui.note(
555 _("note: merging %s and %s using bids from ancestors %s\n") %
555 _("note: merging %s and %s using bids from ancestors %s\n") %
556 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors)))
556 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors)))
557
557
558 # Call for bids
558 # Call for bids
559 fbids = {} # mapping filename to bids (action method to list af actions)
559 fbids = {} # mapping filename to bids (action method to list af actions)
560 for ancestor in ancestors:
560 for ancestor in ancestors:
561 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
561 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
562 actions = manifestmerge(repo, wctx, mctx, ancestor,
562 actions = manifestmerge(repo, wctx, mctx, ancestor,
563 branchmerge, force,
563 branchmerge, force,
564 partial, acceptremote, followcopies)
564 partial, acceptremote, followcopies)
565 for m, l in sorted(actions.items()):
565 for m, l in sorted(actions.items()):
566 for a in l:
566 for a in l:
567 f, args, msg = a
567 f, args, msg = a
568 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
568 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
569 if f in fbids:
569 if f in fbids:
570 d = fbids[f]
570 d = fbids[f]
571 if m in d:
571 if m in d:
572 d[m].append(a)
572 d[m].append(a)
573 else:
573 else:
574 d[m] = [a]
574 d[m] = [a]
575 else:
575 else:
576 fbids[f] = {m: [a]}
576 fbids[f] = {m: [a]}
577
577
578 # Pick the best bid for each file
578 # Pick the best bid for each file
579 repo.ui.note(_('\nauction for merging merge bids\n'))
579 repo.ui.note(_('\nauction for merging merge bids\n'))
580 actions = dict((m, []) for m in actions.keys())
580 actions = dict((m, []) for m in actions.keys())
581 for f, bids in sorted(fbids.items()):
581 for f, bids in sorted(fbids.items()):
582 # bids is a mapping from action method to list af actions
582 # bids is a mapping from action method to list af actions
583 # Consensus?
583 # Consensus?
584 if len(bids) == 1: # all bids are the same kind of method
584 if len(bids) == 1: # all bids are the same kind of method
585 m, l = bids.items()[0]
585 m, l = bids.items()[0]
586 if util.all(a == l[0] for a in l[1:]): # len(bids) is > 1
586 if util.all(a == l[0] for a in l[1:]): # len(bids) is > 1
587 repo.ui.note(" %s: consensus for %s\n" % (f, m))
587 repo.ui.note(" %s: consensus for %s\n" % (f, m))
588 actions[m].append(l[0])
588 actions[m].append(l[0])
589 continue
589 continue
590 # If keep is an option, just do it.
590 # If keep is an option, just do it.
591 if 'k' in bids:
591 if 'k' in bids:
592 repo.ui.note(" %s: picking 'keep' action\n" % f)
592 repo.ui.note(" %s: picking 'keep' action\n" % f)
593 actions['k'].append(bids['k'][0])
593 actions['k'].append(bids['k'][0])
594 continue
594 continue
595 # If there are gets and they all agree [how could they not?], do it.
595 # If there are gets and they all agree [how could they not?], do it.
596 if 'g' in bids:
596 if 'g' in bids:
597 ga0 = bids['g'][0]
597 ga0 = bids['g'][0]
598 if util.all(a == ga0 for a in bids['g'][1:]):
598 if util.all(a == ga0 for a in bids['g'][1:]):
599 repo.ui.note(" %s: picking 'get' action\n" % f)
599 repo.ui.note(" %s: picking 'get' action\n" % f)
600 actions['g'].append(ga0)
600 actions['g'].append(ga0)
601 continue
601 continue
602 # TODO: Consider other simple actions such as mode changes
602 # TODO: Consider other simple actions such as mode changes
603 # Handle inefficient democrazy.
603 # Handle inefficient democrazy.
604 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
604 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
605 for m, l in sorted(bids.items()):
605 for m, l in sorted(bids.items()):
606 for _f, args, msg in l:
606 for _f, args, msg in l:
607 repo.ui.note(' %s -> %s\n' % (msg, m))
607 repo.ui.note(' %s -> %s\n' % (msg, m))
608 # Pick random action. TODO: Instead, prompt user when resolving
608 # Pick random action. TODO: Instead, prompt user when resolving
609 m, l = bids.items()[0]
609 m, l = bids.items()[0]
610 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
610 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
611 (f, m))
611 (f, m))
612 actions[m].append(l[0])
612 actions[m].append(l[0])
613 continue
613 continue
614 repo.ui.note(_('end of auction\n\n'))
614 repo.ui.note(_('end of auction\n\n'))
615
615
616 # Prompt and create actions. TODO: Move this towards resolve phase.
616 # Prompt and create actions. TODO: Move this towards resolve phase.
617 for f, args, msg in sorted(actions['cd']):
617 for f, args, msg in sorted(actions['cd']):
618 if f in ancestors[0] and not wctx[f].cmp(ancestors[0][f]):
618 if f in ancestors[0] and not wctx[f].cmp(ancestors[0][f]):
619 # local did change but ended up with same content
619 # local did change but ended up with same content
620 actions['r'].append((f, None, "prompt same"))
620 actions['r'].append((f, None, "prompt same"))
621 elif repo.ui.promptchoice(
621 elif repo.ui.promptchoice(
622 _("local changed %s which remote deleted\n"
622 _("local changed %s which remote deleted\n"
623 "use (c)hanged version or (d)elete?"
623 "use (c)hanged version or (d)elete?"
624 "$$ &Changed $$ &Delete") % f, 0):
624 "$$ &Changed $$ &Delete") % f, 0):
625 actions['r'].append((f, None, "prompt delete"))
625 actions['r'].append((f, None, "prompt delete"))
626 else:
626 else:
627 actions['a'].append((f, None, "prompt keep"))
627 actions['a'].append((f, None, "prompt keep"))
628 del actions['cd'][:]
628 del actions['cd'][:]
629
629
630 for f, args, msg in sorted(actions['dc']):
630 for f, args, msg in sorted(actions['dc']):
631 flags, = args
631 flags, = args
632 if f in ancestors[0] and not mctx[f].cmp(ancestors[0][f]):
632 if f in ancestors[0] and not mctx[f].cmp(ancestors[0][f]):
633 # remote did change but ended up with same content
633 # remote did change but ended up with same content
634 pass # don't get = keep local deleted
634 pass # don't get = keep local deleted
635 elif repo.ui.promptchoice(
635 elif repo.ui.promptchoice(
636 _("remote changed %s which local deleted\n"
636 _("remote changed %s which local deleted\n"
637 "use (c)hanged version or leave (d)eleted?"
637 "use (c)hanged version or leave (d)eleted?"
638 "$$ &Changed $$ &Deleted") % f, 0) == 0:
638 "$$ &Changed $$ &Deleted") % f, 0) == 0:
639 actions['g'].append((f, (flags,), "prompt recreating"))
639 actions['g'].append((f, (flags,), "prompt recreating"))
640 del actions['dc'][:]
640 del actions['dc'][:]
641
641
642 if wctx.rev() is None:
642 if wctx.rev() is None:
643 ractions, factions = _forgetremoved(wctx, mctx, branchmerge)
643 ractions, factions = _forgetremoved(wctx, mctx, branchmerge)
644 actions['r'].extend(ractions)
644 actions['r'].extend(ractions)
645 actions['f'].extend(factions)
645 actions['f'].extend(factions)
646
646
647 return actions
647 return actions
648
648
649 def batchremove(repo, actions):
649 def batchremove(repo, actions):
650 """apply removes to the working directory
650 """apply removes to the working directory
651
651
652 yields tuples for progress updates
652 yields tuples for progress updates
653 """
653 """
654 verbose = repo.ui.verbose
654 verbose = repo.ui.verbose
655 unlink = util.unlinkpath
655 unlink = util.unlinkpath
656 wjoin = repo.wjoin
656 wjoin = repo.wjoin
657 audit = repo.wopener.audit
657 audit = repo.wopener.audit
658 i = 0
658 i = 0
659 for f, args, msg in actions:
659 for f, args, msg in actions:
660 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
660 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
661 if verbose:
661 if verbose:
662 repo.ui.note(_("removing %s\n") % f)
662 repo.ui.note(_("removing %s\n") % f)
663 audit(f)
663 audit(f)
664 try:
664 try:
665 unlink(wjoin(f), ignoremissing=True)
665 unlink(wjoin(f), ignoremissing=True)
666 except OSError, inst:
666 except OSError, inst:
667 repo.ui.warn(_("update failed to remove %s: %s!\n") %
667 repo.ui.warn(_("update failed to remove %s: %s!\n") %
668 (f, inst.strerror))
668 (f, inst.strerror))
669 if i == 100:
669 if i == 100:
670 yield i, f
670 yield i, f
671 i = 0
671 i = 0
672 i += 1
672 i += 1
673 if i > 0:
673 if i > 0:
674 yield i, f
674 yield i, f
675
675
676 def batchget(repo, mctx, actions):
676 def batchget(repo, mctx, actions):
677 """apply gets to the working directory
677 """apply gets to the working directory
678
678
679 mctx is the context to get from
679 mctx is the context to get from
680
680
681 yields tuples for progress updates
681 yields tuples for progress updates
682 """
682 """
683 verbose = repo.ui.verbose
683 verbose = repo.ui.verbose
684 fctx = mctx.filectx
684 fctx = mctx.filectx
685 wwrite = repo.wwrite
685 wwrite = repo.wwrite
686 i = 0
686 i = 0
687 for f, args, msg in actions:
687 for f, args, msg in actions:
688 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
688 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
689 if verbose:
689 if verbose:
690 repo.ui.note(_("getting %s\n") % f)
690 repo.ui.note(_("getting %s\n") % f)
691 wwrite(f, fctx(f).data(), args[0])
691 wwrite(f, fctx(f).data(), args[0])
692 if i == 100:
692 if i == 100:
693 yield i, f
693 yield i, f
694 i = 0
694 i = 0
695 i += 1
695 i += 1
696 if i > 0:
696 if i > 0:
697 yield i, f
697 yield i, f
698
698
699 def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
699 def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
700 """apply the merge action list to the working directory
700 """apply the merge action list to the working directory
701
701
702 wctx is the working copy context
702 wctx is the working copy context
703 mctx is the context to be merged into the working copy
703 mctx is the context to be merged into the working copy
704
704
705 Return a tuple of counts (updated, merged, removed, unresolved) that
705 Return a tuple of counts (updated, merged, removed, unresolved) that
706 describes how many files were affected by the update.
706 describes how many files were affected by the update.
707 """
707 """
708
708
709 updated, merged, removed, unresolved = 0, 0, 0, 0
709 updated, merged, removed, unresolved = 0, 0, 0, 0
710 ms = mergestate(repo)
710 ms = mergestate(repo)
711 ms.reset(wctx.p1().node(), mctx.node())
711 ms.reset(wctx.p1().node(), mctx.node())
712 moves = []
712 moves = []
713 for m, l in actions.items():
713 for m, l in actions.items():
714 l.sort()
714 l.sort()
715
715
716 # prescan for merges
716 # prescan for merges
717 for f, args, msg in actions['m']:
717 for f, args, msg in actions['m']:
718 f1, f2, fa, move, anc = args
718 f1, f2, fa, move, anc = args
719 if f == '.hgsubstate': # merged internally
719 if f == '.hgsubstate': # merged internally
720 continue
720 continue
721 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
721 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
722 fcl = wctx[f1]
722 fcl = wctx[f1]
723 fco = mctx[f2]
723 fco = mctx[f2]
724 actx = repo[anc]
724 actx = repo[anc]
725 if fa in actx:
725 if fa in actx:
726 fca = actx[fa]
726 fca = actx[fa]
727 else:
727 else:
728 fca = repo.filectx(f1, fileid=nullrev)
728 fca = repo.filectx(f1, fileid=nullrev)
729 ms.add(fcl, fco, fca, f)
729 ms.add(fcl, fco, fca, f)
730 if f1 != f and move:
730 if f1 != f and move:
731 moves.append(f1)
731 moves.append(f1)
732
732
733 audit = repo.wopener.audit
733 audit = repo.wopener.audit
734 _updating = _('updating')
734 _updating = _('updating')
735 _files = _('files')
735 _files = _('files')
736 progress = repo.ui.progress
736 progress = repo.ui.progress
737
737
738 # remove renamed files after safely stored
738 # remove renamed files after safely stored
739 for f in moves:
739 for f in moves:
740 if os.path.lexists(repo.wjoin(f)):
740 if os.path.lexists(repo.wjoin(f)):
741 repo.ui.debug("removing %s\n" % f)
741 repo.ui.debug("removing %s\n" % f)
742 audit(f)
742 audit(f)
743 util.unlinkpath(repo.wjoin(f))
743 util.unlinkpath(repo.wjoin(f))
744
744
745 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
745 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
746
746
747 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
747 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
748 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
748 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
749
749
750 # remove in parallel (must come first)
750 # remove in parallel (must come first)
751 z = 0
751 z = 0
752 prog = worker.worker(repo.ui, 0.001, batchremove, (repo,), actions['r'])
752 prog = worker.worker(repo.ui, 0.001, batchremove, (repo,), actions['r'])
753 for i, item in prog:
753 for i, item in prog:
754 z += i
754 z += i
755 progress(_updating, z, item=item, total=numupdates, unit=_files)
755 progress(_updating, z, item=item, total=numupdates, unit=_files)
756 removed = len(actions['r'])
756 removed = len(actions['r'])
757
757
758 # get in parallel
758 # get in parallel
759 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx), actions['g'])
759 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx), actions['g'])
760 for i, item in prog:
760 for i, item in prog:
761 z += i
761 z += i
762 progress(_updating, z, item=item, total=numupdates, unit=_files)
762 progress(_updating, z, item=item, total=numupdates, unit=_files)
763 updated = len(actions['g'])
763 updated = len(actions['g'])
764
764
765 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
765 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
766 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
766 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
767
767
768 # forget (manifest only, just log it) (must come first)
768 # forget (manifest only, just log it) (must come first)
769 for f, args, msg in actions['f']:
769 for f, args, msg in actions['f']:
770 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
770 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
771 z += 1
771 z += 1
772 progress(_updating, z, item=f, total=numupdates, unit=_files)
772 progress(_updating, z, item=f, total=numupdates, unit=_files)
773
773
774 # re-add (manifest only, just log it)
774 # re-add (manifest only, just log it)
775 for f, args, msg in actions['a']:
775 for f, args, msg in actions['a']:
776 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
776 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
777 z += 1
777 z += 1
778 progress(_updating, z, item=f, total=numupdates, unit=_files)
778 progress(_updating, z, item=f, total=numupdates, unit=_files)
779
779
780 # keep (noop, just log it)
780 # keep (noop, just log it)
781 for f, args, msg in actions['k']:
781 for f, args, msg in actions['k']:
782 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
782 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
783 # no progress
783 # no progress
784
784
785 # merge
785 # merge
786 for f, args, msg in actions['m']:
786 for f, args, msg in actions['m']:
787 repo.ui.debug(" %s: %s -> m\n" % (f, msg))
787 repo.ui.debug(" %s: %s -> m\n" % (f, msg))
788 z += 1
788 z += 1
789 progress(_updating, z, item=f, total=numupdates, unit=_files)
789 progress(_updating, z, item=f, total=numupdates, unit=_files)
790 if f == '.hgsubstate': # subrepo states need updating
790 if f == '.hgsubstate': # subrepo states need updating
791 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
791 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
792 overwrite)
792 overwrite)
793 continue
793 continue
794 audit(f)
794 audit(f)
795 r = ms.resolve(f, wctx, labels=labels)
795 r = ms.resolve(f, wctx, labels=labels)
796 if r is not None and r > 0:
796 if r is not None and r > 0:
797 unresolved += 1
797 unresolved += 1
798 else:
798 else:
799 if r is None:
799 if r is None:
800 updated += 1
800 updated += 1
801 else:
801 else:
802 merged += 1
802 merged += 1
803
803
804 # directory rename, move local
804 # directory rename, move local
805 for f, args, msg in actions['dm']:
805 for f, args, msg in actions['dm']:
806 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
806 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
807 z += 1
807 z += 1
808 progress(_updating, z, item=f, total=numupdates, unit=_files)
808 progress(_updating, z, item=f, total=numupdates, unit=_files)
809 f0, flags = args
809 f0, flags = args
810 repo.ui.note(_("moving %s to %s\n") % (f0, f))
810 repo.ui.note(_("moving %s to %s\n") % (f0, f))
811 audit(f)
811 audit(f)
812 repo.wwrite(f, wctx.filectx(f0).data(), flags)
812 repo.wwrite(f, wctx.filectx(f0).data(), flags)
813 util.unlinkpath(repo.wjoin(f0))
813 util.unlinkpath(repo.wjoin(f0))
814 updated += 1
814 updated += 1
815
815
816 # local directory rename, get
816 # local directory rename, get
817 for f, args, msg in actions['dg']:
817 for f, args, msg in actions['dg']:
818 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
818 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
819 z += 1
819 z += 1
820 progress(_updating, z, item=f, total=numupdates, unit=_files)
820 progress(_updating, z, item=f, total=numupdates, unit=_files)
821 f0, flags = args
821 f0, flags = args
822 repo.ui.note(_("getting %s to %s\n") % (f0, f))
822 repo.ui.note(_("getting %s to %s\n") % (f0, f))
823 repo.wwrite(f, mctx.filectx(f0).data(), flags)
823 repo.wwrite(f, mctx.filectx(f0).data(), flags)
824 updated += 1
824 updated += 1
825
825
826 # divergent renames
826 # divergent renames
827 for f, args, msg in actions['dr']:
827 for f, args, msg in actions['dr']:
828 repo.ui.debug(" %s: %s -> dr\n" % (f, msg))
828 repo.ui.debug(" %s: %s -> dr\n" % (f, msg))
829 z += 1
829 z += 1
830 progress(_updating, z, item=f, total=numupdates, unit=_files)
830 progress(_updating, z, item=f, total=numupdates, unit=_files)
831 fl, = args
831 fl, = args
832 repo.ui.warn(_("note: possible conflict - %s was renamed "
832 repo.ui.warn(_("note: possible conflict - %s was renamed "
833 "multiple times to:\n") % f)
833 "multiple times to:\n") % f)
834 for nf in fl:
834 for nf in fl:
835 repo.ui.warn(" %s\n" % nf)
835 repo.ui.warn(" %s\n" % nf)
836
836
837 # rename and delete
837 # rename and delete
838 for f, args, msg in actions['rd']:
838 for f, args, msg in actions['rd']:
839 repo.ui.debug(" %s: %s -> rd\n" % (f, msg))
839 repo.ui.debug(" %s: %s -> rd\n" % (f, msg))
840 z += 1
840 z += 1
841 progress(_updating, z, item=f, total=numupdates, unit=_files)
841 progress(_updating, z, item=f, total=numupdates, unit=_files)
842 fl, = args
842 fl, = args
843 repo.ui.warn(_("note: possible conflict - %s was deleted "
843 repo.ui.warn(_("note: possible conflict - %s was deleted "
844 "and renamed to:\n") % f)
844 "and renamed to:\n") % f)
845 for nf in fl:
845 for nf in fl:
846 repo.ui.warn(" %s\n" % nf)
846 repo.ui.warn(" %s\n" % nf)
847
847
848 # exec
848 # exec
849 for f, args, msg in actions['e']:
849 for f, args, msg in actions['e']:
850 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
850 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
851 z += 1
851 z += 1
852 progress(_updating, z, item=f, total=numupdates, unit=_files)
852 progress(_updating, z, item=f, total=numupdates, unit=_files)
853 flags, = args
853 flags, = args
854 audit(f)
854 audit(f)
855 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
855 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
856 updated += 1
856 updated += 1
857
857
858 ms.commit()
858 ms.commit()
859 progress(_updating, None, total=numupdates, unit=_files)
859 progress(_updating, None, total=numupdates, unit=_files)
860
860
861 return updated, merged, removed, unresolved
861 return updated, merged, removed, unresolved
862
862
863 def recordupdates(repo, actions, branchmerge):
863 def recordupdates(repo, actions, branchmerge):
864 "record merge actions to the dirstate"
864 "record merge actions to the dirstate"
865 # remove (must come first)
865 # remove (must come first)
866 for f, args, msg in actions['r']:
866 for f, args, msg in actions['r']:
867 if branchmerge:
867 if branchmerge:
868 repo.dirstate.remove(f)
868 repo.dirstate.remove(f)
869 else:
869 else:
870 repo.dirstate.drop(f)
870 repo.dirstate.drop(f)
871
871
872 # forget (must come first)
872 # forget (must come first)
873 for f, args, msg in actions['f']:
873 for f, args, msg in actions['f']:
874 repo.dirstate.drop(f)
874 repo.dirstate.drop(f)
875
875
876 # re-add
876 # re-add
877 for f, args, msg in actions['a']:
877 for f, args, msg in actions['a']:
878 if not branchmerge:
878 if not branchmerge:
879 repo.dirstate.add(f)
879 repo.dirstate.add(f)
880
880
881 # exec change
881 # exec change
882 for f, args, msg in actions['e']:
882 for f, args, msg in actions['e']:
883 repo.dirstate.normallookup(f)
883 repo.dirstate.normallookup(f)
884
884
885 # keep
885 # keep
886 for f, args, msg in actions['k']:
886 for f, args, msg in actions['k']:
887 pass
887 pass
888
888
889 # get
889 # get
890 for f, args, msg in actions['g']:
890 for f, args, msg in actions['g']:
891 if branchmerge:
891 if branchmerge:
892 repo.dirstate.otherparent(f)
892 repo.dirstate.otherparent(f)
893 else:
893 else:
894 repo.dirstate.normal(f)
894 repo.dirstate.normal(f)
895
895
896 # merge
896 # merge
897 for f, args, msg in actions['m']:
897 for f, args, msg in actions['m']:
898 f1, f2, fa, move, anc = args
898 f1, f2, fa, move, anc = args
899 if branchmerge:
899 if branchmerge:
900 # We've done a branch merge, mark this file as merged
900 # We've done a branch merge, mark this file as merged
901 # so that we properly record the merger later
901 # so that we properly record the merger later
902 repo.dirstate.merge(f)
902 repo.dirstate.merge(f)
903 if f1 != f2: # copy/rename
903 if f1 != f2: # copy/rename
904 if move:
904 if move:
905 repo.dirstate.remove(f1)
905 repo.dirstate.remove(f1)
906 if f1 != f:
906 if f1 != f:
907 repo.dirstate.copy(f1, f)
907 repo.dirstate.copy(f1, f)
908 else:
908 else:
909 repo.dirstate.copy(f2, f)
909 repo.dirstate.copy(f2, f)
910 else:
910 else:
911 # We've update-merged a locally modified file, so
911 # We've update-merged a locally modified file, so
912 # we set the dirstate to emulate a normal checkout
912 # we set the dirstate to emulate a normal checkout
913 # of that file some time in the past. Thus our
913 # of that file some time in the past. Thus our
914 # merge will appear as a normal local file
914 # merge will appear as a normal local file
915 # modification.
915 # modification.
916 if f2 == f: # file not locally copied/moved
916 if f2 == f: # file not locally copied/moved
917 repo.dirstate.normallookup(f)
917 repo.dirstate.normallookup(f)
918 if move:
918 if move:
919 repo.dirstate.drop(f1)
919 repo.dirstate.drop(f1)
920
920
921 # directory rename, move local
921 # directory rename, move local
922 for f, args, msg in actions['dm']:
922 for f, args, msg in actions['dm']:
923 f0, flag = args
923 f0, flag = args
924 if branchmerge:
924 if branchmerge:
925 repo.dirstate.add(f)
925 repo.dirstate.add(f)
926 repo.dirstate.remove(f0)
926 repo.dirstate.remove(f0)
927 repo.dirstate.copy(f0, f)
927 repo.dirstate.copy(f0, f)
928 else:
928 else:
929 repo.dirstate.normal(f)
929 repo.dirstate.normal(f)
930 repo.dirstate.drop(f0)
930 repo.dirstate.drop(f0)
931
931
932 # directory rename, get
932 # directory rename, get
933 for f, args, msg in actions['dg']:
933 for f, args, msg in actions['dg']:
934 f0, flag = args
934 f0, flag = args
935 if branchmerge:
935 if branchmerge:
936 repo.dirstate.add(f)
936 repo.dirstate.add(f)
937 repo.dirstate.copy(f0, f)
937 repo.dirstate.copy(f0, f)
938 else:
938 else:
939 repo.dirstate.normal(f)
939 repo.dirstate.normal(f)
940
940
941 def update(repo, node, branchmerge, force, partial, ancestor=None,
941 def update(repo, node, branchmerge, force, partial, ancestor=None,
942 mergeancestor=False, labels=None):
942 mergeancestor=False, labels=None):
943 """
943 """
944 Perform a merge between the working directory and the given node
944 Perform a merge between the working directory and the given node
945
945
946 node = the node to update to, or None if unspecified
946 node = the node to update to, or None if unspecified
947 branchmerge = whether to merge between branches
947 branchmerge = whether to merge between branches
948 force = whether to force branch merging or file overwriting
948 force = whether to force branch merging or file overwriting
949 partial = a function to filter file lists (dirstate not updated)
949 partial = a function to filter file lists (dirstate not updated)
950 mergeancestor = whether it is merging with an ancestor. If true,
950 mergeancestor = whether it is merging with an ancestor. If true,
951 we should accept the incoming changes for any prompts that occur.
951 we should accept the incoming changes for any prompts that occur.
952 If false, merging with an ancestor (fast-forward) is only allowed
952 If false, merging with an ancestor (fast-forward) is only allowed
953 between different named branches. This flag is used by rebase extension
953 between different named branches. This flag is used by rebase extension
954 as a temporary fix and should be avoided in general.
954 as a temporary fix and should be avoided in general.
955
955
956 The table below shows all the behaviors of the update command
956 The table below shows all the behaviors of the update command
957 given the -c and -C or no options, whether the working directory
957 given the -c and -C or no options, whether the working directory
958 is dirty, whether a revision is specified, and the relationship of
958 is dirty, whether a revision is specified, and the relationship of
959 the parent rev to the target rev (linear, on the same named
959 the parent rev to the target rev (linear, on the same named
960 branch, or on another named branch).
960 branch, or on another named branch).
961
961
962 This logic is tested by test-update-branches.t.
962 This logic is tested by test-update-branches.t.
963
963
964 -c -C dirty rev | linear same cross
964 -c -C dirty rev | linear same cross
965 n n n n | ok (1) x
965 n n n n | ok (1) x
966 n n n y | ok ok ok
966 n n n y | ok ok ok
967 n n y n | merge (2) (2)
967 n n y n | merge (2) (2)
968 n n y y | merge (3) (3)
968 n n y y | merge (3) (3)
969 n y * * | --- discard ---
969 n y * * | --- discard ---
970 y n y * | --- (4) ---
970 y n y * | --- (4) ---
971 y n n * | --- ok ---
971 y n n * | --- ok ---
972 y y * * | --- (5) ---
972 y y * * | --- (5) ---
973
973
974 x = can't happen
974 x = can't happen
975 * = don't-care
975 * = don't-care
976 1 = abort: not a linear update (merge or update --check to force update)
976 1 = abort: not a linear update (merge or update --check to force update)
977 2 = abort: uncommitted changes (commit and merge, or update --clean to
977 2 = abort: uncommitted changes (commit and merge, or update --clean to
978 discard changes)
978 discard changes)
979 3 = abort: uncommitted changes (commit or update --clean to discard changes)
979 3 = abort: uncommitted changes (commit or update --clean to discard changes)
980 4 = abort: uncommitted changes (checked in commands.py)
980 4 = abort: uncommitted changes (checked in commands.py)
981 5 = incompatible options (checked in commands.py)
981 5 = incompatible options (checked in commands.py)
982
982
983 Return the same tuple as applyupdates().
983 Return the same tuple as applyupdates().
984 """
984 """
985
985
986 onode = node
986 onode = node
987 wlock = repo.wlock()
987 wlock = repo.wlock()
988 try:
988 try:
989 wc = repo[None]
989 wc = repo[None]
990 pl = wc.parents()
990 pl = wc.parents()
991 p1 = pl[0]
991 p1 = pl[0]
992 pas = [None]
992 pas = [None]
993 if ancestor is not None:
993 if ancestor is not None:
994 pas = [repo[ancestor]]
994 pas = [repo[ancestor]]
995
995
996 if node is None:
996 if node is None:
997 # Here is where we should consider bookmarks, divergent bookmarks,
997 # Here is where we should consider bookmarks, divergent bookmarks,
998 # foreground changesets (successors), and tip of current branch;
998 # foreground changesets (successors), and tip of current branch;
999 # but currently we are only checking the branch tips.
999 # but currently we are only checking the branch tips.
1000 try:
1000 try:
1001 node = repo.branchtip(wc.branch())
1001 node = repo.branchtip(wc.branch())
1002 except errormod.RepoLookupError:
1002 except errormod.RepoLookupError:
1003 if wc.branch() == 'default': # no default branch!
1003 if wc.branch() == 'default': # no default branch!
1004 node = repo.lookup('tip') # update to tip
1004 node = repo.lookup('tip') # update to tip
1005 else:
1005 else:
1006 raise util.Abort(_("branch %s not found") % wc.branch())
1006 raise util.Abort(_("branch %s not found") % wc.branch())
1007
1007
1008 if p1.obsolete() and not p1.children():
1008 if p1.obsolete() and not p1.children():
1009 # allow updating to successors
1009 # allow updating to successors
1010 successors = obsolete.successorssets(repo, p1.node())
1010 successors = obsolete.successorssets(repo, p1.node())
1011
1011
1012 # behavior of certain cases is as follows,
1012 # behavior of certain cases is as follows,
1013 #
1013 #
1014 # divergent changesets: update to highest rev, similar to what
1014 # divergent changesets: update to highest rev, similar to what
1015 # is currently done when there are more than one head
1015 # is currently done when there are more than one head
1016 # (i.e. 'tip')
1016 # (i.e. 'tip')
1017 #
1017 #
1018 # replaced changesets: same as divergent except we know there
1018 # replaced changesets: same as divergent except we know there
1019 # is no conflict
1019 # is no conflict
1020 #
1020 #
1021 # pruned changeset: no update is done; though, we could
1021 # pruned changeset: no update is done; though, we could
1022 # consider updating to the first non-obsolete parent,
1022 # consider updating to the first non-obsolete parent,
1023 # similar to what is current done for 'hg prune'
1023 # similar to what is current done for 'hg prune'
1024
1024
1025 if successors:
1025 if successors:
1026 # flatten the list here handles both divergent (len > 1)
1026 # flatten the list here handles both divergent (len > 1)
1027 # and the usual case (len = 1)
1027 # and the usual case (len = 1)
1028 successors = [n for sub in successors for n in sub]
1028 successors = [n for sub in successors for n in sub]
1029
1029
1030 # get the max revision for the given successors set,
1030 # get the max revision for the given successors set,
1031 # i.e. the 'tip' of a set
1031 # i.e. the 'tip' of a set
1032 node = repo.revs('max(%ln)', successors).first()
1032 node = repo.revs('max(%ln)', successors).first()
1033 pas = [p1]
1033 pas = [p1]
1034
1034
1035 overwrite = force and not branchmerge
1035 overwrite = force and not branchmerge
1036
1036
1037 p2 = repo[node]
1037 p2 = repo[node]
1038 if pas[0] is None:
1038 if pas[0] is None:
1039 if repo.ui.config('merge', 'preferancestor', '*') == '*':
1039 if repo.ui.config('merge', 'preferancestor', '*') == '*':
1040 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
1040 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
1041 pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
1041 pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
1042 else:
1042 else:
1043 pas = [p1.ancestor(p2, warn=branchmerge)]
1043 pas = [p1.ancestor(p2, warn=branchmerge)]
1044
1044
1045 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
1045 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
1046
1046
1047 ### check phase
1047 ### check phase
1048 if not overwrite and len(pl) > 1:
1048 if not overwrite and len(pl) > 1:
1049 raise util.Abort(_("outstanding uncommitted merge"))
1049 raise util.Abort(_("outstanding uncommitted merge"))
1050 if branchmerge:
1050 if branchmerge:
1051 if pas == [p2]:
1051 if pas == [p2]:
1052 raise util.Abort(_("merging with a working directory ancestor"
1052 raise util.Abort(_("merging with a working directory ancestor"
1053 " has no effect"))
1053 " has no effect"))
1054 elif pas == [p1]:
1054 elif pas == [p1]:
1055 if not mergeancestor and p1.branch() == p2.branch():
1055 if not mergeancestor and p1.branch() == p2.branch():
1056 raise util.Abort(_("nothing to merge"),
1056 raise util.Abort(_("nothing to merge"),
1057 hint=_("use 'hg update' "
1057 hint=_("use 'hg update' "
1058 "or check 'hg heads'"))
1058 "or check 'hg heads'"))
1059 if not force and (wc.files() or wc.deleted()):
1059 if not force and (wc.files() or wc.deleted()):
1060 raise util.Abort(_("uncommitted changes"),
1060 raise util.Abort(_("uncommitted changes"),
1061 hint=_("use 'hg status' to list changes"))
1061 hint=_("use 'hg status' to list changes"))
1062 for s in sorted(wc.substate):
1062 for s in sorted(wc.substate):
1063 if wc.sub(s).dirty():
1063 if wc.sub(s).dirty():
1064 raise util.Abort(_("uncommitted changes in "
1064 raise util.Abort(_("uncommitted changes in "
1065 "subrepository '%s'") % s)
1065 "subrepository '%s'") % s)
1066
1066
1067 elif not overwrite:
1067 elif not overwrite:
1068 if p1 == p2: # no-op update
1068 if p1 == p2: # no-op update
1069 # call the hooks and exit early
1069 # call the hooks and exit early
1070 repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
1070 repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
1071 repo.hook('update', parent1=xp2, parent2='', error=0)
1071 repo.hook('update', parent1=xp2, parent2='', error=0)
1072 return 0, 0, 0, 0
1072 return 0, 0, 0, 0
1073
1073
1074 if pas not in ([p1], [p2]): # nonlinear
1074 if pas not in ([p1], [p2]): # nonlinear
1075 dirty = wc.dirty(missing=True)
1075 dirty = wc.dirty(missing=True)
1076 if dirty or onode is None:
1076 if dirty or onode is None:
1077 # Branching is a bit strange to ensure we do the minimal
1077 # Branching is a bit strange to ensure we do the minimal
1078 # amount of call to obsolete.background.
1078 # amount of call to obsolete.background.
1079 foreground = obsolete.foreground(repo, [p1.node()])
1079 foreground = obsolete.foreground(repo, [p1.node()])
1080 # note: the <node> variable contains a random identifier
1080 # note: the <node> variable contains a random identifier
1081 if repo[node].node() in foreground:
1081 if repo[node].node() in foreground:
1082 pas = [p1] # allow updating to successors
1082 pas = [p1] # allow updating to successors
1083 elif dirty:
1083 elif dirty:
1084 msg = _("uncommitted changes")
1084 msg = _("uncommitted changes")
1085 if onode is None:
1085 if onode is None:
1086 hint = _("commit and merge, or update --clean to"
1086 hint = _("commit and merge, or update --clean to"
1087 " discard changes")
1087 " discard changes")
1088 else:
1088 else:
1089 hint = _("commit or update --clean to discard"
1089 hint = _("commit or update --clean to discard"
1090 " changes")
1090 " changes")
1091 raise util.Abort(msg, hint=hint)
1091 raise util.Abort(msg, hint=hint)
1092 else: # node is none
1092 else: # node is none
1093 msg = _("not a linear update")
1093 msg = _("not a linear update")
1094 hint = _("merge or update --check to force update")
1094 hint = _("merge or update --check to force update")
1095 raise util.Abort(msg, hint=hint)
1095 raise util.Abort(msg, hint=hint)
1096 else:
1096 else:
1097 # Allow jumping branches if clean and specific rev given
1097 # Allow jumping branches if clean and specific rev given
1098 pas = [p1]
1098 pas = [p1]
1099
1099
1100 followcopies = False
1100 followcopies = False
1101 if overwrite:
1101 if overwrite:
1102 pas = [wc]
1102 pas = [wc]
1103 elif pas == [p2]: # backwards
1103 elif pas == [p2]: # backwards
1104 pas = [wc.p1()]
1104 pas = [wc.p1()]
1105 elif not branchmerge and not wc.dirty(missing=True):
1105 elif not branchmerge and not wc.dirty(missing=True):
1106 pass
1106 pass
1107 elif pas[0] and repo.ui.configbool('merge', 'followcopies', True):
1107 elif pas[0] and repo.ui.configbool('merge', 'followcopies', True):
1108 followcopies = True
1108 followcopies = True
1109
1109
1110 ### calculate phase
1110 ### calculate phase
1111 actions = calculateupdates(repo, wc, p2, pas, branchmerge, force,
1111 actions = calculateupdates(repo, wc, p2, pas, branchmerge, force,
1112 partial, mergeancestor, followcopies)
1112 partial, mergeancestor, followcopies)
1113
1113
1114 ### apply phase
1114 ### apply phase
1115 if not branchmerge: # just jump to the new rev
1115 if not branchmerge: # just jump to the new rev
1116 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
1116 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
1117 if not partial:
1117 if not partial:
1118 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
1118 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
1119 # note that we're in the middle of an update
1119 # note that we're in the middle of an update
1120 repo.vfs.write('updatestate', p2.hex())
1120 repo.vfs.write('updatestate', p2.hex())
1121
1121
1122 stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
1122 stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
1123
1123
1124 if not partial:
1124 if not partial:
1125 repo.dirstate.beginparentchange()
1125 repo.dirstate.beginparentchange()
1126 repo.setparents(fp1, fp2)
1126 repo.setparents(fp1, fp2)
1127 recordupdates(repo, actions, branchmerge)
1127 recordupdates(repo, actions, branchmerge)
1128 # update completed, clear state
1128 # update completed, clear state
1129 util.unlink(repo.join('updatestate'))
1129 util.unlink(repo.join('updatestate'))
1130
1130
1131 if not branchmerge:
1131 if not branchmerge:
1132 repo.dirstate.setbranch(p2.branch())
1132 repo.dirstate.setbranch(p2.branch())
1133 repo.dirstate.endparentchange()
1133 repo.dirstate.endparentchange()
1134 finally:
1134 finally:
1135 wlock.release()
1135 wlock.release()
1136
1136
1137 if not partial:
1137 if not partial:
1138 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1138 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1139 return stats
1139 return stats
1140
1140
1141 def graft(repo, ctx, pctx, labels):
1141 def graft(repo, ctx, pctx, labels):
1142 """Do a graft-like merge.
1142 """Do a graft-like merge.
1143
1143
1144 This is a merge where the merge ancestor is chosen such that one
1144 This is a merge where the merge ancestor is chosen such that one
1145 or more changesets are grafted onto the current changeset. In
1145 or more changesets are grafted onto the current changeset. In
1146 addition to the merge, this fixes up the dirstate to include only
1146 addition to the merge, this fixes up the dirstate to include only
1147 a single parent and tries to duplicate any renames/copies
1147 a single parent and tries to duplicate any renames/copies
1148 appropriately.
1148 appropriately.
1149
1149
1150 ctx - changeset to rebase
1150 ctx - changeset to rebase
1151 pctx - merge base, usually ctx.p1()
1151 pctx - merge base, usually ctx.p1()
1152 labels - merge labels eg ['local', 'graft']
1152 labels - merge labels eg ['local', 'graft']
1153
1153
1154 """
1154 """
1155
1155
1156 stats = update(repo, ctx.node(), True, True, False, pctx.node(),
1156 stats = update(repo, ctx.node(), True, True, False, pctx.node(),
1157 labels=labels)
1157 labels=labels)
1158 # drop the second merge parent
1158 # drop the second merge parent
1159 repo.dirstate.beginparentchange()
1159 repo.dirstate.beginparentchange()
1160 repo.setparents(repo['.'].node(), nullid)
1160 repo.setparents(repo['.'].node(), nullid)
1161 repo.dirstate.write()
1161 repo.dirstate.write()
1162 # fix up dirstate for copies and renames
1162 # fix up dirstate for copies and renames
1163 copies.duplicatecopies(repo, ctx.rev(), pctx.rev())
1163 copies.duplicatecopies(repo, ctx.rev(), pctx.rev())
1164 repo.dirstate.endparentchange()
1164 repo.dirstate.endparentchange()
1165 return stats
1165 return stats
@@ -1,712 +1,712 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 (this also tests that editor is invoked if '--edit' is specified)
79 (this also tests that editor is invoked if '--edit' is specified)
80
80
81 $ hg status --rev "2^1" --rev 2
81 $ hg status --rev "2^1" --rev 2
82 A b
82 A b
83 R a
83 R a
84 $ HGEDITOR=cat hg graft 2 -u foo --edit
84 $ HGEDITOR=cat hg graft 2 -u foo --edit
85 grafting revision 2
85 grafting revision 2
86 merging a and b to b
86 merging a and b to b
87 2
87 2
88
88
89
89
90 HG: Enter commit message. Lines beginning with 'HG:' are removed.
90 HG: Enter commit message. Lines beginning with 'HG:' are removed.
91 HG: Leave message empty to abort commit.
91 HG: Leave message empty to abort commit.
92 HG: --
92 HG: --
93 HG: user: foo
93 HG: user: foo
94 HG: branch 'default'
94 HG: branch 'default'
95 HG: added b
95 HG: added b
96 HG: removed a
96 HG: removed a
97 $ hg export tip --git
97 $ hg export tip --git
98 # HG changeset patch
98 # HG changeset patch
99 # User foo
99 # User foo
100 # Date 0 0
100 # Date 0 0
101 # Thu Jan 01 00:00:00 1970 +0000
101 # Thu Jan 01 00:00:00 1970 +0000
102 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
102 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
103 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
103 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
104 2
104 2
105
105
106 diff --git a/a b/b
106 diff --git a/a b/b
107 rename from a
107 rename from a
108 rename to b
108 rename to b
109
109
110 Look for extra:source
110 Look for extra:source
111
111
112 $ hg log --debug -r tip
112 $ hg log --debug -r tip
113 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
113 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
114 tag: tip
114 tag: tip
115 phase: draft
115 phase: draft
116 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
116 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
117 parent: -1:0000000000000000000000000000000000000000
117 parent: -1:0000000000000000000000000000000000000000
118 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
118 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
119 user: foo
119 user: foo
120 date: Thu Jan 01 00:00:00 1970 +0000
120 date: Thu Jan 01 00:00:00 1970 +0000
121 files+: b
121 files+: b
122 files-: a
122 files-: a
123 extra: branch=default
123 extra: branch=default
124 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
124 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
125 description:
125 description:
126 2
126 2
127
127
128
128
129
129
130 Graft out of order, skipping a merge and a duplicate
130 Graft out of order, skipping a merge and a duplicate
131 (this also tests that editor is not invoked if '--edit' is not specified)
131 (this also tests that editor is not invoked if '--edit' is not specified)
132
132
133 $ hg graft 1 5 4 3 'merge()' 2 -n
133 $ hg graft 1 5 4 3 'merge()' 2 -n
134 skipping ungraftable merge revision 6
134 skipping ungraftable merge revision 6
135 skipping revision 2 (already grafted to 7)
135 skipping revision 2 (already grafted to 7)
136 grafting revision 1
136 grafting revision 1
137 grafting revision 5
137 grafting revision 5
138 grafting revision 4
138 grafting revision 4
139 grafting revision 3
139 grafting revision 3
140
140
141 $ HGEDITOR=cat hg graft 1 5 4 3 'merge()' 2 --debug
141 $ HGEDITOR=cat hg graft 1 5 4 3 'merge()' 2 --debug
142 skipping ungraftable merge revision 6
142 skipping ungraftable merge revision 6
143 scanning for duplicate grafts
143 scanning for duplicate grafts
144 skipping revision 2 (already grafted to 7)
144 skipping revision 2 (already grafted to 7)
145 grafting revision 1
145 grafting revision 1
146 searching for copies back to rev 1
146 searching for copies back to rev 1
147 unmatched files in local:
147 unmatched files in local:
148 b
148 b
149 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
149 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
150 src: 'a' -> dst: 'b' *
150 src: 'a' -> dst: 'b' *
151 checking for directory renames
151 checking for directory renames
152 resolving manifests
152 resolving manifests
153 branchmerge: True, force: True, partial: False
153 branchmerge: True, force: True, partial: False
154 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
154 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
155 preserving b for resolve of b
155 preserving b for resolve of b
156 b: local copied/moved from a -> m
156 b: local copied/moved from a -> m
157 updating: b 1/1 files (100.00%)
157 updating: b 1/1 files (100.00%)
158 picked tool 'internal:merge' for b (binary False symlink False)
158 picked tool 'internal:merge' for b (binary False symlink False)
159 merging b and a to b
159 merging b and a to b
160 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
160 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
161 premerge successful
161 premerge successful
162 b
162 b
163 grafting revision 5
163 grafting revision 5
164 searching for copies back to rev 1
164 searching for copies back to rev 1
165 resolving manifests
165 resolving manifests
166 branchmerge: True, force: True, partial: False
166 branchmerge: True, force: True, partial: False
167 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
167 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
168 e: remote is newer -> g
168 e: remote is newer -> g
169 getting e
169 getting e
170 updating: e 1/1 files (100.00%)
170 updating: e 1/1 files (100.00%)
171 b: keep -> k
171 b: remote unchanged -> k
172 e
172 e
173 grafting revision 4
173 grafting revision 4
174 searching for copies back to rev 1
174 searching for copies back to rev 1
175 resolving manifests
175 resolving manifests
176 branchmerge: True, force: True, partial: False
176 branchmerge: True, force: True, partial: False
177 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
177 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
178 preserving e for resolve of e
178 preserving e for resolve of e
179 d: remote is newer -> g
179 d: remote is newer -> g
180 getting d
180 getting d
181 updating: d 1/2 files (50.00%)
181 updating: d 1/2 files (50.00%)
182 b: keep -> k
182 b: remote unchanged -> k
183 e: versions differ -> m
183 e: versions differ -> m
184 updating: e 2/2 files (100.00%)
184 updating: e 2/2 files (100.00%)
185 picked tool 'internal:merge' for e (binary False symlink False)
185 picked tool 'internal:merge' for e (binary False symlink False)
186 merging e
186 merging e
187 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
187 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
188 warning: conflicts during merge.
188 warning: conflicts during merge.
189 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
189 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
190 abort: unresolved conflicts, can't continue
190 abort: unresolved conflicts, can't continue
191 (use hg resolve and hg graft --continue)
191 (use hg resolve and hg graft --continue)
192 [255]
192 [255]
193
193
194 Commit while interrupted should fail:
194 Commit while interrupted should fail:
195
195
196 $ hg ci -m 'commit interrupted graft'
196 $ hg ci -m 'commit interrupted graft'
197 abort: graft in progress
197 abort: graft in progress
198 (use 'hg graft --continue' or 'hg update' to abort)
198 (use 'hg graft --continue' or 'hg update' to abort)
199 [255]
199 [255]
200
200
201 Abort the graft and try committing:
201 Abort the graft and try committing:
202
202
203 $ hg up -C .
203 $ hg up -C .
204 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 $ echo c >> e
205 $ echo c >> e
206 $ hg ci -mtest
206 $ hg ci -mtest
207
207
208 $ hg strip . --config extensions.mq=
208 $ hg strip . --config extensions.mq=
209 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
209 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
210 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
210 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
211
211
212 Graft again:
212 Graft again:
213
213
214 $ hg graft 1 5 4 3 'merge()' 2
214 $ hg graft 1 5 4 3 'merge()' 2
215 skipping ungraftable merge revision 6
215 skipping ungraftable merge revision 6
216 skipping revision 2 (already grafted to 7)
216 skipping revision 2 (already grafted to 7)
217 skipping revision 1 (already grafted to 8)
217 skipping revision 1 (already grafted to 8)
218 skipping revision 5 (already grafted to 9)
218 skipping revision 5 (already grafted to 9)
219 grafting revision 4
219 grafting revision 4
220 merging e
220 merging e
221 warning: conflicts during merge.
221 warning: conflicts during merge.
222 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
222 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
223 abort: unresolved conflicts, can't continue
223 abort: unresolved conflicts, can't continue
224 (use hg resolve and hg graft --continue)
224 (use hg resolve and hg graft --continue)
225 [255]
225 [255]
226
226
227 Continue without resolve should fail:
227 Continue without resolve should fail:
228
228
229 $ hg graft -c
229 $ hg graft -c
230 grafting revision 4
230 grafting revision 4
231 abort: unresolved merge conflicts (see hg help resolve)
231 abort: unresolved merge conflicts (see hg help resolve)
232 [255]
232 [255]
233
233
234 Fix up:
234 Fix up:
235
235
236 $ echo b > e
236 $ echo b > e
237 $ hg resolve -m e
237 $ hg resolve -m e
238 (no more unresolved files)
238 (no more unresolved files)
239
239
240 Continue with a revision should fail:
240 Continue with a revision should fail:
241
241
242 $ hg graft -c 6
242 $ hg graft -c 6
243 abort: can't specify --continue and revisions
243 abort: can't specify --continue and revisions
244 [255]
244 [255]
245
245
246 $ hg graft -c -r 6
246 $ hg graft -c -r 6
247 abort: can't specify --continue and revisions
247 abort: can't specify --continue and revisions
248 [255]
248 [255]
249
249
250 Continue for real, clobber usernames
250 Continue for real, clobber usernames
251
251
252 $ hg graft -c -U
252 $ hg graft -c -U
253 grafting revision 4
253 grafting revision 4
254 grafting revision 3
254 grafting revision 3
255
255
256 Compare with original:
256 Compare with original:
257
257
258 $ hg diff -r 6
258 $ hg diff -r 6
259 $ hg status --rev 0:. -C
259 $ hg status --rev 0:. -C
260 M d
260 M d
261 M e
261 M e
262 A b
262 A b
263 a
263 a
264 A c
264 A c
265 a
265 a
266 R a
266 R a
267
267
268 View graph:
268 View graph:
269
269
270 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
270 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
271 @ test@11.draft: 3
271 @ test@11.draft: 3
272 |
272 |
273 o test@10.draft: 4
273 o test@10.draft: 4
274 |
274 |
275 o test@9.draft: 5
275 o test@9.draft: 5
276 |
276 |
277 o bar@8.draft: 1
277 o bar@8.draft: 1
278 |
278 |
279 o foo@7.draft: 2
279 o foo@7.draft: 2
280 |
280 |
281 | o test@6.secret: 6
281 | o test@6.secret: 6
282 | |\
282 | |\
283 | | o test@5.draft: 5
283 | | o test@5.draft: 5
284 | | |
284 | | |
285 | o | test@4.draft: 4
285 | o | test@4.draft: 4
286 | |/
286 | |/
287 | o baz@3.public: 3
287 | o baz@3.public: 3
288 | |
288 | |
289 | o test@2.public: 2
289 | o test@2.public: 2
290 | |
290 | |
291 | o bar@1.public: 1
291 | o bar@1.public: 1
292 |/
292 |/
293 o test@0.public: 0
293 o test@0.public: 0
294
294
295 Graft again onto another branch should preserve the original source
295 Graft again onto another branch should preserve the original source
296 $ hg up -q 0
296 $ hg up -q 0
297 $ echo 'g'>g
297 $ echo 'g'>g
298 $ hg add g
298 $ hg add g
299 $ hg ci -m 7
299 $ hg ci -m 7
300 created new head
300 created new head
301 $ hg graft 7
301 $ hg graft 7
302 grafting revision 7
302 grafting revision 7
303
303
304 $ hg log -r 7 --template '{rev}:{node}\n'
304 $ hg log -r 7 --template '{rev}:{node}\n'
305 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
305 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
306 $ hg log -r 2 --template '{rev}:{node}\n'
306 $ hg log -r 2 --template '{rev}:{node}\n'
307 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
307 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
308
308
309 $ hg log --debug -r tip
309 $ hg log --debug -r tip
310 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
310 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
311 tag: tip
311 tag: tip
312 phase: draft
312 phase: draft
313 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
313 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
314 parent: -1:0000000000000000000000000000000000000000
314 parent: -1:0000000000000000000000000000000000000000
315 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
315 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
316 user: foo
316 user: foo
317 date: Thu Jan 01 00:00:00 1970 +0000
317 date: Thu Jan 01 00:00:00 1970 +0000
318 files+: b
318 files+: b
319 files-: a
319 files-: a
320 extra: branch=default
320 extra: branch=default
321 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
321 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
322 description:
322 description:
323 2
323 2
324
324
325
325
326 Disallow grafting an already grafted cset onto its original branch
326 Disallow grafting an already grafted cset onto its original branch
327 $ hg up -q 6
327 $ hg up -q 6
328 $ hg graft 7
328 $ hg graft 7
329 skipping already grafted revision 7 (was grafted from 2)
329 skipping already grafted revision 7 (was grafted from 2)
330 [255]
330 [255]
331
331
332 Disallow grafting already grafted csets with the same origin onto each other
332 Disallow grafting already grafted csets with the same origin onto each other
333 $ hg up -q 13
333 $ hg up -q 13
334 $ hg graft 2
334 $ hg graft 2
335 skipping revision 2 (already grafted to 13)
335 skipping revision 2 (already grafted to 13)
336 [255]
336 [255]
337 $ hg graft 7
337 $ hg graft 7
338 skipping already grafted revision 7 (13 also has origin 2)
338 skipping already grafted revision 7 (13 also has origin 2)
339 [255]
339 [255]
340
340
341 $ hg up -q 7
341 $ hg up -q 7
342 $ hg graft 2
342 $ hg graft 2
343 skipping revision 2 (already grafted to 7)
343 skipping revision 2 (already grafted to 7)
344 [255]
344 [255]
345 $ hg graft tip
345 $ hg graft tip
346 skipping already grafted revision 13 (7 also has origin 2)
346 skipping already grafted revision 13 (7 also has origin 2)
347 [255]
347 [255]
348
348
349 Graft with --log
349 Graft with --log
350
350
351 $ hg up -Cq 1
351 $ hg up -Cq 1
352 $ hg graft 3 --log -u foo
352 $ hg graft 3 --log -u foo
353 grafting revision 3
353 grafting revision 3
354 warning: can't find ancestor for 'c' copied from 'b'!
354 warning: can't find ancestor for 'c' copied from 'b'!
355 $ hg log --template '{rev} {parents} {desc}\n' -r tip
355 $ hg log --template '{rev} {parents} {desc}\n' -r tip
356 14 1:5d205f8b35b6 3
356 14 1:5d205f8b35b6 3
357 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
357 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
358
358
359 Resolve conflicted graft
359 Resolve conflicted graft
360 $ hg up -q 0
360 $ hg up -q 0
361 $ echo b > a
361 $ echo b > a
362 $ hg ci -m 8
362 $ hg ci -m 8
363 created new head
363 created new head
364 $ echo c > a
364 $ echo c > a
365 $ hg ci -m 9
365 $ hg ci -m 9
366 $ hg graft 1 --tool internal:fail
366 $ hg graft 1 --tool internal:fail
367 grafting revision 1
367 grafting revision 1
368 abort: unresolved conflicts, can't continue
368 abort: unresolved conflicts, can't continue
369 (use hg resolve and hg graft --continue)
369 (use hg resolve and hg graft --continue)
370 [255]
370 [255]
371 $ hg resolve --all
371 $ hg resolve --all
372 merging a
372 merging a
373 warning: conflicts during merge.
373 warning: conflicts during merge.
374 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
374 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
375 [1]
375 [1]
376 $ cat a
376 $ cat a
377 <<<<<<< local: aaa4406d4f0a - test: 9
377 <<<<<<< local: aaa4406d4f0a - test: 9
378 c
378 c
379 =======
379 =======
380 b
380 b
381 >>>>>>> other: 5d205f8b35b6 - bar: 1
381 >>>>>>> other: 5d205f8b35b6 - bar: 1
382 $ echo b > a
382 $ echo b > a
383 $ hg resolve -m a
383 $ hg resolve -m a
384 (no more unresolved files)
384 (no more unresolved files)
385 $ hg graft -c
385 $ hg graft -c
386 grafting revision 1
386 grafting revision 1
387 $ hg export tip --git
387 $ hg export tip --git
388 # HG changeset patch
388 # HG changeset patch
389 # User bar
389 # User bar
390 # Date 0 0
390 # Date 0 0
391 # Thu Jan 01 00:00:00 1970 +0000
391 # Thu Jan 01 00:00:00 1970 +0000
392 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
392 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
393 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
393 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
394 1
394 1
395
395
396 diff --git a/a b/a
396 diff --git a/a b/a
397 --- a/a
397 --- a/a
398 +++ b/a
398 +++ b/a
399 @@ -1,1 +1,1 @@
399 @@ -1,1 +1,1 @@
400 -c
400 -c
401 +b
401 +b
402
402
403 Resolve conflicted graft with rename
403 Resolve conflicted graft with rename
404 $ echo c > a
404 $ echo c > a
405 $ hg ci -m 10
405 $ hg ci -m 10
406 $ hg graft 2 --tool internal:fail
406 $ hg graft 2 --tool internal:fail
407 grafting revision 2
407 grafting revision 2
408 abort: unresolved conflicts, can't continue
408 abort: unresolved conflicts, can't continue
409 (use hg resolve and hg graft --continue)
409 (use hg resolve and hg graft --continue)
410 [255]
410 [255]
411 $ hg resolve --all
411 $ hg resolve --all
412 merging a and b to b
412 merging a and b to b
413 (no more unresolved files)
413 (no more unresolved files)
414 $ hg graft -c
414 $ hg graft -c
415 grafting revision 2
415 grafting revision 2
416 $ hg export tip --git
416 $ hg export tip --git
417 # HG changeset patch
417 # HG changeset patch
418 # User test
418 # User test
419 # Date 0 0
419 # Date 0 0
420 # Thu Jan 01 00:00:00 1970 +0000
420 # Thu Jan 01 00:00:00 1970 +0000
421 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
421 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
422 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
422 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
423 2
423 2
424
424
425 diff --git a/a b/b
425 diff --git a/a b/b
426 rename from a
426 rename from a
427 rename to b
427 rename to b
428
428
429 Test simple origin(), with and without args
429 Test simple origin(), with and without args
430 $ hg log -r 'origin()'
430 $ hg log -r 'origin()'
431 changeset: 1:5d205f8b35b6
431 changeset: 1:5d205f8b35b6
432 user: bar
432 user: bar
433 date: Thu Jan 01 00:00:00 1970 +0000
433 date: Thu Jan 01 00:00:00 1970 +0000
434 summary: 1
434 summary: 1
435
435
436 changeset: 2:5c095ad7e90f
436 changeset: 2:5c095ad7e90f
437 user: test
437 user: test
438 date: Thu Jan 01 00:00:00 1970 +0000
438 date: Thu Jan 01 00:00:00 1970 +0000
439 summary: 2
439 summary: 2
440
440
441 changeset: 3:4c60f11aa304
441 changeset: 3:4c60f11aa304
442 user: baz
442 user: baz
443 date: Thu Jan 01 00:00:00 1970 +0000
443 date: Thu Jan 01 00:00:00 1970 +0000
444 summary: 3
444 summary: 3
445
445
446 changeset: 4:9c233e8e184d
446 changeset: 4:9c233e8e184d
447 user: test
447 user: test
448 date: Thu Jan 01 00:00:00 1970 +0000
448 date: Thu Jan 01 00:00:00 1970 +0000
449 summary: 4
449 summary: 4
450
450
451 changeset: 5:97f8bfe72746
451 changeset: 5:97f8bfe72746
452 branch: stable
452 branch: stable
453 parent: 3:4c60f11aa304
453 parent: 3:4c60f11aa304
454 user: test
454 user: test
455 date: Thu Jan 01 00:00:00 1970 +0000
455 date: Thu Jan 01 00:00:00 1970 +0000
456 summary: 5
456 summary: 5
457
457
458 $ hg log -r 'origin(7)'
458 $ hg log -r 'origin(7)'
459 changeset: 2:5c095ad7e90f
459 changeset: 2:5c095ad7e90f
460 user: test
460 user: test
461 date: Thu Jan 01 00:00:00 1970 +0000
461 date: Thu Jan 01 00:00:00 1970 +0000
462 summary: 2
462 summary: 2
463
463
464 Now transplant a graft to test following through copies
464 Now transplant a graft to test following through copies
465 $ hg up -q 0
465 $ hg up -q 0
466 $ hg branch -q dev
466 $ hg branch -q dev
467 $ hg ci -qm "dev branch"
467 $ hg ci -qm "dev branch"
468 $ hg --config extensions.transplant= transplant -q 7
468 $ hg --config extensions.transplant= transplant -q 7
469 $ hg log -r 'origin(.)'
469 $ hg log -r 'origin(.)'
470 changeset: 2:5c095ad7e90f
470 changeset: 2:5c095ad7e90f
471 user: test
471 user: test
472 date: Thu Jan 01 00:00:00 1970 +0000
472 date: Thu Jan 01 00:00:00 1970 +0000
473 summary: 2
473 summary: 2
474
474
475 Test that the graft and transplant markers in extra are converted, allowing
475 Test that the graft and transplant markers in extra are converted, allowing
476 origin() to still work. Note that these recheck the immediately preceeding two
476 origin() to still work. Note that these recheck the immediately preceeding two
477 tests.
477 tests.
478 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
478 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
479
479
480 The graft case
480 The graft case
481 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
481 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
482 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
482 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
483 branch=default
483 branch=default
484 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
484 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
485 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
485 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
486 $ hg -R ../converted log -r 'origin(7)'
486 $ hg -R ../converted log -r 'origin(7)'
487 changeset: 2:e0213322b2c1
487 changeset: 2:e0213322b2c1
488 user: test
488 user: test
489 date: Thu Jan 01 00:00:00 1970 +0000
489 date: Thu Jan 01 00:00:00 1970 +0000
490 summary: 2
490 summary: 2
491
491
492 Test that template correctly expands more than one 'extra' (issue4362)
492 Test that template correctly expands more than one 'extra' (issue4362)
493 $ hg -R ../converted log -r 7 --template "{extras % ' Extra: {extra}\n'}"
493 $ hg -R ../converted log -r 7 --template "{extras % ' Extra: {extra}\n'}"
494 Extra: branch=default
494 Extra: branch=default
495 Extra: convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
495 Extra: convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
496 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
496 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
497
497
498 The transplant case
498 The transplant case
499 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
499 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
500 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
500 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
501 branch=dev
501 branch=dev
502 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
502 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
503 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
503 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
504 `h\x9b (esc)
504 `h\x9b (esc)
505 $ hg -R ../converted log -r 'origin(tip)'
505 $ hg -R ../converted log -r 'origin(tip)'
506 changeset: 2:e0213322b2c1
506 changeset: 2:e0213322b2c1
507 user: test
507 user: test
508 date: Thu Jan 01 00:00:00 1970 +0000
508 date: Thu Jan 01 00:00:00 1970 +0000
509 summary: 2
509 summary: 2
510
510
511
511
512 Test simple destination
512 Test simple destination
513 $ hg log -r 'destination()'
513 $ hg log -r 'destination()'
514 changeset: 7:ef0ef43d49e7
514 changeset: 7:ef0ef43d49e7
515 parent: 0:68795b066622
515 parent: 0:68795b066622
516 user: foo
516 user: foo
517 date: Thu Jan 01 00:00:00 1970 +0000
517 date: Thu Jan 01 00:00:00 1970 +0000
518 summary: 2
518 summary: 2
519
519
520 changeset: 8:6b9e5368ca4e
520 changeset: 8:6b9e5368ca4e
521 user: bar
521 user: bar
522 date: Thu Jan 01 00:00:00 1970 +0000
522 date: Thu Jan 01 00:00:00 1970 +0000
523 summary: 1
523 summary: 1
524
524
525 changeset: 9:1905859650ec
525 changeset: 9:1905859650ec
526 user: test
526 user: test
527 date: Thu Jan 01 00:00:00 1970 +0000
527 date: Thu Jan 01 00:00:00 1970 +0000
528 summary: 5
528 summary: 5
529
529
530 changeset: 10:52dc0b4c6907
530 changeset: 10:52dc0b4c6907
531 user: test
531 user: test
532 date: Thu Jan 01 00:00:00 1970 +0000
532 date: Thu Jan 01 00:00:00 1970 +0000
533 summary: 4
533 summary: 4
534
534
535 changeset: 11:882b35362a6b
535 changeset: 11:882b35362a6b
536 user: test
536 user: test
537 date: Thu Jan 01 00:00:00 1970 +0000
537 date: Thu Jan 01 00:00:00 1970 +0000
538 summary: 3
538 summary: 3
539
539
540 changeset: 13:9db0f28fd374
540 changeset: 13:9db0f28fd374
541 user: foo
541 user: foo
542 date: Thu Jan 01 00:00:00 1970 +0000
542 date: Thu Jan 01 00:00:00 1970 +0000
543 summary: 2
543 summary: 2
544
544
545 changeset: 14:f64defefacee
545 changeset: 14:f64defefacee
546 parent: 1:5d205f8b35b6
546 parent: 1:5d205f8b35b6
547 user: foo
547 user: foo
548 date: Thu Jan 01 00:00:00 1970 +0000
548 date: Thu Jan 01 00:00:00 1970 +0000
549 summary: 3
549 summary: 3
550
550
551 changeset: 17:f67661df0c48
551 changeset: 17:f67661df0c48
552 user: bar
552 user: bar
553 date: Thu Jan 01 00:00:00 1970 +0000
553 date: Thu Jan 01 00:00:00 1970 +0000
554 summary: 1
554 summary: 1
555
555
556 changeset: 19:9627f653b421
556 changeset: 19:9627f653b421
557 user: test
557 user: test
558 date: Thu Jan 01 00:00:00 1970 +0000
558 date: Thu Jan 01 00:00:00 1970 +0000
559 summary: 2
559 summary: 2
560
560
561 changeset: 21:7e61b508e709
561 changeset: 21:7e61b508e709
562 branch: dev
562 branch: dev
563 tag: tip
563 tag: tip
564 user: foo
564 user: foo
565 date: Thu Jan 01 00:00:00 1970 +0000
565 date: Thu Jan 01 00:00:00 1970 +0000
566 summary: 2
566 summary: 2
567
567
568 $ hg log -r 'destination(2)'
568 $ hg log -r 'destination(2)'
569 changeset: 7:ef0ef43d49e7
569 changeset: 7:ef0ef43d49e7
570 parent: 0:68795b066622
570 parent: 0:68795b066622
571 user: foo
571 user: foo
572 date: Thu Jan 01 00:00:00 1970 +0000
572 date: Thu Jan 01 00:00:00 1970 +0000
573 summary: 2
573 summary: 2
574
574
575 changeset: 13:9db0f28fd374
575 changeset: 13:9db0f28fd374
576 user: foo
576 user: foo
577 date: Thu Jan 01 00:00:00 1970 +0000
577 date: Thu Jan 01 00:00:00 1970 +0000
578 summary: 2
578 summary: 2
579
579
580 changeset: 19:9627f653b421
580 changeset: 19:9627f653b421
581 user: test
581 user: test
582 date: Thu Jan 01 00:00:00 1970 +0000
582 date: Thu Jan 01 00:00:00 1970 +0000
583 summary: 2
583 summary: 2
584
584
585 changeset: 21:7e61b508e709
585 changeset: 21:7e61b508e709
586 branch: dev
586 branch: dev
587 tag: tip
587 tag: tip
588 user: foo
588 user: foo
589 date: Thu Jan 01 00:00:00 1970 +0000
589 date: Thu Jan 01 00:00:00 1970 +0000
590 summary: 2
590 summary: 2
591
591
592 Transplants of grafts can find a destination...
592 Transplants of grafts can find a destination...
593 $ hg log -r 'destination(7)'
593 $ hg log -r 'destination(7)'
594 changeset: 21:7e61b508e709
594 changeset: 21:7e61b508e709
595 branch: dev
595 branch: dev
596 tag: tip
596 tag: tip
597 user: foo
597 user: foo
598 date: Thu Jan 01 00:00:00 1970 +0000
598 date: Thu Jan 01 00:00:00 1970 +0000
599 summary: 2
599 summary: 2
600
600
601 ... grafts of grafts unfortunately can't
601 ... grafts of grafts unfortunately can't
602 $ hg graft -q 13
602 $ hg graft -q 13
603 $ hg log -r 'destination(13)'
603 $ hg log -r 'destination(13)'
604 All copies of a cset
604 All copies of a cset
605 $ hg log -r 'origin(13) or destination(origin(13))'
605 $ hg log -r 'origin(13) or destination(origin(13))'
606 changeset: 2:5c095ad7e90f
606 changeset: 2:5c095ad7e90f
607 user: test
607 user: test
608 date: Thu Jan 01 00:00:00 1970 +0000
608 date: Thu Jan 01 00:00:00 1970 +0000
609 summary: 2
609 summary: 2
610
610
611 changeset: 7:ef0ef43d49e7
611 changeset: 7:ef0ef43d49e7
612 parent: 0:68795b066622
612 parent: 0:68795b066622
613 user: foo
613 user: foo
614 date: Thu Jan 01 00:00:00 1970 +0000
614 date: Thu Jan 01 00:00:00 1970 +0000
615 summary: 2
615 summary: 2
616
616
617 changeset: 13:9db0f28fd374
617 changeset: 13:9db0f28fd374
618 user: foo
618 user: foo
619 date: Thu Jan 01 00:00:00 1970 +0000
619 date: Thu Jan 01 00:00:00 1970 +0000
620 summary: 2
620 summary: 2
621
621
622 changeset: 19:9627f653b421
622 changeset: 19:9627f653b421
623 user: test
623 user: test
624 date: Thu Jan 01 00:00:00 1970 +0000
624 date: Thu Jan 01 00:00:00 1970 +0000
625 summary: 2
625 summary: 2
626
626
627 changeset: 21:7e61b508e709
627 changeset: 21:7e61b508e709
628 branch: dev
628 branch: dev
629 user: foo
629 user: foo
630 date: Thu Jan 01 00:00:00 1970 +0000
630 date: Thu Jan 01 00:00:00 1970 +0000
631 summary: 2
631 summary: 2
632
632
633 changeset: 22:1313d0a825e2
633 changeset: 22:1313d0a825e2
634 branch: dev
634 branch: dev
635 tag: tip
635 tag: tip
636 user: foo
636 user: foo
637 date: Thu Jan 01 00:00:00 1970 +0000
637 date: Thu Jan 01 00:00:00 1970 +0000
638 summary: 2
638 summary: 2
639
639
640
640
641 graft works on complex revset
641 graft works on complex revset
642
642
643 $ hg graft 'origin(13) or destination(origin(13))'
643 $ hg graft 'origin(13) or destination(origin(13))'
644 skipping ancestor revision 21
644 skipping ancestor revision 21
645 skipping ancestor revision 22
645 skipping ancestor revision 22
646 skipping revision 2 (already grafted to 22)
646 skipping revision 2 (already grafted to 22)
647 grafting revision 7
647 grafting revision 7
648 grafting revision 13
648 grafting revision 13
649 grafting revision 19
649 grafting revision 19
650 merging b
650 merging b
651
651
652 graft with --force (still doesn't graft merges)
652 graft with --force (still doesn't graft merges)
653
653
654 $ hg graft 19 0 6
654 $ hg graft 19 0 6
655 skipping ungraftable merge revision 6
655 skipping ungraftable merge revision 6
656 skipping ancestor revision 0
656 skipping ancestor revision 0
657 skipping already grafted revision 19 (22 also has origin 2)
657 skipping already grafted revision 19 (22 also has origin 2)
658 [255]
658 [255]
659 $ hg graft 19 0 6 --force
659 $ hg graft 19 0 6 --force
660 skipping ungraftable merge revision 6
660 skipping ungraftable merge revision 6
661 grafting revision 19
661 grafting revision 19
662 merging b
662 merging b
663 grafting revision 0
663 grafting revision 0
664
664
665 graft --force after backout
665 graft --force after backout
666
666
667 $ echo abc > a
667 $ echo abc > a
668 $ hg ci -m 28
668 $ hg ci -m 28
669 $ hg backout 28
669 $ hg backout 28
670 reverting a
670 reverting a
671 changeset 29:484c03b8dfa4 backs out changeset 28:6c56f0f7f033
671 changeset 29:484c03b8dfa4 backs out changeset 28:6c56f0f7f033
672 $ hg graft 28
672 $ hg graft 28
673 skipping ancestor revision 28
673 skipping ancestor revision 28
674 [255]
674 [255]
675 $ hg graft 28 --force
675 $ hg graft 28 --force
676 grafting revision 28
676 grafting revision 28
677 merging a
677 merging a
678 $ cat a
678 $ cat a
679 abc
679 abc
680
680
681 graft --continue after --force
681 graft --continue after --force
682
682
683 $ echo def > a
683 $ echo def > a
684 $ hg ci -m 31
684 $ hg ci -m 31
685 $ hg graft 28 --force --tool internal:fail
685 $ hg graft 28 --force --tool internal:fail
686 grafting revision 28
686 grafting revision 28
687 abort: unresolved conflicts, can't continue
687 abort: unresolved conflicts, can't continue
688 (use hg resolve and hg graft --continue)
688 (use hg resolve and hg graft --continue)
689 [255]
689 [255]
690 $ hg resolve --all
690 $ hg resolve --all
691 merging a
691 merging a
692 warning: conflicts during merge.
692 warning: conflicts during merge.
693 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
693 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
694 [1]
694 [1]
695 $ echo abc > a
695 $ echo abc > a
696 $ hg resolve -m a
696 $ hg resolve -m a
697 (no more unresolved files)
697 (no more unresolved files)
698 $ hg graft -c
698 $ hg graft -c
699 grafting revision 28
699 grafting revision 28
700 $ cat a
700 $ cat a
701 abc
701 abc
702
702
703 Continue testing same origin policy, using revision numbers from test above
703 Continue testing same origin policy, using revision numbers from test above
704 but do some destructive editing of the repo:
704 but do some destructive editing of the repo:
705
705
706 $ hg up -qC 7
706 $ hg up -qC 7
707 $ hg tag -l -r 13 tmp
707 $ hg tag -l -r 13 tmp
708 $ hg --config extensions.mq= strip 2
708 $ hg --config extensions.mq= strip 2
709 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-backup.hg (glob)
709 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-backup.hg (glob)
710 $ hg graft tmp
710 $ hg graft tmp
711 skipping already grafted revision 8 (2 also has unknown origin 5c095ad7e90f871700f02dd1fa5012cb4498a2d4)
711 skipping already grafted revision 8 (2 also has unknown origin 5c095ad7e90f871700f02dd1fa5012cb4498a2d4)
712 [255]
712 [255]
@@ -1,102 +1,102 b''
1 http://mercurial.selenic.com/bts/issue672
1 http://mercurial.selenic.com/bts/issue672
2
2
3 # 0-2-4
3 # 0-2-4
4 # \ \ \
4 # \ \ \
5 # 1-3-5
5 # 1-3-5
6 #
6 #
7 # rename in #1, content change in #4.
7 # rename in #1, content change in #4.
8
8
9 $ hg init
9 $ hg init
10
10
11 $ touch 1
11 $ touch 1
12 $ touch 2
12 $ touch 2
13 $ hg commit -Am init # 0
13 $ hg commit -Am init # 0
14 adding 1
14 adding 1
15 adding 2
15 adding 2
16
16
17 $ hg rename 1 1a
17 $ hg rename 1 1a
18 $ hg commit -m rename # 1
18 $ hg commit -m rename # 1
19
19
20 $ hg co -C 0
20 $ hg co -C 0
21 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
21 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
22
22
23 $ echo unrelated >> 2
23 $ echo unrelated >> 2
24 $ hg ci -m unrelated1 # 2
24 $ hg ci -m unrelated1 # 2
25 created new head
25 created new head
26
26
27 $ hg merge --debug 1
27 $ hg merge --debug 1
28 searching for copies back to rev 1
28 searching for copies back to rev 1
29 unmatched files in other:
29 unmatched files in other:
30 1a
30 1a
31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
32 src: '1' -> dst: '1a'
32 src: '1' -> dst: '1a'
33 checking for directory renames
33 checking for directory renames
34 resolving manifests
34 resolving manifests
35 branchmerge: True, force: False, partial: False
35 branchmerge: True, force: False, partial: False
36 ancestor: 81f4b099af3d, local: c64f439569a9+, remote: c12dcd37c90a
36 ancestor: 81f4b099af3d, local: c64f439569a9+, remote: c12dcd37c90a
37 1: other deleted -> r
37 1: other deleted -> r
38 removing 1
38 removing 1
39 updating: 1 1/2 files (50.00%)
39 updating: 1 1/2 files (50.00%)
40 1a: remote created -> g
40 1a: remote created -> g
41 getting 1a
41 getting 1a
42 updating: 1a 2/2 files (100.00%)
42 updating: 1a 2/2 files (100.00%)
43 2: keep -> k
43 2: remote unchanged -> k
44 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
44 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
45 (branch merge, don't forget to commit)
45 (branch merge, don't forget to commit)
46
46
47 $ hg ci -m merge1 # 3
47 $ hg ci -m merge1 # 3
48
48
49 $ hg co -C 2
49 $ hg co -C 2
50 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
50 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
51
51
52 $ echo hello >> 1
52 $ echo hello >> 1
53 $ hg ci -m unrelated2 # 4
53 $ hg ci -m unrelated2 # 4
54 created new head
54 created new head
55
55
56 $ hg co -C 3
56 $ hg co -C 3
57 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
57 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
58
58
59 $ hg merge -y --debug 4
59 $ hg merge -y --debug 4
60 searching for copies back to rev 1
60 searching for copies back to rev 1
61 unmatched files in local:
61 unmatched files in local:
62 1a
62 1a
63 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
63 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
64 src: '1' -> dst: '1a' *
64 src: '1' -> dst: '1a' *
65 checking for directory renames
65 checking for directory renames
66 resolving manifests
66 resolving manifests
67 branchmerge: True, force: False, partial: False
67 branchmerge: True, force: False, partial: False
68 ancestor: c64f439569a9, local: e327dca35ac8+, remote: 746e9549ea96
68 ancestor: c64f439569a9, local: e327dca35ac8+, remote: 746e9549ea96
69 preserving 1a for resolve of 1a
69 preserving 1a for resolve of 1a
70 1a: local copied/moved from 1 -> m
70 1a: local copied/moved from 1 -> m
71 updating: 1a 1/1 files (100.00%)
71 updating: 1a 1/1 files (100.00%)
72 picked tool 'internal:merge' for 1a (binary False symlink False)
72 picked tool 'internal:merge' for 1a (binary False symlink False)
73 merging 1a and 1 to 1a
73 merging 1a and 1 to 1a
74 my 1a@e327dca35ac8+ other 1@746e9549ea96 ancestor 1@81f4b099af3d
74 my 1a@e327dca35ac8+ other 1@746e9549ea96 ancestor 1@81f4b099af3d
75 premerge successful
75 premerge successful
76 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
76 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
77 (branch merge, don't forget to commit)
77 (branch merge, don't forget to commit)
78
78
79 $ hg co -C 4
79 $ hg co -C 4
80 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
80 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
81
81
82 $ hg merge -y --debug 3
82 $ hg merge -y --debug 3
83 searching for copies back to rev 1
83 searching for copies back to rev 1
84 unmatched files in other:
84 unmatched files in other:
85 1a
85 1a
86 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
86 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
87 src: '1' -> dst: '1a' *
87 src: '1' -> dst: '1a' *
88 checking for directory renames
88 checking for directory renames
89 resolving manifests
89 resolving manifests
90 branchmerge: True, force: False, partial: False
90 branchmerge: True, force: False, partial: False
91 ancestor: c64f439569a9, local: 746e9549ea96+, remote: e327dca35ac8
91 ancestor: c64f439569a9, local: 746e9549ea96+, remote: e327dca35ac8
92 preserving 1 for resolve of 1a
92 preserving 1 for resolve of 1a
93 removing 1
93 removing 1
94 1a: remote moved from 1 -> m
94 1a: remote moved from 1 -> m
95 updating: 1a 1/1 files (100.00%)
95 updating: 1a 1/1 files (100.00%)
96 picked tool 'internal:merge' for 1a (binary False symlink False)
96 picked tool 'internal:merge' for 1a (binary False symlink False)
97 merging 1 and 1a to 1a
97 merging 1 and 1a to 1a
98 my 1a@746e9549ea96+ other 1a@e327dca35ac8 ancestor 1@81f4b099af3d
98 my 1a@746e9549ea96+ other 1a@e327dca35ac8 ancestor 1@81f4b099af3d
99 premerge successful
99 premerge successful
100 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
100 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
101 (branch merge, don't forget to commit)
101 (branch merge, don't forget to commit)
102
102
@@ -1,354 +1,354 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 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
27 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 $ echo '6 second change' > f2
28 $ echo '6 second change' > f2
29 $ hg ci -m '6 second change f2'
29 $ hg ci -m '6 second change f2'
30
30
31 $ hg log -G
31 $ hg log -G
32 @ changeset: 6:3b08d01b0ab5
32 @ changeset: 6:3b08d01b0ab5
33 | tag: tip
33 | tag: tip
34 | parent: 3:cf89f02107e5
34 | parent: 3:cf89f02107e5
35 | user: test
35 | user: test
36 | date: Thu Jan 01 00:00:00 1970 +0000
36 | date: Thu Jan 01 00:00:00 1970 +0000
37 | summary: 6 second change f2
37 | summary: 6 second change f2
38 |
38 |
39 | o changeset: 5:adfe50279922
39 | o changeset: 5:adfe50279922
40 | | user: test
40 | | user: test
41 | | date: Thu Jan 01 00:00:00 1970 +0000
41 | | date: Thu Jan 01 00:00:00 1970 +0000
42 | | summary: 5 second change f1
42 | | summary: 5 second change f1
43 | |
43 | |
44 | o changeset: 4:7d3e55501ae6
44 | o changeset: 4:7d3e55501ae6
45 | |\ parent: 2:40663881a6dd
45 | |\ parent: 2:40663881a6dd
46 | | | parent: 1:0f6b37dbe527
46 | | | parent: 1:0f6b37dbe527
47 | | | user: test
47 | | | user: test
48 | | | date: Thu Jan 01 00:00:00 1970 +0000
48 | | | date: Thu Jan 01 00:00:00 1970 +0000
49 | | | summary: 4 merge
49 | | | summary: 4 merge
50 | | |
50 | | |
51 o---+ changeset: 3:cf89f02107e5
51 o---+ changeset: 3:cf89f02107e5
52 | | | parent: 2:40663881a6dd
52 | | | parent: 2:40663881a6dd
53 |/ / parent: 1:0f6b37dbe527
53 |/ / parent: 1:0f6b37dbe527
54 | | user: test
54 | | user: test
55 | | date: Thu Jan 01 00:00:00 1970 +0000
55 | | date: Thu Jan 01 00:00:00 1970 +0000
56 | | summary: 3 merge
56 | | summary: 3 merge
57 | |
57 | |
58 | o changeset: 2:40663881a6dd
58 | o changeset: 2:40663881a6dd
59 | | parent: 0:40494bf2444c
59 | | parent: 0:40494bf2444c
60 | | user: test
60 | | user: test
61 | | date: Thu Jan 01 00:00:00 1970 +0000
61 | | date: Thu Jan 01 00:00:00 1970 +0000
62 | | summary: 2 first change f2
62 | | summary: 2 first change f2
63 | |
63 | |
64 o | changeset: 1:0f6b37dbe527
64 o | changeset: 1:0f6b37dbe527
65 |/ user: test
65 |/ user: test
66 | date: Thu Jan 01 00:00:00 1970 +0000
66 | date: Thu Jan 01 00:00:00 1970 +0000
67 | summary: 1 first change f1
67 | summary: 1 first change f1
68 |
68 |
69 o changeset: 0:40494bf2444c
69 o changeset: 0:40494bf2444c
70 user: test
70 user: test
71 date: Thu Jan 01 00:00:00 1970 +0000
71 date: Thu Jan 01 00:00:00 1970 +0000
72 summary: 0 base
72 summary: 0 base
73
73
74
74
75 $ hg merge -v --debug --tool internal:dump 5 --config merge.preferancestor='!'
75 $ hg merge -v --debug --tool internal:dump 5 --config merge.preferancestor='!'
76 note: using 0f6b37dbe527 as ancestor of 3b08d01b0ab5 and adfe50279922
76 note: using 0f6b37dbe527 as ancestor of 3b08d01b0ab5 and adfe50279922
77 alternatively, use --config merge.preferancestor=40663881a6dd
77 alternatively, use --config merge.preferancestor=40663881a6dd
78 searching for copies back to rev 3
78 searching for copies back to rev 3
79 resolving manifests
79 resolving manifests
80 branchmerge: True, force: False, partial: False
80 branchmerge: True, force: False, partial: False
81 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
81 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
82 preserving f2 for resolve of f2
82 preserving f2 for resolve of f2
83 f1: remote is newer -> g
83 f1: remote is newer -> g
84 getting f1
84 getting f1
85 updating: f1 1/2 files (50.00%)
85 updating: f1 1/2 files (50.00%)
86 f2: versions differ -> m
86 f2: versions differ -> m
87 updating: f2 2/2 files (100.00%)
87 updating: f2 2/2 files (100.00%)
88 picked tool 'internal:dump' for f2 (binary False symlink False)
88 picked tool 'internal:dump' for f2 (binary False symlink False)
89 merging f2
89 merging f2
90 my f2@3b08d01b0ab5+ other f2@adfe50279922 ancestor f2@40494bf2444c
90 my f2@3b08d01b0ab5+ other f2@adfe50279922 ancestor f2@40494bf2444c
91 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
91 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
92 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
92 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
93 [1]
93 [1]
94
94
95 $ head *
95 $ head *
96 ==> f1 <==
96 ==> f1 <==
97 5 second change
97 5 second change
98
98
99 ==> f2 <==
99 ==> f2 <==
100 6 second change
100 6 second change
101
101
102 ==> f2.base <==
102 ==> f2.base <==
103 0 base
103 0 base
104
104
105 ==> f2.local <==
105 ==> f2.local <==
106 6 second change
106 6 second change
107
107
108 ==> f2.orig <==
108 ==> f2.orig <==
109 6 second change
109 6 second change
110
110
111 ==> f2.other <==
111 ==> f2.other <==
112 2 first change
112 2 first change
113
113
114 $ hg up -qC .
114 $ hg up -qC .
115 $ hg merge -v --tool internal:dump 5 --config merge.preferancestor="null 40663881 3b08d"
115 $ hg merge -v --tool internal:dump 5 --config merge.preferancestor="null 40663881 3b08d"
116 note: using 40663881a6dd as ancestor of 3b08d01b0ab5 and adfe50279922
116 note: using 40663881a6dd as ancestor of 3b08d01b0ab5 and adfe50279922
117 alternatively, use --config merge.preferancestor=0f6b37dbe527
117 alternatively, use --config merge.preferancestor=0f6b37dbe527
118 resolving manifests
118 resolving manifests
119 merging f1
119 merging f1
120 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
120 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
121 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
121 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
122 [1]
122 [1]
123
123
124 Redo merge with merge.preferancestor="*" to enable bid merge
124 Redo merge with merge.preferancestor="*" to enable bid merge
125
125
126 $ rm f*
126 $ rm f*
127 $ hg up -qC .
127 $ hg up -qC .
128 $ hg merge -v --debug --tool internal:dump 5 --config merge.preferancestor="*"
128 $ hg merge -v --debug --tool internal:dump 5 --config merge.preferancestor="*"
129 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
129 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
130
130
131 calculating bids for ancestor 0f6b37dbe527
131 calculating bids for ancestor 0f6b37dbe527
132 searching for copies back to rev 3
132 searching for copies back to rev 3
133 resolving manifests
133 resolving manifests
134 branchmerge: True, force: False, partial: False
134 branchmerge: True, force: False, partial: False
135 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
135 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
136 f1: remote is newer -> g
136 f1: remote is newer -> g
137 f2: versions differ -> m
137 f2: versions differ -> m
138
138
139 calculating bids for ancestor 40663881a6dd
139 calculating bids for ancestor 40663881a6dd
140 searching for copies back to rev 3
140 searching for copies back to rev 3
141 resolving manifests
141 resolving manifests
142 branchmerge: True, force: False, partial: False
142 branchmerge: True, force: False, partial: False
143 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
143 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
144 f2: keep -> k
144 f2: remote unchanged -> k
145 f1: versions differ -> m
145 f1: versions differ -> m
146
146
147 auction for merging merge bids
147 auction for merging merge bids
148 f1: picking 'get' action
148 f1: picking 'get' action
149 f2: picking 'keep' action
149 f2: picking 'keep' action
150 end of auction
150 end of auction
151
151
152 f1: remote is newer -> g
152 f1: remote is newer -> g
153 getting f1
153 getting f1
154 updating: f1 1/1 files (100.00%)
154 updating: f1 1/1 files (100.00%)
155 f2: keep -> k
155 f2: remote unchanged -> k
156 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
156 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
157 (branch merge, don't forget to commit)
157 (branch merge, don't forget to commit)
158
158
159 $ head *
159 $ head *
160 ==> f1 <==
160 ==> f1 <==
161 5 second change
161 5 second change
162
162
163 ==> f2 <==
163 ==> f2 <==
164 6 second change
164 6 second change
165
165
166
166
167 The other way around:
167 The other way around:
168
168
169 $ hg up -C -r5
169 $ hg up -C -r5
170 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
171 $ hg merge -v --debug --config merge.preferancestor="*"
171 $ hg merge -v --debug --config merge.preferancestor="*"
172 note: merging adfe50279922+ and 3b08d01b0ab5 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
172 note: merging adfe50279922+ and 3b08d01b0ab5 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
173
173
174 calculating bids for ancestor 0f6b37dbe527
174 calculating bids for ancestor 0f6b37dbe527
175 searching for copies back to rev 3
175 searching for copies back to rev 3
176 resolving manifests
176 resolving manifests
177 branchmerge: True, force: False, partial: False
177 branchmerge: True, force: False, partial: False
178 ancestor: 0f6b37dbe527, local: adfe50279922+, remote: 3b08d01b0ab5
178 ancestor: 0f6b37dbe527, local: adfe50279922+, remote: 3b08d01b0ab5
179 f1: keep -> k
179 f1: remote unchanged -> k
180 f2: versions differ -> m
180 f2: versions differ -> m
181
181
182 calculating bids for ancestor 40663881a6dd
182 calculating bids for ancestor 40663881a6dd
183 searching for copies back to rev 3
183 searching for copies back to rev 3
184 resolving manifests
184 resolving manifests
185 branchmerge: True, force: False, partial: False
185 branchmerge: True, force: False, partial: False
186 ancestor: 40663881a6dd, local: adfe50279922+, remote: 3b08d01b0ab5
186 ancestor: 40663881a6dd, local: adfe50279922+, remote: 3b08d01b0ab5
187 f2: remote is newer -> g
187 f2: remote is newer -> g
188 f1: versions differ -> m
188 f1: versions differ -> m
189
189
190 auction for merging merge bids
190 auction for merging merge bids
191 f1: picking 'keep' action
191 f1: picking 'keep' action
192 f2: picking 'get' action
192 f2: picking 'get' action
193 end of auction
193 end of auction
194
194
195 f2: remote is newer -> g
195 f2: remote is newer -> g
196 getting f2
196 getting f2
197 updating: f2 1/1 files (100.00%)
197 updating: f2 1/1 files (100.00%)
198 f1: keep -> k
198 f1: remote unchanged -> k
199 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
199 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
200 (branch merge, don't forget to commit)
200 (branch merge, don't forget to commit)
201
201
202 $ head *
202 $ head *
203 ==> f1 <==
203 ==> f1 <==
204 5 second change
204 5 second change
205
205
206 ==> f2 <==
206 ==> f2 <==
207 6 second change
207 6 second change
208
208
209 Verify how the output looks and and how verbose it is:
209 Verify how the output looks and and how verbose it is:
210
210
211 $ hg up -qC
211 $ hg up -qC
212 $ hg merge
212 $ hg merge
213 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 (branch merge, don't forget to commit)
214 (branch merge, don't forget to commit)
215
215
216 $ hg up -qC
216 $ hg up -qC
217 $ hg merge -v
217 $ hg merge -v
218 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
218 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
219
219
220 calculating bids for ancestor 0f6b37dbe527
220 calculating bids for ancestor 0f6b37dbe527
221 resolving manifests
221 resolving manifests
222
222
223 calculating bids for ancestor 40663881a6dd
223 calculating bids for ancestor 40663881a6dd
224 resolving manifests
224 resolving manifests
225
225
226 auction for merging merge bids
226 auction for merging merge bids
227 f1: picking 'get' action
227 f1: picking 'get' action
228 f2: picking 'keep' action
228 f2: picking 'keep' action
229 end of auction
229 end of auction
230
230
231 getting f1
231 getting f1
232 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
232 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 (branch merge, don't forget to commit)
233 (branch merge, don't forget to commit)
234
234
235 $ hg up -qC
235 $ hg up -qC
236 $ hg merge -v --debug --config merge.preferancestor="*"
236 $ hg merge -v --debug --config merge.preferancestor="*"
237 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
237 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
238
238
239 calculating bids for ancestor 0f6b37dbe527
239 calculating bids for ancestor 0f6b37dbe527
240 searching for copies back to rev 3
240 searching for copies back to rev 3
241 resolving manifests
241 resolving manifests
242 branchmerge: True, force: False, partial: False
242 branchmerge: True, force: False, partial: False
243 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
243 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
244 f1: remote is newer -> g
244 f1: remote is newer -> g
245 f2: versions differ -> m
245 f2: versions differ -> m
246
246
247 calculating bids for ancestor 40663881a6dd
247 calculating bids for ancestor 40663881a6dd
248 searching for copies back to rev 3
248 searching for copies back to rev 3
249 resolving manifests
249 resolving manifests
250 branchmerge: True, force: False, partial: False
250 branchmerge: True, force: False, partial: False
251 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
251 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
252 f2: keep -> k
252 f2: remote unchanged -> k
253 f1: versions differ -> m
253 f1: versions differ -> m
254
254
255 auction for merging merge bids
255 auction for merging merge bids
256 f1: picking 'get' action
256 f1: picking 'get' action
257 f2: picking 'keep' action
257 f2: picking 'keep' action
258 end of auction
258 end of auction
259
259
260 f1: remote is newer -> g
260 f1: remote is newer -> g
261 getting f1
261 getting f1
262 updating: f1 1/1 files (100.00%)
262 updating: f1 1/1 files (100.00%)
263 f2: keep -> k
263 f2: remote unchanged -> k
264 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
264 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
265 (branch merge, don't forget to commit)
265 (branch merge, don't forget to commit)
266
266
267 $ cd ..
267 $ cd ..
268
268
269 http://stackoverflow.com/questions/9350005/how-do-i-specify-a-merge-base-to-use-in-a-hg-merge/9430810
269 http://stackoverflow.com/questions/9350005/how-do-i-specify-a-merge-base-to-use-in-a-hg-merge/9430810
270
270
271 $ hg init ancestor-merging
271 $ hg init ancestor-merging
272 $ cd ancestor-merging
272 $ cd ancestor-merging
273 $ echo a > x
273 $ echo a > x
274 $ hg commit -A -m a x
274 $ hg commit -A -m a x
275 $ hg update -q 0
275 $ hg update -q 0
276 $ echo b >> x
276 $ echo b >> x
277 $ hg commit -m b
277 $ hg commit -m b
278 $ hg update -q 0
278 $ hg update -q 0
279 $ echo c >> x
279 $ echo c >> x
280 $ hg commit -qm c
280 $ hg commit -qm c
281 $ hg update -q 1
281 $ hg update -q 1
282 $ hg merge -q --tool internal:local 2
282 $ hg merge -q --tool internal:local 2
283 $ echo c >> x
283 $ echo c >> x
284 $ hg commit -m bc
284 $ hg commit -m bc
285 $ hg update -q 2
285 $ hg update -q 2
286 $ hg merge -q --tool internal:local 1
286 $ hg merge -q --tool internal:local 1
287 $ echo b >> x
287 $ echo b >> x
288 $ hg commit -qm cb
288 $ hg commit -qm cb
289
289
290 $ hg merge --config merge.preferancestor='!'
290 $ hg merge --config merge.preferancestor='!'
291 note: using 70008a2163f6 as ancestor of 0d355fdef312 and 4b8b546a3eef
291 note: using 70008a2163f6 as ancestor of 0d355fdef312 and 4b8b546a3eef
292 alternatively, use --config merge.preferancestor=b211bbc6eb3c
292 alternatively, use --config merge.preferancestor=b211bbc6eb3c
293 merging x
293 merging x
294 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
294 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
295 (branch merge, don't forget to commit)
295 (branch merge, don't forget to commit)
296 $ cat x
296 $ cat x
297 a
297 a
298 c
298 c
299 b
299 b
300 c
300 c
301
301
302 $ hg up -qC .
302 $ hg up -qC .
303
303
304 $ hg merge --config merge.preferancestor=b211bbc6eb3c
304 $ hg merge --config merge.preferancestor=b211bbc6eb3c
305 note: using b211bbc6eb3c as ancestor of 0d355fdef312 and 4b8b546a3eef
305 note: using b211bbc6eb3c as ancestor of 0d355fdef312 and 4b8b546a3eef
306 alternatively, use --config merge.preferancestor=70008a2163f6
306 alternatively, use --config merge.preferancestor=70008a2163f6
307 merging x
307 merging x
308 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
308 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
309 (branch merge, don't forget to commit)
309 (branch merge, don't forget to commit)
310 $ cat x
310 $ cat x
311 a
311 a
312 b
312 b
313 c
313 c
314 b
314 b
315
315
316 $ hg up -qC .
316 $ hg up -qC .
317
317
318 $ hg merge -v --config merge.preferancestor="*"
318 $ hg merge -v --config merge.preferancestor="*"
319 note: merging 0d355fdef312+ and 4b8b546a3eef using bids from ancestors 70008a2163f6 and b211bbc6eb3c
319 note: merging 0d355fdef312+ and 4b8b546a3eef using bids from ancestors 70008a2163f6 and b211bbc6eb3c
320
320
321 calculating bids for ancestor 70008a2163f6
321 calculating bids for ancestor 70008a2163f6
322 resolving manifests
322 resolving manifests
323
323
324 calculating bids for ancestor b211bbc6eb3c
324 calculating bids for ancestor b211bbc6eb3c
325 resolving manifests
325 resolving manifests
326
326
327 auction for merging merge bids
327 auction for merging merge bids
328 x: multiple bids for merge action:
328 x: multiple bids for merge action:
329 versions differ -> m
329 versions differ -> m
330 versions differ -> m
330 versions differ -> m
331 x: ambiguous merge - picked m action
331 x: ambiguous merge - picked m action
332 end of auction
332 end of auction
333
333
334 merging x
334 merging x
335 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
335 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
336 (branch merge, don't forget to commit)
336 (branch merge, don't forget to commit)
337 $ cat x
337 $ cat x
338 a
338 a
339 c
339 c
340 b
340 b
341 c
341 c
342
342
343 Verify that the old context ancestor works with / despite preferancestor:
343 Verify that the old context ancestor works with / despite preferancestor:
344
344
345 $ hg log -r 'ancestor(head())' --config merge.preferancestor=1 -T '{rev}\n'
345 $ hg log -r 'ancestor(head())' --config merge.preferancestor=1 -T '{rev}\n'
346 1
346 1
347 $ hg log -r 'ancestor(head())' --config merge.preferancestor=2 -T '{rev}\n'
347 $ hg log -r 'ancestor(head())' --config merge.preferancestor=2 -T '{rev}\n'
348 2
348 2
349 $ hg log -r 'ancestor(head())' --config merge.preferancestor=3 -T '{rev}\n'
349 $ hg log -r 'ancestor(head())' --config merge.preferancestor=3 -T '{rev}\n'
350 1
350 1
351 $ hg log -r 'ancestor(head())' --config merge.preferancestor='1337 * - 2' -T '{rev}\n'
351 $ hg log -r 'ancestor(head())' --config merge.preferancestor='1337 * - 2' -T '{rev}\n'
352 2
352 2
353
353
354 $ cd ..
354 $ cd ..
@@ -1,962 +1,962 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 preserving a for resolve of b
89 preserving a for resolve of b
90 preserving rev for resolve of rev
90 preserving rev for resolve of rev
91 a: keep -> k
91 a: remote unchanged -> k
92 b: remote copied from a -> m
92 b: remote copied from a -> m
93 updating: b 1/2 files (50.00%)
93 updating: b 1/2 files (50.00%)
94 picked tool 'python ../merge' for b (binary False symlink False)
94 picked tool 'python ../merge' for b (binary False symlink False)
95 merging a and b to b
95 merging a and b to b
96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
97 premerge successful
97 premerge successful
98 rev: versions differ -> m
98 rev: versions differ -> m
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 preserving b for resolve of b
125 preserving b for resolve of b
126 preserving rev for resolve of rev
126 preserving rev for resolve of rev
127 a: remote is newer -> g
127 a: remote is newer -> g
128 getting a
128 getting a
129 updating: a 1/3 files (33.33%)
129 updating: a 1/3 files (33.33%)
130 b: local copied/moved from a -> m
130 b: local copied/moved from a -> m
131 updating: b 2/3 files (66.67%)
131 updating: b 2/3 files (66.67%)
132 picked tool 'python ../merge' for b (binary False symlink False)
132 picked tool 'python ../merge' for b (binary False symlink False)
133 merging b and a to b
133 merging b and a to b
134 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
134 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
135 premerge successful
135 premerge successful
136 rev: versions differ -> m
136 rev: versions differ -> m
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 preserving a for resolve of b
163 preserving a for resolve of b
164 preserving rev for resolve of rev
164 preserving rev for resolve of rev
165 removing a
165 removing a
166 b: remote moved from a -> m
166 b: remote moved from a -> m
167 updating: b 1/2 files (50.00%)
167 updating: b 1/2 files (50.00%)
168 picked tool 'python ../merge' for b (binary False symlink False)
168 picked tool 'python ../merge' for b (binary False symlink False)
169 merging a and b to b
169 merging a and b to b
170 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
170 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
171 premerge successful
171 premerge successful
172 rev: versions differ -> m
172 rev: versions differ -> m
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 preserving b for resolve of b
198 preserving b for resolve of b
199 preserving rev for resolve of rev
199 preserving rev for resolve of rev
200 b: local copied/moved from a -> m
200 b: local copied/moved from a -> m
201 updating: b 1/2 files (50.00%)
201 updating: b 1/2 files (50.00%)
202 picked tool 'python ../merge' for b (binary False symlink False)
202 picked tool 'python ../merge' for b (binary False symlink False)
203 merging b and a to b
203 merging b and a to b
204 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
204 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
205 premerge successful
205 premerge successful
206 rev: versions differ -> m
206 rev: versions differ -> m
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 preserving rev for resolve of rev
232 preserving rev for resolve of rev
233 b: remote created -> g
233 b: remote created -> g
234 getting b
234 getting b
235 updating: b 1/2 files (50.00%)
235 updating: b 1/2 files (50.00%)
236 rev: versions differ -> m
236 rev: versions differ -> m
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 preserving rev for resolve of rev
262 preserving rev for resolve of rev
263 rev: versions differ -> m
263 rev: versions differ -> m
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 preserving rev for resolve of rev
289 preserving rev for resolve of rev
290 a: other deleted -> r
290 a: other deleted -> r
291 removing a
291 removing a
292 updating: a 1/3 files (33.33%)
292 updating: a 1/3 files (33.33%)
293 b: remote created -> g
293 b: remote created -> g
294 getting b
294 getting b
295 updating: b 2/3 files (66.67%)
295 updating: b 2/3 files (66.67%)
296 rev: versions differ -> m
296 rev: versions differ -> m
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 preserving rev for resolve of rev
321 preserving rev for resolve of rev
322 rev: versions differ -> m
322 rev: versions differ -> m
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 preserving b for resolve of b
344 preserving b for resolve of b
345 preserving rev for resolve of rev
345 preserving rev for resolve of rev
346 b: both renamed from a -> m
346 b: both renamed from a -> m
347 updating: b 1/2 files (50.00%)
347 updating: b 1/2 files (50.00%)
348 picked tool 'python ../merge' for b (binary False symlink False)
348 picked tool 'python ../merge' for b (binary False symlink False)
349 merging b
349 merging b
350 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
350 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
351 rev: versions differ -> m
351 rev: versions differ -> m
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 preserving rev for resolve of rev
382 preserving rev for resolve of rev
383 c: remote created -> g
383 c: remote created -> g
384 getting c
384 getting c
385 updating: c 1/3 files (33.33%)
385 updating: c 1/3 files (33.33%)
386 rev: versions differ -> m
386 rev: versions differ -> m
387 updating: rev 2/3 files (66.67%)
387 updating: rev 2/3 files (66.67%)
388 picked tool 'python ../merge' for rev (binary False symlink False)
388 picked tool 'python ../merge' for rev (binary False symlink False)
389 merging rev
389 merging rev
390 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
390 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
391 a: divergent renames -> dr
391 a: divergent renames -> dr
392 updating: a 3/3 files (100.00%)
392 updating: a 3/3 files (100.00%)
393 note: possible conflict - a was renamed multiple times to:
393 note: possible conflict - a was renamed multiple times to:
394 b
394 b
395 c
395 c
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 preserving b for resolve of b
414 preserving b for resolve of b
415 preserving rev for resolve of rev
415 preserving rev for resolve of rev
416 b: both created -> m
416 b: both created -> m
417 updating: b 1/2 files (50.00%)
417 updating: b 1/2 files (50.00%)
418 picked tool 'python ../merge' for b (binary False symlink False)
418 picked tool 'python ../merge' for b (binary False symlink False)
419 merging b
419 merging b
420 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
420 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
421 rev: versions differ -> m
421 rev: versions differ -> m
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 preserving b for resolve of b
444 preserving b for resolve of b
445 preserving rev for resolve of rev
445 preserving rev for resolve of rev
446 a: other deleted -> r
446 a: other deleted -> r
447 removing a
447 removing a
448 updating: a 1/3 files (33.33%)
448 updating: a 1/3 files (33.33%)
449 b: both created -> m
449 b: both created -> m
450 updating: b 2/3 files (66.67%)
450 updating: b 2/3 files (66.67%)
451 picked tool 'python ../merge' for b (binary False symlink False)
451 picked tool 'python ../merge' for b (binary False symlink False)
452 merging b
452 merging b
453 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
453 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
454 rev: versions differ -> m
454 rev: versions differ -> m
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 preserving b for resolve of b
476 preserving b for resolve of b
477 preserving rev for resolve of rev
477 preserving rev for resolve of rev
478 a: remote is newer -> g
478 a: remote is newer -> g
479 getting a
479 getting a
480 updating: a 1/3 files (33.33%)
480 updating: a 1/3 files (33.33%)
481 b: both created -> m
481 b: both created -> m
482 updating: b 2/3 files (66.67%)
482 updating: b 2/3 files (66.67%)
483 picked tool 'python ../merge' for b (binary False symlink False)
483 picked tool 'python ../merge' for b (binary False symlink False)
484 merging b
484 merging b
485 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
485 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
486 rev: versions differ -> m
486 rev: versions differ -> m
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 preserving b for resolve of b
509 preserving b for resolve of b
510 preserving rev for resolve of rev
510 preserving rev for resolve of rev
511 a: other deleted -> r
511 a: other deleted -> r
512 removing a
512 removing a
513 updating: a 1/3 files (33.33%)
513 updating: a 1/3 files (33.33%)
514 b: both created -> m
514 b: both created -> m
515 updating: b 2/3 files (66.67%)
515 updating: b 2/3 files (66.67%)
516 picked tool 'python ../merge' for b (binary False symlink False)
516 picked tool 'python ../merge' for b (binary False symlink False)
517 merging b
517 merging b
518 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
518 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
519 rev: versions differ -> m
519 rev: versions differ -> m
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 preserving b for resolve of b
541 preserving b for resolve of b
542 preserving rev for resolve of rev
542 preserving rev for resolve of rev
543 a: remote is newer -> g
543 a: remote is newer -> g
544 getting a
544 getting a
545 updating: a 1/3 files (33.33%)
545 updating: a 1/3 files (33.33%)
546 b: both created -> m
546 b: both created -> m
547 updating: b 2/3 files (66.67%)
547 updating: b 2/3 files (66.67%)
548 picked tool 'python ../merge' for b (binary False symlink False)
548 picked tool 'python ../merge' for b (binary False symlink False)
549 merging b
549 merging b
550 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
550 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
551 rev: versions differ -> m
551 rev: versions differ -> m
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 preserving b for resolve of b
574 preserving b for resolve of b
575 preserving rev for resolve of rev
575 preserving rev for resolve of rev
576 a: keep -> k
576 a: remote unchanged -> k
577 b: both created -> m
577 b: both created -> m
578 updating: b 1/2 files (50.00%)
578 updating: b 1/2 files (50.00%)
579 picked tool 'python ../merge' for b (binary False symlink False)
579 picked tool 'python ../merge' for b (binary False symlink False)
580 merging b
580 merging b
581 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
581 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
582 rev: versions differ -> m
582 rev: versions differ -> m
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 preserving b for resolve of b
607 preserving b for resolve of b
608 preserving rev for resolve of rev
608 preserving rev for resolve of rev
609 a: prompt recreating -> g
609 a: prompt recreating -> g
610 getting a
610 getting a
611 updating: a 1/3 files (33.33%)
611 updating: a 1/3 files (33.33%)
612 b: both created -> m
612 b: both created -> m
613 updating: b 2/3 files (66.67%)
613 updating: b 2/3 files (66.67%)
614 picked tool 'python ../merge' for b (binary False symlink False)
614 picked tool 'python ../merge' for b (binary False symlink False)
615 merging b
615 merging b
616 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
616 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
617 rev: versions differ -> m
617 rev: versions differ -> m
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 preserving b for resolve of b
642 preserving b for resolve of b
643 preserving rev for resolve of rev
643 preserving rev for resolve of rev
644 a: prompt keep -> a
644 a: prompt keep -> a
645 updating: a 1/3 files (33.33%)
645 updating: a 1/3 files (33.33%)
646 b: both created -> m
646 b: both created -> m
647 updating: b 2/3 files (66.67%)
647 updating: b 2/3 files (66.67%)
648 picked tool 'python ../merge' for b (binary False symlink False)
648 picked tool 'python ../merge' for b (binary False symlink False)
649 merging b
649 merging b
650 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
650 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
651 rev: versions differ -> m
651 rev: versions differ -> m
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 preserving a for resolve of b
677 preserving a for resolve of b
678 preserving rev for resolve of rev
678 preserving rev for resolve of rev
679 removing a
679 removing a
680 b: remote moved from a -> m
680 b: remote moved from a -> m
681 updating: b 1/2 files (50.00%)
681 updating: b 1/2 files (50.00%)
682 picked tool 'python ../merge' for b (binary False symlink False)
682 picked tool 'python ../merge' for b (binary False symlink False)
683 merging a and b to b
683 merging a and b to b
684 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
684 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
685 rev: versions differ -> m
685 rev: versions differ -> m
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 preserving b for resolve of b
711 preserving b for resolve of b
712 preserving rev for resolve of rev
712 preserving rev for resolve of rev
713 b: local copied/moved from a -> m
713 b: local copied/moved from a -> m
714 updating: b 1/2 files (50.00%)
714 updating: b 1/2 files (50.00%)
715 picked tool 'python ../merge' for b (binary False symlink False)
715 picked tool 'python ../merge' for b (binary False symlink False)
716 merging b and a to b
716 merging b and a to b
717 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
717 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
718 rev: versions differ -> m
718 rev: versions differ -> m
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 preserving b for resolve of b
749 preserving b for resolve of b
750 preserving rev for resolve of rev
750 preserving rev for resolve of rev
751 c: remote created -> g
751 c: remote created -> g
752 getting c
752 getting c
753 updating: c 1/3 files (33.33%)
753 updating: c 1/3 files (33.33%)
754 b: local copied/moved from a -> m
754 b: local copied/moved from a -> m
755 updating: b 2/3 files (66.67%)
755 updating: b 2/3 files (66.67%)
756 picked tool 'python ../merge' for b (binary False symlink False)
756 picked tool 'python ../merge' for b (binary False symlink False)
757 merging b and a to b
757 merging b and a to b
758 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
758 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
759 premerge successful
759 premerge successful
760 rev: versions differ -> m
760 rev: versions differ -> m
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 preserving 0/f for resolve of 0/f
839 preserving 0/f for resolve of 0/f
840 preserving 1/g for resolve of 1/g
840 preserving 1/g for resolve of 1/g
841 preserving 2/f for resolve of 2/f
841 preserving 2/f for resolve of 2/f
842 preserving 3/f for resolve of 3/f
842 preserving 3/f for resolve of 3/f
843 preserving 3/f for resolve of 3/g
843 preserving 3/f for resolve of 3/g
844 preserving 4/f for resolve of 4/g
844 preserving 4/f for resolve of 4/g
845 preserving 5/f for resolve of 5/f
845 preserving 5/f for resolve of 5/f
846 preserving 5/g for resolve of 5/g
846 preserving 5/g for resolve of 5/g
847 preserving 6/g for resolve of 6/g
847 preserving 6/g for resolve of 6/g
848 preserving 7/f for resolve of 7/f
848 preserving 7/f for resolve of 7/f
849 removing 4/f
849 removing 4/f
850 8/f: prompt recreating -> g
850 8/f: prompt recreating -> g
851 getting 8/f
851 getting 8/f
852 $ hg mani
852 $ hg mani
853 0/f
853 0/f
854 1/g
854 1/g
855 2/f
855 2/f
856 3/f
856 3/f
857 4/f
857 4/f
858 5/f
858 5/f
859 5/g
859 5/g
860 6/g
860 6/g
861 $ for f in */*; do echo $f:; cat $f; done
861 $ for f in */*; do echo $f:; cat $f; done
862 0/f:
862 0/f:
863 m1
863 m1
864 0/f.base:
864 0/f.base:
865 0/f.local:
865 0/f.local:
866 m1
866 m1
867 0/f.orig:
867 0/f.orig:
868 m1
868 m1
869 0/f.other:
869 0/f.other:
870 m2
870 m2
871 1/g:
871 1/g:
872 m1
872 m1
873 1/g.base:
873 1/g.base:
874 a
874 a
875 1/g.local:
875 1/g.local:
876 m1
876 m1
877 1/g.orig:
877 1/g.orig:
878 m1
878 m1
879 1/g.other:
879 1/g.other:
880 m2
880 m2
881 2/f:
881 2/f:
882 m1
882 m1
883 2/f.base:
883 2/f.base:
884 a
884 a
885 2/f.local:
885 2/f.local:
886 m1
886 m1
887 2/f.orig:
887 2/f.orig:
888 m1
888 m1
889 2/f.other:
889 2/f.other:
890 m2
890 m2
891 3/f:
891 3/f:
892 m1
892 m1
893 3/f.base:
893 3/f.base:
894 a
894 a
895 3/f.local:
895 3/f.local:
896 m1
896 m1
897 3/f.orig:
897 3/f.orig:
898 m1
898 m1
899 3/f.other:
899 3/f.other:
900 m2
900 m2
901 3/g:
901 3/g:
902 m1
902 m1
903 3/g.base:
903 3/g.base:
904 a
904 a
905 3/g.local:
905 3/g.local:
906 m1
906 m1
907 3/g.orig:
907 3/g.orig:
908 m1
908 m1
909 3/g.other:
909 3/g.other:
910 m2
910 m2
911 4/g:
911 4/g:
912 m1
912 m1
913 4/g.base:
913 4/g.base:
914 a
914 a
915 4/g.local:
915 4/g.local:
916 m1
916 m1
917 4/g.orig:
917 4/g.orig:
918 m1
918 m1
919 4/g.other:
919 4/g.other:
920 m2
920 m2
921 5/f:
921 5/f:
922 m1
922 m1
923 5/f.base:
923 5/f.base:
924 a
924 a
925 5/f.local:
925 5/f.local:
926 m1
926 m1
927 5/f.orig:
927 5/f.orig:
928 m1
928 m1
929 5/f.other:
929 5/f.other:
930 m2
930 m2
931 5/g:
931 5/g:
932 m1
932 m1
933 5/g.base:
933 5/g.base:
934 a
934 a
935 5/g.local:
935 5/g.local:
936 m1
936 m1
937 5/g.orig:
937 5/g.orig:
938 m1
938 m1
939 5/g.other:
939 5/g.other:
940 m2
940 m2
941 6/g:
941 6/g:
942 m1
942 m1
943 6/g.base:
943 6/g.base:
944 a
944 a
945 6/g.local:
945 6/g.local:
946 m1
946 m1
947 6/g.orig:
947 6/g.orig:
948 m1
948 m1
949 6/g.other:
949 6/g.other:
950 m2
950 m2
951 7/f:
951 7/f:
952 m
952 m
953 7/f.base:
953 7/f.base:
954 7/f.local:
954 7/f.local:
955 m
955 m
956 7/f.orig:
956 7/f.orig:
957 m
957 m
958 7/f.other:
958 7/f.other:
959 m2
959 m2
960 8/f:
960 8/f:
961 m2
961 m2
962 $ cd ..
962 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now