# HG changeset patch # User Matt Mackall # Date 1289180562 21600 # Node ID 24a1d7ad12a4ec8008701a5310e304200afd41aa # Parent 0cb90f9c6d8e4f73a6d7ce73d94b419199139267# Parent 99f7dc8def34b4178b7f24f788dc7432903b5b49 merge with crew diff -r 99f7dc8def34 -r 24a1d7ad12a4 mercurial/util.py --- a/mercurial/util.py Mon Nov 08 01:55:32 2010 +0100 +++ b/mercurial/util.py Sun Nov 07 19:42:42 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: diff -r 99f7dc8def34 -r 24a1d7ad12a4 mercurial/win32.py --- a/mercurial/win32.py Mon Nov 08 01:55:32 2010 +0100 +++ b/mercurial/win32.py Sun Nov 07 19:42:42 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