merge with stable
authorMatt Mackall <mpm@selenic.com>
Sun, 07 Nov 2010 16:01:57 -0600
changeset 12939 0cb90f9c6d8e
parent 12936 bdb766e64d35 (current diff)
parent 12938 bf826c0b9537 (diff)
child 12946 24a1d7ad12a4
merge with stable
--- a/mercurial/util.py	Sun Nov 07 18:15:17 2010 +0100
+++ b/mercurial/util.py	Sun Nov 07 16:01:57 2010 -0600
@@ -716,6 +716,29 @@
     except (OSError, AttributeError):
         return False
 
+def checknlink(testfile):
+    '''check whether hardlink count reporting works properly'''
+    f = testfile + ".hgtmp"
+
+    try:
+        os_link(testfile, f)
+    except OSError, inst:
+        if inst.errno == errno.EINVAL:
+            # FS doesn't support creating hardlinks
+            return True
+        return False
+
+    try:
+        # nlinks() may behave differently for files on Windows shares if
+        # the file is open.
+        fd = open(f)
+        return nlinks(f) > 1
+    finally:
+        fd.close()
+        os.unlink(f)
+
+    return False
+
 def endswithsep(path):
     '''Check path ends with os.sep or os.altsep.'''
     return path.endswith(os.sep) or os.altsep and path.endswith(os.altsep)
@@ -840,6 +863,7 @@
         else:
             self.auditor = always
         self.createmode = None
+        self._trustnlink = None
 
     @propertycache
     def _can_symlink(self):
@@ -873,13 +897,20 @@
                     os.unlink(f)
                     nlink = 0
                 else:
+                    # nlinks() may behave differently for files on Windows
+                    # shares if the file is open.
+                    fd = open(f)
                     nlink = nlinks(f)
-            except OSError:
+                    fd.close()
+            except (OSError, IOError):
                 nlink = 0
                 if not os.path.isdir(dirname):
                     makedirs(dirname, self.createmode)
-            if nlink > 1:
-                rename(mktempcopy(f), f)
+            if nlink > 0:
+                if self._trustnlink is None:
+                    self._trustnlink = nlink > 1 or checknlink(f)
+                if nlink > 1 or not self._trustnlink:
+                    rename(mktempcopy(f), f)
         fp = posixfile(f, mode)
         if nlink == 0:
             if st_mode is None:
--- a/mercurial/win32.py	Sun Nov 07 18:15:17 2010 +0100
+++ b/mercurial/win32.py	Sun Nov 07 16:01:57 2010 -0600
@@ -43,17 +43,7 @@
 
 def nlinks(pathname):
     """Return number of hardlinks for the given file."""
-    links = _getfileinfo(pathname)[7]
-    if links < 2:
-        # Known to be wrong for most network drives
-        dirname = os.path.dirname(pathname)
-        if not dirname:
-            dirname = '.'
-        dt = win32file.GetDriveType(dirname + '\\')
-        if dt == 4 or dt == 1:
-            # Fake hardlink to force COW for network drives
-            links = 2
-    return links
+    return _getfileinfo(pathname)[7]
 
 def samefile(fpath1, fpath2):
     """Returns whether fpath1 and fpath2 refer to the same file. This is only