diff -r bde426f18e0a -r 1a9ebc83a74c mercurial/win32.py --- a/mercurial/win32.py Tue Feb 18 15:54:46 2014 -0800 +++ b/mercurial/win32.py Thu Oct 17 13:27:17 2013 +0900 @@ -24,6 +24,7 @@ # GetLastError _ERROR_SUCCESS = 0 +_ERROR_SHARING_VIOLATION = 32 _ERROR_INVALID_PARAMETER = 87 _ERROR_INSUFFICIENT_BUFFER = 122 @@ -59,7 +60,9 @@ _OPEN_EXISTING = 3 +_FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000 _FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 +_FILE_FLAG_DELETE_ON_CLOSE = 0x04000000 # SetFileAttributes _FILE_ATTRIBUTE_NORMAL = 0x80 @@ -420,11 +423,18 @@ def unlink(f): '''try to implement POSIX' unlink semantics on Windows''' - if os.path.isdir(f): - # use EPERM because it is POSIX prescribed value, even though - # unlink(2) on directories returns EISDIR on Linux - raise IOError(errno.EPERM, - "Unlinking directory not permitted: '%s'" % f) + # If we can open f exclusively, no other processes must have open handles + # for it and we can expect its name will be deleted immediately when we + # close the handle unless we have another in the same process. We also + # expect we shall simply fail to open f if it is a directory. + fh = _kernel32.CreateFileA(f, 0, 0, None, _OPEN_EXISTING, + _FILE_FLAG_OPEN_REPARSE_POINT | _FILE_FLAG_DELETE_ON_CLOSE, None) + if fh != _INVALID_HANDLE_VALUE: + _kernel32.CloseHandle(fh) + return + error = _kernel32.GetLastError() + if error != _ERROR_SHARING_VIOLATION: + raise ctypes.WinError(error) # POSIX allows to unlink and rename open files. Windows has serious # problems with doing that: