Mercurial > hg
changeset 23653:0297d8469350
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.
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Fri, 12 Dec 2014 23:18:36 -0800 |
parents | 6fcc3669e483 |
children | 9d56be47b5d6 |
files | hgext/largefiles/overrides.py mercurial/merge.py tests/test-rename-dir-merge.t |
diffstat | 3 files changed, 18 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- 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.