comparison mercurial/merge.py @ 34548:b4955650eb57

merge: add merge action 'pr' to rename files during update Add a new merge action to handle a path conflict by renaming the conflicting file to a safe name. The rename is just to avoid problems on the filesystem. The conflict is still considered unresolved until the user marks the original path as resolved. Differential Revision: https://phab.mercurial-scm.org/D777
author Mark Thomas <mbthomas@fb.com>
date Mon, 02 Oct 2017 14:05:30 -0700
parents 81aebcc73beb
children a991e1d6bc82
comparison
equal deleted inserted replaced
34547:81aebcc73beb 34548:b4955650eb57
1261 s(_("resolve manually then use 'hg resolve --mark %s'\n") % f) 1261 s(_("resolve manually then use 'hg resolve --mark %s'\n") % f)
1262 ms.addpath(f, f1, fo) 1262 ms.addpath(f, f1, fo)
1263 z += 1 1263 z += 1
1264 progress(_updating, z, item=f, total=numupdates, unit=_files) 1264 progress(_updating, z, item=f, total=numupdates, unit=_files)
1265 1265
1266 # remove in parallel (must come before getting) 1266 # remove in parallel (must come before resolving path conflicts and getting)
1267 prog = worker.worker(repo.ui, 0.001, batchremove, (repo, wctx), 1267 prog = worker.worker(repo.ui, 0.001, batchremove, (repo, wctx),
1268 actions['r']) 1268 actions['r'])
1269 for i, item in prog: 1269 for i, item in prog:
1270 z += i 1270 z += i
1271 progress(_updating, z, item=item, total=numupdates, unit=_files) 1271 progress(_updating, z, item=item, total=numupdates, unit=_files)
1272 removed = len(actions['r']) 1272 removed = len(actions['r'])
1273
1274 # resolve path conflicts (must come before getting)
1275 for f, args, msg in actions['pr']:
1276 repo.ui.debug(" %s: %s -> pr\n" % (f, msg))
1277 f0, = args
1278 if wctx[f0].lexists():
1279 repo.ui.note(_("moving %s to %s\n") % (f0, f))
1280 wctx[f].audit()
1281 wctx[f].write(wctx.filectx(f0).data(), wctx.filectx(f0).flags())
1282 wctx[f0].remove()
1283 z += 1
1284 progress(_updating, z, item=f, total=numupdates, unit=_files)
1273 1285
1274 # We should flush before forking into worker processes, since those workers 1286 # We should flush before forking into worker processes, since those workers
1275 # flush when they complete, and we don't want to duplicate work. 1287 # flush when they complete, and we don't want to duplicate work.
1276 wctx.flushall() 1288 wctx.flushall()
1277 1289
1440 repo.dirstate.drop(f) 1452 repo.dirstate.drop(f)
1441 1453
1442 # forget (must come first) 1454 # forget (must come first)
1443 for f, args, msg in actions.get('f', []): 1455 for f, args, msg in actions.get('f', []):
1444 repo.dirstate.drop(f) 1456 repo.dirstate.drop(f)
1457
1458 # resolve path conflicts
1459 for f, args, msg in actions.get('pr', []):
1460 f0, = args
1461 origf0 = repo.dirstate.copied(f0) or f0
1462 repo.dirstate.add(f)
1463 repo.dirstate.copy(origf0, f)
1464 if f0 == origf0:
1465 repo.dirstate.remove(f0)
1466 else:
1467 repo.dirstate.drop(f0)
1445 1468
1446 # re-add 1469 # re-add
1447 for f, args, msg in actions.get('a', []): 1470 for f, args, msg in actions.get('a', []):
1448 repo.dirstate.add(f) 1471 repo.dirstate.add(f)
1449 1472
1676 repo, wc, p2, pas, branchmerge, force, mergeancestor, 1699 repo, wc, p2, pas, branchmerge, force, mergeancestor,
1677 followcopies, matcher=matcher, mergeforce=mergeforce) 1700 followcopies, matcher=matcher, mergeforce=mergeforce)
1678 1701
1679 if updatecheck == 'noconflict': 1702 if updatecheck == 'noconflict':
1680 for f, (m, args, msg) in actionbyfile.iteritems(): 1703 for f, (m, args, msg) in actionbyfile.iteritems():
1681 if m not in ('g', 'k', 'e', 'r'): 1704 if m not in ('g', 'k', 'e', 'r', 'pr'):
1682 msg = _("conflicting changes") 1705 msg = _("conflicting changes")
1683 hint = _("commit or update --clean to discard changes") 1706 hint = _("commit or update --clean to discard changes")
1684 raise error.Abort(msg, hint=hint) 1707 raise error.Abort(msg, hint=hint)
1685 1708
1686 # Prompt and create actions. Most of this is in the resolve phase 1709 # Prompt and create actions. Most of this is in the resolve phase
1712 else: 1735 else:
1713 del actionbyfile[f] 1736 del actionbyfile[f]
1714 1737
1715 # Convert to dictionary-of-lists format 1738 # Convert to dictionary-of-lists format
1716 actions = dict((m, []) 1739 actions = dict((m, [])
1717 for m in 'a am f g cd dc r dm dg m e k p'.split()) 1740 for m in 'a am f g cd dc r dm dg m e k p pr'.split())
1718 for f, (m, args, msg) in actionbyfile.iteritems(): 1741 for f, (m, args, msg) in actionbyfile.iteritems():
1719 if m not in actions: 1742 if m not in actions:
1720 actions[m] = [] 1743 actions[m] = []
1721 actions[m].append((f, args, msg)) 1744 actions[m].append((f, args, msg))
1722 1745