merge: check for path conflicts when updating (issue5628)

When updating to a new revision, check for path conflicts caused by unknown
files in the working directory, and handle these by backing up the file or
directory and replacing it.

Differential Revision: https://phab.mercurial-scm.org/D781
This commit is contained in:
Mark Thomas 2017-10-02 14:05:30 -07:00
parent 8d254022c6
commit 710343cbad
4 changed files with 20 additions and 16 deletions

View File

@ -676,6 +676,7 @@ def _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce):
choose a different action.
"""
fileconflicts = set()
pathconflicts = set()
warnconflicts = set()
abortconflicts = set()
unknownconfig = _getcheckunknownconfig(repo, 'merge', 'checkunknown')
@ -691,11 +692,15 @@ def _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce):
if m in ('c', 'dc'):
if _checkunknownfile(repo, wctx, mctx, f):
fileconflicts.add(f)
elif f not in wctx:
path = _checkunknowndirs(repo, f)
if path is not None:
pathconflicts.add(path)
elif m == 'dg':
if _checkunknownfile(repo, wctx, mctx, f, args[0]):
fileconflicts.add(f)
allconflicts = fileconflicts
allconflicts = fileconflicts | pathconflicts
ignoredconflicts = set([c for c in allconflicts
if repo.dirstate._ignore(c)])
unknownconflicts = allconflicts - ignoredconflicts
@ -745,8 +750,9 @@ def _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce):
repo.ui.warn(_("%s: replacing untracked file\n") % f)
for f, (m, args, msg) in actions.iteritems():
backup = f in fileconflicts
if m == 'c':
backup = (f in fileconflicts or f in pathconflicts or
any(p in pathconflicts for p in util.finddirs(f)))
flags, = args
actions[f] = ('g', (flags, backup), msg)

View File

@ -30,17 +30,17 @@ of the files in a commit we're updating to
$ mkdir b && touch b/nonempty
$ hg up
abort: *: '$TESTTMP/t/b' (glob)
b: untracked file differs
abort: untracked files in working directory differ from files in requested revision
[255]
$ hg ci
abort: last update was interrupted
(use 'hg update' to get a consistent checkout)
[255]
nothing changed
[1]
$ hg sum
parent: 0:538afb845929
commit #0
branch: default
commit: 1 unknown (interrupted update)
commit: 1 unknown (clean)
update: 1 new changesets (update)
phases: 2 draft
$ rm b/nonempty

View File

@ -37,7 +37,8 @@ Basic update - local directory conflicts with remote file
$ mkdir a
$ echo 3 > a/b
$ hg up file
abort: *: '$TESTTMP/repo/a' (glob)
a: untracked file differs
abort: untracked files in working directory differ from files in requested revision
[255]
$ hg up --clean file
abort: *: '$TESTTMP/repo/a' (glob)
@ -53,13 +54,9 @@ Basic update - untracked file conflicts with remote directory
$ hg up -q 0
$ echo untracked > a
$ hg up --config merge.checkunknown=warn dir
abort: *: '$TESTTMP/repo/a/b' (glob)
[255]
Repo is in a very bad state now - recover manually
$ rm -f a
$ hg up -q --clean 0
a: replacing untracked file
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(activating bookmark dir)
Basic clean update - local directory conflicts with changed remote file

View File

@ -50,7 +50,8 @@ make sure that this does not erase untracked data
$ hg st
? name/file
$ hg up 1
abort: *: '$TESTTMP/r1/r2/name' (glob)
name: untracked file differs
abort: untracked files in working directory differ from files in requested revision
[255]
$ cd ..