[PATCH 2 of 3 STABLE] opener: break hardlinks for open files on Windows (issue2524)
Adrian Buehlmann
adrian at cadifra.com
Wed Dec 1 06:53:53 CST 2010
# HG changeset patch
# User Adrian Buehlmann <adrian at cadifra.com>
# Date 1291199694 -3600
# Branch stable
# Node ID 52f97fe43a6be964691d78a0147f6650855fc303
# Parent 923338ecd57c11b2131ef9e90491fc8447d1ac60
opener: break hardlinks for open files on Windows (issue2524)
using new function unlinkopened
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -880,34 +880,50 @@ class opener(object):
nlink = -1
st_mode = None
+ fd = None
dirname, basename = os.path.split(f)
# If basename is empty, then the path is malformed because it points
# to a directory. Let the posixfile() call below raise IOError.
if basename and mode not in ('r', 'rb'):
+
if atomictemp:
if not os.path.isdir(dirname):
makedirs(dirname, self.createmode)
return atomictempfile(f, mode, self.createmode)
- try:
- if 'w' in mode:
+
+ # break up hardlinks
+ if 'w' in mode:
+ # 'w'rite modes truncate the file, so we can unlink it to
+ # break hardlinks (avoiding a gratuitous file copy)
+ try:
st_mode = os.lstat(f).st_mode & 0777
- os.unlink(f)
+ except OSError, err:
+ if err.errno != errno.ENOENT:
+ raise
nlink = 0
- else:
+ if nlink != 0:
+ unlinkopened(f)
+ nlink = 0
+ else:
+ try:
# nlinks() may behave differently for files on Windows
# shares if the file is open.
fd = open(f)
+ except IOError, err:
+ if err.errno != errno.ENOENT:
+ raise
+ nlink = 0
+ if nlink != 0:
nlink = nlinks(f)
fd.close()
- except (OSError, IOError):
- nlink = 0
- if not os.path.isdir(dirname):
- makedirs(dirname, self.createmode)
- 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)
+ if self._trustnlink is None:
+ self._trustnlink = nlink > 1 or checknlink(f)
+ if nlink > 1 or not self._trustnlink:
+ rename(mktempcopy(f), f)
+
+ if st_mode is None and fd is None and not os.path.isdir(dirname):
+ makedirs(dirname, self.createmode)
+
fp = posixfile(f, mode)
if nlink == 0:
if st_mode is None:
More information about the Mercurial-devel
mailing list