##// END OF EJS Templates
merge.mergestate: compute dirstate action...
Siddharth Agarwal -
r27035:de7bf242 default
parent child Browse files
Show More
@@ -1,1402 +1,1419 b''
1 1 # merge.py - directory-level update/merge handling for Mercurial
2 2 #
3 3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import os
12 12 import shutil
13 13 import struct
14 14
15 15 from .i18n import _
16 16 from .node import (
17 17 bin,
18 18 hex,
19 19 nullhex,
20 20 nullid,
21 21 nullrev,
22 22 )
23 23 from . import (
24 24 copies,
25 25 destutil,
26 26 error,
27 27 filemerge,
28 28 obsolete,
29 29 subrepo,
30 30 util,
31 31 worker,
32 32 )
33 33
34 34 _pack = struct.pack
35 35 _unpack = struct.unpack
36 36
37 37 def _droponode(data):
38 38 # used for compatibility for v1
39 39 bits = data.split('\0')
40 40 bits = bits[:-2] + bits[-1:]
41 41 return '\0'.join(bits)
42 42
43 43 class mergestate(object):
44 44 '''track 3-way merge state of individual files
45 45
46 46 The merge state is stored on disk when needed. Two files are used: one with
47 47 an old format (version 1), and one with a new format (version 2). Version 2
48 48 stores a superset of the data in version 1, including new kinds of records
49 49 in the future. For more about the new format, see the documentation for
50 50 `_readrecordsv2`.
51 51
52 52 Each record can contain arbitrary content, and has an associated type. This
53 53 `type` should be a letter. If `type` is uppercase, the record is mandatory:
54 54 versions of Mercurial that don't support it should abort. If `type` is
55 55 lowercase, the record can be safely ignored.
56 56
57 57 Currently known records:
58 58
59 59 L: the node of the "local" part of the merge (hexified version)
60 60 O: the node of the "other" part of the merge (hexified version)
61 61 F: a file to be merged entry
62 62 C: a change/delete or delete/change conflict
63 63 D: a file that the external merge driver will merge internally
64 64 (experimental)
65 65 m: the external merge driver defined for this merge plus its run state
66 66 (experimental)
67 67 X: unsupported mandatory record type (used in tests)
68 68 x: unsupported advisory record type (used in tests)
69 69
70 70 Merge driver run states (experimental):
71 71 u: driver-resolved files unmarked -- needs to be run next time we're about
72 72 to resolve or commit
73 73 m: driver-resolved files marked -- only needs to be run before commit
74 74 s: success/skipped -- does not need to be run any more
75 75
76 76 '''
77 77 statepathv1 = 'merge/state'
78 78 statepathv2 = 'merge/state2'
79 79
80 80 @staticmethod
81 81 def clean(repo, node=None, other=None):
82 82 """Initialize a brand new merge state, removing any existing state on
83 83 disk."""
84 84 ms = mergestate(repo)
85 85 ms.reset(node, other)
86 86 return ms
87 87
88 88 @staticmethod
89 89 def read(repo):
90 90 """Initialize the merge state, reading it from disk."""
91 91 ms = mergestate(repo)
92 92 ms._read()
93 93 return ms
94 94
95 95 def __init__(self, repo):
96 96 """Initialize the merge state.
97 97
98 98 Do not use this directly! Instead call read() or clean()."""
99 99 self._repo = repo
100 100 self._dirty = False
101 101
102 102 def reset(self, node=None, other=None):
103 103 self._state = {}
104 104 self._local = None
105 105 self._other = None
106 106 if 'otherctx' in vars(self):
107 107 del self.otherctx
108 108 if node:
109 109 self._local = node
110 110 self._other = other
111 111 self._readmergedriver = None
112 112 if self.mergedriver:
113 113 self._mdstate = 's'
114 114 else:
115 115 self._mdstate = 'u'
116 116 shutil.rmtree(self._repo.join('merge'), True)
117 117 self._dirty = False
118 118
119 119 def _read(self):
120 120 """Analyse each record content to restore a serialized state from disk
121 121
122 122 This function process "record" entry produced by the de-serialization
123 123 of on disk file.
124 124 """
125 125 self._state = {}
126 126 self._local = None
127 127 self._other = None
128 128 if 'otherctx' in vars(self):
129 129 del self.otherctx
130 130 self._readmergedriver = None
131 131 self._mdstate = 's'
132 132 unsupported = set()
133 133 records = self._readrecords()
134 134 for rtype, record in records:
135 135 if rtype == 'L':
136 136 self._local = bin(record)
137 137 elif rtype == 'O':
138 138 self._other = bin(record)
139 139 elif rtype == 'm':
140 140 bits = record.split('\0', 1)
141 141 mdstate = bits[1]
142 142 if len(mdstate) != 1 or mdstate not in 'ums':
143 143 # the merge driver should be idempotent, so just rerun it
144 144 mdstate = 'u'
145 145
146 146 self._readmergedriver = bits[0]
147 147 self._mdstate = mdstate
148 148 elif rtype in 'FDC':
149 149 bits = record.split('\0')
150 150 self._state[bits[0]] = bits[1:]
151 151 elif not rtype.islower():
152 152 unsupported.add(rtype)
153 153 self._dirty = False
154 154
155 155 if unsupported:
156 156 raise error.UnsupportedMergeRecords(unsupported)
157 157
158 158 def _readrecords(self):
159 159 """Read merge state from disk and return a list of record (TYPE, data)
160 160
161 161 We read data from both v1 and v2 files and decide which one to use.
162 162
163 163 V1 has been used by version prior to 2.9.1 and contains less data than
164 164 v2. We read both versions and check if no data in v2 contradicts
165 165 v1. If there is not contradiction we can safely assume that both v1
166 166 and v2 were written at the same time and use the extract data in v2. If
167 167 there is contradiction we ignore v2 content as we assume an old version
168 168 of Mercurial has overwritten the mergestate file and left an old v2
169 169 file around.
170 170
171 171 returns list of record [(TYPE, data), ...]"""
172 172 v1records = self._readrecordsv1()
173 173 v2records = self._readrecordsv2()
174 174 if self._v1v2match(v1records, v2records):
175 175 return v2records
176 176 else:
177 177 # v1 file is newer than v2 file, use it
178 178 # we have to infer the "other" changeset of the merge
179 179 # we cannot do better than that with v1 of the format
180 180 mctx = self._repo[None].parents()[-1]
181 181 v1records.append(('O', mctx.hex()))
182 182 # add place holder "other" file node information
183 183 # nobody is using it yet so we do no need to fetch the data
184 184 # if mctx was wrong `mctx[bits[-2]]` may fails.
185 185 for idx, r in enumerate(v1records):
186 186 if r[0] == 'F':
187 187 bits = r[1].split('\0')
188 188 bits.insert(-2, '')
189 189 v1records[idx] = (r[0], '\0'.join(bits))
190 190 return v1records
191 191
192 192 def _v1v2match(self, v1records, v2records):
193 193 oldv2 = set() # old format version of v2 record
194 194 for rec in v2records:
195 195 if rec[0] == 'L':
196 196 oldv2.add(rec)
197 197 elif rec[0] == 'F':
198 198 # drop the onode data (not contained in v1)
199 199 oldv2.add(('F', _droponode(rec[1])))
200 200 for rec in v1records:
201 201 if rec not in oldv2:
202 202 return False
203 203 else:
204 204 return True
205 205
206 206 def _readrecordsv1(self):
207 207 """read on disk merge state for version 1 file
208 208
209 209 returns list of record [(TYPE, data), ...]
210 210
211 211 Note: the "F" data from this file are one entry short
212 212 (no "other file node" entry)
213 213 """
214 214 records = []
215 215 try:
216 216 f = self._repo.vfs(self.statepathv1)
217 217 for i, l in enumerate(f):
218 218 if i == 0:
219 219 records.append(('L', l[:-1]))
220 220 else:
221 221 records.append(('F', l[:-1]))
222 222 f.close()
223 223 except IOError as err:
224 224 if err.errno != errno.ENOENT:
225 225 raise
226 226 return records
227 227
228 228 def _readrecordsv2(self):
229 229 """read on disk merge state for version 2 file
230 230
231 231 This format is a list of arbitrary records of the form:
232 232
233 233 [type][length][content]
234 234
235 235 `type` is a single character, `length` is a 4 byte integer, and
236 236 `content` is an arbitrary byte sequence of length `length`.
237 237
238 238 Mercurial versions prior to 3.7 have a bug where if there are
239 239 unsupported mandatory merge records, attempting to clear out the merge
240 240 state with hg update --clean or similar aborts. The 't' record type
241 241 works around that by writing out what those versions treat as an
242 242 advisory record, but later versions interpret as special: the first
243 243 character is the 'real' record type and everything onwards is the data.
244 244
245 245 Returns list of records [(TYPE, data), ...]."""
246 246 records = []
247 247 try:
248 248 f = self._repo.vfs(self.statepathv2)
249 249 data = f.read()
250 250 off = 0
251 251 end = len(data)
252 252 while off < end:
253 253 rtype = data[off]
254 254 off += 1
255 255 length = _unpack('>I', data[off:(off + 4)])[0]
256 256 off += 4
257 257 record = data[off:(off + length)]
258 258 off += length
259 259 if rtype == 't':
260 260 rtype, record = record[0], record[1:]
261 261 records.append((rtype, record))
262 262 f.close()
263 263 except IOError as err:
264 264 if err.errno != errno.ENOENT:
265 265 raise
266 266 return records
267 267
268 268 @util.propertycache
269 269 def mergedriver(self):
270 270 # protect against the following:
271 271 # - A configures a malicious merge driver in their hgrc, then
272 272 # pauses the merge
273 273 # - A edits their hgrc to remove references to the merge driver
274 274 # - A gives a copy of their entire repo, including .hg, to B
275 275 # - B inspects .hgrc and finds it to be clean
276 276 # - B then continues the merge and the malicious merge driver
277 277 # gets invoked
278 278 configmergedriver = self._repo.ui.config('experimental', 'mergedriver')
279 279 if (self._readmergedriver is not None
280 280 and self._readmergedriver != configmergedriver):
281 281 raise error.ConfigError(
282 282 _("merge driver changed since merge started"),
283 283 hint=_("revert merge driver change or abort merge"))
284 284
285 285 return configmergedriver
286 286
287 287 @util.propertycache
288 288 def otherctx(self):
289 289 return self._repo[self._other]
290 290
291 291 def active(self):
292 292 """Whether mergestate is active.
293 293
294 294 Returns True if there appears to be mergestate. This is a rough proxy
295 295 for "is a merge in progress."
296 296 """
297 297 # Check local variables before looking at filesystem for performance
298 298 # reasons.
299 299 return bool(self._local) or bool(self._state) or \
300 300 self._repo.vfs.exists(self.statepathv1) or \
301 301 self._repo.vfs.exists(self.statepathv2)
302 302
303 303 def commit(self):
304 304 """Write current state on disk (if necessary)"""
305 305 if self._dirty:
306 306 records = self._makerecords()
307 307 self._writerecords(records)
308 308 self._dirty = False
309 309
310 310 def _makerecords(self):
311 311 records = []
312 312 records.append(('L', hex(self._local)))
313 313 records.append(('O', hex(self._other)))
314 314 if self.mergedriver:
315 315 records.append(('m', '\0'.join([
316 316 self.mergedriver, self._mdstate])))
317 317 for d, v in self._state.iteritems():
318 318 if v[0] == 'd':
319 319 records.append(('D', '\0'.join([d] + v)))
320 320 # v[1] == local ('cd'), v[6] == other ('dc') -- not supported by
321 321 # older versions of Mercurial
322 322 elif v[1] == nullhex or v[6] == nullhex:
323 323 records.append(('C', '\0'.join([d] + v)))
324 324 else:
325 325 records.append(('F', '\0'.join([d] + v)))
326 326 return records
327 327
328 328 def _writerecords(self, records):
329 329 """Write current state on disk (both v1 and v2)"""
330 330 self._writerecordsv1(records)
331 331 self._writerecordsv2(records)
332 332
333 333 def _writerecordsv1(self, records):
334 334 """Write current state on disk in a version 1 file"""
335 335 f = self._repo.vfs(self.statepathv1, 'w')
336 336 irecords = iter(records)
337 337 lrecords = irecords.next()
338 338 assert lrecords[0] == 'L'
339 339 f.write(hex(self._local) + '\n')
340 340 for rtype, data in irecords:
341 341 if rtype == 'F':
342 342 f.write('%s\n' % _droponode(data))
343 343 f.close()
344 344
345 345 def _writerecordsv2(self, records):
346 346 """Write current state on disk in a version 2 file
347 347
348 348 See the docstring for _readrecordsv2 for why we use 't'."""
349 349 # these are the records that all version 2 clients can read
350 350 whitelist = 'LOF'
351 351 f = self._repo.vfs(self.statepathv2, 'w')
352 352 for key, data in records:
353 353 assert len(key) == 1
354 354 if key not in whitelist:
355 355 key, data = 't', '%s%s' % (key, data)
356 356 format = '>sI%is' % len(data)
357 357 f.write(_pack(format, key, len(data), data))
358 358 f.close()
359 359
360 360 def add(self, fcl, fco, fca, fd):
361 361 """add a new (potentially?) conflicting file the merge state
362 362 fcl: file context for local,
363 363 fco: file context for remote,
364 364 fca: file context for ancestors,
365 365 fd: file path of the resulting merge.
366 366
367 367 note: also write the local version to the `.hg/merge` directory.
368 368 """
369 369 hash = util.sha1(fcl.path()).hexdigest()
370 370 self._repo.vfs.write('merge/' + hash, fcl.data())
371 371 self._state[fd] = ['u', hash, fcl.path(),
372 372 fca.path(), hex(fca.filenode()),
373 373 fco.path(), hex(fco.filenode()),
374 374 fcl.flags()]
375 375 self._dirty = True
376 376
377 377 def __contains__(self, dfile):
378 378 return dfile in self._state
379 379
380 380 def __getitem__(self, dfile):
381 381 return self._state[dfile][0]
382 382
383 383 def __iter__(self):
384 384 return iter(sorted(self._state))
385 385
386 386 def files(self):
387 387 return self._state.keys()
388 388
389 389 def mark(self, dfile, state):
390 390 self._state[dfile][0] = state
391 391 self._dirty = True
392 392
393 393 def mdstate(self):
394 394 return self._mdstate
395 395
396 396 def unresolved(self):
397 397 """Obtain the paths of unresolved files."""
398 398
399 399 for f, entry in self._state.items():
400 400 if entry[0] == 'u':
401 401 yield f
402 402
403 403 def driverresolved(self):
404 404 """Obtain the paths of driver-resolved files."""
405 405
406 406 for f, entry in self._state.items():
407 407 if entry[0] == 'd':
408 408 yield f
409 409
410 410 def _resolve(self, preresolve, dfile, wctx, labels=None):
411 411 """rerun merge process for file path `dfile`"""
412 412 if self[dfile] in 'rd':
413 return True, 0
413 return True, 0, None
414 414 stateentry = self._state[dfile]
415 415 state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
416 416 octx = self._repo[self._other]
417 417 fcd = wctx[dfile]
418 418 fco = octx[ofile]
419 419 fca = self._repo.filectx(afile, fileid=anode)
420 420 # "premerge" x flags
421 421 flo = fco.flags()
422 422 fla = fca.flags()
423 423 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
424 424 if fca.node() == nullid:
425 425 if preresolve:
426 426 self._repo.ui.warn(
427 427 _('warning: cannot merge flags for %s\n') % afile)
428 428 elif flags == fla:
429 429 flags = flo
430 430 if preresolve:
431 431 # restore local
432 432 f = self._repo.vfs('merge/' + hash)
433 433 self._repo.wwrite(dfile, f.read(), flags)
434 434 f.close()
435 435 complete, r, deleted = filemerge.premerge(self._repo, self._local,
436 436 lfile, fcd, fco, fca,
437 437 labels=labels)
438 438 else:
439 439 complete, r, deleted = filemerge.filemerge(self._repo, self._local,
440 440 lfile, fcd, fco, fca,
441 441 labels=labels)
442 442 if r is None:
443 443 # no real conflict
444 444 del self._state[dfile]
445 445 self._dirty = True
446 446 elif not r:
447 447 self.mark(dfile, 'r')
448 return complete, r
448
449 action = None
450 if complete:
451 if deleted:
452 if not fcd.isabsent():
453 # cd: remote picked (or otherwise deleted)
454 action = 'r'
455 # else: dc: local picked (no action necessary)
456 else:
457 if fcd.isabsent(): # dc: remote picked
458 action = 'g'
459 elif fco.isabsent(): # cd: local picked
460 action = 'a'
461 # else: regular merges (no action necessary)
462
463 return complete, r, action
449 464
450 465 def preresolve(self, dfile, wctx, labels=None):
451 466 """run premerge process for dfile
452 467
453 468 Returns whether the merge is complete, and the exit code."""
454 return self._resolve(True, dfile, wctx, labels=labels)
469 complete, r, action = self._resolve(True, dfile, wctx, labels=labels)
470 return complete, r
455 471
456 472 def resolve(self, dfile, wctx, labels=None):
457 473 """run merge process (assuming premerge was run) for dfile
458 474
459 475 Returns the exit code of the merge."""
460 return self._resolve(False, dfile, wctx, labels=labels)[1]
476 complete, r, action = self._resolve(False, dfile, wctx, labels=labels)
477 return r
461 478
462 479 def _checkunknownfile(repo, wctx, mctx, f, f2=None):
463 480 if f2 is None:
464 481 f2 = f
465 482 return (os.path.isfile(repo.wjoin(f))
466 483 and repo.wvfs.audit.check(f)
467 484 and repo.dirstate.normalize(f) not in repo.dirstate
468 485 and mctx[f2].cmp(wctx[f]))
469 486
470 487 def _checkunknownfiles(repo, wctx, mctx, force, actions):
471 488 """
472 489 Considers any actions that care about the presence of conflicting unknown
473 490 files. For some actions, the result is to abort; for others, it is to
474 491 choose a different action.
475 492 """
476 493 aborts = []
477 494 if not force:
478 495 for f, (m, args, msg) in actions.iteritems():
479 496 if m in ('c', 'dc'):
480 497 if _checkunknownfile(repo, wctx, mctx, f):
481 498 aborts.append(f)
482 499 elif m == 'dg':
483 500 if _checkunknownfile(repo, wctx, mctx, f, args[0]):
484 501 aborts.append(f)
485 502
486 503 for f in sorted(aborts):
487 504 repo.ui.warn(_("%s: untracked file differs\n") % f)
488 505 if aborts:
489 506 raise error.Abort(_("untracked files in working directory differ "
490 507 "from files in requested revision"))
491 508
492 509 for f, (m, args, msg) in actions.iteritems():
493 510 if m == 'c':
494 511 actions[f] = ('g', args, msg)
495 512 elif m == 'cm':
496 513 fl2, anc = args
497 514 different = _checkunknownfile(repo, wctx, mctx, f)
498 515 if different:
499 516 actions[f] = ('m', (f, f, None, False, anc),
500 517 "remote differs from untracked local")
501 518 else:
502 519 actions[f] = ('g', (fl2,), "remote created")
503 520
504 521 def _forgetremoved(wctx, mctx, branchmerge):
505 522 """
506 523 Forget removed files
507 524
508 525 If we're jumping between revisions (as opposed to merging), and if
509 526 neither the working directory nor the target rev has the file,
510 527 then we need to remove it from the dirstate, to prevent the
511 528 dirstate from listing the file when it is no longer in the
512 529 manifest.
513 530
514 531 If we're merging, and the other revision has removed a file
515 532 that is not present in the working directory, we need to mark it
516 533 as removed.
517 534 """
518 535
519 536 actions = {}
520 537 m = 'f'
521 538 if branchmerge:
522 539 m = 'r'
523 540 for f in wctx.deleted():
524 541 if f not in mctx:
525 542 actions[f] = m, None, "forget deleted"
526 543
527 544 if not branchmerge:
528 545 for f in wctx.removed():
529 546 if f not in mctx:
530 547 actions[f] = 'f', None, "forget removed"
531 548
532 549 return actions
533 550
534 551 def _checkcollision(repo, wmf, actions):
535 552 # build provisional merged manifest up
536 553 pmmf = set(wmf)
537 554
538 555 if actions:
539 556 # k, dr, e and rd are no-op
540 557 for m in 'a', 'f', 'g', 'cd', 'dc':
541 558 for f, args, msg in actions[m]:
542 559 pmmf.add(f)
543 560 for f, args, msg in actions['r']:
544 561 pmmf.discard(f)
545 562 for f, args, msg in actions['dm']:
546 563 f2, flags = args
547 564 pmmf.discard(f2)
548 565 pmmf.add(f)
549 566 for f, args, msg in actions['dg']:
550 567 pmmf.add(f)
551 568 for f, args, msg in actions['m']:
552 569 f1, f2, fa, move, anc = args
553 570 if move:
554 571 pmmf.discard(f1)
555 572 pmmf.add(f)
556 573
557 574 # check case-folding collision in provisional merged manifest
558 575 foldmap = {}
559 576 for f in sorted(pmmf):
560 577 fold = util.normcase(f)
561 578 if fold in foldmap:
562 579 raise error.Abort(_("case-folding collision between %s and %s")
563 580 % (f, foldmap[fold]))
564 581 foldmap[fold] = f
565 582
566 583 # check case-folding of directories
567 584 foldprefix = unfoldprefix = lastfull = ''
568 585 for fold, f in sorted(foldmap.items()):
569 586 if fold.startswith(foldprefix) and not f.startswith(unfoldprefix):
570 587 # the folded prefix matches but actual casing is different
571 588 raise error.Abort(_("case-folding collision between "
572 589 "%s and directory of %s") % (lastfull, f))
573 590 foldprefix = fold + '/'
574 591 unfoldprefix = f + '/'
575 592 lastfull = f
576 593
577 594 def driverpreprocess(repo, ms, wctx, labels=None):
578 595 """run the preprocess step of the merge driver, if any
579 596
580 597 This is currently not implemented -- it's an extension point."""
581 598 return True
582 599
583 600 def driverconclude(repo, ms, wctx, labels=None):
584 601 """run the conclude step of the merge driver, if any
585 602
586 603 This is currently not implemented -- it's an extension point."""
587 604 return True
588 605
589 606 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
590 607 acceptremote, followcopies):
591 608 """
592 609 Merge p1 and p2 with ancestor pa and generate merge action list
593 610
594 611 branchmerge and force are as passed in to update
595 612 partial = function to filter file lists
596 613 acceptremote = accept the incoming changes without prompting
597 614 """
598 615
599 616 copy, movewithdir, diverge, renamedelete = {}, {}, {}, {}
600 617
601 618 # manifests fetched in order are going to be faster, so prime the caches
602 619 [x.manifest() for x in
603 620 sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())]
604 621
605 622 if followcopies:
606 623 ret = copies.mergecopies(repo, wctx, p2, pa)
607 624 copy, movewithdir, diverge, renamedelete = ret
608 625
609 626 repo.ui.note(_("resolving manifests\n"))
610 627 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
611 628 % (bool(branchmerge), bool(force), bool(partial)))
612 629 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
613 630
614 631 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
615 632 copied = set(copy.values())
616 633 copied.update(movewithdir.values())
617 634
618 635 if '.hgsubstate' in m1:
619 636 # check whether sub state is modified
620 637 for s in sorted(wctx.substate):
621 638 if wctx.sub(s).dirty():
622 639 m1['.hgsubstate'] += '+'
623 640 break
624 641
625 642 # Compare manifests
626 643 diff = m1.diff(m2)
627 644
628 645 actions = {}
629 646 for f, ((n1, fl1), (n2, fl2)) in diff.iteritems():
630 647 if partial and not partial(f):
631 648 continue
632 649 if n1 and n2: # file exists on both local and remote side
633 650 if f not in ma:
634 651 fa = copy.get(f, None)
635 652 if fa is not None:
636 653 actions[f] = ('m', (f, f, fa, False, pa.node()),
637 654 "both renamed from " + fa)
638 655 else:
639 656 actions[f] = ('m', (f, f, None, False, pa.node()),
640 657 "both created")
641 658 else:
642 659 a = ma[f]
643 660 fla = ma.flags(f)
644 661 nol = 'l' not in fl1 + fl2 + fla
645 662 if n2 == a and fl2 == fla:
646 663 actions[f] = ('k' , (), "remote unchanged")
647 664 elif n1 == a and fl1 == fla: # local unchanged - use remote
648 665 if n1 == n2: # optimization: keep local content
649 666 actions[f] = ('e', (fl2,), "update permissions")
650 667 else:
651 668 actions[f] = ('g', (fl2,), "remote is newer")
652 669 elif nol and n2 == a: # remote only changed 'x'
653 670 actions[f] = ('e', (fl2,), "update permissions")
654 671 elif nol and n1 == a: # local only changed 'x'
655 672 actions[f] = ('g', (fl1,), "remote is newer")
656 673 else: # both changed something
657 674 actions[f] = ('m', (f, f, f, False, pa.node()),
658 675 "versions differ")
659 676 elif n1: # file exists only on local side
660 677 if f in copied:
661 678 pass # we'll deal with it on m2 side
662 679 elif f in movewithdir: # directory rename, move local
663 680 f2 = movewithdir[f]
664 681 if f2 in m2:
665 682 actions[f2] = ('m', (f, f2, None, True, pa.node()),
666 683 "remote directory rename, both created")
667 684 else:
668 685 actions[f2] = ('dm', (f, fl1),
669 686 "remote directory rename - move from " + f)
670 687 elif f in copy:
671 688 f2 = copy[f]
672 689 actions[f] = ('m', (f, f2, f2, False, pa.node()),
673 690 "local copied/moved from " + f2)
674 691 elif f in ma: # clean, a different, no remote
675 692 if n1 != ma[f]:
676 693 if acceptremote:
677 694 actions[f] = ('r', None, "remote delete")
678 695 else:
679 696 actions[f] = ('cd', (f, None, f, False, pa.node()),
680 697 "prompt changed/deleted")
681 698 elif n1[20:] == 'a':
682 699 # This extra 'a' is added by working copy manifest to mark
683 700 # the file as locally added. We should forget it instead of
684 701 # deleting it.
685 702 actions[f] = ('f', None, "remote deleted")
686 703 else:
687 704 actions[f] = ('r', None, "other deleted")
688 705 elif n2: # file exists only on remote side
689 706 if f in copied:
690 707 pass # we'll deal with it on m1 side
691 708 elif f in movewithdir:
692 709 f2 = movewithdir[f]
693 710 if f2 in m1:
694 711 actions[f2] = ('m', (f2, f, None, False, pa.node()),
695 712 "local directory rename, both created")
696 713 else:
697 714 actions[f2] = ('dg', (f, fl2),
698 715 "local directory rename - get from " + f)
699 716 elif f in copy:
700 717 f2 = copy[f]
701 718 if f2 in m2:
702 719 actions[f] = ('m', (f2, f, f2, False, pa.node()),
703 720 "remote copied from " + f2)
704 721 else:
705 722 actions[f] = ('m', (f2, f, f2, True, pa.node()),
706 723 "remote moved from " + f2)
707 724 elif f not in ma:
708 725 # local unknown, remote created: the logic is described by the
709 726 # following table:
710 727 #
711 728 # force branchmerge different | action
712 729 # n * * | create
713 730 # y n * | create
714 731 # y y n | create
715 732 # y y y | merge
716 733 #
717 734 # Checking whether the files are different is expensive, so we
718 735 # don't do that when we can avoid it.
719 736 if not force:
720 737 actions[f] = ('c', (fl2,), "remote created")
721 738 elif not branchmerge:
722 739 actions[f] = ('c', (fl2,), "remote created")
723 740 else:
724 741 actions[f] = ('cm', (fl2, pa.node()),
725 742 "remote created, get or merge")
726 743 elif n2 != ma[f]:
727 744 if acceptremote:
728 745 actions[f] = ('c', (fl2,), "remote recreating")
729 746 else:
730 747 actions[f] = ('dc', (None, f, f, False, pa.node()),
731 748 "prompt deleted/changed")
732 749
733 750 return actions, diverge, renamedelete
734 751
735 752 def _resolvetrivial(repo, wctx, mctx, ancestor, actions):
736 753 """Resolves false conflicts where the nodeid changed but the content
737 754 remained the same."""
738 755
739 756 for f, (m, args, msg) in actions.items():
740 757 if m == 'cd' and f in ancestor and not wctx[f].cmp(ancestor[f]):
741 758 # local did change but ended up with same content
742 759 actions[f] = 'r', None, "prompt same"
743 760 elif m == 'dc' and f in ancestor and not mctx[f].cmp(ancestor[f]):
744 761 # remote did change but ended up with same content
745 762 del actions[f] # don't get = keep local deleted
746 763
747 764 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial,
748 765 acceptremote, followcopies):
749 766 "Calculate the actions needed to merge mctx into wctx using ancestors"
750 767
751 768 if len(ancestors) == 1: # default
752 769 actions, diverge, renamedelete = manifestmerge(
753 770 repo, wctx, mctx, ancestors[0], branchmerge, force, partial,
754 771 acceptremote, followcopies)
755 772 _checkunknownfiles(repo, wctx, mctx, force, actions)
756 773
757 774 else: # only when merge.preferancestor=* - the default
758 775 repo.ui.note(
759 776 _("note: merging %s and %s using bids from ancestors %s\n") %
760 777 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors)))
761 778
762 779 # Call for bids
763 780 fbids = {} # mapping filename to bids (action method to list af actions)
764 781 diverge, renamedelete = None, None
765 782 for ancestor in ancestors:
766 783 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
767 784 actions, diverge1, renamedelete1 = manifestmerge(
768 785 repo, wctx, mctx, ancestor, branchmerge, force, partial,
769 786 acceptremote, followcopies)
770 787 _checkunknownfiles(repo, wctx, mctx, force, actions)
771 788
772 789 # Track the shortest set of warning on the theory that bid
773 790 # merge will correctly incorporate more information
774 791 if diverge is None or len(diverge1) < len(diverge):
775 792 diverge = diverge1
776 793 if renamedelete is None or len(renamedelete) < len(renamedelete1):
777 794 renamedelete = renamedelete1
778 795
779 796 for f, a in sorted(actions.iteritems()):
780 797 m, args, msg = a
781 798 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
782 799 if f in fbids:
783 800 d = fbids[f]
784 801 if m in d:
785 802 d[m].append(a)
786 803 else:
787 804 d[m] = [a]
788 805 else:
789 806 fbids[f] = {m: [a]}
790 807
791 808 # Pick the best bid for each file
792 809 repo.ui.note(_('\nauction for merging merge bids\n'))
793 810 actions = {}
794 811 for f, bids in sorted(fbids.items()):
795 812 # bids is a mapping from action method to list af actions
796 813 # Consensus?
797 814 if len(bids) == 1: # all bids are the same kind of method
798 815 m, l = bids.items()[0]
799 816 if all(a == l[0] for a in l[1:]): # len(bids) is > 1
800 817 repo.ui.note(" %s: consensus for %s\n" % (f, m))
801 818 actions[f] = l[0]
802 819 continue
803 820 # If keep is an option, just do it.
804 821 if 'k' in bids:
805 822 repo.ui.note(" %s: picking 'keep' action\n" % f)
806 823 actions[f] = bids['k'][0]
807 824 continue
808 825 # If there are gets and they all agree [how could they not?], do it.
809 826 if 'g' in bids:
810 827 ga0 = bids['g'][0]
811 828 if all(a == ga0 for a in bids['g'][1:]):
812 829 repo.ui.note(" %s: picking 'get' action\n" % f)
813 830 actions[f] = ga0
814 831 continue
815 832 # TODO: Consider other simple actions such as mode changes
816 833 # Handle inefficient democrazy.
817 834 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
818 835 for m, l in sorted(bids.items()):
819 836 for _f, args, msg in l:
820 837 repo.ui.note(' %s -> %s\n' % (msg, m))
821 838 # Pick random action. TODO: Instead, prompt user when resolving
822 839 m, l = bids.items()[0]
823 840 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
824 841 (f, m))
825 842 actions[f] = l[0]
826 843 continue
827 844 repo.ui.note(_('end of auction\n\n'))
828 845
829 846 _resolvetrivial(repo, wctx, mctx, ancestors[0], actions)
830 847
831 848 if wctx.rev() is None:
832 849 fractions = _forgetremoved(wctx, mctx, branchmerge)
833 850 actions.update(fractions)
834 851
835 852 return actions, diverge, renamedelete
836 853
837 854 def batchremove(repo, actions):
838 855 """apply removes to the working directory
839 856
840 857 yields tuples for progress updates
841 858 """
842 859 verbose = repo.ui.verbose
843 860 unlink = util.unlinkpath
844 861 wjoin = repo.wjoin
845 862 audit = repo.wvfs.audit
846 863 i = 0
847 864 for f, args, msg in actions:
848 865 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
849 866 if verbose:
850 867 repo.ui.note(_("removing %s\n") % f)
851 868 audit(f)
852 869 try:
853 870 unlink(wjoin(f), ignoremissing=True)
854 871 except OSError as inst:
855 872 repo.ui.warn(_("update failed to remove %s: %s!\n") %
856 873 (f, inst.strerror))
857 874 if i == 100:
858 875 yield i, f
859 876 i = 0
860 877 i += 1
861 878 if i > 0:
862 879 yield i, f
863 880
864 881 def batchget(repo, mctx, actions):
865 882 """apply gets to the working directory
866 883
867 884 mctx is the context to get from
868 885
869 886 yields tuples for progress updates
870 887 """
871 888 verbose = repo.ui.verbose
872 889 fctx = mctx.filectx
873 890 wwrite = repo.wwrite
874 891 i = 0
875 892 for f, args, msg in actions:
876 893 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
877 894 if verbose:
878 895 repo.ui.note(_("getting %s\n") % f)
879 896 wwrite(f, fctx(f).data(), args[0])
880 897 if i == 100:
881 898 yield i, f
882 899 i = 0
883 900 i += 1
884 901 if i > 0:
885 902 yield i, f
886 903
887 904 def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
888 905 """apply the merge action list to the working directory
889 906
890 907 wctx is the working copy context
891 908 mctx is the context to be merged into the working copy
892 909
893 910 Return a tuple of counts (updated, merged, removed, unresolved) that
894 911 describes how many files were affected by the update.
895 912 """
896 913
897 914 updated, merged, removed, unresolved = 0, 0, 0, 0
898 915 ms = mergestate.clean(repo, wctx.p1().node(), mctx.node())
899 916 moves = []
900 917 for m, l in actions.items():
901 918 l.sort()
902 919
903 920 # prescan for merges
904 921 for f, args, msg in actions['m']:
905 922 f1, f2, fa, move, anc = args
906 923 if f == '.hgsubstate': # merged internally
907 924 continue
908 925 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
909 926 fcl = wctx[f1]
910 927 fco = mctx[f2]
911 928 actx = repo[anc]
912 929 if fa in actx:
913 930 fca = actx[fa]
914 931 else:
915 932 fca = repo.filectx(f1, fileid=nullrev)
916 933 ms.add(fcl, fco, fca, f)
917 934 if f1 != f and move:
918 935 moves.append(f1)
919 936
920 937 audit = repo.wvfs.audit
921 938 _updating = _('updating')
922 939 _files = _('files')
923 940 progress = repo.ui.progress
924 941
925 942 # remove renamed files after safely stored
926 943 for f in moves:
927 944 if os.path.lexists(repo.wjoin(f)):
928 945 repo.ui.debug("removing %s\n" % f)
929 946 audit(f)
930 947 util.unlinkpath(repo.wjoin(f))
931 948
932 949 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
933 950
934 951 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
935 952 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
936 953
937 954 # remove in parallel (must come first)
938 955 z = 0
939 956 prog = worker.worker(repo.ui, 0.001, batchremove, (repo,), actions['r'])
940 957 for i, item in prog:
941 958 z += i
942 959 progress(_updating, z, item=item, total=numupdates, unit=_files)
943 960 removed = len(actions['r'])
944 961
945 962 # get in parallel
946 963 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx), actions['g'])
947 964 for i, item in prog:
948 965 z += i
949 966 progress(_updating, z, item=item, total=numupdates, unit=_files)
950 967 updated = len(actions['g'])
951 968
952 969 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
953 970 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
954 971
955 972 # forget (manifest only, just log it) (must come first)
956 973 for f, args, msg in actions['f']:
957 974 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
958 975 z += 1
959 976 progress(_updating, z, item=f, total=numupdates, unit=_files)
960 977
961 978 # re-add (manifest only, just log it)
962 979 for f, args, msg in actions['a']:
963 980 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
964 981 z += 1
965 982 progress(_updating, z, item=f, total=numupdates, unit=_files)
966 983
967 984 # keep (noop, just log it)
968 985 for f, args, msg in actions['k']:
969 986 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
970 987 # no progress
971 988
972 989 # directory rename, move local
973 990 for f, args, msg in actions['dm']:
974 991 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
975 992 z += 1
976 993 progress(_updating, z, item=f, total=numupdates, unit=_files)
977 994 f0, flags = args
978 995 repo.ui.note(_("moving %s to %s\n") % (f0, f))
979 996 audit(f)
980 997 repo.wwrite(f, wctx.filectx(f0).data(), flags)
981 998 util.unlinkpath(repo.wjoin(f0))
982 999 updated += 1
983 1000
984 1001 # local directory rename, get
985 1002 for f, args, msg in actions['dg']:
986 1003 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
987 1004 z += 1
988 1005 progress(_updating, z, item=f, total=numupdates, unit=_files)
989 1006 f0, flags = args
990 1007 repo.ui.note(_("getting %s to %s\n") % (f0, f))
991 1008 repo.wwrite(f, mctx.filectx(f0).data(), flags)
992 1009 updated += 1
993 1010
994 1011 # exec
995 1012 for f, args, msg in actions['e']:
996 1013 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
997 1014 z += 1
998 1015 progress(_updating, z, item=f, total=numupdates, unit=_files)
999 1016 flags, = args
1000 1017 audit(f)
1001 1018 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
1002 1019 updated += 1
1003 1020
1004 1021 mergeactions = actions['m']
1005 1022 # the ordering is important here -- ms.mergedriver will raise if the merge
1006 1023 # driver has changed, and we want to be able to bypass it when overwrite is
1007 1024 # True
1008 1025 usemergedriver = not overwrite and mergeactions and ms.mergedriver
1009 1026
1010 1027 if usemergedriver:
1011 1028 ms.commit()
1012 1029 proceed = driverpreprocess(repo, ms, wctx, labels=labels)
1013 1030 # the driver might leave some files unresolved
1014 1031 unresolvedf = set(ms.unresolved())
1015 1032 if not proceed:
1016 1033 # XXX setting unresolved to at least 1 is a hack to make sure we
1017 1034 # error out
1018 1035 return updated, merged, removed, max(len(unresolvedf), 1)
1019 1036 newactions = []
1020 1037 for f, args, msg in mergeactions:
1021 1038 if f in unresolvedf:
1022 1039 newactions.append((f, args, msg))
1023 1040 mergeactions = newactions
1024 1041
1025 1042 # premerge
1026 1043 tocomplete = []
1027 1044 for f, args, msg in mergeactions:
1028 1045 repo.ui.debug(" %s: %s -> m (premerge)\n" % (f, msg))
1029 1046 z += 1
1030 1047 progress(_updating, z, item=f, total=numupdates, unit=_files)
1031 1048 if f == '.hgsubstate': # subrepo states need updating
1032 1049 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
1033 1050 overwrite)
1034 1051 continue
1035 1052 audit(f)
1036 1053 complete, r = ms.preresolve(f, wctx, labels=labels)
1037 1054 if complete:
1038 1055 if r is not None and r > 0:
1039 1056 unresolved += 1
1040 1057 else:
1041 1058 if r is None:
1042 1059 updated += 1
1043 1060 else:
1044 1061 merged += 1
1045 1062 else:
1046 1063 numupdates += 1
1047 1064 tocomplete.append((f, args, msg))
1048 1065
1049 1066 # merge
1050 1067 for f, args, msg in tocomplete:
1051 1068 repo.ui.debug(" %s: %s -> m (merge)\n" % (f, msg))
1052 1069 z += 1
1053 1070 progress(_updating, z, item=f, total=numupdates, unit=_files)
1054 1071 r = ms.resolve(f, wctx, labels=labels)
1055 1072 if r is not None and r > 0:
1056 1073 unresolved += 1
1057 1074 else:
1058 1075 if r is None:
1059 1076 updated += 1
1060 1077 else:
1061 1078 merged += 1
1062 1079
1063 1080 ms.commit()
1064 1081
1065 1082 if usemergedriver and not unresolved and ms.mdstate() != 's':
1066 1083 if not driverconclude(repo, ms, wctx, labels=labels):
1067 1084 # XXX setting unresolved to at least 1 is a hack to make sure we
1068 1085 # error out
1069 1086 unresolved = max(unresolved, 1)
1070 1087
1071 1088 ms.commit()
1072 1089
1073 1090 progress(_updating, None, total=numupdates, unit=_files)
1074 1091
1075 1092 return updated, merged, removed, unresolved
1076 1093
1077 1094 def recordupdates(repo, actions, branchmerge):
1078 1095 "record merge actions to the dirstate"
1079 1096 # remove (must come first)
1080 1097 for f, args, msg in actions['r']:
1081 1098 if branchmerge:
1082 1099 repo.dirstate.remove(f)
1083 1100 else:
1084 1101 repo.dirstate.drop(f)
1085 1102
1086 1103 # forget (must come first)
1087 1104 for f, args, msg in actions['f']:
1088 1105 repo.dirstate.drop(f)
1089 1106
1090 1107 # re-add
1091 1108 for f, args, msg in actions['a']:
1092 1109 if not branchmerge:
1093 1110 repo.dirstate.add(f)
1094 1111
1095 1112 # exec change
1096 1113 for f, args, msg in actions['e']:
1097 1114 repo.dirstate.normallookup(f)
1098 1115
1099 1116 # keep
1100 1117 for f, args, msg in actions['k']:
1101 1118 pass
1102 1119
1103 1120 # get
1104 1121 for f, args, msg in actions['g']:
1105 1122 if branchmerge:
1106 1123 repo.dirstate.otherparent(f)
1107 1124 else:
1108 1125 repo.dirstate.normal(f)
1109 1126
1110 1127 # merge
1111 1128 for f, args, msg in actions['m']:
1112 1129 f1, f2, fa, move, anc = args
1113 1130 if branchmerge:
1114 1131 # We've done a branch merge, mark this file as merged
1115 1132 # so that we properly record the merger later
1116 1133 repo.dirstate.merge(f)
1117 1134 if f1 != f2: # copy/rename
1118 1135 if move:
1119 1136 repo.dirstate.remove(f1)
1120 1137 if f1 != f:
1121 1138 repo.dirstate.copy(f1, f)
1122 1139 else:
1123 1140 repo.dirstate.copy(f2, f)
1124 1141 else:
1125 1142 # We've update-merged a locally modified file, so
1126 1143 # we set the dirstate to emulate a normal checkout
1127 1144 # of that file some time in the past. Thus our
1128 1145 # merge will appear as a normal local file
1129 1146 # modification.
1130 1147 if f2 == f: # file not locally copied/moved
1131 1148 repo.dirstate.normallookup(f)
1132 1149 if move:
1133 1150 repo.dirstate.drop(f1)
1134 1151
1135 1152 # directory rename, move local
1136 1153 for f, args, msg in actions['dm']:
1137 1154 f0, flag = args
1138 1155 if branchmerge:
1139 1156 repo.dirstate.add(f)
1140 1157 repo.dirstate.remove(f0)
1141 1158 repo.dirstate.copy(f0, f)
1142 1159 else:
1143 1160 repo.dirstate.normal(f)
1144 1161 repo.dirstate.drop(f0)
1145 1162
1146 1163 # directory rename, get
1147 1164 for f, args, msg in actions['dg']:
1148 1165 f0, flag = args
1149 1166 if branchmerge:
1150 1167 repo.dirstate.add(f)
1151 1168 repo.dirstate.copy(f0, f)
1152 1169 else:
1153 1170 repo.dirstate.normal(f)
1154 1171
1155 1172 def update(repo, node, branchmerge, force, partial, ancestor=None,
1156 1173 mergeancestor=False, labels=None):
1157 1174 """
1158 1175 Perform a merge between the working directory and the given node
1159 1176
1160 1177 node = the node to update to, or None if unspecified
1161 1178 branchmerge = whether to merge between branches
1162 1179 force = whether to force branch merging or file overwriting
1163 1180 partial = a function to filter file lists (dirstate not updated)
1164 1181 mergeancestor = whether it is merging with an ancestor. If true,
1165 1182 we should accept the incoming changes for any prompts that occur.
1166 1183 If false, merging with an ancestor (fast-forward) is only allowed
1167 1184 between different named branches. This flag is used by rebase extension
1168 1185 as a temporary fix and should be avoided in general.
1169 1186
1170 1187 The table below shows all the behaviors of the update command
1171 1188 given the -c and -C or no options, whether the working directory
1172 1189 is dirty, whether a revision is specified, and the relationship of
1173 1190 the parent rev to the target rev (linear, on the same named
1174 1191 branch, or on another named branch).
1175 1192
1176 1193 This logic is tested by test-update-branches.t.
1177 1194
1178 1195 -c -C dirty rev | linear same cross
1179 1196 n n n n | ok (1) x
1180 1197 n n n y | ok ok ok
1181 1198 n n y n | merge (2) (2)
1182 1199 n n y y | merge (3) (3)
1183 1200 n y * * | discard discard discard
1184 1201 y n y * | (4) (4) (4)
1185 1202 y n n * | ok ok ok
1186 1203 y y * * | (5) (5) (5)
1187 1204
1188 1205 x = can't happen
1189 1206 * = don't-care
1190 1207 1 = abort: not a linear update (merge or update --check to force update)
1191 1208 2 = abort: uncommitted changes (commit and merge, or update --clean to
1192 1209 discard changes)
1193 1210 3 = abort: uncommitted changes (commit or update --clean to discard changes)
1194 1211 4 = abort: uncommitted changes (checked in commands.py)
1195 1212 5 = incompatible options (checked in commands.py)
1196 1213
1197 1214 Return the same tuple as applyupdates().
1198 1215 """
1199 1216
1200 1217 onode = node
1201 1218 wlock = repo.wlock()
1202 1219 try:
1203 1220 wc = repo[None]
1204 1221 pl = wc.parents()
1205 1222 p1 = pl[0]
1206 1223 pas = [None]
1207 1224 if ancestor is not None:
1208 1225 pas = [repo[ancestor]]
1209 1226
1210 1227 if node is None:
1211 1228 if (repo.ui.configbool('devel', 'all-warnings')
1212 1229 or repo.ui.configbool('devel', 'oldapi')):
1213 1230 repo.ui.develwarn('update with no target')
1214 1231 rev, _mark, _act = destutil.destupdate(repo)
1215 1232 node = repo[rev].node()
1216 1233
1217 1234 overwrite = force and not branchmerge
1218 1235
1219 1236 p2 = repo[node]
1220 1237 if pas[0] is None:
1221 1238 if repo.ui.configlist('merge', 'preferancestor', ['*']) == ['*']:
1222 1239 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
1223 1240 pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
1224 1241 else:
1225 1242 pas = [p1.ancestor(p2, warn=branchmerge)]
1226 1243
1227 1244 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
1228 1245
1229 1246 ### check phase
1230 1247 if not overwrite and len(pl) > 1:
1231 1248 raise error.Abort(_("outstanding uncommitted merge"))
1232 1249 if branchmerge:
1233 1250 if pas == [p2]:
1234 1251 raise error.Abort(_("merging with a working directory ancestor"
1235 1252 " has no effect"))
1236 1253 elif pas == [p1]:
1237 1254 if not mergeancestor and p1.branch() == p2.branch():
1238 1255 raise error.Abort(_("nothing to merge"),
1239 1256 hint=_("use 'hg update' "
1240 1257 "or check 'hg heads'"))
1241 1258 if not force and (wc.files() or wc.deleted()):
1242 1259 raise error.Abort(_("uncommitted changes"),
1243 1260 hint=_("use 'hg status' to list changes"))
1244 1261 for s in sorted(wc.substate):
1245 1262 wc.sub(s).bailifchanged()
1246 1263
1247 1264 elif not overwrite:
1248 1265 if p1 == p2: # no-op update
1249 1266 # call the hooks and exit early
1250 1267 repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
1251 1268 repo.hook('update', parent1=xp2, parent2='', error=0)
1252 1269 return 0, 0, 0, 0
1253 1270
1254 1271 if pas not in ([p1], [p2]): # nonlinear
1255 1272 dirty = wc.dirty(missing=True)
1256 1273 if dirty or onode is None:
1257 1274 # Branching is a bit strange to ensure we do the minimal
1258 1275 # amount of call to obsolete.background.
1259 1276 foreground = obsolete.foreground(repo, [p1.node()])
1260 1277 # note: the <node> variable contains a random identifier
1261 1278 if repo[node].node() in foreground:
1262 1279 pas = [p1] # allow updating to successors
1263 1280 elif dirty:
1264 1281 msg = _("uncommitted changes")
1265 1282 if onode is None:
1266 1283 hint = _("commit and merge, or update --clean to"
1267 1284 " discard changes")
1268 1285 else:
1269 1286 hint = _("commit or update --clean to discard"
1270 1287 " changes")
1271 1288 raise error.Abort(msg, hint=hint)
1272 1289 else: # node is none
1273 1290 msg = _("not a linear update")
1274 1291 hint = _("merge or update --check to force update")
1275 1292 raise error.Abort(msg, hint=hint)
1276 1293 else:
1277 1294 # Allow jumping branches if clean and specific rev given
1278 1295 pas = [p1]
1279 1296
1280 1297 # deprecated config: merge.followcopies
1281 1298 followcopies = False
1282 1299 if overwrite:
1283 1300 pas = [wc]
1284 1301 elif pas == [p2]: # backwards
1285 1302 pas = [wc.p1()]
1286 1303 elif not branchmerge and not wc.dirty(missing=True):
1287 1304 pass
1288 1305 elif pas[0] and repo.ui.configbool('merge', 'followcopies', True):
1289 1306 followcopies = True
1290 1307
1291 1308 ### calculate phase
1292 1309 actionbyfile, diverge, renamedelete = calculateupdates(
1293 1310 repo, wc, p2, pas, branchmerge, force, partial, mergeancestor,
1294 1311 followcopies)
1295 1312 # Convert to dictionary-of-lists format
1296 1313 actions = dict((m, []) for m in 'a f g cd dc r dm dg m e k'.split())
1297 1314 for f, (m, args, msg) in actionbyfile.iteritems():
1298 1315 if m not in actions:
1299 1316 actions[m] = []
1300 1317 actions[m].append((f, args, msg))
1301 1318
1302 1319 if not util.checkcase(repo.path):
1303 1320 # check collision between files only in p2 for clean update
1304 1321 if (not branchmerge and
1305 1322 (force or not wc.dirty(missing=True, branch=False))):
1306 1323 _checkcollision(repo, p2.manifest(), None)
1307 1324 else:
1308 1325 _checkcollision(repo, wc.manifest(), actions)
1309 1326
1310 1327 # Prompt and create actions. TODO: Move this towards resolve phase.
1311 1328 for f, args, msg in sorted(actions['cd']):
1312 1329 if repo.ui.promptchoice(
1313 1330 _("local changed %s which remote deleted\n"
1314 1331 "use (c)hanged version or (d)elete?"
1315 1332 "$$ &Changed $$ &Delete") % f, 0):
1316 1333 actions['r'].append((f, None, "prompt delete"))
1317 1334 else:
1318 1335 actions['a'].append((f, None, "prompt keep"))
1319 1336
1320 1337 for f, args, msg in sorted(actions['dc']):
1321 1338 f1, f2, fa, move, anc = args
1322 1339 flags = p2[f2].flags()
1323 1340 if repo.ui.promptchoice(
1324 1341 _("remote changed %s which local deleted\n"
1325 1342 "use (c)hanged version or leave (d)eleted?"
1326 1343 "$$ &Changed $$ &Deleted") % f, 0) == 0:
1327 1344 actions['g'].append((f, (flags,), "prompt recreating"))
1328 1345
1329 1346 # divergent renames
1330 1347 for f, fl in sorted(diverge.iteritems()):
1331 1348 repo.ui.warn(_("note: possible conflict - %s was renamed "
1332 1349 "multiple times to:\n") % f)
1333 1350 for nf in fl:
1334 1351 repo.ui.warn(" %s\n" % nf)
1335 1352
1336 1353 # rename and delete
1337 1354 for f, fl in sorted(renamedelete.iteritems()):
1338 1355 repo.ui.warn(_("note: possible conflict - %s was deleted "
1339 1356 "and renamed to:\n") % f)
1340 1357 for nf in fl:
1341 1358 repo.ui.warn(" %s\n" % nf)
1342 1359
1343 1360 ### apply phase
1344 1361 if not branchmerge: # just jump to the new rev
1345 1362 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
1346 1363 if not partial:
1347 1364 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
1348 1365 # note that we're in the middle of an update
1349 1366 repo.vfs.write('updatestate', p2.hex())
1350 1367
1351 1368 stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
1352 1369
1353 1370 if not partial:
1354 1371 repo.dirstate.beginparentchange()
1355 1372 repo.setparents(fp1, fp2)
1356 1373 recordupdates(repo, actions, branchmerge)
1357 1374 # update completed, clear state
1358 1375 util.unlink(repo.join('updatestate'))
1359 1376
1360 1377 if not branchmerge:
1361 1378 repo.dirstate.setbranch(p2.branch())
1362 1379 repo.dirstate.endparentchange()
1363 1380 finally:
1364 1381 wlock.release()
1365 1382
1366 1383 if not partial:
1367 1384 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1368 1385 return stats
1369 1386
1370 1387 def graft(repo, ctx, pctx, labels):
1371 1388 """Do a graft-like merge.
1372 1389
1373 1390 This is a merge where the merge ancestor is chosen such that one
1374 1391 or more changesets are grafted onto the current changeset. In
1375 1392 addition to the merge, this fixes up the dirstate to include only
1376 1393 a single parent and tries to duplicate any renames/copies
1377 1394 appropriately.
1378 1395
1379 1396 ctx - changeset to rebase
1380 1397 pctx - merge base, usually ctx.p1()
1381 1398 labels - merge labels eg ['local', 'graft']
1382 1399
1383 1400 """
1384 1401 # If we're grafting a descendant onto an ancestor, be sure to pass
1385 1402 # mergeancestor=True to update. This does two things: 1) allows the merge if
1386 1403 # the destination is the same as the parent of the ctx (so we can use graft
1387 1404 # to copy commits), and 2) informs update that the incoming changes are
1388 1405 # newer than the destination so it doesn't prompt about "remote changed foo
1389 1406 # which local deleted".
1390 1407 mergeancestor = repo.changelog.isancestor(repo['.'].node(), ctx.node())
1391 1408
1392 1409 stats = update(repo, ctx.node(), True, True, False, pctx.node(),
1393 1410 mergeancestor=mergeancestor, labels=labels)
1394 1411
1395 1412 # drop the second merge parent
1396 1413 repo.dirstate.beginparentchange()
1397 1414 repo.setparents(repo['.'].node(), nullid)
1398 1415 repo.dirstate.write(repo.currenttransaction())
1399 1416 # fix up dirstate for copies and renames
1400 1417 copies.duplicatecopies(repo, ctx.rev(), pctx.rev())
1401 1418 repo.dirstate.endparentchange()
1402 1419 return stats
General Comments 0
You need to be logged in to leave comments. Login now