merge: don't overwrite untracked file at directory rename target
When a directory was renamed and a new untracked file was added in the
new directory and the remote directory added a file by the same name
in the old directory, the local untracked file gets overwritten, as
demonstrated by the broken test case in test-rename-dir-merge.
Fix by checking for unknown files for 'dg' actions too. Since
_checkunknownfile() currently expects the same filename in both
contexts, we need to add a new parameter for the remote filename to
it.
--- a/hgext/largefiles/overrides.py Tue Nov 18 20:29:25 2014 -0800
+++ b/hgext/largefiles/overrides.py Fri Dec 12 23:18:36 2014 -0800
@@ -405,10 +405,10 @@
# The overridden function filters the unknown files by removing any
# largefiles. This makes the merge proceed and we can then handle this
# case further in the overridden calculateupdates function below.
-def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
+def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None):
if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
return False
- return origfn(repo, wctx, mctx, f)
+ return origfn(repo, wctx, mctx, f, f2)
# The manifest merge handles conflicts on the manifest level. We want
# to handle changes in largefile-ness of files at this level too.
--- a/mercurial/merge.py Tue Nov 18 20:29:25 2014 -0800
+++ b/mercurial/merge.py Fri Dec 12 23:18:36 2014 -0800
@@ -297,11 +297,13 @@
self.mark(dfile, 'r')
return r
-def _checkunknownfile(repo, wctx, mctx, f):
+def _checkunknownfile(repo, wctx, mctx, f, f2=None):
+ if f2 is None:
+ f2 = f
return (os.path.isfile(repo.wjoin(f))
and repo.wopener.audit.check(f)
and repo.dirstate.normalize(f) not in repo.dirstate
- and mctx[f].cmp(wctx[f]))
+ and mctx[f2].cmp(wctx[f]))
def _forgetremoved(wctx, mctx, branchmerge):
"""
@@ -517,6 +519,9 @@
if m in ('c', 'dc'):
if _checkunknownfile(repo, wctx, p2, f):
aborts.append(f)
+ elif m == 'dg':
+ if _checkunknownfile(repo, wctx, p2, f, args[0]):
+ aborts.append(f)
for f in sorted(aborts):
repo.ui.warn(_("%s: untracked file differs\n") % f)
--- a/tests/test-rename-dir-merge.t Tue Nov 18 20:29:25 2014 -0800
+++ b/tests/test-rename-dir-merge.t Fri Dec 12 23:18:36 2014 -0800
@@ -108,21 +108,23 @@
Local directory rename with conflicting file added in remote source directory
and untracked in local target directory.
-BROKEN: the uncommitted file is overwritten; we should abort
-
$ hg co -qC 1
$ echo target > b/c
$ hg merge 2
+ b/c: untracked file differs
+ abort: untracked files in working directory differ from files in requested revision
+ [255]
+ $ cat b/c
+ target
+but it should succeed if the content matches
+ $ hg cat -r 2 a/c > b/c
+ $ hg merge 2
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
- $ hg st -A
+ $ hg st -C
A b/c
a/c
? a/d
- C b/a
- C b/b
- $ cat b/c
- baz
Local directory rename with conflicting file added in remote source directory
and committed in local target directory.