--- a/mercurial/win32.py Sun Mar 27 12:59:25 2011 +0200
+++ b/mercurial/win32.py Sun Mar 27 01:17:48 2011 +0100
@@ -6,7 +6,7 @@
# GNU General Public License version 2 or any later version.
import encoding
-import ctypes, errno, os, struct, subprocess
+import ctypes, errno, os, struct, subprocess, random
_kernel32 = ctypes.windll.kernel32
@@ -316,3 +316,43 @@
raise ctypes.WinError()
return pi.dwProcessId
+
+def unlink(f):
+ '''try to implement POSIX' unlink semantics on Windows'''
+
+ # POSIX allows to unlink and rename open files. Windows has serious
+ # problems with doing that:
+ # - Calling os.unlink (or os.rename) on a file f fails if f or any
+ # hardlinked copy of f has been opened with Python's open(). There is no
+ # way such a file can be deleted or renamed on Windows (other than
+ # scheduling the delete or rename for the next reboot).
+ # - Calling os.unlink on a file that has been opened with Mercurial's
+ # posixfile (or comparable methods) will delay the actual deletion of
+ # the file for as long as the file is held open. The filename is blocked
+ # during that time and cannot be used for recreating a new file under
+ # that same name ("zombie file"). Directories containing such zombie files
+ # cannot be removed or moved.
+ # A file that has been opened with posixfile can be renamed, so we rename
+ # f to a random temporary name before calling os.unlink on it. This allows
+ # callers to recreate f immediately while having other readers do their
+ # implicit zombie filename blocking on a temporary name.
+
+ for tries in xrange(10):
+ temp = '%s-%08x' % (f, random.randint(0, 0xffffffff))
+ try:
+ os.rename(f, temp) # raises OSError EEXIST if temp exists
+ break
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ raise
+ else:
+ raise IOError, (errno.EEXIST, "No usable temporary filename found")
+
+ try:
+ os.unlink(temp)
+ except:
+ # Some very rude AV-scanners on Windows may cause this unlink to fail.
+ # Not aborting here just leaks the temp file, whereas aborting at this
+ # point may leave serious inconsistencies. Ideally, we would notify
+ # the user in this case here.
+ pass
--- a/mercurial/windows.py Sun Mar 27 12:59:25 2011 +0200
+++ b/mercurial/windows.py Sun Mar 27 01:17:48 2011 +0100
@@ -7,7 +7,7 @@
from i18n import _
import osutil, error
-import errno, msvcrt, os, re, sys, random, subprocess
+import errno, msvcrt, os, re, sys, subprocess
nulldev = 'NUL:'
umask = 002
@@ -293,46 +293,6 @@
except OSError:
pass
-def unlink(f):
- '''try to implement POSIX' unlink semantics on Windows'''
-
- # POSIX allows to unlink and rename open files. Windows has serious
- # problems with doing that:
- # - Calling os.unlink (or os.rename) on a file f fails if f or any
- # hardlinked copy of f has been opened with Python's open(). There is no
- # way such a file can be deleted or renamed on Windows (other than
- # scheduling the delete or rename for the next reboot).
- # - Calling os.unlink on a file that has been opened with Mercurial's
- # posixfile (or comparable methods) will delay the actual deletion of
- # the file for as long as the file is held open. The filename is blocked
- # during that time and cannot be used for recreating a new file under
- # that same name ("zombie file"). Directories containing such zombie files
- # cannot be removed or moved.
- # A file that has been opened with posixfile can be renamed, so we rename
- # f to a random temporary name before calling os.unlink on it. This allows
- # callers to recreate f immediately while having other readers do their
- # implicit zombie filename blocking on a temporary name.
-
- for tries in xrange(10):
- temp = '%s-%08x' % (f, random.randint(0, 0xffffffff))
- try:
- os.rename(f, temp) # raises OSError EEXIST if temp exists
- break
- except OSError, e:
- if e.errno != errno.EEXIST:
- raise
- else:
- raise IOError, (errno.EEXIST, "No usable temporary filename found")
-
- try:
- os.unlink(temp)
- except:
- # Some very rude AV-scanners on Windows may cause this unlink to fail.
- # Not aborting here just leaks the temp file, whereas aborting at this
- # point may leave serious inconsistencies. Ideally, we would notify
- # the user in this case here.
- pass
-
def rename(src, dst):
'''atomically rename file src to dst, replacing dst if it exists'''
try: