merge: while checking for unknown files don't follow symlinks (
issue5027)
Previously, we were using Python's native 'os.path.isfile' method which follows
symlinks. In this case, since we're operating on repo contents, we don't want
to follow symlinks.
There's a behaviour change here, as shown by the second part of the added test.
Consider a symlink 'f' pointing to a file containing 'abc'. If we try and
replace it with a file with contents 'abc', previously we would have let it
though. Now we don't. Although this breaks naive inspection with tools like
'cat' and 'diff', on balance I believe this is the right change.
--- a/mercurial/merge.py Sat Dec 26 15:18:16 2015 +0900
+++ b/mercurial/merge.py Mon Dec 28 22:51:37 2015 -0800
@@ -404,7 +404,7 @@
def _checkunknownfile(repo, wctx, mctx, f, f2=None):
if f2 is None:
f2 = f
- return (os.path.isfile(repo.wjoin(f))
+ return (repo.wvfs.isfileorlink(f)
and repo.wvfs.audit.check(f)
and repo.dirstate.normalize(f) not in repo.dirstate
and mctx[f2].cmp(wctx[f]))
--- a/mercurial/scmutil.py Sat Dec 26 15:18:16 2015 +0900
+++ b/mercurial/scmutil.py Mon Dec 28 22:51:37 2015 -0800
@@ -312,6 +312,17 @@
def islink(self, path=None):
return os.path.islink(self.join(path))
+ def isfileorlink(self, path=None):
+ '''return whether path is a regular file or a symlink
+
+ Unlike isfile, this doesn't follow symlinks.'''
+ try:
+ st = self.lstat(path)
+ except OSError:
+ return False
+ mode = st.st_mode
+ return stat.S_ISREG(mode) or stat.S_ISLNK(mode)
+
def reljoin(self, *paths):
"""join various elements of a path together (as os.path.join would do)
--- a/tests/test-merge1.t Sat Dec 26 15:18:16 2015 +0900
+++ b/tests/test-merge1.t Mon Dec 28 22:51:37 2015 -0800
@@ -102,6 +102,28 @@
b: untracked file differs
abort: untracked files in working directory differ from files in requested revision
[255]
+
+#if symlink
+symlinks to directories should be treated as regular files (issue5027)
+ $ rm b
+ $ ln -s 'This is file b2' b
+ $ hg merge 1
+ b: untracked file differs
+ abort: untracked files in working directory differ from files in requested revision
+ [255]
+symlinks shouldn't be followed
+ $ rm b
+ $ echo This is file b1 > .hg/b
+ $ ln -s .hg/b b
+ $ hg merge 1
+ b: untracked file differs
+ abort: untracked files in working directory differ from files in requested revision
+ [255]
+
+ $ rm b
+ $ echo This is file b2 > b
+#endif
+
merge of b expected
$ hg merge -f 1
merging b