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
--- a/mercurial/merge.py Mon Oct 02 14:05:30 2017 -0700
+++ b/mercurial/merge.py Mon Oct 02 14:05:30 2017 -0700
@@ -676,6 +676,7 @@
choose a different action.
"""
fileconflicts = set()
+ pathconflicts = set()
warnconflicts = set()
abortconflicts = set()
unknownconfig = _getcheckunknownconfig(repo, 'merge', 'checkunknown')
@@ -691,11 +692,15 @@
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 @@
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)
--- a/tests/test-merge1.t Mon Oct 02 14:05:30 2017 -0700
+++ b/tests/test-merge1.t Mon Oct 02 14:05:30 2017 -0700
@@ -30,17 +30,17 @@
$ 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
--- a/tests/test-pathconflicts-basic.t Mon Oct 02 14:05:30 2017 -0700
+++ b/tests/test-pathconflicts-basic.t Mon Oct 02 14:05:30 2017 -0700
@@ -37,7 +37,8 @@
$ 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 @@
$ 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
--- a/tests/test-update-names.t Mon Oct 02 14:05:30 2017 -0700
+++ b/tests/test-update-names.t Mon Oct 02 14:05:30 2017 -0700
@@ -50,7 +50,8 @@
$ 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 ..