comparison mercurial/merge.py @ 18606:95773237df7f

manifestmerge: handle abort on local unknown, remote created files This replaces the _checkunknown call in calculateupdates with a more performant version. On a repository with over 150,000 files, this speeds up an update by 0.6-0.8 seconds, which is up to 25%. This does not introduce any UI changes. There is existing test coverage for every case, mostly in test-merge*.t.
author Siddharth Agarwal <sid0@fb.com>
date Sat, 09 Feb 2013 15:36:00 +0000
parents bcf29565d89f
children 18c2184c27dc
comparison
equal deleted inserted replaced
18605:bcf29565d89f 18606:95773237df7f
222 for s in sorted(p1.substate): 222 for s in sorted(p1.substate):
223 if p1.sub(s).dirty(): 223 if p1.sub(s).dirty():
224 m1['.hgsubstate'] += "+" 224 m1['.hgsubstate'] += "+"
225 break 225 break
226 226
227 prompts = [] 227 aborts, prompts = [], []
228 # Compare manifests 228 # Compare manifests
229 for f, n in m1.iteritems(): 229 for f, n in m1.iteritems():
230 if partial and not partial(f): 230 if partial and not partial(f):
231 continue 231 continue
232 if f in m2: 232 if f in m2:
283 "remote copied to " + f)) 283 "remote copied to " + f))
284 else: 284 else:
285 actions.append((f2, "m", (f, f, True), 285 actions.append((f2, "m", (f, f, True),
286 "remote moved to " + f)) 286 "remote moved to " + f))
287 elif f not in ma: 287 elif f not in ma:
288 if (not overwrite 288 # local unknown, remote created: the logic is described by the
289 and _checkunknownfile(repo, p1, p2, f)): 289 # following table:
290 actions.append((f, "m", (f, f, False), 290 #
291 "remote differs from untracked local")) 291 # force branchmerge different | action
292 else: 292 # n * n | get
293 # n * y | abort
294 # y n * | get
295 # y y n | get
296 # y y y | merge
297 #
298 # Checking whether the files are different is expensive, so we
299 # don't do that when we can avoid it.
300 if force and not branchmerge:
293 actions.append((f, "g", (m2.flags(f),), "remote created")) 301 actions.append((f, "g", (m2.flags(f),), "remote created"))
302 else:
303 different = _checkunknownfile(repo, p1, p2, f)
304 if force and branchmerge and different:
305 actions.append((f, "m", (f, f, False),
306 "remote differs from untracked local"))
307 elif not force and different:
308 aborts.append((f, "ud"))
309 else:
310 actions.append((f, "g", (m2.flags(f),), "remote created"))
294 elif n != ma[f]: 311 elif n != ma[f]:
295 prompts.append((f, "dc")) # prompt deleted/changed 312 prompts.append((f, "dc")) # prompt deleted/changed
313
314 for f, m in sorted(aborts):
315 if m == "ud":
316 repo.ui.warn(_("%s: untracked file differs\n") % f)
317 else: assert False, m
318 if aborts:
319 raise util.Abort(_("untracked files in working directory differ "
320 "from files in requested revision"))
296 321
297 for f, m in sorted(prompts): 322 for f, m in sorted(prompts):
298 if m == "cd": 323 if m == "cd":
299 if repo.ui.promptchoice( 324 if repo.ui.promptchoice(
300 _("local changed %s which remote deleted\n" 325 _("local changed %s which remote deleted\n"
445 if (not branchmerge and 470 if (not branchmerge and
446 (force or not tctx.dirty(missing=True, branch=False))): 471 (force or not tctx.dirty(missing=True, branch=False))):
447 _checkcollision(mctx, None) 472 _checkcollision(mctx, None)
448 else: 473 else:
449 _checkcollision(mctx, (tctx, ancestor)) 474 _checkcollision(mctx, (tctx, ancestor))
450 if not force:
451 _checkunknown(repo, tctx, mctx)
452 if tctx.rev() is None: 475 if tctx.rev() is None:
453 actions += _forgetremoved(tctx, mctx, branchmerge) 476 actions += _forgetremoved(tctx, mctx, branchmerge)
454 actions += manifestmerge(repo, tctx, mctx, 477 actions += manifestmerge(repo, tctx, mctx,
455 ancestor, 478 ancestor,
456 branchmerge, force, 479 branchmerge, force,