diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -1076,15 +1076,14 @@ def batchget(repo, mctx, actions): absf = repo.wjoin(f) orig = scmutil.origpath(ui, repo, absf) try: - # TODO Mercurial has always aborted if an untracked - # directory is replaced by a tracked file, or generally - # with file/directory merges. This needs to be sorted out. if repo.wvfs.isfileorlink(f): util.rename(absf, orig) except OSError as e: if e.errno != errno.ENOENT: raise + if repo.wvfs.isdir(f): + repo.wvfs.removedirs(f) wwrite(f, fctx(f).data(), flags, backgroundclose=True) if i == 100: yield i, f diff --git a/tests/test-merge1.t b/tests/test-merge1.t --- a/tests/test-merge1.t +++ b/tests/test-merge1.t @@ -24,9 +24,10 @@ $ hg update 0 0 files updated, 0 files merged, 1 files removed, 0 files unresolved -Test interrupted updates by exploiting our non-handling of directory collisions +Test interrupted updates by having a non-empty dir with the same name as one +of the files in a commit we're updating to - $ mkdir b + $ mkdir b && touch b/nonempty $ hg up abort: *: '$TESTTMP/t/b' (glob) [255] @@ -38,10 +39,10 @@ Test interrupted updates by exploiting o parent: 0:538afb845929 commit #0 branch: default - commit: (interrupted update) + commit: 1 unknown (interrupted update) update: 1 new changesets (update) phases: 2 draft - $ rmdir b + $ rm b/nonempty $ hg up 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg sum diff --git a/tests/test-update-renames.t b/tests/test-update-names.t rename from tests/test-update-renames.t rename to tests/test-update-names.t --- a/tests/test-update-renames.t +++ b/tests/test-update-names.t @@ -1,8 +1,9 @@ -Test update logic when there are renames +Test update logic when there are renames or weird same-name cases between dirs +and files Update with local changes across a file rename - $ hg init + $ hg init r1 && cd r1 $ echo a > a $ hg add a @@ -24,3 +25,31 @@ Update with local changes across a file 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges [1] + +Test update when local untracked directory exists with the same name as a +tracked file in a commit we are updating to + $ hg init r2 && cd r2 + $ echo root > root && hg ci -Am root # rev 0 + adding root + $ echo text > name && hg ci -Am "name is a file" # rev 1 + adding name + $ hg up 0 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ mkdir name + $ hg up 1 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Test update when local untracked directory exists with some files in it and has +the same name a tracked file in a commit we are updating to. In future this +should be updated to give an friendlier error message, but now we should just +make sure that this does not erase untracked data + $ hg up 0 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ mkdir name + $ echo text > name/file + $ hg st + ? name/file + $ hg up 1 + abort: *: '$TESTTMP/r1/r2/name' (glob) + [255] + $ cd ..